regcache: Zero-extend small registers described by a register map.
authorJohn Baldwin <jhb@FreeBSD.org>
Fri, 28 Jan 2022 19:14:37 +0000 (11:14 -0800)
committerJohn Baldwin <jhb@FreeBSD.org>
Fri, 28 Jan 2022 19:14:37 +0000 (11:14 -0800)
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).  Upcoming patches also require these semantics for
handling x86 segment register values stored in 16-bit slots on
FreeBSD.  Note that architecturally x86 segment registers are 16 bits,
but the x86 gdb architectures treat these registers as 32 bits.

gdb/regcache.c

index ab45277e3b6b31a343dd5517f99c49e5fd79f557..00d7a10e2892a3f05b3526263f339242af21bdba 100644 (file)
@@ -1164,7 +1164,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.  */