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.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6261
This commit is contained in:
Julian Seward 2006-10-17 01:31:58 +00:00
parent 11f205dc50
commit fa62ba20cb

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