mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-08 00:27:30 +08:00
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
@ -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:
|
||||
|
@ -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++;
|
||||
@ -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("<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.
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user