forked from Imagelibrary/binutils-gdb
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:
@@ -313,14 +313,26 @@ frame_unwind_got_constant (const frame_info_ptr &frame, int regnum,
|
||||
}
|
||||
|
||||
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 value *reg_val;
|
||||
|
||||
reg_val = value::zero (register_type (gdbarch, regnum), not_lval);
|
||||
memcpy (reg_val->contents_raw ().data (), buf,
|
||||
register_size (gdbarch, regnum));
|
||||
gdb::array_view<gdb_byte> val_contents = reg_val->contents_raw ();
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ value *frame_unwind_got_constant (const frame_info_ptr &frame, int regnum,
|
||||
inside BUF. */
|
||||
|
||||
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
|
||||
has a known constant (computed) value of ADDR. Convert the
|
||||
|
||||
@@ -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);
|
||||
|
||||
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);
|
||||
|
||||
if (status == REG_VALID)
|
||||
|
||||
@@ -812,7 +812,7 @@ pyuw_prev_register (const frame_info_ptr &this_frame, void **cache_ptr,
|
||||
for (; reg_info < reg_info_end; ++reg_info)
|
||||
{
|
||||
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);
|
||||
@@ -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->num = reg->number;
|
||||
cached->data.reset ((gdb_byte *) xmalloc (data_size));
|
||||
memcpy (cached->data.get (), value->contents ().data (), data_size);
|
||||
cached->data.resize (data_size);
|
||||
gdb::array_view<const gdb_byte> contents = value->contents ();
|
||||
cached->data.assign (contents.begin (), contents.end ());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -178,10 +178,7 @@ using register_read_ftype
|
||||
struct cached_reg_t
|
||||
{
|
||||
int num;
|
||||
gdb::unique_xmalloc_ptr<gdb_byte> data;
|
||||
|
||||
cached_reg_t () = default;
|
||||
cached_reg_t (cached_reg_t &&rhs) = default;
|
||||
gdb::byte_vector data;
|
||||
};
|
||||
|
||||
/* Buffer of registers. */
|
||||
|
||||
13
gdb/remote.c
13
gdb/remote.c
@@ -8224,16 +8224,15 @@ Packet: '%s'\n"),
|
||||
Packet: '%s'\n"),
|
||||
hex_string (pnum), p, buf);
|
||||
|
||||
int reg_size = register_size (event->arch, reg->regnum);
|
||||
cached_reg.num = reg->regnum;
|
||||
cached_reg.data.reset ((gdb_byte *)
|
||||
xmalloc (register_size (event->arch,
|
||||
reg->regnum)));
|
||||
cached_reg.data.resize (reg_size);
|
||||
|
||||
p = p1 + 1;
|
||||
fieldsize = hex2bin (p, cached_reg.data.get (),
|
||||
register_size (event->arch, reg->regnum));
|
||||
fieldsize = hex2bin (p, cached_reg.data.data (),
|
||||
cached_reg.data.size ());
|
||||
p += 2 * fieldsize;
|
||||
if (fieldsize < register_size (event->arch, reg->regnum))
|
||||
if (fieldsize < reg_size)
|
||||
warning (_("Remote reply is too short: %s"), buf);
|
||||
|
||||
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 ® : 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +122,7 @@ struct trad_frame_saved_reg
|
||||
|
||||
m_kind = trad_frame_saved_reg_kind::VALUE_BYTES;
|
||||
m_reg.value_bytes = data;
|
||||
m_reg.bytes_len = bytes.size ();
|
||||
}
|
||||
|
||||
/* Getters */
|
||||
@@ -144,10 +145,10 @@ struct trad_frame_saved_reg
|
||||
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);
|
||||
return m_reg.value_bytes;
|
||||
return { m_reg.value_bytes, m_reg.bytes_len };
|
||||
}
|
||||
|
||||
/* Convenience functions, return true if the register has been
|
||||
@@ -185,7 +186,10 @@ private:
|
||||
LONGEST value;
|
||||
int realreg;
|
||||
LONGEST addr;
|
||||
const gdb_byte *value_bytes;
|
||||
struct {
|
||||
const gdb_byte *value_bytes;
|
||||
size_t bytes_len;
|
||||
};
|
||||
} m_reg;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user