mangle.c
来自「kaffe Java 解释器语言,源码,Java的子集系统,开放源代码」· C语言 代码 · 共 654 行
C
654 行
/* * mangle.c * Routines for doing name mangling on Java types * * Copyright (c) 2000 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/ */#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(char *p, 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(char *p, 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, char *name){ int retval = 0, len, m_len; /* Constructors are mangled as an empty string */ if( !strcmp(name, "<init>") ) { name = ""; } len = strlen(name); if( (m_len = mangleLength(name, 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)) ) { int 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, 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 curr_len, lpc, retval = -1; /* 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++ ) { int 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 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};char *manglePrimitiveType(char type){ char *retval = 0; 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, char *name){ int quals = 0, num_chars = 0, num_underscores = 0, need_escapes = 0; int ch, len, m_len = 0, error = 0, total_len = 0; char *retval = 0, *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 */ 2 + /* 'cl' */ 2 + /* '0x' */ (sizeof(void *) * 2); /* the number */ quals++; } if( !error && (retval = (char *)KMALLOC(prepend + total_len + 1)) ) { char *dest; /* Start after the prepended section */ dest = retval + prepend; dest[0] = 0; if( quals ) { /* * Its a qualified name, print out how many qualifiers * there are before continuing */ quals++; if( quals < 10 ) sprintf(dest, "Q%d", quals); else sprintf(dest, "Q_%d_", quals); quals--; } dest += strlen(dest); /* Encode the class loader, if there is one */ if( cl ) { int cl_len; sprintf(dest + 3, "l%p", cl); cl_len = strlen(dest + 3) + 1; sprintf(dest, "%d", cl_len); dest[2] = 'c'; /* The previous sprintf overwrote it */ dest += cl_len + 2; quals--; } curr = name; while( curr < end ) { if( (m_len = mangleLength(curr, quals ? -1 : end - curr, NAME_SEPARATORS, &len)) ) {#if MANGLE_GCJ *dest = 'U'; dest++;#endif } else { m_len = len; } /* Write the length of the name */ sprintf(dest, "%d", m_len); dest += strlen(dest); /* Mangle the string */ mangleString(dest, curr, len, m_len != len); /* Move on to the next name */ dest += strlen(dest); curr += len + 1; quals--; } assert((dest - retval) <= (prepend + total_len + 1)); } return( retval );}char *mangleType(int prepend, char *type){ char *retval = 0; switch(type[0]) { case 'L': /* Object reference */ if( (retval = mangleClassType(prepend + 1, 0, type + 1)) ) retval[prepend] = 'P'; break; case '[': /* Array type */ if( (retval = mangleType(prepend + 11, type + 1)) ) strncpy(&retval[prepend], "Pt6JArray1Z", 11); break; default: /* Most likely a primitive */ { char *prim; if( (prim = manglePrimitiveType(type[0])) ) { if( (retval = (char *)KMALLOC(prepend + 2)) ) { retval[prepend] = prim[0]; retval[prepend + 1] = 0; } } } break; } return( retval );}int mangleLength(char *string, int len, char *term, int *out_len){ int num_chars = 0, need_escapes = 0, num_underscores = 0; int retval = -1, error = 0; char *curr, *end; curr = string; if( len < 0 ) end = (char *)-1; /* ick */ else end = string + len; while( !error && ((len < 0) || (curr < end)) ) { int ch = UTF8_GET(curr, end); if( ch < 0 ) { error = 1; break; } else if( term ) { int found_term = 0; int lpc; for( lpc = 0; term[lpc]; lpc++ ) { if( term[lpc] == ch ) found_term = 1; } if( found_term ) { /* Found the specified terminator */ break; } } if( (ch >= '0') && (ch <= '9') ) { /* If a number starts a name then we need an escape */ if( (curr - 1) == string) 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 != '_') ) { /* Special character, we'll need an escape */ need_escapes++; } num_chars++; } if( !error ) { if( need_escapes ) { retval = num_chars + 4 * (need_escapes + num_underscores); } else retval = 0; /* Write back the length */ if( out_len ) *out_len = num_chars; } return( retval );}int mangleString(char *dest, char *src, int slen, int unicode){ int retval = 0, ch, error = 0, need_escape = 0; char *start, *curr, *end; start = dest; curr = src; end = src + slen; while( (curr < end) && !error ) { ch = UTF8_GET(curr, end); if( ch < 0 ) { error = 1; } else if( (ch >= '0') && (ch <= '9') ) { if( (curr - 1) == src ) need_escape = 1; else need_escape = 0; } else if( ch == '_' ) { if( unicode && bad_underscore(curr, end) ) { need_escape = 1; } } else if( ((ch < 'a') || (ch > 'z')) && ((ch < 'A') || (ch > 'Z')) ) { need_escape = 1; } else { need_escape = 0; } if( !error ) { if( need_escape ) { sprintf(dest, "_%04x", ch); dest += 5; } else { *dest = ch; dest++; } } } *dest = 0; if( error ) retval = -1; else retval = dest - start + 1; return( retval );}#endif /* defined(KAFFE_XDEBUGGING) || defined(KAFFE_XPROFILER) */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?