aboutsummaryrefslogtreecommitdiff
path: root/gdb/doc
diff options
context:
space:
mode:
authorAndrew Burgess <aburgess@redhat.com>2024-07-31 07:42:56 +0100
committerAndrew Burgess <aburgess@redhat.com>2024-08-28 10:30:31 +0100
commit56260065c80caf67b57ec612b85bb978e06dad2d (patch)
treea99e8d6be7dbb3c994fea5ccbc239f97c9e7bd57 /gdb/doc
parent3e9907d8496edb66086dcdebd3a9cb2b3c918e77 (diff)
downloadgdb-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.texinfo111
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