diff options
author | Tom de Vries <tdevries@suse.de> | 2025-01-29 11:21:02 +0100 |
---|---|---|
committer | Andrew Burgess <aburgess@redhat.com> | 2025-02-25 10:56:36 +0000 |
commit | 1e9bd86ccda976c0f7ef513cb5e9ee3eff460768 (patch) | |
tree | 60bd79ce4c792df44514d8691a0e59e6a09e34c7 /gdb/windows-nat.c | |
parent | f40b59b91240886003b679ff4a3fd51b6b60696a (diff) | |
download | binutils-1e9bd86ccda976c0f7ef513cb5e9ee3eff460768.zip binutils-1e9bd86ccda976c0f7ef513cb5e9ee3eff460768.tar.gz binutils-1e9bd86ccda976c0f7ef513cb5e9ee3eff460768.tar.bz2 |
gdb: don't show incorrect source file in source window
Consider the test-case sources main.c and foo.c:
$ cat main.c
extern int foo (void);
int
main (void)
{
return foo ();
}
$ cat foo.c
extern int foo (void);
int
foo (void)
{
return 0;
}
and main.c compiled with debug info, and foo.c without:
$ gcc -g main.c -c
$ gcc foo.c -c
$ gcc -g main.o foo.o
In TUI mode, if we run to foo:
$ gdb -q a.out -tui -ex "b foo" -ex run
it gets us "[ No Source Available ]":
┌─main.c─────────────────────────────────────────┐
│ │
│ │
│ │
│ [ No Source Available ] │
│ │
│ │
└────────────────────────────────────────────────┘
(src) In: foo L?? PC: 0x400566
...
Breakpoint 1, 0x0000000000400566 in foo ()
(gdb)
But after resizing (pressing ctrl-<minus> in the gnome-terminal), we
get instead the source for main.c:
┌─main.c─────────────────────────────────────────┐
│ 3 int │
│ 4 main (void) │
│ 5 { │
│ 6 return foo (); │
│ 7 } │
│ │
│ │
└────────────────────────────────────────────────┘
(src) In: foo L?? PC: 0x400566
...
Breakpoint 1, 0x0000000000400566 in foo ()
(gdb)
which is inappropriate because we're stopped in function foo, which is
not in main.c.
The problem is that, when the window is resized, GDB ends up calling
tui_source_window_base::rerender. The rerender function has three
cases, one for when the window already has some source code
content (which is not the case here), a case for when the inferior is
active, and we have a selected frame (which is the case that applies
here), and a final case for when the inferior is not running.
For the case which we end up in, the source code window has no
content, but the inferior is running, so we have a selected frame, GDB
calls the get_current_source_symtab_and_line() function to get the
symtab_and_line for the current location.
The get_current_source_symtab_and_line() will actually return the last
recorded symtab and line location, not the current symtab and line
location.
What this means, is that, if the current location has no debug
information, get_current_source_symtab_and_line() will return any
previously recorded location, or failing that, the default (main)
location.
This behaviour of get_current_source_symtab_and_line() also causes
problems for the 'list' command. Consider this pure CLI session:
(gdb) break foo
Breakpoint 1 at 0x40110a
(gdb) run
Starting program: /tmp/a.out
Breakpoint 1, 0x000000000040110a in foo ()
(gdb) list
1 extern int foo (void);
2
3 int
4 main (void)
5 {
6 return foo ();
7 }
(gdb) list .
Insufficient debug info for showing source lines at current PC (0x40110a).
(gdb)
However, if we look at how GDB's TUI updates the source window during
a normal stop, we see that GDB does a better job of displaying the
expected contents. Going back to our original example, when we start
GDB with:
$ gdb -q a.out -tui -ex "b foo" -ex run
we do get the "[ No Source Available ]" message as expected. Why is
that?
The answer is that, in this case GDB uses tui_show_frame_info to
update the source window, tui_show_frame_info is called each time a
prompt is displayed, like this:
#0 tui_show_frame_info (fi=...) at ../../src/gdb/tui/tui-status.c:269
#1 0x0000000000f55975 in tui_refresh_frame_and_register_information () at ../../src/gdb/tui/tui-hooks.c:118
#2 0x0000000000f55ae8 in tui_before_prompt (current_gdb_prompt=0x31ef930 <top_prompt+16> "(gdb) ") at ../../src/gdb/tui/tui-hooks.c:165
#3 0x000000000090ea45 in std::_Function_handler<void(char const*), void (*)(char const*)>::_M_invoke (__functor=..., __args#0=@0x7ffc955106b0: 0x31ef930 <top_prompt+16> "(gdb) ") at /usr/include/c++/9/bits/std_function.h:300
#4 0x00000000009020df in std::function<void(char const*)>::operator() (this=0x5281260, __args#0=0x31ef930 <top_prompt+16> "(gdb) ") at /usr/include/c++/9/bits/std_function.h:688
#5 0x0000000000901c35 in gdb::observers::observable<char const*>::notify (this=0x31dda00 <gdb::observers::before_prompt>, args#0=0x31ef930 <top_prompt+16> "(gdb) ") at ../../src/gdb/../gdbsupport/observable.h:166
#6 0x00000000008ffed8 in notify_before_prompt (prompt=0x31ef930 <top_prompt+16> "(gdb) ") at ../../src/gdb/event-top.c:518
#7 0x00000000008fff08 in top_level_prompt () at ../../src/gdb/event-top.c:534
#8 0x00000000008ffdeb in display_gdb_prompt (new_prompt=0x0) at ../../src/gdb/event-top.c:487
If we look at how tui_show_frame_info figures out what source to
display, it doesn't use get_current_source_symtab_and_line(), instead,
it finds a symtab_and_line directly from a frame_info_pt. This means
we are not dependent on get_current_source_symtab_and_line() returning
the current location (which it does not).
I propose that we change tui_source_window_base::rerender() so that,
for the case we are discussing here (the inferior has a selected
frame, but the source window has no contents), we move away from using
get_current_source_symtab_and_line(), and instead use find_frame_sal
instead, like tui_show_frame_info does.
This means that we will always use the inferior's current location.
Tested on x86_64-linux.
Reviewed-By: Tom de Vries <tdevries@suse.de>
Reported-By: Andrew Burgess <aburgess@redhat.com>
Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32614
Diffstat (limited to 'gdb/windows-nat.c')
0 files changed, 0 insertions, 0 deletions