aboutsummaryrefslogtreecommitdiff
path: root/gdb/ravenscar-thread.c
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2022-05-03 08:18:14 -0600
committerTom Tromey <tromey@adacore.com>2022-06-14 09:08:29 -0600
commite73434e38f55e21cc33457ce3b218fa7b4592fec (patch)
treee3e443b6bbd889dc8cc9ff321a946a09052dbdd4 /gdb/ravenscar-thread.c
parent2808125fbb5f9c55f52e863283b7f1c5f0ef1a65 (diff)
downloadbinutils-e73434e38f55e21cc33457ce3b218fa7b4592fec.zip
binutils-e73434e38f55e21cc33457ce3b218fa7b4592fec.tar.gz
binutils-e73434e38f55e21cc33457ce3b218fa7b4592fec.tar.bz2
Reimplement ravenscar registers using tables
Currently, the ravenscar-thread implementation for each architecture is written by hand. However, these are actually written by copy-paste. It seems better to switch to a table-driven approach. The previous code also fetched all registers whenever any register was requested. This is corrected in the new implementation.
Diffstat (limited to 'gdb/ravenscar-thread.c')
-rw-r--r--gdb/ravenscar-thread.c113
1 files changed, 112 insertions, 1 deletions
diff --git a/gdb/ravenscar-thread.c b/gdb/ravenscar-thread.c
index aae6e39..e300095 100644
--- a/gdb/ravenscar-thread.c
+++ b/gdb/ravenscar-thread.c
@@ -477,6 +477,116 @@ ravenscar_thread_target::pid_to_str (ptid_t ptid)
phex_nz (ptid.tid (), sizeof (ULONGEST)));
}
+CORE_ADDR
+ravenscar_arch_ops::get_stack_base (struct regcache *regcache) const
+{
+ struct gdbarch *gdbarch = regcache->arch ();
+ const int sp_regnum = gdbarch_sp_regnum (gdbarch);
+ ULONGEST stack_address;
+ regcache_cooked_read_unsigned (regcache, sp_regnum, &stack_address);
+ return (CORE_ADDR) stack_address;
+}
+
+void
+ravenscar_arch_ops::supply_one_register (struct regcache *regcache,
+ int regnum,
+ CORE_ADDR descriptor,
+ CORE_ADDR stack_base) const
+{
+ CORE_ADDR addr;
+ if (regnum >= first_stack_register && regnum <= last_stack_register)
+ addr = stack_base;
+ else
+ addr = descriptor;
+ addr += offsets[regnum];
+
+ struct gdbarch *gdbarch = regcache->arch ();
+ int size = register_size (gdbarch, regnum);
+ gdb_byte *buf = (gdb_byte *) alloca (size);
+ read_memory (addr, buf, size);
+ regcache->raw_supply (regnum, buf);
+}
+
+void
+ravenscar_arch_ops::fetch_registers (struct regcache *regcache,
+ int regnum) const
+{
+ struct gdbarch *gdbarch = regcache->arch ();
+ /* The tid is the thread_id field, which is a pointer to the thread. */
+ CORE_ADDR thread_descriptor_address
+ = (CORE_ADDR) regcache->ptid ().tid ();
+
+ int sp_regno = -1;
+ CORE_ADDR stack_address = 0;
+ if (regnum == -1
+ || (regnum >= first_stack_register && regnum <= last_stack_register))
+ {
+ /* We must supply SP for get_stack_base, so recurse. */
+ sp_regno = gdbarch_sp_regnum (gdbarch);
+ gdb_assert (!(sp_regno >= first_stack_register
+ && sp_regno <= last_stack_register));
+ fetch_registers (regcache, sp_regno);
+ stack_address = get_stack_base (regcache);
+ }
+
+ if (regnum == -1)
+ {
+ /* Fetch all registers. */
+ for (int reg = 0; reg < offsets.size (); ++reg)
+ if (reg != sp_regno && offsets[reg] != -1)
+ supply_one_register (regcache, reg, thread_descriptor_address,
+ stack_address);
+ }
+ else if (regnum < offsets.size () && offsets[regnum] != -1)
+ supply_one_register (regcache, regnum, thread_descriptor_address,
+ stack_address);
+}
+
+void
+ravenscar_arch_ops::store_one_register (struct regcache *regcache, int regnum,
+ CORE_ADDR descriptor,
+ CORE_ADDR stack_base) const
+{
+ CORE_ADDR addr;
+ if (regnum >= first_stack_register && regnum <= last_stack_register)
+ addr = stack_base;
+ else
+ addr = descriptor;
+ addr += offsets[regnum];
+
+ struct gdbarch *gdbarch = regcache->arch ();
+ int size = register_size (gdbarch, regnum);
+ gdb_byte *buf = (gdb_byte *) alloca (size);
+ regcache->raw_collect (regnum, buf);
+ write_memory (addr, buf, size);
+}
+
+void
+ravenscar_arch_ops::store_registers (struct regcache *regcache,
+ int regnum) const
+{
+ /* The tid is the thread_id field, which is a pointer to the thread. */
+ CORE_ADDR thread_descriptor_address
+ = (CORE_ADDR) regcache->ptid ().tid ();
+
+ CORE_ADDR stack_address = 0;
+ if (regnum == -1
+ || (regnum >= first_stack_register && regnum <= last_stack_register))
+ stack_address = get_stack_base (regcache);
+
+ if (regnum == -1)
+ {
+ /* Store all registers. */
+ for (int reg = 0; reg < offsets.size (); ++reg)
+ if (offsets[reg] != -1)
+ store_one_register (regcache, reg, thread_descriptor_address,
+ stack_address);
+ }
+ else if (regnum < offsets.size () && offsets[regnum] != -1)
+ store_one_register (regcache, regnum, thread_descriptor_address,
+ stack_address);
+}
+
/* Temporarily set the ptid of a regcache to some other value. When
this object is destroyed, the regcache's original ptid is
restored. */
@@ -506,7 +616,8 @@ private:
};
void
-ravenscar_thread_target::fetch_registers (struct regcache *regcache, int regnum)
+ravenscar_thread_target::fetch_registers (struct regcache *regcache,
+ int regnum)
{
ptid_t ptid = regcache->ptid ();