[4/8] regcache: Zero-extend small registers described by a register map.

Message ID 20210714140741.6460-5-jhb@FreeBSD.org
State New
Headers show
Series
  • Switch FreeBSD x86 to using register maps for GP registers
Related show

Commit Message

John Baldwin July 14, 2021, 2:07 p.m.
When registers are supplied via regcache_supply_register from a register
block described by a register map, registers may be stored in slots smaller
than GDB's native register size (e.g. x86 segment registers are 16 bits,
but the GDB registers for those are 32-bits).  regcache_collect_regset
is careful to zero-extend slots larger than a register size, but
regcache_supply_regset just used regcache::raw_supply_part and did not
initialize the upper bytes of a register value.

trad_frame_set_reg_regmap assumes these semantics (zero-extending
short registers) as I had misread the implementation of
regcache::transfer_regset and assumed it zero-extended short
registers.  In my specific use case (x86 segment registers stored as
16-bit values), I need the semantics of zero-extending a register
value in a smaller slot.
---
 gdb/regcache.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

-- 
2.31.1

Patch

diff --git a/gdb/regcache.c b/gdb/regcache.c
index 672da0556f..396923c8a5 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -1169,7 +1169,12 @@  regcache::transfer_regset_register (struct regcache *out_regcache, int regnum,
 	memset (out_buf + offs + reg_size, 0, slot_size - reg_size);
     }
   else if (in_buf != nullptr)
-    out_regcache->raw_supply_part (regnum, 0, reg_size, in_buf + offs);
+    {
+      /* Zero-extend the register value if the slot is smaller than the register.  */
+      if (slot_size < register_size (gdbarch, regnum))
+	out_regcache->raw_supply_zeroed (regnum);
+      out_regcache->raw_supply_part (regnum, 0, reg_size, in_buf + offs);
+    }
   else
     {
       /* Invalidate the register.  */