X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Finline-frame.c;h=f8ba249eb407cae9c2ad1ebd485ddd7b4750fcf2;hb=484b3c325d8182cd7b7da4ceeaedc238c7f80b5c;hp=9af88f44159521c7d6fe930414bbaa612f6336df;hpb=f801e1e0ba77d02edaf429e823e2b4734c69a5b8;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c index 9af88f4415..f8ba249eb4 100644 --- a/gdb/inline-frame.c +++ b/gdb/inline-frame.c @@ -1,6 +1,6 @@ /* Inline frame unwinder for GDB. - Copyright (C) 2008, 2009 Free Software Foundation, Inc. + Copyright (C) 2008-2016 Free Software Foundation, Inc. This file is part of GDB. @@ -18,14 +18,15 @@ along with this program. If not, see . */ #include "defs.h" +#include "inline-frame.h" #include "addrmap.h" #include "block.h" #include "frame-unwind.h" #include "inferior.h" +#include "regcache.h" #include "symtab.h" #include "vec.h" - -#include "gdb_assert.h" +#include "frame.h" /* We need to save a few variables for every thread stopped at the virtual call site of an inlined function. If there was always a @@ -59,7 +60,8 @@ DEF_VEC_O(inline_state_s); static VEC(inline_state_s) *inline_states; -/* Locate saved inlined frame state for PTID, if it exists. */ +/* Locate saved inlined frame state for PTID, if it exists + and is valid. */ static struct inline_state * find_inline_frame_state (ptid_t ptid) @@ -70,7 +72,20 @@ find_inline_frame_state (ptid_t ptid) for (ix = 0; VEC_iterate (inline_state_s, inline_states, ix, state); ix++) { if (ptid_equal (state->ptid, ptid)) - return state; + { + struct regcache *regcache = get_thread_regcache (ptid); + CORE_ADDR current_pc = regcache_read_pc (regcache); + + if (current_pc != state->saved_pc) + { + /* PC has changed - this context is invalid. Use the + default behavior. */ + VEC_unordered_remove (inline_state_s, inline_states, ix); + return NULL; + } + else + return state; + } } return NULL; @@ -110,7 +125,10 @@ clear_inline_frame_state (ptid_t ptid) { VEC (inline_state_s) *new_states = NULL; int pid = ptid_get_pid (ptid); - for (ix = 0; VEC_iterate (inline_state_s, inline_states, ix, state); ix++) + + for (ix = 0; + VEC_iterate (inline_state_s, inline_states, ix, state); + ix++) if (pid != ptid_get_pid (state->ptid)) VEC_safe_push (inline_state_s, new_states, state); VEC_free (inline_state_s, inline_states); @@ -135,11 +153,11 @@ inline_frame_this_id (struct frame_info *this_frame, /* In order to have a stable frame ID for a given inline function, we must get the stack / special addresses from the underlying - real frame's this_id method. So we must call get_prev_frame. - Because we are inlined into some function, there must be previous - frames, so this is safe - as long as we're careful not to - create any cycles. */ - *this_id = get_frame_id (get_prev_frame (this_frame)); + real frame's this_id method. So we must call + get_prev_frame_always. Because we are inlined into some + function, there must be previous frames, so this is safe - as + long as we're careful not to create any cycles. */ + *this_id = get_frame_id (get_prev_frame_always (this_frame)); /* We need a valid frame ID, so we need to be based on a valid frame. FSF submission NOTE: this would be a good assertion to @@ -159,7 +177,7 @@ inline_frame_this_id (struct frame_info *this_frame, func = get_frame_function (this_frame); gdb_assert (func != NULL); (*this_id).code_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (func)); - (*this_id).inline_depth++; + (*this_id).artificial_depth++; } static struct value * @@ -189,7 +207,7 @@ inline_frame_sniffer (const struct frame_unwind *self, void **this_cache) { CORE_ADDR this_pc; - struct block *frame_block, *cur_block; + const struct block *frame_block, *cur_block; int depth; struct frame_info *next_frame; struct inline_state *state = find_inline_frame_state (inferior_ptid); @@ -207,6 +225,8 @@ inline_frame_sniffer (const struct frame_unwind *self, { if (block_inlined_p (cur_block)) depth++; + else if (BLOCK_FUNCTION (cur_block) != NULL) + break; cur_block = BLOCK_SUPERBLOCK (cur_block); } @@ -225,13 +245,8 @@ inline_frame_sniffer (const struct frame_unwind *self, can be stepped into later). */ if (state != NULL && state->skipped_frames > 0 && next_frame == NULL) { - if (this_pc != state->saved_pc) - state->skipped_frames = 0; - else - { - gdb_assert (depth >= state->skipped_frames); - depth -= state->skipped_frames; - } + gdb_assert (depth >= state->skipped_frames); + depth -= state->skipped_frames; } /* If all the inlined functions here already have frames, then pass @@ -245,38 +260,37 @@ inline_frame_sniffer (const struct frame_unwind *self, return 1; } -const struct frame_unwind inline_frame_unwinder = { +const struct frame_unwind inline_frame_unwind = { INLINE_FRAME, + default_frame_unwind_stop_reason, inline_frame_this_id, inline_frame_prev_register, NULL, inline_frame_sniffer }; -const struct frame_unwind *const inline_frame_unwind = &inline_frame_unwinder; - /* Return non-zero if BLOCK, an inlined function block containing PC, has a group of contiguous instructions starting at PC (but not before it). */ static int -block_starting_point_at (CORE_ADDR pc, struct block *block) +block_starting_point_at (CORE_ADDR pc, const struct block *block) { - struct blockvector *bv; + const struct blockvector *bv; struct block *new_block; bv = blockvector_for_pc (pc, NULL); if (BLOCKVECTOR_MAP (bv) == NULL) return 0; - new_block = addrmap_find (BLOCKVECTOR_MAP (bv), pc - 1); + new_block = (struct block *) addrmap_find (BLOCKVECTOR_MAP (bv), pc - 1); if (new_block == NULL) return 1; if (new_block == block || contained_in (new_block, block)) return 0; - /* The immediately preceeding address belongs to a different block, + /* The immediately preceding address belongs to a different block, which is not a child of this one. Treat this as an entrance into BLOCK. */ return 1; @@ -290,7 +304,7 @@ void skip_inline_frames (ptid_t ptid) { CORE_ADDR this_pc; - struct block *frame_block, *cur_block; + const struct block *frame_block, *cur_block; struct symbol *last_sym = NULL; int skip_count = 0; struct inline_state *state; @@ -319,6 +333,9 @@ skip_inline_frames (ptid_t ptid) else break; } + else if (BLOCK_FUNCTION (cur_block) != NULL) + break; + cur_block = BLOCK_SUPERBLOCK (cur_block); } }