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 11/11] [RFC, gdb/tui] Don't scroll into non-code sections
Date: Wed,  7 Oct 2026 11:40:57 +0200	[thread overview]
Message-ID: <20261007094057.1811886-12-tdevries@suse.de> (raw)
In-Reply-To: <20261007094057.1811886-1-tdevries@suse.de>

We can disassemble a data section using objdump -D:
...
Disassembly of section .rodata:

0000000000402000 <_IO_stdin_used>:
  402000:       01 00                   add    %eax,(%rax)
  402002:       02 00                   add    (%rax),%al
  402004:       68 65 6c 6c 6f          push   $0x6f6c6c65
        ...
...
and likewise using gdb:
...
(gdb) disassemble 0x0000000000402000,0x000000000040200c
Dump of assembler code from 0x402000 to 0x40200c:
   0x0000000000402000 <_IO_stdin_used+0>:	add    %eax,(%rax)
   0x0000000000402002 <_IO_stdin_used+2>:	add    (%rax),%al
   0x0000000000402004:	push   $0x6f6c6c65
   0x0000000000402009:	.byte 0
End of assembler dump.
...

Generally it's not useful to do this, so we could skip such sections during
disassembling, but OTOH the user may explicitly ask for it using a disassemble command.

Fix this by:
- propagating an explicit_p parameter to disassemble_section_p, and
- returning false in disassemble_section_p for data sections not explicitly
  requested.

I tested this by disassembling .rodata and then scrolling up.

This triggered an assert, which I fixed with some extra code in
tui_find_disassembly_address:
...
 	/* If there are some problems while disassembling exit.  */
 	if (next_addr <= old_next_addr)
 	  return pc;
+	if (next_addr > pc)
+	  break;
 	gdb_assert (single_asm_line.size () == 1);
...

Concretely what happens, if you disassembly .rodata and:
- scroll up, you get the last instruction of the text section
- scroll down, you get an empty screen, and a subsequent scroll
  up gets the last instruction of the text section

I'm not terribly happy with this behavior, hence this is an RFC.

But perhaps this is cornercase enough to be acceptable behavior.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34604
---
 gdb/cli/cli-cmds.c      | 11 ++++++-----
 gdb/disasm.c            | 13 ++++++++++---
 gdb/disasm.h            |  6 ++++--
 gdb/tui/tui-disasm.c    | 12 ++++++++----
 gdb/tui/tui-disasm.h    |  3 ++-
 gdb/tui/tui-source.c    |  2 +-
 gdb/tui/tui-source.h    |  3 ++-
 gdb/tui/tui-winsource.c | 13 +++++++------
 gdb/tui/tui-winsource.h | 12 ++++++++----
 gdb/tui/tui.c           |  4 ++--
 gdb/tui/tui.h           |  3 ++-
 11 files changed, 52 insertions(+), 30 deletions(-)

diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 8a85c813277..c119ca9a3df 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -1583,11 +1583,11 @@ static void
 print_disassembly (struct gdbarch *gdbarch, const char *name,
 		   CORE_ADDR low, CORE_ADDR high,
 		   const struct block *block,
-		   gdb_disassembly_flags flags)
+		   gdb_disassembly_flags flags, bool explicit_p = false)
 {
 #if defined(TUI)
   if (tui_is_window_visible (DISASSEM_WIN))
-    tui_show_assembly (gdbarch, low);
+    tui_show_assembly (gdbarch, low, explicit_p);
   else
 #endif
     {
@@ -1605,7 +1605,8 @@ print_disassembly (struct gdbarch *gdbarch, const char *name,
 				       paddress (gdbarch, high)));
 
 	  /* Dump the specified range.  */
-	  gdb_disassembly (gdbarch, current_uiout, flags, -1, low, high);
+	  gdb_disassembly (gdbarch, current_uiout, flags, -1, low, high,
+			   explicit_p);
 	}
       else
 	{
@@ -1620,7 +1621,7 @@ print_disassembly (struct gdbarch *gdbarch, const char *name,
 			  styled_string (address_style.style (),
 					 paddress (gdbarch, range_high)));
 	      gdb_disassembly (gdbarch, current_uiout, flags, -1,
-			       range_low, range_high);
+			       range_low, range_high, explicit_p);
 	    }
 	}
       gdb_printf (_("End of assembler dump.\n"));
@@ -1787,7 +1788,7 @@ disassemble_command (const char *arg, int from_tty)
 	high += low;
     }
 
-  print_disassembly (gdbarch, name, low, high, block, flags);
+  print_disassembly (gdbarch, name, low, high, block, flags, true);
 }
 
 /* Command completion for the disassemble command.  */
diff --git a/gdb/disasm.c b/gdb/disasm.c
index e847e3ee0ff..bf40e50acae 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -1188,7 +1188,7 @@ gdb_disassembly_1 (struct gdbarch *gdbarch, struct ui_out *uiout,
 bool
 disassemble_section_p (addrmap_mutable &map,
 		       struct obj_section *s, CORE_ADDR range_low,
-		       CORE_ADDR range_high)
+		       CORE_ADDR range_high, bool explicit_p)
 {
   if (s == nullptr)
     {
@@ -1211,6 +1211,13 @@ disassemble_section_p (addrmap_mutable &map,
       return true;
     }
 
+  if (!explicit_p)
+    {
+      /* When not explicitly required, skip over non-code sections.  */
+      return (s->the_bfd_section->flags & SEC_CODE) != 0;
+    }
+
+  /* Explicitly requested, allow any section.  */
   return true;
 }
 
@@ -1219,7 +1226,7 @@ disassemble_section_p (addrmap_mutable &map,
 int
 gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
 		 gdb_disassembly_flags flags, int how_many,
-		 CORE_ADDR low, CORE_ADDR high)
+		 CORE_ADDR low, CORE_ADDR high, bool explicit_p)
 {
   std::unique_ptr<addrmap_mutable> map = section_addrmap ();
   bool update_how_many = how_many != -1;
@@ -1231,7 +1238,7 @@ gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
       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 (!disassemble_section_p (*map, s, range_low, range_high, explicit_p))
 	{
 	  if (range_high == (CORE_ADDR)-1)
 	    break;
diff --git a/gdb/disasm.h b/gdb/disasm.h
index 0366de8f673..cb242c997ae 100644
--- a/gdb/disasm.h
+++ b/gdb/disasm.h
@@ -329,7 +329,8 @@ struct disasm_insn
    match a section.  */
 
 extern bool disassemble_section_p (addrmap_mutable &map, struct obj_section *s,
-				   CORE_ADDR range_low, CORE_ADDR range_high);
+				   CORE_ADDR range_low, CORE_ADDR range_high,
+				   bool explicit_p = false);
 
 /* Print at most HOW_MANY instructions of the instruction stream at
    [LOW, HIGH) on UIOUT using FLAGS.  Return the number of the instructions
@@ -337,7 +338,8 @@ extern bool disassemble_section_p (addrmap_mutable &map, struct obj_section *s,
 
 extern int gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
 			    gdb_disassembly_flags flags, int how_many,
-			    CORE_ADDR low, CORE_ADDR high);
+			    CORE_ADDR low, CORE_ADDR high,
+			    bool explicit_p = false);
 
 /* Print the instruction at address MEMADDR in debugged memory,
    on STREAM.  Returns the length of the instruction, in bytes,
diff --git a/gdb/tui/tui-disasm.c b/gdb/tui/tui-disasm.c
index 09136b6fc60..090ec484d05 100644
--- a/gdb/tui/tui-disasm.c
+++ b/gdb/tui/tui-disasm.c
@@ -172,7 +172,7 @@ static CORE_ADDR
 tui_disassemble (struct gdbarch *gdbarch,
 		 std::vector<tui_asm_line> &asm_lines,
 		 addrmap_mutable &map, CORE_ADDR pc, int count,
-		 size_t *addr_size = nullptr)
+		 size_t *addr_size = nullptr, bool explicit_p = false)
 {
   /* Must start with an empty list.  */
   asm_lines.clear ();
@@ -182,7 +182,7 @@ tui_disassemble (struct gdbarch *gdbarch,
       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 (!disassemble_section_p (map, s, range_low, range_high, explicit_p))
 	{
 	  if (range_high == (CORE_ADDR)-1)
 	    break;
@@ -379,6 +379,8 @@ tui_find_disassembly_address (struct gdbarch *gdbarch, CORE_ADDR pc, int from)
 	/* If there are some problems while disassembling exit.  */
 	if (next_addr <= old_next_addr)
 	  return pc;
+	if (next_addr > pc)
+	  break;
 	gdb_assert (single_asm_line.size () == 1);
 	asm_lines[pos] = single_asm_line[0];
       } while (next_addr <= pc);
@@ -397,7 +399,8 @@ tui_find_disassembly_address (struct gdbarch *gdbarch, CORE_ADDR pc, int from)
 /* Function to set the disassembly window's content.  */
 bool
 tui_disasm_window::set_contents (struct gdbarch *arch,
-				 const struct symtab_and_line &sal)
+				 const struct symtab_and_line &sal,
+				 bool explicit_p)
 {
   int i;
   int max_lines;
@@ -421,7 +424,8 @@ tui_disasm_window::set_contents (struct gdbarch *arch,
   std::vector<tui_asm_line> asm_lines;
   std::unique_ptr<addrmap_mutable> map = section_addrmap ();
   size_t addr_size = 0;
-  tui_disassemble (m_gdbarch, asm_lines, *map, pc, max_lines, &addr_size);
+  tui_disassemble (m_gdbarch, asm_lines, *map, pc, max_lines, &addr_size,
+		   explicit_p);
 
   /* Align instructions to the same column.  */
   insn_pos = (1 + (addr_size / tab_len)) * tab_len;
diff --git a/gdb/tui/tui-disasm.h b/gdb/tui/tui-disasm.h
index 46a974af2a6..43ab26d757e 100644
--- a/gdb/tui/tui-disasm.h
+++ b/gdb/tui/tui-disasm.h
@@ -57,7 +57,8 @@ struct tui_disasm_window : public tui_source_window_base
   void do_scroll_vertical (int num_to_scroll) override;
 
   bool set_contents (struct gdbarch *gdbarch,
-		     const struct symtab_and_line &sal) override;
+		     const struct symtab_and_line &sal,
+		     bool explicit_p = false) override;
 
 private:
   /* Answer whether a particular line number or address is displayed
diff --git a/gdb/tui/tui-source.c b/gdb/tui/tui-source.c
index 466e9972106..c34427b2a8d 100644
--- a/gdb/tui/tui-source.c
+++ b/gdb/tui/tui-source.c
@@ -50,7 +50,7 @@ tui_source_window::~tui_source_window ()
 /* Function to display source in the source window.  */
 bool
 tui_source_window::set_contents (struct gdbarch *arch,
-				 const struct symtab_and_line &sal)
+				 const struct symtab_and_line &sal, bool)
 {
   struct symtab *s = sal.symtab;
   int line_no = sal.line;
diff --git a/gdb/tui/tui-source.h b/gdb/tui/tui-source.h
index 95c28dbb0a3..1495762bcb2 100644
--- a/gdb/tui/tui-source.h
+++ b/gdb/tui/tui-source.h
@@ -65,7 +65,8 @@ struct tui_source_window : public tui_source_window_base
   void do_scroll_vertical (int num_to_scroll) override;
 
   bool set_contents (struct gdbarch *gdbarch,
-		     const struct symtab_and_line &sal) override;
+		     const struct symtab_and_line &sal,
+		     bool explicit_p) override;
 
   int extra_margin () const override
   {
diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
index c7149ff7c80..dbd3cbd8da6 100644
--- a/gdb/tui/tui-winsource.c
+++ b/gdb/tui/tui-winsource.c
@@ -147,10 +147,10 @@ tui_source_window_base::style_changed ()
 void
 tui_source_window_base::update_source_window
   (struct gdbarch *gdbarch,
-   const struct symtab_and_line &sal)
+   const struct symtab_and_line &sal, bool explicit_p)
 {
   m_horizontal_offset = 0;
-  update_source_window_as_is (gdbarch, sal);
+  update_source_window_as_is (gdbarch, sal, explicit_p);
 }
 
 
@@ -159,9 +159,9 @@ tui_source_window_base::update_source_window
 void
 tui_source_window_base::update_source_window_as_is
   (struct gdbarch *gdbarch,
-   const struct symtab_and_line &sal)
+   const struct symtab_and_line &sal, bool explicit_p)
 {
-  bool ret = set_contents (gdbarch, sal);
+  bool ret = set_contents (gdbarch, sal, explicit_p);
 
   if (!ret)
     erase_source_content ();
@@ -190,14 +190,15 @@ tui_source_window_base::update_source_window_with_addr (struct gdbarch *gdbarch,
 /* Function to ensure that the source and/or disassembly windows
    reflect the input address.  */
 void
-tui_update_source_windows_with_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
+tui_update_source_windows_with_addr (struct gdbarch *gdbarch, CORE_ADDR addr,
+				     bool explicit_p)
 {
   struct symtab_and_line sal {};
   if (addr != 0)
     sal = find_sal_for_pc (addr, 0);
 
   for (struct tui_source_window_base *win_info : tui_source_windows ())
-    win_info->update_source_window (gdbarch, sal);
+    win_info->update_source_window (gdbarch, sal, explicit_p);
 }
 
 /* Function to ensure that the source and/or disassembly windows
diff --git a/gdb/tui/tui-winsource.h b/gdb/tui/tui-winsource.h
index 533b159be9b..2c4f6f7fa5e 100644
--- a/gdb/tui/tui-winsource.h
+++ b/gdb/tui/tui-winsource.h
@@ -104,7 +104,8 @@ struct tui_source_window_base : public tui_win_info
   void do_erase_source_content (const char *string);
 
   virtual bool set_contents (struct gdbarch *gdbarch,
-			     const struct symtab_and_line &sal) = 0;
+			     const struct symtab_and_line &sal,
+			     bool explicit_p = false) = 0;
 
   /* Return the number of extra margin characters needed by this
      instance.  */
@@ -163,9 +164,11 @@ struct tui_source_window_base : public tui_win_info
   virtual void maybe_update (struct gdbarch *gdbarch, symtab_and_line sal) = 0;
 
   void update_source_window_as_is  (struct gdbarch *gdbarch,
-				    const struct symtab_and_line &sal);
+				    const struct symtab_and_line &sal,
+				    bool explicit_p = false);
   void update_source_window (struct gdbarch *gdbarch,
-			     const struct symtab_and_line &sal);
+			     const struct symtab_and_line &sal,
+			     bool explicit_p = false);
 
   /* Scan the source window and the breakpoints to update the
      break_mode information for each line.  Returns true if something
@@ -352,7 +355,8 @@ extern void tui_update_all_breakpoint_info (struct breakpoint *being_deleted);
 
 /* Function to display the "main" routine.  */
 extern void tui_display_main (void);
-extern void tui_update_source_windows_with_addr (struct gdbarch *, CORE_ADDR);
+extern void tui_update_source_windows_with_addr (struct gdbarch *, CORE_ADDR,
+						 bool = false);
 extern void tui_update_source_windows_with_line (struct symtab_and_line sal);
 
 /* Extract some source text from PTR.  Returns a string holding the
diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c
index a9a23f29b9a..51f17eb4a31 100644
--- a/gdb/tui/tui.c
+++ b/gdb/tui/tui.c
@@ -744,11 +744,11 @@ tui_disable_command (const char *args, int from_tty)
 }
 
 void
-tui_show_assembly (struct gdbarch *gdbarch, CORE_ADDR addr)
+tui_show_assembly (struct gdbarch *gdbarch, CORE_ADDR addr, bool explicit_p)
 {
   tui_batch_rendering suppress;
   tui_add_win_to_layout (DISASSEM_WIN);
-  tui_update_source_windows_with_addr (gdbarch, addr);
+  tui_update_source_windows_with_addr (gdbarch, addr, explicit_p);
 }
 
 bool
diff --git a/gdb/tui/tui.h b/gdb/tui/tui.h
index b24fed2b322..c55dbd9ee32 100644
--- a/gdb/tui/tui.h
+++ b/gdb/tui/tui.h
@@ -60,7 +60,8 @@ enum tui_win_type
 
 extern CORE_ADDR tui_get_low_disassembly_address (struct gdbarch *,
 						  CORE_ADDR, CORE_ADDR);
-extern void tui_show_assembly (struct gdbarch *gdbarch, CORE_ADDR addr);
+extern void tui_show_assembly (struct gdbarch *gdbarch, CORE_ADDR addr,
+			       bool explicit_p = false);
 extern bool tui_is_window_visible (enum tui_win_type type);
 extern bool tui_get_command_dimension (unsigned int *width,
 				       unsigned int *height);
-- 
2.51.0


      parent reply	other threads:[~2026-10-07  9:44 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 ` [PATCH v4 10/11] [gdb] Don't stop disassembly at section hole Tom de Vries
2026-10-07  9:40 ` 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=20261007094057.1811886-12-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