From: Tom de Vries <tdevries@suse.de>
To: gdb-patches@sourceware.org
Subject: [PATCH v3 5/5] [gdb] Don't stop disassembly at section hole
Date: Mon, 21 Sep 2026 22:55:57 +0200 [thread overview]
Message-ID: <20260921205557.2706300-6-tdevries@suse.de> (raw)
In-Reply-To: <20260921205557.2706300-1-tdevries@suse.de>
Consider the following session:
...
$ gdb -q -batch a.out -ex "disassemble _init,0x0000000000401030"
Dump of assembler code from 0x401000 to 0x401030:
...
0x000000000040101a <_init+26>: ret
0x000000000040101b:
Cannot access memory at address 0x40101b
...
If we disassemble with objdump instead, we get:
...
Disassembly of section .init:
0000000000401000 <_init>:
...
40101a: c3 ret
Disassembly of section .plt:
0000000000401020 <puts@plt-0x10>:
401020: ff 35 ca 2f 00 00 push 0x2fca(%rip)
401026: ff 25 cc 2f 00 00 jmp *0x2fcc(%rip)
40102c: 0f 1f 40 00 nopl 0x0(%rax)
...
The disassembling stops at the section hole, when running into a memory error.
Note that we don't run into this memory error with a live inferior, as
demonstrated in the previous patch.
Fix this by if necessary skipping over the section hole.
This also fixes the paradoxical situation reported in PR34399 where it's
possible to scroll forward into a section hole, but not back out of it.
This also contains a small fix in tui_find_disassembly_address, to fix a
regression in gdb.tui/tui-layout-asm-short-prog.exp.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34399
---
gdb/disasm.c | 55 ++++++++++++++++++++++++++++++++++++++++++--
gdb/disasm.h | 14 +++++++++++
gdb/tui/tui-disasm.c | 39 ++++++++++++++++++++-----------
3 files changed, 93 insertions(+), 15 deletions(-)
diff --git a/gdb/disasm.c b/gdb/disasm.c
index 9e8334b065e..f0c642b2367 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -1182,6 +1182,53 @@ gdb_disassembly_1 (struct gdbarch *gdbarch, struct ui_out *uiout,
return num_displayed;
}
+/* See disasm.h. */
+
+CORE_ADDR
+disassemble_skip_sections (addrmap_mutable *map, CORE_ADDR pc,
+ struct obj_section *s, CORE_ADDR *range_low,
+ CORE_ADDR *range_high, int direction)
+{
+ if (s != nullptr)
+ return pc;
+
+ struct obj_section *prev = nullptr, *next = nullptr;
+ CORE_ADDR prev_low, prev_high;
+ if (*range_low != 0)
+ prev
+ = (struct obj_section *)map->find (*range_low-1, &prev_low, &prev_high);
+ CORE_ADDR next_low, next_high;
+ if (*range_high != (CORE_ADDR)-1)
+ next
+ = (struct obj_section *)map->find (*range_high+1, &next_low, &next_high);
+
+ bool section_hole
+ = prev != nullptr && next != nullptr && prev->objfile == next->objfile;
+ if (!section_hole)
+ return pc;
+
+ if (target_has_registers ())
+ {
+ /* Reading from the section hole doesn't trigger a memory error, so
+ don't skip it. */
+ return pc;
+ }
+
+ if (direction == 1)
+ {
+ *range_low = next_low;
+ *range_high = next_high;
+ return next_low;
+ }
+ else if (direction == -1)
+ {
+ *range_low = prev_low;
+ *range_high = prev_high;
+ return prev_high;
+ }
+ gdb_assert_not_reached ();
+}
+
void
gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
gdb_disassembly_flags flags, int how_many,
@@ -1194,8 +1241,12 @@ gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
{
CORE_ADDR tmp_high = high;
- CORE_ADDR range_high;
- map->find (low, nullptr, &range_high);
+ CORE_ADDR range_low, range_high;
+ struct obj_section *s
+ = (struct obj_section *)map->find (low, &range_low, &range_high);
+
+ low = disassemble_skip_sections (map.get (), low, s, &range_low,
+ &range_high);
/* Don't disassemble past a section change. */
if (range_high != (CORE_ADDR)-1)
diff --git a/gdb/disasm.h b/gdb/disasm.h
index 57195564ca8..c73f15c204d 100644
--- a/gdb/disasm.h
+++ b/gdb/disasm.h
@@ -26,6 +26,7 @@
struct gdbarch;
struct ui_out;
struct ui_file;
+struct addrmap_mutable;
/* A wrapper around a disassemble_info and a gdbarch. This is the core
set of data that all disassembler sub-classes will need. This class
@@ -323,6 +324,19 @@ struct disasm_insn
unsigned int is_speculative:1;
};
+
+/* For an attempt to disassemble PC in section S (which may be nullptr) and
+ range [RANGE_LOW, RANGE_HIGH], skip over S if needed.
+ If so, return an updated PC and [RANGE_LOW, RANGE_HIGH].
+ If DIRECTION == 1 disassemble forward, if DIRECTION == -1, disassemble
+ backward. */
+
+extern CORE_ADDR disassemble_skip_sections (addrmap_mutable *map, CORE_ADDR pc,
+ struct obj_section *s,
+ CORE_ADDR *range_low,
+ CORE_ADDR *range_high,
+ int direction = 1);
+
extern void gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
gdb_disassembly_flags flags, int how_many,
CORE_ADDR low, CORE_ADDR high);
diff --git a/gdb/tui/tui-disasm.c b/gdb/tui/tui-disasm.c
index 26afc4bd978..2cfc9c9e838 100644
--- a/gdb/tui/tui-disasm.c
+++ b/gdb/tui/tui-disasm.c
@@ -179,8 +179,13 @@ tui_disassemble (struct gdbarch *gdbarch,
while (count > 0)
{
- CORE_ADDR range_high;
- map->find (pc, nullptr, &range_high);
+ CORE_ADDR range_low, range_high;
+ struct obj_section *s
+ = (struct obj_section *)map->find (pc, &range_low, &range_high);
+
+ pc = disassemble_skip_sections (map.get (), pc, s, &range_low,
+ &range_high);
+
/* Don't disassemble past a section change. */
std::optional<CORE_ADDR> high_pc;
@@ -206,7 +211,8 @@ tui_disassemble (struct gdbarch *gdbarch,
addresses, or the start of a section. */
static CORE_ADDR
-tui_find_backward_disassembly_start_address (CORE_ADDR addr)
+tui_find_backward_disassembly_start_address (addrmap_mutable *map,
+ CORE_ADDR addr)
{
if (addr == 0)
{
@@ -214,9 +220,16 @@ tui_find_backward_disassembly_start_address (CORE_ADDR addr)
return addr;
}
+ CORE_ADDR range_low, range_high;
+ struct obj_section *s
+ = (struct obj_section *)map->find (addr - 1, &range_low, &range_high);
+
+ addr = disassemble_skip_sections (map, addr - 1, s, &range_low,
+ &range_high, -1);
+
bound_minimal_symbol msym_prev;
bound_minimal_symbol msym
- = lookup_minimal_symbol_by_pc_section (addr - 1, nullptr,
+ = lookup_minimal_symbol_by_pc_section (addr, nullptr,
lookup_msym_prefer::TEXT,
&msym_prev);
if (msym.minsym != nullptr)
@@ -224,13 +237,7 @@ tui_find_backward_disassembly_start_address (CORE_ADDR addr)
else if (msym_prev.minsym != nullptr)
return msym_prev.value_address ();
- /* 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 ();
-
- return addr;
+ return range_low;
}
/* Find the disassembly address that corresponds to FROM lines above
@@ -290,16 +297,22 @@ tui_find_disassembly_address (struct gdbarch *gdbarch, CORE_ADDR pc, int from)
different or not. */
CORE_ADDR prev_low;
+ std::unique_ptr<addrmap_mutable> map = section_addrmap ();
+
do
{
/* Find an address from which we can start disassembling. */
prev_low = new_low;
- new_low = tui_find_backward_disassembly_start_address (new_low);
+ new_low = tui_find_backward_disassembly_start_address (map.get (),
+ new_low);
/* Disassemble forward. */
next_addr = tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
if (asm_lines.empty ())
- break;
+ {
+ new_low = prev_low;
+ break;
+ }
last_addr = asm_lines.back ().addr;
/* If disassembling from the current value of NEW_LOW reached PC
--
2.51.0
prev parent reply other threads:[~2026-09-21 20:57 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-21 20:55 [PATCH v3 0/5] [gdb/tui] Some section hole handling fixes Tom de Vries
2026-09-21 20:55 ` [PATCH v3 1/5] [gdb] Factor out update_section_map Tom de Vries
2026-09-21 20:55 ` [PATCH v3 2/5] [gdb] Add section_addrmap Tom de Vries
2026-09-21 20:55 ` [PATCH v3 3/5] [gdb] Extend addrmap::find with low/high results Tom de Vries
2026-09-21 20:55 ` [PATCH v3 4/5] [gdb] Handle sections when disassembling Tom de Vries
2026-09-21 20:55 ` Tom de Vries [this message]
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=20260921205557.2706300-6-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