Convert observers to C++
[deliverable/binutils-gdb.git] / gdb / arm-linux-nat.c
index 5a8880f3c0865c152f0b3cd4a84e4f3e75344e9b..d41ef723ffb4b4001fba87bc6761761d0f033900 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU/Linux on ARM native support.
-   Copyright (C) 1999-2015 Free Software Foundation, Inc.
+   Copyright (C) 1999-2018 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "linux-nat.h"
 #include "target-descriptions.h"
 #include "auxv.h"
-#include "observer.h"
+#include "observable.h"
 #include "gdbthread.h"
 
 #include "arm-tdep.h"
 #include "arm-linux-tdep.h"
+#include "aarch32-linux-nat.h"
 
 #include <elf/common.h>
 #include <sys/user.h>
-#include <sys/ptrace.h>
+#include "nat/gdb_ptrace.h"
 #include <sys/utsname.h>
 #include <sys/procfs.h>
 
 
 extern int arm_apcs_32;
 
-/* On GNU/Linux, threads are implemented as pseudo-processes, in which
-   case we may be tracing more than one process at a time.  In that
-   case, inferior_ptid will contain the main process ID and the
-   individual thread (process) ID.  get_thread_id () is used to get
-   the thread id if it's available, and the process id otherwise.  */
-
-static int
-get_thread_id (ptid_t ptid)
-{
-  int tid = ptid_get_lwp (ptid);
-  if (0 == tid)
-    tid = ptid_get_pid (ptid);
-  return tid;
-}
-
-#define GET_THREAD_ID(PTID)    get_thread_id (PTID)
-
 /* Get the whole floating point state of the process and store it
    into regcache.  */
 
@@ -92,7 +76,7 @@ fetch_fpregs (struct regcache *regcache)
   gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
 
   /* Get the thread id for the ptrace call.  */
-  tid = GET_THREAD_ID (inferior_ptid);
+  tid = ptid_get_lwp (regcache_get_ptid (regcache));
 
   /* Read the floating point state.  */
   if (have_ptrace_getregset == TRIBOOL_TRUE)
@@ -108,10 +92,7 @@ fetch_fpregs (struct regcache *regcache)
     ret = ptrace (PT_GETFPREGS, tid, 0, fp);
 
   if (ret < 0)
-    {
-      warning (_("Unable to fetch the floating point registers."));
-      return;
-    }
+    perror_with_name (_("Unable to fetch the floating point registers."));
 
   /* Fetch fpsr.  */
   regcache_raw_supply (regcache, ARM_FPS_REGNUM,
@@ -132,7 +113,7 @@ store_fpregs (const struct regcache *regcache)
   gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
 
   /* Get the thread id for the ptrace call.  */
-  tid = GET_THREAD_ID (inferior_ptid);
+  tid = ptid_get_lwp (regcache_get_ptid (regcache));
 
   /* Read the floating point state.  */
   if (have_ptrace_getregset == TRIBOOL_TRUE)
@@ -149,10 +130,7 @@ store_fpregs (const struct regcache *regcache)
     ret = ptrace (PT_GETFPREGS, tid, 0, fp);
 
   if (ret < 0)
-    {
-      warning (_("Unable to fetch the floating point registers."));
-      return;
-    }
+    perror_with_name (_("Unable to fetch the floating point registers."));
 
   /* Store fpsr.  */
   if (REG_VALID == regcache_register_status (regcache, ARM_FPS_REGNUM))
@@ -176,10 +154,7 @@ store_fpregs (const struct regcache *regcache)
     ret = ptrace (PTRACE_SETFPREGS, tid, 0, fp);
 
   if (ret < 0)
-    {
-      warning (_("Unable to store floating point registers."));
-      return;
-    }
+    perror_with_name (_("Unable to store floating point registers."));
 }
 
 /* Fetch all general registers of the process and store into
@@ -192,7 +167,7 @@ fetch_regs (struct regcache *regcache)
   elf_gregset_t regs;
 
   /* Get the thread id for the ptrace call.  */
-  tid = GET_THREAD_ID (inferior_ptid);
+  tid = ptid_get_lwp (regcache_get_ptid (regcache));
 
   if (have_ptrace_getregset == TRIBOOL_TRUE)
     {
@@ -207,25 +182,9 @@ fetch_regs (struct regcache *regcache)
     ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
 
   if (ret < 0)
-    {
-      warning (_("Unable to fetch general registers."));
-      return;
-    }
-
-  for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
-    regcache_raw_supply (regcache, regno, (char *) &regs[regno]);
+    perror_with_name (_("Unable to fetch general registers."));
 
-  if (arm_apcs_32)
-    regcache_raw_supply (regcache, ARM_PS_REGNUM,
-                        (char *) &regs[ARM_CPSR_GREGNUM]);
-  else
-    regcache_raw_supply (regcache, ARM_PS_REGNUM,
-                        (char *) &regs[ARM_PC_REGNUM]);
-
-  regs[ARM_PC_REGNUM] = gdbarch_addr_bits_remove
-                         (get_regcache_arch (regcache), regs[ARM_PC_REGNUM]);
-  regcache_raw_supply (regcache, ARM_PC_REGNUM,
-                      (char *) &regs[ARM_PC_REGNUM]);
+  aarch32_gp_regcache_supply (regcache, (uint32_t *) regs, arm_apcs_32);
 }
 
 static void
@@ -235,7 +194,7 @@ store_regs (const struct regcache *regcache)
   elf_gregset_t regs;
 
   /* Get the thread id for the ptrace call.  */
-  tid = GET_THREAD_ID (inferior_ptid);
+  tid = ptid_get_lwp (regcache_get_ptid (regcache));
 
   /* Fetch the general registers.  */
   if (have_ptrace_getregset == TRIBOOL_TRUE)
@@ -251,20 +210,9 @@ store_regs (const struct regcache *regcache)
     ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
 
   if (ret < 0)
-    {
-      warning (_("Unable to fetch general registers."));
-      return;
-    }
-
-  for (regno = ARM_A1_REGNUM; regno <= ARM_PC_REGNUM; regno++)
-    {
-      if (REG_VALID == regcache_register_status (regcache, regno))
-       regcache_raw_collect (regcache, regno, (char *) &regs[regno]);
-    }
+    perror_with_name (_("Unable to fetch general registers."));
 
-  if (arm_apcs_32 && REG_VALID == regcache_register_status (regcache, ARM_PS_REGNUM))
-    regcache_raw_collect (regcache, ARM_PS_REGNUM,
-                        (char *) &regs[ARM_CPSR_GREGNUM]);
+  aarch32_gp_regcache_collect (regcache, (uint32_t *) regs, arm_apcs_32);
 
   if (have_ptrace_getregset == TRIBOOL_TRUE)
     {
@@ -279,10 +227,7 @@ store_regs (const struct regcache *regcache)
     ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
 
   if (ret < 0)
-    {
-      warning (_("Unable to store general registers."));
-      return;
-    }
+    perror_with_name (_("Unable to store general registers."));
 }
 
 /* Fetch all WMMX registers of the process and store into
@@ -297,14 +242,11 @@ fetch_wmmx_regs (struct regcache *regcache)
   int ret, regno, tid;
 
   /* Get the thread id for the ptrace call.  */
-  tid = GET_THREAD_ID (inferior_ptid);
+  tid = ptid_get_lwp (regcache_get_ptid (regcache));
 
   ret = ptrace (PTRACE_GETWMMXREGS, tid, 0, regbuf);
   if (ret < 0)
-    {
-      warning (_("Unable to fetch WMMX registers."));
-      return;
-    }
+    perror_with_name (_("Unable to fetch WMMX registers."));
 
   for (regno = 0; regno < 16; regno++)
     regcache_raw_supply (regcache, regno + ARM_WR0_REGNUM,
@@ -326,14 +268,11 @@ store_wmmx_regs (const struct regcache *regcache)
   int ret, regno, tid;
 
   /* Get the thread id for the ptrace call.  */
-  tid = GET_THREAD_ID (inferior_ptid);
+  tid = ptid_get_lwp (regcache_get_ptid (regcache));
 
   ret = ptrace (PTRACE_GETWMMXREGS, tid, 0, regbuf);
   if (ret < 0)
-    {
-      warning (_("Unable to fetch WMMX registers."));
-      return;
-    }
+    perror_with_name (_("Unable to fetch WMMX registers."));
 
   for (regno = 0; regno < 16; regno++)
     if (REG_VALID == regcache_register_status (regcache,
@@ -356,27 +295,19 @@ store_wmmx_regs (const struct regcache *regcache)
   ret = ptrace (PTRACE_SETWMMXREGS, tid, 0, regbuf);
 
   if (ret < 0)
-    {
-      warning (_("Unable to store WMMX registers."));
-      return;
-    }
+    perror_with_name (_("Unable to store WMMX registers."));
 }
 
-/* Fetch and store VFP Registers.  The kernel object has space for 32
-   64-bit registers, and the FPSCR.  This is even when on a VFPv2 or
-   VFPv3D16 target.  */
-#define VFP_REGS_SIZE (32 * 8 + 4)
-
 static void
 fetch_vfp_regs (struct regcache *regcache)
 {
-  char regbuf[VFP_REGS_SIZE];
+  gdb_byte regbuf[VFP_REGS_SIZE];
   int ret, regno, tid;
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   /* Get the thread id for the ptrace call.  */
-  tid = GET_THREAD_ID (inferior_ptid);
+  tid = ptid_get_lwp (regcache_get_ptid (regcache));
 
   if (have_ptrace_getregset == TRIBOOL_TRUE)
     {
@@ -390,29 +321,22 @@ fetch_vfp_regs (struct regcache *regcache)
     ret = ptrace (PTRACE_GETVFPREGS, tid, 0, regbuf);
 
   if (ret < 0)
-    {
-      warning (_("Unable to fetch VFP registers."));
-      return;
-    }
-
-  for (regno = 0; regno < tdep->vfp_register_count; regno++)
-    regcache_raw_supply (regcache, regno + ARM_D0_REGNUM,
-                        (char *) regbuf + regno * 8);
+    perror_with_name (_("Unable to fetch VFP registers."));
 
-  regcache_raw_supply (regcache, ARM_FPSCR_REGNUM,
-                      (char *) regbuf + 32 * 8);
+  aarch32_vfp_regcache_supply (regcache, regbuf,
+                              tdep->vfp_register_count);
 }
 
 static void
 store_vfp_regs (const struct regcache *regcache)
 {
-  char regbuf[VFP_REGS_SIZE];
+  gdb_byte regbuf[VFP_REGS_SIZE];
   int ret, regno, tid;
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   /* Get the thread id for the ptrace call.  */
-  tid = GET_THREAD_ID (inferior_ptid);
+  tid = ptid_get_lwp (regcache_get_ptid (regcache));
 
   if (have_ptrace_getregset == TRIBOOL_TRUE)
     {
@@ -426,17 +350,10 @@ store_vfp_regs (const struct regcache *regcache)
     ret = ptrace (PTRACE_GETVFPREGS, tid, 0, regbuf);
 
   if (ret < 0)
-    {
-      warning (_("Unable to fetch VFP registers (for update)."));
-      return;
-    }
+    perror_with_name (_("Unable to fetch VFP registers (for update)."));
 
-  for (regno = 0; regno < tdep->vfp_register_count; regno++)
-    regcache_raw_collect (regcache, regno + ARM_D0_REGNUM,
-                         (char *) regbuf + regno * 8);
-
-  regcache_raw_collect (regcache, ARM_FPSCR_REGNUM,
-                       (char *) regbuf + 32 * 8);
+  aarch32_vfp_regcache_collect (regcache, regbuf,
+                               tdep->vfp_register_count);
 
   if (have_ptrace_getregset == TRIBOOL_TRUE)
     {
@@ -450,10 +367,7 @@ store_vfp_regs (const struct regcache *regcache)
     ret = ptrace (PTRACE_SETVFPREGS, tid, 0, regbuf);
 
   if (ret < 0)
-    {
-      warning (_("Unable to store VFP registers."));
-      return;
-    }
+    perror_with_name (_("Unable to store VFP registers."));
 }
 
 /* Fetch registers from the child process.  Fetch all registers if
@@ -464,19 +378,20 @@ static void
 arm_linux_fetch_inferior_registers (struct target_ops *ops,
                                    struct regcache *regcache, int regno)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (-1 == regno)
     {
       fetch_regs (regcache);
-      fetch_fpregs (regcache);
       if (tdep->have_wmmx_registers)
        fetch_wmmx_regs (regcache);
       if (tdep->vfp_register_count > 0)
        fetch_vfp_regs (regcache);
+      if (tdep->have_fpa_registers)
+       fetch_fpregs (regcache);
     }
-  else 
+  else
     {
       if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
        fetch_regs (regcache);
@@ -487,7 +402,8 @@ arm_linux_fetch_inferior_registers (struct target_ops *ops,
        fetch_wmmx_regs (regcache);
       else if (tdep->vfp_register_count > 0
               && regno >= ARM_D0_REGNUM
-              && regno <= ARM_D0_REGNUM + tdep->vfp_register_count)
+              && (regno < ARM_D0_REGNUM + tdep->vfp_register_count
+                  || regno == ARM_FPSCR_REGNUM))
        fetch_vfp_regs (regcache);
     }
 }
@@ -500,17 +416,18 @@ static void
 arm_linux_store_inferior_registers (struct target_ops *ops,
                                    struct regcache *regcache, int regno)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (-1 == regno)
     {
       store_regs (regcache);
-      store_fpregs (regcache);
       if (tdep->have_wmmx_registers)
        store_wmmx_regs (regcache);
       if (tdep->vfp_register_count > 0)
        store_vfp_regs (regcache);
+      if (tdep->have_fpa_registers)
+       store_fpregs (regcache);
     }
   else
     {
@@ -523,7 +440,8 @@ arm_linux_store_inferior_registers (struct target_ops *ops,
        store_wmmx_regs (regcache);
       else if (tdep->vfp_register_count > 0
               && regno >= ARM_D0_REGNUM
-              && regno <= ARM_D0_REGNUM + tdep->vfp_register_count)
+              && (regno < ARM_D0_REGNUM + tdep->vfp_register_count
+                  || regno == ARM_FPSCR_REGNUM))
        store_vfp_regs (regcache);
     }
 }
@@ -563,7 +481,7 @@ supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
 /* Fetch the thread-local storage pointer for libthread_db.  */
 
 ps_err_e
-ps_get_thread_area (const struct ps_prochandle *ph,
+ps_get_thread_area (struct ps_prochandle *ph,
                     lwpid_t lwpid, int idx, void **base)
 {
   if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
@@ -586,7 +504,7 @@ arm_linux_read_description (struct target_ops *ops)
     {
       elf_gregset_t gpregs;
       struct iovec iov;
-      int tid = GET_THREAD_ID (inferior_ptid);
+      int tid = ptid_get_lwp (inferior_ptid);
 
       iov.iov_base = &gpregs;
       iov.iov_len = sizeof (gpregs);
@@ -625,7 +543,7 @@ arm_linux_read_description (struct target_ops *ops)
         registers.  Support was added in 2.6.30.  */
       pid = ptid_get_lwp (inferior_ptid);
       errno = 0;
-      buf = alloca (VFP_REGS_SIZE);
+      buf = (char *) alloca (VFP_REGS_SIZE);
       if (ptrace (PTRACE_GETVFPREGS, pid, 0, buf) < 0
          && errno == EIO)
        result = NULL;
@@ -669,7 +587,7 @@ arm_linux_get_hwbp_cap (void)
       int tid;
       unsigned int val;
 
-      tid = GET_THREAD_ID (inferior_ptid);
+      tid = ptid_get_lwp (inferior_ptid);
       if (ptrace (PTRACE_GETHBPREGS, tid, 0, &val) < 0)
        available = 0;
       else
@@ -719,7 +637,8 @@ arm_linux_get_hw_watchpoint_count (void)
    there is not an appropriate resource available, otherwise returns 1.  */
 static int
 arm_linux_can_use_hw_breakpoint (struct target_ops *self,
-                                int type, int cnt, int ot)
+                                enum bptype type,
+                                int cnt, int ot)
 {
   if (type == bp_hardware_watchpoint || type == bp_read_watchpoint
       || type == bp_access_watchpoint || type == bp_watchpoint)
@@ -840,7 +759,7 @@ arm_linux_add_process (pid_t pid)
 {
   struct arm_linux_process_info *proc;
 
-  proc = xcalloc (1, sizeof (*proc));
+  proc = XCNEW (struct arm_linux_process_info);
   proc->pid = pid;
 
   proc->next = arm_linux_process_list;
@@ -955,14 +874,14 @@ arm_linux_hw_breakpoint_initialize (struct gdbarch *gdbarch,
   p->control = arm_hwbp_control_initialize (mask, arm_hwbp_break, 1);
 }
 
-/* Get the ARM hardware breakpoint type from the RW value we're given when
-   asked to set a watchpoint.  */
+/* Get the ARM hardware breakpoint type from the TYPE value we're
+   given when asked to set a watchpoint.  */
 static arm_hwbp_type 
-arm_linux_get_hwbp_type (int rw)
+arm_linux_get_hwbp_type (enum target_hw_bp_type type)
 {
-  if (rw == hw_read)
+  if (type == hw_read)
     return arm_hwbp_load;
-  else if (rw == hw_write)
+  else if (type == hw_write)
     return arm_hwbp_store;
   else
     return arm_hwbp_access;
@@ -971,7 +890,8 @@ arm_linux_get_hwbp_type (int rw)
 /* Initialize the hardware breakpoint structure P for a watchpoint at ADDR
    to LEN.  The type of watchpoint is given in RW.  */
 static void
-arm_linux_hw_watchpoint_initialize (CORE_ADDR addr, int len, int rw,
+arm_linux_hw_watchpoint_initialize (CORE_ADDR addr, int len,
+                                   enum target_hw_bp_type type,
                                    struct arm_linux_hw_breakpoint *p)
 {
   const struct arm_linux_hwbp_cap *cap = arm_linux_get_hwbp_cap ();
@@ -984,7 +904,7 @@ arm_linux_hw_watchpoint_initialize (CORE_ADDR addr, int len, int rw,
 
   p->address = (unsigned int) addr;
   p->control = arm_hwbp_control_initialize (mask, 
-                                           arm_linux_get_hwbp_type (rw), 1);
+                                           arm_linux_get_hwbp_type (type), 1);
 }
 
 /* Are two break-/watch-points equal?  */
@@ -1180,7 +1100,8 @@ arm_linux_region_ok_for_hw_watchpoint (struct target_ops *self,
 /* Insert a Hardware breakpoint.  */
 static int
 arm_linux_insert_watchpoint (struct target_ops *self,
-                            CORE_ADDR addr, int len, int rw,
+                            CORE_ADDR addr, int len,
+                            enum target_hw_bp_type rw,
                             struct expression *cond)
 {
   struct lwp_info *lp;
@@ -1198,8 +1119,8 @@ arm_linux_insert_watchpoint (struct target_ops *self,
 
 /* Remove a hardware breakpoint.  */
 static int
-arm_linux_remove_watchpoint (struct target_ops *self,
-                            CORE_ADDR addr, int len, int rw,
+arm_linux_remove_watchpoint (struct target_ops *self, CORE_ADDR addr,
+                            int len, enum target_hw_bp_type rw,
                             struct expression *cond)
 {
   struct lwp_info *lp;
@@ -1281,6 +1202,14 @@ arm_linux_new_thread (struct lwp_info *lp)
   lp->arch_private = info;
 }
 
+/* Function to call when a thread is being deleted.  */
+
+static void
+arm_linux_delete_thread (struct arch_lwp_info *arch_lwp)
+{
+  xfree (arch_lwp);
+}
+
 /* Called when resuming a thread.
    The hardware debug registers are updated when there is any change.  */
 
@@ -1362,8 +1291,6 @@ arm_linux_new_fork (struct lwp_info *parent, pid_t child_pid)
   *child_state = *parent_state;
 }
 
-void _initialize_arm_linux_nat (void);
-
 void
 _initialize_arm_linux_nat (void)
 {
@@ -1394,6 +1321,7 @@ _initialize_arm_linux_nat (void)
 
   /* Handle thread creation and exit.  */
   linux_nat_set_new_thread (t, arm_linux_new_thread);
+  linux_nat_set_delete_thread (t, arm_linux_delete_thread);
   linux_nat_set_prepare_to_resume (t, arm_linux_prepare_to_resume);
 
   /* Handle process creation and exit.  */
This page took 0.034657 seconds and 4 git commands to generate.