diff options
author | Mark Wielaard <mark@klomp.org> | 2002-09-02 15:55:57 +0000 |
---|---|---|
committer | Mark Wielaard <mark@gcc.gnu.org> | 2002-09-02 15:55:57 +0000 |
commit | 4d5c703ec010dbc5d4fad628639ae2b346ae22e4 (patch) | |
tree | eaa7255427dbc59adb36a9342d65ab7b66ffc9b4 | |
parent | f60518c8debf595354f37c0b2974a5dfa56aa5f1 (diff) | |
download | gcc-4d5c703ec010dbc5d4fad628639ae2b346ae22e4.zip gcc-4d5c703ec010dbc5d4fad628639ae2b346ae22e4.tar.gz gcc-4d5c703ec010dbc5d4fad628639ae2b346ae22e4.tar.bz2 |
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
-rw-r--r-- | libjava/ChangeLog | 10 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/NameFinder.java | 156 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/natNameFinder.cc | 7 | ||||
-rw-r--r-- | libjava/java/lang/natVMThrowable.cc | 2 |
4 files changed, 159 insertions, 16 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 0fe3d27..dabee51 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,13 @@ +2002-09-01 Mark Wielaard <mark@klomp.org> + + * 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 <konqueror@gmx.de> * 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 f32ebe0..1d729d2 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.</ul> * <ul><code>gnu.gcj.runtime.NameFinder.remove_unknown</code> - * 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.</ul> + * <ul><code>gnu.gcj.runtime.NameFinder.remove_interpreter</code> + * 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.</ul> * <ul><code>gnu.gcj.runtime.NameFinder.use_addr2line</code> - * 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 <code>dladdr</code>.</ul> * </li> @@ -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++; @@ -395,6 +422,111 @@ public class NameFinder } /** + * 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("<init>")) + { + 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 = "<unknown ref>"; + break; + case '[': + type = ""; + arrayDepth++; + break; + default: + type = "<unknown " + c + '>'; + } + 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. */ public void close() diff --git a/libjava/gnu/gcj/runtime/natNameFinder.cc b/libjava/gnu/gcj/runtime/natNameFinder.cc index 29488ed..29687cb 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 f5c56c7..ce897c2 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 |