]> Git Repo - binutils.git/blob - gdb/inline-frame.c
gdb: remove SYMBOL_CLASS macro, add getter
[binutils.git] / gdb / inline-frame.c
1 /* Inline frame unwinder for GDB.
2
3    Copyright (C) 2008-2022 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21 #include "breakpoint.h"
22 #include "inline-frame.h"
23 #include "addrmap.h"
24 #include "block.h"
25 #include "frame-unwind.h"
26 #include "inferior.h"
27 #include "gdbthread.h"
28 #include "regcache.h"
29 #include "symtab.h"
30 #include "frame.h"
31 #include <algorithm>
32
33 /* We need to save a few variables for every thread stopped at the
34    virtual call site of an inlined function.  If there was always a
35    "struct thread_info", we could hang it off that; in the mean time,
36    keep our own list.  */
37 struct inline_state
38 {
39   inline_state (thread_info *thread_, int skipped_frames_, CORE_ADDR saved_pc_,
40                 std::vector<symbol *> &&skipped_symbols_)
41     : thread (thread_), skipped_frames (skipped_frames_), saved_pc (saved_pc_),
42       skipped_symbols (std::move (skipped_symbols_))
43   {}
44
45   /* The thread this data relates to.  It should be a currently
46      stopped thread.  */
47   thread_info *thread;
48
49   /* The number of inlined functions we are skipping.  Each of these
50      functions can be stepped in to.  */
51   int skipped_frames;
52
53   /* Only valid if SKIPPED_FRAMES is non-zero.  This is the PC used
54      when calculating SKIPPED_FRAMES; used to check whether we have
55      moved to a new location by user request.  If so, we invalidate
56      any skipped frames.  */
57   CORE_ADDR saved_pc;
58
59   /* Only valid if SKIPPED_FRAMES is non-zero.  This is the list of all
60      function symbols that have been skipped, from inner most to outer
61      most.  It is used to find the call site of the current frame.  */
62   std::vector<struct symbol *> skipped_symbols;
63 };
64
65 static std::vector<inline_state> inline_states;
66
67 /* Locate saved inlined frame state for THREAD, if it exists and is
68    valid.  */
69
70 static struct inline_state *
71 find_inline_frame_state (thread_info *thread)
72 {
73   auto state_it = std::find_if (inline_states.begin (), inline_states.end (),
74                                 [thread] (const inline_state &state)
75                                   {
76                                     return state.thread == thread;
77                                   });
78
79   if (state_it == inline_states.end ())
80     return nullptr;
81
82   inline_state &state = *state_it;
83   struct regcache *regcache = get_thread_regcache (thread);
84   CORE_ADDR current_pc = regcache_read_pc (regcache);
85
86   if (current_pc != state.saved_pc)
87     {
88       /* PC has changed - this context is invalid.  Use the
89          default behavior.  */
90
91       unordered_remove (inline_states, state_it);
92       return nullptr;
93     }
94
95   return &state;
96 }
97
98 /* See inline-frame.h.  */
99
100 void
101 clear_inline_frame_state (process_stratum_target *target, ptid_t filter_ptid)
102 {
103   gdb_assert (target != NULL);
104
105   if (filter_ptid == minus_one_ptid || filter_ptid.is_pid ())
106     {
107       auto matcher = [target, &filter_ptid] (const inline_state &state)
108         {
109           thread_info *t = state.thread;
110           return (t->inf->process_target () == target
111                   && t->ptid.matches (filter_ptid));
112         };
113
114       auto it = std::remove_if (inline_states.begin (), inline_states.end (),
115                                 matcher);
116
117       inline_states.erase (it, inline_states.end ());
118
119       return;
120     }
121
122
123   auto matcher = [target, &filter_ptid] (const inline_state &state)
124     {
125       thread_info *t = state.thread;
126       return (t->inf->process_target () == target
127               && filter_ptid == t->ptid);
128     };
129
130   auto it = std::find_if (inline_states.begin (), inline_states.end (),
131                           matcher);
132
133   if (it != inline_states.end ())
134     unordered_remove (inline_states, it);
135 }
136
137 /* See inline-frame.h.  */
138
139 void
140 clear_inline_frame_state (thread_info *thread)
141 {
142   auto it = std::find_if (inline_states.begin (), inline_states.end (),
143                           [thread] (const inline_state &state)
144                             {
145                               return thread == state.thread;
146                             });
147
148   if (it != inline_states.end ())
149     unordered_remove (inline_states, it);
150 }
151
152 static void
153 inline_frame_this_id (struct frame_info *this_frame,
154                       void **this_cache,
155                       struct frame_id *this_id)
156 {
157   struct symbol *func;
158
159   /* In order to have a stable frame ID for a given inline function,
160      we must get the stack / special addresses from the underlying
161      real frame's this_id method.  So we must call
162      get_prev_frame_always.  Because we are inlined into some
163      function, there must be previous frames, so this is safe - as
164      long as we're careful not to create any cycles.  See related
165      comments in get_prev_frame_always_1.  */
166   frame_info *prev_frame = get_prev_frame_always (this_frame);
167   if (prev_frame == nullptr)
168     error (_("failed to find previous frame when computing inline frame id"));
169   *this_id = get_frame_id (prev_frame);
170
171   /* We need a valid frame ID, so we need to be based on a valid
172      frame.  FSF submission NOTE: this would be a good assertion to
173      apply to all frames, all the time.  That would fix the ambiguity
174      of null_frame_id (between "no/any frame" and "the outermost
175      frame").  This will take work.  */
176   gdb_assert (frame_id_p (*this_id));
177
178   /* Future work NOTE: Alexandre Oliva applied a patch to GCC 4.3
179      which generates DW_AT_entry_pc for inlined functions when
180      possible.  If this attribute is available, we should use it
181      in the frame ID (and eventually, to set breakpoints).  */
182   func = get_frame_function (this_frame);
183   gdb_assert (func != NULL);
184   (*this_id).code_addr = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (func));
185   (*this_id).artificial_depth++;
186 }
187
188 static struct value *
189 inline_frame_prev_register (struct frame_info *this_frame, void **this_cache,
190                             int regnum)
191 {
192   /* Use get_frame_register_value instead of
193      frame_unwind_got_register, to avoid requiring this frame's ID.
194      This frame's ID depends on the previous frame's ID (unusual), and
195      the previous frame's ID depends on this frame's unwound
196      registers.  If unwinding registers from this frame called
197      get_frame_id, there would be a loop.
198
199      Do not copy this code into any other unwinder!  Inlined functions
200      are special; other unwinders must not have a dependency on the
201      previous frame's ID, and therefore can and should use
202      frame_unwind_got_register instead.  */
203   return get_frame_register_value (this_frame, regnum);
204 }
205
206 /* Check whether we are at an inlining site that does not already
207    have an associated frame.  */
208
209 static int
210 inline_frame_sniffer (const struct frame_unwind *self,
211                       struct frame_info *this_frame,
212                       void **this_cache)
213 {
214   CORE_ADDR this_pc;
215   const struct block *frame_block, *cur_block;
216   int depth;
217   struct frame_info *next_frame;
218   struct inline_state *state = find_inline_frame_state (inferior_thread ());
219
220   this_pc = get_frame_address_in_block (this_frame);
221   frame_block = block_for_pc (this_pc);
222   if (frame_block == NULL)
223     return 0;
224
225   /* Calculate DEPTH, the number of inlined functions at this
226      location.  */
227   depth = 0;
228   cur_block = frame_block;
229   while (BLOCK_SUPERBLOCK (cur_block))
230     {
231       if (block_inlined_p (cur_block))
232         depth++;
233       else if (BLOCK_FUNCTION (cur_block) != NULL)
234         break;
235
236       cur_block = BLOCK_SUPERBLOCK (cur_block);
237     }
238
239   /* Check how many inlined functions already have frames.  */
240   for (next_frame = get_next_frame (this_frame);
241        next_frame && get_frame_type (next_frame) == INLINE_FRAME;
242        next_frame = get_next_frame (next_frame))
243     {
244       gdb_assert (depth > 0);
245       depth--;
246     }
247
248   /* If this is the topmost frame, or all frames above us are inlined,
249      then check whether we were requested to skip some frames (so they
250      can be stepped into later).  */
251   if (state != NULL && state->skipped_frames > 0 && next_frame == NULL)
252     {
253       gdb_assert (depth >= state->skipped_frames);
254       depth -= state->skipped_frames;
255     }
256
257   /* If all the inlined functions here already have frames, then pass
258      to the normal unwinder for this PC.  */
259   if (depth == 0)
260     return 0;
261
262   /* If the next frame is an inlined function, but not the outermost, then
263      we are the next outer.  If it is not an inlined function, then we
264      are the innermost inlined function of a different real frame.  */
265   return 1;
266 }
267
268 const struct frame_unwind inline_frame_unwind = {
269   "inline",
270   INLINE_FRAME,
271   default_frame_unwind_stop_reason,
272   inline_frame_this_id,
273   inline_frame_prev_register,
274   NULL,
275   inline_frame_sniffer
276 };
277
278 /* Return non-zero if BLOCK, an inlined function block containing PC,
279    has a group of contiguous instructions starting at PC (but not
280    before it).  */
281
282 static int
283 block_starting_point_at (CORE_ADDR pc, const struct block *block)
284 {
285   const struct blockvector *bv;
286   const struct block *new_block;
287
288   bv = blockvector_for_pc (pc, NULL);
289   if (BLOCKVECTOR_MAP (bv) == NULL)
290     return 0;
291
292   new_block = (const struct block *) addrmap_find (BLOCKVECTOR_MAP (bv),
293                                                    pc - 1);
294   if (new_block == NULL)
295     return 1;
296
297   if (new_block == block || contained_in (new_block, block))
298     return 0;
299
300   /* The immediately preceding address belongs to a different block,
301      which is not a child of this one.  Treat this as an entrance into
302      BLOCK.  */
303   return 1;
304 }
305
306 /* Loop over the stop chain and determine if execution stopped in an
307    inlined frame because of a breakpoint with a user-specified location
308    set at FRAME_BLOCK.  */
309
310 static bool
311 stopped_by_user_bp_inline_frame (const block *frame_block, bpstat *stop_chain)
312 {
313   for (bpstat *s = stop_chain; s != nullptr; s = s->next)
314     {
315       struct breakpoint *bpt = s->breakpoint_at;
316
317       if (bpt != NULL
318           && (user_breakpoint_p (bpt) || bpt->type == bp_until))
319         {
320           bp_location *loc = s->bp_location_at.get ();
321           enum bp_loc_type t = loc->loc_type;
322
323           if (t == bp_loc_software_breakpoint
324               || t == bp_loc_hardware_breakpoint)
325             {
326               /* If the location has a function symbol, check whether
327                  the frame was for that inlined function.  If it has
328                  no function symbol, then assume it is.  I.e., default
329                  to presenting the stop at the innermost inline
330                  function.  */
331               if (loc->symbol == nullptr
332                   || frame_block == SYMBOL_BLOCK_VALUE (loc->symbol))
333                 return true;
334             }
335         }
336     }
337
338   return false;
339 }
340
341 /* See inline-frame.h.  */
342
343 void
344 skip_inline_frames (thread_info *thread, bpstat *stop_chain)
345 {
346   const struct block *frame_block, *cur_block;
347   std::vector<struct symbol *> skipped_syms;
348   int skip_count = 0;
349
350   /* This function is called right after reinitializing the frame
351      cache.  We try not to do more unwinding than absolutely
352      necessary, for performance.  */
353   CORE_ADDR this_pc = get_frame_pc (get_current_frame ());
354   frame_block = block_for_pc (this_pc);
355
356   if (frame_block != NULL)
357     {
358       cur_block = frame_block;
359       while (BLOCK_SUPERBLOCK (cur_block))
360         {
361           if (block_inlined_p (cur_block))
362             {
363               /* See comments in inline_frame_this_id about this use
364                  of BLOCK_ENTRY_PC.  */
365               if (BLOCK_ENTRY_PC (cur_block) == this_pc
366                   || block_starting_point_at (this_pc, cur_block))
367                 {
368                   /* Do not skip the inlined frame if execution
369                      stopped in an inlined frame because of a user
370                      breakpoint for this inline function.  */
371                   if (stopped_by_user_bp_inline_frame (cur_block, stop_chain))
372                     break;
373
374                   skip_count++;
375                   skipped_syms.push_back (BLOCK_FUNCTION (cur_block));
376                 }
377               else
378                 break;
379             }
380           else if (BLOCK_FUNCTION (cur_block) != NULL)
381             break;
382
383           cur_block = BLOCK_SUPERBLOCK (cur_block);
384         }
385     }
386
387   gdb_assert (find_inline_frame_state (thread) == NULL);
388   inline_states.emplace_back (thread, skip_count, this_pc,
389                               std::move (skipped_syms));
390
391   if (skip_count != 0)
392     reinit_frame_cache ();
393 }
394
395 /* Step into an inlined function by unhiding it.  */
396
397 void
398 step_into_inline_frame (thread_info *thread)
399 {
400   inline_state *state = find_inline_frame_state (thread);
401
402   gdb_assert (state != NULL && state->skipped_frames > 0);
403   state->skipped_frames--;
404   reinit_frame_cache ();
405 }
406
407 /* Return the number of hidden functions inlined into the current
408    frame.  */
409
410 int
411 inline_skipped_frames (thread_info *thread)
412 {
413   inline_state *state = find_inline_frame_state (thread);
414
415   if (state == NULL)
416     return 0;
417   else
418     return state->skipped_frames;
419 }
420
421 /* If one or more inlined functions are hidden, return the symbol for
422    the function inlined into the current frame.  */
423
424 struct symbol *
425 inline_skipped_symbol (thread_info *thread)
426 {
427   inline_state *state = find_inline_frame_state (thread);
428   gdb_assert (state != NULL);
429
430   /* This should only be called when we are skipping at least one frame,
431      hence SKIPPED_FRAMES will be greater than zero when we get here.
432      We initialise SKIPPED_FRAMES at the same time as we build
433      SKIPPED_SYMBOLS, hence it should be true that SKIPPED_FRAMES never
434      indexes outside of the SKIPPED_SYMBOLS vector.  */
435   gdb_assert (state->skipped_frames > 0);
436   gdb_assert (state->skipped_frames <= state->skipped_symbols.size ());
437   return state->skipped_symbols[state->skipped_frames - 1];
438 }
439
440 /* Return the number of functions inlined into THIS_FRAME.  Some of
441    the callees may not have associated frames (see
442    skip_inline_frames).  */
443
444 int
445 frame_inlined_callees (struct frame_info *this_frame)
446 {
447   struct frame_info *next_frame;
448   int inline_count = 0;
449
450   /* First count how many inlined functions at this PC have frames
451      above FRAME (are inlined into FRAME).  */
452   for (next_frame = get_next_frame (this_frame);
453        next_frame && get_frame_type (next_frame) == INLINE_FRAME;
454        next_frame = get_next_frame (next_frame))
455     inline_count++;
456
457   /* Simulate some most-inner inlined frames which were suppressed, so
458      they can be stepped into later.  If we are unwinding already
459      outer frames from some non-inlined frame this does not apply.  */
460   if (next_frame == NULL)
461     inline_count += inline_skipped_frames (inferior_thread ());
462
463   return inline_count;
464 }
This page took 0.049905 seconds and 4 git commands to generate.