public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Zoran Zaric <zoran.zaric@amd.com>
To: <gdb-patches@sourceware.org>
Subject: [PATCH v3 14/28] Add new computed struct value callback interface
Date: Thu, 14 Oct 2021 10:32:21 +0100	[thread overview]
Message-ID: <20211014093235.69756-15-zoran.zaric@amd.com> (raw)
In-Reply-To: <20211014093235.69756-1-zoran.zaric@amd.com>

From: Zoran Zaric <Zoran.Zaric@amd.com>

At this point all support is there to add a new callback interface
for the computed struct value infrastructure.

Original callback interface (piece closure) is going to be removed as
soon as the switch to the new DWARF entry classes is done in the next
few patches.

gdb/ChangeLog:

        * dwarf2/expr.c (class computed_closure): New class.
        (closure_value_funcs): New closure callback structure.
        (copy_value_closure): New function.
        (free_value_closure): New function.
        (rw_closure_value): New function.
        (check_synthetic_pointer): New function.
        (write_closure_value): New function.
        (read_closure_value): New function.
        (is_optimized_out_closure_value): New function.
        (indirect_closure_value): New function.
        (coerce_closure_ref): New function.
---
 gdb/dwarf2/expr.c | 307 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 307 insertions(+)

diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index 1b6622d5f59..e33be7e7c1c 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -323,6 +323,92 @@ class dwarf_location;
 class dwarf_memory;
 class dwarf_value;
 
+/* Closure callback functions.  */
+
+static void *
+copy_value_closure (const value *v);
+
+static void
+free_value_closure (value *v);
+
+static void
+rw_closure_value (value *v, value *from);
+
+static int
+check_synthetic_pointer (const value *value, LONGEST bit_offset,
+			 int bit_length);
+
+static void
+write_closure_value (value *to, value *from);
+
+static void
+read_closure_value (value *v);
+
+static bool
+is_optimized_out_closure_value (value *v);
+
+static value *
+indirect_closure_value (value *value);
+
+static value *
+coerce_closure_ref (const value *value);
+
+/* Functions for accessing a variable described by DW_OP_piece,
+   DW_OP_bit_piece or DW_OP_implicit_pointer.  */
+
+static const lval_funcs closure_value_funcs = {
+  read_closure_value,
+  write_closure_value,
+  is_optimized_out_closure_value,
+  indirect_closure_value,
+  coerce_closure_ref,
+  check_synthetic_pointer,
+  copy_value_closure,
+  free_value_closure
+};
+
+/* Closure class that encapsulates a DWARF location description and a
+   frame information used when that location description was created.
+   Used for lval_computed value abstraction.  */
+
+class computed_closure : public refcounted_object
+{
+public:
+  computed_closure (std::unique_ptr<dwarf_location> location,
+		    struct frame_id frame_id)
+    : m_location (std::move (location)), m_frame_id (frame_id)
+  {}
+
+  computed_closure (std::unique_ptr<dwarf_location> location,
+		    struct frame_info *frame)
+    : m_location (std::move (location)), m_frame (frame)
+  {}
+
+  const dwarf_location &get_location () const;
+
+  frame_id get_frame_id () const
+  {
+    return m_frame_id;
+  }
+
+  frame_info *get_frame () const
+  {
+    return m_frame;
+  }
+
+private:
+  /* Entry that this class encloses.  */
+  const std::unique_ptr<const dwarf_location> m_location;
+
+  /* Frame ID context of the closure.  */
+  frame_id m_frame_id;
+
+  /* In the case of frame expression evaluator the frame_id
+     is not safe to use because the frame itself is being built.
+     Only in these cases we set and use frame info directly.  */
+  frame_info *m_frame = NULL;
+};
+
 /* Base class that describes entries found on a DWARF expression
    evaluation stack.  */
 
@@ -524,6 +610,11 @@ class dwarf_location : public dwarf_entry
 
 using dwarf_location_up = std::unique_ptr<dwarf_location>;
 
+const dwarf_location &computed_closure::get_location () const
+{
+  return *m_location;
+}
+
 void
 dwarf_location::read_from_gdb_value (frame_info *frame, struct value *value,
 				     int value_bit_offset,
@@ -1594,6 +1685,222 @@ dwarf_composite::is_optimized_out (frame_info *frame, bool big_endian,
   return false;
 }
 
+static void *
+copy_value_closure (const value *v)
+{
+  computed_closure *closure = ((computed_closure*) value_computed_closure (v));
+
+  if (closure == nullptr)
+    internal_error (__FILE__, __LINE__, _("invalid closure type"));
+
+  closure->incref ();
+  return closure;
+}
+
+static void
+free_value_closure (value *v)
+{
+  computed_closure *closure = ((computed_closure*) value_computed_closure (v));
+
+  if (closure == nullptr)
+    internal_error (__FILE__, __LINE__, _("invalid closure type"));
+
+  closure->decref ();
+
+  if (closure->refcount () == 0)
+    delete closure;
+}
+
+/* Read or write a closure value V.  If FROM != NULL, operate in "write
+   mode": copy FROM into the closure comprising V.  If FROM == NULL,
+   operate in "read mode": fetch the contents of the (lazy) value V by
+   composing it from its closure.  */
+
+static void
+rw_closure_value (value *v, value *from)
+{
+  LONGEST bit_offset = 0, max_bit_size;
+  computed_closure *closure = (computed_closure*) value_computed_closure (v);
+  bool big_endian = type_byte_order (value_type (v)) == BFD_ENDIAN_BIG;
+  const dwarf_location &location = closure->get_location ();
+
+  if (from == NULL)
+    {
+      if (value_type (v) != value_enclosing_type (v))
+        internal_error (__FILE__, __LINE__,
+			_("Should not be able to create a lazy value with "
+			  "an enclosing type"));
+    }
+
+  ULONGEST bits_to_skip = HOST_CHAR_BIT * value_offset (v);
+
+  /* If there are bits that don't complete a byte, count them in.  */
+  if (value_bitsize (v))
+    {
+      bits_to_skip += HOST_CHAR_BIT * value_offset (value_parent (v))
+		       + value_bitpos (v);
+      if (from != NULL && big_endian)
+	{
+	  /* Use the least significant bits of FROM.  */
+	  max_bit_size = HOST_CHAR_BIT * TYPE_LENGTH (value_type (from));
+	  bit_offset = max_bit_size - value_bitsize (v);
+	}
+      else
+	max_bit_size = value_bitsize (v);
+    }
+  else
+    max_bit_size = HOST_CHAR_BIT * TYPE_LENGTH (value_type (v));
+
+  frame_info *frame = closure->get_frame ();
+
+  if (frame == NULL)
+    frame = frame_find_by_id (closure->get_frame_id ());
+
+  if (from == NULL)
+    {
+      location.write_to_gdb_value (frame, v, bit_offset, bits_to_skip,
+				   max_bit_size - bit_offset, 0);
+    }
+  else
+    {
+      location.read_from_gdb_value (frame, from, bit_offset, bits_to_skip,
+				    max_bit_size - bit_offset, 0);
+    }
+}
+
+static void
+read_closure_value (value *v)
+{
+  rw_closure_value (v, NULL);
+}
+
+static void
+write_closure_value (value *to, value *from)
+{
+  rw_closure_value (to, from);
+}
+
+/* Check if a closure value V contains describes any piece
+   of the underlying location description as optimized out.  */
+
+static bool
+is_optimized_out_closure_value (value *v)
+{
+  LONGEST max_bit_size;
+  computed_closure *closure = (computed_closure*) value_computed_closure (v);
+  bool big_endian = type_byte_order (value_type (v)) == BFD_ENDIAN_BIG;
+  const dwarf_location &location = closure->get_location ();
+
+  if (value_type (v) != value_enclosing_type (v))
+    internal_error (__FILE__, __LINE__,
+		    _("Should not be able to create a lazy value with "
+		      "an enclosing type"));
+
+  ULONGEST bits_to_skip = HOST_CHAR_BIT * value_offset (v);
+
+  /* If there are bits that don't complete a byte, count them in.  */
+  if (value_bitsize (v))
+    {
+      bits_to_skip += HOST_CHAR_BIT * value_offset (value_parent (v))
+		      + value_bitpos (v);
+      max_bit_size = value_bitsize (v);
+    }
+  else
+    max_bit_size = HOST_CHAR_BIT * TYPE_LENGTH (value_type (v));
+
+  frame_info *frame = closure->get_frame ();
+
+  if (frame == NULL)
+    frame = frame_find_by_id (closure->get_frame_id ());
+
+  return location.is_optimized_out (frame, big_endian, bits_to_skip,
+				    max_bit_size, 0);
+}
+
+/* An implementation of an lval_funcs method to see whether a value is
+   a synthetic pointer.  */
+
+static int
+check_synthetic_pointer (const value *value, LONGEST bit_offset,
+			 int bit_length)
+{
+  LONGEST total_bit_offset = bit_offset + HOST_CHAR_BIT * value_offset (value);
+
+  if (value_bitsize (value))
+    total_bit_offset += value_bitpos (value);
+
+  computed_closure *closure
+    = (computed_closure *) value_computed_closure (value);
+
+  return closure->get_location ().is_implicit_ptr_at (total_bit_offset,
+						      bit_length);
+}
+
+/* An implementation of an lval_funcs method to indirect through a
+   pointer.  This handles the synthetic pointer case when needed.  */
+
+static value *
+indirect_closure_value (value *value)
+{
+  computed_closure *closure
+    = (computed_closure *) value_computed_closure (value);
+
+  struct type *type = check_typedef (value_type (value));
+  if (type->code () != TYPE_CODE_PTR)
+    return NULL;
+
+  LONGEST bit_length = HOST_CHAR_BIT * TYPE_LENGTH (type);
+  LONGEST bit_offset = HOST_CHAR_BIT * value_offset (value);
+
+  if (value_bitsize (value))
+    bit_offset += value_bitpos (value);
+
+  frame_info *frame = get_selected_frame (_("No frame selected."));
+
+  /* This is an offset requested by GDB, such as value subscripts.
+     However, due to how synthetic pointers are implemented, this is
+     always presented to us as a pointer type.  This means we have to
+     sign-extend it manually as appropriate.  Use raw
+     extract_signed_integer directly rather than value_as_address and
+     sign extend afterwards on architectures that would need it
+     (mostly everywhere except MIPS, which has signed addresses) as
+     the later would go through gdbarch_pointer_to_address and thus
+     return a CORE_ADDR with high bits set on architectures that
+     encode address spaces and other things in CORE_ADDR.  */
+  bfd_endian byte_order = gdbarch_byte_order (get_frame_arch (frame));
+  LONGEST pointer_offset
+    = extract_signed_integer (value_contents (value),
+			      TYPE_LENGTH (type), byte_order);
+
+  return closure->get_location ().indirect_implicit_ptr (frame, type,
+							 pointer_offset,
+							 bit_offset, bit_length);
+}
+
+/* Implementation of the coerce_ref method of lval_funcs for synthetic C++
+   references.  */
+
+static value *
+coerce_closure_ref (const value *value)
+{
+  struct type *type = check_typedef (value_type (value));
+
+  if (value_bits_synthetic_pointer (value, value_embedded_offset (value),
+				    TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+    {
+      computed_closure *closure
+	= (computed_closure *) value_computed_closure (value);
+      frame_info *frame = get_selected_frame (_("No frame selected."));
+
+      return closure->get_location ().indirect_implicit_ptr (frame, type);
+    }
+  else
+    {
+      /* Else: not a synthetic reference; do nothing.  */
+      return NULL;
+    }
+}
+
 struct piece_closure
 {
   /* Reference count.  */
-- 
2.17.1


  parent reply	other threads:[~2021-10-14  9:33 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-14  9:32 [PATCH v3 00/28] Allow location description on the DWARF stack Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 01/28] Add new register access interface to expr.c Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 02/28] Add new memory " Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 03/28] Add new classes that model DWARF stack element Zoran Zaric
2021-10-21 23:43   ` Lancelot SIX
2021-10-22 16:38     ` Zoran Zaric
2021-10-22 21:34       ` Lancelot SIX
2021-10-14  9:32 ` [PATCH v3 04/28] Add to_location method to DWARF entry classes Zoran Zaric
2021-10-22 21:21   ` Lancelot SIX
2021-10-25 21:23     ` Simon Marchi
2021-11-01 16:01       ` Zoran Zaric
2021-11-01 20:36         ` Simon Marchi
2021-11-01 16:00     ` Zoran Zaric
2021-11-01 17:48       ` Lancelot SIX
2021-10-14  9:32 ` [PATCH v3 05/28] Add to_value " Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 06/28] Add read method to location description classes Zoran Zaric
2021-10-25 18:33   ` Lancelot SIX
2021-10-25 21:37     ` Simon Marchi
2021-11-02 14:26       ` Zoran Zaric
2021-11-03 19:03         ` Simon Marchi
2021-11-05 11:58           ` Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 07/28] Add write " Zoran Zaric
2021-10-25 20:21   ` Lancelot SIX
2021-11-03 10:27     ` Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 08/28] Add deref " Zoran Zaric
2021-10-25 22:31   ` Lancelot SIX
2021-11-03 10:51     ` Zoran Zaric
2021-11-03 17:37       ` Simon Marchi
2021-11-05 11:55         ` Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 09/28] Add read_from_gdb_value method to dwarf_location Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 10/28] Add write_to_gdb_value " Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 11/28] Add is_implicit_ptr_at " Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 12/28] Add indirect_implicit_ptr to dwarf_location class Zoran Zaric
2021-10-26 20:52   ` Lancelot SIX
2021-11-03 15:11     ` Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 13/28] Add is_optimized_out " Zoran Zaric
2021-10-14  9:32 ` Zoran Zaric [this message]
2021-10-26 22:50   ` [PATCH v3 14/28] Add new computed struct value callback interface Lancelot SIX
2021-11-04 11:32     ` Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 15/28] Add to_gdb_value method to DWARF entry class Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 16/28] Change DWARF stack to use new dwarf_entry classes Zoran Zaric
2021-10-31 17:58   ` Lancelot SIX
2021-11-04 12:43     ` Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 17/28] Remove old computed struct value callbacks Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 18/28] Comments cleanup between expr.h and expr.c Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 19/28] Remove dwarf_expr_context from expr.h interface Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 20/28] Move read_addr_from_reg function to frame.c Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 21/28] Add frame info check to DW_OP_reg operations Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 22/28] Remove DWARF expression composition check Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 23/28] Add support for any location description in CFI Zoran Zaric
2021-10-31 22:58   ` Lancelot SIX
2021-11-04 15:09     ` Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 24/28] Add DWARF operations for byte and bit offset Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 25/28] Add support for DW_OP_LLVM_undefined operation Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 26/28] Add support for nested composite locations Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 27/28] Add DW_OP_LLVM_extend DWARF operation Zoran Zaric
2021-11-01 21:48   ` Lancelot SIX
2021-11-04 16:26     ` Zoran Zaric
2021-10-14  9:32 ` [PATCH v3 28/28] Add DW_OP_LLVM_select_bit_piece " Zoran Zaric
2021-11-01 22:25   ` Lancelot SIX
2021-11-04 16:39     ` Zoran Zaric
2021-11-05 11:54 ` [PATCH v3 00/28] Allow location description on the DWARF stack Zaric, Zoran (Zare)

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=20211014093235.69756-15-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).