binutils-gdb/gdb/testsuite/gdb.base/maint-info-inline-frames-and-blocks.c
Andrew Burgess 56260065c8 gdb: Add 'maint info inline-frames' command
While reviewing a patch I wanted to view GDB's inline frame state.  I
don't believe there's currently a maintenance command to view this
information, so in this commit I've added one.

The new command is:

  maintenance info inline-frames
  maintenance info inline-frames ADDRESS

The command lists the inline frames that start at ADDRESS, or at the
current $pc if no ADDRESS is given.  The command also displays the
"outer" function in which the inline functions are present.

An example of the command output:

  (gdb) maintenance info inline-frames
  Cached inline state information for thread 1.
  program counter = 0x401137
  skipped frames = 1
    bar
  > foo
    main
  (gdb)

This tells us that function 'main' called 'foo' which called 'bar'.
The functions 'foo' and 'bar' are both inline and both start at the
address 0x401137.  Currently GDB considers the inferior to be stopped
in frame 'foo' (note the '>' marker), this means that there is 1
skipped frame (function 'bar').

The function 'main' is the outer function.  The outer function might
not start at 0x401137, it is simply the function that contains the
inline functions.

If the user does a 'step' then GDB will not actually move the inferior
forward, but will instead simply tell the user that the inferior
entered 'bar'.  The output of 'maint info inline-frames' will change
like this:

  (gdb) step
  bar () at inline.c:6
  6	  ++global_counter;
  (gdb) maintenance info inline-frames
  Cached inline state information for thread 1.
  program counter = 0x401137
  skipped frames = 0
  > bar
    foo
    main
  (gdb)

Now GDB is in function 'bar' and there are no skipped frames.

I have renamed skipped_symbols to function symbols within the
inline_state class.  We are now going to carry the "outer"
function (the function that contains all the inlined functions) within
this list (as the last entry), so the old name didn't really make
sense.  As a consequence of this rename I've updated some comments.

I've changed stopped_by_user_bp_inline_frame to take a symbol rather
than a block.  Previously we just used the block to access the
associated function symbol.  After this commit we can just pass in the
function symbol directly, so lets do that.

New function gather_inline_frames contains some of the logic pulled
from skip_inline_frames.  This new function builds the list of all
symbols of inlined functions that start at a given $pc value and also
the "outer" function that contains all of the inlined functions.

In skip_inline_frames I've split the loop logic into two.  The loop to
build the function symbol list has moved to gather_inline_frames.  The
loop to figure out how many of the inlined functions we are skipping
remains in skip_inline_frames and uses the result of calling
gather_inline_frames.

In inline_skipped_symbol there are some minor updates to the comment,
and I've tweaked one of the asserts now that the function symbols list
also contains the "outer" function (a <= becomes <).

The maintenance_info_inline_frames function is now and implements the
new maintenance command.

And _initialize_inline_frame is updated to register the new command.

I've added a basic test for the new command.  Please excuse the file
name for the new test, in the next commit I'll be adding additional
tests and at that point the file name will make sense.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Simon Marchi <simon.marchi@efficios.com>
2024-08-28 10:30:31 +01:00

58 lines
1.4 KiB
C

/* This testcase is part of GDB, the GNU debugger.
Copyright 2024 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
static void inline_func_a (void);
static void inline_func_b (void);
static void normal_func (void);
volatile int global_var = 0;
static void __attribute__((noinline))
normal_func (void)
{
/* Do some work. */
++global_var;
++global_var;
/* Now the inline function. */
inline_func_a ();
/* Do some work. */
++global_var; /* After inline function. */
++global_var;
}
static inline void __attribute__((__always_inline__))
inline_func_a (void)
{
inline_func_b ();
}
static inline void __attribute__((__always_inline__))
inline_func_b (void)
{
++global_var;
++global_var;
}
int
main ()
{
normal_func ();
return 0;
}