Make VG_(get_StackTrace2) aware of bogus LR values in

replacement/wrapper functions on ppc64-linux, which otherwise mess up
the backtraces.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5549
This commit is contained in:
Julian Seward 2006-01-18 04:25:20 +00:00
parent a9bbc3690b
commit 8a98207bcf
4 changed files with 48 additions and 7 deletions

View File

@ -138,7 +138,8 @@ static void report_and_quit ( const Char* report,
stacktop = tst->os_state.valgrind_stack_init_SP;
VG_(get_StackTrace2)(ips, BACKTRACE_DEPTH, ip, sp, fp, lr, sp, stacktop);
VG_(get_StackTrace2)(0/*tid is unknown*/,
ips, BACKTRACE_DEPTH, ip, sp, fp, lr, sp, stacktop);
VG_(pp_StackTrace) (ips, BACKTRACE_DEPTH);
// Don't print this, as it's not terribly interesting and avoids a

View File

@ -48,8 +48,13 @@
IPs into 'ips'. In order to be thread-safe, we pass in the
thread's IP SP, FP if that's meaningful, and LR if that's
meaningful. Returns number of IPs put in 'ips'.
If you know what the thread ID for this stack is, send that as the
first parameter, else send zero. This helps generate better stack
traces on ppc64-linux and has no effect on other platforms.
*/
UInt VG_(get_StackTrace2) ( Addr* ips, UInt n_ips,
UInt VG_(get_StackTrace2) ( ThreadId tid_if_known,
Addr* ips, UInt n_ips,
Addr ip, Addr sp, Addr fp, Addr lr,
Addr fp_min, Addr fp_max_orig )
{
@ -230,7 +235,7 @@ UInt VG_(get_StackTrace2) ( Addr* ips, UInt n_ips,
# elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
/*--------------------- ppc32 ---------------------*/
/*--------------------- ppc32/64 ---------------------*/
/* fp is %r1. ip is %cia. Note, ppc uses r1 as both the stack and
frame pointers. */
@ -259,7 +264,11 @@ UInt VG_(get_StackTrace2) ( Addr* ips, UInt n_ips,
/* 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. */
const Int lr_offset = VG_WORDSIZE==8 ? 2 : 1;
# if defined(VGP_ppc64_linux)
const Int lr_offset = 2;
# else
const Int lr_offset = 1;
# endif
if (i >= n_ips)
break;
@ -274,6 +283,24 @@ UInt VG_(get_StackTrace2) ( Addr* ips, UInt n_ips,
else
ip = (((UWord*)fp)[lr_offset]);
# if defined(VGP_ppc64_linux)
/* 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)
&& 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)
ip = VG_(threads)[tid_if_known]
.arch.vex.guest_REDIR_STACK[hsp-1];
}
# endif
fp = (((UWord*)fp)[0]);
ips[i++] = ip;
if (debug)
@ -324,7 +351,8 @@ UInt VG_(get_StackTrace) ( ThreadId tid, StackTrace ips, UInt n_ips )
VG_(printf)("tid %d: stack_highest=%p ip=%p sp=%p fp=%p\n",
tid, stack_highest_word, ip, sp, fp);
return VG_(get_StackTrace2)(ips, n_ips, ip, sp, fp, lr, sp, stack_highest_word);
return VG_(get_StackTrace2)(tid, ips, n_ips, ip, sp, fp, lr, sp,
stack_highest_word);
}
static void printIpDesc(UInt n, Addr ip)

View File

@ -566,6 +566,8 @@ static Bool chase_into_ok ( void* closureV, Addr64 addr64 )
}
/* --------------- ppc64-linux specific helpers --------------- */
#if defined(VGP_ppc64_linux)
static IRExpr* mkU64 ( ULong n )
{
@ -681,6 +683,7 @@ Bool mk_preamble__ppc64_magic_return_stub ( void* closureV, IRBB* bb )
}
#endif
/* --------------- END ppc64-linux specific helpers --------------- */
/* This is an the IR preamble generators used for replacement
functions. It adds code to set the guest_NRADDR to zero
@ -692,7 +695,11 @@ Bool mk_preamble__ppc64_magic_return_stub ( void* closureV, IRBB* bb )
replacement function, and sets LR to point at the magic return-stub
address. Setting LR causes the return of the wrapped/redirected
function to lead to our magic return stub, which restores LR and R2
from said stack and returns for real. */
from said stack and returns for real.
VG_(get_StackTrace2) understands that the LR value may point to the
return stub address, and that in that case it can get the real LR
value from the hidden stack instead. */
static
Bool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRBB* bb )
{

View File

@ -39,7 +39,12 @@
#include "pub_tool_stacktrace.h"
// Variant that gives a little more control over the stack-walking.
extern UInt VG_(get_StackTrace2) ( StackTrace ips, UInt n_ips,
// If you know what the thread ID for this stack is, send that
// as the first parameter, else send zero. This helps generate
// better stack traces on ppc64-linux and has no effect on other
// platforms.
extern UInt VG_(get_StackTrace2) ( ThreadId tid_if_known,
StackTrace ips, UInt n_ips,
Addr ip, Addr sp, Addr fp, Addr lr,
Addr fp_min, Addr fp_max );