From: Zoran Zaric <zoran.zaric@amd.com>
To: <gdb-patches@sourceware.org>
Subject: [PATCH v4 15/28] Add to_gdb_value method to DWARF entry class
Date: Fri, 5 Nov 2021 11:38:36 +0000 [thread overview]
Message-ID: <20211105113849.118800-16-zoran.zaric@amd.com> (raw)
In-Reply-To: <20211105113849.118800-1-zoran.zaric@amd.com>
From: Zoran Zaric <Zoran.Zaric@amd.com>
The result of the DWARF expression evaluation is expected to be in a
format of a struct value object. This means that a new to_gdb_value
method is needed for both dwarf_location and dwarf_value classes.
In the case of the dwarf_value class, the conversion between that
class and struct value can happen often, this is why it is usefull to
cache once created struct value object in a dwarf_value
m_gdb_value member to reduce the number of conversions needed.
However, this also means that the to_gdb_value method cant be declared
as a constant method.
In the case of classes that derive from dwarf_location class, there is
now a need for a cloning method because the encapsulating
computed_closure class has a life span separated from the expression
evaluator.
gdb/ChangeLog:
* dwarf2/expr.c (dwarf_entry::to_gdb_value): New method.
(dwarf_location::to_gdb_value): New method.
(dwarf_location::clone_location): New method.
(dwarf_value::m_gdb_value): New member.
(dwarf_value::to_gdb_value): New method.
(dwarf_undefined::to_gdb_value): New method.
(dwarf_undefined::clone_location): New method.
(dwarf_memory::to_gdb_value): New method.
(dwarf_memory::clone_location): New method.
(dwarf_register::to_gdb_value): New method.
(dwarf_register::clone_location): New method.
(dwarf_implicit::to_gdb_value): New method.
(dwarf_implicit::clone_location): New method.
(dwarf_implicit_pointer::to_gdb_value): New method.
(dwarf_implicit_pointer::clone_location): New method.
(dwarf_composite::to_gdb_value): New method.
(dwarf_composite::clone_location): New method.
---
gdb/dwarf2/expr.c | 283 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 283 insertions(+)
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index d76dddab643..ac26b4c5613 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -436,6 +436,10 @@ class dwarf_location : public dwarf_entry
public:
virtual ~dwarf_location () = default;
+ /* Clone the location and return the result as a
+ dwarf_location pointer. */
+ virtual std::unique_ptr<dwarf_location> clone_location () const = 0;
+
/* Add bit offset to the location description. */
void add_bit_offset (LONGEST bit_offset)
{
@@ -588,6 +592,16 @@ class dwarf_location : public dwarf_entry
return false;
}
+ /* Convert DWARF location description to the matching struct value
+ representation of the given TYPE type in a given FRAME.
+ SUBOBJ_TYPE information if specified, will be used for more
+ precise description of the source variable type information.
+ Where SUBOBJ_OFFSET defines an offset into the DWARF entry
+ contents. */
+ virtual value *to_gdb_value (frame_info *frame, struct type *type,
+ struct type *subobj_type,
+ LONGEST subobj_offset) const = 0;
+
protected:
/* Architecture of the location. */
gdbarch *m_arch;
@@ -670,6 +684,15 @@ class dwarf_value final : public dwarf_entry
pack_long (m_contents.data (), type, value);
}
+ dwarf_value (value *gdb_value)
+ {
+ m_type = value_type (gdb_value);
+ gdb::array_view<const gdb_byte> contents = value_contents_raw (gdb_value);
+ m_contents
+ = std::move (gdb::byte_vector (contents.begin (), contents.end ()));
+ m_gdb_value = gdb_value;
+ }
+
gdb::array_view<const gdb_byte> contents () const
{
return m_contents;
@@ -694,12 +717,22 @@ class dwarf_value final : public dwarf_entry
ARCH defines an architecture of the location described. */
dwarf_location_up to_location (struct gdbarch *arch) const;
+ /* Convert DWARF value to the matching struct value representation
+ of the given TYPE type. Where OFFSET defines an offset into the
+ DWARF value contents. */
+ value *to_gdb_value (struct type *type, LONGEST offset = 0);
+
private:
/* Value contents as a stream of bytes in target byte order. */
gdb::byte_vector m_contents;
/* Type of the value held by the entry. */
struct type *m_type;
+
+ /* Struct value representation of the DWARF value. Only used until
+ a set of arithmethic/logic operations that works with this class
+ are implemented. */
+ value *m_gdb_value = nullptr;
};
using dwarf_value_up = std::unique_ptr<dwarf_value>;
@@ -741,6 +774,23 @@ dwarf_location::deref (frame_info *frame, const property_addr_info *addr_info,
(gdb::array_view<const gdb_byte> (read_buf), type);
}
+value *
+dwarf_value::to_gdb_value (struct type *type, LONGEST offset)
+{
+ if (m_gdb_value != nullptr)
+ return m_gdb_value;
+
+ size_t type_len = TYPE_LENGTH (type);
+
+ if (offset + type_len > TYPE_LENGTH (m_type))
+ invalid_synthetic_pointer ();
+
+ m_gdb_value = allocate_value (type);
+ memcpy (value_contents_raw (m_gdb_value).data (),
+ m_contents.data () + offset, type_len);
+ return m_gdb_value;
+}
+
/* Undefined location description entry. This is a special location
description type that describes the location description that is
not known. */
@@ -752,6 +802,11 @@ class dwarf_undefined final : public dwarf_location
: dwarf_location (arch, 0)
{}
+ dwarf_location_up clone_location () const override
+ {
+ return make_unique<dwarf_undefined> (*this);
+ }
+
void read (frame_info *frame, gdb_byte *buf, int buf_bit_offset,
size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit,
bool big_endian, int *optimized, int *unavailable) const override
@@ -774,6 +829,19 @@ class dwarf_undefined final : public dwarf_location
{
return true;
}
+
+ value *to_gdb_value (frame_info *frame, struct type *type,
+ struct type *subobj_type,
+ LONGEST subobj_offset) const override
+ {
+ gdb_assert (type != nullptr);
+ gdb_assert (subobj_type != nullptr);
+
+ value *retval = allocate_value (subobj_type);
+ mark_value_bytes_optimized_out (retval, subobj_offset,
+ TYPE_LENGTH (subobj_type));
+ return retval;
+ }
};
class dwarf_memory final : public dwarf_location
@@ -783,6 +851,11 @@ class dwarf_memory final : public dwarf_location
: dwarf_location (arch, offset), m_stack (stack)
{}
+ dwarf_location_up clone_location () const override
+ {
+ return make_unique<dwarf_memory> (*this);
+ }
+
void set_stack (bool stack)
{
m_stack = stack;
@@ -805,6 +878,10 @@ class dwarf_memory final : public dwarf_location
struct type *type,
size_t size = 0) const override;
+ value *to_gdb_value (frame_info *frame, struct type *type,
+ struct type *subobj_type,
+ LONGEST subobj_offset) const override;
+
private:
/* True if the location belongs to a stack memory region. */
bool m_stack;
@@ -996,6 +1073,27 @@ dwarf_memory::deref (frame_info *frame, const property_addr_info *addr_info,
(gdb::array_view<const gdb_byte> (read_buf), type);
}
+value *
+dwarf_memory::to_gdb_value (frame_info *frame, struct type *type,
+ struct type *subobj_type,
+ LONGEST subobj_offset) const
+{
+ gdb_assert (type != nullptr);
+ gdb_assert (subobj_type != nullptr);
+
+ struct type *ptr_type = builtin_type (m_arch)->builtin_data_ptr;
+
+ if (subobj_type->code () == TYPE_CODE_FUNC
+ || subobj_type->code () == TYPE_CODE_METHOD)
+ ptr_type = builtin_type (m_arch)->builtin_func_ptr;
+
+ CORE_ADDR address
+ = value_as_address (value_from_pointer (ptr_type, m_offset));
+ value *retval = value_at_lazy (subobj_type, address + subobj_offset);
+ set_value_stack (retval, m_stack);
+ return retval;
+}
+
/* Register location description entry. */
class dwarf_register final : public dwarf_location
@@ -1005,6 +1103,11 @@ class dwarf_register final : public dwarf_location
: dwarf_location (arch, offset), m_regnum (regnum)
{}
+ dwarf_location_up clone_location () const override
+ {
+ return make_unique<dwarf_register> (*this);
+ }
+
void read (frame_info *frame, gdb_byte *buf, int buf_bit_offset,
size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit,
bool big_endian, int *optimized, int *unavailable) const override;
@@ -1018,6 +1121,11 @@ class dwarf_register final : public dwarf_location
LONGEST bits_to_skip, size_t bit_size,
size_t location_bit_limit) const override;
+ value *to_gdb_value (frame_info *frame, struct type *type,
+ struct type *subobj_type,
+ LONGEST subobj_offset) const override;
+
+
private:
/* DWARF register number. */
unsigned int m_regnum;
@@ -1129,6 +1237,55 @@ dwarf_register::is_optimized_out (frame_info *frame, bool big_endian,
return false;
}
+value *
+dwarf_register::to_gdb_value (frame_info *frame, struct type *type,
+ struct type *subobj_type,
+ LONGEST subobj_offset) const
+{
+ gdb_assert (type != nullptr);
+ gdb_assert (subobj_type != nullptr);
+
+ gdbarch *frame_arch = get_frame_arch (frame);
+ int gdb_regnum = dwarf_reg_to_regnum_or_error (frame_arch, m_regnum);
+
+ if (frame == nullptr)
+ internal_error (__FILE__, __LINE__, _("invalid frame information"));
+
+ /* Construct the value. */
+ value *retval
+ = gdbarch_value_from_register (frame_arch, type,
+ gdb_regnum, get_frame_id (frame));
+
+ /* DWARF evaluator only supports targets with byte size of 8 bits,
+ while struct value offset is expressed in memory unit size. */
+ int unit_size = gdbarch_addressable_memory_unit_size (m_arch);
+ LONGEST retval_offset = value_offset (retval) * unit_size;
+
+ if (type_byte_order (type) == BFD_ENDIAN_BIG
+ && TYPE_LENGTH (type) + m_offset < retval_offset)
+ /* Big-endian, and we want less than full size. */
+ set_value_offset (retval, (retval_offset - m_offset) / unit_size);
+ else
+ set_value_offset (retval, (retval_offset + m_offset) / unit_size);
+
+ /* Get the data. */
+ read_frame_register_value (retval, frame);
+
+ if (value_optimized_out (retval))
+ {
+ /* This means the register has undefined value / was not saved.
+ As we're computing the location of some variable etc. in the
+ program, not a value for inspecting a register ($pc, $sp, etc.),
+ return a generic optimized out value instead, so that we show
+ <optimized out> instead of <not saved>. */
+ value *temp = allocate_value (subobj_type);
+ value_contents_copy (temp, 0, retval, 0, TYPE_LENGTH (subobj_type));
+ retval = temp;
+ }
+
+ return retval;
+}
+
/* Implicit location description entry. Describes a location
description not found on the target but instead saved in a
gdb-allocated buffer. */
@@ -1144,6 +1301,11 @@ class dwarf_implicit final : public dwarf_location
m_byte_order (byte_order)
{}
+ dwarf_location_up clone_location () const override
+ {
+ return make_unique<dwarf_implicit> (*this);
+ }
+
void read (frame_info *frame, gdb_byte *buf, int buf_bit_offset,
size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit,
bool big_endian, int *optimized, int *unavailable) const override;
@@ -1164,6 +1326,10 @@ class dwarf_implicit final : public dwarf_location
return true;
}
+ value *to_gdb_value (frame_info *frame, struct type *type,
+ struct type *subobj_type,
+ LONGEST subobj_offset) const override;
+
private:
/* Implicit location contents as a stream of bytes in target byte-order. */
gdb::byte_vector m_contents;
@@ -1211,6 +1377,36 @@ dwarf_implicit::read (frame_info *frame, gdb_byte *buf,
total_bits_to_skip, bit_size, big_endian);
}
+value *
+dwarf_implicit::to_gdb_value (frame_info *frame, struct type *type,
+ struct type *subobj_type,
+ LONGEST subobj_offset) const
+{
+ gdb_assert (type != nullptr);
+ gdb_assert (subobj_type != nullptr);
+
+ size_t subtype_len = TYPE_LENGTH (subobj_type);
+ size_t type_len = TYPE_LENGTH (type);
+
+ /* To be compatible with expected error output of the existing
+ tests, the invalid synthetic pointer is not reported for
+ DW_OP_implicit_value operation. */
+ if (subobj_offset + subtype_len > type_len
+ && m_byte_order != BFD_ENDIAN_UNKNOWN)
+ invalid_synthetic_pointer ();
+
+ value *retval = allocate_value (subobj_type);
+
+ /* The given offset is relative to the actual object. */
+ if (m_byte_order == BFD_ENDIAN_BIG)
+ subobj_offset += m_contents.size () - type_len;
+
+ memcpy ((void *) value_contents_raw (retval).data (),
+ (void *) (m_contents.data () + subobj_offset), subtype_len);
+
+ return retval;
+}
+
/* Implicit pointer location description entry. */
class dwarf_implicit_pointer final : public dwarf_location
@@ -1226,6 +1422,11 @@ class dwarf_implicit_pointer final : public dwarf_location
m_addr_size (addr_size), m_die_offset (die_offset)
{}
+ dwarf_location_up clone_location () const override
+ {
+ return make_unique<dwarf_implicit_pointer> (*this);
+ }
+
void read (frame_info *frame, gdb_byte *buf, int buf_bit_offset,
size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit,
bool big_endian, int *optimized, int *unavailable) const override;
@@ -1265,6 +1466,10 @@ class dwarf_implicit_pointer final : public dwarf_location
LONGEST bit_offset = 0,
int bit_length = 0) const override;
+ value *to_gdb_value (frame_info *frame, struct type *type,
+ struct type *subobj_type,
+ LONGEST subobj_offset) const override;
+
private:
/* Per object file data of the implicit pointer. */
dwarf2_per_objfile *m_per_objfile;
@@ -1328,6 +1533,26 @@ dwarf_implicit_pointer::indirect_implicit_ptr (frame_info *frame,
m_per_cu, m_per_objfile, frame, type);
}
+value *
+dwarf_implicit_pointer::to_gdb_value (frame_info *frame, struct type *type,
+ struct type *subobj_type,
+ LONGEST subobj_offset) const
+{
+ gdb_assert (type != nullptr);
+ gdb_assert (subobj_type != nullptr);
+
+ computed_closure *closure
+ = new computed_closure (make_unique<dwarf_implicit_pointer> (*this),
+ get_frame_id (frame));
+ closure->incref ();
+
+ value *retval
+ = allocate_computed_value (subobj_type, &closure_value_funcs, closure);
+ set_value_offset (retval, subobj_offset);
+
+ return retval;
+}
+
/* Composite location description entry. */
class dwarf_composite final : public dwarf_location
@@ -1337,6 +1562,11 @@ class dwarf_composite final : public dwarf_location
: dwarf_location (arch, 0), m_per_cu (per_cu)
{}
+ dwarf_location_up clone_location () const override
+ {
+ return make_unique<dwarf_composite> (*this);
+ }
+
void add_piece (std::unique_ptr<dwarf_location> location, ULONGEST bit_size)
{
gdb_assert (location != nullptr);
@@ -1373,6 +1603,10 @@ class dwarf_composite final : public dwarf_location
LONGEST bits_to_skip, size_t bit_size,
size_t location_bit_limit) const override;
+ value *to_gdb_value (frame_info *frame, struct type *type,
+ struct type *subobj_type,
+ LONGEST subobj_offset) const override;
+
private:
/* Composite piece that contains a piece location
description and it's size. */
@@ -1383,6 +1617,17 @@ class dwarf_composite final : public dwarf_location
: location (std::move (location)), size (size)
{}
+ /* We need to make a piece copyiable, because dwarf_composite can be
+ copied / cloned. */
+ piece (const piece &other)
+ : location (other.location->clone_location ()), size (other.size)
+ {}
+
+ piece (piece &&) = default;
+
+ void operator=(const piece &) = delete;
+ void operator=(piece &&) = delete;
+
std::unique_ptr<dwarf_location> location;
ULONGEST size;
};
@@ -1682,6 +1927,44 @@ dwarf_composite::is_optimized_out (frame_info *frame, bool big_endian,
return false;
}
+value *
+dwarf_composite::to_gdb_value (frame_info *frame, struct type *type,
+ struct type *subobj_type,
+ LONGEST subobj_offset) const
+{
+ gdb_assert (type != nullptr);
+ gdb_assert (subobj_type != nullptr);
+
+ ULONGEST bit_size = 0;
+
+ for (const piece &piece : m_pieces)
+ bit_size += piece.size;
+
+ /* Complain if the expression is larger than the size of the
+ outer type. */
+ if (bit_size > HOST_CHAR_BIT * TYPE_LENGTH (type))
+ invalid_synthetic_pointer ();
+
+ computed_closure *closure;
+
+ /* If compilation unit information is not available
+ we are in a CFI context. */
+ if (m_per_cu == nullptr)
+ closure = new computed_closure (make_unique<dwarf_composite> (*this),
+ frame);
+ else
+ closure = new computed_closure (make_unique<dwarf_composite> (*this),
+ get_frame_id (frame));
+
+ closure->incref ();
+
+ value *retval
+ = allocate_computed_value (subobj_type, &closure_value_funcs, closure);
+ set_value_offset (retval, subobj_offset);
+
+ return retval;
+}
+
static void *
copy_value_closure (const value *v)
{
--
2.17.1
next prev parent reply other threads:[~2021-11-05 11:39 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-05 11:38 [PATCH v4 00/28] Allow location description on the DWARF stack Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 01/28] Add new register access interface to expr.c Zoran Zaric
2021-12-14 20:34 ` Tom Tromey
2021-11-05 11:38 ` [PATCH v4 02/28] Add new memory " Zoran Zaric
2021-12-14 20:42 ` Tom Tromey
2021-11-05 11:38 ` [PATCH v4 03/28] Add new classes that model DWARF stack element Zoran Zaric
2021-12-14 21:10 ` Tom Tromey
2022-01-12 10:23 ` Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 04/28] Add to_location method to dwarf_value class Zoran Zaric
2021-12-14 21:16 ` Tom Tromey
2022-01-12 10:51 ` Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 05/28] Add to_value method to dwarf_location class Zoran Zaric
2021-12-14 21:34 ` Tom Tromey
2022-01-12 12:14 ` Zoran Zaric
2022-01-12 18:42 ` Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 06/28] Add read method to location description classes Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 07/28] Add write " Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 08/28] Add deref " Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 09/28] Add read_from_gdb_value method to dwarf_location Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 10/28] Add write_to_gdb_value " Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 11/28] Add is_implicit_ptr_at " Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 12/28] Add indirect_implicit_ptr to dwarf_location class Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 13/28] Add is_optimized_out " Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 14/28] Add new computed struct value callback interface Zoran Zaric
2021-11-05 11:38 ` Zoran Zaric [this message]
2021-11-05 11:38 ` [PATCH v4 16/28] Change DWARF stack to use new dwarf_entry classes Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 17/28] Remove old computed struct value callbacks Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 18/28] Comments cleanup between expr.h and expr.c Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 19/28] Remove dwarf_expr_context from expr.h interface Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 20/28] Move read_addr_from_reg function to frame.c Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 21/28] Add frame info check to DW_OP_reg operations Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 22/28] Remove DWARF expression composition check Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 23/28] Add support for any location description in CFI Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 24/28] Add DWARF operations for byte and bit offset Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 25/28] Add support for DW_OP_LLVM_undefined operation Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 26/28] Add support for nested composite locations Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 27/28] Add DW_OP_LLVM_extend DWARF operation Zoran Zaric
2021-11-05 11:38 ` [PATCH v4 28/28] Add DW_OP_LLVM_select_bit_piece " Zoran Zaric
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211105113849.118800-16-zoran.zaric@amd.com \
--to=zoran.zaric@amd.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).