Add FreeBSD/riscv architecture.

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.
This commit is contained in:
John Baldwin 2018-10-08 14:47:34 -07:00
parent 498f740792
commit ed65e20bc7
6 changed files with 258 additions and 0 deletions

View File

@ -1,3 +1,13 @@
2018-10-08 John Baldwin <jhb@FreeBSD.org>
* 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-10-08 John Baldwin <jhb@FreeBSD.org>
* regcache.h (struct regcache_map_entry): Note that this type can

View File

@ -744,6 +744,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 \
@ -1338,6 +1339,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 \

View File

@ -99,6 +99,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

View File

@ -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 \

206
gdb/riscv-fbsd-tdep.c Normal file
View File

@ -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 <http://www.gnu.org/licenses/>. */
#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);
}

33
gdb/riscv-fbsd-tdep.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>. */
#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;