]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/arm-nbsd-nat.c
[gdb/symtab] Make gold index workaround more precise
[thirdparty/binutils-gdb.git] / gdb / arm-nbsd-nat.c
index 82c8ad5eedaf0bcdb3249dfff4a3021267478b60..a8a67e6e85202c71bfeb905d356b3f28f23b6380 100644 (file)
@@ -1,6 +1,6 @@
 /* Native-dependent code for BSD Unix running on ARM's, for GDB.
 
-   Copyright (C) 1988-2019 Free Software Foundation, Inc.
+   Copyright (C) 1988-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -17,6 +17,8 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
+/* We define this to get types like register_t.  */
+#define _KERNTYPES
 #include "defs.h"
 #include "gdbcore.h"
 #include "inferior.h"
 #include "target.h"
 #include <sys/types.h>
 #include <sys/ptrace.h>
+#include <sys/sysctl.h>
 #include <machine/reg.h>
 #include <machine/frame.h>
 
 #include "arm-tdep.h"
+#include "arm-nbsd-tdep.h"
+#include "aarch32-tdep.h"
 #include "inf-ptrace.h"
+#include "nbsd-nat.h"
 
-class arm_netbsd_nat_target final : public inf_ptrace_target
+class arm_netbsd_nat_target final : public nbsd_nat_target
 {
 public:
   /* Add our register access methods.  */
   void fetch_registers (struct regcache *, int) override;
   void store_registers (struct regcache *, int) override;
+  const struct target_desc *read_description () override;
 };
 
 static arm_netbsd_nat_target the_arm_netbsd_nat_target;
 
 static void
-arm_supply_gregset (struct regcache *regcache, struct reg *gregset)
+arm_supply_vfpregset (struct regcache *regcache, struct fpreg *fpregset)
 {
-  int regno;
-  CORE_ADDR r_pc;
-
-  /* Integer registers.  */
-  for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
-    regcache->raw_supply (regno, (char *) &gregset->r[regno]);
-
-  regcache->raw_supply (ARM_SP_REGNUM, (char *) &gregset->r_sp);
-  regcache->raw_supply (ARM_LR_REGNUM, (char *) &gregset->r_lr);
-  /* This is ok: we're running native...  */
-  r_pc = gdbarch_addr_bits_remove (regcache->arch (), gregset->r_pc);
-  regcache->raw_supply (ARM_PC_REGNUM, (char *) &r_pc);
-
-  if (arm_apcs_32)
-    regcache->raw_supply (ARM_PS_REGNUM, (char *) &gregset->r_cpsr);
-  else
-    regcache->raw_supply (ARM_PS_REGNUM, (char *) &gregset->r_pc);
-}
-
-static void
-arm_supply_fparegset (struct regcache *regcache, struct fpreg *fparegset)
-{
-  int regno;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
+  if (tdep->vfp_register_count == 0)
+    return;
 
-  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
-    regcache->raw_supply (regno,
-                         (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]);
+  struct vfpreg &vfp = fpregset->fpr_vfp;
+  for (int regno = 0; regno <= tdep->vfp_register_count; regno++)
+    regcache->raw_supply (regno + ARM_D0_REGNUM, (char *) &vfp.vfp_regs[regno]);
 
-  regcache->raw_supply (ARM_FPS_REGNUM, (char *) &fparegset->fpr_fpsr);
+  regcache->raw_supply (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr);
 }
 
 static void
@@ -79,76 +66,30 @@ fetch_register (struct regcache *regcache, int regno)
 {
   struct reg inferior_registers;
   int ret;
+  int lwp = regcache->ptid ().lwp ();
 
   ret = ptrace (PT_GETREGS, regcache->ptid ().pid (),
-               (PTRACE_TYPE_ARG3) &inferior_registers, 0);
+               (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
 
   if (ret < 0)
     {
       warning (_("unable to fetch general register"));
       return;
     }
-
-  switch (regno)
-    {
-    case ARM_SP_REGNUM:
-      regcache->raw_supply (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
-      break;
-
-    case ARM_LR_REGNUM:
-      regcache->raw_supply (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
-      break;
-
-    case ARM_PC_REGNUM:
-      /* This is ok: we're running native...  */
-      inferior_registers.r_pc = gdbarch_addr_bits_remove
-                                 (regcache->arch (),
-                                  inferior_registers.r_pc);
-      regcache->raw_supply (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
-      break;
-
-    case ARM_PS_REGNUM:
-      if (arm_apcs_32)
-       regcache->raw_supply (ARM_PS_REGNUM,
-                             (char *) &inferior_registers.r_cpsr);
-      else
-       regcache->raw_supply (ARM_PS_REGNUM,
-                             (char *) &inferior_registers.r_pc);
-      break;
-
-    default:
-      regcache->raw_supply (regno, (char *) &inferior_registers.r[regno]);
-      break;
-    }
-}
-
-static void
-fetch_regs (struct regcache *regcache)
-{
-  struct reg inferior_registers;
-  int ret;
-  int regno;
-
-  ret = ptrace (PT_GETREGS, regcache->ptid ().pid (),
-               (PTRACE_TYPE_ARG3) &inferior_registers, 0);
-
-  if (ret < 0)
-    {
-      warning (_("unable to fetch general registers"));
-      return;
-    }
-
-  arm_supply_gregset (regcache, &inferior_registers);
+  arm_nbsd_supply_gregset (nullptr, regcache, regno, &inferior_registers,
+                          sizeof (inferior_registers));
 }
 
 static void
 fetch_fp_register (struct regcache *regcache, int regno)
 {
   struct fpreg inferior_fp_registers;
-  int ret;
+  int lwp = regcache->ptid ().lwp ();
 
-  ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
-               (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
+  int ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
+                   (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
+
+  struct vfpreg &vfp = inferior_fp_registers.fpr_vfp;
 
   if (ret < 0)
     {
@@ -156,29 +97,29 @@ fetch_fp_register (struct regcache *regcache, int regno)
       return;
     }
 
-  switch (regno)
+  struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
+  if (regno == ARM_FPSCR_REGNUM && tdep->vfp_register_count != 0)
+    regcache->raw_supply (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr);
+  else if (regno >= ARM_D0_REGNUM
+          && regno <= ARM_D0_REGNUM + tdep->vfp_register_count)
     {
-    case ARM_FPS_REGNUM:
-      regcache->raw_supply (ARM_FPS_REGNUM,
-                           (char *) &inferior_fp_registers.fpr_fpsr);
-      break;
-
-    default:
-      regcache->raw_supply
-       (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
-      break;
+      regcache->raw_supply (regno,
+                           (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]);
     }
+  else
+    warning (_("Invalid register number."));
 }
 
 static void
 fetch_fp_regs (struct regcache *regcache)
 {
   struct fpreg inferior_fp_registers;
+  int lwp = regcache->ptid ().lwp ();
   int ret;
   int regno;
 
   ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
-               (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
+               (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
 
   if (ret < 0)
     {
@@ -186,11 +127,11 @@ fetch_fp_regs (struct regcache *regcache)
       return;
     }
 
-  arm_supply_fparegset (regcache, &inferior_fp_registers);
+  arm_supply_vfpregset (regcache, &inferior_fp_registers);
 }
 
 void
-arm_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
+arm_netbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
 {
   if (regno >= 0)
     {
@@ -201,7 +142,7 @@ arm_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
     }
   else
     {
-      fetch_regs (regcache);
+      fetch_register (regcache, -1);
       fetch_fp_regs (regcache);
     }
 }
@@ -212,10 +153,11 @@ store_register (const struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = regcache->arch ();
   struct reg inferior_registers;
+  int lwp = regcache->ptid ().lwp ();
   int ret;
 
   ret = ptrace (PT_GETREGS, regcache->ptid ().pid (),
-               (PTRACE_TYPE_ARG3) &inferior_registers, 0);
+               (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
 
   if (ret < 0)
     {
@@ -273,7 +215,7 @@ store_register (const struct regcache *regcache, int regno)
     }
 
   ret = ptrace (PT_SETREGS, regcache->ptid ().pid (),
-               (PTRACE_TYPE_ARG3) &inferior_registers, 0);
+               (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
 
   if (ret < 0)
     warning (_("unable to write register %d to inferior"), regno);
@@ -284,6 +226,7 @@ store_regs (const struct regcache *regcache)
 {
   struct gdbarch *gdbarch = regcache->arch ();
   struct reg inferior_registers;
+  int lwp = regcache->ptid ().lwp ();
   int ret;
   int regno;
 
@@ -315,7 +258,7 @@ store_regs (const struct regcache *regcache)
     }
 
   ret = ptrace (PT_SETREGS, regcache->ptid ().pid (),
-               (PTRACE_TYPE_ARG3) &inferior_registers, 0);
+               (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
 
   if (ret < 0)
     warning (_("unable to store general registers"));
@@ -325,10 +268,10 @@ static void
 store_fp_register (const struct regcache *regcache, int regno)
 {
   struct fpreg inferior_fp_registers;
-  int ret;
-
-  ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
-               (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
+  int lwp = regcache->ptid ().lwp ();
+  int ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
+                   (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
+  struct vfpreg &vfp = inferior_fp_registers.fpr_vfp;
 
   if (ret < 0)
     {
@@ -336,21 +279,20 @@ store_fp_register (const struct regcache *regcache, int regno)
       return;
     }
 
-  switch (regno)
+  struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
+  if (regno == ARM_FPSCR_REGNUM && tdep->vfp_register_count != 0)
+    regcache->raw_collect (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr);
+  else if (regno >= ARM_D0_REGNUM
+          && regno <= ARM_D0_REGNUM + tdep->vfp_register_count)
     {
-    case ARM_FPS_REGNUM:
-      regcache->raw_collect (ARM_FPS_REGNUM,
-                            (char *) &inferior_fp_registers.fpr_fpsr);
-      break;
-
-    default:
-      regcache->raw_collect
-       (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
-      break;
+      regcache->raw_collect (regno,
+                            (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]);
     }
+  else
+    warning (_("Invalid register number."));
 
   ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (),
-               (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
+               (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
 
   if (ret < 0)
     warning (_("unable to write register %d to inferior"), regno);
@@ -359,27 +301,28 @@ store_fp_register (const struct regcache *regcache, int regno)
 static void
 store_fp_regs (const struct regcache *regcache)
 {
-  struct fpreg inferior_fp_registers;
-  int ret;
-  int regno;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
+  int lwp = regcache->ptid ().lwp ();
+  if (tdep->vfp_register_count == 0)
+    return;
 
-
-  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
+  struct fpreg fpregs;
+  for (int regno = 0; regno <= tdep->vfp_register_count; regno++)
     regcache->raw_collect
-      (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
+      (regno + ARM_D0_REGNUM, (char *) &fpregs.fpr_vfp.vfp_regs[regno]);
 
-  regcache->raw_collect (ARM_FPS_REGNUM,
-                        (char *) &inferior_fp_registers.fpr_fpsr);
+  regcache->raw_collect (ARM_FPSCR_REGNUM,
+                        (char *) &fpregs.fpr_vfp.vfp_fpscr);
 
-  ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (),
-               (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
+  int ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (),
+                   (PTRACE_TYPE_ARG3) &fpregs, lwp);
 
   if (ret < 0)
     warning (_("unable to store floating-point registers"));
 }
 
 void
-arm_nbsd_nat_target::store_registers (struct regcache *regcache, int regno)
+arm_netbsd_nat_target::store_registers (struct regcache *regcache, int regno)
 {
   if (regno >= 0)
     {
@@ -395,59 +338,26 @@ arm_nbsd_nat_target::store_registers (struct regcache *regcache, int regno)
     }
 }
 
-static void
-fetch_elfcore_registers (struct regcache *regcache,
-                        char *core_reg_sect, unsigned core_reg_size,
-                        int which, CORE_ADDR ignore)
+const struct target_desc *
+arm_netbsd_nat_target::read_description ()
 {
-  struct reg gregset;
-  struct fpreg fparegset;
+  int flag;
+  size_t len = sizeof (flag);
 
-  switch (which)
-    {
-    case 0:    /* Integer registers.  */
-      if (core_reg_size != sizeof (struct reg))
-       warning (_("wrong size of register set in core file"));
-      else
-       {
-         /* The memcpy may be unnecessary, but we can't really be sure
-            of the alignment of the data in the core file.  */
-         memcpy (&gregset, core_reg_sect, sizeof (gregset));
-         arm_supply_gregset (regcache, &gregset);
-       }
-      break;
+  if (sysctlbyname("machdep.fpu_present", &flag, &len, NULL, 0) != 0
+      || !flag)
+    return arm_read_description (ARM_FP_TYPE_NONE);
 
-    case 2:
-      if (core_reg_size != sizeof (struct fpreg))
-       warning (_("wrong size of FPA register set in core file"));
-      else
-       {
-         /* The memcpy may be unnecessary, but we can't really be sure
-            of the alignment of the data in the core file.  */
-         memcpy (&fparegset, core_reg_sect, sizeof (fparegset));
-         arm_supply_fparegset (regcache, &fparegset);
-       }
-      break;
+  len = sizeof(flag);
+  if (sysctlbyname("machdep.neon_present", &flag, &len, NULL, 0) == 0 && flag)
+    return aarch32_read_description ();
 
-    default:
-      /* Don't know what kind of register request this is; just ignore it.  */
-      break;
-    }
+  return arm_read_description (ARM_FP_TYPE_VFPV3);
 }
 
-static struct core_fns arm_netbsd_elfcore_fns =
-{
-  bfd_target_elf_flavour,              /* core_flavour.  */
-  default_check_format,                        /* check_format.  */
-  default_core_sniffer,                        /* core_sniffer.  */
-  fetch_elfcore_registers,             /* core_read_registers.  */
-  NULL
-};
-
+void _initialize_arm_netbsd_nat ();
 void
-_initialize_arm_netbsd_nat (void)
+_initialize_arm_netbsd_nat ()
 {
   add_inf_child_target (&the_arm_netbsd_nat_target);
-
-  deprecated_add_core_fns (&arm_netbsd_elfcore_fns);
 }