|
From: <sv...@va...> - 2006-10-01 17:37:27
|
Author: sewardj
Date: 2006-10-01 18:37:24 +0100 (Sun, 01 Oct 2006)
New Revision: 6123
Log:
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.
Modified:
branches/AIX5/coregrind/m_stacktrace.c
Modified: branches/AIX5/coregrind/m_stacktrace.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/AIX5/coregrind/m_stacktrace.c 2006-10-01 17:27:36 UTC (rev 6=
122)
+++ branches/AIX5/coregrind/m_stacktrace.c 2006-10-01 17:37:24 UTC (rev 6=
123)
@@ -29,6 +29,7 @@
*/
=20
#include "pub_core_basics.h"
+#include "pub_core_vki.h"
#include "pub_core_threadstate.h"
#include "pub_core_debuginfo.h"
#include "pub_core_aspacemgr.h" // For VG_(is_addressable)()
@@ -59,7 +60,8 @@
Addr ip, Addr sp, Addr fp, Addr lr,
Addr fp_min, Addr fp_max_orig )
{
-#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
+ || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
Bool lr_is_first_RA =3D False; /* ppc only */
#endif
Bool debug =3D False;
@@ -153,7 +155,7 @@
continue;
}
=20
- /* 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++] =3D ip;
@@ -234,26 +236,45 @@
break;
}
=20
-# 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)
=20
/*--------------------- ppc32/64 ---------------------*/
=20
/* fp is %r1. ip is %cia. Note, ppc uses r1 as both the stack and
frame pointers. */
=20
-# if defined(VGP_ppc64_linux)
+# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
+ Word redir_stack_size =3D VEX_GUEST_PPC64_REDIR_STACK_SIZE;
+ Word redirs_used =3D 0;
+# elif defined(VGP_ppc32_aix5)
+ Word redir_stack_size =3D VEX_GUEST_PPC32_REDIR_STACK_SIZE;
+ Word redirs_used =3D 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 =3D=3D (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) =3D=3D (void*)&VG_(ppctoc_magic_redirect_return_=
stub)
&& VG_(is_valid_tid)(tid_if_known)) {
- Long hsp =3D VG_(threads)[tid_if_known].arch.vex.guest_REDIR_SP;
- if (hsp >=3D 1 && hsp < VEX_GUEST_PPC64_REDIR_STACK_SIZE)
+ Word hsp =3D VG_(threads)[tid_if_known].arch.vex.guest_REDIR_SP;
+ redirs_used++;
+ if (hsp >=3D 1 && hsp < redir_stack_size)
lr =3D VG_(threads)[tid_if_known]
.arch.vex.guest_REDIR_STACK[hsp-1];
}
# endif
=20
+ /* 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 =3D False;
{
# define M_VG_ERRTXT 1000
@@ -275,10 +296,11 @@
=20
while (True) {
=20
- /* 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 =3D 2;
# else
const Int lr_offset =3D 1;
@@ -297,19 +319,23 @@
else
ip =3D (((UWord*)fp)[lr_offset]);
=20
-# 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 =3D=3D 1=20
- && ip =3D=3D (Addr)&VG_(ppc64_linux_magic_redirect_retur=
n_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 =3D=3D (Addr)&VG_(ppctoc_magic_redirect_return_stub)
&& VG_(is_valid_tid)(tid_if_known)) {
- Long hsp =3D VG_(threads)[tid_if_known].arch.vex.guest_RE=
DIR_SP;
- if (hsp >=3D 1 && hsp < VEX_GUEST_PPC64_REDIR_STACK_SIZE)
+ Word hsp =3D VG_(threads)[tid_if_known].arch.vex.guest_RE=
DIR_SP;
+ hsp -=3D 2 * redirs_used;
+ redirs_used ++;
+ if (hsp >=3D 1 && hsp < redir_stack_size)
ip =3D VG_(threads)[tid_if_known]
.arch.vex.guest_REDIR_STACK[hsp-1];
}
|