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 07/28] Add write method to location description classes
Date: Fri, 5 Nov 2021 11:38:28 +0000	[thread overview]
Message-ID: <20211105113849.118800-8-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 reading from the location, it also
makes sense to add the interface for writing.

To be clear, DWARF standard doesn't have a concept of writting to a
location, but because of the way how callback functions are used to
interact with the opaque implementation of the computed struct value
objects, the choice was to either use the existing DWARF entry classes
or to invent another way of representing the complexity behind those
computed objects.

Adding a write method seems to be a simpler option of the two.

gdb/ChangeLog:

        * dwarf2/expr.c (dwarf_location::write): New method.
        (dwarf_undefined::write): New method.
        (dwarf_memory::write): New method.
        (dwarf_register::write): New method.
        (dwarf_implicit::write): New method.
        (dwarf_implicit_pointer::write): New method.
        (dwarf_composite::write): New method.
---
 gdb/dwarf2/expr.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 211 insertions(+)

diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index f2349208412..6129f4e8ec9 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -391,6 +391,28 @@ class dwarf_location : public dwarf_entry
 		     bool big_endian, int *optimized,
 		     int *unavailable) const = 0;
 
+  /* Write contents to a described location.
+
+     The write operation is performed in the context of a FRAME.
+     BIT_SIZE is the number of bits written.  The data written is
+     copied from the caller-managed BUF buffer.  BIG_ENDIAN defines an
+     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 written without a FRAME
+     context.
+
+     If the location is optimized out or unavailable, the OPTIMIZED and
+     UNAVAILABLE outputs are set.  */
+  virtual void write (frame_info *frame, const 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;
@@ -481,6 +503,14 @@ class dwarf_undefined final : public dwarf_location
     *unavailable = 0;
     *optimized = 1;
   }
+
+  void write (frame_info *frame, const 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
@@ -502,6 +532,11 @@ class dwarf_memory final : public dwarf_location
 	     size_t location_bit_limit, bool big_endian,
 	     int *optimized, int *unavailable) const override;
 
+  void write (frame_info *frame, const 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;
@@ -568,6 +603,62 @@ dwarf_memory::read (frame_info *frame, gdb_byte *buf,
     }
 }
 
+void
+dwarf_memory::write (frame_info *frame, const 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.  */
+      write_to_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);
+
+      if (total_bits_to_skip % HOST_CHAR_BIT != 0
+	  || bit_size % HOST_CHAR_BIT != 0)
+	{
+	  if (this_size <= HOST_CHAR_BIT)
+	    /* Perform a single read for small sizes.  */
+	    read_from_memory (start_address, temp_buf.data (),
+			      this_size, m_stack, unavailable);
+	  else
+	    {
+	      /* Only the first and last bytes can possibly have
+		 any bits reused.  */
+	      read_from_memory (start_address, temp_buf.data (),
+				1, m_stack, unavailable);
+
+	      if (!*unavailable)
+		read_from_memory (start_address + this_size - 1,
+				  &temp_buf[this_size - 1], 1,
+				  m_stack, unavailable);
+	    }
+	}
+
+      copy_bitwise (temp_buf.data (), total_bits_to_skip % HOST_CHAR_BIT,
+		    buf, buf_bit_offset, bit_size, big_endian);
+
+      write_to_memory (start_address, temp_buf.data (), this_size,
+		       m_stack, unavailable);
+    }
+}
+
 /* Register location description entry.  */
 
 class dwarf_register final : public dwarf_location
@@ -581,6 +672,11 @@ class dwarf_register final : public dwarf_location
 	     size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit,
 	     bool big_endian, int *optimized, int *unavailable) const override;
 
+  void write (frame_info *frame, const 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;
@@ -627,6 +723,53 @@ dwarf_register::read (frame_info *frame, gdb_byte *buf,
 		  total_bits_to_skip % HOST_CHAR_BIT, bit_size, big_endian);
 }
 
+void
+dwarf_register::write (frame_info *frame, const 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 write_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 (frame == nullptr)
+    internal_error (__FILE__, __LINE__, _("invalid frame information"));
+
+  if (big_endian)
+    {
+      if (!write_bit_limit || reg_bits <= write_bit_limit)
+	write_bit_limit = bit_size;
+
+      total_bits_to_skip += reg_bits - (m_offset * HOST_CHAR_BIT
+					+ m_bit_suboffset + write_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 (total_bits_to_skip % HOST_CHAR_BIT != 0
+      || bit_size % HOST_CHAR_BIT != 0)
+    {
+      /* Contents is copied non-byte-aligned into the register.
+         Need some bits from original register value.  */
+      read_from_register (frame, reg,
+			  total_bits_to_skip / HOST_CHAR_BIT,
+			  temp_buf, optimized, unavailable);
+    }
+
+  copy_bitwise (temp_buf.data (), total_bits_to_skip % HOST_CHAR_BIT, buf,
+		buf_bit_offset, bit_size, big_endian);
+
+  write_to_register (frame, reg, total_bits_to_skip / HOST_CHAR_BIT,
+		     temp_buf, optimized, unavailable);
+}
+
 /* Implicit location description entry.  Describes a location
    description not found on the target but instead saved in a
    gdb-allocated buffer.  */
@@ -646,6 +789,15 @@ class dwarf_implicit final : public dwarf_location
 	     size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit,
 	     bool big_endian, int *optimized, int *unavailable) const override;
 
+  void write (frame_info *frame, const 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
+  {
+    *optimized = 1;
+    *unavailable = 0;
+  }
+
 private:
   /* Implicit location contents as a stream of bytes in target byte-order.  */
   gdb::byte_vector m_contents;
@@ -712,6 +864,15 @@ class dwarf_implicit_pointer final : public dwarf_location
 	     size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit,
 	     bool big_endian, int *optimized, int *unavailable) const override;
 
+  void write (frame_info *frame, const 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
+  {
+    *optimized = 1;
+    *unavailable = 0;
+  }
+
 private:
   /* Per object file data of the implicit pointer.  */
   dwarf2_per_objfile *m_per_objfile;
@@ -783,6 +944,11 @@ class dwarf_composite final : public dwarf_location
 	     size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit,
 	     bool big_endian, int *optimized, int *unavailable) const override;
 
+  void write (frame_info *frame, const 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.  */
@@ -848,6 +1014,51 @@ dwarf_composite::read (frame_info *frame, gdb_byte *buf,
     }
 }
 
+void
+dwarf_composite::write (frame_info *frame, const 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;
+  unsigned int pieces_num = m_pieces.size ();
+  unsigned int i;
+
+  total_bits_to_skip += m_offset * HOST_CHAR_BIT + m_bit_suboffset;
+
+  /* Skip pieces covered by the write 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->write (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.  */
-- 
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 ` [PATCH v4 06/28] Add read method to location description classes Zoran Zaric
2021-11-05 11:38 ` Zoran Zaric [this message]
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-8-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).