public inbox for java@gcc.gnu.org
 help / color / mirror / Atom feed
* Question about a comment in _Jv_StackTrace::UnwindTraceFn
@ 2009-05-21 16:50 Dave Korn
  2009-05-21 17:15 ` Andrew Haley
  2009-05-21 17:17 ` Bryce McKinlay
  0 siblings, 2 replies; 7+ messages in thread
From: Dave Korn @ 2009-05-21 16:50 UTC (permalink / raw)
  To: java


    Hi java team,

  It suggests to me here that there should be an entry on the interpreter
stack corresponding to every entry though the interpreter's main function on
the CPU's native stack:

122       // If we see the interpreter's main function, "pop" an entry off the
123       // interpreter stack and use that instead, so that the trace goes
through
124       // the java code and not the interpreter itself. This assumes a 1:1
125       // correspondance between call frames in the interpreted stack and
occurances
126       // of _Jv_InterpMethod::run() on the native stack.

  I wonder if this assumption is still correct?  Or maybe it's a side-effect
of having configured with --enable-libgcj-debug?

127     #ifdef INTERPRETER
128       void *interp_run = NULL;
129
130       if (::gnu::classpath::jdwp::Jdwp::isDebugging)
(gdb)
131             interp_run = (void *) &_Jv_InterpMethod::run_debug;
132       else
133         interp_run = (void *) &_Jv_InterpMethod::run;
134
135       if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run))
136         {
137           state->frames[pos].type = frame_interpreter;
138           _Jv_Frame *frame = static_cast<_Jv_Frame *> (state->interp_frame);
139           state->frames[pos].interp.meth
140             = static_cast<_Jv_InterpMethod *> (frame->self);

... because I'm getting a NULL pointer here.  I saw that
gnu::classpath::jdwp::Jdwp::isDebugging is zero, so we're looking for the
plain run method, not run_debug.

(gdb) print ((_Jv_UnwindState *) state_ptr)[0]
$6 = {length = 100, pos = 23, frames = 0x22bba0, interp_frame = 0x0,
  trace_function = 0, trace_data = 0x0}
(gdb)

  There's no interp_frame entries.  Looking at the stack trace:

(gdb) bt
#0  _Jv_StackTrace::UnwindTraceFn (context=0x22bafc, state_ptr=0x22c388)
    at /gnu/gcc/gcc-patched/libjava/stacktrace.cc:140
#1  0x67f0660d in _Unwind_Backtrace (
    trace=0x5f0940 <_Jv_StackTrace::UnwindTraceFn(_Unwind_Context*, void*)>,
    trace_argument=0x22c388)
    at /usr/src/gcc/gcc4-4.3.2-2/src/gcc-4.3.2/libgcc/../gcc/unwind.inc:302
#2  0x005f0d2f in _Jv_StackTrace::GetStackTrace ()
    at /gnu/gcc/gcc-patched/libjava/stacktrace.cc:192
#3  0x005c5354 in java::lang::VMThrowable::fillInStackTrace ()
    at /gnu/gcc/gcc-patched/libjava/java/lang/natVMThrowable.cc:33
#4  0x00406400 in java.lang.Throwable.fillInStackTrace()java.lang.Throwable (
    this=0x29e8468)
    at /gnu/gcc/gcc-patched/libjava/classpath/java/lang/Throwable.java:500
#5  0x0041c84d in java.lang.Throwable.Throwable(java.lang.String) (
    this=0x29e8468, message=0x29ef5b0)
    at /gnu/gcc/gcc-patched/libjava/classpath/java/lang/Throwable.java:161
#6  0x0041faf7 in java.lang.Exception.Exception(java.lang.String) (
    this=0x29e8468, s=0x29ef5b0)
    at /gnu/gcc/gcc-patched/libjava/classpath/java/lang/Exception.java:78
#7  0x005468d7 in java.io.IOException.IOException(java.lang.String) (
    this=0x29e8468, message=0x29ef5b0)
    at /gnu/gcc/gcc-patched/libjava/classpath/java/io/IOException.java:72
#8  0x0073c154 in gnu::gcj::Core::create (name=0x29e8498)
    at /gnu/gcc/gcc-patched/libjava/gnu/gcj/natCore.cc:118
#9  0x005f1f05 in gnu.java.net.protocol.core.Connection.connect()void (
    this=0x29ef5e8)
    at /gnu/gcc/gcc-patched/libjava/gnu/java/net/protocol/core/Connection.java:5
0
#10 0x005f208f in gnu.java.net.protocol.core.Connection.getHeaders()void (
    this=0x29ef5e8)
    at /gnu/gcc/gcc-patched/libjava/gnu/java/net/protocol/core/Connection.java:1
54
#11 0x005f22c5 in gnu.java.net.protocol.core.Connection.getHeaderField(java.lang
.String)java.lang.String (this=0x29ef5e8, name=0x28f8070)
    at /gnu/gcc/gcc-patched/libjava/gnu/java/net/protocol/core/Connection.java:6
9
#12 0x0051cdae in java.net.URLConnection.getHeaderFieldInt(java.lang.String, int
)int (this=0x29ef5e8, name=0x28f8070, defaultValue=-1)
    at /gnu/gcc/gcc-patched/libjava/classpath/java/net/URLConnection.java:426
#13 0x0051b8a3 in java.net.URLConnection.getContentLength()int (
    this=0x29ef5e8)
    at /gnu/gcc/gcc-patched/libjava/classpath/java/net/URLConnection.java:302
#14 0x0071db1b in gnu.java.net.loader.RemoteURLLoader.getResource(java.lang.Stri
ng)gnu.java.net.loader.Resource (this=0x29d1dc0, name=0x29e84c8)
    at /gnu/gcc/gcc-patched/libjava/classpath/gnu/java/net/loader/RemoteURLLoade
r.java:79
#15 0x00532d7c in java.net.URLClassLoader.findClass(java.lang.String)java.lang.C
lass (this=0x29ab370, className=0x29f8ec0)
    at /gnu/gcc/gcc-patched/libjava/classpath/java/net/URLClassLoader.java:528
#16 0x004311cc in gnu.gcj.runtime.BootClassLoader.bootLoadClass(java.lang.String
)java.lang.Class (this=0x29ab370, name=0x29f8ec0)
    at /gnu/gcc/gcc-patched/libjava/gnu/gcj/runtime/BootClassLoader.java:68
#17 0x005c7ff5 in java::lang::VMClassLoader::loadClass (name=0x29f8ec0,
    resolve=0 '\0')
    at /gnu/gcc/gcc-patched/libjava/java/lang/natVMClassLoader.cc:223
#18 0x0042022b in java.lang.ClassLoader.loadClass(java.lang.String, boolean)java
.lang.Class (this=0x29120f0, name=0x29f8ec0, resolve=false)
---Type <return> to continue, or q <return> to quit---
    at /gnu/gcc/gcc-patched/libjava/java/lang/ClassLoader.java:439
#19 0x0042020d in java.lang.ClassLoader.loadClass(java.lang.String, boolean)java
.lang.Class (this=0x2912050, name=0x29f8ec0, resolve=false)
    at /gnu/gcc/gcc-patched/libjava/java/lang/ClassLoader.java:445
#20 0x00407701 in java.lang.ClassLoader.loadClass(java.lang.String)java.lang.Cla
ss (this=0x2912050, name=0x29f8ec0)
    at /gnu/gcc/gcc-patched/libjava/java/lang/ClassLoader.java:387
#21 0x004496a2 in _Jv_FindClass (name=0x29e7930, loader=0x2912050)
    at /gnu/gcc/gcc-patched/libjava/java/lang/natClassLoader.cc:512
#22 0x00449737 in _Jv_FindClassNoException (name=0x29e7930, loader=0x2912050)
    at /gnu/gcc/gcc-patched/libjava/java/lang/natClassLoader.cc:476
#23 0x0043e86b in _Jv_Linker::resolve_pool_entry (klass=0x294d4c0, index=97,
    lazy=false) at /gnu/gcc/gcc-patched/libjava/link.cc:440
#24 0x0044e695 in _Jv_InterpMethod::run (retp=0x22cb40, args=0x22cb60,
    meth=0x292e870) at /gnu/gcc/gcc-patched/libjava/interpret-run.cc:2385
#25 0x00780c45 in ffi_closure_raw_SYSV ()
    at /gnu/gcc/gcc-patched/libffi/src/x86/win32.S:338
#26 0x0044836c in java::lang::Class::initializeClass (this=0x294d4c0)
    at /gnu/gcc/gcc-patched/libjava/java/lang/natClass.cc:780
#27 0x00451d3b in _Jv_InterpMethod::run_class (ret=0x22cbc0, args=0x22cbe0,
    __this=0x2918c00) at /gnu/gcc/gcc-patched/libjava/java/lang/Class.h:742
#28 0x00780c45 in ffi_closure_raw_SYSV ()
    at /gnu/gcc/gcc-patched/libffi/src/x86/win32.S:338
#29 0x0061c684 in gnu::java::lang::MainThread::call_main (this=0x29af540)
    at /gnu/gcc/gcc-patched/libjava/gnu/java/lang/natMainThread.cc:54
#30 0x0043946a in gnu.java.lang.MainThread.run()void (this=0x29af540)
    at /gnu/gcc/gcc-patched/libjava/gnu/java/lang/MainThread.java:106
#31 0x004687b4 in _Jv_ThreadRun (thread=0x29af540)
    at /gnu/gcc/gcc-patched/libjava/java/lang/natThread.cc:335
#32 0x00404b7d in _Jv_RunMain (vm_args=0x22ccb0, klass=0x0,
    name=0x22cd4c "/gnu/gcc/gcc-patched/libjava/testsuite/libjava.jar/TestClosur
eGC.jar", argc=1, argv=0x28b9d48, is_jar=true)
    at /gnu/gcc/gcc-patched/libjava/prims.cc:1789
#33 0x00401392 in main (argc=3, argv=0x28b9d40)
    at /gnu/gcc/gcc-patched/libjava/gij.cc:333
(gdb)

... there is a single call to _Jv_InterpMethod::run, at frame #24, coming from
a call to ffi_closure_raw_SYSV.

  I've worked around this before by just avoiding the situation with

Index: libjava/stacktrace.cc
===================================================================
--- libjava/stacktrace.cc	(revision 147638)
+++ libjava/stacktrace.cc	(working copy)
@@ -132,7 +132,8 @@
   else
     interp_run = (void *) &_Jv_InterpMethod::run;
   	
-  if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run))
+  if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run)
+      && state->interp_frame)
     {
       state->frames[pos].type = frame_interpreter;
       _Jv_Frame *frame = static_cast<_Jv_Frame *> (state->interp_frame);

... but is that the right thing to do?  Where should state->interp_frame have
been set up?  It appears to fix testsuite failures, but I don't know for sure
if they're doing everything right internally.  I'll run it through a test
cycle if just avoiding the problem in this way is indeed correct, but a
pointer or two could speed me on the way or save me barking up any wrong trees.

    cheers,
      DaveK

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Question about a comment in _Jv_StackTrace::UnwindTraceFn
  2009-05-21 16:50 Question about a comment in _Jv_StackTrace::UnwindTraceFn Dave Korn
@ 2009-05-21 17:15 ` Andrew Haley
  2009-05-22  1:12   ` Dave Korn
  2009-05-21 17:17 ` Bryce McKinlay
  1 sibling, 1 reply; 7+ messages in thread
From: Andrew Haley @ 2009-05-21 17:15 UTC (permalink / raw)
  To: Dave Korn; +Cc: java

Dave Korn wrote:
>     Hi java team,
> 
>   It suggests to me here that there should be an entry on the interpreter
> stack corresponding to every entry though the interpreter's main function on
> the CPU's native stack:
> 
> 122       // If we see the interpreter's main function, "pop" an entry off the
> 123       // interpreter stack and use that instead, so that the trace goes
> through
> 124       // the java code and not the interpreter itself. This assumes a 1:1
> 125       // correspondance between call frames in the interpreted stack and
> occurances
> 126       // of _Jv_InterpMethod::run() on the native stack.
> 
>   I wonder if this assumption is still correct?  Or maybe it's a side-effect
> of having configured with --enable-libgcj-debug?
> 
> 127     #ifdef INTERPRETER
> 128       void *interp_run = NULL;
> 129
> 130       if (::gnu::classpath::jdwp::Jdwp::isDebugging)
> (gdb)
> 131             interp_run = (void *) &_Jv_InterpMethod::run_debug;
> 132       else
> 133         interp_run = (void *) &_Jv_InterpMethod::run;
> 134
> 135       if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run))
> 136         {
> 137           state->frames[pos].type = frame_interpreter;
> 138           _Jv_Frame *frame = static_cast<_Jv_Frame *> (state->interp_frame);
> 139           state->frames[pos].interp.meth
> 140             = static_cast<_Jv_InterpMethod *> (frame->self);
> 
> ... because I'm getting a NULL pointer here.  I saw that
> gnu::classpath::jdwp::Jdwp::isDebugging is zero, so we're looking for the
> plain run method, not run_debug.
> 
> (gdb) print ((_Jv_UnwindState *) state_ptr)[0]
> $6 = {length = 100, pos = 23, frames = 0x22bba0, interp_frame = 0x0,
>   trace_function = 0, trace_data = 0x0}
> (gdb)
> 
>   There's no interp_frame entries.  Looking at the stack trace:
> 
> (gdb) bt
> #0  _Jv_StackTrace::UnwindTraceFn (context=0x22bafc, state_ptr=0x22c388)
>     at /gnu/gcc/gcc-patched/libjava/stacktrace.cc:140
> #1  0x67f0660d in _Unwind_Backtrace (
>     trace=0x5f0940 <_Jv_StackTrace::UnwindTraceFn(_Unwind_Context*, void*)>,
>     trace_argument=0x22c388)
>     at /usr/src/gcc/gcc4-4.3.2-2/src/gcc-4.3.2/libgcc/../gcc/unwind.inc:302
> #2  0x005f0d2f in _Jv_StackTrace::GetStackTrace ()
>     at /gnu/gcc/gcc-patched/libjava/stacktrace.cc:192
> #3  0x005c5354 in java::lang::VMThrowable::fillInStackTrace ()
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natVMThrowable.cc:33
> #4  0x00406400 in java.lang.Throwable.fillInStackTrace()java.lang.Throwable (
>     this=0x29e8468)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/lang/Throwable.java:500
> #5  0x0041c84d in java.lang.Throwable.Throwable(java.lang.String) (
>     this=0x29e8468, message=0x29ef5b0)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/lang/Throwable.java:161
> #6  0x0041faf7 in java.lang.Exception.Exception(java.lang.String) (
>     this=0x29e8468, s=0x29ef5b0)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/lang/Exception.java:78
> #7  0x005468d7 in java.io.IOException.IOException(java.lang.String) (
>     this=0x29e8468, message=0x29ef5b0)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/io/IOException.java:72
> #8  0x0073c154 in gnu::gcj::Core::create (name=0x29e8498)
>     at /gnu/gcc/gcc-patched/libjava/gnu/gcj/natCore.cc:118
> #9  0x005f1f05 in gnu.java.net.protocol.core.Connection.connect()void (
>     this=0x29ef5e8)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/net/protocol/core/Connection.java:5
> 0
> #10 0x005f208f in gnu.java.net.protocol.core.Connection.getHeaders()void (
>     this=0x29ef5e8)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/net/protocol/core/Connection.java:1
> 54
> #11 0x005f22c5 in gnu.java.net.protocol.core.Connection.getHeaderField(java.lang
> .String)java.lang.String (this=0x29ef5e8, name=0x28f8070)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/net/protocol/core/Connection.java:6
> 9
> #12 0x0051cdae in java.net.URLConnection.getHeaderFieldInt(java.lang.String, int
> )int (this=0x29ef5e8, name=0x28f8070, defaultValue=-1)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/net/URLConnection.java:426
> #13 0x0051b8a3 in java.net.URLConnection.getContentLength()int (
>     this=0x29ef5e8)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/net/URLConnection.java:302
> #14 0x0071db1b in gnu.java.net.loader.RemoteURLLoader.getResource(java.lang.Stri
> ng)gnu.java.net.loader.Resource (this=0x29d1dc0, name=0x29e84c8)
>     at /gnu/gcc/gcc-patched/libjava/classpath/gnu/java/net/loader/RemoteURLLoade
> r.java:79
> #15 0x00532d7c in java.net.URLClassLoader.findClass(java.lang.String)java.lang.C
> lass (this=0x29ab370, className=0x29f8ec0)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/net/URLClassLoader.java:528
> #16 0x004311cc in gnu.gcj.runtime.BootClassLoader.bootLoadClass(java.lang.String
> )java.lang.Class (this=0x29ab370, name=0x29f8ec0)
>     at /gnu/gcc/gcc-patched/libjava/gnu/gcj/runtime/BootClassLoader.java:68
> #17 0x005c7ff5 in java::lang::VMClassLoader::loadClass (name=0x29f8ec0,
>     resolve=0 '\0')
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natVMClassLoader.cc:223
> #18 0x0042022b in java.lang.ClassLoader.loadClass(java.lang.String, boolean)java
> .lang.Class (this=0x29120f0, name=0x29f8ec0, resolve=false)
> ---Type <return> to continue, or q <return> to quit---
>     at /gnu/gcc/gcc-patched/libjava/java/lang/ClassLoader.java:439
> #19 0x0042020d in java.lang.ClassLoader.loadClass(java.lang.String, boolean)java
> .lang.Class (this=0x2912050, name=0x29f8ec0, resolve=false)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/ClassLoader.java:445
> #20 0x00407701 in java.lang.ClassLoader.loadClass(java.lang.String)java.lang.Cla
> ss (this=0x2912050, name=0x29f8ec0)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/ClassLoader.java:387
> #21 0x004496a2 in _Jv_FindClass (name=0x29e7930, loader=0x2912050)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natClassLoader.cc:512
> #22 0x00449737 in _Jv_FindClassNoException (name=0x29e7930, loader=0x2912050)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natClassLoader.cc:476
> #23 0x0043e86b in _Jv_Linker::resolve_pool_entry (klass=0x294d4c0, index=97,
>     lazy=false) at /gnu/gcc/gcc-patched/libjava/link.cc:440
> #24 0x0044e695 in _Jv_InterpMethod::run (retp=0x22cb40, args=0x22cb60,
>     meth=0x292e870) at /gnu/gcc/gcc-patched/libjava/interpret-run.cc:2385
> #25 0x00780c45 in ffi_closure_raw_SYSV ()
>     at /gnu/gcc/gcc-patched/libffi/src/x86/win32.S:338
> #26 0x0044836c in java::lang::Class::initializeClass (this=0x294d4c0)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natClass.cc:780
> #27 0x00451d3b in _Jv_InterpMethod::run_class (ret=0x22cbc0, args=0x22cbe0,
>     __this=0x2918c00) at /gnu/gcc/gcc-patched/libjava/java/lang/Class.h:742
> #28 0x00780c45 in ffi_closure_raw_SYSV ()
>     at /gnu/gcc/gcc-patched/libffi/src/x86/win32.S:338
> #29 0x0061c684 in gnu::java::lang::MainThread::call_main (this=0x29af540)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/lang/natMainThread.cc:54
> #30 0x0043946a in gnu.java.lang.MainThread.run()void (this=0x29af540)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/lang/MainThread.java:106
> #31 0x004687b4 in _Jv_ThreadRun (thread=0x29af540)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natThread.cc:335
> #32 0x00404b7d in _Jv_RunMain (vm_args=0x22ccb0, klass=0x0,
>     name=0x22cd4c "/gnu/gcc/gcc-patched/libjava/testsuite/libjava.jar/TestClosur
> eGC.jar", argc=1, argv=0x28b9d48, is_jar=true)
>     at /gnu/gcc/gcc-patched/libjava/prims.cc:1789
> #33 0x00401392 in main (argc=3, argv=0x28b9d40)
>     at /gnu/gcc/gcc-patched/libjava/gij.cc:333
> (gdb)
> 
> ... there is a single call to _Jv_InterpMethod::run, at frame #24, coming from
> a call to ffi_closure_raw_SYSV.
> 
>   I've worked around this before by just avoiding the situation with
> 
> Index: libjava/stacktrace.cc
> ===================================================================
> --- libjava/stacktrace.cc	(revision 147638)
> +++ libjava/stacktrace.cc	(working copy)
> @@ -132,7 +132,8 @@
>    else
>      interp_run = (void *) &_Jv_InterpMethod::run;
>    	
> -  if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run))
> +  if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run)
> +      && state->interp_frame)
>      {
>        state->frames[pos].type = frame_interpreter;
>        _Jv_Frame *frame = static_cast<_Jv_Frame *> (state->interp_frame);
> 
> ... but is that the right thing to do?  Where should state->interp_frame have
> been set up?  It appears to fix testsuite failures, but I don't know for sure
> if they're doing everything right internally.  I'll run it through a test
> cycle if just avoiding the problem in this way is indeed correct, but a
> pointer or two could speed me on the way or save me barking up any wrong trees.

You need to put a breakpoint at the constructor of _Jv_InterpFrame.  It creates
a node and pushes it into the linked list starting at thr->interp_frame:

  _Jv_InterpFrame (void *meth, java::lang::Thread *thr, jclass proxyCls = NULL,
                   pc_t *pc = NULL,
		   _Jv_FrameType frame_type = frame_interpreter)
  : _Jv_Frame (reinterpret_cast<_Jv_MethodBase *> (meth), thr,
	             frame_type)
  {
    next_interp = (_Jv_InterpFrame *) thr->interp_frame;
    proxyClass = proxyCls;
    thr->interp_frame = (gnu::gcj::RawData *) this;
    obj_ptr = NULL;
    pc_ptr = pc;
  }

This constructor is called from interpret-run.cc:27.

Andrew.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Question about a comment in _Jv_StackTrace::UnwindTraceFn
  2009-05-21 16:50 Question about a comment in _Jv_StackTrace::UnwindTraceFn Dave Korn
  2009-05-21 17:15 ` Andrew Haley
@ 2009-05-21 17:17 ` Bryce McKinlay
  2009-05-21 18:53   ` Dave Korn
  1 sibling, 1 reply; 7+ messages in thread
From: Bryce McKinlay @ 2009-05-21 17:17 UTC (permalink / raw)
  To: Dave Korn; +Cc: java

On Thu, May 21, 2009 at 6:02 PM, Dave Korn
<dave.korn.cygwin@googlemail.com> wrote:

> ... but is that the right thing to do?  Where should state->interp_frame have
> been set up?  It appears to fix testsuite failures, but I don't know for sure
> if they're doing everything right internally.  I'll run it through a test
> cycle if just avoiding the problem in this way is indeed correct, but a
> pointer or two could speed me on the way or save me barking up any wrong trees.

Hi Dave

state->interp_frame is set in the _Jv_InterpFrame constructor, right
at the top of interp-run.cc

#ifdef __GCJ_DEBUG
  _Jv_InterpFrame frame_desc (meth, thread, NULL, &pc);
#else
  _Jv_InterpFrame frame_desc (meth, thread);
#endif

_Jv_InterpFrame itself is defined in include/java-interp.h

Bryce

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Question about a comment in _Jv_StackTrace::UnwindTraceFn
  2009-05-21 17:17 ` Bryce McKinlay
@ 2009-05-21 18:53   ` Dave Korn
  2009-05-21 19:13     ` Dave Korn
  2009-05-21 20:36     ` Dave Korn
  0 siblings, 2 replies; 7+ messages in thread
From: Dave Korn @ 2009-05-21 18:53 UTC (permalink / raw)
  To: Bryce McKinlay; +Cc: Dave Korn, java

Bryce McKinlay wrote:
> On Thu, May 21, 2009 at 6:02 PM, Dave Korn
> <dave.korn.cygwin@googlemail.com> wrote:
> 
>> ... but is that the right thing to do?  Where should state->interp_frame have
>> been set up?  It appears to fix testsuite failures, but I don't know for sure
>> if they're doing everything right internally.  I'll run it through a test
>> cycle if just avoiding the problem in this way is indeed correct, but a
>> pointer or two could speed me on the way or save me barking up any wrong trees.
> 
> Hi Dave
> 
> state->interp_frame is set in the _Jv_InterpFrame constructor, right
> at the top of interp-run.cc
> 
> #ifdef __GCJ_DEBUG
>   _Jv_InterpFrame frame_desc (meth, thread, NULL, &pc);
> #else
>   _Jv_InterpFrame frame_desc (meth, thread);
> #endif
> 
> _Jv_InterpFrame itself is defined in include/java-interp.h

  Okeydokey, I've watched it go through the constructor, and tag itself onto
the linked list, and it's still the only entry.  Stepping through the
interpreter we get to

514           NEXT_INSN;
(gdb)
2382            SAVE_PC();
(gdb)
2383            int index = GET2U ();
(gdb) step
2385

and that leads us through _Jv_Linker::resolve_pool_entry ->
_Jv_FindClassNoException -> _Jv_FindClass -> java.lang.ClassLoader.loadClass.

It's trying to load 'java.util.HashSet'.  It ends up calling through a bunch
of java.lang.ClassLoader methods and java::lang::VMClassLoader into
gnu.gcj.runtime.BootClassLoader.bootLoadClass which tries to open some sort of
URLConnection.  The gnu.java.net.protocol.core.Connection.connect method wants
to create a Core object:

42        // Implementation of abstract method.
43        public void connect() throws IOException
44        {
45          // Call is ignored if already connected.
46          if (connected)
47            return;
48
49          // If not connected, then file needs to be opened.
50          core = Core.create (url.getFile());

and _Jv_create_core fails.

113     gnu::gcj::Core *
114     gnu::gcj::Core::create (jstring name)
115     {
116       gnu::gcj::Core *core = _Jv_create_core (root, name);
117       if (core == NULL)
118         throw new ::java::io::IOException (JvNewStringLatin1 ("can't open co
re"));
119       return core;
120     }
(gdb)

  name is "/java/lang/Object.class".  There are no _Jv_core_chain nodes on the
root chain.  So we throw an exception.

  That proceeds smoothly through the IOException and base Exception
constructors and then reaches the Throwable constructor:


(gdb) list
156        *
157        * @param message the message to associate with the Throwable
158        */
159       public Throwable(String message)
160       {
161         fillInStackTrace();
162         detailMessage = message;
163       }
164
165       /**
(gdb)

.. which calls fillInStackTrace.  And this is where I think it's going to go
wrong:

(gdb) list
25      java::lang::VMThrowable::fillInStackTrace (java::lang::Throwable *)
26      {
27        using namespace java::lang;
28
29        // Don't trace stack during initialization of the runtime.
30        if (! gcj::runtimeInitialized)
31          return NULL;
32
33        _Jv_StackTrace *trace = _Jv_StackTrace::GetStackTrace ();
34        VMThrowable *vmthrowable = new VMThrowable ();
(gdb)
35        vmthrowable->data = (RawDataManaged *) trace;
36        return vmthrowable;
37      }

... because we're still in runtime initialisation here:

(gdb) frame 25
#25 0x004049af in _Jv_CreateJavaVM (vm_args=0x22ccb0)
    at /gnu/gcc/gcc-patched/libjava/prims.cc:1682
1682      _Jv_JNI_Init ();
(gdb) list
1677      LTDL_SET_PRELOADED_SYMBOLS ();
1678    #endif
1679
1680      _Jv_platform_initialize ();
1681
1682      _Jv_JNI_Init ();
1683
1684    #ifdef INTERPRETER
1685      _Jv_JVMTI_Init ();
1686    #endif
(gdb)


... as called from _Jv_RunMain.  But the runtimeInitialized flag was set true
right at the start of _Jv_CreateJavaVM:

1610    jint
1611    _Jv_CreateJavaVM (JvVMInitArgs* vm_args)
1612    {
1613      using namespace gcj;
1614
1615      if (runtimeInitialized)
1616        return -1;



  So, I think maybe I have *two* problems:

i)  The gcj::Core::root chain is empty.  Should it be?  Do I have a problem
with static c/dtors?  I don't have JCR_SECTIONS turned on yet, so maybe I need
to enable it?

ii) I don't think the library is able to handle an exception being thrown this
early in startup because the code that segfaults filling out the stacktrace
does assume it's inside at least one nested interpreter frame, and it wouldn't
be called at all if it wasn't for what looks like a race-condition failure of
the safety check at the top of java::lang::VMThrowable::fillInStackTrace.
Should nothing be throwing at this early stage, or should we perhaps not set
runtimeInitialized until later?  I note that it gets set true a second time,
apparently redundantly, at the very end of _Jv_CreateJavaVM, so perhaps an
accident of some sort has occurred here?  I'll take a look through the svn
history.

    cheers,
      DaveK

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Question about a comment in _Jv_StackTrace::UnwindTraceFn
  2009-05-21 18:53   ` Dave Korn
@ 2009-05-21 19:13     ` Dave Korn
  2009-05-21 20:36     ` Dave Korn
  1 sibling, 0 replies; 7+ messages in thread
From: Dave Korn @ 2009-05-21 19:13 UTC (permalink / raw)
  To: Dave Korn; +Cc: Bryce McKinlay, java, Andrew Haley

Dave Korn wrote:

>   So, I think maybe I have *two* problems:
> 
> i)  The gcj::Core::root chain is empty.  Should it be?  Do I have a problem
> with static c/dtors?  I don't have JCR_SECTIONS turned on yet, so maybe I need
> to enable it?

  To half-answer my own question there, __Jv_global_static_constructor is at
least being called at static ctor time, so I should be OK on most fronts.

> ii) I don't think the library is able to handle an exception being thrown this
> early in startup because the code that segfaults filling out the stacktrace
> does assume it's inside at least one nested interpreter frame, and it wouldn't
> be called at all if it wasn't for what looks like a race-condition failure of
> the safety check at the top of java::lang::VMThrowable::fillInStackTrace.
> Should nothing be throwing at this early stage, or should we perhaps not set
> runtimeInitialized until later?  I note that it gets set true a second time,
> apparently redundantly, at the very end of _Jv_CreateJavaVM, so perhaps an
> accident of some sort has occurred here?  I'll take a look through the svn
> history.


  Yes, this looks like a regression.  The setting of runtimeInitialized was
moved to the end of the function in r115791

Revision 115791 - (view) (download) - [select for diffs]
Modified Fri Jul 28 07:40:17 2006 UTC (2 years, 9 months ago) by gary
File length: 45045 byte(s)
Diff to previous 114300 (colored)

2006-07-28  Gary Benson  <gbenson@redhat.com>

	* prims.cc (_Jv_CreateJavaVM): Move setting runtimeInitialized
	from the start to the end of the function.  Remove references
	to VMThrowable.trace_enabled.
	* java/lang/natVMThrowable.cc (fillInStackTrace): Use
	runtimeInitialized rather than trace_enabled to decide
	whether to inhibit stack trace generation.
	* java/lang/VMThrowable.java (trace_enabled): Removed.


... and apparently re-added at the start, almost certainly inadvertently, when
Tom merged the gcj-eclipse branch to trunk at r120621.

  I will prepare and test a patch that simply removes the re-added set at the
top of the function.

    cheers,
      DaveK

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Question about a comment in _Jv_StackTrace::UnwindTraceFn
  2009-05-21 18:53   ` Dave Korn
  2009-05-21 19:13     ` Dave Korn
@ 2009-05-21 20:36     ` Dave Korn
  1 sibling, 0 replies; 7+ messages in thread
From: Dave Korn @ 2009-05-21 20:36 UTC (permalink / raw)
  To: Dave Korn; +Cc: Bryce McKinlay, java

Dave Korn wrote:

> ... because we're still in runtime initialisation here:
> 
> (gdb) frame 25
> #25 0x004049af in _Jv_CreateJavaVM (vm_args=0x22ccb0)
>     at /gnu/gcc/gcc-patched/libjava/prims.cc:1682
> 1682      _Jv_JNI_Init ();

  Uhh, waittaminnit, no we aren't.  Where did I get that from?  Certainly
wasn't in my original stack dump.  Removing the early set didn't help.

>   So, I think maybe I have *two* problems:

  *honk!*  Make that three ... I'll do some further digging.

    cheers,
      DaveK

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Question about a comment in _Jv_StackTrace::UnwindTraceFn
  2009-05-21 17:15 ` Andrew Haley
@ 2009-05-22  1:12   ` Dave Korn
  0 siblings, 0 replies; 7+ messages in thread
From: Dave Korn @ 2009-05-22  1:12 UTC (permalink / raw)
  To: java; +Cc: Dave Korn

Andrew Haley wrote:
> Dave Korn wrote:

>> 124       // the java code and not the interpreter itself. This assumes a 1:1
>> 125       // correspondance between call frames in the interpreted stack and
>> occurances
>> 126       // of _Jv_InterpMethod::run() on the native stack.

>> 127     #ifdef INTERPRETER
>> 128       void *interp_run = NULL;
>> 129
>> 130       if (::gnu::classpath::jdwp::Jdwp::isDebugging)
>> (gdb)
>> 131         interp_run = (void *) &_Jv_InterpMethod::run_debug;
>> 132       else
>> 133         interp_run = (void *) &_Jv_InterpMethod::run;
>> 134
>> 135       if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run))
>> 136         {
>> 137           state->frames[pos].type = frame_interpreter;
>> 138           _Jv_Frame *frame = static_cast<_Jv_Frame *> (state->interp_frame);
>> 139           state->frames[pos].interp.meth
>> 140             = static_cast<_Jv_InterpMethod *> (frame->self);

> #23 0x0043e86b in _Jv_Linker::resolve_pool_entry (klass=0x294d4c0, index=97,
>     lazy=false) at /gnu/gcc/gcc-patched/libjava/link.cc:440
> #24 0x0044e695 in _Jv_InterpMethod::run (retp=0x22cb40, args=0x22cb60,
>     meth=0x292e870) at /gnu/gcc/gcc-patched/libjava/interpret-run.cc:2385
> #25 0x00780c45 in ffi_closure_raw_SYSV ()
>     at /gnu/gcc/gcc-patched/libffi/src/x86/win32.S:338
> #26 0x0044836c in java::lang::Class::initializeClass (this=0x294d4c0)

>> ... there is a single call to _Jv_InterpMethod::run, at frame #24, coming from
>> a call to ffi_closure_raw_SYSV.

  And that's where it goes wrong.  _Unwind_Backtrace happily unwinds the stack
all the way down through _Jv_Linker::resolve_pool_entry calling the unwind
hook, which does nothing in each case.  It unwinds one more frame level,
reaching _Jv_InterpMethod::run, and calls the hook, which this time pops the
(one and only) interpreter frame.  _Unwind_Backtrace unwinds one more level
and then calls the hook again - but the _Unwind_Context it passes is still the
same as last time - it has not been updated, and still points at
_Jv_InterpMethod::run.  So the hook attempts to pop another interpreter frame,
and that's when it falls off the end of the linklist and dies.

  I think the explanation why _Unwind_Backtrace fails to update the context
and calls the stack trace hook with the same context for the run method twice
is pretty simple: there's no eh_frame data for the calling function
ffi_closure_raw_SYSV.  All the other .S files in libffi/src/$arch/ have a
hand-written .eh_frame section, but x86/win32.S is lacking one.

  The solution is now obvious, but not easy.  I'll be off in the corner with a
copy of the Dwarf spec for a while, learning how to hand-craft CIEs and FDEs
and all those things.  If anyone knows of a handy tool or shortcut that can
help me with that task, please drop me a reply, because I don't know of any
option apart from doing it manually.

    cheers,
      DaveK

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-05-22  1:12 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-21 16:50 Question about a comment in _Jv_StackTrace::UnwindTraceFn Dave Korn
2009-05-21 17:15 ` Andrew Haley
2009-05-22  1:12   ` Dave Korn
2009-05-21 17:17 ` Bryce McKinlay
2009-05-21 18:53   ` Dave Korn
2009-05-21 19:13     ` Dave Korn
2009-05-21 20:36     ` Dave Korn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).