X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Finline-frame.c;h=cecb2afb8e9d46e45e6036ff56f00e49ab9c3efc;hb=9c1877ead06db18e19614a598d1e280acb97e971;hp=0e6dae323fd5311f66d634344be3b8047112e7c1;hpb=005ca36a8b302b4d6da415e0cf66d5d9f684a8da;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c index 0e6dae323f..cecb2afb8e 100644 --- a/gdb/inline-frame.c +++ b/gdb/inline-frame.c @@ -1,6 +1,6 @@ /* Inline frame unwinder for GDB. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008-2014 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); @@ -225,13 +243,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,24 +258,23 @@ 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); @@ -276,7 +288,7 @@ block_starting_point_at (CORE_ADDR pc, struct block *block) 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 +302,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;