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;
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;
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
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;
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];
}