From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25891 invoked by alias); 9 Jul 2006 09:19:28 -0000 Received: (qmail 25883 invoked by uid 22791); 9 Jul 2006 09:19:27 -0000 X-Spam-Check-By: sourceware.org Received: from main.gmane.org (HELO ciao.gmane.org) (80.91.229.2) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sun, 09 Jul 2006 09:19:25 +0000 Received: from list by ciao.gmane.org with local (Exim 4.43) id 1FzVRe-00010S-1E for java-patches@gcc.gnu.org; Sun, 09 Jul 2006 11:19:18 +0200 Received: from 59.92.154.170 ([59.92.154.170]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sun, 09 Jul 2006 11:19:18 +0200 Received: from rmathew by 59.92.154.170 with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sun, 09 Jul 2006 11:19:18 +0200 To: java-patches@gcc.gnu.org From: Ranjit Mathew Subject: [MinGW] RFA: Make Stack Traces Work for Interpreted Code on Windows Date: Sun, 09 Jul 2006 09:19:00 -0000 Message-ID: Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------020608070505050308060504" User-Agent: Thunderbird 1.5.0.4 (X11/20060516) OpenPGP: url=http://ranjitmathew.hostingzero.com/aa_6C114B8F.txt X-IsSubscribed: yes Mailing-List: contact java-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: java-patches-owner@gcc.gnu.org X-SW-Source: 2006-q3/txt/msg00101.txt.bz2 This is a multi-part message in MIME format. --------------020608070505050308060504 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-length: 2246 -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hello, When run under the interpreter, an exception-throwing programme crashes the interpreter on Windows since JvRunMain() does not occur in the call stack and we once again roam the wilderness of arbitrary EBP values. The fix was to change fallback_backtrace() in "sysdep/i386/backtrace.h" to stop on _Jv_RunMain() instead since this does occur in both interpreted and natively-executed call stacks. (Since this function is overloaded, I needed to use an interim variable with the appropriate cast to tell the compiler which of these function variants to pick up.) fallback_backtrace() also does not correctly handle unwinding through interpreted code. The fix was as simple as copying the relevant bits of code from _Jv_StackTrace::Unwind_TraceFn() and adjusting it a little bit. This exposed the fact that _Jv_InterpMethod::run() is a private method. Therefore I had to declare fallback_backtrace() as a friend function for this class (similar to that for the _Jv_StackTrace class). This declaration is done only if HAVE_FALLBACK_BACKTRACE is defined. This definition in turn was moved out of "sysdep/i386/backtrace.h" to configure.host, where it is added to libgcj_cxxflags (this jugglery avoids having to deal with included file ordering issues). The attached patch contains all these changes. Note that it also contains the "sysdep/i386/backtrace.h" changes from: http://gcc.gnu.org/ml/java-patches/2006-q3/msg00098.html purely as a matter of convenience for yours truly. With this patch, we now get proper stack traces for interpreted code also on Windows. (I note that under the interpreter we do not get line numbers for the innermost call frame, even on Linux. I haven't investigated this issue yet.) Tested via a crossed-native i686-pc-mingw32 compiler built on i686-pc-linux-gnu. OK to apply? Thanks, Ranjit. - -- Ranjit Mathew Email: rmathew AT gmail DOT com Bangalore, INDIA. Web: http://rmathew.com/ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFEsMo5Yb1hx2wRS48RAmZmAJsHu0Iyx3r9W4ILKg27BMBDC1sOZwCgix8m CFfW9c39jTSvqNxoH6lBLxY= =wLCp -----END PGP SIGNATURE----- --------------020608070505050308060504 Content-Type: text/plain; name="p2.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="p2.txt" Content-length: 4113 Index: ChangeLog from Ranjit Mathew * configure.host: Add a definition of HAVE_FALLBACK_BACKTRACE to libgcj_cxxflags for Windows. * include/java-interp.h (_Jv_InterpMethod): Declare fallback_backtrace() as a friend function. * sysdep/i386/backtrace.h: Do not define HAVE_FALLBACK_BACKTRACE. (fallback_backtrace): If we see _Jv_InterpMethod::run(), make sure the trace goes through the interpreted java stack. Stop unwinding when we see _Jv_RunMain(). Index: configure.host =================================================================== --- configure.host (revision 115260) +++ configure.host (working copy) @@ -283,6 +283,7 @@ esac case "${host}" in *-cygwin* | *-mingw*) fallback_backtrace_h=sysdep/i386/backtrace.h + libgcj_cxxflags="${libgcj_cxxflags} -DHAVE_FALLBACK_BACKTRACE" # We need a frame pointer on Windows, so override BACKTRACESPEC BACKTRACESPEC= ;; Index: include/java-interp.h =================================================================== --- include/java-interp.h (revision 115260) +++ include/java-interp.h (working copy) @@ -34,6 +34,11 @@ details. */ struct _Jv_ResolvedMethod; +#ifdef HAVE_FALLBACK_BACKTRACE +struct _Jv_UnwindState; +extern "C" void fallback_backtrace (_Jv_UnwindState *); +#endif + void _Jv_InitInterpreter (); void _Jv_DefineClass (jclass, jbyteArray, jint, jint, java::security::ProtectionDomain *, @@ -209,6 +214,10 @@ class _Jv_InterpMethod : public _Jv_Meth friend class _Jv_StackTrace; friend class _Jv_InterpreterEngine; +#ifdef HAVE_FALLBACK_BACKTRACE + friend void fallback_backtrace (_Jv_UnwindState *); +#endif + #ifdef JV_MARKOBJ_DECL friend JV_MARKOBJ_DECL; #endif Index: sysdep/i386/backtrace.h =================================================================== --- sysdep/i386/backtrace.h (revision 115261) +++ sysdep/i386/backtrace.h (working copy) @@ -13,8 +13,6 @@ details. */ #include -#define HAVE_FALLBACK_BACKTRACE - /* Store return addresses of the current program stack in STATE and return the exact number of values stored. */ void @@ -65,17 +63,44 @@ fallback_backtrace (_Jv_UnwindState *sta if (scan_bytes[0] == 0x55 && scan_bytes[1] == 0x89 && scan_bytes[2] == 0xE5) { - state->frames[i].start_ip = (void *)scan_addr; + // If we see the interpreter's main function, "pop" an entry + // off the interpreter stack and use that instead, so that the + // trace goes through the java code and not the interpreter + // itself. This assumes a 1:1 correspondance between call frames + // in the interpreted stack and occurances of + // _Jv_InterpMethod::run() on the native stack. + #ifdef INTERPRETER + void *interp_run = (void *) &_Jv_InterpMethod::run; + if ((void *)scan_addr == interp_run) + { + state->frames[i].type = frame_interpreter; + state->frames[i].interp.meth = state->interp_frame->self; + state->frames[i].interp.pc = state->interp_frame->pc; + state->interp_frame = state->interp_frame->next; + } + else + #endif /* INTERPRETER */ + { + state->frames[i].start_ip = (void *)scan_addr; + } + + // If we have a trace callback function, call it now. + if (state->trace_function != NULL) + (state->trace_function) (state); + break; } } - /* No need to unwind beyond JvRunMain(). */ - if (state->frames[i].start_ip == (void *)JvRunMain) + /* No need to unwind beyond _Jv_RunMain(). */ + void *jv_runmain + = (void *)(void (*)(JvVMInitArgs *, jclass, const char *, int, + const char **, bool))_Jv_RunMain; + if (state->frames[i].start_ip == jv_runmain) break; i++; + state->pos = i; } - state->pos = i; } #endif --------------020608070505050308060504--