diff options
-rw-r--r-- | gdb/ChangeLog | 10 | ||||
-rw-r--r-- | gdb/dwarf2-frame.c | 37 |
2 files changed, 32 insertions, 15 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4bc944c..c4bcdf6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2013-11-22 Pedro Alves <palves@redhat.com> + + PR 16155 + * dwarf2-frame.c (struct dwarf2_frame_cache) + <checked_tailcall_bottom, entry_cfa_sp_offset, + entry_cfa_sp_offset_p>: New fields. + (dwarf2_frame_cache): Adjust to use the new cache fields instead + of locals. Don't call dwarf2_tailcall_sniffer_first here. + (dwarf2_frame_prev_register): Call it here, but only once. + 2013-11-21 Doug Evans <xdje42@gmail.com> * gdbtypes.c: #include bcache.h, dwarf2loc.h. diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index 91d8802..c4f8771 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -993,12 +993,22 @@ struct dwarf2_frame_cache /* The .text offset. */ CORE_ADDR text_offset; + /* True if we already checked whether this frame is the bottom frame + of a virtual tail call frame chain. */ + int checked_tailcall_bottom; + /* If not NULL then this frame is the bottom frame of a TAILCALL_FRAME sequence. If NULL then it is a normal case with no TAILCALL_FRAME involved. Non-bottom frames of a virtual tail call frames chain use dwarf2_tailcall_frame_unwind unwinder so this field does not apply for them. */ void *tailcall_cache; + + /* The number of bytes to subtract from TAILCALL_FRAME frames frame + base to get the SP, to simulate the return address pushed on the + stack. */ + LONGEST entry_cfa_sp_offset; + int entry_cfa_sp_offset_p; }; /* A cleanup that sets a pointer to NULL. */ @@ -1023,8 +1033,6 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) struct dwarf2_fde *fde; volatile struct gdb_exception ex; CORE_ADDR entry_pc; - LONGEST entry_cfa_sp_offset; - int entry_cfa_sp_offset_p = 0; const gdb_byte *instr; if (*this_cache) @@ -1089,8 +1097,8 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) && (gdbarch_dwarf2_reg_to_regnum (gdbarch, fs->regs.cfa_reg) == gdbarch_sp_regnum (gdbarch))) { - entry_cfa_sp_offset = fs->regs.cfa_offset; - entry_cfa_sp_offset_p = 1; + cache->entry_cfa_sp_offset = fs->regs.cfa_offset; + cache->entry_cfa_sp_offset_p = 1; } } else @@ -1239,13 +1247,6 @@ incomplete CFI data; unspecified registers (e.g., %s) at %s"), cache->undefined_retaddr = 1; do_cleanups (old_chain); - - /* Try to find a virtual tail call frames chain with bottom (callee) frame - starting at THIS_FRAME. */ - dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache, - (entry_cfa_sp_offset_p - ? &entry_cfa_sp_offset : NULL)); - discard_cleanups (reset_cache_cleanup); return cache; } @@ -1292,6 +1293,16 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache, CORE_ADDR addr; int realnum; + /* Check whether THIS_FRAME is the bottom frame of a virtual tail + call frame chain. */ + if (!cache->checked_tailcall_bottom) + { + cache->checked_tailcall_bottom = 1; + dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache, + (cache->entry_cfa_sp_offset_p + ? &cache->entry_cfa_sp_offset : NULL)); + } + /* Non-bottom frames of a virtual tail call frames chain use dwarf2_tailcall_frame_unwind unwinder so this code does not apply for them. If dwarf2_tailcall_prev_register_first does not have specific value @@ -1418,10 +1429,6 @@ dwarf2_frame_sniffer (const struct frame_unwind *self, if (self->type != NORMAL_FRAME) return 0; - /* Preinitializa the cache so that TAILCALL_FRAME can find the record by - dwarf2_tailcall_sniffer_first. */ - dwarf2_frame_cache (this_frame, this_cache); - return 1; } |