/* 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-2020 Free Software Foundation, Inc.
Contributed by Mentor Graphics, Inc.
#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>
/* 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
/* 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. */
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. */
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. */
{
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;
/* 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)
return PS_OK;
}
-#ifdef HAVE_PTRACE_GETREGS
-
/* Helper functions to collect/supply a single register REGNO. */
static void
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++)
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 ®s_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);
+}