Message ID | 20191211165231.17943-1-tromey@adacore.com |
---|---|
State | New |
Headers | show |
* Tom Tromey <tromey@adacore.com> [2019-12-11 09:52:31 -0700]: > This adds Ravenscar support to gdb for RISC-V targets. > > This was tested internally using AdaCore's test suite and qemu. > > gdb/ChangeLog > 2019-12-11 Tom Tromey <tromey@adacore.com> > > * 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. LGTM. Thanks, Andre > > Change-Id: Ic47a3b3cfbbe80c2c82a5f48d2e0481845cac8b0 > --- > gdb/ChangeLog | 11 +++ > gdb/Makefile.in | 3 + > gdb/configure.tgt | 3 +- > gdb/riscv-ravenscar-thread.c | 140 +++++++++++++++++++++++++++++++++++ > gdb/riscv-ravenscar-thread.h | 27 +++++++ > gdb/riscv-tdep.c | 3 + > 6 files changed, 186 insertions(+), 1 deletion(-) > create mode 100644 gdb/riscv-ravenscar-thread.c > create mode 100644 gdb/riscv-ravenscar-thread.h > > diff --git a/gdb/Makefile.in b/gdb/Makefile.in > index 67fa1dfa90a..fa5c820b918 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 caa42be1c01..b3717c7a80c 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 00000000000..d6b34e5b8cb > --- /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 <http://www.gnu.org/licenses/>. */ > + > +#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 00000000000..d360ad7417a > --- /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 <http://www.gnu.org/licenses/>. */ > + > +#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 d262b7d07e7..a8b057f622b 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; > } > > -- > 2.21.0 >
diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 67fa1dfa90a..fa5c820b918 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 caa42be1c01..b3717c7a80c 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 00000000000..d6b34e5b8cb --- /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 <http://www.gnu.org/licenses/>. */ + +#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 00000000000..d360ad7417a --- /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 <http://www.gnu.org/licenses/>. */ + +#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 d262b7d07e7..a8b057f622b 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; }