]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Add write_to_gdb_value method to dwarf_location
authorZoran Zaric <Zoran.Zaric@amd.com>
Wed, 24 Feb 2021 16:31:10 +0000 (16:31 +0000)
committerZoran Zaric <zoran.zaric@amd.com>
Fri, 5 Nov 2021 11:46:38 +0000 (11:46 +0000)
Similar story behind the previous read_from_gdb_value method applies
to the new write_to_gdb_value.

In the same way, reading the data from a location described and writing
that data to a struct value object, can be different from just generic
read the data from a buffer (location description read method).

To make this distinction clear, a new write_to_gdb_value method is
added to classes that derive from location description class.

gdb/ChangeLog:

        * dwarf2/expr.c (dwarf_location::write_to_gdb_value):
        New method.
        (dwarf_composite::write_to_gdb_value): New method.

gdb/dwarf2/expr.c

index e79d57fbfd4bee54d59e2062121ab5c1a173c3a6..b2fb0099b0e78fd460d5c1a758261ef7c26f8b84 100644 (file)
@@ -441,6 +441,22 @@ public:
                                    LONGEST bits_to_skip, size_t bit_size,
                                    size_t location_bit_limit) const;
 
+/* Write data to the VALUE contents from the location specified by the
+   location description.
+
+   The write operation is performed in the context of a FRAME.
+   BIT_SIZE is the number of bits to read.  VALUE_BIT_OFFSET is a bit
+   offset into a VALUE content and BITS_TO_SKIP is a bit offset into
+   the location.  LOCATION_BIT_LIMIT is a maximum number of bits that
+   location can hold, where value zero signifies that there is no such
+   restriction.
+
+   Note that some location types can be read without a FRAME context.  */
+  virtual void write_to_gdb_value (frame_info *frame, struct value *value,
+                                  int value_bit_offset,
+                                  LONGEST bits_to_skip, size_t bit_size,
+                                  size_t location_bit_limit) const;
+
 protected:
   /* Architecture of the location.  */
   gdbarch *m_arch;
@@ -483,6 +499,25 @@ dwarf_location::read_from_gdb_value (frame_info *frame, struct value *value,
                   "is unavailable"));
 }
 
+void
+dwarf_location::write_to_gdb_value (frame_info *frame, struct value *value,
+                                   int value_bit_offset,
+                                   LONGEST bits_to_skip, size_t bit_size,
+                                   size_t location_bit_limit) const
+{
+  int optimized, unavailable;
+  bool big_endian = type_byte_order (value_type (value)) == BFD_ENDIAN_BIG;
+
+  this->read (frame, value_contents_raw (value).data (), value_bit_offset,
+             bit_size, bits_to_skip, location_bit_limit,
+             big_endian, &optimized, &unavailable);
+
+  if (optimized)
+    mark_value_bits_optimized_out (value, value_bit_offset, bit_size);
+  if (unavailable)
+    mark_value_bits_unavailable (value, value_bit_offset, bit_size);
+}
+
 /* Value entry found on a DWARF expression evaluation stack.  */
 
 class dwarf_value final : public dwarf_entry
@@ -1047,6 +1082,12 @@ public:
     mark_value_bits_optimized_out (value, bits_to_skip, bit_size);
   }
 
+  void write_to_gdb_value (frame_info *frame, struct value *value,
+                          int value_bit_offset,
+                          LONGEST bits_to_skip, size_t bit_size,
+                          size_t location_bit_limit) const override
+  {}
+
 private:
   /* Per object file data of the implicit pointer.  */
   dwarf2_per_objfile *m_per_objfile;
@@ -1128,6 +1169,11 @@ public:
                            LONGEST bits_to_skip, size_t bit_size,
                            size_t location_bit_limit) const override;
 
+  void write_to_gdb_value (frame_info *frame, struct value *value,
+                          int value_bit_offset,
+                          LONGEST bits_to_skip, size_t bit_size,
+                          size_t location_bit_limit) const override;
+
 private:
   /* Composite piece that contains a piece location
      description and it's size.  */
@@ -1281,6 +1327,49 @@ dwarf_composite::read_from_gdb_value (frame_info *frame, struct value *value,
     }
 }
 
+void
+dwarf_composite::write_to_gdb_value (frame_info *frame, struct value *value,
+                                    int value_bit_offset,
+                                    LONGEST bits_to_skip, size_t bit_size,
+                                    size_t location_bit_limit) const
+{
+  ULONGEST total_bits_to_skip
+    = bits_to_skip + HOST_CHAR_BIT * m_offset + m_bit_suboffset;
+  ULONGEST remaining_bit_size = bit_size;
+  ULONGEST bit_offset = value_bit_offset;
+  unsigned int pieces_num = m_pieces.size ();
+  unsigned int i;
+
+  /* Advance to the first non-skipped piece.  */
+  for (i = 0; i < pieces_num; i++)
+    {
+      ULONGEST piece_bit_size = m_pieces[i].size;
+
+      if (total_bits_to_skip < piece_bit_size)
+       break;
+
+      total_bits_to_skip -= piece_bit_size;
+    }
+
+  for (; i < pieces_num; i++)
+    {
+      const dwarf_location &location = *m_pieces[i].location;
+      ULONGEST piece_bit_size = m_pieces[i].size;
+      size_t this_bit_size = piece_bit_size - total_bits_to_skip;
+
+      if (this_bit_size > remaining_bit_size)
+       this_bit_size = remaining_bit_size;
+
+      location.write_to_gdb_value (frame, value, bit_offset,
+                                  total_bits_to_skip, this_bit_size,
+                                  piece_bit_size);
+
+      bit_offset += this_bit_size;
+      remaining_bit_size -= this_bit_size;
+      total_bits_to_skip = 0;
+    }
+}
+
 struct piece_closure
 {
   /* Reference count.  */