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 + -
显示快捷键?