From: Julian Seward Date: Thu, 23 Sep 2010 22:05:59 +0000 (+0000) Subject: On arm-linux, add r7 to the set of registers that the CFI unwinder X-Git-Tag: svn/VALGRIND_3_6_0~80 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0bb6f49531d6bd46abc0a2c1a7e1689ae186456f;p=thirdparty%2Fvalgrind.git 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 --- diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c index 25f5615e7f..6133fea1fd 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -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" diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h index b269825166..e272529609 100644 --- a/coregrind/m_debuginfo/priv_storage.h +++ b/coregrind/m_debuginfo/priv_storage.h @@ -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) diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c index 3d16d5e37a..d637a759fc 100644 --- a/coregrind/m_debuginfo/readdwarf.c +++ b/coregrind/m_debuginfo/readdwarf.c @@ -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 diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c index 8046f1eacc..52aec79376 100644 --- a/coregrind/m_debuginfo/storage.c +++ b/coregrind/m_debuginfo/storage.c @@ -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" diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c index 4a1b765842..731864ff26 100644 --- a/coregrind/m_libcassert.c +++ b/coregrind/m_libcassert.c @@ -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 diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c index 5f3bc927b9..8dc3e17dbe 100644 --- a/coregrind/m_machine.c +++ b/coregrind/m_machine.c @@ -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 diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c index 76c05df2c6..a3b7690a58 100644 --- a/coregrind/m_signals.c +++ b/coregrind/m_signals.c @@ -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) diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c index ad86b79d94..4896a9a1e1 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -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. */ diff --git a/coregrind/pub_core_basics.h b/coregrind/pub_core_basics.h index fdfd733f6f..35aba2f2ba 100644 --- a/coregrind/pub_core_basics.h +++ b/coregrind/pub_core_basics.h @@ -103,6 +103,7 @@ typedef UInt r14; UInt r12; UInt r11; + UInt r7; } ARM; } misc; } diff --git a/coregrind/pub_core_debuginfo.h b/coregrind/pub_core_debuginfo.h index 48ac9aa9c3..facca244d3 100644 --- a/coregrind/pub_core_debuginfo.h +++ b/coregrind/pub_core_debuginfo.h @@ -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