On arm-linux, add r7 to the set of registers that the CFI unwinder

knows how to unwind.  This is important when unwinding Thumb code
the CFA is often stated as being at some offset from r7.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11377
This commit is contained in:
Julian Seward 2010-09-23 22:05:59 +00:00
parent 4953c95227
commit 0bb6f49531
10 changed files with 45 additions and 16 deletions

View File

@ -1944,10 +1944,10 @@ UWord evalCfiExpr ( XArray* exprs, Int ix,
case Creg_IA_SP: return eec->uregs->xsp;
case Creg_IA_BP: return eec->uregs->xbp;
# elif defined(VGA_arm)
case Creg_ARM_R13: return eec->uregs->r13;
case Creg_ARM_R12: return eec->uregs->r12;
case Creg_ARM_R15: return eec->uregs->r15;
case Creg_ARM_R14: return eec->uregs->r14;
case Creg_ARM_R13: return eec->uregs->r13;
case Creg_ARM_R12: return eec->uregs->r12;
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
# else
# error "Unsupported arch"
@ -2155,6 +2155,9 @@ static Addr compute_cfa ( D3UnwindRegs* uregs,
case CFIC_ARM_R11REL:
cfa = cfsi->cfa_off + uregs->r11;
break;
case CFIC_ARM_R7REL:
cfa = cfsi->cfa_off + uregs->r7;
break;
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
# else
# error "Unsupported arch"
@ -2221,7 +2224,7 @@ Addr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
For x86 and amd64, the unwound registers are: {E,R}IP,
{E,R}SP, {E,R}BP.
For arm, the unwound registers are: R11 R12 R13 R14 R15.
For arm, the unwound registers are: R7 R11 R12 R13 R14 R15.
*/
Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
Addr min_accessible,
@ -2310,6 +2313,7 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
COMPUTE(uregsPrev.r13, uregsHere->r13, cfsi->r13_how, cfsi->r13_off);
COMPUTE(uregsPrev.r12, uregsHere->r12, cfsi->r12_how, cfsi->r12_off);
COMPUTE(uregsPrev.r11, uregsHere->r11, cfsi->r11_how, cfsi->r11_off);
COMPUTE(uregsPrev.r7, uregsHere->r7, cfsi->r7_how, cfsi->r7_off);
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
# else
# error "Unknown arch"

View File

@ -130,15 +130,16 @@ typedef
CFIC_R13REL -> r13 + cfa_off
CFIC_R12REL -> r12 + cfa_off
CFIC_R11REL -> r11 + cfa_off
CFIC_R7REL -> r7 + cfa_off
CFIR_EXPR -> expr whose index is in cfa_off
old_r14/r13/r12/r11/ra
= case r14/r13/r12/r11/ra_how of
old_r14/r13/r12/r11/r7/ra
= case r14/r13/r12/r11/r7/ra_how of
CFIR_UNKNOWN -> we don't know, sorry
CFIR_SAME -> same as it was before (r14/r13/r12/r11 only)
CFIR_CFAREL -> cfa + r14/r13/r12/r11/ra_off
CFIR_MEMCFAREL -> *( cfa + r14/r13/r12/r11/ra_off )
CFIR_EXPR -> expr whose index is in r14/r13/r12/r11/ra_off
CFIR_SAME -> same as it was before (r14/r13/r12/r11/r7 only)
CFIR_CFAREL -> cfa + r14/r13/r12/r11/r7/ra_off
CFIR_MEMCFAREL -> *( cfa + r14/r13/r12/r11/r7/ra_off )
CFIR_EXPR -> expr whose index is in r14/r13/r12/r11/r7/ra_off
*/
#define CFIC_IA_SPREL ((UChar)1)
@ -147,7 +148,8 @@ typedef
#define CFIC_ARM_R13REL ((UChar)4)
#define CFIC_ARM_R12REL ((UChar)5)
#define CFIC_ARM_R11REL ((UChar)6)
#define CFIC_EXPR ((UChar)7) /* all targets */
#define CFIC_ARM_R7REL ((UChar)7)
#define CFIC_EXPR ((UChar)8) /* all targets */
#define CFIR_UNKNOWN ((UChar)64)
#define CFIR_SAME ((UChar)65)
@ -181,12 +183,14 @@ typedef
UChar r13_how; /* a CFIR_ value */
UChar r12_how; /* a CFIR_ value */
UChar r11_how; /* a CFIR_ value */
UChar r7_how; /* a CFIR_ value */
Int cfa_off;
Int ra_off;
Int r14_off;
Int r13_off;
Int r12_off;
Int r11_off;
Int r7_off;
}
DiCfSI;
#elif defined(VGA_ppc32) || defined(VGA_ppc64)

View File

@ -2059,6 +2059,7 @@ static void initUnwindContext ( /*OUT*/UnwindContext* ctx )
/* ctx->state[j].reg[13].tag = RR_Same; */
ctx->state[j].reg[14].tag = RR_Same;
ctx->state[j].reg[12].tag = RR_Same;
ctx->state[j].reg[7].tag = RR_Same;
/* this can't be right though: R12 (IP) isn't callee saved. */
# endif
}
@ -2163,6 +2164,11 @@ static Bool summarise_context( /*OUT*/DiCfSI* si,
si->cfa_how = CFIC_ARM_R11REL;
si->cfa_off = ctxs->cfa_off;
}
else
if (ctxs->cfa_is_regoff && ctxs->cfa_reg == 7/*??_REG*/) {
si->cfa_how = CFIC_ARM_R7REL;
si->cfa_off = ctxs->cfa_off;
}
# endif
else {
why = 1;
@ -2257,6 +2263,9 @@ static Bool summarise_context( /*OUT*/DiCfSI* si,
SUMMARISE_HOW(si->r11_how, si->r11_off,
ctxs->reg[11/*FP_REG*/] );
SUMMARISE_HOW(si->r7_how, si->r7_off,
ctxs->reg[7] );
if (ctxs->reg[14/*LR*/].tag == RR_Same
&& ctx->ra_reg == 14/*as we expect it always to be*/) {
/* Generate a trivial CfiExpr, which merely says "r14". First

View File

@ -141,6 +141,9 @@ void ML_(ppDiCfSI) ( XArray* /* of CfiExpr */ exprs, DiCfSI* si )
case CFIC_ARM_R11REL:
VG_(printf)("let cfa=oldR11+%d", si->cfa_off);
break;
case CFIC_ARM_R7REL:
VG_(printf)("let cfa=oldR7+%d", si->cfa_off);
break;
case CFIC_EXPR:
VG_(printf)("let cfa={");
ML_(ppCfiExpr)(exprs, si->cfa_off);
@ -166,6 +169,8 @@ void ML_(ppDiCfSI) ( XArray* /* of CfiExpr */ exprs, DiCfSI* si )
SHOW_HOW(si->r12_how, si->r12_off);
VG_(printf)(" R11=");
SHOW_HOW(si->r11_how, si->r11_off);
VG_(printf)(" R7=");
SHOW_HOW(si->r7_how, si->r7_off);
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
# else
# error "Unknown arch"

View File

@ -116,13 +116,14 @@
}
#elif defined(VGP_arm_linux)
# define GET_STARTREGS(srP) \
{ UInt block[5]; \
{ UInt block[6]; \
__asm__ __volatile__( \
"str r15, [%0, #+0];" \
"str r14, [%0, #+4];" \
"str r13, [%0, #+8];" \
"str r12, [%0, #+12];" \
"str r11, [%0, #+16];" \
"str r7, [%0, #+20];" \
: /* out */ \
: /* in */ "r"(&block[0]) \
: /* trash */ "memory" \
@ -132,6 +133,7 @@
(srP)->misc.ARM.r14 = block[2]; \
(srP)->misc.ARM.r12 = block[3]; \
(srP)->misc.ARM.r11 = block[4]; \
(srP)->misc.ARM.r7 = block[5]; \
}
#else
# error Unknown platform

View File

@ -92,6 +92,8 @@ void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs,
= VG_(threads)[tid].arch.vex.guest_R12;
regs->misc.ARM.r11
= VG_(threads)[tid].arch.vex.guest_R11;
regs->misc.ARM.r7
= VG_(threads)[tid].arch.vex.guest_R7;
# else
# error "Unknown arch"
# endif

View File

@ -378,6 +378,7 @@ typedef struct SigQueue {
(srP)->misc.ARM.r14 = (uc)->uc_mcontext.arm_lr; \
(srP)->misc.ARM.r12 = (uc)->uc_mcontext.arm_ip; \
(srP)->misc.ARM.r11 = (uc)->uc_mcontext.arm_fp; \
(srP)->misc.ARM.r7 = (uc)->uc_mcontext.arm_r7; \
}
#elif defined(VGP_ppc32_aix5)

View File

@ -593,11 +593,12 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
vg_assert(sizeof(Addr) == sizeof(void*));
D3UnwindRegs uregs;
uregs.r15 = startRegs->r_pc;
uregs.r15 = startRegs->r_pc & 0xFFFFFFFE;
uregs.r14 = startRegs->misc.ARM.r14;
uregs.r13 = startRegs->r_sp;
uregs.r12 = startRegs->misc.ARM.r12;
uregs.r11 = startRegs->misc.ARM.r11;
uregs.r7 = startRegs->misc.ARM.r7;
Addr fp_min = uregs.r13;
/* Snaffle IPs from the client's stack into ips[0 .. max_n_ips-1],
@ -612,7 +613,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
fp_max -= sizeof(Addr);
if (debug)
VG_(printf)("max_n_ips=%d fp_min=0x%lx fp_max_orig=0x%lx, "
VG_(printf)("\nmax_n_ips=%d fp_min=0x%lx fp_max_orig=0x%lx, "
"fp_max=0x%lx r15=0x%lx r13=0x%lx\n",
max_n_ips, fp_min, fp_max_orig, fp_max,
uregs.r15, uregs.r13);
@ -652,11 +653,11 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
if (VG_(use_CF_info)( &uregs, fp_min, fp_max )) {
if (sps) sps[i] = uregs.r13;
if (fps) fps[i] = 0;
ips[i++] = uregs.r15 -1;
ips[i++] = (uregs.r15 & 0xFFFFFFFE) - 1;
if (debug)
VG_(printf)("USING CFI: r15: 0x%lx, r13: 0x%lx\n",
uregs.r15, uregs.r13);
uregs.r15 = uregs.r15 - 1;
uregs.r15 = (uregs.r15 & 0xFFFFFFFE) - 1;
continue;
}
/* No luck. We have to give up. */

View File

@ -103,6 +103,7 @@ typedef
UInt r14;
UInt r12;
UInt r11;
UInt r7;
} ARM;
} misc;
}

View File

@ -117,7 +117,7 @@ typedef
D3UnwindRegs;
#elif defined(VGA_arm)
typedef
struct { Addr r15; Addr r14; Addr r13; Addr r12; Addr r11; }
struct { Addr r15; Addr r14; Addr r13; Addr r12; Addr r11; Addr r7; }
D3UnwindRegs;
#elif defined(VGA_ppc32) || defined(VGA_ppc64)
typedef