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 v4 06/28] Add read method to location description classes
Date: Fri, 5 Nov 2021 11:38:27 +0000	[thread overview]
Message-ID: <20211105113849.118800-7-zoran.zaric@amd.com> (raw)
In-Reply-To: <20211105113849.118800-1-zoran.zaric@amd.com>

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

After adding the interface for register and memory location access, a
new method for reading from any location derived from a dwarf_location
class, can now be defined.

In the case of implicit pointer location description the existing
indirect_synthetic_pointer interface requiers a type of the pointer
to be specified, so for a generic read interface the only type that
makes sense is the DWARF generic type. This means that the existing
address_type method of a dwarf_expr_context class needs to be exposed
outside of that class.

gdb/ChangeLog:

        * dwarf2/expr.c (dwarf_location::read): New method.
        (dwarf_undefined::read): New method.
        (dwarf_memory::read): New method.
        (dwarf_register::read): New method.
        (dwarf_implicit::read): New method.
        (dwarf_implicit_pointer::read): New method.
        (dwarf_composite::read): New method.
        (dwarf_expr_context::address_type): Change to use the new
        address_type function.
        (address_type): New function.
---
 gdb/dwarf2/expr.c | 305 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 284 insertions(+), 21 deletions(-)

diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index e9e5e55ca61..f2349208412 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -279,6 +279,36 @@ write_to_memory (CORE_ADDR address, const gdb_byte *buffer,
 					 length, buffer);
 }
 
+/* Return the type used for DWARF operations where the type is
+   generic in the DWARF spec, the ARCH is a target architecture
+   of the type and ADDR_SIZE is expected size of the address.
+   Only certain sizes are supported.  */
+
+static type *
+address_type (gdbarch *arch, int addr_size)
+{
+  dwarf_gdbarch_types *types
+    = (dwarf_gdbarch_types *) gdbarch_data (arch, dwarf_arch_cookie);
+  int ndx;
+
+  if (addr_size == 2)
+    ndx = 0;
+  else if (addr_size == 4)
+    ndx = 1;
+  else if (addr_size == 8)
+    ndx = 2;
+  else
+    error (_("Unsupported address size in DWARF expressions: %d bits"),
+	   HOST_CHAR_BIT * addr_size);
+
+  if (types->dw_types[ndx] == nullptr)
+    types->dw_types[ndx]
+      = arch_integer_type (arch, HOST_CHAR_BIT * addr_size,
+			   0, "<signed DWARF address type>");
+
+  return types->dw_types[ndx];
+}
+
 class dwarf_location;
 class dwarf_value;
 
@@ -340,6 +370,27 @@ class dwarf_location : public dwarf_entry
     ill_formed_expression ();
   }
 
+  /* Read contents from the described location.
+
+     The read operation is performed in the context of a FRAME.
+     BIT_SIZE is the number of bits to read.  The data read is copied
+     to the caller-managed buffer BUF.  BIG_ENDIAN defines the
+     endianness of the target.  BITS_TO_SKIP is a bit offset into the
+     location and BUF_BIT_OFFSET is buffer BUF's bit offset.
+     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.
+
+     If the location is optimized out or unavailable, the OPTIMIZED and
+     UNAVAILABLE outputs are set accordingly.  */
+  virtual 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 = 0;
+
 protected:
   /* Architecture of the location.  */
   gdbarch *m_arch;
@@ -422,6 +473,14 @@ class dwarf_undefined final : public dwarf_location
   dwarf_undefined (gdbarch *arch)
     : dwarf_location (arch, 0)
   {}
+
+  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
+  {
+    *unavailable = 0;
+    *optimized = 1;
+  }
 };
 
 class dwarf_memory final : public dwarf_location
@@ -438,6 +497,11 @@ class dwarf_memory final : public dwarf_location
 
   dwarf_value_up to_value (struct type *type) const override;
 
+  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;
+
 private:
   /* True if the location belongs to a stack memory region.  */
   bool m_stack;
@@ -464,6 +528,46 @@ dwarf_memory::to_value (struct type *type) const
   return make_unique<dwarf_value> (m_offset, type);
 }
 
+void
+dwarf_memory::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
+{
+  LONGEST total_bits_to_skip = bits_to_skip;
+  CORE_ADDR start_address
+    = m_offset + (m_bit_suboffset + total_bits_to_skip) / HOST_CHAR_BIT;
+  gdb::byte_vector temp_buf;
+
+  *optimized = 0;
+  total_bits_to_skip += m_bit_suboffset;
+
+  if (total_bits_to_skip % HOST_CHAR_BIT == 0
+      && bit_size % HOST_CHAR_BIT == 0
+      && buf_bit_offset % HOST_CHAR_BIT == 0)
+    {
+      /* Everything is byte-aligned, no buffer needed.  */
+      read_from_memory (start_address,
+			buf + buf_bit_offset / HOST_CHAR_BIT,
+			bit_size / HOST_CHAR_BIT, m_stack, unavailable);
+    }
+  else
+    {
+      LONGEST this_size = bits_to_bytes (total_bits_to_skip, bit_size);
+      temp_buf.resize (this_size);
+
+      /* Can only read from memory on byte granularity so an
+	 additional buffer is required.  */
+      read_from_memory (start_address, temp_buf.data (), this_size,
+			m_stack, unavailable);
+
+      if (!*unavailable)
+	copy_bitwise (buf, buf_bit_offset, temp_buf.data (),
+		      total_bits_to_skip % HOST_CHAR_BIT,
+		      bit_size, big_endian);
+    }
+}
+
 /* Register location description entry.  */
 
 class dwarf_register final : public dwarf_location
@@ -473,11 +577,56 @@ class dwarf_register final : public dwarf_location
     : dwarf_location (arch, offset), m_regnum (regnum)
   {}
 
+  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;
+
 private:
   /* DWARF register number.  */
   unsigned int m_regnum;
 };
 
+void
+dwarf_register::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
+{
+  LONGEST total_bits_to_skip = bits_to_skip;
+  size_t read_bit_limit = location_bit_limit;
+  gdbarch *frame_arch = get_frame_arch (frame);
+  int reg = dwarf_reg_to_regnum_or_error (frame_arch, m_regnum);
+  ULONGEST reg_bits = HOST_CHAR_BIT * register_size (frame_arch, reg);
+  gdb::byte_vector temp_buf;
+
+  if (big_endian)
+    {
+      if (!read_bit_limit || reg_bits <= read_bit_limit)
+	read_bit_limit = bit_size;
+
+      total_bits_to_skip += reg_bits - (m_offset * HOST_CHAR_BIT
+					+ m_bit_suboffset + read_bit_limit);
+    }
+  else
+    total_bits_to_skip += m_offset * HOST_CHAR_BIT + m_bit_suboffset;
+
+  LONGEST this_size = bits_to_bytes (total_bits_to_skip, bit_size);
+  temp_buf.resize (this_size);
+
+  if (frame == nullptr)
+    internal_error (__FILE__, __LINE__, _("invalid frame information"));
+
+  /* Can only read from a register on byte granularity so an
+     additional buffer is required.  */
+  read_from_register (frame, reg, total_bits_to_skip / HOST_CHAR_BIT,
+		      temp_buf, optimized, unavailable);
+
+  /* Only copy data if valid.  */
+  if (!*optimized && !*unavailable)
+    copy_bitwise (buf, buf_bit_offset, temp_buf.data (),
+		  total_bits_to_skip % HOST_CHAR_BIT, bit_size, big_endian);
+}
+
 /* Implicit location description entry.  Describes a location
    description not found on the target but instead saved in a
    gdb-allocated buffer.  */
@@ -493,6 +642,10 @@ class dwarf_implicit final : public dwarf_location
       m_byte_order (byte_order)
   {}
 
+  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;
+
 private:
   /* Implicit location contents as a stream of bytes in target byte-order.  */
   gdb::byte_vector m_contents;
@@ -501,6 +654,45 @@ class dwarf_implicit final : public dwarf_location
   bfd_endian m_byte_order;
 };
 
+void
+dwarf_implicit::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
+{
+  ULONGEST implicit_bit_size = HOST_CHAR_BIT * m_contents.size ();
+  LONGEST total_bits_to_skip = bits_to_skip;
+  size_t read_bit_limit = location_bit_limit;
+
+  *optimized = 0;
+  *unavailable = 0;
+
+  /* Cut off at the end of the implicit value.  */
+  if (m_byte_order == BFD_ENDIAN_BIG)
+    {
+      if (!read_bit_limit || read_bit_limit > implicit_bit_size)
+	read_bit_limit = bit_size;
+
+      total_bits_to_skip
+	+= implicit_bit_size - (m_offset * HOST_CHAR_BIT
+			       + m_bit_suboffset + read_bit_limit);
+    }
+  else
+    total_bits_to_skip += m_offset * HOST_CHAR_BIT + m_bit_suboffset;
+
+  if (total_bits_to_skip >= implicit_bit_size)
+    {
+      *unavailable = 1;
+      return;
+    }
+
+  if (bit_size > implicit_bit_size - total_bits_to_skip)
+    bit_size = implicit_bit_size - total_bits_to_skip;
+
+  copy_bitwise (buf, buf_bit_offset, m_contents.data (),
+		total_bits_to_skip, bit_size, big_endian);
+}
+
 /* Implicit pointer location description entry.  */
 
 class dwarf_implicit_pointer final : public dwarf_location
@@ -516,6 +708,10 @@ class dwarf_implicit_pointer final : public dwarf_location
       m_addr_size (addr_size), m_die_offset (die_offset)
   {}
 
+  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;
+
 private:
   /* Per object file data of the implicit pointer.  */
   dwarf2_per_objfile *m_per_objfile;
@@ -530,6 +726,44 @@ class dwarf_implicit_pointer final : public dwarf_location
   sect_offset m_die_offset;
 };
 
+void
+dwarf_implicit_pointer::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
+{
+  frame_info *actual_frame = frame;
+  LONGEST total_bits_to_skip = bits_to_skip + m_bit_suboffset;
+
+  if (actual_frame == nullptr)
+    actual_frame = get_selected_frame (_("No frame selected."));
+
+  struct type *type
+    = address_type (get_frame_arch (actual_frame), m_addr_size);
+
+  struct value *value
+    = indirect_synthetic_pointer (m_die_offset, m_offset, m_per_cu,
+				  m_per_objfile, actual_frame, type);
+
+  gdb_byte *value_contents = value_contents_raw (value).data ()
+			     + total_bits_to_skip / HOST_CHAR_BIT;
+
+  if (total_bits_to_skip % HOST_CHAR_BIT == 0
+      && bit_size % HOST_CHAR_BIT == 0
+      && buf_bit_offset % HOST_CHAR_BIT == 0)
+    {
+      memcpy (buf + buf_bit_offset / HOST_CHAR_BIT,
+	      value_contents, bit_size / HOST_CHAR_BIT);
+    }
+  else
+    {
+      copy_bitwise (buf, buf_bit_offset, value_contents,
+		    total_bits_to_skip % HOST_CHAR_BIT,
+		    bit_size, big_endian);
+    }
+}
+
 /* Composite location description entry.  */
 
 class dwarf_composite final : public dwarf_location
@@ -545,6 +779,10 @@ class dwarf_composite final : public dwarf_location
     m_pieces.emplace_back (std::move (location), bit_size);
   }
 
+  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;
+
 private:
   /* Composite piece that contains a piece location
      description and it's size.  */
@@ -566,6 +804,50 @@ class dwarf_composite final : public dwarf_location
   std::vector<piece> m_pieces;
 };
 
+void
+dwarf_composite::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
+{
+  unsigned int pieces_num = m_pieces.size ();
+  LONGEST total_bits_to_skip = bits_to_skip;
+  unsigned int i;
+
+  total_bits_to_skip += m_offset * HOST_CHAR_BIT + m_bit_suboffset;
+
+  /* Skip pieces covered by the read offset.  */
+  for (i = 0; i < pieces_num; i++)
+    {
+      LONGEST piece_bit_size = m_pieces[i].size;
+
+      if (total_bits_to_skip < piece_bit_size)
+        break;
+
+      total_bits_to_skip -= piece_bit_size;
+    }
+
+  for (; i < pieces_num; i++)
+    {
+      LONGEST piece_bit_size = m_pieces[i].size;
+      LONGEST actual_bit_size = piece_bit_size;
+
+      if (actual_bit_size > bit_size)
+        actual_bit_size = bit_size;
+
+      m_pieces[i].location->read (frame, buf, buf_bit_offset,
+				  actual_bit_size, total_bits_to_skip,
+				  piece_bit_size, big_endian,
+				  optimized, unavailable);
+
+      if (bit_size == actual_bit_size || *optimized || *unavailable)
+	break;
+
+      buf_bit_offset += actual_bit_size;
+      bit_size -= actual_bit_size;
+    }
+}
+
 struct piece_closure
 {
   /* Reference count.  */
@@ -1181,27 +1463,8 @@ sect_variable_value (sect_offset sect_off,
 struct type *
 dwarf_expr_context::address_type () const
 {
-  gdbarch *arch = this->m_per_objfile->objfile->arch ();
-  dwarf_gdbarch_types *types
-    = (dwarf_gdbarch_types *) gdbarch_data (arch, dwarf_arch_cookie);
-  int ndx;
-
-  if (this->m_addr_size == 2)
-    ndx = 0;
-  else if (this->m_addr_size == 4)
-    ndx = 1;
-  else if (this->m_addr_size == 8)
-    ndx = 2;
-  else
-    error (_("Unsupported address size in DWARF expressions: %d bits"),
-	   8 * this->m_addr_size);
-
-  if (types->dw_types[ndx] == NULL)
-    types->dw_types[ndx]
-      = arch_integer_type (arch, 8 * this->m_addr_size,
-			   0, "<signed DWARF address type>");
-
-  return types->dw_types[ndx];
+  return ::address_type (this->m_per_objfile->objfile->arch (),
+			 this->m_addr_size);
 }
 
 /* Create a new context for the expression evaluator.  */
-- 
2.17.1


  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 ` Zoran Zaric [this message]
2021-11-05 11:38 ` [PATCH v4 07/28] Add write method to location description classes 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 ` [PATCH v4 15/28] Add to_gdb_value method to DWARF entry class Zoran Zaric
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-7-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).