diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 9dbc7b2012..766cff499e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2019-12-12 Tom Tromey + + * Makefile.in (ALL_TARGET_OBS): Add riscv-ravenscar-thread.o. + (HFILES_NO_SRCDIR): Add riscv-ravenscar-thread.h. + (ALLDEPFILES): Add riscv-ravenscar-thread.c. + * configure.tgt (riscv-*-*): Add riscv-ravenscar-thread.o. + * riscv-ravenscar-thread.c: New file. + * riscv-ravenscar-thread.h: New file. + * riscv-tdep.c (riscv_gdbarch_init): Call + register_riscv_ravenscar_ops. + 2019-12-12 Tom Tromey * gdbsupport/thread-pool.c (set_thread_name): Use diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 67fa1dfa90..fa5c820b91 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -777,6 +777,7 @@ ALL_TARGET_OBS = \ ravenscar-thread.o \ riscv-fbsd-tdep.o \ riscv-linux-tdep.o \ + riscv-ravenscar-thread.o \ riscv-tdep.o \ rl78-tdep.o \ rs6000-aix-tdep.o \ @@ -1380,6 +1381,7 @@ HFILES_NO_SRCDIR = \ remote-fileio.h \ remote-notif.h \ riscv-fbsd-tdep.h \ + riscv-ravenscar-thread.h \ riscv-tdep.h \ rs6000-aix-tdep.h \ rs6000-tdep.h \ @@ -2299,6 +2301,7 @@ ALLDEPFILES = \ riscv-fbsd-tdep.c \ riscv-linux-nat.c \ riscv-linux-tdep.c \ + riscv-ravenscar-thread.c \ riscv-tdep.c \ rl78-tdep.c \ rs6000-lynx178-tdep.c \ diff --git a/gdb/configure.tgt b/gdb/configure.tgt index caa42be1c0..b3717c7a80 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -85,7 +85,8 @@ ia64*-*-*) ;; riscv*-*-*) - cpu_obs="riscv-tdep.o arch/riscv.o";; + cpu_obs="riscv-tdep.o arch/riscv.o \ + ravenscar-thread.o riscv-ravenscar-thread.o";; x86_64-*-*) cpu_obs="${i386_tobjs} ${amd64_tobjs}";; diff --git a/gdb/riscv-ravenscar-thread.c b/gdb/riscv-ravenscar-thread.c new file mode 100644 index 0000000000..d6b34e5b8c --- /dev/null +++ b/gdb/riscv-ravenscar-thread.c @@ -0,0 +1,140 @@ +/* Ravenscar RISC-V target support. + + Copyright (C) 2019 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 "gdbarch.h" +#include "gdbcore.h" +#include "regcache.h" +#include "riscv-tdep.h" +#include "inferior.h" +#include "ravenscar-thread.h" +#include "riscv-ravenscar-thread.h" + +struct riscv_ravenscar_ops : public ravenscar_arch_ops +{ + void fetch_registers (struct regcache *regcache, int regnum) override; + void store_registers (struct regcache *regcache, int regnum) override; + +private: + + /* Return the offset of the register in the context buffer. */ + int register_offset (struct gdbarch *arch, int regnum); +}; + +int +riscv_ravenscar_ops::register_offset (struct gdbarch *arch, int regnum) +{ + int offset; + if (regnum == RISCV_RA_REGNUM || regnum == RISCV_PC_REGNUM) + offset = 0; + else if (regnum == RISCV_SP_REGNUM) + offset = 1; + else if (regnum == RISCV_ZERO_REGNUM + 8) /* S0 */ + offset = 2; + else if (regnum == RISCV_ZERO_REGNUM + 9) /* S1 */ + offset = 3; + else if (regnum >= RISCV_ZERO_REGNUM + 19 + && regnum <= RISCV_ZERO_REGNUM + 27) /* S2..S11 */ + offset = regnum - (RISCV_ZERO_REGNUM + 19) + 4; + else if (regnum >= RISCV_FIRST_FP_REGNUM + && regnum <= RISCV_FIRST_FP_REGNUM + 11) + offset = regnum - RISCV_FIRST_FP_REGNUM + 14; /* FS0..FS11 */ + else + { + /* Not saved. */ + return -1; + } + + int size = register_size (arch, regnum); + return offset * size; +} + +/* Supply register REGNUM, which has been saved on REGISTER_ADDR, to the + regcache. */ + +static void +supply_register_at_address (struct regcache *regcache, int regnum, + CORE_ADDR register_addr) +{ + struct gdbarch *gdbarch = regcache->arch (); + int buf_size = register_size (gdbarch, regnum); + gdb_byte *buf; + + buf = (gdb_byte *) alloca (buf_size); + read_memory (register_addr, buf, buf_size); + regcache->raw_supply (regnum, buf); +} + +void +riscv_ravenscar_ops::fetch_registers (struct regcache *regcache, int regnum) +{ + struct gdbarch *gdbarch = regcache->arch (); + const int num_regs = gdbarch_num_regs (gdbarch); + int current_regnum; + CORE_ADDR current_address; + CORE_ADDR thread_descriptor_address; + + /* The tid is the thread_id field, which is a pointer to the thread. */ + thread_descriptor_address = (CORE_ADDR) inferior_ptid.tid (); + + /* Read registers. */ + for (current_regnum = 0; current_regnum < num_regs; current_regnum++) + { + int offset = register_offset (gdbarch, current_regnum); + + if (offset != -1) + { + current_address = thread_descriptor_address + offset; + supply_register_at_address (regcache, current_regnum, + current_address); + } + } +} + +void +riscv_ravenscar_ops::store_registers (struct regcache *regcache, int regnum) +{ + struct gdbarch *gdbarch = regcache->arch (); + int buf_size = register_size (gdbarch, regnum); + gdb_byte buf[buf_size]; + CORE_ADDR register_address; + + int offset = register_offset (gdbarch, regnum); + if (offset != -1) + { + register_address = inferior_ptid.tid () + offset; + + regcache->raw_collect (regnum, buf); + write_memory (register_address, + buf, + buf_size); + } +} + +/* The ravenscar_arch_ops vector for most RISC-V targets. */ + +static struct riscv_ravenscar_ops riscv_ravenscar_ops; + +/* Register riscv_ravenscar_ops in GDBARCH. */ + +void +register_riscv_ravenscar_ops (struct gdbarch *gdbarch) +{ + set_gdbarch_ravenscar_ops (gdbarch, &riscv_ravenscar_ops); +} diff --git a/gdb/riscv-ravenscar-thread.h b/gdb/riscv-ravenscar-thread.h new file mode 100644 index 0000000000..d360ad7417 --- /dev/null +++ b/gdb/riscv-ravenscar-thread.h @@ -0,0 +1,27 @@ +/* Ravenscar RISC-V target support. + + Copyright (C) 2019 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 . */ + +#ifndef RISCV_RAVENSCAR_THREAD_H +#define RISCV_RAVENSCAR_THREAD_H + +struct gdbarch; + +extern void register_riscv_ravenscar_ops (struct gdbarch *gdbarch); + +#endif diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index d262b7d07e..a8b057f622 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -56,6 +56,7 @@ #include "observable.h" #include "prologue-value.h" #include "arch/riscv.h" +#include "riscv-ravenscar-thread.h" /* The stack must be 16-byte aligned. */ #define SP_ALIGNMENT 16 @@ -3358,6 +3359,8 @@ riscv_gdbarch_init (struct gdbarch_info info, /* Hook in OS ABI-specific overrides, if they have been registered. */ gdbarch_init_osabi (info, gdbarch); + register_riscv_ravenscar_ops (gdbarch); + return gdbarch; }