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
This commit is contained in:
parent
f60518c8de
commit
4d5c703ec0
4 changed files with 159 additions and 16 deletions
|
@ -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>
|
2002-09-02 Michael Koch <konqueror@gmx.de>
|
||||||
|
|
||||||
* java/net/DatagramPacket.java, java/net/MulticsstSocket.java:
|
* java/net/DatagramPacket.java, java/net/MulticsstSocket.java:
|
||||||
|
|
|
@ -34,11 +34,15 @@ import java.io.File;
|
||||||
* should be removed from the stack trace. Only done when names are
|
* should be removed from the stack trace. Only done when names are
|
||||||
* demangled.</ul>
|
* demangled.</ul>
|
||||||
* <ul><code>gnu.gcj.runtime.NameFinder.remove_unknown</code>
|
* <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
|
* should be removed from the stack trace. Only done when the stack is
|
||||||
* sanitized.</ul>
|
* 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>
|
* <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
|
* as fallback to convert the addresses to function names when the runtime
|
||||||
* is unable to do it through <code>dladdr</code>.</ul>
|
* is unable to do it through <code>dladdr</code>.</ul>
|
||||||
* </li>
|
* </li>
|
||||||
|
@ -68,6 +72,10 @@ public class NameFinder
|
||||||
= Boolean.valueOf(System.getProperty
|
= Boolean.valueOf(System.getProperty
|
||||||
("gnu.gcj.runtime.NameFinder.remove_unknown", "true")
|
("gnu.gcj.runtime.NameFinder.remove_unknown", "true")
|
||||||
).booleanValue();
|
).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
|
private static final boolean use_addr2line
|
||||||
= Boolean.valueOf(System.getProperty
|
= Boolean.valueOf(System.getProperty
|
||||||
("gnu.gcj.runtime.NameFinder.use_addr2line", "true")
|
("gnu.gcj.runtime.NameFinder.use_addr2line", "true")
|
||||||
|
@ -257,6 +265,7 @@ public class NameFinder
|
||||||
consName = className.substring(lastDot + 1) + '(';
|
consName = className.substring(lastDot + 1) + '(';
|
||||||
|
|
||||||
int unknown = 0;
|
int unknown = 0;
|
||||||
|
int interpreter = 0;
|
||||||
int last_throw = -1;
|
int last_throw = -1;
|
||||||
int length = elements.length;
|
int length = elements.length;
|
||||||
int end = length-1;
|
int end = length-1;
|
||||||
|
@ -274,10 +283,20 @@ public class NameFinder
|
||||||
&& (MName.startsWith(consName)
|
&& (MName.startsWith(consName)
|
||||||
|| MName.startsWith("Throwable(")
|
|| MName.startsWith("Throwable(")
|
||||||
|| MName.startsWith("fillInStackTrace("))))
|
|| 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
|
else if (remove_unknown && CName == null
|
||||||
&& (MName == null || MName.startsWith("0x")))
|
&& (MName == null || MName.startsWith("0x")))
|
||||||
unknown++;
|
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))
|
else if ("main(java.lang.String[])".equals(MName))
|
||||||
{
|
{
|
||||||
end = i;
|
end = i;
|
||||||
|
@ -287,20 +306,28 @@ public class NameFinder
|
||||||
int begin = last_throw+1;
|
int begin = last_throw+1;
|
||||||
|
|
||||||
// Now filter out everything at the start and the end that is not part
|
// 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
|
// of the "normal" user program including any elements that are interpreter
|
||||||
// usefull information whatsoever unless that means we filter out all info.
|
// calls or have no usefull information whatsoever.
|
||||||
int nr_elements = end-begin-unknown+1;
|
// Unless that means we filter out all info.
|
||||||
if ((begin > 0 || end < length-1 || unknown > 0) && nr_elements > 0)
|
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];
|
stack = new StackTraceElement[nr_elements];
|
||||||
int pos =0;
|
int pos =0;
|
||||||
for (int i=begin; i<=end; i++)
|
for (int i=begin; i<=end; i++)
|
||||||
{
|
{
|
||||||
String MName;
|
String MName = elements[i].getMethodName();
|
||||||
if (unknown == 0
|
String CName = elements[i].getClassName();
|
||||||
|| !(elements[i].getClassName() == null
|
if (remove_unknown && CName == null
|
||||||
&& ((MName = elements[i].getMethodName()) == null
|
&& (MName == null || MName.startsWith("0x")))
|
||||||
|| 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];
|
stack[pos] = elements[i];
|
||||||
pos++;
|
pos++;
|
||||||
|
@ -394,6 +421,111 @@ public class NameFinder
|
||||||
return s;
|
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("<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.
|
* Releases all resources used by this NameFinder.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -95,7 +95,6 @@ gnu::gcj::runtime::NameFinder::lookupInterp(RawData* addrs, jint n)
|
||||||
|
|
||||||
_Jv_InterpMethod *meth
|
_Jv_InterpMethod *meth
|
||||||
= reinterpret_cast<_Jv_InterpMethod *> (stack[n].interp);
|
= reinterpret_cast<_Jv_InterpMethod *> (stack[n].interp);
|
||||||
// FIXME: demangle.
|
|
||||||
java::lang::StringBuffer *sb = new java::lang::StringBuffer();
|
java::lang::StringBuffer *sb = new java::lang::StringBuffer();
|
||||||
sb->append(_Jv_NewStringUtf8Const(meth->self->name));
|
sb->append(_Jv_NewStringUtf8Const(meth->self->name));
|
||||||
sb->append(_Jv_NewStringUtf8Const(meth->self->signature));
|
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
|
// bytecode debug information. But currently we don't keep that
|
||||||
// around.
|
// around.
|
||||||
// FIXME: is using the defining class correct here?
|
// 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,
|
return new java::lang::StackTraceElement(NULL, -1,
|
||||||
meth->defining_class->getName(),
|
className, methodName, false);
|
||||||
sb->toString(), false);
|
|
||||||
#else // INTERPRETER
|
#else // INTERPRETER
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif // INTERPRETER
|
#endif // INTERPRETER
|
||||||
|
|
|
@ -72,7 +72,7 @@ java::lang::VMThrowable::fillInStackTrace (java::lang::Throwable* t)
|
||||||
state->length = n;
|
state->length = n;
|
||||||
int len = n;
|
int len = n;
|
||||||
addrs = (_Jv_frame_info *) _Jv_Malloc (n * sizeof (_Jv_frame_info));
|
addrs = (_Jv_frame_info *) _Jv_Malloc (n * sizeof (_Jv_frame_info));
|
||||||
while (n--)
|
for (n = 0; n < len; n++)
|
||||||
{
|
{
|
||||||
addrs[n].addr = p[n];
|
addrs[n].addr = p[n];
|
||||||
#ifdef INTERPRETER
|
#ifdef INTERPRETER
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue