Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
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


  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