From d400dcac5e66047f86291d1a4b90fffb6327dc43 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Tue, 20 Aug 2013 15:01:59 -0500 Subject: PowerPC: fix backtrace to handle signal trampolines This patch fixes backtrace for PPC32 and PPC64 to correctly handle signal trampolines. The 'debug/tst-backtrace6.c' also check for SA_SIGINFO handling, where is triggers another vDSO symbols for PPC32. --- sysdeps/powerpc/powerpc64/backtrace.c | 36 ++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'sysdeps/powerpc/powerpc64/backtrace.c') diff --git a/sysdeps/powerpc/powerpc64/backtrace.c b/sysdeps/powerpc/powerpc64/backtrace.c index 2d3e051cb9..9b9a9f19da 100644 --- a/sysdeps/powerpc/powerpc64/backtrace.c +++ b/sysdeps/powerpc/powerpc64/backtrace.c @@ -18,6 +18,9 @@ #include #include +#include +#include +#include /* This is the stack layout we see with every stack frame. Note that every routine is required by the ABI to lay out the stack @@ -38,6 +41,27 @@ struct layout void *return_address; }; +/* Since the signal handler is just like any other function it needs to + save/restore its LR and it will save it into callers stack frame. + Since a signal handler doesn't have a caller, the kernel creates a + dummy frame to make it look like it has a caller. */ +struct signal_frame_64 { +#define SIGNAL_FRAMESIZE 128 + char dummy[SIGNAL_FRAMESIZE]; + struct ucontext uc; + /* We don't care about the rest, since the IP value is at 'uc' field. */ +}; + +static inline int +is_sigtramp_address (unsigned long nip) +{ +#ifdef SHARED + if (nip == (unsigned long)__vdso_sigtramp_rt64) + return 1; +#endif + return 0; +} + int __backtrace (void **array, int size) { @@ -53,7 +77,17 @@ __backtrace (void **array, int size) for ( count = 0; current != NULL && count < size; current = current->next, count++) - array[count] = current->return_address; + { + array[count] = current->return_address; + + /* Check if the symbol is the signal trampoline and get the interrupted + * symbol address from the trampoline saved area. */ + if (is_sigtramp_address ((unsigned long)current->return_address)) + { + struct signal_frame_64 *sigframe = (struct signal_frame_64*) current; + array[++count] = (void*)sigframe->uc.uc_mcontext.gp_regs[PT_NIP]; + } + } /* It's possible the second-last stack frame can't return (that is, it's __libc_start_main), in which case -- cgit 1.4.1