aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorYao Qi <yao@codesourcery.com>2014-07-02 15:16:26 +0800
committerYao Qi <yao@codesourcery.com>2014-07-11 21:34:01 +0800
commit808f7ab1fc88da40007c17a20e49928359f27491 (patch)
tree58ec46b185bb93fb65d98aafe3205943d3ee46c3 /gdb
parent540314bdd87c7478d21b44dd4856d937bcc1479b (diff)
downloadgdb-808f7ab1fc88da40007c17a20e49928359f27491.zip
gdb-808f7ab1fc88da40007c17a20e49928359f27491.tar.gz
gdb-808f7ab1fc88da40007c17a20e49928359f27491.tar.bz2
Stop prologue analysis when past the epilogue
We see a fail in gdb.trace/entry-values.exp on armv4t thumb, bt^M #0 0x000086fc in foo (i=0, i@entry=<optimized out>, j=2, j@entry=<optimized out>)^M #1 0x00000002 in ?? ()^M Backtrace stopped: previous frame identical to this frame (corrupt stack?)^M (gdb) FAIL: gdb.trace/entry-values.exp: bt (1) (pattern 1) The fail is caused by incorrect prologue analysis, which can be illustrated by setting a breakpoint on function foo, (gdb) disassemble foo Dump of assembler code for function foo: 0x000086e8 <+0>: push {r7, lr} 0x000086ea <+2>: sub sp, #8 0x000086ec <+4>: add r7, sp, #0 0x000086ee <+6>: str r0, [r7, #4] 0x000086f0 <+8>: str r1, [r7, #0] 0x000086f2 <+10>: movs r3, #0 0x000086f4 <+12>: adds r0, r3, #0 0x000086f6 <+14>: mov sp, r7 0x000086f8 <+16>: add sp, #8 0x000086fa <+18>: pop {r7} 0x000086fc <+20>: pop {r1} 0x000086fe <+22>: bx r1 End of assembler dump. (gdb) b foo Breakpoint 1 at 0x86fc As we can see, GDB analyzes the prologue and skip the prologue to the last instruction but one. The breakpoint is set within the epilogue, and GDB skips too many instruction for prologue. This patch teaches GDB to stop prologue analysis when goes into the epilogue. With this patch applied, GDB is able to unwind correctly, (gdb) bt #0 0x000086f6 in foo (i=0, i@entry=2, j=2, j@entry=3) #1 0x00008718 in bar (i=<optimized out>) #2 0x00008758 in main () gdb: 2014-07-11 Yao Qi <yao@codesourcery.com> * arm-tdep.c (thumb_analyze_prologue): Break the loop if thumb_instruction_restores_sp return true.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog5
-rw-r--r--gdb/arm-tdep.c5
2 files changed, 10 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 7bc1d03..1ccacd3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
2014-07-11 Yao Qi <yao@codesourcery.com>
+ * arm-tdep.c (thumb_analyze_prologue): Break the loop if
+ thumb_instruction_restores_sp return true.
+
+2014-07-11 Yao Qi <yao@codesourcery.com>
+
* arm-tdep.c (thumb_instruction_restores_sp): New function.
(thumb_in_function_epilogue_p): Call
thumb_instruction_restores_sp.
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 0e7d9c2..cb0030c 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -754,6 +754,11 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM],
-offset);
}
+ else if (thumb_instruction_restores_sp (insn))
+ {
+ /* Don't scan past the epilogue. */
+ break;
+ }
else if ((insn & 0xf800) == 0xa800) /* add Rd, sp, #imm */
regs[bits (insn, 8, 10)] = pv_add_constant (regs[ARM_SP_REGNUM],
(insn & 0xff) << 2);