|
From: <sv...@va...> - 2006-10-17 01:32:00
|
Author: sewardj
Date: 2006-10-17 02:31:58 +0100 (Tue, 17 Oct 2006)
New Revision: 6261
Log:
Merge r6123:
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:
trunk/coregrind/m_stacktrace.c
Modified: trunk/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
--- trunk/coregrind/m_stacktrace.c 2006-10-17 01:31:27 UTC (rev 6260)
+++ trunk/coregrind/m_stacktrace.c 2006-10-17 01:31:58 UTC (rev 6261)
@@ -60,9 +60,17 @@
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 =3D 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 =3D False;
+# endif
+# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5) \
+ || defined(VGP_ppc32_aix5)
+ Word redir_stack_size =3D 0;
+ Word redirs_used =3D 0;
+# endif
+
Bool debug =3D False;
Int i;
Addr fp_max;
@@ -154,7 +162,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;
@@ -235,26 +243,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)
+ redir_stack_size =3D VEX_GUEST_PPC64_REDIR_STACK_SIZE;
+ redirs_used =3D 0;
+# elif defined(VGP_ppc32_aix5)
+ redir_stack_size =3D VEX_GUEST_PPC32_REDIR_STACK_SIZE;
+ 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
@@ -276,10 +303,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;
@@ -298,19 +326,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];
}
|