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
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 )
{
# 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. */
/* 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;
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)
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)
}
+/* --------------- ppc64-linux specific helpers --------------- */
+
#if defined(VGP_ppc64_linux)
static IRExpr* mkU64 ( ULong n )
{
}
#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
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 )
{
#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 );