summaryrefslogtreecommitdiff
path: root/gdb/dwarf2-frame.c
diff options
context:
space:
mode:
authorJoel Brobecker <brobecker@gnat.com>2012-08-16 15:45:46 +0000
committerJoel Brobecker <brobecker@gnat.com>2012-08-16 15:45:46 +0000
commit0c92d8c1c34359a02073b9b3ec19956841b232b2 (patch)
tree3460482b67902826fe910c901c4cc7a3fe070524 /gdb/dwarf2-frame.c
parenta3074307fcc835389974b37ce6ecf1bb7ec4b52f (diff)
downloadbinutils-gdb-0c92d8c1c34359a02073b9b3ec19956841b232b2.tar.gz
DWARF frame unwinder executes one too many rows
The problem is trying to unwind from a function where %ebp is NOT used as the frame pointer, and the size of the frame changes over the lifetime of that function. For instance, trying to unwind past the GNAT runtime function called system.tasking.rendezvous.timed_selective_wait on x86-linux, one can get: (gdb) bt [...] #3 0x0805364b in system.tasking.rendezvous.timed_selective_wait () #4 0xb7fe5068 in ?? () Backtrace stopped: previous frame inner to this frame (corrupt stack?) Looking at the CFI, we find the following initial instructions... > DW_CFA_def_cfa: %esp+4 (r4 ofs 4) > DW_CFA_offset: %eip at cfa-4 (r8 = %eip) ... and the associated FDE: > 00001be4 00000054 00001be8 FDE cie=00000000 pc=08053310..08053951 [...] > DW_CFA_advance_loc: 8 to 080534ad > DW_CFA_def_cfa_offset: 112 > DW_CFA_advance_loc2: 414 to 0805364b > DW_CFA_def_cfa_offset: 108 [...] The problem is that the DWARF frame unwinder executed the FDE until the row for PC == 0x0805364b. But in reality, our program hasn't executed the instruction at that address yet (it is the return address). So GDB executed a little too much of the FDE, giving us the wrong offset for the frame base, and thus the wrong address where %eip got saved. This patch fixes the problem by using a more correct PC as the bound for executing the FDE. gdb/ChangeLog: * dwarf2-frame.c (dwarf2_frame_cache): Use get_frame_address_in_block instead of get_frame_pc as the bound for executing the frame's FDE. gdb/testsuite/ChangeLog: * gdb.ada/rdv_wait: New testcase.
Diffstat (limited to 'gdb/dwarf2-frame.c')
-rw-r--r--gdb/dwarf2-frame.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index 986aaea2335..dcfbeb7be59 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -1065,7 +1065,8 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
/* First decode all the insns in the CIE. */
execute_cfa_program (fde, fde->cie->initial_instructions,
- fde->cie->end, gdbarch, get_frame_pc (this_frame), fs);
+ fde->cie->end, gdbarch,
+ get_frame_address_in_block (this_frame), fs);
/* Save the initialized register set. */
fs->initial = fs->regs;
@@ -1090,7 +1091,7 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
/* Then decode the insns in the FDE up to our target PC. */
execute_cfa_program (fde, instr, fde->end, gdbarch,
- get_frame_pc (this_frame), fs);
+ get_frame_address_in_block (this_frame), fs);
TRY_CATCH (ex, RETURN_MASK_ERROR)
{