From: Mark Wielaard Date: Mon, 2 Sep 2002 15:55:57 +0000 (+0000) Subject: NameFinder.java (remove_interpreter): New field. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4d5c703ec010dbc5d4fad628639ae2b346ae22e4;p=gcc.git NameFinder.java (remove_interpreter): New field. * gnu/gcj/runtime/NameFinder.java (remove_interpreter): New field. (sanitizeStack): Correctly reset unknown and interpreter counters, detect interpreter runtime frames. (demangleInterpreterMethod): New method. * gnu/gcj/runtime/natNameFinder.cc (lookupInterp): Use new method. * java/lang/natVMThrowable.cc (fillInStackTrace): Change order of filling in addrs[]. From-SVN: r56741 --- diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 0fe3d270249..dabee5148f5 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,13 @@ +2002-09-01 Mark Wielaard + + * gnu/gcj/runtime/NameFinder.java (remove_interpreter): New field. + (sanitizeStack): Correctly reset unknown and interpreter counters, + detect interpreter runtime frames. + (demangleInterpreterMethod): New method. + * gnu/gcj/runtime/natNameFinder.cc (lookupInterp): Use new method. + * java/lang/natVMThrowable.cc (fillInStackTrace): Change order of + filling in addrs[]. + 2002-09-02 Michael Koch * java/net/DatagramPacket.java, java/net/MulticsstSocket.java: diff --git a/libjava/gnu/gcj/runtime/NameFinder.java b/libjava/gnu/gcj/runtime/NameFinder.java index f32ebe0f530..1d729d252ac 100644 --- a/libjava/gnu/gcj/runtime/NameFinder.java +++ b/libjava/gnu/gcj/runtime/NameFinder.java @@ -34,11 +34,15 @@ import java.io.File; * should be removed from the stack trace. Only done when names are * demangled. *
    gnu.gcj.runtime.NameFinder.remove_unknown - * Wheter calls to unknown functions (class and method names are unknown) + * Whether calls to unknown functions (class and method names are unknown) * should be removed from the stack trace. Only done when the stack is * sanitized.
+ *
    gnu.gcj.runtime.NameFinder.remove_interpreter + * Whether runtime interpreter calls (methods in the _Jv_InterpMethod class + * and functions starting with 'ffi_') should be removed from the stack + * trace. Only done when the stack is sanitized.
*
    gnu.gcj.runtime.NameFinder.use_addr2line - * Wheter an external process (addr2line or addr2name.awk) should be used + * Whether an external process (addr2line or addr2name.awk) should be used * as fallback to convert the addresses to function names when the runtime * is unable to do it through dladdr.
* @@ -68,6 +72,10 @@ public class NameFinder = Boolean.valueOf(System.getProperty ("gnu.gcj.runtime.NameFinder.remove_unknown", "true") ).booleanValue(); + private static final boolean remove_interpreter + = Boolean.valueOf(System.getProperty + ("gnu.gcj.runtime.NameFinder.remove_interpreter", "true") + ).booleanValue(); private static final boolean use_addr2line = Boolean.valueOf(System.getProperty ("gnu.gcj.runtime.NameFinder.use_addr2line", "true") @@ -257,6 +265,7 @@ public class NameFinder consName = className.substring(lastDot + 1) + '('; int unknown = 0; + int interpreter = 0; int last_throw = -1; int length = elements.length; int end = length-1; @@ -274,10 +283,20 @@ public class NameFinder && (MName.startsWith(consName) || MName.startsWith("Throwable(") || MName.startsWith("fillInStackTrace(")))) - last_throw = i; + { + last_throw = i; + // Reset counting of unknown and interpreter frames. + unknown = 0; + interpreter = 0; + } else if (remove_unknown && CName == null && (MName == null || MName.startsWith("0x"))) unknown++; + else if (remove_interpreter + && ((CName == null + && MName != null && MName.startsWith("ffi_")) + || (CName != null && CName.equals("_Jv_InterpMethod")))) + interpreter++; else if ("main(java.lang.String[])".equals(MName)) { end = i; @@ -287,20 +306,28 @@ public class NameFinder int begin = last_throw+1; // Now filter out everything at the start and the end that is not part - // of the "normal" user program including any elements that have no - // usefull information whatsoever unless that means we filter out all info. - int nr_elements = end-begin-unknown+1; - if ((begin > 0 || end < length-1 || unknown > 0) && nr_elements > 0) + // of the "normal" user program including any elements that are interpreter + // calls or have no usefull information whatsoever. + // Unless that means we filter out all info. + int nr_elements = end-begin-unknown-interpreter+1; + if ((begin > 0 || end < length-1 || unknown > 0 || interpreter > 0) + && nr_elements > 0) { stack = new StackTraceElement[nr_elements]; int pos =0; for (int i=begin; i<=end; i++) { - String MName; - if (unknown == 0 - || !(elements[i].getClassName() == null - && ((MName = elements[i].getMethodName()) == null - || MName.startsWith("0x")))) + String MName = elements[i].getMethodName(); + String CName = elements[i].getClassName(); + if (remove_unknown && CName == null + && (MName == null || MName.startsWith("0x"))) + ; // Skip unknown frame + else if (remove_interpreter + && ((CName == null + && MName != null && MName.startsWith("ffi_")) + || (CName != null && CName.equals("_Jv_InterpMethod")))) + ; // Skip interpreter runtime frame + else { stack[pos] = elements[i]; pos++; @@ -394,6 +421,111 @@ public class NameFinder return s; } + /** + * Returns human readable method name and aguments given a method type + * signature as known to the interpreter and a classname. + */ + public static String demangleInterpreterMethod(String m, String cn) + { + int index = 0; + int length = m.length(); + StringBuffer sb = new StringBuffer(length); + + // Figure out the real method name + if (m.startsWith("")) + { + String className; + int i = cn.lastIndexOf('.'); + if (i < 0) + className = cn; + else + className = cn.substring(i + 1); + sb.append(className); + index += 7; + } + else + { + int i = m.indexOf('('); + if (i > 0) + { + sb.append(m.substring(0,i)); + index += i + 1; + } + } + + sb.append('('); + + // Demangle the type arguments + int arrayDepth = 0; + char c = (index < length) ? m.charAt(index) : ')'; + while (c != ')') + { + String type; + switch(c) + { + case 'B': + type = "byte"; + break; + case 'C': + type = "char"; + break; + case 'D': + type = "double"; + break; + case 'F': + type = "float"; + break; + case 'I': + type = "int"; + break; + case 'J': + type = "long"; + break; + case 'S': + type = "short"; + break; + case 'Z': + type = "boolean"; + break; + case 'L': + int i = m.indexOf(';', index); + if (i > 0) + { + type = m.substring(index+1, i); + index = i; + } + else + type = ""; + break; + case '[': + type = ""; + arrayDepth++; + break; + default: + type = "'; + } + sb.append(type); + + // Handle arrays + if (c != '[' && arrayDepth > 0) + while (arrayDepth > 0) + { + sb.append("[]"); + arrayDepth--; + } + + index++; + char nc = (index < length) ? m.charAt(index) : ')'; + if (c != '[' && nc != ')') + sb.append(", "); + c = nc; + } + + // Stop. We are not interested in the return type. + sb.append(')'); + return sb.toString(); + } + /** * Releases all resources used by this NameFinder. */ diff --git a/libjava/gnu/gcj/runtime/natNameFinder.cc b/libjava/gnu/gcj/runtime/natNameFinder.cc index 29488eddda7..29687cb5bb9 100644 --- a/libjava/gnu/gcj/runtime/natNameFinder.cc +++ b/libjava/gnu/gcj/runtime/natNameFinder.cc @@ -95,7 +95,6 @@ gnu::gcj::runtime::NameFinder::lookupInterp(RawData* addrs, jint n) _Jv_InterpMethod *meth = reinterpret_cast<_Jv_InterpMethod *> (stack[n].interp); - // FIXME: demangle. java::lang::StringBuffer *sb = new java::lang::StringBuffer(); sb->append(_Jv_NewStringUtf8Const(meth->self->name)); sb->append(_Jv_NewStringUtf8Const(meth->self->signature)); @@ -103,9 +102,11 @@ gnu::gcj::runtime::NameFinder::lookupInterp(RawData* addrs, jint n) // bytecode debug information. But currently we don't keep that // around. // FIXME: is using the defining class correct here? + java::lang::String *className = meth->defining_class->getName(); + java::lang::String *methodName + = demangleInterpreterMethod(sb->toString(), className); return new java::lang::StackTraceElement(NULL, -1, - meth->defining_class->getName(), - sb->toString(), false); + className, methodName, false); #else // INTERPRETER return NULL; #endif // INTERPRETER diff --git a/libjava/java/lang/natVMThrowable.cc b/libjava/java/lang/natVMThrowable.cc index f5c56c7a1d4..ce897c23e0b 100644 --- a/libjava/java/lang/natVMThrowable.cc +++ b/libjava/java/lang/natVMThrowable.cc @@ -72,7 +72,7 @@ java::lang::VMThrowable::fillInStackTrace (java::lang::Throwable* t) state->length = n; int len = n; addrs = (_Jv_frame_info *) _Jv_Malloc (n * sizeof (_Jv_frame_info)); - while (n--) + for (n = 0; n < len; n++) { addrs[n].addr = p[n]; #ifdef INTERPRETER