]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
GDB: trad-frame: Store length of value_bytes in trad_frame_saved_reg
authorThiago Jung Bauermann <thiago.bauermann@linaro.org>
Thu, 22 Aug 2024 22:42:45 +0000 (19:42 -0300)
committerThiago Jung Bauermann <thiago.bauermann@linaro.org>
Fri, 10 Jan 2025 01:47:21 +0000 (22:47 -0300)
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>
gdb/frame-unwind.c
gdb/frame-unwind.h
gdb/jit.c
gdb/python/py-unwind.c
gdb/regcache.h
gdb/remote.c
gdb/trad-frame.h

index 352779fcdcc67fa525686b5d852497e678a6d8ca..6c6ca46be437837b946295db674be673bc086f93 100644 (file)
@@ -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;
 }
 
index 1799d3625bd1c21cd69a1bf0ef2c9e20edb41a94..480c9c81ace81743ef4c88e001573f8ff6ff8731 100644 (file)
@@ -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
index 77d41bf86bad16c2434633f2ec6367f77adb615a..4b9400ab2f8efa4497955db8015ba5eda57f87bd 100644 (file)
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -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)
index 68deaf98d81f4d856421d3acf7d067c2c29a7dd8..c1a01bf7cfe4e76cab0f033a243702d8bb667a27 100644 (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)
     {
       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 ());
       }
   }
 
index 347c2b8ce9fbd5eea28961907c3a6d4e896ef7a2..bbb17c81adb6d441cc35e3c4d8ecf4a759556bef 100644 (file)
@@ -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.  */
index 8cb9050eaedade733890d8913a7edff8d7693563..79d91d6251ab1b0ba6c314b022c188c36fbc455c 100644 (file)
@@ -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 &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);
            }
        }
index 40a3f74d44a44292b2104b64413f919b1efbc5df..abbc631b6119f8272ad166dc41d0768bb3aff753 100644 (file)
@@ -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;
 };