X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Finline-frame.c;h=5cb6776aaff15df6adae2dbc7d02243e69aeb480;hb=e9061058b4fb26a6b4a7243f5dca1eb9066f2671;hp=896b0004e4a381c24cb9042841d80dd6b5813d3f;hpb=00431a78b28f913a9d5c912c49680e39cfd20847;p=binutils-gdb.git diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c index 896b0004e4a..5cb6776aaff 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-2022 Free Software Foundation, Inc. This file is part of GDB. @@ -27,7 +27,6 @@ #include "gdbthread.h" #include "regcache.h" #include "symtab.h" -#include "vec.h" #include "frame.h" #include @@ -38,9 +37,9 @@ struct inline_state { inline_state (thread_info *thread_, int skipped_frames_, CORE_ADDR saved_pc_, - symbol *skipped_symbol_) + std::vector &&skipped_symbols_) : thread (thread_), skipped_frames (skipped_frames_), saved_pc (saved_pc_), - skipped_symbol (skipped_symbol_) + skipped_symbols (std::move (skipped_symbols_)) {} /* The thread this data relates to. It should be a currently @@ -57,10 +56,10 @@ 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; @@ -96,37 +95,54 @@ find_inline_frame_state (thread_info *thread) 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.thread->inf->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.thread->ptid; + return thread == state.thread; }); if (it != inline_states.end ()) @@ -145,8 +161,12 @@ inline_frame_this_id (struct frame_info *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)); + long as we're careful not to create any cycles. See related + comments in get_prev_frame_always_1. */ + frame_info *prev_frame = get_prev_frame_always (this_frame); + if (prev_frame == nullptr) + error (_("failed to find previous frame when computing inline frame id")); + *this_id = get_frame_id (prev_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 @@ -155,17 +175,13 @@ inline_frame_this_id (struct frame_info *this_frame, frame"). This will take work. */ gdb_assert (frame_id_p (*this_id)); - /* For now, require we don't match outer_frame_id either (see - comment above). */ - gdb_assert (!frame_id_eq (*this_id, outer_frame_id)); - /* Future work NOTE: Alexandre Oliva applied a patch to GCC 4.3 which generates DW_AT_entry_pc for inlined functions when possible. If this attribute is available, we should use it 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 = func->value_block ()->entry_pc (); (*this_id).artificial_depth++; } @@ -210,14 +226,14 @@ inline_frame_sniffer (const struct frame_unwind *self, location. */ depth = 0; cur_block = frame_block; - while (BLOCK_SUPERBLOCK (cur_block)) + while (cur_block->superblock ()) { if (block_inlined_p (cur_block)) depth++; - else if (BLOCK_FUNCTION (cur_block) != NULL) + else if (cur_block->function () != NULL) break; - cur_block = BLOCK_SUPERBLOCK (cur_block); + cur_block = cur_block->superblock (); } /* Check how many inlined functions already have frames. */ @@ -250,6 +266,7 @@ inline_frame_sniffer (const struct frame_unwind *self, } const struct frame_unwind inline_frame_unwind = { + "inline", INLINE_FRAME, default_frame_unwind_stop_reason, inline_frame_this_id, @@ -266,13 +283,13 @@ 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) + if (bv->map () == nullptr) return 0; - new_block = (struct block *) addrmap_find (BLOCKVECTOR_MAP (bv), pc - 1); + new_block = (const struct block *) bv->map ()->find (pc - 1); if (new_block == NULL) return 1; @@ -286,24 +303,34 @@ 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 set at FRAME_BLOCK. */ + inlined frame because of a breakpoint with a user-specified location + set at FRAME_BLOCK. */ static bool -stopped_by_user_bp_inline_frame (const block *frame_block, 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) + for (bpstat *s = stop_chain; s != nullptr; s = s->next) { struct breakpoint *bpt = s->breakpoint_at; - if (bpt != NULL && user_breakpoint_p (bpt)) + if (bpt != NULL + && (user_breakpoint_p (bpt) || bpt->type == bp_until)) { - bp_location *loc = s->bp_location_at; + bp_location *loc = s->bp_location_at.get (); enum bp_loc_type t = loc->loc_type; - if ((t == bp_loc_software_breakpoint - || t == bp_loc_hardware_breakpoint) - && frame_block == SYMBOL_BLOCK_VALUE (loc->symbol)) - 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 == loc->symbol->value_block ()) + return true; + } } } @@ -313,10 +340,10 @@ stopped_by_user_bp_inline_frame (const block *frame_block, bpstat stop_chain) /* See inline-frame.h. */ void -skip_inline_frames (thread_info *thread, 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 @@ -328,13 +355,13 @@ skip_inline_frames (thread_info *thread, bpstat stop_chain) if (frame_block != NULL) { cur_block = frame_block; - while (BLOCK_SUPERBLOCK (cur_block)) + while (cur_block->superblock ()) { 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 (cur_block->entry_pc () == this_pc || block_starting_point_at (this_pc, cur_block)) { /* Do not skip the inlined frame if execution @@ -344,20 +371,21 @@ skip_inline_frames (thread_info *thread, bpstat stop_chain) break; skip_count++; - last_sym = BLOCK_FUNCTION (cur_block); + skipped_syms.push_back (cur_block->function ()); } else break; } - else if (BLOCK_FUNCTION (cur_block) != NULL) + else if (cur_block->function () != NULL) break; - cur_block = BLOCK_SUPERBLOCK (cur_block); + cur_block = cur_block->superblock (); } } gdb_assert (find_inline_frame_state (thread) == NULL); - inline_states.emplace_back (thread, skip_count, this_pc, last_sym); + inline_states.emplace_back (thread, skip_count, this_pc, + std::move (skipped_syms)); if (skip_count != 0) reinit_frame_cache (); @@ -396,9 +424,16 @@ struct symbol * inline_skipped_symbol (thread_info *thread) { 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