public inbox for dwz@sourceware.org
 help / color / mirror / Atom feed
From: Mark Wielaard <mark@klomp.org>
To: dwz@sourceware.org
Cc: Mark Wielaard <mark@klomp.org>
Subject: [PATCH 4/4] Handle DW_FORM_implicit_const [experiment].
Date: Thu, 24 Sep 2020 18:25:57 +0200	[thread overview]
Message-ID: <20200924162557.15870-5-mark@klomp.org> (raw)
In-Reply-To: <20200924162557.15870-1-mark@klomp.org>

This handles DW_FORM_implicit_const. This form keeps the actual data
value in the abbrev. This makes things tricky because we have to decide
where to keep (a reference to) the value and when to update the value
if necessary. In particular DW_FORM_implicit_const might be used with
a line table index for the DW_AT_decl_file or DW_AT_call_file which
might be updated in multifile mode.

This implementation keeps a value with each attribute (which is highly
inefficient, we could allocate values at the end of the struct abbrev_attr
only when there is an DW_FORM_implicit_const attribute). And updates the
value late in compute_abbrevs when writing the final multifile.

	* dwz.c (struct abbrev_attr): Add value field.
	(abbrev_eq2): Handle DW_FORM_implicit_const by also comparing
	the value.
	(compute_abbrev_hash): Likewise.
	(read_abbrev): Read DW_FORM_implicit_const.
	(skip_attr_no_dw_form_indirect): Skip DW_FORM_implicit_const.
	(get_AT): Return pointer to value for DW_FORM_implicit_const.
	(get_AT_int): Return value of DW_FORM_implicit_const.
	(checksum_die): Get value for DW_AT_decl_file or DW_AT_call_file
	from DW_FORM_implicit_const, skip for others (should the value
	then be in the u.p1.die_hash instead?).
	(checksum_ref_die): Likewise.
	(die_eq_1): Likewise.
	(mark_refs): Handle DW_FORM_implicit_const.
	(read_debug_info): Handle DW_FORM_implicit_const, set cu_lang
	for compile/partial units.
	(build_abbrevs_for_die): Handle DW_FORM_implicit_const value.
	Don't update value for DW_AT_decl_file or DW_AT_call_file here.
	(abbrev_cmp): Also compare DW_FORM_implicit_const values.
	(compute_abbrevs): Update DW_AT_decl_file and DW_AT_call_file
	DW_FORM_implicit_const values here.
	(write_abbrev): Also write DW_FORM_implicit_const value.
	(write_die): Handle DW_FORM_implicit_const, but don't change
	form/value for DW_AT_decl_file and DW_AT_call_file.
---
 dwz.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 118 insertions(+), 27 deletions(-)

diff --git a/dwz.c b/dwz.c
index 8f13298..f020d15 100644
--- a/dwz.c
+++ b/dwz.c
@@ -848,6 +848,8 @@ struct abbrev_attr
   unsigned int attr;
   /* DW_FORM_* form code.  */
   unsigned int form;
+  /* Only for DW_FORM_implicit_const.  */
+  int64_t value;
 };
 
 /* Internal structure for .debug_abbrev entries.  */
@@ -1211,7 +1213,9 @@ abbrev_eq2 (const void *p, const void *q)
     return 0;
   for (i = 0; i < t1->nattr; i++)
     if (t1->attr[i].attr != t2->attr[i].attr
-	|| t1->attr[i].form != t2->attr[i].form)
+	|| t1->attr[i].form != t2->attr[i].form
+	|| (t1->attr[i].form == DW_FORM_implicit_const
+	    && t1->attr[i].value != t2->attr[i].value))
       return 0;
   return 1;
 }
@@ -1229,6 +1233,8 @@ compute_abbrev_hash (struct abbrev_tag *t)
     {
       t->hash = iterative_hash_object (t->attr[i].attr, t->hash);
       t->hash = iterative_hash_object (t->attr[i].form, t->hash);
+      if (t->attr[i].form == DW_FORM_implicit_const)
+	t->hash = iterative_hash_object (t->attr[i].value, t->hash);
     }
 }
 
@@ -1259,7 +1265,9 @@ read_abbrev (DSO *dso, unsigned char *ptr)
 	{
 	  nattr++;
 	  form = read_uleb128 (p);
-	  if (form == 2
+	  if (form == DW_FORM_implicit_const)
+	    skip_leb128 (p);
+	  else if (form == 2
 	      || (form > DW_FORM_flag_present
 		  && (form != DW_FORM_ref_sig8
 		      || form != DW_FORM_data16
@@ -1291,6 +1299,8 @@ read_abbrev (DSO *dso, unsigned char *ptr)
       while ((attr = read_uleb128 (ptr)) != 0)
 	{
 	  form = read_uleb128 (ptr);
+	  if (form == DW_FORM_implicit_const)
+	    t->attr[t->nattr].value = read_sleb128 (ptr);
 	  t->attr[t->nattr].attr = attr;
 	  t->attr[t->nattr++].form = form;
 	}
@@ -1691,6 +1701,7 @@ skip_attr_no_dw_form_indirect (unsigned int cu_version, uint32_t form,
       ptr += ptr_size;
       break;
     case DW_FORM_flag_present:
+    case DW_FORM_implicit_const:
       break;
     case DW_FORM_ref1:
     case DW_FORM_flag:
@@ -1791,6 +1802,8 @@ get_AT (dw_die_ref die, enum dwarf_attribute at, enum dwarf_form *formp)
       if (t->attr[i].attr == at)
 	{
 	  *formp = form;
+	  if (form == DW_FORM_implicit_const)
+	    return (unsigned char *) &t->attr[i].value;
 	  return ptr;
 	}
 
@@ -1839,6 +1852,8 @@ get_AT_int (dw_die_ref die, enum dwarf_attribute at, bool *present,
     case DW_FORM_ref_udata:
     case DW_FORM_udata:
       return read_uleb128 (ptr);
+    case DW_FORM_implicit_const:
+      return *(uint64_t *)ptr; /* See get_AT.  */
     default:
       *present = false;
       return 0;
@@ -2837,6 +2852,8 @@ checksum_die (DSO *dso, dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die)
 	    case DW_FORM_data8: value = read_64 (ptr); handled = true; break;
 	    case DW_FORM_udata:
 	      value = read_uleb128 (ptr); handled = true; break;
+	    case DW_FORM_implicit_const:
+	      value = t->attr[i].value; handled = true; break;
 	    default:
 	      error (0, 0, "%s: Unhandled %s for %s",
 		     dso->filename, get_DW_FORM_str (form),
@@ -2971,6 +2988,7 @@ checksum_die (DSO *dso, dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die)
 	  ptr += ptr_size;
 	  break;
 	case DW_FORM_flag_present:
+	case DW_FORM_implicit_const:
 	  break;
 	case DW_FORM_flag:
 	case DW_FORM_data1:
@@ -3403,6 +3421,7 @@ checksum_ref_die (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die,
 	      ptr += ptr_size;
 	      break;
 	    case DW_FORM_flag_present:
+	    case DW_FORM_implicit_const:
 	      break;
 	    case DW_FORM_flag:
 	    case DW_FORM_data1:
@@ -4095,6 +4114,7 @@ die_eq_1 (dw_cu_ref cu1, dw_cu_ref cu2,
 	    case DW_FORM_data4: value1 = read_32 (ptr1); break;
 	    case DW_FORM_data8: value1 = read_64 (ptr1); break;
 	    case DW_FORM_udata: value1 = read_uleb128 (ptr1); break;
+	    case DW_FORM_implicit_const: value1 = t1->attr[i].value; break;
 	    default: abort ();
 	    }
 	  switch (form2)
@@ -4104,6 +4124,7 @@ die_eq_1 (dw_cu_ref cu1, dw_cu_ref cu2,
 	    case DW_FORM_data4: value2 = read_32 (ptr2); break;
 	    case DW_FORM_data8: value2 = read_64 (ptr2); break;
 	    case DW_FORM_udata: value2 = read_uleb128 (ptr2); break;
+	    case DW_FORM_implicit_const: value2 = t2->attr[j].value; break;
 	    default: abort ();
 	    }
 	  if (ignore_locus)
@@ -4224,6 +4245,7 @@ die_eq_1 (dw_cu_ref cu1, dw_cu_ref cu2,
 	  ptr2 += ptr_size;
 	  break;
 	case DW_FORM_flag_present:
+	case DW_FORM_implicit_const:
 	  break;
 	case DW_FORM_flag:
 	case DW_FORM_data1:
@@ -5316,6 +5338,7 @@ mark_refs (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die, int mode)
 	      ptr += ptr_size;
 	      break;
 	    case DW_FORM_flag_present:
+	    case DW_FORM_implicit_const:
 	      break;
 	    case DW_FORM_flag:
 	    case DW_FORM_data1:
@@ -6269,6 +6292,13 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count)
 		  break;
 		case DW_FORM_flag_present:
 		  break;
+		case DW_FORM_implicit_const:
+		  if (lang_p
+		      && (die->die_tag == DW_TAG_compile_unit
+			  || die->die_tag == DW_TAG_partial_unit)
+		      && t->attr[i].attr == DW_AT_language)
+		    cu->lang = t->attr[i].value;
+		  break;
 		case DW_FORM_data1:
 		  if (lang_p
 		      && (die->die_tag == DW_TAG_compile_unit
@@ -9785,6 +9815,8 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die,
 	    {
 	      t->attr[i].attr = reft->attr[i].attr;
 	      t->attr[i].form = reft->attr[i].form;
+	      if (t->attr[i].form == DW_FORM_implicit_const)
+		t->attr[i].value = reft->attr[i].value;
 	    }
 	  t->nattr = reft->nattr;
 	}
@@ -9814,28 +9846,36 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die,
 		    case DW_FORM_data4: value = read_32 (ptr); break;
 		    case DW_FORM_data8: value = read_64 (ptr); break;
 		    case DW_FORM_udata: value = read_uleb128 (ptr); break;
+		    case DW_FORM_implicit_const: break;
 		    default:
 		      error (0, 0, "Unhandled %s for %s",
 			     get_DW_FORM_str (form),
 			     get_DW_AT_str (reft->attr[i].attr));
 		      return 1;
 		    }
-		  value = line_htab_lookup (refcu, value);
-		  if (value <= 0xff)
-		    {
-		      form = DW_FORM_data1;
-		      die->die_size++;
-		    }
-		  else if (value <= 0xffff)
+		  /* Note that we transform DW_FORM_implicit_const in
+		     compute_abbrev ().  */
+		  if (form != DW_FORM_implicit_const)
 		    {
-		      form = DW_FORM_data2;
-		      die->die_size += 2;
+		      value = line_htab_lookup (refcu, value);
+		      if (value <= 0xff)
+			{
+			  form = DW_FORM_data1;
+			  die->die_size++;
+			}
+		      else if (value <= 0xffff)
+			{
+			  form = DW_FORM_data2;
+			  die->die_size += 2;
+			}
+		      else
+			{
+			  form = DW_FORM_data4;
+			  die->die_size += 4;
+			}
 		    }
 		  else
-		    {
-		      form = DW_FORM_data4;
-		      die->die_size += 4;
-		    }
+		    t->attr[j].value = reft->attr[i].value;
 		  t->attr[j].attr = reft->attr[i].attr;
 		  t->attr[j++].form = form;
 		  continue;
@@ -9941,6 +9981,7 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die,
 		    }
 		  break;
 		case DW_FORM_flag_present:
+		case DW_FORM_implicit_const:
 		  break;
 		case DW_FORM_flag:
 		case DW_FORM_data1:
@@ -10123,7 +10164,10 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die,
 	      if (form == DW_FORM_block1)
 		ptr += len;
 	      t->attr[j].attr = reft->attr[i].attr;
-	      t->attr[j++].form = reft->attr[i].form;
+	      t->attr[j].form = reft->attr[i].form;
+	      if (reft->attr[i].form == DW_FORM_implicit_const)
+		t->attr[j].value = reft->attr[i].value;
+	      j++;
 	      die->die_size += ptr - orig_ptr;
 	    }
 	  t->nattr = j;
@@ -10348,6 +10392,13 @@ abbrev_cmp (const void *p, const void *q)
 	return -1;
       if (t1->attr[i].form > t2->attr[i].form)
 	return 1;
+      if (t1->attr[i].form == DW_FORM_implicit_const)
+	{
+	  if (t1->attr[i].value < t2->attr[i].value)
+	    return -1;
+	  if (t1->attr[i].value > t2->attr[i].value)
+	    return 1;
+	}
     }
   return 0;
 }
@@ -10947,6 +10998,21 @@ compute_abbrevs (DSO *dso)
 	    {
 	      abbrev_size += size_of_uleb128 (arr[i]->attr[j].attr);
 	      abbrev_size += size_of_uleb128 (arr[i]->attr[j].form);
+	      if (arr[i]->attr[j].form == DW_FORM_implicit_const)
+		{
+		  /* If this is a shared abbrev for a file reference
+		     attribute, update to the new file number (in the
+		     mulifile .debug_line).  Note that this might
+		     change the abbrev size...  */
+		  if (unlikely (wr_multifile)
+		      && (arr[i]->attr[j].attr == DW_AT_decl_file
+			  || arr[i]->attr[j].attr == DW_AT_call_file))
+		    {
+		      uint64_t value = arr[i]->attr[j].value;
+		      arr[i]->attr[j].value = line_htab_lookup (cu, value);
+		    }
+		  abbrev_size += size_of_uleb128 (arr[i]->attr[j].value);
+		}
 	    }
 	  abbrev_size += 2;
 	}
@@ -11037,6 +11103,8 @@ write_abbrev (void)
 	    {
 	      write_uleb128 (ptr, arr[i]->attr[j].attr);
 	      write_uleb128 (ptr, arr[i]->attr[j].form);
+	      if (arr[i]->attr[j].form == DW_FORM_implicit_const)
+		write_uleb128 (ptr, arr[i]->attr[j].value);
 	    }
 	  *ptr++ = 0;
 	  *ptr++ = 0;
@@ -11398,22 +11466,44 @@ write_die (unsigned char *ptr, dw_cu_ref cu, dw_die_ref die,
 	      && (reft->attr[i].attr == DW_AT_decl_file
 		  || reft->attr[i].attr == DW_AT_call_file))
 	    {
+	      bool update = false;
 	      switch (form)
 		{
-		case DW_FORM_data1: value = read_8 (inptr); break;
-		case DW_FORM_data2: value = read_16 (inptr); break;
-		case DW_FORM_data4: value = read_32 (inptr); break;
-		case DW_FORM_data8: value = read_64 (inptr); break;
-		case DW_FORM_udata: value = read_uleb128 (inptr); break;
+		case DW_FORM_data1:
+		  value = read_8 (inptr);
+		  update = true;
+		  break;
+		case DW_FORM_data2:
+		  value = read_16 (inptr);
+		  update = true;
+		  break;
+		case DW_FORM_data4:
+		  value = read_32 (inptr);
+		  update = true;
+		  break;
+		case DW_FORM_data8:
+		  value = read_64 (inptr);
+		  update = true;
+		  break;
+		case DW_FORM_udata:
+		  value = read_uleb128 (inptr);
+		  update = true;
+		  break;
+		case DW_FORM_implicit_const:
+		  /* This gets updated in compute_abbrevs.  */
+		  break;
 		default: abort ();
 		}
-	      value = line_htab_lookup (refcu, value);
-	      switch (t->attr[j].form)
+	      if (update)
 		{
-		case DW_FORM_data1: write_8 (ptr, value); break;
-		case DW_FORM_data2: write_16 (ptr, value); break;
-		case DW_FORM_data4: write_32 (ptr, value); break;
-		default: abort ();
+		  value = line_htab_lookup (refcu, value);
+		  switch (t->attr[j].form)
+		    {
+		    case DW_FORM_data1: write_8 (ptr, value); break;
+		    case DW_FORM_data2: write_16 (ptr, value); break;
+		    case DW_FORM_data4: write_32 (ptr, value); break;
+		    default: abort ();
+		    }
 		}
 	      j++;
 	      continue;
@@ -11505,6 +11595,7 @@ write_die (unsigned char *ptr, dw_cu_ref cu, dw_die_ref die,
 		}
 	      break;
 	    case DW_FORM_flag_present:
+	    case DW_FORM_implicit_const:
 	      break;
 	    case DW_FORM_flag:
 	    case DW_FORM_data1:
-- 
2.18.4


  parent reply	other threads:[~2020-09-24 16:26 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-24 16:25 Read and write DWARF5 units and forms Mark Wielaard
2020-09-24 16:25 ` [PATCH 1/4] Calculate size and write correct DWARF5 header Mark Wielaard
2020-09-24 19:39   ` Jakub Jelinek
2020-09-25 16:35     ` Mark Wielaard
2020-09-25 16:39       ` Jakub Jelinek
2020-09-24 16:25 ` [PATCH 2/4] Handle DW_FORM_data16 Mark Wielaard
2020-09-24 19:43   ` Jakub Jelinek
2020-09-24 21:53     ` Jakub Jelinek
2020-09-25 16:42     ` Mark Wielaard
2020-09-24 16:25 ` [PATCH 3/4] Handle DW_FORM_line_strp by not moving DIE Mark Wielaard
2020-09-24 19:45   ` Jakub Jelinek
2020-09-24 16:25 ` Mark Wielaard [this message]
2020-09-24 19:57   ` [PATCH 4/4] Handle DW_FORM_implicit_const [experiment] Jakub Jelinek

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=20200924162557.15870-5-mark@klomp.org \
    --to=mark@klomp.org \
    --cc=dwz@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).