diff options
author | Andrew Burgess <aburgess@redhat.com> | 2024-07-31 07:42:56 +0100 |
---|---|---|
committer | Andrew Burgess <aburgess@redhat.com> | 2024-08-28 10:30:31 +0100 |
commit | 56260065c80caf67b57ec612b85bb978e06dad2d (patch) | |
tree | a99e8d6be7dbb3c994fea5ccbc239f97c9e7bd57 /gdb/doc | |
parent | 3e9907d8496edb66086dcdebd3a9cb2b3c918e77 (diff) | |
download | gdb-56260065c80caf67b57ec612b85bb978e06dad2d.zip gdb-56260065c80caf67b57ec612b85bb978e06dad2d.tar.gz gdb-56260065c80caf67b57ec612b85bb978e06dad2d.tar.bz2 |
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>
Diffstat (limited to 'gdb/doc')
-rw-r--r-- | gdb/doc/gdb.texinfo | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 7938b07..e85099f 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -41858,6 +41858,117 @@ frame-id for frame #0: @{stack=0x7fffffffac70,code=0x0000000000401106,!special@} frame-id for frame #2: @{stack=0x7fffffffac90,code=0x000000000040111c,!special@} @end smallexample +@item maint info inline-frames +@itemx maint info inline-frames @var{address} +@cindex frames of inlined functions +@kindex maint info inline-frames +Print information about inlined frames which start at the current +address, or @var{address} if specified. + +In order to allow the user to correctly step into inlined functions, +@value{GDBN} needs to identify which inlined functions start at a +particular address, and @value{GDBN} also needs to track which of +these functions was last displayed to the user as the current frame. + +Imagine a situation where function @code{main} calls @code{foo}, which +then calls @code{bar}, something like this: + +@smallexample +@group +int +main () +@{ + /* Some interesting code here... */ + + foo (); + + /* More interesting code here... */ +@} + +void +foo () +@{ + bar (); +@} + +void +bar () +@{ + /* Some interesting code here... */ +@} +@end group +@end smallexample + +As both @code{foo} and @code{bar} are inlined within @code{main} then +there could be one address within @code{main} which is also the start +of @code{foo} and also the start of @code{bar}. When the user stops +at this address they will initially be told the inferior is in +@code{main}, if the user does a @kbd{step} then @value{GDBN} doesn't +actually step the inferior, instead the user is told the inferior +entered @code{foo}. After the next @kbd{step} the user is told the +inferior entered @code{bar}. The @kbd{maint info inline-frames} +command can be used to view this internal @value{GDBN} state, like +this: + +@smallexample +@group +(@value{GDBP}) step +24 foo (); +(@value{GDBP}) maintenance info inline-frames +Cached inline state information for thread 1. +program counter = 0x401137 +skipped frames = 2 + bar + foo +> main +@end group +@end smallexample + +Here the user is stopped in @code{main} at the call to @code{foo}. The +inline-frames information shows that at this address @value{GDBN} has +found the start of inlined functions @code{bar} and @code{foo}, but +currently @value{GDBN} has skipped 2 frames and considers @code{main} +to be the current frame, this is indicated with the @samp{>}. + +If the user performs a @kbd{step} to enter @code{foo} then the +situation is updated: + +@smallexample +@group +(@value{GDBP}) step +foo () at inline.c:14 +14 bar (); +(@value{GDBP}) maintenance info inline-frames +Cached inline state information for thread 1. +program counter = 0x401137 +skipped frames = 1 + bar +> foo + main +@end group +@end smallexample + +Notice that the program counter value @code{0x401137} hasn't change, +but now @value{GDBN} considers @code{foo} to be the current frame, and +it is marked as such with the @samp{>}. + +Finally, the user performs another @kbd{step} to enter @code{bar}: + +@smallexample +@group +(@value{GDBP}) step +bar () at inline.c:6 +6 ++global_counter; +(@value{GDBP}) maintenance info inline-frames +Cached inline state information for thread 1. +program counter = 0x401137 +skipped frames = 0 +> bar + foo + main +@end group +@end smallexample + @kindex maint print registers @kindex maint print raw-registers @kindex maint print cooked-registers |