PatchSet 7218 Date: 2006/04/11 23:59:52 Author: robilad Branch: HEAD Tag: (none) Log: small warning fixlet
2006-04-12 Dalibor Topic <[EMAIL PROTECTED]> * kaffe/xprof/mangle.c (mangleClassType): Added missing cast to ptrdiff_t to fix compiler warning. Members: ChangeLog:1.4724->1.4725 kaffe/xprof/mangle.c:INITIAL->1.9 Index: kaffe/ChangeLog diff -u kaffe/ChangeLog:1.4724 kaffe/ChangeLog:1.4725 --- kaffe/ChangeLog:1.4724 Thu Apr 6 03:29:45 2006 +++ kaffe/ChangeLog Tue Apr 11 23:59:52 2006 @@ -1,3 +1,8 @@ +2006-04-12 Dalibor Topic <[EMAIL PROTECTED]> + + * kaffe/xprof/mangle.c (mangleClassType): + Added missing cast to ptrdiff_t to fix compiler warning. + 2006-04-06 Dalibor Topic <[EMAIL PROTECTED]> * kaffe/kaffevm/readClass.c (readSignatureAttribute): =================================================================== Checking out kaffe/kaffe/xprof/mangle.c RCS: /home/cvs/kaffe/kaffe/kaffe/xprof/mangle.c,v VERS: 1.9 *************** --- /dev/null Sun Aug 4 19:57:58 2002 +++ kaffe/kaffe/xprof/mangle.c Wed Apr 12 00:09:42 2006 @@ -0,0 +1,830 @@ +/* + * 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 == '_'); + } +#endif + +struct 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 */ + 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) <= (ptrdiff_t)(prepend + total_len + 1)); + } + return( retval ); +} + +char *mangleType(size_t prepend, const char *type) +{ + char *retval = 0; + + switch(type[0]) + { + case 'L': + /* Object reference */ + if( (retval = mangleClassType((int)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 */ + { + const char *prim; + + if( (prim = manglePrimitiveType(type[0])) ) + { + if( (retval = (char *)KMALLOC(prepend + 2)) ) + { + retval[prepend] = prim[0]; + retval[prepend + 1] = 0; + } + } + } + break; + } + return( retval ); +} + +size_t mangleLength(const char *string, int len, const char *term, size_t *out_len) +{ + int num_chars = 0, need_escapes = 0, num_underscores = 0; + int retval = -1, error = 0; + const 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 ); +} + +size_t mangleString(char *dest, const char *src, size_t slen, int _unicode) +{ + int retval = 0, ch, error = 0, need_escape = 0; + char *start; + const char *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 ); +} + +static int fputss(const char *str, size_t len, FILE *stream) +{ + size_t lpc; + int retval = 0; + + for( lpc = 0; lpc < len; lpc++ ) + { + putc(str[lpc], stream); + } + return( retval ); +} + +int vfmanglef(FILE *file, const char *format, va_list args) +{ + unsigned int sindex, eindex; + int retval = 0; + + for( sindex = eindex = 0; format[eindex] != '\0'; eindex++ ) + { + switch( format[eindex] ) + { + case '%': + { + int done = 0; + + while( !done ) + { + eindex += 1; + switch( format[eindex] ) + { + case 'q': /* qualified string */ + { + const char *quals, *str; + size_t offset = 0, len; + void *ptr; + + quals = va_arg(args, const char *); + str = va_arg(args, const char *); + ptr = va_arg(args, void *); + + len = strlen(str); + + while( offset < len ) + { + char buffer[1 + 2 + sizeof(void *) * 2 + 1]; + const char *sub_end; + size_t slen; + + buffer[0] = '\0'; + sub_end = strpbrk(&str[offset], quals); + if( sub_end == NULL ) + { + sub_end = &str[len]; + if( ptr != NULL ) + { + snprintf(buffer, + sizeof(buffer), + "_%p", + ptr); + } + } + slen = sub_end - &str[offset]; + fprintf(file, "%d", slen + strlen(buffer)); + fputss(&str[offset], slen, file); + fprintf(file, "%s", buffer); + offset += slen + 1; + } + done = 1; + } + break; + case 't': + { + const char *in, *out, *str; + unsigned int lpc; + + in = va_arg(args, const char *); + out = va_arg(args, const char *); + str = va_arg(args, const char *); + + assert(strlen(in) == strlen(out)); + for( lpc = 0; str[lpc] != '\0'; lpc++ ) + { + const char *rep; + + if( (rep = strchr(in, str[lpc])) != NULL ) + { + putc(out[rep - in], file); + } + else + { + putc(str[lpc], file); + } + } + done = 1; + } + break; + case 'c': + { + char c; + + c = (char)va_arg(args, int); + fprintf(file, "%c", c); + done = 1; + } + break; + case 'd': + { + int i; + + i = va_arg(args, int); + fprintf(file, "%d", i); + done = 1; + } + break; + case 'p': + { + void *ptr; + + ptr = va_arg(args, void *); + fprintf(file, "%p", ptr); + done = 1; + } + break; + case 's': + { + const char *str; + + str = va_arg(args, const char *); + + fprintf(file, "%s", str); + done = 1; + } + break; + case 'S': + { + const char *str; + size_t len; + + str = va_arg(args, const char *); + len = va_arg(args, size_t); + + fputss(str, len, file); + done = 1; + } + break; + default: + assert(0); + break; + } + } + } + break; + default: + putc(format[eindex], file); + break; + } + } + return( retval ); +} + +int fmanglef(FILE *file, const char *format, ...) +{ + va_list args; + int retval; + + va_start(args, format); + retval = vfmanglef(file, format, args); + va_end(args); + return( retval ); +} + +#endif /* defined(KAFFE_XDEBUGGING) || defined(KAFFE_XPROFILER) */ _______________________________________________ kaffe mailing list kaffe@kaffe.org http://kaffe.org/cgi-bin/mailman/listinfo/kaffe