]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Merge r6123:
authorJulian Seward <jseward@acm.org>
Tue, 17 Oct 2006 01:31:58 +0000 (01:31 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 17 Oct 2006 01:31:58 +0000 (01:31 +0000)
Extensions for unwinding stacks on ppc32-aix5 and ppc64-aix5.  Also,
extend the mechanism developed for ppc64-linux for fishing return
addresses out of the thread's redirection-stack when needed.

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

coregrind/m_stacktrace.c

index d7d9d165fe8bf30017933000a3589298dda8d922..b7fb5605ec3ed668409b5181def7d56a50e51d67 100644 (file)
@@ -60,9 +60,17 @@ UInt VG_(get_StackTrace2) ( ThreadId tid_if_known,
                             Addr ip, Addr sp, Addr fp, Addr lr,
                             Addr fp_min, Addr fp_max_orig )
 {
-#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
-   Bool  lr_is_first_RA = False; /* ppc only */
-#endif
+#  if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
+                               || defined(VGP_ppc32_aix5) \
+                               || defined(VGP_ppc64_aix5)
+   Bool  lr_is_first_RA = False;
+#  endif
+#  if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5) \
+                               || defined(VGP_ppc32_aix5)
+   Word redir_stack_size = 0;
+   Word redirs_used      = 0;
+#  endif
+
    Bool  debug = False;
    Int   i;
    Addr  fp_max;
@@ -154,7 +162,7 @@ UInt VG_(get_StackTrace2) ( ThreadId tid_if_known,
          continue;
       }
 
-      /* That didn't work out, so see if there is any CFI info to hand
+      /* That didn't work out, so see if there is any CF info to hand
          which can be used. */
       if ( VG_(use_CF_info)( &ip, &sp, &fp, fp_min, fp_max ) ) {
          ips[i++] = ip;
@@ -235,26 +243,45 @@ UInt VG_(get_StackTrace2) ( ThreadId tid_if_known,
       break;
    }
 
-#  elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
+#  elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
+        || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
 
    /*--------------------- ppc32/64 ---------------------*/
 
    /* fp is %r1.  ip is %cia.  Note, ppc uses r1 as both the stack and
       frame pointers. */
 
-#  if defined(VGP_ppc64_linux)
+#  if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
+   redir_stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
+   redirs_used      = 0;
+#  elif defined(VGP_ppc32_aix5)
+   redir_stack_size = VEX_GUEST_PPC32_REDIR_STACK_SIZE;
+   redirs_used      = 0;
+#  endif
+
+#  if defined(VG_PLAT_USES_PPCTOC)
    /* Deal with bogus LR values caused by function
-      interception/wrapping; see comment on similar code a few lines
-      further down. */
-   if (lr == (Addr)&VG_(ppc64_linux_magic_redirect_return_stub)
+      interception/wrapping on ppc-TOC platforms; see comment on
+      similar code a few lines further down. */
+   if (ULong_to_Ptr(lr) == (void*)&VG_(ppctoc_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)
+      Word hsp = VG_(threads)[tid_if_known].arch.vex.guest_REDIR_SP;
+      redirs_used++;
+      if (hsp >= 1 && hsp < redir_stack_size)
          lr = VG_(threads)[tid_if_known]
                  .arch.vex.guest_REDIR_STACK[hsp-1];
    }
 #  endif
 
+   /* We have to determine whether or not LR currently holds this fn
+      (call it F)'s return address.  It might not if F has previously
+      called some other function, hence overwriting LR with a pointer
+      to some part of F.  Hence if LR and IP point to the same
+      function then we conclude LR does not hold this function's
+      return address; instead the LR at entry must have been saved in
+      the stack by F's prologue and so we must get it from there
+      instead.  Note all this guff only applies to the innermost
+      frame. */
    lr_is_first_RA = False;
    {
 #     define M_VG_ERRTXT 1000
@@ -276,10 +303,11 @@ UInt VG_(get_StackTrace2) ( ThreadId tid_if_known,
 
       while (True) {
 
-        /* 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. */
-#        if defined(VGP_ppc64_linux)
+        /* On ppc64-linux (ppc64-elf, really), and on AIX, the lr save
+           slot is 2 words back from sp, whereas on ppc32-elf(?) it's
+           only one word back. */
+#        if defined(VGP_ppc64_linux) \
+            || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
          const Int lr_offset = 2;
 #        else
          const Int lr_offset = 1;
@@ -298,19 +326,23 @@ UInt VG_(get_StackTrace2) ( ThreadId tid_if_known,
             else
                ip = (((UWord*)fp)[lr_offset]);
 
-#           if defined(VGP_ppc64_linux)
+#           if defined(VG_PLAT_USES_PPCTOC)
             /* 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)
+               ppc64-linux/ppc64-aix/ppc32-aix.  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.  Since nested redirections can and
+               do happen, we keep track of the number of nested LRs
+               used by the unwinding so far with 'redirs_used'. */
+            if (ip == (Addr)&VG_(ppctoc_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)
+               Word hsp = VG_(threads)[tid_if_known].arch.vex.guest_REDIR_SP;
+               hsp -= 2 * redirs_used;
+               redirs_used ++;
+               if (hsp >= 1 && hsp < redir_stack_size)
                   ip = VG_(threads)[tid_if_known]
                           .arch.vex.guest_REDIR_STACK[hsp-1];
             }