gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / riscv-linux-nat.c
index c09121d052b662fcee27fed559ec1a3608d5388a..4f78dfdc6a20f447863b1821a598c0434afaa5e7 100644 (file)
@@ -1,5 +1,5 @@
 /* Native-dependent code for GNU/Linux RISC-V.
-   Copyright (C) 2018 Free Software Foundation, Inc.
+   Copyright (C) 2018-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "gregset.h"
 #include "linux-nat.h"
 #include "riscv-tdep.h"
+#include "inferior.h"
 
 #include "elf/common.h"
 
+#include "nat/riscv-linux-tdesc.h"
+
 #include <sys/ptrace.h>
 
+/* Work around glibc header breakage causing ELF_NFPREG not to be usable.  */
+#ifndef NFPREG
+# define NFPREG 33
+#endif
+
 /* RISC-V Linux native additions to the default linux support.  */
 
 class riscv_linux_nat_target final : public linux_nat_target
@@ -34,6 +42,9 @@ public:
   /* Add our register access methods.  */
   void fetch_registers (struct regcache *regcache, int regnum) override;
   void store_registers (struct regcache *regcache, int regnum) override;
+
+  /* Read suitable target description.  */
+  const struct target_desc *read_description () override;
 };
 
 static riscv_linux_nat_target the_riscv_linux_nat_target;
@@ -83,21 +94,35 @@ static void
 supply_fpregset_regnum (struct regcache *regcache, const prfpregset_t *fpregs,
                        int regnum)
 {
+  int flen = register_size (regcache->arch (), RISCV_FIRST_FP_REGNUM);
+  union
+    {
+      const prfpregset_t *fpregs;
+      const gdb_byte *buf;
+    }
+  fpbuf = { .fpregs = fpregs };
   int i;
 
   if (regnum == -1)
     {
       /* We only support the FP registers and FCSR here.  */
-      for (i = RISCV_FIRST_FP_REGNUM; i <= RISCV_LAST_FP_REGNUM; i++)
-       regcache->raw_supply (i, &fpregs->__d.__f[i - RISCV_FIRST_FP_REGNUM]);
+      for (i = RISCV_FIRST_FP_REGNUM;
+          i <= RISCV_LAST_FP_REGNUM;
+          i++, fpbuf.buf += flen)
+       regcache->raw_supply (i, fpbuf.buf);
 
-      regcache->raw_supply (RISCV_CSR_FCSR_REGNUM, &fpregs->__d.__fcsr);
+      regcache->raw_supply (RISCV_CSR_FCSR_REGNUM, fpbuf.buf);
     }
   else if (regnum >= RISCV_FIRST_FP_REGNUM && regnum <= RISCV_LAST_FP_REGNUM)
-    regcache->raw_supply (regnum,
-                         &fpregs->__d.__f[regnum - RISCV_FIRST_FP_REGNUM]);
+    {
+      fpbuf.buf += flen * (regnum - RISCV_FIRST_FP_REGNUM);
+      regcache->raw_supply (regnum, fpbuf.buf);
+    }
   else if (regnum == RISCV_CSR_FCSR_REGNUM)
-    regcache->raw_supply (RISCV_CSR_FCSR_REGNUM, &fpregs->__d.__fcsr);
+    {
+      fpbuf.buf += flen * (RISCV_LAST_FP_REGNUM - RISCV_FIRST_FP_REGNUM + 1);
+      regcache->raw_supply (RISCV_CSR_FCSR_REGNUM, fpbuf.buf);
+    }
 }
 
 /* Copy all floating point registers from regset FPREGS into REGCACHE.  */
@@ -140,19 +165,45 @@ void
 fill_fpregset (const struct regcache *regcache, prfpregset_t *fpregs,
               int regnum)
 {
+  int flen = register_size (regcache->arch (), RISCV_FIRST_FP_REGNUM);
+  union
+    {
+      prfpregset_t *fpregs;
+      gdb_byte *buf;
+    }
+  fpbuf = { .fpregs = fpregs };
+  int i;
+
   if (regnum == -1)
     {
       /* We only support the FP registers and FCSR here.  */
-      for (int i = RISCV_FIRST_FP_REGNUM; i <= RISCV_LAST_FP_REGNUM; i++)
-       regcache->raw_collect (i, &fpregs->__d.__f[i - RISCV_FIRST_FP_REGNUM]);
+      for (i = RISCV_FIRST_FP_REGNUM;
+          i <= RISCV_LAST_FP_REGNUM;
+          i++, fpbuf.buf += flen)
+       regcache->raw_collect (i, fpbuf.buf);
 
-      regcache->raw_collect (RISCV_CSR_FCSR_REGNUM, &fpregs->__d.__fcsr);
+      regcache->raw_collect (RISCV_CSR_FCSR_REGNUM, fpbuf.buf);
     }
   else if (regnum >= RISCV_FIRST_FP_REGNUM && regnum <= RISCV_LAST_FP_REGNUM)
-    regcache->raw_collect (regnum,
-                          &fpregs->__d.__f[regnum - RISCV_FIRST_FP_REGNUM]);
+    {
+      fpbuf.buf += flen * (regnum - RISCV_FIRST_FP_REGNUM);
+      regcache->raw_collect (regnum, fpbuf.buf);
+    }
   else if (regnum == RISCV_CSR_FCSR_REGNUM)
-    regcache->raw_collect (RISCV_CSR_FCSR_REGNUM, &fpregs->__d.__fcsr);
+    {
+      fpbuf.buf += flen * (RISCV_LAST_FP_REGNUM - RISCV_FIRST_FP_REGNUM + 1);
+      regcache->raw_collect (RISCV_CSR_FCSR_REGNUM, fpbuf.buf);
+    }
+}
+
+/* Return a target description for the current target.  */
+
+const struct target_desc *
+riscv_linux_nat_target::read_description ()
+{
+  const struct riscv_gdbarch_features features
+    = riscv_linux_read_features (inferior_ptid.lwp ());
+  return riscv_lookup_target_description (features);
 }
 
 /* Fetch REGNUM (or all registers if REGNUM == -1) from the target
@@ -190,7 +241,9 @@ riscv_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
       elf_fpregset_t regs;
 
       iov.iov_base = &regs;
-      iov.iov_len = sizeof (regs);
+      iov.iov_len = ELF_NFPREG * register_size (regcache->arch (),
+                                               RISCV_FIRST_FP_REGNUM);
+      gdb_assert (iov.iov_len <= sizeof (regs));
 
       if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET,
                  (PTRACE_TYPE_ARG3) &iov) == -1)
@@ -201,8 +254,10 @@ riscv_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
 
   if ((regnum == RISCV_CSR_MISA_REGNUM)
       || (regnum == -1))
-    /* TODO: Need to add a ptrace call for this.  */
-    regcache->raw_supply_zeroed (RISCV_CSR_MISA_REGNUM);
+    {
+      /* TODO: Need to add a ptrace call for this.  */
+      regcache->raw_supply_zeroed (RISCV_CSR_MISA_REGNUM);
+    }
 
   /* Access to other CSRs has potential security issues, don't support them for
      now.  */
@@ -249,7 +304,9 @@ riscv_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
       elf_fpregset_t regs;
 
       iov.iov_base = &regs;
-      iov.iov_len = sizeof (regs);
+      iov.iov_len = ELF_NFPREG * register_size (regcache->arch (),
+                                               RISCV_FIRST_FP_REGNUM);
+      gdb_assert (iov.iov_len <= sizeof (regs));
 
       if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET,
                  (PTRACE_TYPE_ARG3) &iov) == -1)
@@ -270,8 +327,9 @@ riscv_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
 
 /* Initialize RISC-V Linux native support.  */
 
+void _initialize_riscv_linux_nat ();
 void
-_initialize_riscv_linux_nat (void)
+_initialize_riscv_linux_nat ()
 {
   /* Register the target.  */
   linux_target = &the_riscv_linux_nat_target;
This page took 0.027653 seconds and 4 git commands to generate.