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 30/30] Add support for nested composite locations
Date: Mon,  7 Dec 2020 19:00:31 +0000	[thread overview]
Message-ID: <20201207190031.13341-31-Zoran.Zaric@amd.com> (raw)
In-Reply-To: <20201207190031.13341-1-Zoran.Zaric@amd.com>

After allowing a location description to be placed on a DWARF stack,
in an effort to achieve a full composability of the DWARF expression,
it is necessary to enable forming of a nested composite location
descriptions.

To be able do this, a new operation DW_OP_LLVM_piece_end needs to be
introduced, along with some additional rules on the way how the
composite location description is formed using the existing DW_OP_piece
and DW_OP_bit_piece operations. These new rules are fully compatible
with the composite forming rules from the DWARF 5 standard.

More details on the new operation and added rules can be found here:

https://llvm.org/docs/AMDGPUDwarfExtensionsForHeterogeneousDebugging.html

gdb/ChangeLog:

	* compile/compile-loc2c.c (compute_stack_depth_worker): Add new
	DW_OP_LLVM_piece_end operation support.
	* dwarf2/expr.c (class dwarf_value): Add copy constructor.
	(class dwarf_location): Add copy constructor.
	(class dwarf_undefined): Add copy constructor.
	(class dwarf_memory): Add copy constructor.
	(class dwarf_register): Add copy constructor.
	(class dwarf_implicit): Add copy constructor.
	(class dwarf_implicit_pointer): Add copy constructor.
	(class dwarf_composite): Add copy constructor.
	(read_from_location): Add composite completed check.
	(write_to_location): Add composite completed check.
	(read_value_contents_from_location): New function.
	(dwarf_entry_factory::copy_entry): New method.
	(rw_closure_value): Now calls read_value_contents_from_location
	function.
	(dwarf_expr_context::add_piece): Use new composite forming
	rules.
	(dwarf_expr_context::execute_stack_op): Add new
	DW_OP_LLVM_piece_end operation support.
	* dwarf2/loc.c (dwarf2_get_symbol_read_needs): Add new
	DW_OP_LLVM_piece_end operation support.

include/ChangeLog:

	* dwarf2.def (DW_OP_DUP): Add new DW_OP_LLVM_piece_end
          enumeration.

gdb/testsuite/ChangeLog:

	* gdb.dwarf2/dw2-llvm-piece-end.exp: New test.
---
 gdb/compile/compile-loc2c.c                   |   1 +
 gdb/dwarf2/expr.c                             | 305 ++++++++++++++++--
 gdb/dwarf2/loc.c                              |   1 +
 .../gdb.dwarf2/dw2-llvm-piece-end.exp         | 191 +++++++++++
 include/dwarf2.def                            |   1 +
 5 files changed, 469 insertions(+), 30 deletions(-)
 create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-llvm-piece-end.exp

diff --git a/gdb/compile/compile-loc2c.c b/gdb/compile/compile-loc2c.c
index e9698a758e..fd28f2cd4e 100644
--- a/gdb/compile/compile-loc2c.c
+++ b/gdb/compile/compile-loc2c.c
@@ -365,6 +365,7 @@ compute_stack_depth_worker (int start, int *need_tempvar,
 	  ++stack_depth;
 	  break;
 
+	case DW_OP_LLVM_piece_end:
 	case DW_OP_LLVM_offset_constu:
 	case DW_OP_nop:
 	  break;
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index a65d18d492..647bf8810a 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -308,6 +308,17 @@ class dwarf_value : public dwarf_entry
     m_type = type;
   }
 
+  dwarf_value (const dwarf_value &value)
+  {
+    struct type *type = value.m_type;
+    size_t type_len = TYPE_LENGTH (type);
+
+    m_contents.reset ((gdb_byte *) xzalloc (type_len));
+
+    memcpy (m_contents.get (), value.m_contents.get (), type_len);
+    m_type = type;
+  }
+
   virtual ~dwarf_value () = default;
 
   const gdb_byte* get_contents () const
@@ -352,6 +363,12 @@ class dwarf_location : public dwarf_entry
     m_bit_suboffset = bit_suboffset % HOST_CHAR_BIT;
   }
 
+  dwarf_location (const dwarf_location &location)
+    : m_offset (location.m_offset),
+      m_bit_suboffset (location.m_bit_suboffset),
+      m_initialised (location.m_initialised)
+  {}
+
   virtual ~dwarf_location () = default;
 
   LONGEST get_offset () const
@@ -404,6 +421,11 @@ class dwarf_undefined : public dwarf_location
   dwarf_undefined (LONGEST offset = 0, LONGEST bit_suboffset = 0)
     : dwarf_location (offset, bit_suboffset)
   {}
+
+  dwarf_undefined (const dwarf_undefined &undefined_entry)
+    : dwarf_location (undefined_entry)
+  {}
+
 };
 
 class dwarf_memory : public dwarf_location
@@ -415,6 +437,11 @@ class dwarf_memory : public dwarf_location
       m_stack (stack)
   {}
 
+  dwarf_memory (const dwarf_memory &memory_entry)
+    : dwarf_location (memory_entry),
+      m_stack (memory_entry.m_stack)
+  {}
+
   bool in_stack () const
   {
     return m_stack;
@@ -440,6 +467,11 @@ class dwarf_register : public dwarf_location
       m_regnum (regnum)
   {}
 
+  dwarf_register (const dwarf_register &register_entry)
+    : dwarf_location (register_entry),
+      m_regnum (register_entry.m_regnum)
+  {}
+
   unsigned int get_regnum () const
   {
     return m_regnum;
@@ -468,6 +500,17 @@ class dwarf_implicit : public dwarf_location
     m_byte_order = byte_order;
   }
 
+  dwarf_implicit (const dwarf_implicit &implicit_entry)
+    : dwarf_location (implicit_entry)
+  {
+    size_t size = implicit_entry.m_size;
+    m_contents.reset ((gdb_byte *) xzalloc (size));
+
+    memcpy (m_contents.get (), implicit_entry.m_contents.get (), size);
+    m_size = size;
+    m_byte_order = implicit_entry.m_byte_order;
+  }
+
   const gdb_byte* get_contents () const
   {
     return m_contents.get ();
@@ -508,6 +551,14 @@ class dwarf_implicit_pointer : public dwarf_location
       m_addr_size (addr_size), m_die_offset (die_offset)
   {}
 
+  dwarf_implicit_pointer (const dwarf_implicit_pointer &implicit_ptr_entry)
+    : dwarf_location (implicit_ptr_entry),
+      m_per_objfile (implicit_ptr_entry.m_per_objfile),
+      m_per_cu (implicit_ptr_entry.m_per_cu),
+      m_addr_size (implicit_ptr_entry.m_addr_size),
+      m_die_offset (implicit_ptr_entry.m_die_offset)
+  {}
+
   dwarf2_per_objfile *get_per_objfile () const
   {
     return m_per_objfile;
@@ -551,6 +602,22 @@ class dwarf_composite : public dwarf_location
     : dwarf_location (offset, bit_suboffset)
   {}
 
+  dwarf_composite (const dwarf_composite &composite_entry)
+    : dwarf_location (composite_entry)
+  {
+    /* We do a shallow copy of the pieces because they are not
+       expected to be modified after they are already formed.  */
+    for (unsigned int i = 0; i < composite_entry.m_pieces.size (); i++)
+      {
+	dwarf_location* location = composite_entry.m_pieces[i].m_location;
+
+	location->incref ();
+	m_pieces.emplace_back (location, composite_entry.m_pieces[i].m_size);
+      }
+
+    m_completed = composite_entry.m_completed;
+  }
+
   /* A composite location gets detached from its factory object for
      the purpose of lval_computed resolution, which means that it
      needs to take care of garbage collecting its pieces.  */
@@ -591,6 +658,16 @@ class dwarf_composite : public dwarf_location
     return m_pieces.size ();
   }
 
+  void set_completed (bool completed)
+  {
+    m_completed = completed;
+  };
+
+  bool is_completed () const
+  {
+    return m_completed;
+  };
+
 private:
   /* Composite piece that contains a piece location
      description and it's size.  */
@@ -608,6 +685,9 @@ class dwarf_composite : public dwarf_location
 
   /* Vector of composite pieces.  */
   std::vector<struct piece> m_pieces;
+
+  /* True if location description is completed.  */
+  bool m_completed = false;
 };
 
 /* Read contents from the location specified by the DWARF location
@@ -789,6 +869,9 @@ read_from_location (const dwarf_location *location, struct frame_info *frame,
       unsigned int pieces_num = composite_entry->get_pieces_num ();
       unsigned int i;
 
+      if (!composite_entry->is_completed ())
+	ill_formed_expression ();
+
       total_bits_to_skip += offset * HOST_CHAR_BIT + bit_suboffset;
 
       /* Skip pieces covered by the read offset.  */
@@ -971,6 +1054,9 @@ write_to_location (const dwarf_location *location, struct frame_info *frame,
       unsigned int pieces_num = composite_entry->get_pieces_num ();
       unsigned int i;
 
+      if (!composite_entry->is_completed ())
+	ill_formed_expression ();
+
       total_bits_to_skip += offset * HOST_CHAR_BIT + bit_suboffset;
 
       /* Skip pieces covered by the write offset.  */
@@ -1008,6 +1094,92 @@ write_to_location (const dwarf_location *location, struct frame_info *frame,
     internal_error (__FILE__, __LINE__, _("invalid location type"));
 }
 
+/* Read value contents from the location specified by the DWARF
+   location description entry LOCATION.
+
+   The read operation is performed in the context of FRAME.  BIT_SIZE
+   is the number of bits to read.  The data read is copied to the
+   caller-managed buffer BUF.  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.  */
+
+static void
+read_value_contents_from_location (struct value * value,
+				   const dwarf_location *location,
+				   struct frame_info *frame,
+				   LONGEST bits_to_skip,
+				   int value_bit_offset, size_t bit_size,
+				   size_t location_bit_limit)
+{
+  /* Implicit pointers are handled later.  */
+  if (dynamic_cast<const dwarf_implicit_pointer *> (location) != nullptr)
+    return;
+
+  auto composite_entry = dynamic_cast<const dwarf_composite *> (location);
+
+  if (composite_entry == nullptr)
+    {
+      int optimized, unavailable;
+      bool big_endian = type_byte_order (value_type (value)) == BFD_ENDIAN_BIG;
+
+      read_from_location (location, frame, bits_to_skip,
+			  value_contents_raw (value),
+			  value_bit_offset, bit_size, location_bit_limit,
+			  big_endian, &optimized, &unavailable);
+
+      if (optimized)
+	mark_value_bits_optimized_out (value, value_bit_offset, bit_size);
+      if (unavailable)
+	mark_value_bits_unavailable (value, value_bit_offset, bit_size);
+
+      return;
+    }
+
+  if (!composite_entry->is_completed ())
+    ill_formed_expression ();
+
+  unsigned int pieces_num = composite_entry->get_pieces_num ();
+  unsigned int i;
+
+  LONGEST total_bits_to_skip = bits_to_skip
+			       + composite_entry->get_offset () * HOST_CHAR_BIT
+			       + composite_entry->get_bit_suboffset ();
+
+  /* Skip pieces covered by the read offset.  */
+  for (i = 0; i < pieces_num; i++)
+    {
+      LONGEST piece_bit_size = composite_entry->get_bit_size_at (i);
+
+      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 = composite_entry->get_bit_size_at (i);
+      const dwarf_location *piece = composite_entry->get_piece_at (i);
+
+      if (piece_bit_size > bit_size)
+	piece_bit_size = bit_size;
+
+      read_value_contents_from_location (value, piece, frame,
+					 total_bits_to_skip,
+					 value_bit_offset, piece_bit_size,
+					 piece_bit_size);
+
+      if (bit_size == piece_bit_size)
+	break;
+
+      value_bit_offset += piece_bit_size;
+      bit_size -= piece_bit_size;
+    }
+}
+
 /* Convert a value entry to the matching struct value representation
    of a given TYPE.  OFFSET defines the offset into the value
    contents.
@@ -1107,6 +1279,9 @@ class dwarf_entry_factory
   dwarf_composite *create_composite (LONGEST offset = 0,
 				     LONGEST bit_suboffset = 0);
 
+  /* Create a deep copy of the DWARF ENTRY.  */
+  dwarf_entry *copy_entry (dwarf_entry *entry);
+
   /* Convert an entry to a location description entry. If the entry
      is a location description entry a dynamic cast is applied.
 
@@ -1252,6 +1427,33 @@ dwarf_entry_factory::create_composite (LONGEST offset, LONGEST bit_suboffset)
   return composite_entry;
 }
 
+dwarf_entry *
+dwarf_entry_factory::copy_entry (dwarf_entry *entry)
+{
+  dwarf_entry *entry_copy;
+
+  if (auto value = dynamic_cast<dwarf_value *> (entry))
+    entry_copy = new dwarf_value (*value);
+  else if (auto undefined = dynamic_cast<dwarf_undefined *> (entry))
+    entry_copy = new dwarf_undefined (*undefined);
+  else if (auto memory = dynamic_cast<dwarf_memory *> (entry))
+    entry_copy = new dwarf_memory (*memory);
+  else if (auto reg = dynamic_cast<dwarf_register *> (entry))
+    entry_copy = new dwarf_register (*reg);
+  else if (auto implicit = dynamic_cast<dwarf_implicit *> (entry))
+    entry_copy = new dwarf_implicit (*implicit);
+  else if (auto implicit_pointer
+	    = dynamic_cast<dwarf_implicit_pointer *> (entry))
+    entry_copy = new dwarf_implicit_pointer (*implicit_pointer);
+  else if (auto composite = dynamic_cast<dwarf_composite *> (entry))
+    entry_copy = new dwarf_composite (*composite);
+  else
+    internal_error (__FILE__, __LINE__, _("invalid DWARF entry to copy."));
+
+  record_entry (entry_copy);
+  return entry_copy;
+}
+
 dwarf_location *
 dwarf_entry_factory::entry_to_location (dwarf_entry *entry)
 {
@@ -1460,30 +1662,19 @@ rw_closure_value (struct value *v, struct value *from)
       const dwarf_location *location = composite_entry->get_piece_at (i);
       ULONGEST bit_size = composite_entry->get_bit_size_at (i);
       size_t this_bit_size = bit_size - bits_to_skip;
-      int optimized, unavailable;
 
       if (this_bit_size > max_bit_offset - bit_offset)
 	this_bit_size = max_bit_offset - bit_offset;
 
       if (from == NULL)
 	{
-	  /* Implicit pointers are handled later.  */
-	  if (dynamic_cast<const dwarf_implicit_pointer *>
-		(location) == nullptr)
-	    {
-	      read_from_location (location, frame, bits_to_skip,
-				  value_contents_raw (v), bit_offset,
-				  this_bit_size, bit_size, big_endian,
-				  &optimized, &unavailable);
-
-	      if (optimized)
-		mark_value_bits_optimized_out (v, bit_offset, this_bit_size);
-	      if (unavailable)
-		mark_value_bits_unavailable (v, bit_offset, this_bit_size);
-	    }
+	  read_value_contents_from_location (v, location, frame, bits_to_skip,
+					     bit_offset, this_bit_size, bit_size);
 	}
       else
 	{
+	  int optimized, unavailable;
+
 	  write_to_location (location, frame, bits_to_skip,
 			     value_contents (from), bit_offset,
 			     this_bit_size, bit_size, big_endian,
@@ -1892,10 +2083,34 @@ struct dwarf_expr_context
 
   /* Pop a top element of the stack and add as a composite piece.
 
-     If the fallowing top element of the stack is a composite
-     location description, the piece will be added to it.  Otherwise
-     a new composite location description will be created and
-     the piece will be added to that composite.  */
+     The action is based on the context:
+
+      - If the stack is empty, then an incomplete composite location
+	description (comprised of one undefined location description),
+	is pushed on the stack.
+
+      - Otherwise, if the top stack entry is an incomplete composite
+	location description, then it is updated to append a new piece
+	comprised of one undefined location description.  The
+	incomplete composite location description is then left on the
+	stack.
+
+      - Otherwise, if the top stack entry is a location description or
+	can be converted to one, it is popped. Then:
+
+	 - If the top stack entry (after popping) is a location
+	   description comprised of one incomplete composite location
+	   description, then it is updated to append a new piece
+	   specified by the previously popped location description.
+	   The incomplete composite location description is then left
+	   on the stack.
+
+	 - Otherwise, a new location description comprised of one
+	   incomplete composite location description, with a new piece
+	   specified by the previously popped location description, is
+	   pushed on the stack.
+
+      - Otherwise, the DWARF expression is ill-formed  */
   dwarf_entry *add_piece (ULONGEST bit_size, ULONGEST bit_offset);
 
   /* The engine for the expression evaluator.  Using the context in this
@@ -2534,26 +2749,39 @@ dwarf_expr_context::add_piece (ULONGEST bit_size, ULONGEST bit_offset)
   dwarf_location *piece_entry;
   dwarf_composite *composite_entry;
 
-  if (!stack_empty_p ()
-      && dynamic_cast<dwarf_composite *> (fetch (0)) == nullptr)
+  if (stack_empty_p ())
+    piece_entry = entry_factory->create_undefined ();
+  else
     {
       piece_entry = entry_factory->entry_to_location (fetch (0));
-      pop ();
+
+      if (auto old_composite_entry
+	    = dynamic_cast<dwarf_composite *> (piece_entry))
+	{
+	  if (!old_composite_entry->is_completed ())
+	    piece_entry = entry_factory->create_undefined ();
+	}
+      else if (dynamic_cast<dwarf_undefined *> (piece_entry) != nullptr)
+	pop ();
     }
-  else
-    piece_entry = entry_factory->create_undefined ();
 
-  piece_entry->add_bit_offset (bit_offset);
+  if (dynamic_cast<dwarf_undefined *> (piece_entry) == nullptr)
+    {
+      piece_entry->add_bit_offset (bit_offset);
+      pop ();
+    }
 
-  /* If stack is empty then it is a start of a new composite.  In the
-     future this will check if the composite is finished or not.  */
   if (stack_empty_p ()
       || dynamic_cast<dwarf_composite *> (fetch (0)) == nullptr)
     composite_entry = entry_factory->create_composite ();
   else
     {
       composite_entry = dynamic_cast<dwarf_composite *> (fetch (0));
-      pop ();
+
+      if (composite_entry->is_completed ())
+	composite_entry = entry_factory->create_composite ();
+      else
+	pop ();
     }
 
   composite_entry->add_piece (piece_entry, bit_size);
@@ -3156,7 +3384,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	  break;
 
 	case DW_OP_dup:
-	  result_entry = fetch (0);
+	  result_entry = entry_factory->copy_entry (fetch (0));
 	  break;
 
 	case DW_OP_drop:
@@ -3182,7 +3410,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	  }
 
 	case DW_OP_over:
-	  result_entry = fetch (1);
+	  result_entry = entry_factory->copy_entry (fetch (1));
 	  break;
 
 	case DW_OP_rot:
@@ -3742,6 +3970,23 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	  result_entry = entry_factory->create_undefined ();
 	  break;
 
+	case DW_OP_LLVM_piece_end:
+	  {
+	    dwarf_entry *entry = fetch (0);
+
+	    dwarf_composite *composite_entry
+	      = dynamic_cast<dwarf_composite *> (entry);
+
+	    if (composite_entry == nullptr)
+	      ill_formed_expression ();
+
+	    if (composite_entry->is_completed ())
+	      ill_formed_expression ();
+
+	    composite_entry->set_completed (true);
+	    goto no_push;
+	  }
+
 	default:
 	  error (_("Unhandled dwarf expression opcode 0x%x"), op);
 	}
diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c
index 1a903ce123..e98d6fb39d 100644
--- a/gdb/dwarf2/loc.c
+++ b/gdb/dwarf2/loc.c
@@ -1832,6 +1832,7 @@ dwarf2_get_symbol_read_needs (gdb::array_view<const gdb_byte> expr,
 	case DW_OP_LLVM_offset:
 	case DW_OP_LLVM_bit_offset:
 	case DW_OP_LLVM_undefined:
+	case DW_OP_LLVM_piece_end:
 	  break;
 
 	case DW_OP_form_tls_address:
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-llvm-piece-end.exp b/gdb/testsuite/gdb.dwarf2/dw2-llvm-piece-end.exp
new file mode 100644
index 0000000000..3da739ea72
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-llvm-piece-end.exp
@@ -0,0 +1,191 @@
+# Copyright 2017-2020 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test the nested composition location description by using the new
+# DW_OP_LLVM_piece_end operation.
+#
+# The test uses three nested levels of composite location descriptions
+# to define a location of an array.
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if {![dwarf2_support]} {
+    return 0
+}
+
+# Choose suitable integer registers for the test.
+
+set dwarf_regnum 0
+
+if { [is_aarch64_target] } {
+    set regname x0
+} elseif { [is_aarch32_target]
+	   || [istarget "s390*-*-*" ]
+	   || [istarget "powerpc*-*-*"]
+	   || [istarget "rs6000*-*-aix*"] } {
+    set regname r0
+} elseif { [is_x86_like_target] } {
+    set regname eax
+} elseif { [is_amd64_regs_target] } {
+    set regname rax
+} else {
+    verbose "Skipping ${gdb_test_file_name}."
+    return
+}
+
+standard_testfile var-access.c ${gdb_test_file_name}-dw.S
+
+# Make some DWARF for the test.
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+    global dwarf_regnum regname srcdir subdir srcfile
+    set buf_src [gdb_target_symbol buf]
+
+    set main_result [function_range main ${srcdir}/${subdir}/${srcfile}]
+    set main_start [lindex $main_result 0]
+    set main_length [lindex $main_result 1]
+
+    cu {} {
+	DW_TAG_compile_unit {
+	    {DW_AT_name var-access.c}
+	    {DW_AT_comp_dir /tmp}
+	} {
+	    declare_labels array_type_label int_type_label char_type_label
+
+	    # define char type
+	    char_type_label: DW_TAG_base_type {
+		{DW_AT_name "char"}
+		{DW_AT_encoding @DW_ATE_signed}
+		{DW_AT_byte_size 1 DW_FORM_sdata}
+	    }
+
+	    int_type_label: DW_TAG_base_type {
+		{DW_AT_name "int"}
+		{DW_AT_encoding @DW_ATE_signed}
+		{DW_AT_byte_size 4 DW_FORM_sdata}
+	    }
+
+	    array_type_label: DW_TAG_array_type {
+		{DW_AT_type :$char_type_label}
+	    } {
+		DW_TAG_subrange_type {
+		    {DW_AT_type :$int_type_label}
+		    {DW_AT_upper_bound 7 DW_FORM_udata}
+		}
+	    }
+
+	    DW_TAG_subprogram {
+		{DW_AT_name main}
+		{DW_AT_low_pc $main_start addr}
+		{DW_AT_high_pc $main_length data8}
+	    } {
+		# Array spread in different pieces, of which some are
+		# undefined (1st and sixth bytes) and some are either
+		# in buf variable or REGNAME register.
+		#
+		# Location consists of three nested composite levels:
+		# - Third level consists of a composite location
+		# descriptions which hold a single simple location
+		# description each.
+		# - Second level consist of two more composite location
+		# descriptions that hold two of the third level
+		# composite location descriptions.
+		# - First level holds two of the second level composite
+		# location descriptions.
+
+		DW_TAG_variable {
+		    {DW_AT_name var_array}
+		    {DW_AT_type :$array_type_label}
+		    {DW_AT_location {
+			# First level composite start
+			# Second level first composite start
+			# Third level first composite start
+			DW_OP_addr $buf_src
+			DW_OP_piece 0x2
+			DW_OP_LLVM_piece_end
+			# Third level first composite end
+
+			# Third level second composite start
+			DW_OP_LLVM_undefined
+			DW_OP_piece 0x1
+			DW_OP_LLVM_piece_end
+			# Third level second composite end
+
+			DW_OP_piece 0x1
+			DW_OP_swap
+			DW_OP_piece 0x2
+			DW_OP_LLVM_piece_end
+			# Second level first composite end
+
+			# Second level second composite start
+			# Third level third composite start
+			DW_OP_regx $dwarf_regnum
+			DW_OP_piece 0x4
+			DW_OP_LLVM_piece_end
+			# Third level third composite end
+
+			# Third level fourth composite start
+			DW_OP_LLVM_undefined
+			DW_OP_piece 0x1
+			DW_OP_LLVM_piece_end
+			# Third level fourth composite end
+
+			DW_OP_piece 0x1
+			DW_OP_swap
+			DW_OP_piece 0x4
+			DW_OP_LLVM_piece_end
+			# Second level second composite end
+
+			DW_OP_piece 0x5
+			DW_OP_swap
+			DW_OP_piece 0x3
+			DW_OP_LLVM_piece_end
+			# First level composite end
+
+		    } SPECIAL_expr}
+		}
+	    }
+	}
+    }
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} \
+     [list $srcfile $asm_file] {nodebug}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_test_no_output "set var \$$regname = 0x4030201" "init reg"
+
+# Determine byte order.
+set endian [get_endianness]
+set optimized "<optimized out>"
+
+switch $endian {
+    little {
+	set val "$optimized, 0x1, 0x2, 0x3, 0x4, $optimized, 0x0, 0x1"
+    }
+    big {
+	set val "$optimized, 0x4, 0x3, 0x2, 0x1, $optimized, 0x0, 0x1"
+    }
+}
+
+gdb_test "print/x var_array" " = \\{${val}\\}" "var_array print"
+
diff --git a/include/dwarf2.def b/include/dwarf2.def
index b58560296d..fa6c20a9ef 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -709,6 +709,7 @@ DW_OP_DUP (DW_OP_LLVM_offset, 0xe3)
 DW_OP_DUP (DW_OP_LLVM_offset_constu, 0xe4)
 DW_OP_DUP (DW_OP_LLVM_bit_offset, 0xe5)
 DW_OP (DW_OP_LLVM_undefined, 0xe7)
+DW_OP_DUP (DW_OP_LLVM_piece_end, 0xea)
 DW_END_OP
 
 DW_FIRST_ATE (DW_ATE_void, 0x0)
-- 
2.17.1


  parent reply	other threads:[~2020-12-07 19:02 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 ` [PATCH 20/30] Add dwarf_entry factory class to expr.c Zoran Zaric via Gdb-patches
2021-02-09 19:54   ` 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 ` Zoran Zaric via Gdb-patches [this message]
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-31-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