|
From: <sv...@va...> - 2005-08-19 16:03:03
|
Author: sewardj
Date: 2005-08-19 17:02:59 +0100 (Fri, 19 Aug 2005)
New Revision: 4464
Log:
Incorporate a patch from Craig Chaney which gives better stack
snapshots on ppc32-linux in the presence of functions subject to
leaf-function optimisations.
At the same time, simplify the stack unwinding logic by basically
implementing it separately for each target. Having a single piece of
logic for amd64 and x86 was tenable, but merging ppc32 into it is too
confusing. So now there is an x86/amd64 unwinder and a ppc32
unwinder.
This requires plumbing a link-register value into
VG_(get_StackTrace2), and that in turn requires passing it around
several other stack-trace-related functions. Hence 7 changed files.
Modified:
trunk/coregrind/m_libcassert.c
trunk/coregrind/m_machine.c
trunk/coregrind/m_signals.c
trunk/coregrind/m_stacktrace.c
trunk/coregrind/pub_core_libcassert.h
trunk/coregrind/pub_core_stacktrace.h
trunk/include/pub_tool_machine.h
Modified: trunk/coregrind/m_libcassert.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_libcassert.c 2005-08-19 10:07:29 UTC (rev 4463)
+++ trunk/coregrind/m_libcassert.c 2005-08-19 16:02:59 UTC (rev 4464)
@@ -94,7 +94,8 @@
}
=20
__attribute__ ((noreturn))
-static void report_and_quit ( const Char* report, Addr ip, Addr sp, Addr=
fp )
+static void report_and_quit ( const Char* report,=20
+ Addr ip, Addr sp, Addr fp, Addr lr )
{
Addr stacktop;
Addr ips[BACKTRACE_DEPTH];
@@ -111,7 +112,7 @@
stacktop =3D tst->os_state.valgrind_stack_base +=20
tst->os_state.valgrind_stack_szB;
=20
- VG_(get_StackTrace2)(ips, BACKTRACE_DEPTH, ip, sp, fp, sp, stacktop);
+ VG_(get_StackTrace2)(ips, BACKTRACE_DEPTH, ip, sp, fp, lr, sp, stackt=
op);
VG_(pp_StackTrace) (ips, BACKTRACE_DEPTH);
=20
// Don't print this, as it's not terribly interesting and avoids a
@@ -166,30 +167,30 @@
if (!VG_STREQ(buf, ""))
VG_(printf)("%s: %s\n", component, buf );
=20
- report_and_quit(bugs_to, 0,0,0);
+ report_and_quit(bugs_to, 0,0,0,0);
}
=20
__attribute__ ((noreturn))
static void panic ( Char* name, Char* report, Char* str,
- Addr ip, Addr sp, Addr fp )
+ Addr ip, Addr sp, Addr fp, Addr lr )
{
VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
- report_and_quit(report, ip, sp, fp);
+ report_and_quit(report, ip, sp, fp, lr);
}
=20
-void VG_(core_panic_at) ( Char* str, Addr ip, Addr sp, Addr fp )
+void VG_(core_panic_at) ( Char* str, Addr ip, Addr sp, Addr fp, Addr lr =
)
{
- panic("valgrind", VG_BUGS_TO, str, ip, sp, fp);
+ panic("valgrind", VG_BUGS_TO, str, ip, sp, fp, lr);
}
=20
void VG_(core_panic) ( Char* str )
{
- VG_(core_panic_at)(str, 0,0,0);
+ VG_(core_panic_at)(str, 0,0,0,0);
}
=20
void VG_(tool_panic) ( Char* str )
{
- panic(VG_(details).name, VG_(details).bug_reports_to, str, 0,0,0);
+ panic(VG_(details).name, VG_(details).bug_reports_to, str, 0,0,0,0);
}
=20
/* Print some helpful-ish text about unimplemented things, and give up. =
*/
Modified: trunk/coregrind/m_machine.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_machine.c 2005-08-19 10:07:29 UTC (rev 4463)
+++ trunk/coregrind/m_machine.c 2005-08-19 16:02:59 UTC (rev 4464)
@@ -53,6 +53,17 @@
return FRAME_PTR( VG_(threads)[tid].arch );
}
=20
+Addr VG_(get_LR) ( ThreadId tid )
+{
+# if defined(VGA_ppc32)
+ return VG_(threads)[tid].arch.vex.guest_LR;
+# elif defined(VGA_x86) || defined(VGA_amd64)
+ return 0;
+# else
+# error "Unknown arch"
+# endif
+}
+
void VG_(set_SP) ( ThreadId tid, Addr sp )
{
STACK_PTR( VG_(threads)[tid].arch ) =3D sp;
Modified: trunk/coregrind/m_signals.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_signals.c 2005-08-19 10:07:29 UTC (rev 4463)
+++ trunk/coregrind/m_signals.c 2005-08-19 16:02:59 UTC (rev 4464)
@@ -134,28 +134,31 @@
# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.esp)
# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.ebp)
# define VG_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.eax)
-# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \
+# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \
/* Convert the value in uc_mcontext.eax into a SysRes. */ \
VG_(mk_SysRes_x86_linux)( (uc)->uc_mcontext.eax )
+# define VG_UCONTEXT_LINK_REG(uc) 0 /* Dude, where's my LR? */
=20
#elif defined(VGP_amd64_linux)
# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.rip)
# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.rsp)
# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.rbp)
# define VG_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.rax)
-# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \
+# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \
/* Convert the value in uc_mcontext.rax into a SysRes. */ \
VG_(mk_SysRes_amd64_linux)( (uc)->uc_mcontext.rax )
+# define VG_UCONTEXT_LINK_REG(uc) 0 /* No LR on amd64 either */
=20
#elif defined(VGP_ppc32_linux)
# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.mc_gregs[VK=
I_PT_NIP])
# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.mc_gregs[1]=
)
# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.mc_gregs[1]=
)
# define VG_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.mc_gregs[0]=
)
-# define VG_UCONTEXT_SYSCALL_SYSRES(uc) =
\
+# define VG_UCONTEXT_SYSCALL_SYSRES(uc) =
\
/* Convert the values in uc_mcontext r3,cr into a SysRes. */ =
\
VG_(mk_SysRes_ppc32_linux)( (uc)->uc_mcontext.mc_gregs[3], =
\
(uc)->uc_mcontext.mc_gregs[VKI_PT_CCR] )
+# define VG_UCONTEXT_LINK_REG(uc) ((uc)->uc_mcontext.mc_gregs[VK=
I_PT_LNK])=20
=20
#else
# error Unknown platform
@@ -1966,7 +1969,8 @@
VG_(core_panic_at)("Killed by fatal signal",
VG_UCONTEXT_INSTR_PTR(uc),
VG_UCONTEXT_STACK_PTR(uc),
- VG_UCONTEXT_FRAME_PTR(uc));
+ VG_UCONTEXT_FRAME_PTR(uc),
+ VG_UCONTEXT_LINK_REG(uc));
}
}
=20
Modified: trunk/coregrind/m_stacktrace.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_stacktrace.c 2005-08-19 10:07:29 UTC (rev 4463)
+++ trunk/coregrind/m_stacktrace.c 2005-08-19 16:02:59 UTC (rev 4464)
@@ -62,30 +62,33 @@
# error Unknown platform
#endif
=20
-/* Take a snapshot of the client's stack, putting the up to 'n_ips' IPs=20
- into 'ips'. In order to be thread-safe, we pass in the thread's IP
- and FP. Returns number of IPs put in 'ips'. */
+/* Take a snapshot of the client's stack, putting the up to 'n_ips'
+ 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'.
+*/
UInt VG_(get_StackTrace2) ( Addr* ips, UInt n_ips,=20
- Addr ip, Addr sp, Addr fp,
+ Addr ip, Addr sp, Addr fp, Addr lr,
Addr fp_min, Addr fp_max_orig )
{
- static const Bool debug =3D False;
- Int i;
- Addr fp_max;
- UInt n_found =3D 0;
+ Bool lr_is_first_RA =3D False; /* ppc only */
+ Bool debug =3D False;
+ Int i;
+ Addr fp_max;
+ UInt n_found =3D 0;
=20
VGP_PUSHCC(VgpExeContext);
=20
- /* First snaffle IPs from the client's stack into ips[0 .. n_ips-1],=20
- putting zeroes in when the trail goes cold, which we guess to be w=
hen
- FP is not a reasonable stack location. We also assert that FP
- increases down the chain. */
+ vg_assert(sizeof(Addr) =3D=3D sizeof(UWord));
+ vg_assert(sizeof(Addr) =3D=3D sizeof(void*));
=20
- // Gives shorter stack trace for tests/badjump.c
- // JRS 2002-aug-16: I don't think this is a big deal; looks ok for
- // most "normal" backtraces.
- // NJN 2002-sep-05: traces for pthreaded programs are particularly ba=
d.
+ /* Snaffle IPs from the client's stack into ips[0 .. n_ips-1],
+ putting zeroes in when the trail goes cold, which we guess to be
+ when FP is not a reasonable stack location. */
=20
+ for (i =3D 0; i < n_ips; i++)
+ ips[i] =3D 0;
+
// JRS 2002-sep-17: hack, to round up fp_max to the end of the
// current page, at least. Dunno if it helps.
// NJN 2002-sep-17: seems to -- stack traces look like 1.0.X again
@@ -100,68 +103,124 @@
* offending stack traces only have one item. --njn, 2002-aug-16 */
/* vg_assert(fp_min <=3D fp_max);*/
=20
- ips[0] =3D ip;
- i =3D 1;
-
if (fp_min + VG_(clo_max_stackframe) <=3D fp_max) {
/* If the stack is ridiculously big, don't poke around ... but
don't bomb out either. Needed to make John Regehr's
user-space threads package work. JRS 20021001 */
- } else {
+ ips[0] =3D ip;
+ VGP_POPCC(VgpExeContext);
+ return 1;
+ }=20
=20
- fp =3D FIRST_STACK_FRAME(fp);
+ /* Otherwise unwind the stack in a platform-specific way. Trying
+ to merge the x86, amd64 and ppc32 logic into a single piece of
+ code is just too confusing. */
=20
- while (True) {
+ /*--------------------- x86 and amd64 ---------------------*/
=20
- if (i >=3D n_ips)
- break;
+# if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
=20
- /* Try to derive a new (ip,sp,fp) triple from the current
- set. */
+ /* fp is %ebp/%rbp. sp is %esp/%rsp. ip is %eip/%rip. */
=20
- /* First off, see if there is any CFI info to hand which can
- be used. */
- if ( VG_(use_CFI_info)( &ip, &sp, &fp, fp_min, fp_max ) ) {
- ips[i++] =3D ip;
- if (debug)
- VG_(printf)(" ipsC[%d]=3D%08p\n", i-1, ips[i-1]);
- continue;
- }
+ ips[0] =3D ip;
+ i =3D 1;
=20
- /* If VG_(use_CFI_info) fails, it won't modify ip/sp/fp, so
- we can safely try the old-fashioned method. */
- /* This bit is supposed to deal with frames resulting from
- functions which begin "pushl% ebp ; movl %esp, %ebp" (x86)
- or "pushq %rbp ; movq %rsp, %rbp" (amd64). Unfortunately,
- since we can't (easily) look at the insns at the start of
- the fn, like GDB does, there's no reliable way to tell.
- Hence the hack of first trying out CFI, and if that fails,
- then use this as a fallback. */
- if (fp_min <=3D fp && fp <=3D fp_max) {
- /* fp looks sane, so use it. */
- ip =3D STACK_FRAME_RET(fp);
- sp =3D fp + sizeof(Addr) /*saved %ebp/%rbp*/=20
- + sizeof(Addr) /*ra*/;
- fp =3D STACK_FRAME_NEXT(fp);
- ips[i++] =3D ip;
- if (debug)
- VG_(printf)(" ipsF[%d]=3D%08p\n", i-1, ips[i-1]);
- continue;
- }
+ while (True) {
=20
- /* No luck there. We have to give up. */
+ if (i >=3D n_ips)
break;
+
+ /* Try to derive a new (ip,sp,fp) triple from the current
+ set. */
+
+ /* First off, see if there is any CFI info to hand which can
+ be used. */
+ if ( VG_(use_CFI_info)( &ip, &sp, &fp, fp_min, fp_max ) ) {
+ ips[i++] =3D ip;
+ if (debug)
+ VG_(printf)(" ipsC[%d]=3D%08p\n", i-1, ips[i-1]);
+ continue;
}
=20
+ /* If VG_(use_CFI_info) fails, it won't modify ip/sp/fp, so
+ we can safely try the old-fashioned method. */
+ /* This bit is supposed to deal with frames resulting from
+ functions which begin "pushl% ebp ; movl %esp, %ebp" (x86)
+ or "pushq %rbp ; movq %rsp, %rbp" (amd64). Unfortunately,
+ since we can't (easily) look at the insns at the start of
+ the fn, like GDB does, there's no reliable way to tell.
+ Hence the hack of first trying out CFI, and if that fails,
+ then use this as a fallback. */
+ if (fp_min <=3D fp && fp <=3D fp_max) {
+ /* fp looks sane, so use it. */
+ ip =3D (((UWord*)fp)[1]);
+ sp =3D fp + sizeof(Addr) /*saved %ebp/%rbp*/=20
+ + sizeof(Addr) /*ra*/;
+ fp =3D (((UWord*)fp)[0]);
+ ips[i++] =3D ip;
+ if (debug)
+ VG_(printf)(" ipsF[%d]=3D%08p\n", i-1, ips[i-1]);
+ continue;
+ }
+
+ /* No luck there. We have to give up. */
+ break;
}
- n_found =3D i;
=20
- /* Put zeroes in the rest. */
- for (; i < n_ips; i++) {
- ips[i] =3D 0;
+ /*--------------------- ppc32 ---------------------*/
+
+# elif defined(VGP_ppc32_linux)
+
+ /* fp is %r1. ip is %cia. Note, ppc uses r1 as both the stack and
+ frame pointers. */
+
+ lr_is_first_RA =3D False;
+ {
+# define M_VG_ERRTXT 1000
+ UChar buf_lr[M_VG_ERRTXT], buf_ip[M_VG_ERRTXT];
+ if (VG_(get_fnname_nodemangle) (lr, buf_lr, M_VG_ERRTXT))
+ if (VG_(get_fnname_nodemangle) (ip, buf_ip, M_VG_ERRTXT))
+ if (VG_(strncmp)(buf_lr, buf_ip, M_VG_ERRTXT))
+ lr_is_first_RA =3D True;
+# undef M_VG_ERRTXT
}
+
+ ips[0] =3D ip;
+ i =3D 1;
+ fp =3D (((UWord*)fp)[0]);
+
+ while (True) {
+
+ if (i >=3D n_ips)
+ break;
+
+ /* Try to derive a new (ip,fp) pair from the current set. */
+
+ if (fp_min <=3D fp && fp <=3D fp_max) {
+ /* fp looks sane, so use it. */
+
+ if (i =3D=3D 1 && lr_is_first_RA)
+ ip =3D lr;
+ else
+ ip =3D (((UWord*)fp)[1]);
+
+ fp =3D (((UWord*)fp)[0]);
+ ips[i++] =3D ip;
+ if (debug)
+ VG_(printf)(" ipsF[%d]=3D%08p\n", i-1, ips[i-1]);
+ continue;
+ }
+
+ /* No luck there. We have to give up. */
+ break;
+ }
+
+# else
+# error "Unknown platform"
+# endif
+
+ n_found =3D i;
VGP_POPCC(VgpExeContext);
-
return n_found;
}
=20
@@ -171,6 +230,7 @@
Addr ip =3D VG_(get_IP)(tid);
Addr fp =3D VG_(get_FP)(tid);
Addr sp =3D VG_(get_SP)(tid);
+ Addr lr =3D VG_(get_LR)(tid);
Addr stack_highest_word =3D VG_(threads)[tid].client_stack_highest_wo=
rd;
=20
# if defined(VGP_x86_linux)
@@ -194,7 +254,7 @@
VG_(printf)("tid %d: stack_highest=3D%p ip=3D%p sp=3D%p fp=3D%p\n"=
,
tid, stack_highest_word, ip, sp, fp);
=20
- return VG_(get_StackTrace2)(ips, n_ips, ip, sp, fp, sp, stack_highest=
_word);
+ return VG_(get_StackTrace2)(ips, n_ips, ip, sp, fp, lr, sp, stack_hig=
hest_word);
}
=20
static void printIpDesc(UInt n, Addr ip)
Modified: trunk/coregrind/pub_core_libcassert.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/pub_core_libcassert.h 2005-08-19 10:07:29 UTC (rev 44=
63)
+++ trunk/coregrind/pub_core_libcassert.h 2005-08-19 16:02:59 UTC (rev 44=
64)
@@ -63,7 +63,8 @@
__attribute__ ((__noreturn__))
extern void VG_(core_panic) ( Char* str );
__attribute__ ((__noreturn__))
-extern void VG_(core_panic_at) ( Char* str, Addr ip, Addr sp, Addr fp=
);
+extern void VG_(core_panic_at) ( Char* str,=20
+ Addr ip, Addr sp, Addr fp, Addr lr )=
;
=20
/* Called when some unhandleable client behaviour is detected.
Prints a msg and aborts. */
Modified: trunk/coregrind/pub_core_stacktrace.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/pub_core_stacktrace.h 2005-08-19 10:07:29 UTC (rev 44=
63)
+++ trunk/coregrind/pub_core_stacktrace.h 2005-08-19 16:02:59 UTC (rev 44=
64)
@@ -40,7 +40,7 @@
=20
// Variant that gives a little more control over the stack-walking.
extern UInt VG_(get_StackTrace2) ( StackTrace ips, UInt n_ips,=20
- Addr ip, Addr sp, Addr fp,=20
+ Addr ip, Addr sp, Addr fp, Addr lr,
Addr fp_min, Addr fp_max );
=20
#endif // __PUB_CORE_STACKTRACE_H
Modified: trunk/include/pub_tool_machine.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/include/pub_tool_machine.h 2005-08-19 10:07:29 UTC (rev 4463)
+++ trunk/include/pub_tool_machine.h 2005-08-19 16:02:59 UTC (rev 4464)
@@ -53,6 +53,7 @@
extern Addr VG_(get_SP) ( ThreadId tid );
extern Addr VG_(get_IP) ( ThreadId tid );
extern Addr VG_(get_FP) ( ThreadId tid );
+extern Addr VG_(get_LR) ( ThreadId tid );
=20
extern void VG_(set_SP) ( ThreadId tid, Addr sp );
extern void VG_(set_IP) ( ThreadId tid, Addr ip );
|