From ef0067c5bc73bd934bbf9ae9185cfa319a1076b7 Mon Sep 17 00:00:00 2001 From: Philippe Waroquiers Date: Thu, 4 Jun 2015 19:44:47 +0000 Subject: [PATCH] On platforms that have an accessible redzone below the SP, the unwind logic should be able to access the redzone. So, when computing fp_min, substract the redzone. Currently, only amd64 and ppc64 have a non 0 redzone. Regtested on amd64 and ppc64le, no regression. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15309 --- coregrind/m_stacktrace.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c index d720eb3ecd..1299bb4383 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -75,7 +75,20 @@ } \ } - +/* Note about calculation of fp_min : fp_min is the lowest address + which can be accessed during unwinding. This is SP - VG_STACK_REDZONE_SZB. + On most platforms, this will be equal to SP (as VG_STACK_REDZONE_SZB + is 0). However, on some platforms (e.g. amd64), there is an accessible + redzone below the SP. Some CFI unwind info are generated, taking this + into account. As an example, the following is a CFI unwind info on + amd64 found for a 'retq' instruction: +[0x400f7e .. 0x400f7e]: let cfa=oldSP+8 in RA=*(cfa+-8) SP=cfa+0 BP=*(cfa+-16) + 0x400f7e: retq + As you can see, the previous BP is found 16 bytes below the cfa, which + is the oldSP+8. So, effectively, the BP is found 8 bytes below the SP. + The fp_min must take this into account, otherwise, VG_(use_CF_info) will + not unwind the BP. */ + /* ------------------------ x86 ------------------------- */ #if defined(VGP_x86_linux) || defined(VGP_x86_darwin) @@ -196,7 +209,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, uregs.xip = (Addr)startRegs->r_pc; uregs.xsp = (Addr)startRegs->r_sp; uregs.xbp = startRegs->misc.X86.r_ebp; - Addr fp_min = uregs.xsp; + Addr fp_min = uregs.xsp - VG_STACK_REDZONE_SZB; /* 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 @@ -479,7 +492,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, uregs.xip = startRegs->r_pc; uregs.xsp = startRegs->r_sp; uregs.xbp = startRegs->misc.AMD64.r_rbp; - Addr fp_min = uregs.xsp; + Addr fp_min = uregs.xsp - VG_STACK_REDZONE_SZB; /* 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 @@ -682,7 +695,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) Addr lr = startRegs->misc.PPC64.r_lr; # endif - Addr fp_min = sp; + Addr fp_min = sp - VG_STACK_REDZONE_SZB; /* 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 @@ -947,7 +960,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, uregs.r12 = startRegs->misc.ARM.r12; uregs.r11 = startRegs->misc.ARM.r11; uregs.r7 = startRegs->misc.ARM.r7; - Addr fp_min = uregs.r13; + Addr fp_min = uregs.r13 - VG_STACK_REDZONE_SZB; /* 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 @@ -1091,7 +1104,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, uregs.sp = startRegs->r_sp; uregs.x30 = startRegs->misc.ARM64.x30; uregs.x29 = startRegs->misc.ARM64.x29; - Addr fp_min = uregs.sp; + Addr fp_min = uregs.sp - VG_STACK_REDZONE_SZB; /* 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 @@ -1185,7 +1198,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, D3UnwindRegs uregs; uregs.ia = startRegs->r_pc; uregs.sp = startRegs->r_sp; - Addr fp_min = uregs.sp; + Addr fp_min = uregs.sp - VG_STACK_REDZONE_SZB; uregs.fp = startRegs->misc.S390X.r_fp; uregs.lr = startRegs->misc.S390X.r_lr; @@ -1268,7 +1281,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, D3UnwindRegs uregs; uregs.pc = startRegs->r_pc; uregs.sp = startRegs->r_sp; - Addr fp_min = uregs.sp; + Addr fp_min = uregs.sp - VG_STACK_REDZONE_SZB; #if defined(VGP_mips32_linux) uregs.fp = startRegs->misc.MIPS32.r30; @@ -1423,7 +1436,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, D3UnwindRegs uregs; uregs.pc = startRegs->r_pc; uregs.sp = startRegs->r_sp; - Addr fp_min = uregs.sp; + Addr fp_min = uregs.sp - VG_STACK_REDZONE_SZB; uregs.fp = startRegs->misc.TILEGX.r52; uregs.lr = startRegs->misc.TILEGX.r55; -- 2.47.2