/* 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.
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#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"
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)
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;
{
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);
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 *
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
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). */
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;