]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: specify sh pointer register types
authorSébastien Michelland <sebastien.michelland@lcis.grenoble-inp.fr>
Mon, 1 Apr 2024 09:55:53 +0000 (11:55 +0200)
committerSimon Marchi <simon.marchi@polymtl.ca>
Fri, 26 Apr 2024 13:48:12 +0000 (09:48 -0400)
This patch fixes a pretty funny issue on sh targets that occurred
because $pc (and similar registers) were typed as int. When $pc is in
the upper half of the address space (i.e. kernel code on sh), `x/i $pc'
would resolve to a negative value. At least in the case of a remote
target with an Xfer memory map, this leads to a spurious "cannot access
memory" error as negative addresses are out of bounds.

(gdb) x/i $pc
    0x8c202c04:    Cannot access memory at address 0x8c202c04
(gdb) x/i 0x8c202c04
=> 0x8c202c04 <gintctl_gint_gdb+304>:    mov.l    @r1,r10

The issue is fixed by specifying pointer types for pc and other pointer
registers. Code pointer registers on sh include pc, pr (return address
of a call), vbr (interrupt handler) and spc (return address after
interrupt). Data pointers include r15 (stack pointer) and gbr (base
register for a few specific addressing modes).

Change-Id: I043a058f7cbc6494f380dc0461616a9f3e0d87e0
Approved-By: Simon Marchi <simon.marchi@efficios.com>
gdb/sh-tdep.c

index 0a3b50702d9506cc47eb03bf0562a30a749b2fcd..0dbb905f1db3646b1ce0f5d95551173ea0784dec 100644 (file)
@@ -1401,6 +1401,11 @@ sh_sh2a_register_type (struct gdbarch *gdbarch, int reg_nr)
     return builtin_type (gdbarch)->builtin_float;
   else if (reg_nr >= DR0_REGNUM && reg_nr <= DR_LAST_REGNUM)
     return builtin_type (gdbarch)->builtin_double;
+  else if (reg_nr == PC_REGNUM || reg_nr == PR_REGNUM || reg_nr == VBR_REGNUM
+          || reg_nr == SPC_REGNUM)
+    return builtin_type (gdbarch)->builtin_func_ptr;
+  else if (reg_nr == R0_REGNUM + 15 || reg_nr == GBR_REGNUM)
+    return builtin_type (gdbarch)->builtin_data_ptr;
   else
     return builtin_type (gdbarch)->builtin_int;
 }
@@ -1413,6 +1418,11 @@ sh_sh3e_register_type (struct gdbarch *gdbarch, int reg_nr)
   if ((reg_nr >= gdbarch_fp0_regnum (gdbarch)
        && (reg_nr <= FP_LAST_REGNUM)) || (reg_nr == FPUL_REGNUM))
     return builtin_type (gdbarch)->builtin_float;
+  else if (reg_nr == PC_REGNUM || reg_nr == PR_REGNUM || reg_nr == VBR_REGNUM
+          || reg_nr == SPC_REGNUM)
+    return builtin_type (gdbarch)->builtin_func_ptr;
+  else if (reg_nr == R0_REGNUM + 15 || reg_nr == GBR_REGNUM)
+    return builtin_type (gdbarch)->builtin_data_ptr;
   else
     return builtin_type (gdbarch)->builtin_int;
 }
@@ -1434,6 +1444,11 @@ sh_sh4_register_type (struct gdbarch *gdbarch, int reg_nr)
     return builtin_type (gdbarch)->builtin_double;
   else if (reg_nr >= FV0_REGNUM && reg_nr <= FV_LAST_REGNUM)
     return sh_sh4_build_float_register_type (gdbarch, 3);
+  else if (reg_nr == PC_REGNUM || reg_nr == PR_REGNUM || reg_nr == VBR_REGNUM
+          || reg_nr == SPC_REGNUM)
+    return builtin_type (gdbarch)->builtin_func_ptr;
+  else if (reg_nr == R0_REGNUM + 15 || reg_nr == GBR_REGNUM)
+    return builtin_type (gdbarch)->builtin_data_ptr;
   else
     return builtin_type (gdbarch)->builtin_int;
 }
@@ -1441,7 +1456,13 @@ sh_sh4_register_type (struct gdbarch *gdbarch, int reg_nr)
 static struct type *
 sh_default_register_type (struct gdbarch *gdbarch, int reg_nr)
 {
-  return builtin_type (gdbarch)->builtin_int;
+  if (reg_nr == PC_REGNUM || reg_nr == PR_REGNUM || reg_nr == VBR_REGNUM
+      || reg_nr == SPC_REGNUM)
+    return builtin_type (gdbarch)->builtin_func_ptr;
+  else if (reg_nr == R0_REGNUM + 15 || reg_nr == GBR_REGNUM)
+    return builtin_type (gdbarch)->builtin_data_ptr;
+  else
+    return builtin_type (gdbarch)->builtin_int;
 }
 
 /* Is a register in a reggroup?