public inbox for dwz@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] DWARFv5: Support for unit type DW_UT_type and DW_TAG_type_unit.
@ 2021-06-11  9:37 Achra, Nitika
  2021-06-11 10:54 ` Jakub Jelinek
  0 siblings, 1 reply; 3+ messages in thread
From: Achra, Nitika @ 2021-06-11  9:37 UTC (permalink / raw)
  To: dwz; +Cc: George, Jini Susan

[-- Attachment #1: Type: text/plain, Size: 172 bytes --]

[AMD Official Use Only]

Hi,

The attached patch handles the DW_UT_type and DW_TAG_type_unit for DWARFv5. Requesting everyone to please review this.

Regards,
Nitika

[-- Attachment #2: 0001-DWARFv5-Handle-unit-type-DW_UT_type-and-DW_TAG_type_.patch --]
[-- Type: application/octet-stream, Size: 12393 bytes --]

From 3a5f9d720de5c2db87d9cb95a24e5f1ed8aa0a53 Mon Sep 17 00:00:00 2001
From: nitachra <Nitika.Achra@amd.com>
Date: Wed, 14 Apr 2021 15:59:10 +0530
Subject: [PATCH] DWARFv5: Support for unit type DW_UT_type and DW_TAG_type_unit.

In Dwarfv5, .debug_types section is eliminated and its contents are moved
into the .debug_info section.

As per the DWARF Debugging Information Format Version 5, for each type defined
in a compilation unit, a separate contribution is made to the .debug_info section
of the object file. Each such contribution consists of a type unit header (see
Section 7.5.1.3 on page 202) followed by a DW_TAG_type_unit entry, together with its
children.

The type header contains:
unit_length
version
unit_type
address_size
debug_abbrev_offset
type_signature
type_offset

This patch handles DW_UT_type (value of unit_type in type unit header) and
DW_TAG_type_entry.

Test case used (test.c):

int main()
{
int a,b,sum;
sum = a+b;
return sum;
}

Before applying the patch dwz throws the following error messgae:

gcc -gdwarf-5 -fdebug-types-section test.c -o test.out
dwz test.out

dwz: test.out: DWARF CU type DW_UT_type unhandled.

Note: Used the gcc version 9.3

ChangeLog:
	* dwz.c (struct dw_cu): Add the header fields for type unit
	and a flag to denote whether this unit is type unit or not.
	(checksum_die): Handle DW_TAG_unit_type.
	(checksum_ref_die): Likewise.
	(die_eq_1): Likewise.
	(mark_refs): Likewise.
	(try_debug_info): Add DW_UT_type in the if condition.
	(read_debug_info): Add DW_UT_type in the if condition.
	Set the boolean flag isUTType if the unit_type is
	DW_UT_type. Read the type signature from the header.
	Read the language if the die is DW_TAG_type_unit.
	(mark_singletons): Handle DW_TAG_type_unit.
	(build_abbrevs_for_die): Likewise.
	(compute_abbrevs): Set the header size to be 24 bytes
	if the Dwarf version is 5 and the unit type is DW_UT_type.
	(write_info): Write the DW_UT_type as unit_type and write
	the type signature and type offset if the CU die tag is
	DW_TAG_type_unit.
---
 dwz.c | 73 +++++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 56 insertions(+), 17 deletions(-)

diff --git a/dwz.c b/dwz.c
index a3b289f..bdaf124 100644
--- a/dwz.c
+++ b/dwz.c
@@ -903,6 +903,13 @@ struct dw_cu
   unsigned int cu_offset;
   /* DWARF version of the CU.  */
   unsigned int cu_version;
+  /* True if the CU unit_type is DW_UT_type inside the debug_info.  */
+  bool isUTType;
+  /* A unique 8-byte signature of the type described in this type unit.  */
+  uint64_t cu_type_signature;
+  /* A 4-byte unsigned offset relative to the beginning of the type unit
+     header.  */
+  unsigned int cu_type_offset;
   /* Cached DW_AT_comp_dir value from DW_TAG_*_unit cu_die,
      or NULL if that attribute is not present.  */
   char *cu_comp_dir;
@@ -3245,6 +3252,7 @@ checksum_die (DSO *dso, dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die)
   die->u.p1.die_hash = 0;
   if (die->die_tag == DW_TAG_compile_unit
       || die->die_tag == DW_TAG_partial_unit
+      || die->die_tag == DW_TAG_type_unit
       || die->die_tag == DW_TAG_namespace
       || die->die_tag == DW_TAG_module
       || die->die_tag == DW_TAG_imported_unit)
@@ -4065,6 +4073,7 @@ checksum_ref_die (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die,
 	      while (!reft->die_root
 		     && reft->die_parent->die_tag != DW_TAG_compile_unit
 		     && reft->die_parent->die_tag != DW_TAG_partial_unit
+		     && reft->die_parent->die_tag != DW_TAG_type_unit
 		     && !reft->die_parent->die_named_namespace)
 		reft = reft->die_parent;
 	      if (reft->die_ck_state != CK_KNOWN || reft->die_root)
@@ -4580,9 +4589,11 @@ die_eq_1 (dw_cu_ref cu1, dw_cu_ref cu2,
 	{
 	  const char *name1, *name2;
 	  if ((ref1->die_tag == DW_TAG_compile_unit
-	       || ref1->die_tag == DW_TAG_partial_unit)
+	       || ref1->die_tag == DW_TAG_partial_unit
+	       || ref1->die_tag == DW_TAG_type_unit)
 	      && (ref2->die_tag == DW_TAG_compile_unit
-		  || ref2->die_tag == DW_TAG_partial_unit))
+		  || ref2->die_tag == DW_TAG_partial_unit
+		  || ref2->die_tag == DW_TAG_type_unit))
 	    break;
 	  if (ref1->die_tag != ref2->die_tag)
 	    return 0;
@@ -6023,6 +6034,7 @@ mark_refs (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die, int mode)
 	      while (!reft->die_root
 		     && reft->die_parent->die_tag != DW_TAG_compile_unit
 		     && reft->die_parent->die_tag != DW_TAG_partial_unit
+		     && reft->die_parent->die_tag != DW_TAG_type_unit
 		     && !reft->die_parent->die_named_namespace)
 		reft = reft->die_parent;
 	      if ((mode & MARK_REFS_FOLLOW_DUPS) && reft->die_dup != NULL)
@@ -6342,7 +6354,7 @@ try_debug_info (DSO *dso)
       if (cu_version == 5)
 	{
 	  value = read_8 (ptr);
-	  if (value != DW_UT_compile && value != DW_UT_partial)
+	  if (value != DW_UT_compile && value != DW_UT_partial && value != DW_UT_type)
 	    error (0, 0, "%s: DWARF CU type %s unhandled", dso->filename,
 		   get_DW_UT_str (value));
 	}
@@ -6571,6 +6583,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
       bool present;
       unsigned int debug_line_off;
       unsigned int type_offset = 0;
+      uint64_t type_signature = 0;
+      bool isUTType = false;
 
       /* Note header is one bigger with DWARF version 5.  */
       if (ptr + (kind == DEBUG_TYPES ? 23 : 11) > endsec)
@@ -6613,12 +6627,13 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
       if (cu_version == 5)
 	{
 	  value = read_8 (ptr);
-	  if (value != DW_UT_compile && value != DW_UT_partial)
+	  if (value != DW_UT_compile && value != DW_UT_partial && value != DW_UT_type)
 	    {
 	      error (0, 0, "%s: DWARF CU type %s unhandled", dso->filename,
 		     get_DW_UT_str (value));
 	      goto fail;
 	    }
+	  isUTType = (value == DW_UT_type);
 	}
       else
 	{
@@ -6760,9 +6775,9 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 	}
       last_abbrev_offset = value;
 
-      if (unlikely (kind == DEBUG_TYPES))
+      if (unlikely (kind == DEBUG_TYPES) || isUTType)
 	{
-	  ptr += 8;
+	  type_signature = read_64 (ptr);
 	  type_offset = read_32 (ptr);
 	}
 
@@ -6775,6 +6790,10 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
       cu->cu_offset = cu_offset;
       cu->cu_version = cu_version;
       cu->cu_chunk = cu_chunk;
+      cu->cu_type_offset = type_offset;
+      cu->cu_type_signature = type_signature;
+      cu->isUTType = isUTType;
+
       if (unlikely (op_multifile || low_mem))
 	cu->cu_abbrev = abbrev;
       diep = &cu->cu_die;
@@ -6955,14 +6974,16 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 		case DW_FORM_implicit_const:
 		  if (lang_p
 		      && (die->die_tag == DW_TAG_compile_unit
-			  || die->die_tag == DW_TAG_partial_unit)
+			  || die->die_tag == DW_TAG_partial_unit
+			  || die->die_tag == DW_TAG_type_unit)
 		      && t->attr[i].attr == DW_AT_language)
 		    cu->lang = t->values[i];
 		  break;
 		case DW_FORM_data1:
 		  if (lang_p
 		      && (die->die_tag == DW_TAG_compile_unit
-			  || die->die_tag == DW_TAG_partial_unit)
+			  || die->die_tag == DW_TAG_partial_unit
+			  || die->die_tag == DW_TAG_type_unit)
 		      && t->attr[i].attr == DW_AT_language)
 		    cu->lang = *ptr;
 		  /* FALLTHRU */
@@ -6973,7 +6994,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 		case DW_FORM_data2:
 		  if (lang_p
 		      && (die->die_tag == DW_TAG_compile_unit
-			  || die->die_tag == DW_TAG_partial_unit)
+			  || die->die_tag == DW_TAG_partial_unit
+			  || die->die_tag == DW_TAG_type_unit)
 		      && t->attr[i].attr == DW_AT_language)
 		    cu->lang = do_read_16 (ptr);
 		  /* FALLTHRU */
@@ -6983,7 +7005,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 		case DW_FORM_data4:
 		  if (lang_p
 		      && (die->die_tag == DW_TAG_compile_unit
-			  || die->die_tag == DW_TAG_partial_unit)
+			  || die->die_tag == DW_TAG_partial_unit
+			  || die->die_tag == DW_TAG_type_unit)
 		      && t->attr[i].attr == DW_AT_language)
 		    read_lang (ptr, form, &cu->lang);
 		  /* FALLTHRU */
@@ -6994,7 +7017,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 		case DW_FORM_data8:
 		  if (lang_p
 		      && (die->die_tag == DW_TAG_compile_unit
-			  || die->die_tag == DW_TAG_partial_unit)
+			  || die->die_tag == DW_TAG_partial_unit
+			  || die->die_tag == DW_TAG_type_unit)
 		      && t->attr[i].attr == DW_AT_language)
 		    read_lang (ptr, form, &cu->lang);
 		  /* FALLTHRU */
@@ -7009,7 +7033,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 		case DW_FORM_udata:
 		  if (lang_p
 		      && (die->die_tag == DW_TAG_compile_unit
-			  || die->die_tag == DW_TAG_partial_unit)
+			  || die->die_tag == DW_TAG_partial_unit
+			  || die->die_tag == DW_TAG_type_unit)
 		      && t->attr[i].attr == DW_AT_language)
 		    {
 		      ptr = read_lang (ptr, form, &cu->lang);
@@ -7559,6 +7584,7 @@ mark_singletons (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die,
 	  while (!reft->die_root
 		 && reft->die_parent->die_tag != DW_TAG_compile_unit
 		 && reft->die_parent->die_tag != DW_TAG_partial_unit
+		 && reft->die_parent->die_tag != DW_TAG_type_unit
 		 && !reft->die_parent->die_named_namespace)
 	    reft = reft->die_parent;
 	  if (reft->die_dup != NULL || reft->die_nextdup != NULL)
@@ -11001,6 +11027,7 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die,
       {
       case DW_TAG_partial_unit:
       case DW_TAG_compile_unit:
+      case DW_TAG_type_unit:
 	t->nattr = 0;
 	die->die_size = 0;
 	if (origin == NULL)
@@ -11014,7 +11041,7 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die,
 	    die->die_size += 4;
 	    t->nattr++;
 	  }
-	if (uni_lang_p || cu->cu_die->die_tag == DW_TAG_compile_unit)
+	if (uni_lang_p || cu->cu_die->die_tag == DW_TAG_compile_unit || cu->cu_die->die_tag == DW_TAG_type_unit)
 	  {
 	    unsigned int lang_size = nr_bytes_for (cu->lang);
 	    die->die_size += lang_size;
@@ -11421,7 +11448,7 @@ compute_abbrevs (DSO *dso)
       enum dwarf_form intracuform = DW_FORM_ref4;
       dw_die_ref child, *lastotr, child_next, *last;
       unsigned int headersz = (cu->cu_kind == CU_TYPES
-			       ? 23 : (cu->cu_version >= 5 ? 12 : 11));
+			       ? 23 : (cu->cu_version >= 5 ? (cu->isUTType ? 24 : 12) : 11));
 
       if (unlikely (fi_multifile) && cu->cu_die->die_remove)
 	continue;
@@ -12639,6 +12666,7 @@ write_die (unsigned char *ptr, dw_cu_ref cu, dw_die_ref die,
       {
       case DW_TAG_partial_unit:
       case DW_TAG_compile_unit:
+      case DW_TAG_type_unit:
 	ptr = write_unit_die (ptr, die, origin);
 	break;
       case DW_TAG_namespace:
@@ -12737,7 +12765,7 @@ static void
 recompute_abbrevs (dw_cu_ref cu, unsigned int cu_size)
 {
   unsigned int headersz = (cu->cu_kind == CU_TYPES
-			   ? 23 : (cu->cu_version >= 5 ? 12 : 11));
+			   ? 23 : (cu->cu_version >= 5 ? (cu->isUTType ? 24 : 12) : 11));
   struct abbrev_tag *t;
   unsigned int ndies = 0, intracusize, off, i;
   dw_die_ref *intracuarr, *intracuvec;
@@ -12846,13 +12874,23 @@ write_info (unsigned int *die_count)
       write_16 (ptr, cu->cu_version);
       if (cu->cu_version >= 5)
 	{
-	  *ptr++ = (cu->cu_die->die_tag == DW_TAG_compile_unit
-		    ? DW_UT_compile : DW_UT_partial);
+	  if (cu->cu_die->die_tag == DW_TAG_compile_unit)
+	    *ptr++ = DW_UT_compile;
+	  else if (cu->cu_die->die_tag == DW_TAG_type_unit)
+	    *ptr++ = DW_UT_type;
+	  else
+	    *ptr++ = DW_UT_partial;
 	  write_8 (ptr, ptr_size);
 	}
       write_32 (ptr, cu->u2.cu_new_abbrev_offset);
       if (cu->cu_version < 5)
 	write_8 (ptr, ptr_size);
+      if (cu->cu_die->die_tag == DW_TAG_type_unit)
+	{ 
+	  write_64 (ptr, cu->cu_type_signature);
+	  write_32 (ptr, cu->cu_type_offset);
+	}
+
       ptr = write_die (ptr, cu, cu->cu_die, NULL, NULL, die_count);
       assert (info + (next_off - (wr_multifile ? multi_info_off : 0)) == ptr);
       if (unlikely (low_mem) && cu->cu_kind != CU_PU)
@@ -14470,6 +14508,7 @@ propagate_multifile_refs_backward (dw_cu_ref cu, dw_die_ref top_die,
 	  while (!reft->die_root
 		 && reft->die_parent->die_tag != DW_TAG_compile_unit
 		 && reft->die_parent->die_tag != DW_TAG_partial_unit
+		 && reft->die_parent->die_tag != DW_TAG_type_unit
 		 && !reft->die_parent->die_named_namespace)
 	    reft = reft->die_parent;
 	  if (reft->die_root)
-- 
2.17.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] DWARFv5: Support for unit type DW_UT_type and DW_TAG_type_unit.
  2021-06-11  9:37 [PATCH] DWARFv5: Support for unit type DW_UT_type and DW_TAG_type_unit Achra, Nitika
@ 2021-06-11 10:54 ` Jakub Jelinek
  2021-07-28 14:32   ` Achra, Nitika
  0 siblings, 1 reply; 3+ messages in thread
From: Jakub Jelinek @ 2021-06-11 10:54 UTC (permalink / raw)
  To: Achra, Nitika; +Cc: dwz, George, Jini Susan

On Fri, Jun 11, 2021 at 09:37:18AM +0000, Achra, Nitika via Dwz wrote:
> The attached patch handles the DW_UT_type and DW_TAG_type_unit for DWARFv5. Requesting everyone to please review this.

Ideally, dwz should rewrite all those DW_TAG_type_units into
DW_TAG_partial_unit, after a library or binary is linked, nothing
from outside can refer to its type units.  The DW_FORM_ref_sig8 references
are too large, DW_FORM_ref_addr is (for 32-bit DWARF) half the size and
cheaper for the consumer which doesn't have to look up the type id in some
hash table.  Furthermore one can save some bytes from the unit header too.

--- a/dwz.c
+++ b/dwz.c
@@ -903,6 +903,13 @@ struct dw_cu
   unsigned int cu_offset;
   /* DWARF version of the CU.  */
   unsigned int cu_version;
+  /* True if the CU unit_type is DW_UT_type inside the debug_info.  */
+  bool isUTType;

Why can't this be in cu_kind instead, just another kind?
And, dwz doesn't use this kind of variable/field names.

+  /* A unique 8-byte signature of the type described in this type unit.  */
+  uint64_t cu_type_signature;
+  /* A 4-byte unsigned offset relative to the beginning of the type unit
+     header.  */
+  unsigned int cu_type_offset;

This will create unnecessary padding in the struct on 64-bit arches.
They should be moved somewhere where that doesn't happen.

   /* Cached DW_AT_comp_dir value from DW_TAG_*_unit cu_die,
      or NULL if that attribute is not present.  */
   char *cu_comp_dir;
@@ -3245,6 +3252,7 @@ checksum_die (DSO *dso, dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die)
   die->u.p1.die_hash = 0;
   if (die->die_tag == DW_TAG_compile_unit
       || die->die_tag == DW_TAG_partial_unit
+      || die->die_tag == DW_TAG_type_unit
       || die->die_tag == DW_TAG_namespace
       || die->die_tag == DW_TAG_module
       || die->die_tag == DW_TAG_imported_unit)
@@ -4065,6 +4073,7 @@ checksum_ref_die (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die,
 	      while (!reft->die_root
 		     && reft->die_parent->die_tag != DW_TAG_compile_unit
 		     && reft->die_parent->die_tag != DW_TAG_partial_unit
+		     && reft->die_parent->die_tag != DW_TAG_type_unit
 		     && !reft->die_parent->die_named_namespace)
 		reft = reft->die_parent;
 	      if (reft->die_ck_state != CK_KNOWN || reft->die_root)
@@ -4580,9 +4589,11 @@ die_eq_1 (dw_cu_ref cu1, dw_cu_ref cu2,
 	{
 	  const char *name1, *name2;
 	  if ((ref1->die_tag == DW_TAG_compile_unit
-	       || ref1->die_tag == DW_TAG_partial_unit)
+	       || ref1->die_tag == DW_TAG_partial_unit
+	       || ref1->die_tag == DW_TAG_type_unit)
 	      && (ref2->die_tag == DW_TAG_compile_unit
-		  || ref2->die_tag == DW_TAG_partial_unit))
+		  || ref2->die_tag == DW_TAG_partial_unit
+		  || ref2->die_tag == DW_TAG_type_unit))
 	    break;
 	  if (ref1->die_tag != ref2->die_tag)
 	    return 0;
@@ -6023,6 +6034,7 @@ mark_refs (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die, int mode)
 	      while (!reft->die_root
 		     && reft->die_parent->die_tag != DW_TAG_compile_unit
 		     && reft->die_parent->die_tag != DW_TAG_partial_unit
+		     && reft->die_parent->die_tag != DW_TAG_type_unit
 		     && !reft->die_parent->die_named_namespace)
 		reft = reft->die_parent;
 	      if ((mode & MARK_REFS_FOLLOW_DUPS) && reft->die_dup != NULL)
@@ -6342,7 +6354,7 @@ try_debug_info (DSO *dso)
       if (cu_version == 5)
 	{
 	  value = read_8 (ptr);
-	  if (value != DW_UT_compile && value != DW_UT_partial)
+	  if (value != DW_UT_compile && value != DW_UT_partial && value != DW_UT_type)
 	    error (0, 0, "%s: DWARF CU type %s unhandled", dso->filename,
 		   get_DW_UT_str (value));
 	}
@@ -6571,6 +6583,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
       bool present;
       unsigned int debug_line_off;
       unsigned int type_offset = 0;
+      uint64_t type_signature = 0;
+      bool isUTType = false;
 
       /* Note header is one bigger with DWARF version 5.  */
       if (ptr + (kind == DEBUG_TYPES ? 23 : 11) > endsec)
@@ -6613,12 +6627,13 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
       if (cu_version == 5)
 	{
 	  value = read_8 (ptr);
-	  if (value != DW_UT_compile && value != DW_UT_partial)
+	  if (value != DW_UT_compile && value != DW_UT_partial && value != DW_UT_type)
 	    {
 	      error (0, 0, "%s: DWARF CU type %s unhandled", dso->filename,
 		     get_DW_UT_str (value));
 	      goto fail;
 	    }
+	  isUTType = (value == DW_UT_type);
 	}
       else
 	{
@@ -6760,9 +6775,9 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 	}
       last_abbrev_offset = value;
 
-      if (unlikely (kind == DEBUG_TYPES))
+      if (unlikely (kind == DEBUG_TYPES) || isUTType)
 	{
-	  ptr += 8;
+	  type_signature = read_64 (ptr);
 	  type_offset = read_32 (ptr);
 	}
 
@@ -6775,6 +6790,10 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
       cu->cu_offset = cu_offset;
       cu->cu_version = cu_version;
       cu->cu_chunk = cu_chunk;
+      cu->cu_type_offset = type_offset;
+      cu->cu_type_signature = type_signature;
+      cu->isUTType = isUTType;
+
       if (unlikely (op_multifile || low_mem))
 	cu->cu_abbrev = abbrev;
       diep = &cu->cu_die;
@@ -6955,14 +6974,16 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 		case DW_FORM_implicit_const:
 		  if (lang_p
 		      && (die->die_tag == DW_TAG_compile_unit
-			  || die->die_tag == DW_TAG_partial_unit)
+			  || die->die_tag == DW_TAG_partial_unit
+			  || die->die_tag == DW_TAG_type_unit)
 		      && t->attr[i].attr == DW_AT_language)
 		    cu->lang = t->values[i];
 		  break;
 		case DW_FORM_data1:
 		  if (lang_p
 		      && (die->die_tag == DW_TAG_compile_unit
-			  || die->die_tag == DW_TAG_partial_unit)
+			  || die->die_tag == DW_TAG_partial_unit
+			  || die->die_tag == DW_TAG_type_unit)
 		      && t->attr[i].attr == DW_AT_language)
 		    cu->lang = *ptr;
 		  /* FALLTHRU */
@@ -6973,7 +6994,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 		case DW_FORM_data2:
 		  if (lang_p
 		      && (die->die_tag == DW_TAG_compile_unit
-			  || die->die_tag == DW_TAG_partial_unit)
+			  || die->die_tag == DW_TAG_partial_unit
+			  || die->die_tag == DW_TAG_type_unit)
 		      && t->attr[i].attr == DW_AT_language)
 		    cu->lang = do_read_16 (ptr);
 		  /* FALLTHRU */
@@ -6983,7 +7005,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 		case DW_FORM_data4:
 		  if (lang_p
 		      && (die->die_tag == DW_TAG_compile_unit
-			  || die->die_tag == DW_TAG_partial_unit)
+			  || die->die_tag == DW_TAG_partial_unit
+			  || die->die_tag == DW_TAG_type_unit)
 		      && t->attr[i].attr == DW_AT_language)
 		    read_lang (ptr, form, &cu->lang);
 		  /* FALLTHRU */
@@ -6994,7 +7017,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 		case DW_FORM_data8:
 		  if (lang_p
 		      && (die->die_tag == DW_TAG_compile_unit
-			  || die->die_tag == DW_TAG_partial_unit)
+			  || die->die_tag == DW_TAG_partial_unit
+			  || die->die_tag == DW_TAG_type_unit)
 		      && t->attr[i].attr == DW_AT_language)
 		    read_lang (ptr, form, &cu->lang);
 		  /* FALLTHRU */
@@ -7009,7 +7033,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 		case DW_FORM_udata:
 		  if (lang_p
 		      && (die->die_tag == DW_TAG_compile_unit
-			  || die->die_tag == DW_TAG_partial_unit)
+			  || die->die_tag == DW_TAG_partial_unit
+			  || die->die_tag == DW_TAG_type_unit)
 		      && t->attr[i].attr == DW_AT_language)
 		    {
 		      ptr = read_lang (ptr, form, &cu->lang);
@@ -7559,6 +7584,7 @@ mark_singletons (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die,
 	  while (!reft->die_root
 		 && reft->die_parent->die_tag != DW_TAG_compile_unit
 		 && reft->die_parent->die_tag != DW_TAG_partial_unit
+		 && reft->die_parent->die_tag != DW_TAG_type_unit
 		 && !reft->die_parent->die_named_namespace)
 	    reft = reft->die_parent;
 	  if (reft->die_dup != NULL || reft->die_nextdup != NULL)
@@ -11001,6 +11027,7 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die,
       {
       case DW_TAG_partial_unit:
       case DW_TAG_compile_unit:
+      case DW_TAG_type_unit:
 	t->nattr = 0;
 	die->die_size = 0;
 	if (origin == NULL)
@@ -11014,7 +11041,7 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die,
 	    die->die_size += 4;
 	    t->nattr++;
 	  }
-	if (uni_lang_p || cu->cu_die->die_tag == DW_TAG_compile_unit)
+	if (uni_lang_p || cu->cu_die->die_tag == DW_TAG_compile_unit || cu->cu_die->die_tag == DW_TAG_type_unit)
 	  {
 	    unsigned int lang_size = nr_bytes_for (cu->lang);
 	    die->die_size += lang_size;
@@ -11421,7 +11448,7 @@ compute_abbrevs (DSO *dso)
       enum dwarf_form intracuform = DW_FORM_ref4;
       dw_die_ref child, *lastotr, child_next, *last;
       unsigned int headersz = (cu->cu_kind == CU_TYPES
-			       ? 23 : (cu->cu_version >= 5 ? 12 : 11));
+			       ? 23 : (cu->cu_version >= 5 ? (cu->isUTType ? 24 : 12) : 11));
 
       if (unlikely (fi_multifile) && cu->cu_die->die_remove)
 	continue;
@@ -12639,6 +12666,7 @@ write_die (unsigned char *ptr, dw_cu_ref cu, dw_die_ref die,
       {
       case DW_TAG_partial_unit:
       case DW_TAG_compile_unit:
+      case DW_TAG_type_unit:
 	ptr = write_unit_die (ptr, die, origin);
 	break;
       case DW_TAG_namespace:
@@ -12737,7 +12765,7 @@ static void
 recompute_abbrevs (dw_cu_ref cu, unsigned int cu_size)
 {
   unsigned int headersz = (cu->cu_kind == CU_TYPES
-			   ? 23 : (cu->cu_version >= 5 ? 12 : 11));
+			   ? 23 : (cu->cu_version >= 5 ? (cu->isUTType ? 24 : 12) : 11));
   struct abbrev_tag *t;
   unsigned int ndies = 0, intracusize, off, i;
   dw_die_ref *intracuarr, *intracuvec;
@@ -12846,13 +12874,23 @@ write_info (unsigned int *die_count)
       write_16 (ptr, cu->cu_version);
       if (cu->cu_version >= 5)
 	{
-	  *ptr++ = (cu->cu_die->die_tag == DW_TAG_compile_unit
-		    ? DW_UT_compile : DW_UT_partial);
+	  if (cu->cu_die->die_tag == DW_TAG_compile_unit)
+	    *ptr++ = DW_UT_compile;
+	  else if (cu->cu_die->die_tag == DW_TAG_type_unit)
+	    *ptr++ = DW_UT_type;
+	  else
+	    *ptr++ = DW_UT_partial;
 	  write_8 (ptr, ptr_size);
 	}
       write_32 (ptr, cu->u2.cu_new_abbrev_offset);
       if (cu->cu_version < 5)
 	write_8 (ptr, ptr_size);
+      if (cu->cu_die->die_tag == DW_TAG_type_unit)
+	{ 
+	  write_64 (ptr, cu->cu_type_signature);
+	  write_32 (ptr, cu->cu_type_offset);
+	}
+
       ptr = write_die (ptr, cu, cu->cu_die, NULL, NULL, die_count);
       assert (info + (next_off - (wr_multifile ? multi_info_off : 0)) == ptr);
       if (unlikely (low_mem) && cu->cu_kind != CU_PU)
@@ -14470,6 +14508,7 @@ propagate_multifile_refs_backward (dw_cu_ref cu, dw_die_ref top_die,
 	  while (!reft->die_root
 		 && reft->die_parent->die_tag != DW_TAG_compile_unit
 		 && reft->die_parent->die_tag != DW_TAG_partial_unit
+		 && reft->die_parent->die_tag != DW_TAG_type_unit
 		 && !reft->die_parent->die_named_namespace)
 	    reft = reft->die_parent;
 	  if (reft->die_root)
-- 
2.17.1


	Jakub


^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: [PATCH] DWARFv5: Support for unit type DW_UT_type and DW_TAG_type_unit.
  2021-06-11 10:54 ` Jakub Jelinek
@ 2021-07-28 14:32   ` Achra, Nitika
  0 siblings, 0 replies; 3+ messages in thread
From: Achra, Nitika @ 2021-07-28 14:32 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: dwz, George, Jini Susan

[-- Attachment #1: Type: text/plain, Size: 13512 bytes --]

[AMD Official Use Only]

Hi Jakub,

Thanks for the review. Please find the attached patch with some of the changes you suggested.
Please take a look at it.

Regards,
Nitika

-----Original Message-----
From: Jakub Jelinek <jakub@redhat.com> 
Sent: Friday, June 11, 2021 4:25 PM
To: Achra, Nitika <Nitika.Achra@amd.com>
Cc: dwz@sourceware.org; George, Jini Susan <JiniSusan.George@amd.com>
Subject: Re: [PATCH] DWARFv5: Support for unit type DW_UT_type and DW_TAG_type_unit.

[CAUTION: External Email]

On Fri, Jun 11, 2021 at 09:37:18AM +0000, Achra, Nitika via Dwz wrote:
> The attached patch handles the DW_UT_type and DW_TAG_type_unit for DWARFv5. Requesting everyone to please review this.

Ideally, dwz should rewrite all those DW_TAG_type_units into DW_TAG_partial_unit, after a library or binary is linked, nothing from outside can refer to its type units.  The DW_FORM_ref_sig8 references are too large, DW_FORM_ref_addr is (for 32-bit DWARF) half the size and cheaper for the consumer which doesn't have to look up the type id in some hash table.  Furthermore one can save some bytes from the unit header too.

--- a/dwz.c
+++ b/dwz.c
@@ -903,6 +903,13 @@ struct dw_cu
   unsigned int cu_offset;
   /* DWARF version of the CU.  */
   unsigned int cu_version;
+  /* True if the CU unit_type is DW_UT_type inside the debug_info.  */  
+ bool isUTType;

Why can't this be in cu_kind instead, just another kind?
And, dwz doesn't use this kind of variable/field names.

+  /* A unique 8-byte signature of the type described in this type unit.  
+ */  uint64_t cu_type_signature;
+  /* A 4-byte unsigned offset relative to the beginning of the type unit
+     header.  */
+  unsigned int cu_type_offset;

This will create unnecessary padding in the struct on 64-bit arches.
They should be moved somewhere where that doesn't happen.

   /* Cached DW_AT_comp_dir value from DW_TAG_*_unit cu_die,
      or NULL if that attribute is not present.  */
   char *cu_comp_dir;
@@ -3245,6 +3252,7 @@ checksum_die (DSO *dso, dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die)
   die->u.p1.die_hash = 0;
   if (die->die_tag == DW_TAG_compile_unit
       || die->die_tag == DW_TAG_partial_unit
+      || die->die_tag == DW_TAG_type_unit
       || die->die_tag == DW_TAG_namespace
       || die->die_tag == DW_TAG_module
       || die->die_tag == DW_TAG_imported_unit) @@ -4065,6 +4073,7 @@ checksum_ref_die (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die,
              while (!reft->die_root
                     && reft->die_parent->die_tag != DW_TAG_compile_unit
                     && reft->die_parent->die_tag != DW_TAG_partial_unit
+                    && reft->die_parent->die_tag != DW_TAG_type_unit
                     && !reft->die_parent->die_named_namespace)
                reft = reft->die_parent;
              if (reft->die_ck_state != CK_KNOWN || reft->die_root) @@ -4580,9 +4589,11 @@ die_eq_1 (dw_cu_ref cu1, dw_cu_ref cu2,
        {
          const char *name1, *name2;
          if ((ref1->die_tag == DW_TAG_compile_unit
-              || ref1->die_tag == DW_TAG_partial_unit)
+              || ref1->die_tag == DW_TAG_partial_unit
+              || ref1->die_tag == DW_TAG_type_unit)
              && (ref2->die_tag == DW_TAG_compile_unit
-                 || ref2->die_tag == DW_TAG_partial_unit))
+                 || ref2->die_tag == DW_TAG_partial_unit
+                 || ref2->die_tag == DW_TAG_type_unit))
            break;
          if (ref1->die_tag != ref2->die_tag)
            return 0;
@@ -6023,6 +6034,7 @@ mark_refs (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die, int mode)
              while (!reft->die_root
                     && reft->die_parent->die_tag != DW_TAG_compile_unit
                     && reft->die_parent->die_tag != DW_TAG_partial_unit
+                    && reft->die_parent->die_tag != DW_TAG_type_unit
                     && !reft->die_parent->die_named_namespace)
                reft = reft->die_parent;
              if ((mode & MARK_REFS_FOLLOW_DUPS) && reft->die_dup != NULL) @@ -6342,7 +6354,7 @@ try_debug_info (DSO *dso)
       if (cu_version == 5)
        {
          value = read_8 (ptr);
-         if (value != DW_UT_compile && value != DW_UT_partial)
+         if (value != DW_UT_compile && value != DW_UT_partial && value 
+ != DW_UT_type)
            error (0, 0, "%s: DWARF CU type %s unhandled", dso->filename,
                   get_DW_UT_str (value));
        }
@@ -6571,6 +6583,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
       bool present;
       unsigned int debug_line_off;
       unsigned int type_offset = 0;
+      uint64_t type_signature = 0;
+      bool isUTType = false;

       /* Note header is one bigger with DWARF version 5.  */
       if (ptr + (kind == DEBUG_TYPES ? 23 : 11) > endsec) @@ -6613,12 +6627,13 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
       if (cu_version == 5)
        {
          value = read_8 (ptr);
-         if (value != DW_UT_compile && value != DW_UT_partial)
+         if (value != DW_UT_compile && value != DW_UT_partial && value 
+ != DW_UT_type)
            {
              error (0, 0, "%s: DWARF CU type %s unhandled", dso->filename,
                     get_DW_UT_str (value));
              goto fail;
            }
+         isUTType = (value == DW_UT_type);
        }
       else
        {
@@ -6760,9 +6775,9 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
        }
       last_abbrev_offset = value;

-      if (unlikely (kind == DEBUG_TYPES))
+      if (unlikely (kind == DEBUG_TYPES) || isUTType)
        {
-         ptr += 8;
+         type_signature = read_64 (ptr);
          type_offset = read_32 (ptr);
        }

@@ -6775,6 +6790,10 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
       cu->cu_offset = cu_offset;
       cu->cu_version = cu_version;
       cu->cu_chunk = cu_chunk;
+      cu->cu_type_offset = type_offset;
+      cu->cu_type_signature = type_signature;
+      cu->isUTType = isUTType;
+
       if (unlikely (op_multifile || low_mem))
        cu->cu_abbrev = abbrev;
       diep = &cu->cu_die;
@@ -6955,14 +6974,16 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
                case DW_FORM_implicit_const:
                  if (lang_p
                      && (die->die_tag == DW_TAG_compile_unit
-                         || die->die_tag == DW_TAG_partial_unit)
+                         || die->die_tag == DW_TAG_partial_unit
+                         || die->die_tag == DW_TAG_type_unit)
                      && t->attr[i].attr == DW_AT_language)
                    cu->lang = t->values[i];
                  break;
                case DW_FORM_data1:
                  if (lang_p
                      && (die->die_tag == DW_TAG_compile_unit
-                         || die->die_tag == DW_TAG_partial_unit)
+                         || die->die_tag == DW_TAG_partial_unit
+                         || die->die_tag == DW_TAG_type_unit)
                      && t->attr[i].attr == DW_AT_language)
                    cu->lang = *ptr;
                  /* FALLTHRU */
@@ -6973,7 +6994,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
                case DW_FORM_data2:
                  if (lang_p
                      && (die->die_tag == DW_TAG_compile_unit
-                         || die->die_tag == DW_TAG_partial_unit)
+                         || die->die_tag == DW_TAG_partial_unit
+                         || die->die_tag == DW_TAG_type_unit)
                      && t->attr[i].attr == DW_AT_language)
                    cu->lang = do_read_16 (ptr);
                  /* FALLTHRU */
@@ -6983,7 +7005,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
                case DW_FORM_data4:
                  if (lang_p
                      && (die->die_tag == DW_TAG_compile_unit
-                         || die->die_tag == DW_TAG_partial_unit)
+                         || die->die_tag == DW_TAG_partial_unit
+                         || die->die_tag == DW_TAG_type_unit)
                      && t->attr[i].attr == DW_AT_language)
                    read_lang (ptr, form, &cu->lang);
                  /* FALLTHRU */
@@ -6994,7 +7017,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
                case DW_FORM_data8:
                  if (lang_p
                      && (die->die_tag == DW_TAG_compile_unit
-                         || die->die_tag == DW_TAG_partial_unit)
+                         || die->die_tag == DW_TAG_partial_unit
+                         || die->die_tag == DW_TAG_type_unit)
                      && t->attr[i].attr == DW_AT_language)
                    read_lang (ptr, form, &cu->lang);
                  /* FALLTHRU */
@@ -7009,7 +7033,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
                case DW_FORM_udata:
                  if (lang_p
                      && (die->die_tag == DW_TAG_compile_unit
-                         || die->die_tag == DW_TAG_partial_unit)
+                         || die->die_tag == DW_TAG_partial_unit
+                         || die->die_tag == DW_TAG_type_unit)
                      && t->attr[i].attr == DW_AT_language)
                    {
                      ptr = read_lang (ptr, form, &cu->lang); @@ -7559,6 +7584,7 @@ mark_singletons (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die,
          while (!reft->die_root
                 && reft->die_parent->die_tag != DW_TAG_compile_unit
                 && reft->die_parent->die_tag != DW_TAG_partial_unit
+                && reft->die_parent->die_tag != DW_TAG_type_unit
                 && !reft->die_parent->die_named_namespace)
            reft = reft->die_parent;
          if (reft->die_dup != NULL || reft->die_nextdup != NULL) @@ -11001,6 +11027,7 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die,
       {
       case DW_TAG_partial_unit:
       case DW_TAG_compile_unit:
+      case DW_TAG_type_unit:
        t->nattr = 0;
        die->die_size = 0;
        if (origin == NULL)
@@ -11014,7 +11041,7 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die,
            die->die_size += 4;
            t->nattr++;
          }
-       if (uni_lang_p || cu->cu_die->die_tag == DW_TAG_compile_unit)
+       if (uni_lang_p || cu->cu_die->die_tag == DW_TAG_compile_unit || 
+ cu->cu_die->die_tag == DW_TAG_type_unit)
          {
            unsigned int lang_size = nr_bytes_for (cu->lang);
            die->die_size += lang_size;
@@ -11421,7 +11448,7 @@ compute_abbrevs (DSO *dso)
       enum dwarf_form intracuform = DW_FORM_ref4;
       dw_die_ref child, *lastotr, child_next, *last;
       unsigned int headersz = (cu->cu_kind == CU_TYPES
-                              ? 23 : (cu->cu_version >= 5 ? 12 : 11));
+                              ? 23 : (cu->cu_version >= 5 ? 
+ (cu->isUTType ? 24 : 12) : 11));

       if (unlikely (fi_multifile) && cu->cu_die->die_remove)
        continue;
@@ -12639,6 +12666,7 @@ write_die (unsigned char *ptr, dw_cu_ref cu, dw_die_ref die,
       {
       case DW_TAG_partial_unit:
       case DW_TAG_compile_unit:
+      case DW_TAG_type_unit:
        ptr = write_unit_die (ptr, die, origin);
        break;
       case DW_TAG_namespace:
@@ -12737,7 +12765,7 @@ static void
 recompute_abbrevs (dw_cu_ref cu, unsigned int cu_size)  {
   unsigned int headersz = (cu->cu_kind == CU_TYPES
-                          ? 23 : (cu->cu_version >= 5 ? 12 : 11));
+                          ? 23 : (cu->cu_version >= 5 ? (cu->isUTType ? 
+ 24 : 12) : 11));
   struct abbrev_tag *t;
   unsigned int ndies = 0, intracusize, off, i;
   dw_die_ref *intracuarr, *intracuvec;
@@ -12846,13 +12874,23 @@ write_info (unsigned int *die_count)
       write_16 (ptr, cu->cu_version);
       if (cu->cu_version >= 5)
        {
-         *ptr++ = (cu->cu_die->die_tag == DW_TAG_compile_unit
-                   ? DW_UT_compile : DW_UT_partial);
+         if (cu->cu_die->die_tag == DW_TAG_compile_unit)
+           *ptr++ = DW_UT_compile;
+         else if (cu->cu_die->die_tag == DW_TAG_type_unit)
+           *ptr++ = DW_UT_type;
+         else
+           *ptr++ = DW_UT_partial;
          write_8 (ptr, ptr_size);
        }
       write_32 (ptr, cu->u2.cu_new_abbrev_offset);
       if (cu->cu_version < 5)
        write_8 (ptr, ptr_size);
+      if (cu->cu_die->die_tag == DW_TAG_type_unit)
+       {
+         write_64 (ptr, cu->cu_type_signature);
+         write_32 (ptr, cu->cu_type_offset);
+       }
+
       ptr = write_die (ptr, cu, cu->cu_die, NULL, NULL, die_count);
       assert (info + (next_off - (wr_multifile ? multi_info_off : 0)) == ptr);
       if (unlikely (low_mem) && cu->cu_kind != CU_PU) @@ -14470,6 +14508,7 @@ propagate_multifile_refs_backward (dw_cu_ref cu, dw_die_ref top_die,
          while (!reft->die_root
                 && reft->die_parent->die_tag != DW_TAG_compile_unit
                 && reft->die_parent->die_tag != DW_TAG_partial_unit
+                && reft->die_parent->die_tag != DW_TAG_type_unit
                 && !reft->die_parent->die_named_namespace)
            reft = reft->die_parent;
          if (reft->die_root)
--
2.17.1


        Jakub

[-- Attachment #2: 0001-DWARFv5-Support-for-unit-type-DW_UT_type-and-DW_TAG_.patch --]
[-- Type: application/octet-stream, Size: 5125 bytes --]

From 9b60ae0d44425f87091919a653ba8d6b6bb59411 Mon Sep 17 00:00:00 2001
From: nitachra <Nitika.Achra@amd.com>
Date: Wed, 21 Jul 2021 15:32:44 +0530
Subject: [PATCH] DWARFv5: Support for unit type DW_UT_type and
 DW_TAG_type_unit.

In Dwarfv5, .debug_types section is eliminated and its contents are
moved into the .debug_info section.

This patch handles DW_UT_type units.

ChangeLog:
	* dwz.c (struct dw_cu): Add a type signature field.
	(try_debug_info): Add DW_UT_type in the if condition.
	(read_debug_info): Add DW_UT_type in the if condition.
	Set the boolean flag is_UT_type if the unit_type is
	DW_UT_type. Read the type signature from the header.
	Rewrite the DW_TAG_type_unit as partial unit.
	(build_abbrevs_for_die): Convert the DW_FORM_ref_sig8
	reference to DW_FORM_ref_addr.
	(write_die): Write the DW_FORM_ref_addr reference if
	the orignal form is DW_FORM_ref_sig8. Look for the
	compilation unit with the given type signature and
	write the reference to the first die after the unit
	die.
---
 dwz.c | 44 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 39 insertions(+), 5 deletions(-)

diff --git a/dwz.c b/dwz.c
index f758ddb..fc8bfc3 100644
--- a/dwz.c
+++ b/dwz.c
@@ -929,6 +929,8 @@ struct dw_cu
   unsigned int cu_offset;
   /* DWARF version of the CU.  */
   unsigned int cu_version;
+  /* A unique 8-byte signature of the type described in this type unit.  */
+  uint64_t cu_type_signature;
   /* Cached DW_AT_comp_dir value from DW_TAG_*_unit cu_die,
      or NULL if that attribute is not present.  */
   char *cu_comp_dir;
@@ -6471,7 +6473,7 @@ try_debug_info (DSO *dso)
       if (cu_version == 5)
 	{
 	  value = read_8 (ptr);
-	  if (value != DW_UT_compile && value != DW_UT_partial)
+	  if (value != DW_UT_compile && value != DW_UT_partial && value != DW_UT_type)
 	    error (0, 0, "%s: DWARF CU type %s unhandled", dso->filename,
 		   get_DW_UT_str (value));
 	}
@@ -6700,6 +6702,8 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
       bool present;
       unsigned int debug_line_off;
       unsigned int type_offset = 0;
+      uint64_t type_signature = 0;
+      bool is_UT_type = false;
 
       /* Note header is one bigger with DWARF version 5.  */
       if (ptr + (kind == DEBUG_TYPES ? 23 : 11) > endsec)
@@ -6742,12 +6746,13 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
       if (cu_version == 5)
 	{
 	  value = read_8 (ptr);
-	  if (value != DW_UT_compile && value != DW_UT_partial)
+	  if (value != DW_UT_compile && value != DW_UT_partial && value != DW_UT_type)
 	    {
 	      error (0, 0, "%s: DWARF CU type %s unhandled", dso->filename,
 		     get_DW_UT_str (value));
 	      goto fail;
 	    }
+	  is_UT_type = (value == DW_UT_type);
 	}
       else
 	{
@@ -6889,9 +6894,9 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 	}
       last_abbrev_offset = value;
 
-      if (unlikely (kind == DEBUG_TYPES))
+      if (unlikely (kind == DEBUG_TYPES) || is_UT_type)
 	{
-	  ptr += 8;
+	  type_signature = read_64 (ptr);
 	  type_offset = read_32 (ptr);
 	}
 
@@ -6904,6 +6909,7 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
       cu->cu_offset = cu_offset;
       cu->cu_version = cu_version;
       cu->cu_chunk = cu_chunk;
+      cu->cu_type_signature = type_signature;
       if (unlikely (op_multifile || low_mem))
 	cu->cu_abbrev = abbrev;
       diep = &cu->cu_die;
@@ -6996,7 +7002,10 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 	      memset (die, '\0', offsetof (struct dw_die, die_dup));
 	    }
 	  *diep = die;
-	  die->die_tag = t->tag;
+	  if (t->tag == DW_TAG_type_unit)
+	    die->die_tag = DW_TAG_partial_unit;
+	  else
+	    die->die_tag = t->tag;
 	  die->die_abbrev = t;
 	  die->die_offset = die_offset;
 	  if (parent)
@@ -10750,6 +10759,7 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die,
 	    case DW_FORM_ref4:
 	    case DW_FORM_ref8:
 	    case DW_FORM_ref_udata:
+	    case DW_FORM_ref_sig8:
 	    case DW_FORM_indirect:
 	      i = -2U;
 	      break;
@@ -11010,6 +11020,13 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die,
 		  ptr += 8;
 		  break;
 		case DW_FORM_ref_sig8:
+		  if (refcu->cu_version > 4)
+		    {
+		      t->attr[j].attr = reft->attr[i].attr;
+		      t->attr[j++].form = DW_FORM_ref_addr;
+		      die->die_size += 4;
+		      continue;
+		    }
 		  ptr += 8;
 		  break;
 		case DW_FORM_data16:
@@ -12692,6 +12709,23 @@ write_die (unsigned char *ptr, dw_cu_ref cu, dw_die_ref die,
 	      inptr += 8;
 	      break;
 	    case DW_FORM_ref_sig8:
+	      if (t->attr[j].form != reft->attr[i].form)
+		{
+		  value = read_64 (inptr);
+		  dw_cu_ref comp_unit;
+		  for (comp_unit = first_cu; comp_unit; comp_unit = comp_unit->cu_next)
+		    {
+		      if (value == comp_unit->cu_type_signature)
+			{
+			  value = comp_unit->cu_new_offset + comp_unit->cu_die->u.p2.die_new_offset
+				  + comp_unit->cu_die->die_size;
+			  break;
+			}
+		    }
+		  write_32(ptr, value);
+		  j++;
+		  continue;
+		}
 	      inptr += 8;
 	      break;
 	    case DW_FORM_data16:
-- 
2.17.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-07-28 14:32 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-11  9:37 [PATCH] DWARFv5: Support for unit type DW_UT_type and DW_TAG_type_unit Achra, Nitika
2021-06-11 10:54 ` Jakub Jelinek
2021-07-28 14:32   ` Achra, Nitika

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).