mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 12:03:41 +08:00
56260065c8
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>
58 lines
1.4 KiB
C
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;
|
|
}
|