From: Zoran Zaric via Gdb-patches <gdb-patches@sourceware.org>
To: gdb-patches@sourceware.org
Cc: Zoran Zaric <Zoran.Zaric@amd.com>
Subject: [PATCH 20/30] Add dwarf_entry factory class to expr.c
Date: Mon, 7 Dec 2020 19:00:21 +0000 [thread overview]
Message-ID: <20201207190031.13341-21-Zoran.Zaric@amd.com> (raw)
In-Reply-To: <20201207190031.13341-1-Zoran.Zaric@amd.com>
This patch introduces a new class in charge of creating, tracking and
destroying dwarf_entry class based objects.
gdb/ChangeLog:
* dwarf2/expr.c (ill_formed_expression): New function.
(value_to_gdb_value): New function.
(class dwarf_entry_factory): New class.
(dwarf_entry_factory::~dwarf_entry_factory): New method.
(dwarf_entry_factory::record_entry): New method.
(dwarf_entry_factory::create_value): New method.
(dwarf_entry_factory::create_undefined): New method.
(dwarf_entry_factory::create_memory): New method.
(dwarf_entry_factory::create_register): New method.
(dwarf_entry_factory::create_implicit): New method.
(dwarf_entry_factory::create_implicit_pointer): New method.
(dwarf_entry_factory::create_composite): New method.
(dwarf_entry_factory::entry_to_location): New method.
(dwarf_entry_factory::entry_to_value): New method.
(dwarf_entry_factory::value_binary_op): New method.
(dwarf_entry_factory::value_negation_op): New method.
(dwarf_entry_factory::value_complement_op): New method.
(dwarf_entry_factory::value_cast_op): New method.
---
gdb/dwarf2/expr.c | 316 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 316 insertions(+)
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index fea82f8a87..f188240d8b 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -89,6 +89,14 @@ bits_to_bytes (ULONGEST start, ULONGEST n_bits)
return (start % HOST_CHAR_BIT + n_bits + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
}
+/* Throw an exception about the invalid DWARF expression. */
+
+static void
+ill_formed_expression ()
+{
+ error (_("Ill-formed DWARF expression"));
+}
+
/* See expr.h. */
CORE_ADDR
@@ -1011,6 +1019,314 @@ write_to_location (const dwarf_location *location, struct frame_info *frame,
internal_error (__FILE__, __LINE__, _("invalid location type"));
}
+/* Convert a value entry to the matching struct value representation
+ of a given TYPE. OFFSET defines the offset into the value
+ contents.
+
+ We only need to support dwarf_value to gdb struct value conversion
+ here so that we can utilize the existing unary and binary operations
+ on struct value's.
+
+ We could implement them for the dwarf_value's but that would lead
+ to code duplication with no real gain at the moment. */
+
+static struct value *
+value_to_gdb_value (const dwarf_value *value, struct type *type,
+ LONGEST offset = 0)
+{
+ size_t type_len = TYPE_LENGTH (type);
+
+ if (offset + type_len > TYPE_LENGTH (value->get_type ()))
+ invalid_synthetic_pointer ();
+
+ struct value *retval = allocate_value (type);
+ memcpy (value_contents_raw (retval),
+ value->get_contents () + offset, type_len);
+
+ return retval;
+}
+
+/* Factory class for creation and lifetime management of all DWARF
+ entries found on a DWARF evaluation stack. */
+
+class dwarf_entry_factory
+{
+public:
+ dwarf_entry_factory () = default;
+ ~dwarf_entry_factory ();
+
+ /* Create a value entry of a given TYPE and copy a type size number of
+ bytes from the CONTENTS byte stream to the entry. */
+ dwarf_value *create_value (const gdb_byte* contents, struct type *type);
+
+ /* Creates a value entry of a TYPE type and copies the NUM
+ value to it's contents byte stream. */
+ dwarf_value *create_value (ULONGEST num, struct type *type);
+
+ /* Create a value entry of TYPE type and copy the NUM value to its
+ contents byte stream. */
+ dwarf_value *create_value (LONGEST num, struct type *type);
+
+ /* Create an undefined location description entry. */
+ dwarf_undefined *create_undefined ();
+
+ /* Create a memory location description entry. */
+ dwarf_memory *create_memory (LONGEST offset, LONGEST bit_suboffset = 0,
+ bool stack = false);
+
+ /* Create a register location description entry. */
+ dwarf_register *create_register (unsigned int regnum, LONGEST offset = 0,
+ LONGEST bit_suboffset = 0);
+
+ /* Create an implicit location description entry and copy SIZE
+ number of bytes from the CONTENTS byte stream to the location.
+ BYTE_ORDER holds the byte order of the location described. */
+ dwarf_implicit *create_implicit (const gdb_byte *content, size_t size,
+ enum bfd_endian byte_order);
+
+ /* Create an implicit pointer location description entry. */
+ dwarf_implicit_pointer *create_implicit_pointer
+ (dwarf2_per_objfile *per_objfile, struct dwarf2_per_cu_data *per_cu,
+ int addr_size, sect_offset die_offset, LONGEST offset,
+ LONGEST bit_suboffset = 0);
+
+ /* Create a composite location description entry. */
+ dwarf_composite *create_composite (LONGEST offset = 0,
+ LONGEST bit_suboffset = 0);
+
+ /* Convert an entry to a location description entry. If the entry
+ is a location description entry a dynamic cast is applied.
+
+ In a case of a value entry, the value is implicitly
+ converted to a memory location description entry. */
+ dwarf_location *entry_to_location (dwarf_entry *entry);
+
+ /* Convert an entry to a value entry. If the entry is a value entry
+ a dynamic cast is applied.
+
+ A location description entry is implicitly converted to a value
+ entry of DEFAULT_TYPE type.
+ Note that only 'memory location description entry' to 'value
+ entry' conversion is currently supported. */
+ dwarf_value *entry_to_value (dwarf_entry *entry, struct type *default_type);
+
+ /* Execute OP operation between ARG1 and ARG2 and return a new value
+ entry containing the result of that operation. */
+ dwarf_value *value_binary_op (const dwarf_value *arg1,
+ const dwarf_value *arg2, enum exp_opcode op);
+
+ /* Execute a negation operation on ARG and return a new value entry
+ containing the result of that operation. */
+ dwarf_value *value_negation_op (const dwarf_value *arg);
+
+ /* Execute a complement operation on ARG and return a new value
+ entry containing the result of that operation. */
+ dwarf_value *value_complement_op (const dwarf_value *arg);
+
+ /* Execute a cast operation on ARG and return a new value entry
+ containing the result of that operation. */
+ dwarf_value *value_cast_op (const dwarf_value *arg, struct type *type);
+
+private:
+ /* Record entry for garbage collection. */
+ void record_entry (dwarf_entry *entry);
+
+ /* List of all entries created by the factory. */
+ std::vector<dwarf_entry *> m_dwarf_entries;
+};
+
+dwarf_entry_factory::~dwarf_entry_factory ()
+{
+ for (unsigned int i = 0; i < m_dwarf_entries.size (); i++)
+ {
+ dwarf_entry* entry = m_dwarf_entries[i];
+
+ entry->decref ();
+
+ if (entry->refcount () == 0)
+ delete entry;
+ }
+}
+
+void
+dwarf_entry_factory::record_entry (dwarf_entry *entry)
+{
+ entry->incref ();
+ m_dwarf_entries.push_back (entry);
+}
+
+dwarf_value *
+dwarf_entry_factory::create_value (const gdb_byte* content, struct type *type)
+{
+ dwarf_value *value = new dwarf_value (content, type);
+ record_entry (value);
+ return value;
+}
+
+dwarf_value *
+dwarf_entry_factory::create_value (ULONGEST num, struct type *type)
+{
+ dwarf_value *value = new dwarf_value (num, type);
+ record_entry (value);
+ return value;
+}
+
+dwarf_value *
+dwarf_entry_factory::create_value (LONGEST num, struct type *type)
+{
+ dwarf_value *value = new dwarf_value (num, type);
+ record_entry (value);
+ return value;
+}
+
+dwarf_undefined *
+dwarf_entry_factory::create_undefined ()
+{
+ dwarf_undefined *undefined_entry = new dwarf_undefined ();
+ record_entry (undefined_entry);
+ return undefined_entry;
+}
+
+dwarf_memory *
+dwarf_entry_factory::create_memory (LONGEST offset, LONGEST bit_suboffset,
+ bool stack)
+{
+ dwarf_memory *memory_entry
+ = new dwarf_memory (offset, bit_suboffset, stack);
+ record_entry (memory_entry);
+ return memory_entry;
+}
+
+dwarf_register *
+dwarf_entry_factory::create_register (unsigned int regnum, LONGEST offset,
+ LONGEST bit_suboffset)
+{
+ dwarf_register *register_entry
+ = new dwarf_register (regnum, offset, bit_suboffset);
+ record_entry (register_entry);
+ return register_entry;
+}
+
+dwarf_implicit *
+dwarf_entry_factory::create_implicit (const gdb_byte* content, size_t size,
+ enum bfd_endian byte_order)
+{
+ dwarf_implicit *implicit_entry
+ = new dwarf_implicit (content, size, byte_order);
+ record_entry (implicit_entry);
+ return implicit_entry;
+}
+
+dwarf_implicit_pointer *
+dwarf_entry_factory::create_implicit_pointer
+ (dwarf2_per_objfile *per_objfile, struct dwarf2_per_cu_data *per_cu,
+ int addr_size, sect_offset die_offset, LONGEST offset,
+ LONGEST bit_suboffset)
+{
+ dwarf_implicit_pointer *implicit_pointer_entry
+ = new dwarf_implicit_pointer (per_objfile, per_cu, addr_size,
+ die_offset, offset, bit_suboffset);
+ record_entry (implicit_pointer_entry);
+ return implicit_pointer_entry;
+}
+
+dwarf_composite *
+dwarf_entry_factory::create_composite (LONGEST offset, LONGEST bit_suboffset)
+{
+ dwarf_composite *composite_entry
+ = new dwarf_composite (offset, bit_suboffset);
+ record_entry (composite_entry);
+ return composite_entry;
+}
+
+dwarf_location *
+dwarf_entry_factory::entry_to_location (dwarf_entry *entry)
+{
+ /* If the given entry is already a location,
+ just send it back to the caller. */
+ if (auto location = dynamic_cast<dwarf_location *> (entry))
+ return location;
+
+ auto value = dynamic_cast<dwarf_value *> (entry);
+ gdb_assert (value != nullptr);
+
+ struct type *type = value->get_type ();
+ struct gdbarch *gdbarch = get_type_arch (type);
+ LONGEST offset;
+
+ if (gdbarch_integer_to_address_p (gdbarch))
+ offset = gdbarch_integer_to_address (gdbarch, type,
+ value->get_contents ());
+
+ offset = extract_unsigned_integer (value->get_contents (),
+ TYPE_LENGTH (type),
+ type_byte_order (type));
+
+ return create_memory (offset);
+}
+
+dwarf_value *
+dwarf_entry_factory::entry_to_value (dwarf_entry *entry,
+ struct type *default_type)
+{
+ /* If the given entry is already a value,
+ just send it back to the caller. */
+ if (auto value = dynamic_cast<dwarf_value *> (entry))
+ return value;
+
+ auto location = dynamic_cast<dwarf_location *> (entry);
+ gdb_assert (location != nullptr);
+
+ /* We only support memory location to value conversion at this point.
+ It is hard to define how would that conversion work for other
+ location description types. */
+ if (dynamic_cast<dwarf_memory *> (location) == nullptr)
+ ill_formed_expression ();
+
+ return create_value (location->get_offset (), default_type);
+}
+
+/* We use the existing struct value operations to avoid code
+ duplication. Vector types are planned to be promoted to base types
+ in the future anyway which means that the subset we actually need
+ from these operations is just going to grow anyway. */
+
+dwarf_value *
+dwarf_entry_factory::value_binary_op (const dwarf_value *arg1,
+ const dwarf_value *arg2,
+ enum exp_opcode op)
+{
+ struct value *arg1_value = value_to_gdb_value (arg1, arg1->get_type ());
+ struct value *arg2_value = value_to_gdb_value (arg2, arg2->get_type ());
+ struct value *result = value_binop (arg1_value, arg2_value, op);
+
+ return create_value (value_contents_raw (result), value_type (result));
+}
+
+dwarf_value *
+dwarf_entry_factory::value_negation_op (const dwarf_value *arg)
+{
+ struct value *result
+ = value_neg (value_to_gdb_value (arg, arg->get_type ()));
+ return create_value (value_contents_raw (result), value_type (result));
+}
+
+dwarf_value *
+dwarf_entry_factory::value_complement_op (const dwarf_value *arg)
+{
+ struct value *result
+ = value_complement (value_to_gdb_value (arg, arg->get_type ()));
+ return create_value (value_contents_raw (result), value_type (result));
+}
+
+dwarf_value *
+dwarf_entry_factory::value_cast_op (const dwarf_value *arg, struct type *type)
+{
+ struct value *result
+ = value_cast (type, value_to_gdb_value (arg, arg->get_type ()));
+ return create_value (value_contents_raw (result), type);
+}
+
struct piece_closure
{
/* Reference count. */
--
2.17.1
next prev parent reply other threads:[~2020-12-07 19:01 UTC|newest]
Thread overview: 75+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-07 19:00 [PATCH 00/30] Allow location description on the DWARF stack Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 01/30] Replace the symbol needs evaluator with a parser Zoran Zaric via Gdb-patches
2021-01-21 21:16 ` Tom Tromey
2021-01-21 21:48 ` Zoran Zaric via Gdb-patches
2021-02-23 14:15 ` Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 02/30] Move frame context info to dwarf_expr_context Zoran Zaric via Gdb-patches
2021-01-21 21:23 ` Tom Tromey
2020-12-07 19:00 ` [PATCH 03/30] Remove get_frame_cfa from dwarf_expr_context Zoran Zaric via Gdb-patches
2021-01-21 21:23 ` Tom Tromey
2020-12-07 19:00 ` [PATCH 04/30] Move compilation unit info to dwarf_expr_context Zoran Zaric via Gdb-patches
2021-01-21 21:28 ` Tom Tromey
2021-02-23 14:21 ` Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 05/30] Move dwarf_call " Zoran Zaric via Gdb-patches
2021-01-21 21:30 ` Tom Tromey
2020-12-07 19:00 ` [PATCH 06/30] Move get_object_address " Zoran Zaric via Gdb-patches
2021-01-21 21:31 ` Tom Tromey
2021-02-23 14:33 ` Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 07/30] Move read_mem " Zoran Zaric via Gdb-patches
2021-01-21 21:34 ` Tom Tromey
2020-12-07 19:00 ` [PATCH 08/30] Move push_dwarf_reg_entry_value to expr.c Zoran Zaric via Gdb-patches
2021-01-21 21:35 ` Tom Tromey
2020-12-07 19:00 ` [PATCH 09/30] Inline get_reg_value method of dwarf_expr_context Zoran Zaric via Gdb-patches
2021-01-21 21:36 ` Tom Tromey
2020-12-07 19:00 ` [PATCH 10/30] Remove empty frame and full evaluators Zoran Zaric via Gdb-patches
2021-01-21 21:37 ` Tom Tromey
2020-12-07 19:00 ` [PATCH 11/30] Merge evaluate_for_locexpr_baton evaluator Zoran Zaric via Gdb-patches
2021-02-08 21:21 ` Tom Tromey
2020-12-07 19:00 ` [PATCH 12/30] Move piece_closure and its support to expr.c Zoran Zaric via Gdb-patches
2021-02-08 21:32 ` Tom Tromey
2021-02-09 14:53 ` Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 13/30] Make DWARF evaluator return a single struct value Zoran Zaric via Gdb-patches
2021-02-08 21:35 ` Tom Tromey
2021-02-09 14:55 ` Zoran Zaric via Gdb-patches
2021-02-09 17:13 ` Tom Tromey
2020-12-07 19:00 ` [PATCH 14/30] Simplify dwarf_expr_context class interface Zoran Zaric via Gdb-patches
2021-02-08 21:38 ` Tom Tromey
2021-02-09 14:56 ` Zoran Zaric via Gdb-patches
2021-02-23 14:38 ` Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 15/30] Add as_lval argument to expression evaluator Zoran Zaric via Gdb-patches
2021-02-08 21:41 ` Tom Tromey
2021-02-09 15:25 ` Zoran Zaric via Gdb-patches
2021-02-09 20:33 ` Tom Tromey
2020-12-07 19:00 ` [PATCH 16/30] Add new register access interface to expr.c Zoran Zaric via Gdb-patches
2021-02-09 19:37 ` Tom Tromey
2020-12-07 19:00 ` [PATCH 17/30] Add new memory " Zoran Zaric via Gdb-patches
2021-02-09 19:45 ` Tom Tromey
2021-02-23 15:35 ` Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 18/30] Add new classes that model DWARF stack element Zoran Zaric via Gdb-patches
2021-02-08 21:54 ` Tom Tromey
2021-02-09 17:34 ` Zoran Zaric via Gdb-patches
2021-02-09 20:36 ` Tom Tromey
2021-02-09 21:07 ` Tom Tromey
2021-02-09 21:26 ` Zoran Zaric via Gdb-patches
2021-02-23 14:57 ` Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 19/30] Add new location description access interface Zoran Zaric via Gdb-patches
2021-02-08 21:46 ` Tom Tromey
2021-02-09 16:00 ` Zoran Zaric via Gdb-patches
2021-02-09 17:30 ` Zoran Zaric via Gdb-patches
2021-02-23 14:49 ` Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` Zoran Zaric via Gdb-patches [this message]
2021-02-09 19:54 ` [PATCH 20/30] Add dwarf_entry factory class to expr.c Tom Tromey
2020-12-07 19:00 ` [PATCH 21/30] Change DWARF stack to use new dwarf_entry classes Zoran Zaric via Gdb-patches
2021-02-09 20:11 ` Tom Tromey
2020-12-07 19:00 ` [PATCH 22/30] Remove dwarf_expr_context from expr.h interface Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 23/30] Rename and update the piece_closure structure Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 24/30] Move read_addr_from_reg function to frame.c Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 25/30] Add frame info check to DW_OP_reg operations Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 26/30] Remove DWARF expression composition check Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 27/30] Add support for any location description in CFI Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 28/30] Add DWARF operations for byte and bit offset Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 29/30] Add support for DW_OP_LLVM_undefined operation Zoran Zaric via Gdb-patches
2020-12-07 19:00 ` [PATCH 30/30] Add support for nested composite locations Zoran Zaric via Gdb-patches
2020-12-08 14:48 ` [PATCH 00/30] Allow location description on the DWARF stack Metzger, Markus T via Gdb-patches
2020-12-08 16:17 ` Simon Marchi via Gdb-patches
2020-12-09 0:30 ` Tye, Tony via Gdb-patches
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=20201207190031.13341-21-Zoran.Zaric@amd.com \
--to=gdb-patches@sourceware.org \
--cc=Zoran.Zaric@amd.com \
/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