GDB: trad-frame: Store length of value_bytes in trad_frame_saved_reg

The goal is to ensure that it is available in frame_unwind_got_bytes () to
make sure that the provided buf isn't larger than the size of the register
being provisioned.

In the process, regcache's cached_reg_t::data also needed to be
converted to a gdb::byte_vector, so that the register contents' size can
be tracked.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
This commit is contained in:
Thiago Jung Bauermann
2024-08-22 19:42:45 -03:00
parent 1f493519f7
commit ad59259604
7 changed files with 35 additions and 22 deletions

View File

@@ -313,14 +313,26 @@ frame_unwind_got_constant (const frame_info_ptr &frame, int regnum,
} }
struct value * struct value *
frame_unwind_got_bytes (const frame_info_ptr &frame, int regnum, const gdb_byte *buf) frame_unwind_got_bytes (const frame_info_ptr &frame, int regnum,
gdb::array_view<const gdb_byte> buf)
{ {
struct gdbarch *gdbarch = frame_unwind_arch (frame); struct gdbarch *gdbarch = frame_unwind_arch (frame);
struct value *reg_val; struct value *reg_val;
reg_val = value::zero (register_type (gdbarch, regnum), not_lval); reg_val = value::zero (register_type (gdbarch, regnum), not_lval);
memcpy (reg_val->contents_raw ().data (), buf, gdb::array_view<gdb_byte> val_contents = reg_val->contents_raw ();
register_size (gdbarch, regnum));
/* The value's contents buffer is zeroed on allocation so if buf is
smaller, the remaining space will be filled with zero.
This can happen when unwinding through signal frames. For example, if
an AArch64 program doesn't use SVE, then the Linux kernel will only
save in the signal frame the first 128 bits of the vector registers,
which is their minimum size, even if the vector length says they're
bigger. */
gdb_assert (buf.size () <= val_contents.size ());
memcpy (val_contents.data (), buf.data (), buf.size ());
return reg_val; return reg_val;
} }

View File

@@ -226,7 +226,7 @@ value *frame_unwind_got_constant (const frame_info_ptr &frame, int regnum,
inside BUF. */ inside BUF. */
value *frame_unwind_got_bytes (const frame_info_ptr &frame, int regnum, value *frame_unwind_got_bytes (const frame_info_ptr &frame, int regnum,
const gdb_byte *buf); gdb::array_view<const gdb_byte> buf);
/* Return a value which indicates that FRAME's saved version of REGNUM /* Return a value which indicates that FRAME's saved version of REGNUM
has a known constant (computed) value of ADDR. Convert the has a known constant (computed) value of ADDR. Convert the

View File

@@ -1096,7 +1096,7 @@ jit_frame_prev_register (const frame_info_ptr &this_frame, void **cache, int reg
return frame_unwind_got_optimized (this_frame, reg); return frame_unwind_got_optimized (this_frame, reg);
gdbarch = priv->regcache->arch (); gdbarch = priv->regcache->arch ();
gdb_byte *buf = (gdb_byte *) alloca (register_size (gdbarch, reg)); gdb::byte_vector buf (register_size (gdbarch, reg));
enum register_status status = priv->regcache->cooked_read (reg, buf); enum register_status status = priv->regcache->cooked_read (reg, buf);
if (status == REG_VALID) if (status == REG_VALID)

View File

@@ -812,7 +812,7 @@ pyuw_prev_register (const frame_info_ptr &this_frame, void **cache_ptr,
for (; reg_info < reg_info_end; ++reg_info) for (; reg_info < reg_info_end; ++reg_info)
{ {
if (regnum == reg_info->num) if (regnum == reg_info->num)
return frame_unwind_got_bytes (this_frame, regnum, reg_info->data.get ()); return frame_unwind_got_bytes (this_frame, regnum, reg_info->data);
} }
return frame_unwind_got_optimized (this_frame, regnum); return frame_unwind_got_optimized (this_frame, regnum);
@@ -936,8 +936,9 @@ pyuw_sniffer (const struct frame_unwind *self, const frame_info_ptr &this_frame,
cached_reg_t *cached = new (&cached_frame->reg[i]) cached_reg_t (); cached_reg_t *cached = new (&cached_frame->reg[i]) cached_reg_t ();
cached->num = reg->number; cached->num = reg->number;
cached->data.reset ((gdb_byte *) xmalloc (data_size)); cached->data.resize (data_size);
memcpy (cached->data.get (), value->contents ().data (), data_size); gdb::array_view<const gdb_byte> contents = value->contents ();
cached->data.assign (contents.begin (), contents.end ());
} }
} }

View File

@@ -178,10 +178,7 @@ using register_read_ftype
struct cached_reg_t struct cached_reg_t
{ {
int num; int num;
gdb::unique_xmalloc_ptr<gdb_byte> data; gdb::byte_vector data;
cached_reg_t () = default;
cached_reg_t (cached_reg_t &&rhs) = default;
}; };
/* Buffer of registers. */ /* Buffer of registers. */

View File

@@ -8224,16 +8224,15 @@ Packet: '%s'\n"),
Packet: '%s'\n"), Packet: '%s'\n"),
hex_string (pnum), p, buf); hex_string (pnum), p, buf);
int reg_size = register_size (event->arch, reg->regnum);
cached_reg.num = reg->regnum; cached_reg.num = reg->regnum;
cached_reg.data.reset ((gdb_byte *) cached_reg.data.resize (reg_size);
xmalloc (register_size (event->arch,
reg->regnum)));
p = p1 + 1; p = p1 + 1;
fieldsize = hex2bin (p, cached_reg.data.get (), fieldsize = hex2bin (p, cached_reg.data.data (),
register_size (event->arch, reg->regnum)); cached_reg.data.size ());
p += 2 * fieldsize; p += 2 * fieldsize;
if (fieldsize < register_size (event->arch, reg->regnum)) if (fieldsize < reg_size)
warning (_("Remote reply is too short: %s"), buf); warning (_("Remote reply is too short: %s"), buf);
event->regcache.push_back (std::move (cached_reg)); event->regcache.push_back (std::move (cached_reg));
@@ -8572,7 +8571,7 @@ remote_target::process_stop_reply (stop_reply_up stop_reply,
for (cached_reg_t &reg : stop_reply->regcache) for (cached_reg_t &reg : stop_reply->regcache)
{ {
regcache->raw_supply (reg.num, reg.data.get ()); regcache->raw_supply (reg.num, reg.data);
rs->last_seen_expedited_registers.insert (reg.num); rs->last_seen_expedited_registers.insert (reg.num);
} }
} }

View File

@@ -122,6 +122,7 @@ struct trad_frame_saved_reg
m_kind = trad_frame_saved_reg_kind::VALUE_BYTES; m_kind = trad_frame_saved_reg_kind::VALUE_BYTES;
m_reg.value_bytes = data; m_reg.value_bytes = data;
m_reg.bytes_len = bytes.size ();
} }
/* Getters */ /* Getters */
@@ -144,10 +145,10 @@ struct trad_frame_saved_reg
return m_reg.addr; return m_reg.addr;
} }
const gdb_byte *value_bytes () const gdb::array_view<const gdb_byte> value_bytes () const
{ {
gdb_assert (m_kind == trad_frame_saved_reg_kind::VALUE_BYTES); gdb_assert (m_kind == trad_frame_saved_reg_kind::VALUE_BYTES);
return m_reg.value_bytes; return { m_reg.value_bytes, m_reg.bytes_len };
} }
/* Convenience functions, return true if the register has been /* Convenience functions, return true if the register has been
@@ -185,7 +186,10 @@ private:
LONGEST value; LONGEST value;
int realreg; int realreg;
LONGEST addr; LONGEST addr;
struct {
const gdb_byte *value_bytes; const gdb_byte *value_bytes;
size_t bytes_len;
};
} m_reg; } m_reg;
}; };