public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] riscv: add gdbserver support
@ 2020-01-15  5:01 jiangshuai_li
  2020-01-20 23:33 ` Jim Wilson
  0 siblings, 1 reply; 16+ messages in thread
From: jiangshuai_li @ 2020-01-15  5:01 UTC (permalink / raw)
  To: 'Jim Wilson', andrew.burgess, guoren
  Cc: gdb-patches, '夏立方', 'yunhai_shang'

This patch is a base support for Riscv32 and Riscv64  arch. It implemented
how to
r/w gprs and fprs, identify the software bkpt insns and the *.dat files for
regs_info.
I have tested it on kernel 5.1.15, and it works normally.

Some requirements may be implemented later:
1. if fpu has 64bits in riscv32
2. hardware bkpt/watchpoint support
3. vector regitsers r/w

Add riscv base linux32 add linux64 gdbserver support.

gdb/gdbserver/Changlog:

2020-0113 Jiangshuai Li <jiangshuai_li@c-sky.com>

	* Makefile.in (SFILES): Add '$(srcdir)/linux-riscv-low.c'.
	* configure.srv: Target support riscv*-*linux*
	* linux-riscv-low.c: New file: Riscv low target supporting code
	(init_registers_riscv32_linux): Defined in auto-generated file
	 riscv32-linux-generated.c for RV32 linux.
	(init_registers_riscv64_linux): Defined in auto-generated file
	 riscv64-linux-generated.c for RV64 linux.
	(riscv_cannot_fetch_register): Implement
	linux_target_ops.cannot_fetch_register.
	(riscv_cannot_store_register,): Implement
	linux_target_ops.cannot_store_register.
	(riscv_fill_gregset): Fill *BUF according to elf_greg_t.
	(riscv_store_gregset): Supply *BUF according to elf_greg_t.
	(riscv_fill_fpregset): Fill *BUF according to prfpregset_t.
	(riscv_store_fpregset): Supply *BUF according to prfpregset_t.
	(riscv_arch_setup): Init current_process ()->tdesc with RV32 or
RV64.
	(regs_info): Implement linux_target_ops.riscv_regs_info.
	(riscv_sw_breakpoint_from_kind): Implement
	linux_target_ops.sw_breakpoint_from_kind, 32bits ebreak or 16bits c.
ebreak.
	(riscv_breakpoint_at): Implement
	linux_target_ops.breakpoint_at, check if mem at pc is bkpt-insn.

2020-0113 Jiangshuai Li <jiangshuai_li@c-sky.com>

	* regformats/riscv32-linux.dat: New file.
	* regformats/riscv64-linux.dat: New file.

Change-Id: Ie94277dd709b853912afe3a146be0ac2e636d5a1
---
 gdb/ChangeLog                    |   5 +
 gdb/gdbserver/ChangeLog          |  24 ++++
 gdb/gdbserver/Makefile.in        |   1 +
 gdb/gdbserver/configure.srv      |   5 +
 gdb/gdbserver/linux-riscv-low.c  | 229
+++++++++++++++++++++++++++++++++++++++
 gdb/regformats/riscv32-linux.dat |  71 ++++++++++++
 gdb/regformats/riscv64-linux.dat |  71 ++++++++++++
 7 files changed, 406 insertions(+)
 create mode 100644 gdb/gdbserver/linux-riscv-low.c
 create mode 100644 gdb/regformats/riscv32-linux.dat
 create mode 100644 gdb/regformats/riscv64-linux.dat

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 39fcac7..f5cf6c7 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2020-0113 Jiangshuai Li <jiangshuai_li@c-sky.com>
+
+	* regformats/riscv32-linux.dat: New file.
+	* regformats/riscv64-linux.dat: New file.
+
 2019-09-18  Christian Biesinger  <cbiesinger@google.com>
 
 	* dwarf2loc.c: Change extern declaration of dwarf_always_disassemble
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index faafdfd..be2b8f0 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,27 @@
+2020-0113 Jiangshuai Li <jiangshuai_li@c-sky.com>
+
+	* Makefile.in (SFILES): Add '$(srcdir)/linux-riscv-low.c'.
+	* configure.srv: Target support riscv*-*linux*
+	* linux-riscv-low.c: New file: Riscv low target supporting code 
+	(init_registers_riscv32_linux): Defined in auto-generated file
+	 riscv32-linux-generated.c for RV32 linux.
+	(init_registers_riscv64_linux): Defined in auto-generated file
+	 riscv64-linux-generated.c for RV64 linux.
+	(riscv_cannot_fetch_register): Implement
+	linux_target_ops.cannot_fetch_register.
+	(riscv_cannot_store_register,): Implement
+	linux_target_ops.cannot_store_register.
+	(riscv_fill_gregset): Fill *BUF according to elf_greg_t.
+	(riscv_store_gregset): Supply *BUF according to elf_greg_t.
+	(riscv_fill_fpregset): Fill *BUF according to prfpregset_t.
+	(riscv_store_fpregset): Supply *BUF according to prfpregset_t.
+	(riscv_arch_setup): Init current_process ()->tdesc with RV32 or
RV64.
+	(regs_info): Implement linux_target_ops.riscv_regs_info.
+	(riscv_sw_breakpoint_from_kind): Implement
+	linux_target_ops.sw_breakpoint_from_kind, 32bits ebreak or 16bits c.
ebreak.
+	(riscv_breakpoint_at): Implement
+	linux_target_ops.breakpoint_at, check if mem at pc is bkpt-insn.
+
 2019-08-23  Sergio Durigan Junior  <sergiodj@redhat.com>
 
 	* Makefile.in (SFILES): Add 'gdbsupport/gdb-dlfcn.c'.
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index ca0a4cb..ada3494 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -172,6 +172,7 @@ SFILES = \
 	$(srcdir)/linux-mips-low.c \
 	$(srcdir)/linux-nios2-low.c \
 	$(srcdir)/linux-ppc-low.c \
+	$(srcdir)/linux-riscv-low.c \
 	$(srcdir)/linux-s390-low.c \
 	$(srcdir)/linux-sh-low.c \
 	$(srcdir)/linux-sparc-low.c \
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index 66d3d42..b1dc77d 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -391,6 +391,11 @@ case "${target}" in
 			srv_linux_regsets=yes
 			srv_linux_thread_db=yes
 			;;
+  riscv*-*linux*)	srv_regobj="riscv32-linux.o riscv64-linux.o"
+			srv_tgtobj="$srv_linux_obj linux-riscv-low.o"
+			srv_linux_regsets=yes
+			srv_linux_thread_db=yes
+			;;
   *)			echo "Error: target not supported by gdbserver."
 			exit 1
 			;;
diff --git a/gdb/gdbserver/linux-riscv-low.c
b/gdb/gdbserver/linux-riscv-low.c
new file mode 100644
index 0000000..efd156e
--- /dev/null
+++ b/gdb/gdbserver/linux-riscv-low.c
@@ -0,0 +1,229 @@
+/* GNU/Linux/RISCV specific low level interface, for the remote server for
GDB.
+
+   Copyright (C) 2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
+
+#include "server.h"
+#include "linux-low.h"
+#include <asm/ptrace.h>
+#include "elf.h"
+#include "riscv-tdep.h"
+
+
+/* Defined in auto-generated file riscv32-linux-generated.c.  */
+void init_registers_riscv32_linux (void);
+extern const struct target_desc *tdesc_riscv32_linux;
+
+/* Defined in auto-generated file riscv64-linux-generated.c.  */
+void init_registers_riscv64_linux (void);
+extern const struct target_desc *tdesc_riscv64_linux;
+
+static int
+riscv_cannot_fetch_register (int regno)
+{
+  if (regno >=0 && regno <= 63)
+    return 0;
+  else
+    return 1;
+}
+
+static int
+riscv_cannot_store_register (int regno)
+{
+  if (regno >=0 && regno <= 63)
+    return 0;
+  else
+    return 1;
+}
+
+static void
+riscv_fill_gregset (struct regcache *regcache, void *buf)
+{
+   elf_greg_t *regp = (elf_greg_t *)buf;
+
+   /* We only support the integer registers and PC here.  */
+   for (int i = RISCV_ZERO_REGNUM + 1; i < RISCV_PC_REGNUM; i++)
+     collect_register (regcache, i, regp + i);
+
+   collect_register (regcache, 32, regp + 0);
+}
+
+static void
+riscv_store_gregset (struct regcache *regcache, const void *buf)
+{
+  const elf_greg_t *regp = (const elf_greg_t *)buf;
+
+  /* We only support the integer registers and PC here.  */
+  for (int i = RISCV_ZERO_REGNUM + 1; i < RISCV_PC_REGNUM; i++)
+    supply_register (regcache, i, regp + i);
+
+  /* GDB stores PC in reg 32.  Linux kernel stores it in reg 0.  */
+  supply_register (regcache, 32, regp + 0);
+
+  /* Fill the inaccessible zero register with zero.  */
+  supply_register_zeroed (regcache, 0);
+}
+
+static void
+riscv_fill_fpregset (struct regcache *regcache, void *buf)
+{
+  prfpregset_t *fpregs = (prfpregset_t *)buf;
+
+  /* We only support the FP registers and FCSR here.  */
+  for (int i = RISCV_FIRST_FP_REGNUM; i <= RISCV_LAST_FP_REGNUM; i++)
+    collect_register (regcache, i, &fpregs->__d.__f[i -
RISCV_FIRST_FP_REGNUM]);
+
+  collect_register (regcache, RISCV_CSR_FCSR_REGNUM, &fpregs->__d.__fcsr);
+}
+
+static void
+riscv_store_fpregset (struct regcache *regcache, const void *buf)
+{
+  const prfpregset_t *fpregs = (const prfpregset_t *)buf;
+
+  /* We only support the FP registers and FCSR here.  */
+  for (int i = RISCV_FIRST_FP_REGNUM; i <= RISCV_LAST_FP_REGNUM; i++)
+    supply_register (regcache, i, &fpregs->__d.__f[i -
RISCV_FIRST_FP_REGNUM]);
+
+  supply_register (regcache, RISCV_CSR_FCSR_REGNUM, &fpregs->__d.__fcsr);
+}
+
+static struct regset_info riscv_regsets[] = {
+  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS, sizeof
(elf_gregset_t),
+    GENERAL_REGS,
+    riscv_fill_gregset, riscv_store_gregset },
+  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_FPREGSET, sizeof
(elf_fpregset_t),
+    FP_REGS,
+    riscv_fill_fpregset, riscv_store_fpregset },
+  NULL_REGSET
+};
+
+
+static void
+riscv_arch_setup (void)
+{
+  int size = sizeof (elf_greg_t);
+
+  if (size == 4)
+    current_process ()->tdesc = tdesc_riscv32_linux;
+  else
+    current_process ()->tdesc = tdesc_riscv64_linux;
+}
+
+static struct regsets_info riscv_regsets_info =
+  {
+    riscv_regsets, /* regsets */
+    0, /* num_regsets */
+    NULL, /* disabled_regsets */
+  };
+
+static struct regs_info regs_info =
+  {
+    NULL, /* regset_bitmap */
+    NULL, /* usrregs */
+    &riscv_regsets_info
+  };
+
+static const struct regs_info *
+riscv_regs_info (void)
+{
+  return &regs_info;
+}
+
+/* Implementation of linux_target_ops method "sw_breakpoint_from_kind".  */
+static const gdb_byte ebreak[] = {0x73, 0x00, 0x10, 0x00};
+static const gdb_byte c_ebreak[] = {0x02, 0x90};
+
+static const gdb_byte *
+riscv_sw_breakpoint_from_kind (int kind, int *size)
+{
+  *size = kind;
+
+  switch (kind)
+    {
+      case 2:
+        return c_ebreak;
+      case 4:
+        return ebreak;
+      default:
+        gdb_assert (0);
+    }
+}
+
+static int
+riscv_breakpoint_at (CORE_ADDR where)
+{
+  unsigned char insn[4];
+
+  (*the_target->read_memory) (where, (unsigned char *) insn, 4);
+
+  if (insn[0] == ebreak[0] && insn[1] == ebreak[1]
+      && insn[2] == ebreak[2] && insn[3] == ebreak[3])
+    return 1;
+  else if (insn[0] == ebreak[0] && insn[1] == ebreak[1])
+    return 1;
+  else
+    return 0;
+}
+
+
+struct linux_target_ops the_low_target = {
+  riscv_arch_setup, /* arch_setup */
+  riscv_regs_info, /* regs_info */
+  riscv_cannot_fetch_register, /* cannot_fetch_register */
+  riscv_cannot_store_register, /* cannot_store_register */
+  NULL, /* fetch_register */
+  linux_get_pc_64bit, /* get_pc */
+  linux_set_pc_64bit, /* set_pc */
+  NULL, /* breakpoint_kind_from_pc */
+  riscv_sw_breakpoint_from_kind, /* sw_breakpoint_from_kind */
+  NULL, /* get_next_pcs */
+  0,    /* decr_pc_after_break */
+  riscv_breakpoint_at, /* breakpoint_at */
+  NULL, /* supports_z_point_type */
+  NULL, /* insert_point */
+  NULL, /* remove_point */
+  NULL, /* stopped_by_watchpoint */
+  NULL, /* stopped_data_address */
+  NULL, /* collect_ptrace_register */
+  NULL, /* supply_ptrace_register */
+  NULL, /* siginfo_fixup */
+  NULL, /* new_process */
+  NULL, /* delete_process */
+  NULL, /* new_thread */
+  NULL, /* delete_thread */
+  NULL, /* new_fork */
+  NULL, /* prepare_to_resume */
+  NULL, /* process_qsupported */
+  NULL, /* supports_tracepoints */
+  NULL, /* get_thread_area */
+  NULL, /* install_fast_tracepoint_jump_pad */
+  NULL, /* emit_ops */
+  NULL, /* get_min_fast_tracepoint_insn_len */
+  NULL, /* supports_range_stepping */
+  NULL, /* breakpoint_kind_from_current_state */
+  NULL, /* supports_hardware_single_step */
+};
+
+
+void
+initialize_low_arch (void)
+{
+  init_registers_riscv32_linux ();
+  init_registers_riscv64_linux ();
+  initialize_regsets_info (&riscv_regsets_info);
+}
diff --git a/gdb/regformats/riscv32-linux.dat
b/gdb/regformats/riscv32-linux.dat
new file mode 100644
index 0000000..d7dae52
--- /dev/null
+++ b/gdb/regformats/riscv32-linux.dat
@@ -0,0 +1,71 @@
+name:riscv32_linux
+xmltarget:riscv32-linux.xml
+expedite:sp,fp,pc
+32:zero
+32:ra
+32:sp
+32:gp
+32:tp
+32:t0
+32:t1
+32:t2
+32:fp
+32:s1
+32:a0
+32:a1
+32:a2
+32:a3
+32:a4
+32:a5
+32:a6
+32:a7
+32:s2
+32:s3
+32:s4
+32:s5
+32:s6
+32:s7
+32:s8
+32:s9
+32:s10
+32:s11
+32:t3
+32:t4
+32:t5
+32:t6
+32:pc
+32:ft0
+32:ft1
+32:ft2
+32:ft3
+32:ft4
+32:ft5
+32:ft6
+32:ft7
+32:fs0
+32:fs1
+32:fa0
+32:fa1
+32:fa2
+32:fa3
+32:fa4
+32:fa5
+32:fa6
+32:fa7
+32:fs2
+32:fs3
+32:fs4
+32:fs5
+32:fs6
+32:fs7
+32:fs8
+32:fs9
+32:fs10
+32:fs11
+32:ft8
+32:ft9
+32:ft10
+32:ft11
+32:fflags
+32:frm
+32:fcsr
diff --git a/gdb/regformats/riscv64-linux.dat
b/gdb/regformats/riscv64-linux.dat
new file mode 100644
index 0000000..1b88f6c
--- /dev/null
+++ b/gdb/regformats/riscv64-linux.dat
@@ -0,0 +1,71 @@
+name:riscv64_linux
+xmltarget:riscv64-linux.xml
+expedite:sp,fp,pc
+64:zero
+64:ra
+64:sp
+64:gp
+64:tp
+64:t0
+64:t1
+64:t2
+64:fp
+64:s1
+64:a0
+64:a1
+64:a2
+64:a3
+64:a4
+64:a5
+64:a6
+64:a7
+64:s2
+64:s3
+64:s4
+64:s5
+64:s6
+64:s7
+64:s8
+64:s9
+64:s10
+64:s11
+64:t3
+64:t4
+64:t5
+64:t6
+64:pc
+64:ft0
+64:ft1
+64:ft2
+64:ft3
+64:ft4
+64:ft5
+64:ft6
+64:ft7
+64:fs0
+64:fs1
+64:fa0
+64:fa1
+64:fa2
+64:fa3
+64:fa4
+64:fa5
+64:fa6
+64:fa7
+64:fs2
+64:fs3
+64:fs4
+64:fs5
+64:fs6
+64:fs7
+64:fs8
+64:fs9
+64:fs10
+64:fs11
+64:ft8
+64:ft9
+64:ft10
+64:ft11
+32:fflags
+32:frm
+32:fcsr
-- 
2.7.4

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2020-01-22 13:39 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-15  5:01 [PATCH] riscv: add gdbserver support jiangshuai_li
2020-01-20 23:33 ` Jim Wilson
2020-01-21  0:30   ` Maciej W. Rozycki
2020-01-21  2:13     ` Simon Marchi
2020-01-21  2:17       ` Maciej W. Rozycki
2020-01-21 13:01       ` Andrew Burgess
2020-01-21 13:28         ` Andrew Burgess
2020-01-21 13:47           ` Andreas Schwab
2020-01-22  0:11             ` Jim Wilson
2020-01-22  0:45           ` Jim Wilson
2020-01-22 10:19             ` Jim Wilson
2020-01-22 14:08               ` Andrew Burgess
2020-01-21 17:11         ` Maciej W. Rozycki
2020-01-21 23:56     ` Jim Wilson
2020-01-22  5:26   ` Guo Ren
2020-01-22  6:15     ` Jim Wilson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).