diff options
author | John Baldwin <jhb@FreeBSD.org> | 2018-10-08 14:47:34 -0700 |
---|---|---|
committer | John Baldwin <jhb@FreeBSD.org> | 2018-10-08 14:47:34 -0700 |
commit | 74792ff782431ec6113b9a8a8e85b95f46094c7f (patch) | |
tree | a026f6d0b5ecb9afad8a85b0d84a168c5befd016 /gdb/riscv-fbsd-nat.c | |
parent | ed65e20bc7cd18406081cf5ba29f9c9bccd4e52f (diff) | |
download | binutils-gdb-74792ff782431ec6113b9a8a8e85b95f46094c7f.tar.gz |
Add native target for FreeBSD/riscv.
gdb/ChangeLog:
* Makefile.in (ALLDEPFILES): Add riscv-fbsd-nat.c.
* NEWS: Mention new FreeBSD/riscv native configuration.
* configure.host: Add riscv*-*-freebsd*.
* configure.nat: Likewise.
* riscv-fbsd-nat.c: New file.
gdb/doc/ChangeLog:
* gdb.texinfo (Contributors): Add SRI International and University
of Cambridge for FreeBSD/riscv.
Diffstat (limited to 'gdb/riscv-fbsd-nat.c')
-rw-r--r-- | gdb/riscv-fbsd-nat.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/gdb/riscv-fbsd-nat.c b/gdb/riscv-fbsd-nat.c new file mode 100644 index 00000000000..ad4ea1e0ad1 --- /dev/null +++ b/gdb/riscv-fbsd-nat.c @@ -0,0 +1,135 @@ +/* Native-dependent code for FreeBSD/riscv. + + 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 "target.h" + +#include <sys/types.h> +#include <sys/ptrace.h> +#include <machine/reg.h> + +#include "fbsd-nat.h" +#include "riscv-tdep.h" +#include "riscv-fbsd-tdep.h" +#include "inf-ptrace.h" + +struct riscv_fbsd_nat_target final : public fbsd_nat_target +{ + void fetch_registers (struct regcache *, int) override; + void store_registers (struct regcache *, int) override; +}; + +static riscv_fbsd_nat_target the_riscv_fbsd_nat_target; + +/* Determine if PT_GETREGS fetches REGNUM. */ + +static bool +getregs_supplies (struct gdbarch *gdbarch, int regnum) +{ + return (regnum >= RISCV_RA_REGNUM && regnum <= RISCV_PC_REGNUM); +} + +/* Determine if PT_GETFPREGS fetches REGNUM. */ + +static bool +getfpregs_supplies (struct gdbarch *gdbarch, int regnum) +{ + return ((regnum >= RISCV_FIRST_FP_REGNUM && regnum <= RISCV_LAST_FP_REGNUM) + || regnum == RISCV_CSR_FCSR_REGNUM); +} + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers. */ + +void +riscv_fbsd_nat_target::fetch_registers (struct regcache *regcache, + int regnum) +{ + pid_t pid = get_ptrace_pid (regcache->ptid ()); + + struct gdbarch *gdbarch = regcache->arch (); + if (regnum == -1 || regnum == RISCV_ZERO_REGNUM) + regcache->raw_supply_zeroed (RISCV_ZERO_REGNUM); + if (regnum == -1 || getregs_supplies (gdbarch, regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + regcache->supply_regset (&riscv_fbsd_gregset, regnum, ®s, + sizeof (regs)); + } + + if (regnum == -1 || getfpregs_supplies (gdbarch, regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + regcache->supply_regset (&riscv_fbsd_fpregset, regnum, &fpregs, + sizeof (fpregs)); + } +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers. */ + +void +riscv_fbsd_nat_target::store_registers (struct regcache *regcache, + int regnum) +{ + pid_t pid = get_ptrace_pid (regcache->ptid ()); + + struct gdbarch *gdbarch = regcache->arch (); + if (regnum == -1 || getregs_supplies (gdbarch, regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + regcache->collect_regset (&riscv_fbsd_gregset, regnum, ®s, + sizeof (regs)); + + if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); + } + + if (regnum == -1 || getfpregs_supplies (gdbarch, regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + regcache->collect_regset (&riscv_fbsd_fpregset, regnum, &fpregs, + sizeof (fpregs)); + + if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't write floating point status")); + } +} + +void +_initialize_riscv_fbsd_nat (void) +{ + add_inf_child_target (&the_riscv_fbsd_nat_target); +} |