]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: use builtin_func_ptr for `$_` set by "x/i"
authorTankut Baris Aktemur <tankut.baris.aktemur@intel.com>
Thu, 5 Mar 2026 15:07:54 +0000 (16:07 +0100)
committerTankut Baris Aktemur <tankut.baris.aktemur@intel.com>
Thu, 5 Mar 2026 15:08:24 +0000 (16:08 +0100)
The 'x' command with the 'i' format specifier is for displaying
instructions.  The "last address examined" convenience var, that is
'$_', is set to a single byte pointer by "x/i":

  (gdb) p $pc
  $1 = (void (*)()) 0x5555555551d4 <main+15>
  (gdb) x/i $pc
  => 0x5555555551d4 <main+15>:    movl   $0x2a,-0x4(%rbp)
  (gdb) p $_
  $2 = (int8_t *) 0x5555555551d4 <main+15>
  (gdb)

However, because "x/i" is for displaying instructions, it makes more
sense to give '$_' a code pointer type, which is done by this patch:

  (gdb) p $pc
  $1 = (void (*)()) 0x5555555551d4 <main+15>
  (gdb) x/i $pc
  => 0x5555555551d4 <main+15>:    movl   $0x2a,-0x4(%rbp)
  (gdb) p $_
  $2 = (void (*)()) 0x5555555551d4 <main+15>
  (gdb)

This is a minor user experience improvement and should not change
functionality.

Reviewed-By: Keith Seitz <keiths@redhat.com>
Approved-By: Tom Tromey <tom@tromey.com>
gdb/printcmd.c
gdb/testsuite/gdb.base/gdbvars.exp

index f637bccc58ab7b417d3c09652d69f6a25b04c59f..d7abbcc499b122b5f86ee2b77c966e8f9abf6fc1 100644 (file)
@@ -1013,13 +1013,6 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
   next_gdbarch = gdbarch;
   next_address = addr;
 
-  /* Instruction format implies fetch single bytes
-     regardless of the specified size.
-     The case of strings is handled in decode_format, only explicit
-     size operator are not changed to 'b'.  */
-  if (format == 'i')
-    size = 'b';
-
   if (size == 'a')
     {
       /* Pick the appropriate size for an address.  */
@@ -1065,6 +1058,17 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
        }
     }
 
+  /* For the instruction format, arbitrarily pick single byte as the
+     SIZE; how much we fetch is determined by the disassembler anyway.
+     Use the builtin function type for the value type, so that the
+     convenience var $_ becomes a code pointer after "x/i".  */
+  if (format == 'i')
+    {
+      size = 'b';
+      val_type
+       = builtin_type (next_gdbarch)->builtin_func_ptr->target_type ();
+    }
+
   maxelts = 8;
   if (size == 'w')
     maxelts = 4;
index b9a5f1078c403a7bd01217081f11d44c802a59da..1768b36c8b64eea8acd8d6d9d1d8e6c4f1add897 100644 (file)
@@ -61,6 +61,16 @@ proc test_convenience_variables {} {
     gdb_test "print \$_" "= $re_fptr $::hex.*" \
        "convenience var \$_ is set to an address again"
 
+    # Test $_ after the 'x' command without and with '/i'.
+    gdb_test "x/1xb &main" "$::hex\[^\r\n\]+" \
+       "examine code with x/b"
+    gdb_test "print \$_" "= \\(int8_t \\*\\) $::hex.*" \
+       "convenience var \$_ is set to a byte pointer"
+    gdb_test "x/i &main" "$::hex\[^\r\n\]+" \
+       "examine code with x/i"
+    gdb_test "print \$_" "= $re_fptr $::hex.*" \
+       "convenience var \$_ is set to an address after x/i"
+
     gdb_test "print \$foo + 10"        " = 311" \
        "use convenience variable in arithmetic expression"