[PATCH 27/43] Add write_to_gdb_value method to dwarf_location

Zoran Zaric via Gdb-patches
2021-03-01T14:47:33Z

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 | 91 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)

diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index 10386cca858..7e5ba5d636b 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -472,6 +472,23 @@ class dwarf_location : public dwarf_entry
LONGEST bits_to_skip, size_t bit_size,
size_t location_bit_limit);

+/* 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 (struct frame_info *frame,
+ struct value *value,
+ int value_bit_offset,
+ LONGEST bits_to_skip, size_t bit_size,
+ size_t location_bit_limit);
+
protected:
/* Architecture of the location. */
struct gdbarch *m_arch;
@@ -550,6 +567,26 @@ dwarf_location::read_from_gdb_value (struct frame_info *frame,
"is unavailable"));
}

+void
+dwarf_location::write_to_gdb_value (struct frame_info *frame,
+ struct value *value,
+ int value_bit_offset,
+ LONGEST bits_to_skip, size_t bit_size,
+ size_t location_bit_limit)
+{
+ int optimized, unavailable;
+ bool big_endian = type_byte_order (value_type (value)) == BFD_ENDIAN_BIG;
+
+ this->read (frame, value_contents_raw (value), 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 : public dwarf_entry
@@ -1094,6 +1131,12 @@ class dwarf_implicit_pointer : public dwarf_location
mark_value_bits_optimized_out (value, bits_to_skip, bit_size);
}

+ void write_to_gdb_value (struct frame_info *frame,
+ struct value *value, int value_bit_offset,
+ LONGEST bits_to_skip, size_t bit_size,
+ size_t location_bit_limit) override
+ {}
+
private:
/* Per object file data of the implicit pointer. */
dwarf2_per_objfile *m_per_objfile;
@@ -1176,6 +1219,11 @@ class dwarf_composite : public dwarf_location
LONGEST bits_to_skip, size_t bit_size,
size_t location_bit_limit) override;

+ void write_to_gdb_value (struct frame_info *frame,
+ struct value *value, int value_bit_offset,
+ LONGEST bits_to_skip, size_t bit_size,
+ size_t location_bit_limit) override;
+
private:
/* Composite piece that contains a piece location
description and it's size. */
@@ -1331,6 +1379,49 @@ dwarf_composite::read_from_gdb_value (struct frame_info *frame,
}
}

+void
+dwarf_composite::write_to_gdb_value (struct frame_info *frame,
+ struct value *value, int value_bit_offset,
+ LONGEST bits_to_skip, size_t bit_size,
+ size_t location_bit_limit)
+{
+ 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].m_size;
+
+ if (total_bits_to_skip < piece_bit_size)
+ break;
+
+ total_bits_to_skip -= piece_bit_size;
+ }
+
+ for (; i < pieces_num; i++)
+ {
+ auto location = m_pieces[i].m_location;
+ ULONGEST piece_bit_size = m_pieces[i].m_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. */
--
2.17.1