diff options
author | Tom Tromey <tromey@adacore.com> | 2022-05-03 08:18:14 -0600 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2022-06-14 09:08:29 -0600 |
commit | e73434e38f55e21cc33457ce3b218fa7b4592fec (patch) | |
tree | e3e443b6bbd889dc8cc9ff321a946a09052dbdd4 /gdb/ravenscar-thread.c | |
parent | 2808125fbb5f9c55f52e863283b7f1c5f0ef1a65 (diff) | |
download | binutils-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.c | 113 |
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 (); |