This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Fix backtrace for interpreted code
- From: Andrew Haley <aph at redhat dot com>
- To: java-patches at gcc dot gnu dot org
- Date: Wed, 13 Oct 2004 18:47:33 +0100
- Subject: Fix backtrace for interpreted code
Tom Tromey noticed that stack traces no longer work for interpreted code.
This is due to the fact that we use a truly bogus way to discover if
the PC points into _Jv_InterpMethod::run.
There's no truly portable way to do something like this, but with a
little help from the unwinder library we can do it. This won't work
without the unwinder, but as far as I'm aware
_Unwind_FindEnclosingFunction should work on all targets.
Is this true even of mingw and Cygwin? Anyone who knows, please let
me know.
Andrew.
2004-10-13 Andrew Haley <aph@redhat.com>
* interpret.cc (_Jv_InterpMethod::run): Initialize
_Jv_StartOfInterpreter.
(_Jv_StartOfInterpreter, _Jv_EndOfInterpreter): Functions removed.
(_Jv_StartOfInterpreter, _Jv_EndOfInterpreter): New variables.
* gnu/gcj/runtime/natStackTrace.cc (fillInStackTrace): Use
_Unwind_FindEnclosingFunction to discover whether PC is within the
interpreter.
Index: interpret.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/interpret.cc,v
retrieving revision 1.45
diff -u -w -r1.45 interpret.cc
--- interpret.cc 13 Jul 2004 21:06:33 -0000 1.45
+++ interpret.cc 13 Oct 2004 17:40:10 -0000
@@ -774,18 +774,25 @@
}
#endif /* DIRECT_THREADED */
-// This function exists so that the stack-tracing code can find the
-// boundaries of the interpreter.
-void
-_Jv_StartOfInterpreter (void)
-{
-}
+// These exist so that the stack-tracing code can find the boundaries
+// of the interpreter.
+void *_Jv_StartOfInterpreter;
+void *_Jv_EndOfInterpreter;
+extern "C" void *_Unwind_FindEnclosingFunction (void *pc);
void
_Jv_InterpMethod::run (void *retp, ffi_raw *args)
{
using namespace java::lang::reflect;
+ // Record the address of the start of this member function in
+ // _Jv_StartOfInterpreter. Such a write to a global variable
+ // without acquiring a lock is correct iff reads and writes of words
+ // in memory are atomic, but Java requires that anyway.
+ foo:
+ if (! _Jv_StartOfInterpreter)
+ _Jv_StartOfInterpreter = _Unwind_FindEnclosingFunction (&&foo);
+
// FRAME_DESC registers this particular invocation as the top-most
// interpreter frame. This lets the stack tracing code (for
// Throwable) print information about the method being interpreted
@@ -3219,13 +3226,6 @@
}
}
-// This function exists so that the stack-tracing code can find the
-// boundaries of the interpreter.
-void
-_Jv_EndOfInterpreter (void)
-{
-}
-
static void
throw_internal_error (char *msg)
{
Index: gnu/gcj/runtime/natStackTrace.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/runtime/natStackTrace.cc,v
retrieving revision 1.6
diff -u -w -r1.6 natStackTrace.cc
--- gnu/gcj/runtime/natStackTrace.cc 2 Oct 2003 07:10:34 -0000 1.6
+++ gnu/gcj/runtime/natStackTrace.cc 13 Oct 2004 17:40:10 -0000
@@ -45,6 +45,10 @@
#include <unwind.h>
+#ifdef INTERPRETER
+extern "C" void *_Unwind_FindEnclosingFunction (void *pc);
+#endif // INTERPRETER
+
// Fill in this stack trace with MAXLEN elements starting at offset.
void
gnu::gcj::runtime::StackTrace::fillInStackTrace (jint maxlen, jint offset)
@@ -58,8 +62,8 @@
if (len > 0)
{
#ifdef INTERPRETER
- extern void _Jv_StartOfInterpreter (void);
- extern void _Jv_EndOfInterpreter (void);
+ extern void *_Jv_StartOfInterpreter;
+ extern void *_Jv_EndOfInterpreter;
java::lang::Thread *thread = java::lang::Thread::currentThread();
_Jv_MethodChain *interp_frame
@@ -70,15 +74,24 @@
frame = (_Jv_frame_info *) _Jv_Malloc (len * sizeof (_Jv_frame_info));
for (int n = 0; n < len; n++)
{
- frame[n].addr = p[n];
+ void *pc = p[n];
+ frame[n].addr = pc;
#ifdef INTERPRETER
- if (p[n] >= &_Jv_StartOfInterpreter && p[n] <= &_Jv_EndOfInterpreter)
+ frame[n].interp = 0;
+ if (_Jv_StartOfInterpreter != NULL)
+ {
+ if ((_Jv_EndOfInterpreter == NULL || pc < _Jv_EndOfInterpreter)
+ && _Unwind_FindEnclosingFunction (pc) == _Jv_StartOfInterpreter)
{
frame[n].interp = (void *) interp_frame->self;
interp_frame = interp_frame->next;
}
else
- frame[n].interp = 0;
+ {
+ if (_Jv_EndOfInterpreter == NULL || pc < _Jv_EndOfInterpreter)
+ _Jv_EndOfInterpreter = pc;
+ }
+ }
#endif // INTERPRETER
}
}