diff options
author | Thiago Jung Bauermann <thiago.bauermann@linaro.org> | 2024-08-22 19:42:45 -0300 |
---|---|---|
committer | Thiago Jung Bauermann <thiago.bauermann@linaro.org> | 2025-01-09 22:47:21 -0300 |
commit | ad59259604f008e20490f9c82cf287d5a601a66c (patch) | |
tree | 4e99f99c286fa94b1eefe8effdcb5ebc2dbc7bbf | |
parent | 1f493519f703220bc072538ce3586f7363eba904 (diff) | |
download | binutils-ad59259604f008e20490f9c82cf287d5a601a66c.zip binutils-ad59259604f008e20490f9c82cf287d5a601a66c.tar.gz binutils-ad59259604f008e20490f9c82cf287d5a601a66c.tar.bz2 |
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>
-rw-r--r-- | gdb/frame-unwind.c | 18 | ||||
-rw-r--r-- | gdb/frame-unwind.h | 2 | ||||
-rw-r--r-- | gdb/jit.c | 2 | ||||
-rw-r--r-- | gdb/python/py-unwind.c | 7 | ||||
-rw-r--r-- | gdb/regcache.h | 5 | ||||
-rw-r--r-- | gdb/remote.c | 13 | ||||
-rw-r--r-- | gdb/trad-frame.h | 10 |
7 files changed, 35 insertions, 22 deletions
diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c index 352779f..6c6ca46 100644 --- a/gdb/frame-unwind.c +++ b/gdb/frame-unwind.c @@ -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; } diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h index 1799d36..480c9c8 100644 --- a/gdb/frame-unwind.h +++ b/gdb/frame-unwind.h @@ -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) diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c index 68deaf9..c1a01bf 100644 --- a/gdb/python/py-unwind.c +++ b/gdb/python/py-unwind.c @@ -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 ()); } } diff --git a/gdb/regcache.h b/gdb/regcache.h index 347c2b8..bbb17c8 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -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. */ diff --git a/gdb/remote.c b/gdb/remote.c index 8cb9050..79d91d6 100644 --- a/gdb/remote.c +++ b/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); } } diff --git a/gdb/trad-frame.h b/gdb/trad-frame.h index 40a3f74..abbc631 100644 --- a/gdb/trad-frame.h +++ b/gdb/trad-frame.h @@ -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; }; |