Sync proc_service definition with GLIBC
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-nios2-low.c
index c41579fd54ba7950e89d4c0cb78cb7abde3f8600..02fe198012757bda0f3714fddca8740cf8804665 100644 (file)
@@ -1,6 +1,6 @@
 /* GNU/Linux/Nios II specific low level interface, for the remote server for
    GDB.
-   Copyright (C) 2008-2013 Free Software Foundation, Inc.
+   Copyright (C) 2008-2016 Free Software Foundation, Inc.
 
    Contributed by Mentor Graphics, Inc.
 
@@ -21,7 +21,8 @@
 
 #include "server.h"
 #include "linux-low.h"
-#include <sys/ptrace.h>
+#include "elf/common.h"
+#include "nat/gdb_ptrace.h"
 #include <endian.h>
 #include "gdb_proc_service.h"
 #include <asm/ptrace.h>
@@ -32,7 +33,7 @@
 
 /* The following definition must agree with the number of registers
    defined in "struct user_regs" in GLIBC
-   (ports/sysdeps/unix/sysv/linux/nios2/sys/user.h), and also with
+   (sysdeps/unix/sysv/linux/nios2/sys/user.h), and also with
    NIOS2_NUM_REGS in GDB proper.  */
 
 #define nios2_num_regs 49
@@ -40,6 +41,7 @@
 /* Defined in auto-generated file nios2-linux.c.  */
 
 void init_registers_nios2_linux (void);
+extern const struct target_desc *tdesc_nios2_linux;
 
 /* This union is used to convert between int and byte buffer
    representations of register contents.  */
@@ -68,7 +70,7 @@ static int nios2_regmap[] = {
 static void
 nios2_arch_setup (void)
 {
-  init_registers_nios2_linux ();
+  current_process ()->tdesc = tdesc_nios2_linux;
 }
 
 /* Implement the cannot_fetch_register linux_target_ops method.  */
@@ -93,43 +95,31 @@ nios2_cannot_store_register (int regno)
   return 0;
 }
 
-/* Implement the get_pc linux_target_ops method.  */
-
-static CORE_ADDR
-nios2_get_pc (struct regcache *regcache)
-{
-  union nios2_register pc;
+/* Breakpoint support.  Also see comments on nios2_breakpoint_from_pc
+   in nios2-tdep.c.  */
 
-  collect_register_by_name (regcache, "pc", pc.buf);
-  return pc.reg32;
-}
-
-/* Implement the set_pc linux_target_ops method.  */
-
-static void
-nios2_set_pc (struct regcache *regcache, CORE_ADDR pc)
-{
-  union nios2_register newpc;
-
-  newpc.reg32 = pc;
-  supply_register_by_name (regcache, "pc", newpc.buf);
-}
-
-/* Breakpoint support.  */
+#if defined(__nios2_arch__) && __nios2_arch__ == 2
+#define NIOS2_BREAKPOINT 0xb7fd0020
+#define CDX_BREAKPOINT 0xd7c9
+#else
+#define NIOS2_BREAKPOINT 0x003b6ffa
+#endif
 
-static const unsigned int nios2_breakpoint = 0x003b6ffa;
+/* We only register the 4-byte breakpoint, even on R2 targets which also
+   support 2-byte breakpoints.  Since there is no supports_z_point_type
+   function provided, gdbserver never inserts software breakpoints itself
+   and instead relies on GDB to insert the breakpoint of the correct length
+   via a memory write.  */
+static const unsigned int nios2_breakpoint = NIOS2_BREAKPOINT;
 #define nios2_breakpoint_len 4
 
-/* Implement the breakpoint_reinsert_addr linux_target_ops method.  */
+/* Implementation of linux_target_ops method "sw_breakpoint_from_kind".  */
 
-static CORE_ADDR
-nios2_reinsert_addr (void)
+static const gdb_byte *
+nios2_sw_breakpoint_from_kind (int kind, int *size)
 {
-  union nios2_register ra;
-  struct regcache *regcache = get_thread_regcache (current_inferior, 1);
-
-  collect_register_by_name (regcache, "ra", ra.buf);
-  return ra.reg32;
+  *size = nios2_breakpoint_len;
+  return (const gdb_byte *) &nios2_breakpoint;
 }
 
 /* Implement the breakpoint_at linux_target_ops method.  */
@@ -139,6 +129,13 @@ nios2_breakpoint_at (CORE_ADDR where)
 {
   unsigned int insn;
 
+  /* For R2, first check for the 2-byte CDX trap.n breakpoint encoding.  */
+#if defined(__nios2_arch__) && __nios2_arch__ == 2
+  (*the_target->read_memory) (where, (unsigned char *) &insn, 2);
+  if (insn == CDX_BREAKPOINT)
+    return 1;
+#endif
+
   (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
   if (insn == nios2_breakpoint)
     return 1;
@@ -148,7 +145,7 @@ nios2_breakpoint_at (CORE_ADDR where)
 /* 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)
@@ -162,8 +159,6 @@ ps_get_thread_area (const struct ps_prochandle *ph,
   return PS_OK;
 }
 
-#ifdef HAVE_PTRACE_GETREGS
-
 /* Helper functions to collect/supply a single register REGNO.  */
 
 static void
@@ -188,7 +183,7 @@ nios2_supply_register (struct regcache *regcache, int regno,
 static void
 nios2_fill_gregset (struct regcache *regcache, void *buf)
 {
-  union nios2_register *regset = buf;
+  union nios2_register *regset = (union nios2_register *) buf;
   int i;
 
   for (i = 1; i < nios2_num_regs; i++)
@@ -198,37 +193,67 @@ nios2_fill_gregset (struct regcache *regcache, void *buf)
 static void
 nios2_store_gregset (struct regcache *regcache, const void *buf)
 {
-  const union nios2_register *regset = buf;
+  const union nios2_register *regset = (union nios2_register *) buf;
   int i;
 
   for (i = 0; i < nios2_num_regs; i++)
     nios2_supply_register (regcache, i, regset + i);
 }
-#endif /* HAVE_PTRACE_GETREGS */
 
-struct regset_info target_regsets[] =
+static struct regset_info nios2_regsets[] =
 {
-#ifdef HAVE_PTRACE_GETREGS
-  { PTRACE_GETREGS, PTRACE_SETREGS, 0, nios2_num_regs * 4, GENERAL_REGS,
+  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS,
+    nios2_num_regs * 4, GENERAL_REGS,
     nios2_fill_gregset, nios2_store_gregset },
-#endif /* HAVE_PTRACE_GETREGS */
-  { 0, 0, 0, -1, -1, NULL, NULL }
+  NULL_REGSET
 };
 
+static struct regsets_info nios2_regsets_info =
+  {
+    nios2_regsets, /* regsets */
+    0, /* num_regsets */
+    NULL, /* disabled_regsets */
+  };
+
+static struct usrregs_info nios2_usrregs_info =
+  {
+    nios2_num_regs,
+    nios2_regmap,
+  };
+
+static struct regs_info regs_info =
+  {
+    NULL, /* regset_bitmap */
+    &nios2_usrregs_info,
+    &nios2_regsets_info
+  };
+
+static const struct regs_info *
+nios2_regs_info (void)
+{
+  return &regs_info;
+}
+
 struct linux_target_ops the_low_target =
 {
   nios2_arch_setup,
-  nios2_num_regs,
-  nios2_regmap,
-  NULL,
+  nios2_regs_info,
   nios2_cannot_fetch_register,
   nios2_cannot_store_register,
   NULL,
-  nios2_get_pc,
-  nios2_set_pc,
-  (const unsigned char *) &nios2_breakpoint,
-  nios2_breakpoint_len,
-  nios2_reinsert_addr,
+  linux_get_pc_32bit,
+  linux_set_pc_32bit,
+  NULL, /* breakpoint_kind_from_pc */
+  nios2_sw_breakpoint_from_kind,
+  NULL, /* get_next_pcs */
   0,
   nios2_breakpoint_at,
 };
+
+void
+initialize_low_arch (void)
+{
+  init_registers_nios2_linux ();
+
+  initialize_regsets_info (&nios2_regsets_info);
+}
This page took 0.028972 seconds and 4 git commands to generate.