From: Tom de Vries <tdevries@suse.de>
To: gdb-patches@sourceware.org
Subject: [pushed] [gdb/tui] Improve section handling in tui_find_backward_disassembly_start_address
Date: Sat, 19 Sep 2026 17:59:48 +0200 [thread overview]
Message-ID: <20260919155948.1356120-1-tdevries@suse.de> (raw)
Consider a hello world:
...
$ gcc hello.c -g
...
and gdb setup like this:
...
$ gdb a.out -ex "layout asm" -ex "disassemble _start"
...
which gives us the following asm window:
...
┌─────────────────────────────────────────────────────────────────────┐
│ 0x401040 <_start> endbr64 │
│ 0x401044 <_start+4> xor %ebp,%ebp │
│ 0x401046 <_start+6> mov %rdx,%r9 │
│ 0x401049 <_start+9> pop %rsi │
│ 0x40104a <_start+10> mov %rsp,%rdx │
│ 0x40104d <_start+13> and $0xfffffffffffffff0,%rsp │
│ 0x401051 <_start+17> push %rax │
│ 0x401052 <_start+18> push %rsp │
│ 0x401053 <_start+19> xor %r8d,%r8d │
│ 0x401056 <_start+22> xor %ecx,%ecx │
└─────────────────────────────────────────────────────────────────────┘
...
The _start function sits at the start of the text section:
...
Disassembly of section .plt:
...
0000000000401030 <puts@plt>:
401030: ff 25 ca 2f 00 00 jmp *0x2fca(%rip)
401036: 68 00 00 00 00 push $0x0
40103b: e9 e0 ff ff ff jmp 401020 <_init+0x20>
Disassembly of section .text:
0000000000401040 <_start>:
...
and using <Up Arrow> we can scroll to the last instruction of the plt section,
at 0x40103b.
To make this happen:
- tui_find_backward_disassembly_start_address is called with addr == 0x401040
- lookup_minimal_symbol_by_pc_section is called with addr - 1
- minimal symbol puts@plt is found
- its address is returned and used as starting point for disassembly
However, tui_find_backward_disassembly_start_address uses two types of
information: minimal symbols, and sections.
If we disable the minimal symbol handling in
tui_find_backward_disassembly_start_address, we're no longer able to scroll to
the instruction at 0x40103b.
The section handling code:
....
/* Find the section that ADDR is in, and look for the start of the
section. */
struct obj_section *section = find_pc_section (addr);
if (section != NULL)
return section->addr ();
...
looks up the section for 0x401040, which is .text, and it returns its start
address, which is also 0x401040, signalling that we cannot scroll to before
that address.
Fix this by using addr - 1.
This happens to work because there's no section hole between sections plt and
text.
---
gdb/testsuite/gdb.tui/scroll-back.S | 52 ++++++++++++++++
gdb/testsuite/gdb.tui/scroll-back.exp | 89 +++++++++++++++++++++++++++
gdb/tui/tui-disasm.c | 6 +-
3 files changed, 144 insertions(+), 3 deletions(-)
create mode 100644 gdb/testsuite/gdb.tui/scroll-back.S
create mode 100644 gdb/testsuite/gdb.tui/scroll-back.exp
diff --git a/gdb/testsuite/gdb.tui/scroll-back.S b/gdb/testsuite/gdb.tui/scroll-back.S
new file mode 100644
index 00000000000..0ee1067ad2c
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/scroll-back.S
@@ -0,0 +1,52 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2026 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/>. */
+
+ .section .text
+ .global main
+main:
+ nop
+
+#ifdef __arm__
+ .section .text_1,"ax",%progbits
+#else
+ .section .text_1,"ax",@progbits
+#endif
+
+ # This is foo, but we don't use a symbol. We use a repetition of 8 to
+ # get the end of the section to be 8-byte aligned, to increase the
+ # chances of avoiding a section hole in between .text_1 and .text_2.
+ .rept 8
+ nop
+ .endr
+
+ .align 1
+
+#ifdef __arm__
+ .section .text_2,"ax",%progbits
+#else
+ .section .text_2,"ax",@progbits
+#endif
+
+ .global bar
+bar:
+ nop
+
+#ifdef __arm__
+ .section .note.GNU-stack,"",%progbits
+#else
+ .section .note.GNU-stack,"",@progbits
+#endif
diff --git a/gdb/testsuite/gdb.tui/scroll-back.exp b/gdb/testsuite/gdb.tui/scroll-back.exp
new file mode 100644
index 00000000000..76eb66eafca
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/scroll-back.exp
@@ -0,0 +1,89 @@
+# Copyright 2026 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/>.
+
+# Setup TUI such that the first instruction in the disassembly window is the
+# start of a section. Then scroll back to the last instruction of the
+# previous section. ATM this won't work if there's a section hole.
+#
+# The .S file tries to make sure that there's no section hole, but AFAIU that
+# can't be guaranteed. If this test-case detects a section hole, it bails
+# out with unsupported.
+#
+# The .S file is odd in the sense that the "previous section" doesn't contain
+# any symbols. This is done to trigger a different path in
+# tui_find_backward_disassembly_start_address.
+
+# This test-case uses two extra text sections. This is not supported on cygwin.
+require {!istarget *-*-cygwin*}
+
+tuiterm_env
+
+standard_testfile scroll-back.S
+
+if {[build_executable "failed to prepare" $testfile $srcfile \
+ {nodebug}] == -1} {
+ return
+}
+
+Term::clean_restart 24 80 $testfile
+if {![Term::prepare_for_tui]} {
+ unsupported "TUI not supported"
+ return
+}
+
+set re_no_hole \
+ [subst_vars \
+ {$hex:\s+$hex}]
+set re_hole \
+ [subst_vars \
+ {$hex:\s+Cannot access memory at address $hex}]
+
+set section_hole -1
+gdb_test_multiple "x /cx bar-1" "" {
+ -re -wrap $re_no_hole {
+ set section_hole 0
+ }
+ -re -wrap $re_hole {
+ set section_hole 1
+ }
+}
+
+if {$section_hole != 0} {
+ unsupported "require no section hole between .text_1 and .text_2"
+ return
+}
+
+gdb_assert {[Term::command_no_prompt_prefix "layout asm"] == 1}
+gdb_assert {[Term::command "disassemble bar"] == 1}
+
+set first_line_asm {1 1 78 1}
+Term::check_region_contents "first insn bar" {*}$first_line_asm \
+ [subst_vars \
+ {$hex\s+<bar>\s+nop}]
+
+# Send an up arrow.
+set esc "\033"
+set left_square_bracket "\["
+set csi "$esc$left_square_bracket"
+set cursor_up "${csi}A"
+send_gdb $cursor_up
+
+Term::dump_screen
+
+gdb_assert \
+ {[Term::wait_for_region_contents {*}$first_line_asm \
+ [subst_vars \
+ {$hex\s+nop}]]} \
+ "last insn foo"
diff --git a/gdb/tui/tui-disasm.c b/gdb/tui/tui-disasm.c
index 7dcb59e6264..1a1866003dd 100644
--- a/gdb/tui/tui-disasm.c
+++ b/gdb/tui/tui-disasm.c
@@ -177,9 +177,9 @@ tui_find_backward_disassembly_start_address (CORE_ADDR addr)
else if (msym_prev.minsym != nullptr)
return msym_prev.value_address ();
- /* Find the section that ADDR is in, and look for the start of the
- section. */
- struct obj_section *section = find_pc_section (addr);
+ /* Find the first section with start address before ADDR, and use its start
+ address. */
+ struct obj_section *section = find_pc_section (addr - 1);
if (section != NULL)
return section->addr ();
base-commit: dd41575147933228c3996204b68c6c6e6ed3d9e8
--
2.51.0
reply other threads:[~2026-09-19 16:00 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260919155948.1356120-1-tdevries@suse.de \
--to=tdevries@suse.de \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox