C++ keyword cleanliness, mostly auto-generated
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-arm-low.c
index 547292ecd6436bb405589fdbdafdd5ba87df141e..2cd16682574c6338291e1238727ea821b287bfb0 100644 (file)
@@ -1,6 +1,5 @@
 /* GNU/Linux/ARM specific low level interface, for the remote server for GDB.
-   Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1995-2015 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
 /* Defined in auto-generated files.  */
 void init_registers_arm (void);
+extern const struct target_desc *tdesc_arm;
+
 void init_registers_arm_with_iwmmxt (void);
+extern const struct target_desc *tdesc_arm_with_iwmmxt;
+
 void init_registers_arm_with_vfpv2 (void);
+extern const struct target_desc *tdesc_arm_with_vfpv2;
+
 void init_registers_arm_with_vfpv3 (void);
+extern const struct target_desc *tdesc_arm_with_vfpv3;
+
 void init_registers_arm_with_neon (void);
+extern const struct target_desc *tdesc_arm_with_neon;
 
 #ifndef PTRACE_GET_THREAD_AREA
 #define PTRACE_GET_THREAD_AREA 22
@@ -213,7 +221,7 @@ arm_fill_vfpregset (struct regcache *regcache, void *buf)
   else
     num = 16;
 
-  base = find_regno ("d0");
+  base = find_regno (regcache->tdesc, "d0");
   for (i = 0; i < num; i++)
     collect_register (regcache, base + i, (char *) buf + i * 8);
 
@@ -233,7 +241,7 @@ arm_store_vfpregset (struct regcache *regcache, const void *buf)
   else
     num = 16;
 
-  base = find_regno ("d0");
+  base = find_regno (regcache->tdesc, "d0");
   for (i = 0; i < num; i++)
     supply_register (regcache, base + i, (char *) buf + i * 8);
 
@@ -248,7 +256,7 @@ arm_get_pc (struct regcache *regcache)
   unsigned long pc;
   collect_register_by_name (regcache, "pc", &pc);
   if (debug_threads)
-    fprintf (stderr, "stop pc is %08lx\n", pc);
+    debug_printf ("stop pc is %08lx\n", pc);
   return pc;
 }
 
@@ -274,7 +282,7 @@ static const unsigned long arm_eabi_breakpoint = 0xe7f001f0;
 static int
 arm_breakpoint_at (CORE_ADDR where)
 {
-  struct regcache *regcache = get_thread_regcache (current_inferior, 1);
+  struct regcache *regcache = get_thread_regcache (current_thread, 1);
   unsigned long cpsr;
 
   collect_register_by_name (regcache, "cpsr", &cpsr);
@@ -317,7 +325,7 @@ arm_breakpoint_at (CORE_ADDR where)
 static CORE_ADDR
 arm_reinsert_addr (void)
 {
-  struct regcache *regcache = get_thread_regcache (current_inferior, 1);
+  struct regcache *regcache = get_thread_regcache (current_thread, 1);
   unsigned long pc;
   collect_register_by_name (regcache, "lr", &pc);
   return pc;
@@ -431,42 +439,39 @@ arm_linux_hw_breakpoint_equal (const struct arm_linux_hw_breakpoint *p1,
   return p1->address == p2->address && p1->control == p2->control;
 }
 
+/* Convert a raw breakpoint type to an enum arm_hwbp_type.  */
+
+static int
+raw_bkpt_type_to_arm_hwbp_type (enum raw_bkpt_type raw_type)
+{
+  switch (raw_type)
+    {
+    case raw_bkpt_type_hw:
+      return arm_hwbp_break;
+    case raw_bkpt_type_write_wp:
+      return arm_hwbp_store;
+    case raw_bkpt_type_read_wp:
+      return arm_hwbp_load;
+    case raw_bkpt_type_access_wp:
+      return arm_hwbp_access;
+    default:
+      gdb_assert_not_reached ("unhandled raw type");
+    }
+}
+
 /* Initialize the hardware breakpoint structure P for a breakpoint or
    watchpoint at ADDR to LEN.  The type of watchpoint is given in TYPE.
-   Returns -1 if TYPE is unsupported, 0 if TYPE represents a breakpoint,
-   and 1 if type represents a watchpoint.  */
+   Returns -1 if TYPE is unsupported, or -2 if the particular combination
+   of ADDR and LEN cannot be implemented.  Otherwise, returns 0 if TYPE
+   represents a breakpoint and 1 if type represents a watchpoint.  */
 static int
-arm_linux_hw_point_initialize (char type, CORE_ADDR addr, int len,
-                              struct arm_linux_hw_breakpoint *p)
+arm_linux_hw_point_initialize (enum raw_bkpt_type raw_type, CORE_ADDR addr,
+                              int len, struct arm_linux_hw_breakpoint *p)
 {
   arm_hwbp_type hwbp_type;
   unsigned mask;
 
-  /* Breakpoint/watchpoint types (GDB terminology):
-     0 = memory breakpoint for instructions
-     (not supported; done via memory write instead)
-     1 = hardware breakpoint for instructions (supported)
-     2 = write watchpoint (supported)
-     3 = read watchpoint (supported)
-     4 = access watchpoint (supported).  */
-  switch (type)
-    {
-    case '1':
-      hwbp_type = arm_hwbp_break;
-      break;
-    case '2':
-      hwbp_type = arm_hwbp_store;
-      break;
-    case '3':
-      hwbp_type = arm_hwbp_load;
-      break;
-    case '4':
-      hwbp_type = arm_hwbp_access;
-      break;
-    default:
-      /* Unsupported.  */
-      return -1;
-    }
+  hwbp_type = raw_bkpt_type_to_arm_hwbp_type (raw_type);
 
   if (hwbp_type == arm_hwbp_break)
     {
@@ -475,17 +480,17 @@ arm_linux_hw_point_initialize (char type, CORE_ADDR addr, int len,
        {
        case 2:  /* 16-bit Thumb mode breakpoint */
        case 3:  /* 32-bit Thumb mode breakpoint */
-         mask = 0x3 << (addr & 2);
+         mask = 0x3;
+         addr &= ~1;
          break;
        case 4:  /* 32-bit ARM mode breakpoint */
          mask = 0xf;
+         addr &= ~3;
          break;
        default:
          /* Unsupported. */
-         return -1;
+         return -2;
        }
-
-      addr &= ~3;
     }
   else
     {
@@ -494,17 +499,17 @@ arm_linux_hw_point_initialize (char type, CORE_ADDR addr, int len,
 
       /* Can not set watchpoints for zero or negative lengths.  */
       if (len <= 0)
-       return -1;
+       return -2;
       /* The current ptrace interface can only handle watchpoints that are a
         power of 2.  */
       if ((len & (len - 1)) != 0)
-       return -1;
+       return -2;
 
       /* Test that the range [ADDR, ADDR + LEN) fits into the largest address
         range covered by a watchpoint.  */
       aligned_addr = addr & ~(max_wp_length - 1);
       if (aligned_addr + max_wp_length < addr + len)
-       return -1;
+       return -2;
 
       mask = (1 << len) - 1;
     }
@@ -527,11 +532,12 @@ struct update_registers_data
 static int
 update_registers_callback (struct inferior_list_entry *entry, void *arg)
 {
-  struct lwp_info *lwp = (struct lwp_info *) entry;
+  struct thread_info *thread = (struct thread_info *) entry;
+  struct lwp_info *lwp = get_thread_lwp (thread);
   struct update_registers_data *data = (struct update_registers_data *) arg;
 
   /* Only update the threads of the current process.  */
-  if (pid_of (lwp) == pid_of (get_thread_lwp (current_inferior)))
+  if (pid_of (thread) == pid_of (current_thread))
     {
       /* The actual update is done later just before resuming the lwp,
          we just mark that the registers need updating.  */
@@ -549,9 +555,26 @@ update_registers_callback (struct inferior_list_entry *entry, void *arg)
   return 0;
 }
 
+static int
+arm_supports_z_point_type (char z_type)
+{
+  switch (z_type)
+    {
+    case Z_PACKET_HW_BP:
+    case Z_PACKET_WRITE_WP:
+    case Z_PACKET_READ_WP:
+    case Z_PACKET_ACCESS_WP:
+      return 1;
+    default:
+      /* Leave the handling of sw breakpoints with the gdb client.  */
+      return 0;
+    }
+}
+
 /* Insert hardware break-/watchpoint.  */
 static int
-arm_insert_point (char type, CORE_ADDR addr, int len)
+arm_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
+                 int len, struct raw_breakpoint *bp)
 {
   struct process_info *proc = current_process ();
   struct arm_linux_hw_breakpoint p, *pts;
@@ -561,18 +584,18 @@ arm_insert_point (char type, CORE_ADDR addr, int len)
   if (watch < 0)
     {
       /* Unsupported.  */
-      return 1;
+      return watch == -1 ? 1 : -1;
     }
 
   if (watch)
     {
       count = arm_linux_get_hw_watchpoint_count ();
-      pts = proc->private->arch_private->wpts;
+      pts = proc->priv->arch_private->wpts;
     }
   else
     {
       count = arm_linux_get_hw_breakpoint_count ();
-      pts = proc->private->arch_private->bpts;
+      pts = proc->priv->arch_private->bpts;
     }
 
   for (i = 0; i < count; i++)
@@ -580,7 +603,7 @@ arm_insert_point (char type, CORE_ADDR addr, int len)
       {
        struct update_registers_data data = { watch, i };
        pts[i] = p;
-       find_inferior (&all_lwps, update_registers_callback, &data);
+       find_inferior (&all_threads, update_registers_callback, &data);
        return 0;
       }
 
@@ -590,7 +613,8 @@ arm_insert_point (char type, CORE_ADDR addr, int len)
 
 /* Remove hardware break-/watchpoint.  */
 static int
-arm_remove_point (char type, CORE_ADDR addr, int len)
+arm_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
+                 int len, struct raw_breakpoint *bp)
 {
   struct process_info *proc = current_process ();
   struct arm_linux_hw_breakpoint p, *pts;
@@ -606,12 +630,12 @@ arm_remove_point (char type, CORE_ADDR addr, int len)
   if (watch)
     {
       count = arm_linux_get_hw_watchpoint_count ();
-      pts = proc->private->arch_private->wpts;
+      pts = proc->priv->arch_private->wpts;
     }
   else
     {
       count = arm_linux_get_hw_breakpoint_count ();
-      pts = proc->private->arch_private->bpts;
+      pts = proc->priv->arch_private->bpts;
     }
 
   for (i = 0; i < count; i++)
@@ -619,7 +643,7 @@ arm_remove_point (char type, CORE_ADDR addr, int len)
       {
        struct update_registers_data data = { watch, i };
        pts[i].control = arm_hwbp_control_disable (pts[i].control);
-       find_inferior (&all_lwps, update_registers_callback, &data);
+       find_inferior (&all_threads, update_registers_callback, &data);
        return 0;
       }
 
@@ -631,8 +655,8 @@ arm_remove_point (char type, CORE_ADDR addr, int len)
 static int
 arm_stopped_by_watchpoint (void)
 {
-  struct lwp_info *lwp = get_thread_lwp (current_inferior);
-  struct siginfo siginfo;
+  struct lwp_info *lwp = get_thread_lwp (current_thread);
+  siginfo_t siginfo;
 
   /* We must be able to set hardware watchpoints.  */
   if (arm_linux_get_hw_watchpoint_count () == 0)
@@ -640,7 +664,7 @@ arm_stopped_by_watchpoint (void)
 
   /* Retrieve siginfo.  */
   errno = 0;
-  ptrace (PTRACE_GETSIGINFO, lwpid_of (lwp), 0, &siginfo);
+  ptrace (PTRACE_GETSIGINFO, lwpid_of (current_thread), 0, &siginfo);
   if (errno != 0)
     return 0;
 
@@ -666,7 +690,7 @@ arm_stopped_by_watchpoint (void)
 static CORE_ADDR
 arm_stopped_data_address (void)
 {
-  struct lwp_info *lwp = get_thread_lwp (current_inferior);
+  struct lwp_info *lwp = get_thread_lwp (current_thread);
   return lwp->arch_private->stopped_data_address;
 }
 
@@ -698,9 +722,10 @@ arm_new_thread (void)
 static void
 arm_prepare_to_resume (struct lwp_info *lwp)
 {
-  int pid = lwpid_of (lwp);
-  struct process_info *proc = find_process_pid (pid_of (lwp));
-  struct arch_process_info *proc_info = proc->private->arch_private;
+  struct thread_info *thread = get_lwp_thread (lwp);
+  int pid = lwpid_of (thread);
+  struct process_info *proc = find_process_pid (pid_of (thread));
+  struct arch_process_info *proc_info = proc->priv->arch_private;
   struct arch_lwp_info *lwp_info = lwp->arch_private;
   int i;
 
@@ -710,13 +735,15 @@ arm_prepare_to_resume (struct lwp_info *lwp)
        errno = 0;
 
        if (arm_hwbp_control_is_enabled (proc_info->bpts[i].control))
-         if (ptrace (PTRACE_SETHBPREGS, pid, ((i << 1) + 1),
-             &proc_info->bpts[i].address) < 0)
+         if (ptrace (PTRACE_SETHBPREGS, pid,
+                     (PTRACE_TYPE_ARG3) ((i << 1) + 1),
+                     &proc_info->bpts[i].address) < 0)
            perror_with_name ("Unexpected error setting breakpoint address");
 
        if (arm_hwbp_control_is_initialized (proc_info->bpts[i].control))
-         if (ptrace (PTRACE_SETHBPREGS, pid, ((i << 1) + 2),
-             &proc_info->bpts[i].control) < 0)
+         if (ptrace (PTRACE_SETHBPREGS, pid,
+                     (PTRACE_TYPE_ARG3) ((i << 1) + 2),
+                     &proc_info->bpts[i].control) < 0)
            perror_with_name ("Unexpected error setting breakpoint");
 
        lwp_info->bpts_changed[i] = 0;
@@ -728,13 +755,15 @@ arm_prepare_to_resume (struct lwp_info *lwp)
        errno = 0;
 
        if (arm_hwbp_control_is_enabled (proc_info->wpts[i].control))
-         if (ptrace (PTRACE_SETHBPREGS, pid, -((i << 1) + 1),
-             &proc_info->wpts[i].address) < 0)
+         if (ptrace (PTRACE_SETHBPREGS, pid,
+                     (PTRACE_TYPE_ARG3) -((i << 1) + 1),
+                     &proc_info->wpts[i].address) < 0)
            perror_with_name ("Unexpected error setting watchpoint address");
 
        if (arm_hwbp_control_is_initialized (proc_info->wpts[i].control))
-         if (ptrace (PTRACE_SETHBPREGS, pid, -((i << 1) + 2),
-             &proc_info->wpts[i].control) < 0)
+         if (ptrace (PTRACE_SETHBPREGS, pid,
+                     (PTRACE_TYPE_ARG3) -((i << 1) + 2),
+                     &proc_info->wpts[i].control) < 0)
            perror_with_name ("Unexpected error setting watchpoint");
 
        lwp_info->wpts_changed[i] = 0;
@@ -764,39 +793,34 @@ arm_get_hwcap (unsigned long *valp)
   return 0;
 }
 
-static void
-arm_arch_setup (void)
+static const struct target_desc *
+arm_read_description (void)
 {
-  int pid = lwpid_of (get_thread_lwp (current_inferior));
+  int pid = lwpid_of (current_thread);
 
   /* Query hardware watchpoint/breakpoint capabilities.  */
   arm_linux_init_hwbp_cap (pid);
 
   arm_hwcap = 0;
   if (arm_get_hwcap (&arm_hwcap) == 0)
-    {
-      init_registers_arm ();
-      return;
-    }
+    return tdesc_arm;
 
   if (arm_hwcap & HWCAP_IWMMXT)
-    {
-      init_registers_arm_with_iwmmxt ();
-      return;
-    }
+    return tdesc_arm_with_iwmmxt;
 
   if (arm_hwcap & HWCAP_VFP)
     {
+      const struct target_desc *result;
       char *buf;
 
       /* NEON implies either no VFP, or VFPv3-D32.  We only support
         it with VFP.  */
       if (arm_hwcap & HWCAP_NEON)
-       init_registers_arm_with_neon ();
+       result = tdesc_arm_with_neon;
       else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
-       init_registers_arm_with_vfpv3 ();
+       result = tdesc_arm_with_vfpv3;
       else
-       init_registers_arm_with_vfpv2 ();
+       result = tdesc_arm_with_vfpv2;
 
       /* Now make sure that the kernel supports reading these
         registers.  Support was added in 2.6.30.  */
@@ -806,19 +830,25 @@ arm_arch_setup (void)
          && errno == EIO)
        {
          arm_hwcap = 0;
-         init_registers_arm ();
+         result = tdesc_arm;
        }
       free (buf);
 
-      return;
+      return result;
     }
 
   /* The default configuration uses legacy FPA registers, probably
      simulated.  */
-  init_registers_arm ();
+  return tdesc_arm;
 }
 
-struct regset_info target_regsets[] = {
+static void
+arm_arch_setup (void)
+{
+  current_process ()->tdesc = arm_read_description ();
+}
+
+static struct regset_info arm_regsets[] = {
   { PTRACE_GETREGS, PTRACE_SETREGS, 0, 18 * 4,
     GENERAL_REGS,
     arm_fill_gregset, arm_store_gregset },
@@ -831,12 +861,38 @@ struct regset_info target_regsets[] = {
   { 0, 0, 0, -1, -1, NULL, NULL }
 };
 
+static struct regsets_info arm_regsets_info =
+  {
+    arm_regsets, /* regsets */
+    0, /* num_regsets */
+    NULL, /* disabled_regsets */
+  };
+
+static struct usrregs_info arm_usrregs_info =
+  {
+    arm_num_regs,
+    arm_regmap,
+  };
+
+static struct regs_info regs_info =
+  {
+    NULL, /* regset_bitmap */
+    &arm_usrregs_info,
+    &arm_regsets_info
+  };
+
+static const struct regs_info *
+arm_regs_info (void)
+{
+  return &regs_info;
+}
+
 struct linux_target_ops the_low_target = {
   arm_arch_setup,
-  arm_num_regs,
-  arm_regmap,
+  arm_regs_info,
   arm_cannot_fetch_register,
   arm_cannot_store_register,
+  NULL, /* fetch_register */
   arm_get_pc,
   arm_set_pc,
 
@@ -854,6 +910,7 @@ struct linux_target_ops the_low_target = {
   arm_reinsert_addr,
   0,
   arm_breakpoint_at,
+  arm_supports_z_point_type,
   arm_insert_point,
   arm_remove_point,
   arm_stopped_by_watchpoint,
@@ -865,3 +922,16 @@ struct linux_target_ops the_low_target = {
   arm_new_thread,
   arm_prepare_to_resume,
 };
+
+void
+initialize_low_arch (void)
+{
+  /* Initialize the Linux target descriptions.  */
+  init_registers_arm ();
+  init_registers_arm_with_iwmmxt ();
+  init_registers_arm_with_vfpv2 ();
+  init_registers_arm_with_vfpv3 ();
+  init_registers_arm_with_neon ();
+
+  initialize_regsets_info (&arm_regsets_info);
+}
This page took 0.031159 seconds and 4 git commands to generate.