]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Make VG_(get_StackTrace2) aware of bogus LR values in
authorJulian Seward <jseward@acm.org>
Wed, 18 Jan 2006 04:25:20 +0000 (04:25 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 18 Jan 2006 04:25:20 +0000 (04:25 +0000)
replacement/wrapper functions on ppc64-linux, which otherwise mess up
the backtraces.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5549

coregrind/m_libcassert.c
coregrind/m_stacktrace.c
coregrind/m_translate.c
coregrind/pub_core_stacktrace.h

index f5e4a17ff1ecc4411367a541dfc95f0acded1ea8..d7bd1d3cddafab0f80fe5c0f570e4565765fc0b0 100644 (file)
@@ -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
index e17e39bc403be00ce1ed7d723221716bd8db7db7..8f4877cf2782e11b3c016c759601084d58b74fb0 100644 (file)
    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)
index eb845e43b17ade6a92c90a0dcd4131a5571dc37a..fabee9f8063bca147ef166714c8ad060df19c9ff 100644 (file)
@@ -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 )
 {
index 04e405b69f4968bcab6ce2fc09fc55fc7da7689f..51327aec7f8b399e495a29fd02f3595ec1c85419 100644 (file)
 #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 );