From: Julian Seward Date: Wed, 18 Jan 2006 04:25:20 +0000 (+0000) Subject: Make VG_(get_StackTrace2) aware of bogus LR values in X-Git-Tag: svn/VALGRIND_3_2_0~362 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8a98207bcf827d76404f5ddda1e50a2411342f83;p=thirdparty%2Fvalgrind.git Make VG_(get_StackTrace2) aware of bogus LR values in replacement/wrapper functions on ppc64-linux, which otherwise mess up the backtraces. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5549 --- diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c index f5e4a17ff1..d7bd1d3cdd 100644 --- a/coregrind/m_libcassert.c +++ b/coregrind/m_libcassert.c @@ -138,7 +138,8 @@ static void report_and_quit ( const Char* report, stacktop = tst->os_state.valgrind_stack_init_SP; - VG_(get_StackTrace2)(ips, BACKTRACE_DEPTH, ip, sp, fp, lr, sp, stacktop); + VG_(get_StackTrace2)(0/*tid is unknown*/, + ips, BACKTRACE_DEPTH, ip, sp, fp, lr, sp, stacktop); VG_(pp_StackTrace) (ips, BACKTRACE_DEPTH); // Don't print this, as it's not terribly interesting and avoids a diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c index e17e39bc40..8f4877cf27 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -48,8 +48,13 @@ IPs into 'ips'. In order to be thread-safe, we pass in the thread's IP SP, FP if that's meaningful, and LR if that's meaningful. Returns number of IPs put in 'ips'. + + If you know what the thread ID for this stack is, send that as the + first parameter, else send zero. This helps generate better stack + traces on ppc64-linux and has no effect on other platforms. */ -UInt VG_(get_StackTrace2) ( Addr* ips, UInt n_ips, +UInt VG_(get_StackTrace2) ( ThreadId tid_if_known, + Addr* ips, UInt n_ips, Addr ip, Addr sp, Addr fp, Addr lr, Addr fp_min, Addr fp_max_orig ) { @@ -230,7 +235,7 @@ UInt VG_(get_StackTrace2) ( Addr* ips, UInt n_ips, # elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) - /*--------------------- ppc32 ---------------------*/ + /*--------------------- ppc32/64 ---------------------*/ /* fp is %r1. ip is %cia. Note, ppc uses r1 as both the stack and frame pointers. */ @@ -259,7 +264,11 @@ UInt VG_(get_StackTrace2) ( Addr* ips, UInt n_ips, /* on ppc64-linux (ppc64-elf, really), the lr save slot is 2 words back from sp, whereas on ppc32-elf(?) it's only one word back. */ - const Int lr_offset = VG_WORDSIZE==8 ? 2 : 1; +# if defined(VGP_ppc64_linux) + const Int lr_offset = 2; +# else + const Int lr_offset = 1; +# endif if (i >= n_ips) break; @@ -274,6 +283,24 @@ UInt VG_(get_StackTrace2) ( Addr* ips, UInt n_ips, else ip = (((UWord*)fp)[lr_offset]); +# if defined(VGP_ppc64_linux) + /* Nasty hack to do with function replacement/wrapping on + ppc64-linux. If LR points to our magic return stub, + then we are in a wrapped or intercepted function, in + which LR has been messed with. The original LR will + have been pushed onto the thread's hidden REDIR stack + one down from the top (top element is the saved R2) and + so we should restore the value from there instead. */ + if (i == 1 + && ip == (Addr)&VG_(ppc64_linux_magic_redirect_return_stub) + && VG_(is_valid_tid)(tid_if_known)) { + Long hsp = VG_(threads)[tid_if_known].arch.vex.guest_REDIR_SP; + if (hsp >= 1 && hsp < VEX_GUEST_PPC64_REDIR_STACK_SIZE) + ip = VG_(threads)[tid_if_known] + .arch.vex.guest_REDIR_STACK[hsp-1]; + } +# endif + fp = (((UWord*)fp)[0]); ips[i++] = ip; if (debug) @@ -324,7 +351,8 @@ UInt VG_(get_StackTrace) ( ThreadId tid, StackTrace ips, UInt n_ips ) VG_(printf)("tid %d: stack_highest=%p ip=%p sp=%p fp=%p\n", tid, stack_highest_word, ip, sp, fp); - return VG_(get_StackTrace2)(ips, n_ips, ip, sp, fp, lr, sp, stack_highest_word); + return VG_(get_StackTrace2)(tid, ips, n_ips, ip, sp, fp, lr, sp, + stack_highest_word); } static void printIpDesc(UInt n, Addr ip) diff --git a/coregrind/m_translate.c b/coregrind/m_translate.c index eb845e43b1..fabee9f806 100644 --- a/coregrind/m_translate.c +++ b/coregrind/m_translate.c @@ -566,6 +566,8 @@ static Bool chase_into_ok ( void* closureV, Addr64 addr64 ) } +/* --------------- ppc64-linux specific helpers --------------- */ + #if defined(VGP_ppc64_linux) static IRExpr* mkU64 ( ULong n ) { @@ -681,6 +683,7 @@ Bool mk_preamble__ppc64_magic_return_stub ( void* closureV, IRBB* bb ) } #endif +/* --------------- END ppc64-linux specific helpers --------------- */ /* This is an the IR preamble generators used for replacement functions. It adds code to set the guest_NRADDR to zero @@ -692,7 +695,11 @@ Bool mk_preamble__ppc64_magic_return_stub ( void* closureV, IRBB* bb ) replacement function, and sets LR to point at the magic return-stub address. Setting LR causes the return of the wrapped/redirected function to lead to our magic return stub, which restores LR and R2 - from said stack and returns for real. */ + from said stack and returns for real. + + VG_(get_StackTrace2) understands that the LR value may point to the + return stub address, and that in that case it can get the real LR + value from the hidden stack instead. */ static Bool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRBB* bb ) { diff --git a/coregrind/pub_core_stacktrace.h b/coregrind/pub_core_stacktrace.h index 04e405b69f..51327aec7f 100644 --- a/coregrind/pub_core_stacktrace.h +++ b/coregrind/pub_core_stacktrace.h @@ -39,7 +39,12 @@ #include "pub_tool_stacktrace.h" // Variant that gives a little more control over the stack-walking. -extern UInt VG_(get_StackTrace2) ( StackTrace ips, UInt n_ips, +// If you know what the thread ID for this stack is, send that +// as the first parameter, else send zero. This helps generate +// better stack traces on ppc64-linux and has no effect on other +// platforms. +extern UInt VG_(get_StackTrace2) ( ThreadId tid_if_known, + StackTrace ips, UInt n_ips, Addr ip, Addr sp, Addr fp, Addr lr, Addr fp_min, Addr fp_max );