Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Tom de Vries <tdevries@suse.de>
To: gdb-patches@sourceware.org
Subject: [PATCH v4 10/11] [gdb] Don't stop disassembly at section hole
Date: Wed,  7 Oct 2026 11:40:56 +0200	[thread overview]
Message-ID: <20261007094057.1811886-11-tdevries@suse.de> (raw)
In-Reply-To: <20261007094057.1811886-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.

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.

Without the "Fix buglet in tui_find_disassembly_address" patch in this series,
this patch regresses as follows:
...
FAIL: gdb.tui/tui-layout-asm-short-prog.exp: check first line is back
...

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34399
---
 gdb/disasm.c         | 44 ++++++++++++++++++++++++++++++++++++++++++--
 gdb/disasm.h         |  8 ++++++++
 gdb/tui/tui-disasm.c | 42 ++++++++++++++++++++++++++++++++----------
 3 files changed, 82 insertions(+), 12 deletions(-)

diff --git a/gdb/disasm.c b/gdb/disasm.c
index 23d0c880777..e847e3ee0ff 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -1185,6 +1185,37 @@ gdb_disassembly_1 (struct gdbarch *gdbarch, struct ui_out *uiout,
 
 /* See disasm.h.  */
 
+bool
+disassemble_section_p (addrmap_mutable &map,
+		       struct obj_section *s, CORE_ADDR range_low,
+		       CORE_ADDR range_high)
+{
+  if (s == nullptr)
+    {
+      struct obj_section *prev = (range_low == 0
+				  ? nullptr
+				  : (obj_section *)map.find (range_low - 1));
+      struct obj_section *next = (range_high == (CORE_ADDR)-1
+				  ? nullptr
+				  : (obj_section *)map.find (range_high + 1));
+      bool section_hole
+	= (prev != nullptr && next != nullptr
+	   && prev->objfile == next->objfile);
+      if (section_hole)
+	{
+	  /* Don't disassemble if it would trigger a memory error.  */
+	  return target_has_registers ();
+	}
+
+      /* Random memory not in a section; might contain JIT-ed instructions.  */
+      return true;
+    }
+
+  return true;
+}
+
+/* See disasm.h.  */
+
 int
 gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
 		 gdb_disassembly_flags flags, int how_many,
@@ -1197,8 +1228,17 @@ 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
+	= (obj_section *)map->find (low, &range_low, &range_high);
+      if (!disassemble_section_p (*map, s, range_low, range_high))
+	{
+	  if (range_high == (CORE_ADDR)-1)
+	    break;
+
+	  low = range_high + 1;
+	  continue;
+	}
 
       /* Don't disassemble past a section change.  */
       if (range_high != (CORE_ADDR)-1)
diff --git a/gdb/disasm.h b/gdb/disasm.h
index 9109dbf0a79..0366de8f673 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,13 @@ struct disasm_insn
   unsigned int is_speculative:1;
 };
 
+/* Return true if memory in [RANGE_LOW, RANGE_HIGH] should be disassembled.
+   S is either the corresponding section, or nullptr if the range doesn't
+   match a section.  */
+
+extern bool disassemble_section_p (addrmap_mutable &map, struct obj_section *s,
+				   CORE_ADDR range_low, CORE_ADDR range_high);
+
 /* Print at most HOW_MANY instructions of the instruction stream at
    [LOW, HIGH) on UIOUT using FLAGS.  Return the number of the instructions
    printed.  */
diff --git a/gdb/tui/tui-disasm.c b/gdb/tui/tui-disasm.c
index ba11b8e8188..09136b6fc60 100644
--- a/gdb/tui/tui-disasm.c
+++ b/gdb/tui/tui-disasm.c
@@ -179,8 +179,17 @@ 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);
+      if (!disassemble_section_p (map, s, range_low, range_high))
+	{
+	  if (range_high == (CORE_ADDR)-1)
+	    break;
+
+	  pc = range_high + 1;
+	  continue;
+	}
 
       /* Don't disassemble past a section change.  */
       std::optional<CORE_ADDR> high_pc;
@@ -206,17 +215,34 @@ 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)
     {
       /* We cannot go backwards from zero.  */
       return addr;
     }
+  CORE_ADDR search_addr = addr - 1;
+
+  struct obj_section *s = nullptr;
+  CORE_ADDR range_low, range_high;
+  while (true)
+    {
+      s = (struct obj_section *)map.find (search_addr, &range_low,
+					  &range_high);
+
+      if (disassemble_section_p (map, s, range_low, range_high))
+	break;
+
+      if (range_low == 0)
+	return addr;
+
+      search_addr = range_low - 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 (search_addr, nullptr,
 					   lookup_msym_prefer::TEXT,
 					   &msym_prev);
   if (msym.minsym != nullptr)
@@ -226,11 +252,7 @@ tui_find_backward_disassembly_start_address (CORE_ADDR 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 ();
-
-  return addr;
+  return range_low;
 }
 
 /* Find the disassembly address that corresponds to FROM lines above
@@ -292,7 +314,7 @@ tui_find_disassembly_address (struct gdbarch *gdbarch, CORE_ADDR pc, int from)
       CORE_ADDR prev_low = new_low;
 
       /* Find an address from which we can start disassembling.  */
-      new_low = tui_find_backward_disassembly_start_address (new_low);
+      new_low = tui_find_backward_disassembly_start_address (*map, new_low);
       if (new_low == prev_low)
 	break;
 
-- 
2.51.0


  parent reply	other threads:[~2026-10-07  9:43 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-07  9:40 [PATCH v4 00/11] [gdb/tui] Some section hole handling fixes Tom de Vries
2026-10-07  9:40 ` [PATCH v4 01/11] [gdb/tui] Use early exit in tui_find_disassembly_address Tom de Vries
2026-10-07  9:40 ` [PATCH v4 02/11] [gdb/tui] Make low_prev loop-local " Tom de Vries
2026-10-07  9:40 ` [PATCH v4 03/11] [gdb/tui] Disassemble less often " Tom de Vries
2026-10-07  9:40 ` [PATCH v4 04/11] [gdb/tui] Fix buglet " Tom de Vries
2026-10-07  9:40 ` [PATCH v4 05/11] [gdb] Factor out update_section_map Tom de Vries
2026-10-07  9:40 ` [PATCH v4 06/11] [gdb] Add section_addrmap Tom de Vries
2026-10-07  9:40 ` [PATCH v4 07/11] [gdb] Extend addrmap::find with low/high results Tom de Vries
2026-10-07  9:40 ` [PATCH v4 08/11] [gdb] Make gdb_disassembly return number of insns Tom de Vries
2026-10-07  9:40 ` [PATCH v4 09/11] [gdb] Handle sections when disassembling Tom de Vries
2026-10-07  9:40 ` Tom de Vries [this message]
2026-10-07  9:40 ` [PATCH v4 11/11] [RFC, gdb/tui] Don't scroll into non-code sections Tom de Vries

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=20261007094057.1811886-11-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