mangle.c
来自「基于LWVCL开发的库」· C语言 代码 · 共 831 行 · 第 1/2 页
C
831 行
/* * mangle.c * Routines for doing name mangling on Java types * * Copyright (c) 2000, 2004 University of Utah and the Flux Group. * All rights reserved. * * This file is licensed under the terms of the GNU Public License. * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Contributed by the Flux Research Group, Department of Computer Science, * University of Utah, http://www.cs.utah.edu/flux/ */#include "config.h"#if defined(KAFFE_XDEBUGGING) || defined(KAFFE_XPROFILER)#include <stdlib.h>#include <string.h>#include <assert.h>#include "config.h"#include "kaffe/jmalloc.h"#include "stringSupport.h"#include "classMethod.h"#include "xprofiler.h"#include "mangle.h"#ifndef MANGLE_GCJ# ifdef HAVE_GCJ_SUPPORT# define MANGLE_GCJ 1# else# define MANGLE_GCJ 0# endif#endif/* * GCJ name mangling can confuse older tools. It would be nice to be * able to dectect whether gcj-aware versions of gdb and gprof are * present, but we are already doing the next-best thing: detecting * whether GCJ itself is present. * * Our simplified mangler differs from gcj in two respects: First, it * it treats outer class names (left of a $), as qualifiers. And * second, it does not use U to indicate a unicode name part. * Instead, is always escapes underscores preceding hex digits. */#if MANGLE_GCJ# define IS_SEP(c) ((c) == '/')# define NAME_SEPARATORS "/" /* GCJ escapes out underscore iff this is a unicode word */ static inline int bad_underscore(const char *p, const char *end) { return 1; }#else# define IS_SEP(c) ((c) == '/' || (c) == '$')# define NAME_SEPARATORS "/$" /* In kaffe, everything is potential unicode-mangled, but underscores * are only escaped out if they precede hex digits or underscores. */ static inline int bad_underscore(const char *p, const char *end) { int next = UTF8_GET(p, end); return ((next >= '0' && next <= '9') || (next >= 'a' && next <= 'f') || next == '_'); }#endifstruct mangled_method *createMangledMethod(void){ struct mangled_method *retval; xProfilingOff(); if( (retval = (struct mangled_method *) KMALLOC(sizeof(struct mangled_method))) ) { retval->mm_flags = 0; retval->mm_method = 0; retval->mm_class = 0; retval->mm_args = 0; retval->mm_nargs = 0; } xProfilingOn(); return( retval );}void deleteMangledMethod(struct mangled_method *mm){ xProfilingOff(); if( mm ) { int lpc; KFREE(mm->mm_method); KFREE(mm->mm_class); for( lpc = 0; lpc < mm->mm_nargs; lpc++ ) { KFREE(mm->mm_args[lpc]); } KFREE(mm->mm_args); KFREE(mm); } xProfilingOn();}int mangleMethodName(struct mangled_method *mm, const char *name){ int retval = 0; size_t len, m_len; /* Constructors are mangled as an empty string */ if( !strcmp(name, "<init>") ) { name = ""; } len = strlen(name); if( (m_len = mangleLength(name, (int)len, 0, 0)) ) { /* * A method name with special chars has the `U' placed at the * end */ mm->mm_flags |= MMF_UNICODE_METHOD; } else m_len = len; if( (mm->mm_method = (char *)KMALLOC(m_len + 1)) ) { size_t res; res = mangleString(mm->mm_method, name, len, m_len != len); assert(res <= (m_len + 1)); retval = 1; } return( retval );}int mangleMethodClass(struct mangled_method *mm, void *cl, const char *name){ int retval = 0; /* Just mangle the type directly */ if( (mm->mm_class = mangleClassType(0, cl, name)) ) { retval = 1; } return( retval );}int mangleMethodArgCount(struct mangled_method *mm, int count){ int retval = 0; if( !count || (mm->mm_args = (char **)KMALLOC(sizeof(char *) * count)) ) { mm->mm_nargs = count; retval = 1; } return( retval );}/* * Helper function that checks for duplicate parameter types. */static int duplicateParameter(Method *meth, int curr_param){ int lpc, retval = -1; size_t curr_len; /* Figure out the length of the curr_param type string */ if( curr_param == METHOD_PSIG(meth)->nargs ) { /* * Its the last arg, an ')' and the return type follow, so we * use them to find the length */ curr_len = (METHOD_PSIG(meth)->ret_and_args[0] - 1) - METHOD_PSIG(meth)->ret_and_args[curr_param]; } else { curr_len = METHOD_PSIG(meth)->ret_and_args[curr_param] - METHOD_PSIG(meth)->ret_and_args[curr_param + 1]; } /* * Loop over the parameters searching for one that matches curr_param, * we start at 1 since 0 is the return type. */ for( lpc = 1; (lpc < curr_param) && (retval != -1); lpc++ ) { size_t arg_len; /* Figure out the length of the current parameter type */ if( lpc == METHOD_PSIG(meth)->nargs ) { arg_len = (METHOD_PSIG(meth)->ret_and_args[0] - 1) - METHOD_PSIG(meth)->ret_and_args[lpc]; } else { arg_len = METHOD_PSIG(meth)->ret_and_args[lpc] - METHOD_PSIG(meth)->ret_and_args[lpc + 1]; } if( arg_len > 1 ) { if( (strncmp(&METHOD_PSIG(meth)->signature-> data[METHOD_PSIG(meth)-> ret_and_args[curr_param]], &METHOD_PSIG(meth)->signature-> data[METHOD_PSIG(meth)->ret_and_args[lpc]], arg_len) == 0) && (curr_len == arg_len) ) { retval = lpc; } } } return( retval );}int mangleMethodArgs(struct mangled_method *mm, Method *meth){ int retval = 1, lpc, ref; for( lpc = 1; lpc <= mm->mm_nargs; lpc++ ) { if( (ref = duplicateParameter(meth, lpc)) >= 0 ) { /* * Duplicate parameter, use `T' to back ref the * previous one */ if( (mm->mm_args[lpc - 1] = (char *) KMALLOC(5)) ) { sprintf(mm->mm_args[lpc - 1], "T%d%s", ref, (ref > 9) ? "_" : ""); } } else { /* Unique parameter, mangle the type */ mm->mm_args[lpc - 1] = mangleType( 0, (char *)&METHOD_PSIG(meth)->signature-> data[METHOD_PSIG(meth)->ret_and_args[lpc]]); } } return( retval );}int mangleMethod(struct mangled_method *mm, Method *meth){ int retval = 0; xProfilingOff(); /* Try to mangle everything provided by `meth' */ if( mangleMethodName(mm, (char *)meth->name->data) && mangleMethodClass(mm, meth->class->loader, (char *)CLASS_CNAME(meth->class)) && mangleMethodArgCount(mm, METHOD_PSIG(meth)->nargs) && mangleMethodArgs(mm, meth) ) { retval = 1; } xProfilingOn(); return( retval );}int printMangledMethod(struct mangled_method *mm, FILE *file){ int retval = 0; /* Atleast check for method and class */ if( mm && mm->mm_method && mm->mm_class ) { int lpc; retval = 1; fprintf(file, "%s__%s", mm->mm_method, mm->mm_class); for( lpc = 0; (lpc < mm->mm_nargs) && retval; lpc++ ) { if( mm->mm_args[lpc] ) fprintf(file, "%s", mm->mm_args[lpc]); else retval = 0; } /* * If the method name has escapes we need to append the `U' to * the end */#if MANGLE_GCJ if( mm->mm_flags & MMF_UNICODE_METHOD ) fprintf(file, "U");#endif if( ferror(file) ) retval = 0; } return( retval );}/* Map of primitive Java types to the mangled types */static const char *primitive_type_map[] = { "Z", "b", /* boolean */ "C", "w", /* wide char */ "V", "v", /* void */ "B", "c", /* byte */ "S", "s", /* short */ "I", "i", /* integer */ "J", "x", /* long */ "F", "f", /* float */ "D", "d", /* double */ 0};const char *manglePrimitiveType(char type){ const char *retval = NULL; int lpc; for( lpc = 0; primitive_type_map[lpc] && !retval; lpc += 2 ) { if( type == primitive_type_map[lpc][0] ) retval = primitive_type_map[lpc + 1]; } return( retval );}char *mangleClassType(int prepend, void *cl, const char *name){ int quals = 0, num_chars = 0, num_underscores = 0, need_escapes = 0; int ch, error = 0; size_t len, m_len = 0, total_len = 0; char *retval = 0; const char *curr, *end; /* First we find the length of mangled string */ len = strlen(name); curr = name; end = name + len; while( (curr < end) && !error ) { ch = UTF8_GET(curr, end); if( ch < 0 ) { error = 1; } else if( ch == ';' ) { /* * The given name was of the form Ljava/lang/Object;, * so the `;' marks the end instead of the given null */ end = curr - 1; break; } else if( IS_SEP(ch) ) { /* * Its a qualified name, record the current counts for * this name segment and increment the number of * qualifiers */ quals++; m_len += 4 + (need_escapes ? 7 : 0) + num_chars + 4 * (need_escapes + num_underscores); num_chars = 0; need_escapes = 0; num_underscores = 0; } else if( (ch >= '0') && (ch <= '9') ) { /* If a number starts a name then we need an escape */ if( num_chars == 0 ) need_escapes++; } else if( ch == '_' && bad_underscore(curr, end)) {#if MANGLE_GCJ num_underscores++;#else need_escapes++;#endif } else if( ((ch < 'a') || (ch > 'z')) && ((ch < 'A') || (ch > 'Z')) && (ch != '_') ) { /* Its a special char, we'll need an escape */ need_escapes++; } num_chars++; } /* Figure out the total length of the mangled name */ total_len = m_len + 4 + (need_escapes ? 7 : 0) + (quals ? 7 : 0) + num_chars + 4 * (need_escapes + num_underscores); /* * If the class uses a non-root classLoader we need to encode that in * the name, otherwise we can make duplicate names for the same class * that are loaded by different class loaders. */ if( cl ) { total_len += (quals ? 0 : 7) + 2 + /* character count of `cl' + the number */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?