]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/sparc-linux-tdep.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / sparc-linux-tdep.c
index 02c4137a3b63ae051ec2eb8861bdef0e051f0a7f..5f9d3cb0246efab14bd047a13b59c030533da6a3 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for GNU/Linux SPARC.
 
-   Copyright (C) 2003-2013 Free Software Foundation, Inc.
+   Copyright (C) 2003-2023 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -18,7 +18,7 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
-#include "dwarf2-frame.h"
+#include "dwarf2/frame.h"
 #include "frame.h"
 #include "frame-unwind.h"
 #include "gdbtypes.h"
@@ -42,7 +42,7 @@
 /* Signal trampoline support.  */
 
 static void sparc32_linux_sigframe_init (const struct tramp_frame *self,
-                                        struct frame_info *this_frame,
+                                        frame_info_ptr this_frame,
                                         struct trad_frame_cache *this_cache,
                                         CORE_ADDR func);
 
@@ -68,9 +68,9 @@ static const struct tramp_frame sparc32_linux_sigframe =
   SIGTRAMP_FRAME,
   4,
   {
-    { 0x821020d8, -1 },                /* mov __NR_sugreturn, %g1 */
-    { 0x91d02010, -1 },                /* ta  0x10 */
-    { TRAMP_SENTINEL_INSN, -1 }
+    { 0x821020d8, ULONGEST_MAX },              /* mov __NR_sigreturn, %g1 */
+    { 0x91d02010, ULONGEST_MAX },              /* ta  0x10 */
+    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
   },
   sparc32_linux_sigframe_init
 };
@@ -83,16 +83,41 @@ static const struct tramp_frame sparc32_linux_rt_sigframe =
   SIGTRAMP_FRAME,
   4,
   {
-    { 0x82102065, -1 },                /* mov __NR_rt_sigreturn, %g1 */
-    { 0x91d02010, -1 },                /* ta  0x10 */
-    { TRAMP_SENTINEL_INSN, -1 }
+    { 0x82102065, ULONGEST_MAX },              /* mov __NR_rt_sigreturn, %g1 */
+    { 0x91d02010, ULONGEST_MAX },              /* ta  0x10 */
+    { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
   },
   sparc32_linux_sigframe_init
 };
 
+/* This enum represents the signals' numbers on the SPARC
+   architecture.  It just contains the signal definitions which are
+   different from the generic implementation.
+
+   It is derived from the file <arch/sparc/include/uapi/asm/signal.h>,
+   from the Linux kernel tree.  */
+
+enum
+  {
+    SPARC_LINUX_SIGEMT = 7,
+    SPARC_LINUX_SIGBUS = 10,
+    SPARC_LINUX_SIGSYS = 12,
+    SPARC_LINUX_SIGURG = 16,
+    SPARC_LINUX_SIGSTOP = 17,
+    SPARC_LINUX_SIGTSTP = 18,
+    SPARC_LINUX_SIGCONT = 19,
+    SPARC_LINUX_SIGCHLD = 20,
+    SPARC_LINUX_SIGIO = 23,
+    SPARC_LINUX_SIGPOLL = SPARC_LINUX_SIGIO,
+    SPARC_LINUX_SIGLOST = 29,
+    SPARC_LINUX_SIGPWR = SPARC_LINUX_SIGLOST,
+    SPARC_LINUX_SIGUSR1 = 30,
+    SPARC_LINUX_SIGUSR2 = 31,
+  };
+
 static void
 sparc32_linux_sigframe_init (const struct tramp_frame *self,
-                            struct frame_info *this_frame,
+                            frame_info_ptr this_frame,
                             struct trad_frame_cache *this_cache,
                             CORE_ADDR func)
 {
@@ -134,7 +159,7 @@ sparc32_linux_sigframe_init (const struct tramp_frame *self,
    address.  */
 
 static CORE_ADDR
-sparc32_linux_step_trap (struct frame_info *frame, unsigned long insn)
+sparc32_linux_step_trap (frame_info_ptr frame, unsigned long insn)
 {
   if (insn == 0x91d02010)
     {
@@ -173,7 +198,7 @@ sparc32_linux_step_trap (struct frame_info *frame, unsigned long insn)
 }
 \f
 
-const struct sparc_gregset sparc32_linux_core_gregset =
+const struct sparc_gregmap sparc32_linux_core_gregmap =
 {
   32 * 4,                      /* %psr */
   33 * 4,                      /* %pc */
@@ -192,7 +217,7 @@ sparc32_linux_supply_core_gregset (const struct regset *regset,
                                   struct regcache *regcache,
                                   int regnum, const void *gregs, size_t len)
 {
-  sparc32_supply_gregset (&sparc32_linux_core_gregset,
+  sparc32_supply_gregset (&sparc32_linux_core_gregmap,
                          regcache, regnum, gregs);
 }
 
@@ -201,7 +226,7 @@ sparc32_linux_collect_core_gregset (const struct regset *regset,
                                    const struct regcache *regcache,
                                    int regnum, void *gregs, size_t len)
 {
-  sparc32_collect_gregset (&sparc32_linux_core_gregset,
+  sparc32_collect_gregset (&sparc32_linux_core_gregmap,
                           regcache, regnum, gregs);
 }
 
@@ -210,7 +235,7 @@ sparc32_linux_supply_core_fpregset (const struct regset *regset,
                                    struct regcache *regcache,
                                    int regnum, const void *fpregs, size_t len)
 {
-  sparc32_supply_fpregset (&sparc32_bsd_fpregset, regcache, regnum, fpregs);
+  sparc32_supply_fpregset (&sparc32_bsd_fpregmap, regcache, regnum, fpregs);
 }
 
 static void
@@ -218,7 +243,7 @@ sparc32_linux_collect_core_fpregset (const struct regset *regset,
                                     const struct regcache *regcache,
                                     int regnum, void *fpregs, size_t len)
 {
-  sparc32_collect_fpregset (&sparc32_bsd_fpregset, regcache, regnum, fpregs);
+  sparc32_collect_fpregset (&sparc32_bsd_fpregmap, regcache, regnum, fpregs);
 }
 
 /* Set the program counter for process PTID to PC.  */
@@ -228,7 +253,8 @@ sparc32_linux_collect_core_fpregset (const struct regset *regset,
 static void
 sparc_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+  gdbarch *arch = regcache->arch ();
+  sparc_gdbarch_tdep *tdep = gdbarch_tdep<sparc_gdbarch_tdep> (arch);
   ULONGEST psr;
 
   regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc);
@@ -249,9 +275,9 @@ sparc_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
 
 static LONGEST
 sparc32_linux_get_syscall_number (struct gdbarch *gdbarch,
-                                 ptid_t ptid)
+                                 thread_info *thread)
 {
-  struct regcache *regcache = get_thread_regcache (ptid);
+  struct regcache *regcache = get_thread_regcache (thread);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   /* The content of a register.  */
   gdb_byte buf[4];
@@ -261,28 +287,148 @@ sparc32_linux_get_syscall_number (struct gdbarch *gdbarch,
   /* Getting the system call number from the register.
      When dealing with the sparc architecture, this information
      is stored at the %g1 register.  */
-  regcache_cooked_read (regcache, SPARC_G1_REGNUM, buf);
+  regcache->cooked_read (SPARC_G1_REGNUM, buf);
 
   ret = extract_signed_integer (buf, 4, byte_order);
 
   return ret;
 }
 
+/* Implementation of `gdbarch_gdb_signal_from_target', as defined in
+   gdbarch.h.  */
+
+static enum gdb_signal
+sparc32_linux_gdb_signal_from_target (struct gdbarch *gdbarch,
+                                     int signal)
+{
+  switch (signal)
+    {
+    case SPARC_LINUX_SIGEMT:
+      return GDB_SIGNAL_EMT;
+
+    case SPARC_LINUX_SIGBUS:
+      return GDB_SIGNAL_BUS;
+
+    case SPARC_LINUX_SIGSYS:
+      return GDB_SIGNAL_SYS;
+
+    case SPARC_LINUX_SIGURG:
+      return GDB_SIGNAL_URG;
+
+    case SPARC_LINUX_SIGSTOP:
+      return GDB_SIGNAL_STOP;
+
+    case SPARC_LINUX_SIGTSTP:
+      return GDB_SIGNAL_TSTP;
+
+    case SPARC_LINUX_SIGCONT:
+      return GDB_SIGNAL_CONT;
+
+    case SPARC_LINUX_SIGCHLD:
+      return GDB_SIGNAL_CHLD;
+
+    /* No way to differentiate between SIGIO and SIGPOLL.
+       Therefore, we just handle the first one.  */
+    case SPARC_LINUX_SIGIO:
+      return GDB_SIGNAL_IO;
+
+    /* No way to differentiate between SIGLOST and SIGPWR.
+       Therefore, we just handle the first one.  */
+    case SPARC_LINUX_SIGLOST:
+      return GDB_SIGNAL_LOST;
+
+    case SPARC_LINUX_SIGUSR1:
+      return GDB_SIGNAL_USR1;
+
+    case SPARC_LINUX_SIGUSR2:
+      return GDB_SIGNAL_USR2;
+    }
+
+  return linux_gdb_signal_from_target (gdbarch, signal);
+}
+
+/* Implementation of `gdbarch_gdb_signal_to_target', as defined in
+   gdbarch.h.  */
+
+static int
+sparc32_linux_gdb_signal_to_target (struct gdbarch *gdbarch,
+                                   enum gdb_signal signal)
+{
+  switch (signal)
+    {
+    case GDB_SIGNAL_EMT:
+      return SPARC_LINUX_SIGEMT;
+
+    case GDB_SIGNAL_BUS:
+      return SPARC_LINUX_SIGBUS;
+
+    case GDB_SIGNAL_SYS:
+      return SPARC_LINUX_SIGSYS;
+
+    case GDB_SIGNAL_URG:
+      return SPARC_LINUX_SIGURG;
+
+    case GDB_SIGNAL_STOP:
+      return SPARC_LINUX_SIGSTOP;
+
+    case GDB_SIGNAL_TSTP:
+      return SPARC_LINUX_SIGTSTP;
+
+    case GDB_SIGNAL_CONT:
+      return SPARC_LINUX_SIGCONT;
+
+    case GDB_SIGNAL_CHLD:
+      return SPARC_LINUX_SIGCHLD;
+
+    case GDB_SIGNAL_IO:
+      return SPARC_LINUX_SIGIO;
+
+    case GDB_SIGNAL_POLL:
+      return SPARC_LINUX_SIGPOLL;
+
+    case GDB_SIGNAL_LOST:
+      return SPARC_LINUX_SIGLOST;
+
+    case GDB_SIGNAL_PWR:
+      return SPARC_LINUX_SIGPWR;
+
+    case GDB_SIGNAL_USR1:
+      return SPARC_LINUX_SIGUSR1;
+
+    case GDB_SIGNAL_USR2:
+      return SPARC_LINUX_SIGUSR2;
+    }
+
+  return linux_gdb_signal_to_target (gdbarch, signal);
+}
+
 \f
 
+static const struct regset sparc32_linux_gregset =
+  {
+    NULL,
+    sparc32_linux_supply_core_gregset,
+    sparc32_linux_collect_core_gregset
+  };
+
+static const struct regset sparc32_linux_fpregset =
+  {
+    NULL,
+    sparc32_linux_supply_core_fpregset,
+    sparc32_linux_collect_core_fpregset
+  };
+
 static void
 sparc32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  sparc_gdbarch_tdep *tdep = gdbarch_tdep<sparc_gdbarch_tdep> (gdbarch);
 
-  linux_init_abi (info, gdbarch);
+  linux_init_abi (info, gdbarch, 0);
 
-  tdep->gregset = regset_alloc (gdbarch, sparc32_linux_supply_core_gregset,
-                               sparc32_linux_collect_core_gregset);
+  tdep->gregset = &sparc32_linux_gregset;
   tdep->sizeof_gregset = 152;
 
-  tdep->fpregset = regset_alloc (gdbarch, sparc32_linux_supply_core_fpregset,
-                                sparc32_linux_collect_core_fpregset);
+  tdep->fpregset = &sparc32_linux_fpregset;
   tdep->sizeof_fpregset = 396;
 
   tramp_frame_prepend_unwinder (gdbarch, &sparc32_linux_sigframe);
@@ -291,7 +437,7 @@ sparc32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* GNU/Linux has SVR4-style shared libraries...  */
   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
   set_solib_svr4_fetch_link_map_offsets
-    (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+    (gdbarch, linux_ilp32_fetch_link_map_offsets);
 
   /* ...which means that we need some special handling when doing
      prologue analysis.  */
@@ -299,7 +445,7 @@ sparc32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   /* Enable TLS support.  */
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
-                                             svr4_fetch_objfile_link_map);
+                                            svr4_fetch_objfile_link_map);
 
   /* Make sure we can single-step over signal return system calls.  */
   tdep->step_trap = sparc32_linux_step_trap;
@@ -310,16 +456,19 @@ sparc32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_write_pc (gdbarch, sparc_linux_write_pc);
 
   /* Functions for 'catch syscall'.  */
-  set_xml_syscall_file_name (XML_SYSCALL_FILENAME_SPARC32);
+  set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_SPARC32);
   set_gdbarch_get_syscall_number (gdbarch,
-                                  sparc32_linux_get_syscall_number);
-}
+                                 sparc32_linux_get_syscall_number);
 
-/* Provide a prototype to silence -Wmissing-prototypes.  */
-extern void _initialize_sparc_linux_tdep (void);
+  set_gdbarch_gdb_signal_from_target (gdbarch,
+                                     sparc32_linux_gdb_signal_from_target);
+  set_gdbarch_gdb_signal_to_target (gdbarch,
+                                   sparc32_linux_gdb_signal_to_target);
+}
 
+void _initialize_sparc_linux_tdep ();
 void
-_initialize_sparc_linux_tdep (void)
+_initialize_sparc_linux_tdep ()
 {
   gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_LINUX,
                          sparc32_linux_init_abi);