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 *
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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. */
|
||||||
|
|||||||
13
gdb/remote.c
13
gdb/remote.c
@@ -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 ® : stop_reply->regcache)
|
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);
|
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_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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user