From patchwork Mon Sep 24 20:51:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Baldwin X-Patchwork-Id: 29527 Received: (qmail 49046 invoked by alias); 24 Sep 2018 20:52:04 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 48893 invoked by uid 89); 24 Sep 2018 20:52:03 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_HELO_PASS, SPF_SOFTFAIL autolearn=ham version=3.3.2 spammy=Supply, supplying, sk:rs6000-, sk:print_o X-HELO: mail.baldwin.cx Received: from bigwig.baldwin.cx (HELO mail.baldwin.cx) (96.47.65.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 24 Sep 2018 20:51:59 +0000 Received: from ralph.baldwin.cx (ralph.baldwin.cx [66.234.199.215]) by mail.baldwin.cx (Postfix) with ESMTPSA id 7282B10B709; Mon, 24 Sep 2018 16:51:57 -0400 (EDT) From: John Baldwin To: gdb-patches@sourceware.org Cc: andrew.burgess@embecosm.com, jimw@sifive.com Subject: [PATCH v2 3/4] Add FreeBSD/riscv architecture. Date: Mon, 24 Sep 2018 13:51:50 -0700 Message-Id: <20180924205151.22217-4-jhb@FreeBSD.org> In-Reply-To: <20180924205151.22217-1-jhb@FreeBSD.org> References: <20180924205151.22217-1-jhb@FreeBSD.org> X-IsSubscribed: yes Support for collecting and supplying general purpose and floating point register sets is provided along with signal frame unwinding. FreeBSD only supports RV64 currently, so while some provision is made for RV32 in the general-purpose register set, the changes have only been tested on RV64. gdb/ChangeLog: * Makefile.in (ALL_TARGET_OBS): Add riscv-fbsd-tdep.o. (HFILES_NO_SRCDIR): Add riscv-fbsd-tdep.h. (ALLDEPFILES): Add riscv-fbsd-tdep.c. * NEWS: Mention new FreeBSD/riscv target. * configure.tgt: Add riscv*-*-freebsd*. * riscv-fbsd-tdep.c: New file. * riscv-fbsd-tdep.h: New file. --- gdb/ChangeLog | 10 ++ gdb/Makefile.in | 3 + gdb/NEWS | 1 + gdb/configure.tgt | 5 + gdb/riscv-fbsd-tdep.c | 206 ++++++++++++++++++++++++++++++++++++++++++ gdb/riscv-fbsd-tdep.h | 33 +++++++ 6 files changed, 258 insertions(+) create mode 100644 gdb/riscv-fbsd-tdep.c create mode 100644 gdb/riscv-fbsd-tdep.h diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f56b0487cc..1367f37db7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2018-09-24 John Baldwin + + * Makefile.in (ALL_TARGET_OBS): Add riscv-fbsd-tdep.o. + (HFILES_NO_SRCDIR): Add riscv-fbsd-tdep.h. + (ALLDEPFILES): Add riscv-fbsd-tdep.c. + * NEWS: Mention new FreeBSD/riscv target. + * configure.tgt: Add riscv*-*-freebsd*. + * riscv-fbsd-tdep.c: New file. + * riscv-fbsd-tdep.h: New file. + 2018-09-24 John Baldwin * disasm-selftests.c (print_one_insn_test): Add bfd_arch_riscv to diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 3b158fa1db..2e03bb956c 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -745,6 +745,7 @@ ALL_TARGET_OBS = \ ppc-sysv-tdep.o \ ppc64-tdep.o \ ravenscar-thread.o \ + riscv-fbsd-tdep.o \ riscv-linux-tdep.o \ riscv-tdep.o \ rl78-tdep.o \ @@ -1339,6 +1340,7 @@ HFILES_NO_SRCDIR = \ remote.h \ remote-fileio.h \ remote-notif.h \ + riscv-fbsd-tdep.h \ riscv-tdep.h \ rs6000-aix-tdep.h \ rs6000-tdep.h \ @@ -2306,6 +2308,7 @@ ALLDEPFILES = \ procfs.c \ ravenscar-thread.c \ remote-sim.c \ + riscv-fbsd-tdep.c \ riscv-linux-nat.c \ riscv-linux-tdep.c \ riscv-tdep.c \ diff --git a/gdb/NEWS b/gdb/NEWS index a1936ca1cc..a191ae2714 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -86,6 +86,7 @@ GNU/Linux/RISC-V riscv*-*-linux* GNU/Linux/RISC-V riscv*-*-linux* CSKY ELF csky*-*-elf CSKY GNU/LINUX csky*-*-linux +FreeBSD/riscv riscv*-*-freebsd* * Python API diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 6d1a4df84a..3b94942732 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -528,6 +528,11 @@ s390*-*-linux*) build_gdbserver=yes ;; +riscv*-*-freebsd*) + # Target: FreeBSD/riscv + gdb_target_obs="riscv-fbsd-tdep.o riscv-tdep.o" + ;; + riscv*-*-linux*) # Target: Linux/RISC-V gdb_target_obs="riscv-linux-tdep.o riscv-tdep.o glibc-tdep.o \ diff --git a/gdb/riscv-fbsd-tdep.c b/gdb/riscv-fbsd-tdep.c new file mode 100644 index 0000000000..c09ec650ca --- /dev/null +++ b/gdb/riscv-fbsd-tdep.c @@ -0,0 +1,206 @@ +/* Target-dependent code for FreeBSD on RISC-V processors. + Copyright (C) 2018 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 . */ + +#include "defs.h" +#include "fbsd-tdep.h" +#include "osabi.h" +#include "riscv-tdep.h" +#include "riscv-fbsd-tdep.h" +#include "solib-svr4.h" +#include "target.h" +#include "trad-frame.h" +#include "tramp-frame.h" + +/* Register maps. */ + +static const struct regcache_map_entry riscv_fbsd_gregmap[] = + { + { 1, RISCV_RA_REGNUM, 0 }, + { 1, RISCV_SP_REGNUM, 0 }, + { 1, RISCV_GP_REGNUM, 0 }, + { 1, RISCV_TP_REGNUM, 0 }, + { 3, 5, 0 }, /* t0 - t2 */ + { 4, 28, 0 }, /* t3 - t6 */ + { 2, RISCV_FP_REGNUM, 0 }, /* s0 - s1 */ + { 10, 18, 0 }, /* s2 - s11 */ + { 8, RISCV_A0_REGNUM, 0 }, /* a0 - a7 */ + { 1, RISCV_PC_REGNUM, 0 }, + { 1, RISCV_CSR_SSTATUS_REGNUM, 0 }, + { 0 } + }; + +static const struct regcache_map_entry riscv_fbsd_fpregmap[] = + { + { 32, RISCV_FIRST_FP_REGNUM, 16 }, + { 1, RISCV_CSR_FCSR_REGNUM, 8 }, + { 0 } + }; + +/* Supply the general-purpose registers stored in GREGS to REGCACHE. + This function only exists to supply the always-zero x0 in addition + to the registers in GREGS. */ + +static void +riscv_fbsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *gregs, size_t len) +{ + regcache->supply_regset (&riscv_fbsd_gregset, regnum, gregs, len); + if (regnum == -1 || regnum == RISCV_ZERO_REGNUM) + regcache->raw_supply_zeroed (RISCV_ZERO_REGNUM); +} + +/* Register set definitions. */ + +const struct regset riscv_fbsd_gregset = + { + riscv_fbsd_gregmap, + riscv_fbsd_supply_gregset, regcache_collect_regset + }; + +const struct regset riscv_fbsd_fpregset = + { + riscv_fbsd_fpregmap, + regcache_supply_regset, regcache_collect_regset + }; + +/* Implement the "regset_from_core_section" gdbarch method. */ + +static void +riscv_fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", RISCV_FBSD_NUM_GREGS * riscv_isa_xlen (gdbarch), + RISCV_FBSD_NUM_GREGS * riscv_isa_xlen (gdbarch), + &riscv_fbsd_gregset, NULL, cb_data); + cb (".reg2", RISCV_FBSD_SIZEOF_FPREGSET, RISCV_FBSD_SIZEOF_FPREGSET, + &riscv_fbsd_fpregset, NULL, cb_data); +} + +/* In a signal frame, sp points to a 'struct sigframe' which is + defined as: + + struct sigframe { + siginfo_t sf_si; + ucontext_t sf_uc; + }; + + ucontext_t is defined as: + + struct __ucontext { + sigset_t uc_sigmask; + mcontext_t uc_mcontext; + ... + }; + + The mcontext_t contains the general purpose register set followed + by the floating point register set. The floating point register + set is only valid if the _MC_FP_VALID flag is set in mc_flags. */ + +#define RISCV_SIGFRAME_UCONTEXT_OFFSET 80 +#define RISCV_UCONTEXT_MCONTEXT_OFFSET 16 +#define RISCV_MCONTEXT_FLAG_FP_VALID 0x1 + +/* Implement the "init" method of struct tramp_frame. */ + +static void +riscv_fbsd_sigframe_init (const struct tramp_frame *self, + struct frame_info *this_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp = get_frame_register_unsigned (this_frame, RISCV_SP_REGNUM); + CORE_ADDR mcontext_addr = + sp + + RISCV_SIGFRAME_UCONTEXT_OFFSET + + RISCV_UCONTEXT_MCONTEXT_OFFSET; + gdb_byte buf[4]; + int i; + + trad_frame_set_reg_regmap (this_cache, riscv_fbsd_gregmap, mcontext_addr, + RISCV_FBSD_NUM_GREGS * riscv_isa_xlen (gdbarch)); + + CORE_ADDR fpregs_addr + = mcontext_addr + RISCV_FBSD_NUM_GREGS * riscv_isa_xlen (gdbarch); + CORE_ADDR fp_flags_addr + = fpregs_addr + RISCV_FBSD_SIZEOF_FPREGSET; + if (target_read_memory (fp_flags_addr, buf, 4) == 0 + && (extract_unsigned_integer (buf, 4, byte_order) + & RISCV_MCONTEXT_FLAG_FP_VALID)) + trad_frame_set_reg_regmap (this_cache, riscv_fbsd_fpregmap, fpregs_addr, + RISCV_FBSD_SIZEOF_FPREGSET); + + trad_frame_set_id (this_cache, frame_id_build (sp, func)); +} + +/* RISC-V supports 16-bit instructions ("C") as well as 32-bit + instructions. The signal trampoline on FreeBSD uses a mix of + these, but tramp_frame assumes a fixed instruction size. To cope, + claim that all instructions are 16 bits and use two "slots" for + 32-bit instructions. */ + +static const struct tramp_frame riscv_fbsd_sigframe = +{ + SIGTRAMP_FRAME, + 2, + { + {0x850a, ULONGEST_MAX}, /* mov a0, sp */ + {0x0513, ULONGEST_MAX}, /* addi a0, a0, #SF_UC */ + {0x0505, ULONGEST_MAX}, + {0x0293, ULONGEST_MAX}, /* li t0, #SYS_sigreturn */ + {0x1a10, ULONGEST_MAX}, + {0x0073, ULONGEST_MAX}, /* ecall */ + {0x0000, ULONGEST_MAX}, + {TRAMP_SENTINEL_INSN, ULONGEST_MAX} + }, + riscv_fbsd_sigframe_init +}; + +/* Implement the 'init_osabi' method of struct gdb_osabi_handler. */ + +static void +riscv_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Generic FreeBSD support. */ + fbsd_init_abi (info, gdbarch); + + set_gdbarch_software_single_step (gdbarch, riscv_software_single_step); + + set_solib_svr4_fetch_link_map_offsets (gdbarch, + (riscv_isa_xlen (gdbarch) == 4 + ? svr4_ilp32_fetch_link_map_offsets + : svr4_lp64_fetch_link_map_offsets)); + + tramp_frame_prepend_unwinder (gdbarch, &riscv_fbsd_sigframe); + + set_gdbarch_iterate_over_regset_sections + (gdbarch, riscv_fbsd_iterate_over_regset_sections); +} + +void +_initialize_riscv_fbsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_riscv, 0, GDB_OSABI_FREEBSD, + riscv_fbsd_init_abi); +} diff --git a/gdb/riscv-fbsd-tdep.h b/gdb/riscv-fbsd-tdep.h new file mode 100644 index 0000000000..8b6abd565b --- /dev/null +++ b/gdb/riscv-fbsd-tdep.h @@ -0,0 +1,33 @@ +/* FreeBSD/riscv target support, prototypes. + + Copyright (C) 2018 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 . */ + +#include "regset.h" + +/* The general-purpose regset consists of 31 X registers, EPC, and + SSTATUS. */ +#define RISCV_FBSD_NUM_GREGS 33 + +/* The fp regset always consists of 32 128-bit registers, plus a + 64-bit CSR_FCSR. If 'Q' is not supported, only the low 64-bits of + each floating point register are valid. If 'D' is not supported, + only the low 32-bits of each floating point register are valid. */ +#define RISCV_FBSD_SIZEOF_FPREGSET (32 * 16 + 8) + +extern const struct regset riscv_fbsd_gregset; +extern const struct regset riscv_fbsd_fpregset;