|
From: <sv...@va...> - 2010-01-01 19:55:33
|
Author: sewardj
Date: 2010-01-01 19:55:17 +0000 (Fri, 01 Jan 2010)
New Revision: 10987
Log:
Unbreak stack unwinding on x86-linux and amd64-linux following merge
of ARM CFI unwinding in r10986.
Modified:
trunk/coregrind/m_debuginfo/debuginfo.c
trunk/coregrind/m_debuginfo/readdwarf.c
trunk/coregrind/m_stacktrace.c
Modified: trunk/coregrind/m_debuginfo/debuginfo.c
===================================================================
--- trunk/coregrind/m_debuginfo/debuginfo.c 2010-01-01 18:46:41 UTC (rev 10986)
+++ trunk/coregrind/m_debuginfo/debuginfo.c 2010-01-01 19:55:17 UTC (rev 10987)
@@ -2217,8 +2217,8 @@
# if defined(VGA_x86) || defined(VGA_amd64)
COMPUTE(uregsPrev.xip, uregsHere->xip, cfsi->ra_how, cfsi->ra_off);
- COMPUTE(uregsPrev.xsp, uregsPrev->xsp, cfsi->sp_how, cfsi->sp_off);
- COMPUTE(uregsPrev.xbp, uregsPrev->xbp, cfsi->bp_how, cfsi->bp_off);
+ COMPUTE(uregsPrev.xsp, uregsHere->xsp, cfsi->sp_how, cfsi->sp_off);
+ COMPUTE(uregsPrev.xbp, uregsHere->xbp, cfsi->bp_how, cfsi->bp_off);
# elif defined(VGA_arm)
COMPUTE(uregsPrev.r15, uregsHere->r15, cfsi->ra_how, cfsi->ra_off);
COMPUTE(uregsPrev.r14, uregsHere->r14, cfsi->r14_how, cfsi->r14_off);
Modified: trunk/coregrind/m_debuginfo/readdwarf.c
===================================================================
--- trunk/coregrind/m_debuginfo/readdwarf.c 2010-01-01 18:46:41 UTC (rev 10986)
+++ trunk/coregrind/m_debuginfo/readdwarf.c 2010-01-01 19:55:17 UTC (rev 10987)
@@ -2175,10 +2175,9 @@
SUMMARISE_HOW(si->ra_how, si->ra_off,
ctxs->reg[ctx->ra_reg] );
- SUMMARISE_HOW(si->fp_how, si->fp_off,
+ SUMMARISE_HOW(si->bp_how, si->bp_off,
ctxs->reg[FP_REG] );
-
/* on x86/amd64, it seems the old %{e,r}sp value before the call is
always the same as the CFA. Therefore ... */
si->sp_how = CFIR_CFAREL;
@@ -2187,7 +2186,7 @@
/* also, gcc says "Undef" for %{e,r}bp when it is unchanged. So
.. */
if (ctxs->reg[FP_REG].tag == RR_Undef)
- si->fp_how = CFIR_SAME;
+ si->bp_how = CFIR_SAME;
/* knock out some obviously stupid cases */
if (si->ra_how == CFIR_SAME)
@@ -2319,11 +2318,11 @@
dwreg = src->Cex.DwReg.reg;
# if defined(VGA_x86) || defined(VGA_amd64)
if (dwreg == SP_REG)
- return ML_(CfiExpr_CfiReg)( dstxa, Creg_SP );
+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
if (dwreg == FP_REG)
- return ML_(CfiExpr_CfiReg)( dstxa, Creg_FP );
+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
if (dwreg == srcuc->ra_reg)
- return ML_(CfiExpr_CfiReg)( dstxa, Creg_IP ); /* correct? */
+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP ); /* correct? */
# elif defined(VGA_arm)
if (dwreg == SP_REG)
return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R13 );
Modified: trunk/coregrind/m_stacktrace.c
===================================================================
--- trunk/coregrind/m_stacktrace.c 2010-01-01 18:46:41 UTC (rev 10986)
+++ trunk/coregrind/m_stacktrace.c 2010-01-01 19:55:17 UTC (rev 10987)
@@ -79,10 +79,11 @@
vg_assert(sizeof(Addr) == sizeof(UWord));
vg_assert(sizeof(Addr) == sizeof(void*));
- Addr ip = (Addr)startRegs->r_pc;
- Addr sp = (Addr)startRegs->r_sp;
- Addr fp = startRegs->misc.X86.r_ebp;
- Addr fp_min = sp;
+ D3UnwindRegs uregs;
+ uregs.xip = (Addr)startRegs->r_pc;
+ uregs.xsp = (Addr)startRegs->r_sp;
+ uregs.xbp = startRegs->misc.X86.r_ebp;
+ Addr fp_min = uregs.xsp;
/* Snaffle IPs from the client's stack into ips[0 .. max_n_ips-1],
stopping when the trail goes cold, which we guess to be
@@ -98,7 +99,8 @@
if (debug)
VG_(printf)("max_n_ips=%d fp_min=0x%lx fp_max_orig=0x%lx, "
"fp_max=0x%lx ip=0x%lx fp=0x%lx\n",
- max_n_ips, fp_min, fp_max_orig, fp_max, ip, fp);
+ max_n_ips, fp_min, fp_max_orig, fp_max,
+ uregs.xip, uregs.xbp);
/* Assertion broken before main() is reached in pthreaded programs; the
* offending stack traces only have one item. --njn, 2002-aug-16 */
@@ -109,18 +111,18 @@
if (fp_min + 512 >= fp_max) {
/* If the stack limits look bogus, don't poke around ... but
don't bomb out either. */
- if (sps) sps[0] = sp;
- if (fps) fps[0] = fp;
- ips[0] = ip;
+ if (sps) sps[0] = uregs.xsp;
+ if (fps) fps[0] = uregs.xbp;
+ ips[0] = uregs.xip;
return 1;
}
# endif
/* fp is %ebp. sp is %esp. ip is %eip. */
- if (sps) sps[0] = sp;
- if (fps) fps[0] = fp;
- ips[0] = ip;
+ if (sps) sps[0] = uregs.xsp;
+ if (fps) fps[0] = uregs.xbp;
+ ips[0] = uregs.xip;
i = 1;
/* Loop unwinding the stack. Note that the IP value we get on
@@ -153,52 +155,55 @@
fails, and is expensive. */
/* Deal with frames resulting from functions which begin "pushl%
ebp ; movl %esp, %ebp" which is the ABI-mandated preamble. */
- if (fp_min <= fp &&
- fp <= fp_max - 1 * sizeof(UWord)/*see comment below*/)
+ if (fp_min <= uregs.xbp &&
+ uregs.xbp <= fp_max - 1 * sizeof(UWord)/*see comment below*/)
{
/* fp looks sane, so use it. */
- ip = (((UWord*)fp)[1]);
+ uregs.xip = (((UWord*)uregs.xbp)[1]);
// We stop if we hit a zero (the traditional end-of-stack
// marker) or a one -- these correspond to recorded IPs of 0 or -1.
// The latter because r8818 (in this file) changes the meaning of
// entries [1] and above in a stack trace, by subtracting 1 from
// them. Hence stacks that used to end with a zero value now end in
// -1 and so we must detect that too.
- if (0 == ip || 1 == ip) break;
- sp = fp + sizeof(Addr) /*saved %ebp*/
- + sizeof(Addr) /*ra*/;
- fp = (((UWord*)fp)[0]);
- if (sps) sps[i] = sp;
- if (fps) fps[i] = fp;
- ips[i++] = ip - 1; /* -1: refer to calling insn, not the RA */
+ if (0 == uregs.xip || 1 == uregs.xip) break;
+ uregs.xsp = uregs.xbp + sizeof(Addr) /*saved %ebp*/
+ + sizeof(Addr) /*ra*/;
+ uregs.xbp = (((UWord*)uregs.xbp)[0]);
+ if (sps) sps[i] = uregs.xsp;
+ if (fps) fps[i] = uregs.xbp;
+ ips[i++] = uregs.xip - 1; /* -1: refer to calling insn, not the RA */
if (debug)
VG_(printf)(" ipsF[%d]=0x%08lx\n", i-1, ips[i-1]);
- ip = ip - 1; /* as per comment at the head of this loop */
+ uregs.xip = uregs.xip - 1;
+ /* as per comment at the head of this loop */
continue;
}
/* 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 ) ) {
- if (0 == ip || 1 == ip) break;
- if (sps) sps[i] = sp;
- if (fps) fps[i] = fp;
- ips[i++] = ip - 1; /* -1: refer to calling insn, not the RA */
+ if ( VG_(use_CF_info)( &uregs, fp_min, fp_max ) ) {
+ if (0 == uregs.xip || 1 == uregs.xip) break;
+ if (sps) sps[i] = uregs.xsp;
+ if (fps) fps[i] = uregs.xbp;
+ ips[i++] = uregs.xip - 1; /* -1: refer to calling insn, not the RA */
if (debug)
VG_(printf)(" ipsC[%d]=0x%08lx\n", i-1, ips[i-1]);
- ip = ip - 1; /* as per comment at the head of this loop */
+ uregs.xip = uregs.xip - 1;
+ /* as per comment at the head of this loop */
continue;
}
/* And, similarly, try for MSVC FPO unwind info. */
- if ( VG_(use_FPO_info)( &ip, &sp, &fp, fp_min, fp_max ) ) {
- if (0 == ip || 1 == ip) break;
- if (sps) sps[i] = sp;
- if (fps) fps[i] = fp;
- ips[i++] = ip;
+ if ( VG_(use_FPO_info)( &uregs.xip, &uregs.xsp, &uregs.xbp,
+ fp_min, fp_max ) ) {
+ if (0 == uregs.xip || 1 == uregs.xip) break;
+ if (sps) sps[i] = uregs.xsp;
+ if (fps) fps[i] = uregs.xbp;
+ ips[i++] = uregs.xip;
if (debug)
VG_(printf)(" ipsC[%d]=0x%08lx\n", i-1, ips[i-1]);
- ip = ip - 1;
+ uregs.xip = uregs.xip - 1;
continue;
}
@@ -230,10 +235,11 @@
vg_assert(sizeof(Addr) == sizeof(UWord));
vg_assert(sizeof(Addr) == sizeof(void*));
- Addr ip = startRegs->r_pc;
- Addr sp = startRegs->r_sp;
- Addr fp = startRegs->misc.AMD64.r_rbp;
- Addr fp_min = sp;
+ D3UnwindRegs uregs;
+ uregs.xip = startRegs->r_pc;
+ uregs.xsp = startRegs->r_sp;
+ uregs.xbp = startRegs->misc.AMD64.r_rbp;
+ Addr fp_min = uregs.xsp;
/* Snaffle IPs from the client's stack into ips[0 .. max_n_ips-1],
stopping when the trail goes cold, which we guess to be
@@ -249,7 +255,8 @@
if (debug)
VG_(printf)("max_n_ips=%d fp_min=0x%lx fp_max_orig=0x%lx, "
"fp_max=0x%lx ip=0x%lx fp=0x%lx\n",
- max_n_ips, fp_min, fp_max_orig, fp_max, ip, fp);
+ max_n_ips, fp_min, fp_max_orig, fp_max,
+ uregs.xip, uregs.xbp);
/* Assertion broken before main() is reached in pthreaded programs; the
* offending stack traces only have one item. --njn, 2002-aug-16 */
@@ -260,18 +267,18 @@
if (fp_min + 512 >= fp_max) {
/* If the stack limits look bogus, don't poke around ... but
don't bomb out either. */
- if (sps) sps[0] = sp;
- if (fps) fps[0] = fp;
- ips[0] = ip;
+ if (sps) sps[0] = uregs.xsp;
+ if (fps) fps[0] = uregs.xbp;
+ ips[0] = uregs.xip;
return 1;
}
# endif
/* fp is %rbp. sp is %rsp. ip is %rip. */
- ips[0] = ip;
- if (sps) sps[0] = sp;
- if (fps) fps[0] = fp;
+ ips[0] = uregs.xip;
+ if (sps) sps[0] = uregs.xsp;
+ if (fps) fps[0] = uregs.xbp;
i = 1;
/* Loop unwinding the stack. Note that the IP value we get on
@@ -298,14 +305,14 @@
/* First off, see if there is any CFI info to hand which can
be used. */
- if ( VG_(use_CF_info)( &ip, &sp, &fp, fp_min, fp_max ) ) {
- if (0 == ip || 1 == ip) break;
- if (sps) sps[i] = sp;
- if (fps) fps[i] = fp;
- ips[i++] = ip - 1; /* -1: refer to calling insn, not the RA */
+ if ( VG_(use_CF_info)( &uregs, fp_min, fp_max ) ) {
+ if (0 == uregs.xip || 1 == uregs.xip) break;
+ if (sps) sps[i] = uregs.xsp;
+ if (fps) fps[i] = uregs.xbp;
+ ips[i++] = uregs.xip - 1; /* -1: refer to calling insn, not the RA */
if (debug)
VG_(printf)(" ipsC[%d]=%#08lx\n", i-1, ips[i-1]);
- ip = ip - 1; /* as per comment at the head of this loop */
+ uregs.xip = uregs.xip - 1; /* as per comment at the head of this loop */
continue;
}
@@ -321,19 +328,19 @@
fact that we are prodding at & ((UWord*)fp)[1] and so need to
adjust the limit check accordingly. Omitting this has been
observed to cause segfaults on rare occasions. */
- if (fp_min <= fp && fp <= fp_max - 1 * sizeof(UWord)) {
+ if (fp_min <= uregs.xbp && uregs.xbp <= fp_max - 1 * sizeof(UWord)) {
/* fp looks sane, so use it. */
- ip = (((UWord*)fp)[1]);
- if (0 == ip || 1 == ip) break;
- sp = fp + sizeof(Addr) /*saved %rbp*/
- + sizeof(Addr) /*ra*/;
- fp = (((UWord*)fp)[0]);
- if (sps) sps[i] = sp;
- if (fps) fps[i] = fp;
- ips[i++] = ip - 1; /* -1: refer to calling insn, not the RA */
+ uregs.xip = (((UWord*)uregs.xbp)[1]);
+ if (0 == uregs.xip || 1 == uregs.xip) break;
+ uregs.xsp = uregs.xbp + sizeof(Addr) /*saved %rbp*/
+ + sizeof(Addr) /*ra*/;
+ uregs.xbp = (((UWord*)uregs.xbp)[0]);
+ if (sps) sps[i] = uregs.xsp;
+ if (fps) fps[i] = uregs.xbp;
+ ips[i++] = uregs.xip - 1; /* -1: refer to calling insn, not the RA */
if (debug)
VG_(printf)(" ipsF[%d]=%#08lx\n", i-1, ips[i-1]);
- ip = ip - 1; /* as per comment at the head of this loop */
+ uregs.xip = uregs.xip - 1; /* as per comment at the head of this loop */
continue;
}
@@ -349,19 +356,20 @@
address; instead scan a likely section of stack (eg sp .. sp+256)
and use suitable values found there.
*/
- if (fp_min <= sp && sp < fp_max) {
- ip = ((UWord*)sp)[0];
- if (0 == ip || 1 == ip) break;
- if (sps) sps[i] = sp;
- if (fps) fps[i] = fp;
- ips[i++] = ip == 0
+ if (fp_min <= uregs.xsp && uregs.xsp < fp_max) {
+ uregs.xip = ((UWord*)uregs.xsp)[0];
+ if (0 == uregs.xip || 1 == uregs.xip) break;
+ if (sps) sps[i] = uregs.xsp;
+ if (fps) fps[i] = uregs.xbp;
+ ips[i++] = uregs.xip == 0
? 0 /* sp[0] == 0 ==> stuck at the bottom of a
thread stack */
- : ip - 1; /* -1: refer to calling insn, not the RA */
+ : uregs.xip - 1;
+ /* -1: refer to calling insn, not the RA */
if (debug)
VG_(printf)(" ipsH[%d]=%#08lx\n", i-1, ips[i-1]);
- ip = ip - 1; /* as per comment at the head of this loop */
- sp += 8;
+ uregs.xip = uregs.xip - 1; /* as per comment at the head of this loop */
+ uregs.xsp += 8;
continue;
}
|