X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Finline-frame.c;h=c650195e570e8d44b455aa5a3e13aaf29b7fe5f6;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=1ac5835438da4577fb45bea560b7e03296824d63;hpb=ddfe970e6bec29f779a60b071f12590e53cfe6eb;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c index 1ac5835438..c650195e57 100644 --- a/gdb/inline-frame.c +++ b/gdb/inline-frame.c @@ -1,6 +1,6 @@ /* Inline frame unwinder for GDB. - Copyright (C) 2008-2018 Free Software Foundation, Inc. + Copyright (C) 2008-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -24,9 +24,9 @@ #include "block.h" #include "frame-unwind.h" #include "inferior.h" +#include "gdbthread.h" #include "regcache.h" #include "symtab.h" -#include "vec.h" #include "frame.h" #include @@ -36,16 +36,15 @@ keep our own list. */ struct inline_state { - inline_state (ptid_t ptid_, int skipped_frames_, CORE_ADDR saved_pc_, - symbol *skipped_symbol_) - : ptid (ptid_), skipped_frames (skipped_frames_), saved_pc (saved_pc_), - skipped_symbol (skipped_symbol_) + inline_state (thread_info *thread_, int skipped_frames_, CORE_ADDR saved_pc_, + std::vector &&skipped_symbols_) + : thread (thread_), skipped_frames (skipped_frames_), saved_pc (saved_pc_), + skipped_symbols (std::move (skipped_symbols_)) {} /* The thread this data relates to. It should be a currently - stopped thread; we assume thread IDs never change while the - thread is stopped. */ - ptid_t ptid; + stopped thread. */ + thread_info *thread; /* The number of inlined functions we are skipping. Each of these functions can be stepped in to. */ @@ -57,31 +56,31 @@ struct inline_state any skipped frames. */ CORE_ADDR saved_pc; - /* Only valid if SKIPPED_FRAMES is non-zero. This is the symbol - of the outermost skipped inline function. It's used to find the - call site of the current frame. */ - struct symbol *skipped_symbol; + /* Only valid if SKIPPED_FRAMES is non-zero. This is the list of all + function symbols that have been skipped, from inner most to outer + most. It is used to find the call site of the current frame. */ + std::vector skipped_symbols; }; static std::vector inline_states; -/* Locate saved inlined frame state for PTID, if it exists - and is valid. */ +/* Locate saved inlined frame state for THREAD, if it exists and is + valid. */ static struct inline_state * -find_inline_frame_state (ptid_t ptid) +find_inline_frame_state (thread_info *thread) { auto state_it = std::find_if (inline_states.begin (), inline_states.end (), - [&ptid] (const inline_state &state) + [thread] (const inline_state &state) { - return ptid == state.ptid; + return state.thread == thread; }); if (state_it == inline_states.end ()) return nullptr; inline_state &state = *state_it; - struct regcache *regcache = get_thread_regcache (ptid); + struct regcache *regcache = get_thread_regcache (thread); CORE_ADDR current_pc = regcache_read_pc (regcache); if (current_pc != state.saved_pc) @@ -96,37 +95,54 @@ find_inline_frame_state (ptid_t ptid) return &state; } -/* Forget about any hidden inlined functions in PTID, which is new or - about to be resumed. PTID may be minus_one_ptid (all processes) - or a PID (all threads in this process). */ +/* See inline-frame.h. */ void -clear_inline_frame_state (ptid_t ptid) +clear_inline_frame_state (process_stratum_target *target, ptid_t filter_ptid) { - if (ptid == minus_one_ptid) - { - inline_states.clear (); - return; - } + gdb_assert (target != NULL); - if (ptid.is_pid ()) + if (filter_ptid == minus_one_ptid || filter_ptid.is_pid ()) { - int pid = ptid.pid (); + auto matcher = [target, &filter_ptid] (const inline_state &state) + { + thread_info *t = state.thread; + return (t->inf->process_target () == target + && t->ptid.matches (filter_ptid)); + }; + auto it = std::remove_if (inline_states.begin (), inline_states.end (), - [pid] (const inline_state &state) - { - return pid == state.ptid.pid (); - }); + matcher); inline_states.erase (it, inline_states.end ()); return; } + + auto matcher = [target, &filter_ptid] (const inline_state &state) + { + thread_info *t = state.thread; + return (t->inf->process_target () == target + && filter_ptid == t->ptid); + }; + + auto it = std::find_if (inline_states.begin (), inline_states.end (), + matcher); + + if (it != inline_states.end ()) + unordered_remove (inline_states, it); +} + +/* See inline-frame.h. */ + +void +clear_inline_frame_state (thread_info *thread) +{ auto it = std::find_if (inline_states.begin (), inline_states.end (), - [&ptid] (const inline_state &state) + [thread] (const inline_state &state) { - return ptid == state.ptid; + return thread == state.thread; }); if (it != inline_states.end ()) @@ -165,7 +181,7 @@ inline_frame_this_id (struct frame_info *this_frame, in the frame ID (and eventually, to set breakpoints). */ func = get_frame_function (this_frame); gdb_assert (func != NULL); - (*this_id).code_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (func)); + (*this_id).code_addr = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (func)); (*this_id).artificial_depth++; } @@ -199,7 +215,7 @@ inline_frame_sniffer (const struct frame_unwind *self, const struct block *frame_block, *cur_block; int depth; struct frame_info *next_frame; - struct inline_state *state = find_inline_frame_state (inferior_ptid); + struct inline_state *state = find_inline_frame_state (inferior_thread ()); this_pc = get_frame_address_in_block (this_frame); frame_block = block_for_pc (this_pc); @@ -266,13 +282,14 @@ static int block_starting_point_at (CORE_ADDR pc, const struct block *block) { const struct blockvector *bv; - struct block *new_block; + const struct block *new_block; bv = blockvector_for_pc (pc, NULL); if (BLOCKVECTOR_MAP (bv) == NULL) return 0; - new_block = (struct block *) addrmap_find (BLOCKVECTOR_MAP (bv), pc - 1); + new_block = (const struct block *) addrmap_find (BLOCKVECTOR_MAP (bv), + pc - 1); if (new_block == NULL) return 1; @@ -286,11 +303,10 @@ block_starting_point_at (CORE_ADDR pc, const struct block *block) } /* Loop over the stop chain and determine if execution stopped in an - inlined frame because of a user breakpoint. THIS_PC is the current - frame's PC. */ + inlined frame because of a user breakpoint set at FRAME_BLOCK. */ static bool -stopped_by_user_bp_inline_frame (CORE_ADDR this_pc, bpstat stop_chain) +stopped_by_user_bp_inline_frame (const block *frame_block, bpstat stop_chain) { for (bpstat s = stop_chain; s != NULL; s = s->next) { @@ -301,10 +317,18 @@ stopped_by_user_bp_inline_frame (CORE_ADDR this_pc, bpstat stop_chain) bp_location *loc = s->bp_location_at; enum bp_loc_type t = loc->loc_type; - if (loc->address == this_pc - && (t == bp_loc_software_breakpoint - || t == bp_loc_hardware_breakpoint)) - return true; + if (t == bp_loc_software_breakpoint + || t == bp_loc_hardware_breakpoint) + { + /* If the location has a function symbol, check whether + the frame was for that inlined function. If it has + no function symbol, then assume it is. I.e., default + to presenting the stop at the innermost inline + function. */ + if (loc->symbol == nullptr + || frame_block == SYMBOL_BLOCK_VALUE (loc->symbol)) + return true; + } } } @@ -314,10 +338,10 @@ stopped_by_user_bp_inline_frame (CORE_ADDR this_pc, bpstat stop_chain) /* See inline-frame.h. */ void -skip_inline_frames (ptid_t ptid, bpstat stop_chain) +skip_inline_frames (thread_info *thread, bpstat stop_chain) { const struct block *frame_block, *cur_block; - struct symbol *last_sym = NULL; + std::vector skipped_syms; int skip_count = 0; /* This function is called right after reinitializing the frame @@ -334,18 +358,18 @@ skip_inline_frames (ptid_t ptid, bpstat stop_chain) if (block_inlined_p (cur_block)) { /* See comments in inline_frame_this_id about this use - of BLOCK_START. */ - if (BLOCK_START (cur_block) == this_pc + of BLOCK_ENTRY_PC. */ + if (BLOCK_ENTRY_PC (cur_block) == this_pc || block_starting_point_at (this_pc, cur_block)) { /* Do not skip the inlined frame if execution stopped in an inlined frame because of a user - breakpoint. */ - if (!stopped_by_user_bp_inline_frame (this_pc, stop_chain)) - { - skip_count++; - last_sym = BLOCK_FUNCTION (cur_block); - } + breakpoint for this inline function. */ + if (stopped_by_user_bp_inline_frame (cur_block, stop_chain)) + break; + + skip_count++; + skipped_syms.push_back (BLOCK_FUNCTION (cur_block)); } else break; @@ -357,8 +381,9 @@ skip_inline_frames (ptid_t ptid, bpstat stop_chain) } } - gdb_assert (find_inline_frame_state (ptid) == NULL); - inline_states.emplace_back (ptid, skip_count, this_pc, last_sym); + gdb_assert (find_inline_frame_state (thread) == NULL); + inline_states.emplace_back (thread, skip_count, this_pc, + std::move (skipped_syms)); if (skip_count != 0) reinit_frame_cache (); @@ -367,9 +392,9 @@ skip_inline_frames (ptid_t ptid, bpstat stop_chain) /* Step into an inlined function by unhiding it. */ void -step_into_inline_frame (ptid_t ptid) +step_into_inline_frame (thread_info *thread) { - struct inline_state *state = find_inline_frame_state (ptid); + inline_state *state = find_inline_frame_state (thread); gdb_assert (state != NULL && state->skipped_frames > 0); state->skipped_frames--; @@ -380,9 +405,9 @@ step_into_inline_frame (ptid_t ptid) frame. */ int -inline_skipped_frames (ptid_t ptid) +inline_skipped_frames (thread_info *thread) { - struct inline_state *state = find_inline_frame_state (ptid); + inline_state *state = find_inline_frame_state (thread); if (state == NULL) return 0; @@ -394,12 +419,19 @@ inline_skipped_frames (ptid_t ptid) the function inlined into the current frame. */ struct symbol * -inline_skipped_symbol (ptid_t ptid) +inline_skipped_symbol (thread_info *thread) { - struct inline_state *state = find_inline_frame_state (ptid); - + inline_state *state = find_inline_frame_state (thread); gdb_assert (state != NULL); - return state->skipped_symbol; + + /* This should only be called when we are skipping at least one frame, + hence SKIPPED_FRAMES will be greater than zero when we get here. + We initialise SKIPPED_FRAMES at the same time as we build + SKIPPED_SYMBOLS, hence it should be true that SKIPPED_FRAMES never + indexes outside of the SKIPPED_SYMBOLS vector. */ + gdb_assert (state->skipped_frames > 0); + gdb_assert (state->skipped_frames <= state->skipped_symbols.size ()); + return state->skipped_symbols[state->skipped_frames - 1]; } /* Return the number of functions inlined into THIS_FRAME. Some of @@ -423,7 +455,7 @@ frame_inlined_callees (struct frame_info *this_frame) they can be stepped into later. If we are unwinding already outer frames from some non-inlined frame this does not apply. */ if (next_frame == NULL) - inline_count += inline_skipped_frames (inferior_ptid); + inline_count += inline_skipped_frames (inferior_thread ()); return inline_count; }