Mark Wielaard 652537
From 8cd4d5046d7cb1bc16f01e77a5ff50eca8d9da3d Mon Sep 17 00:00:00 2001
Mark Wielaard 652537
From: Jan Kratochvil <jan.kratochvil@redhat.com>
Mark Wielaard 652537
Date: Sat, 1 Aug 2020 10:45:47 +0200
Mark Wielaard 652537
Subject: [PATCH 3/6] debugedit: Fix missing relocation of .debug_types
Mark Wielaard 652537
 section.
Mark Wielaard 652537
Mark Wielaard 652537
---
Mark Wielaard 652537
 tools/debugedit.c | 123 ++++++++++++++++++++++++++++++----------------
Mark Wielaard 652537
 1 file changed, 80 insertions(+), 43 deletions(-)
Mark Wielaard 652537
Mark Wielaard 652537
diff --git a/tools/debugedit.c b/tools/debugedit.c
Mark Wielaard 652537
index cad0cc349..87c1cd622 100644
Mark Wielaard 652537
--- a/tools/debugedit.c
Mark Wielaard 652537
+++ b/tools/debugedit.c
Mark Wielaard 652537
@@ -433,7 +433,8 @@ typedef struct debug_section
Mark Wielaard 652537
     int sec, relsec;
Mark Wielaard 652537
     REL *relbuf;
Mark Wielaard 652537
     REL *relend;
Mark Wielaard 652537
-    struct debug_section *next; /* Only happens for COMDAT .debug_macro.  */
Mark Wielaard 652537
+    /* Only happens for COMDAT .debug_macro and .debug_types.  */
Mark Wielaard 652537
+    struct debug_section *next;
Mark Wielaard 652537
   } debug_section;
Mark Wielaard 652537
 
Mark Wielaard 652537
 static debug_section debug_sections[] =
Mark Wielaard 652537
@@ -1269,7 +1270,9 @@ static int dirty_elf;
Mark Wielaard 652537
 static void
Mark Wielaard 652537
 dirty_section (unsigned int sec)
Mark Wielaard 652537
 {
Mark Wielaard 652537
-  elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTY);
Mark Wielaard 652537
+  for (struct debug_section *secp = &debug_sections[sec]; secp != NULL;
Mark Wielaard 652537
+       secp = secp->next)
Mark Wielaard 652537
+    elf_flagdata (secp->elf_data, ELF_C_SET, ELF_F_DIRTY);
Mark Wielaard 652537
   dirty_elf = 1;
Mark Wielaard 652537
 }
Mark Wielaard 652537
 
Mark Wielaard 652537
@@ -1469,12 +1472,7 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
Mark Wielaard 652537
 
Mark Wielaard 652537
   if (get_line_table (dso, off, &table) == false
Mark Wielaard 652537
       || table == NULL)
Mark Wielaard 652537
-    {
Mark Wielaard 652537
-      if (table != NULL)
Mark Wielaard 652537
-	error (0, 0, ".debug_line offset 0x%x referenced multiple times",
Mark Wielaard 652537
-	       off);
Mark Wielaard 652537
-      return false;
Mark Wielaard 652537
-    }
Mark Wielaard 652537
+    return false;
Mark Wielaard 652537
 
Mark Wielaard 652537
   /* Skip to the directory table. The rest of the header has already
Mark Wielaard 652537
      been read and checked by get_line_table. */
Mark Wielaard 652537
@@ -1965,22 +1963,25 @@ line_rel_cmp (const void *a, const void *b)
Mark Wielaard 652537
 }
Mark Wielaard 652537
 
Mark Wielaard 652537
 static int
Mark Wielaard 652537
-edit_info (DSO *dso, int phase)
Mark Wielaard 652537
+edit_info (DSO *dso, int phase, struct debug_section *sec)
Mark Wielaard 652537
 {
Mark Wielaard 652537
   unsigned char *ptr, *endcu, *endsec;
Mark Wielaard 652537
   uint32_t value;
Mark Wielaard 652537
   htab_t abbrev;
Mark Wielaard 652537
   struct abbrev_tag tag, *t;
Mark Wielaard 652537
 
Mark Wielaard 652537
-  ptr = debug_sections[DEBUG_INFO].data;
Mark Wielaard 652537
-  setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
Mark Wielaard 652537
-  endsec = ptr + debug_sections[DEBUG_INFO].size;
Mark Wielaard 652537
+  ptr = sec->data;
Mark Wielaard 652537
+  if (ptr == NULL)
Mark Wielaard 652537
+    return 0;
Mark Wielaard 652537
+
Mark Wielaard 652537
+  setup_relbuf(dso, sec, &reltype);
Mark Wielaard 652537
+  endsec = ptr + sec->size;
Mark Wielaard 652537
   while (ptr < endsec)
Mark Wielaard 652537
     {
Mark Wielaard 652537
-      if (ptr + 11 > endsec)
Mark Wielaard 652537
+      if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec)
Mark Wielaard 652537
 	{
Mark Wielaard 652537
-	  error (0, 0, "%s: .debug_info CU header too small",
Mark Wielaard 652537
-		 dso->filename);
Mark Wielaard 652537
+	  error (0, 0, "%s: %s CU header too small",
Mark Wielaard 652537
+		 dso->filename, sec->name);
Mark Wielaard 652537
 	  return 1;
Mark Wielaard 652537
 	}
Mark Wielaard 652537
 
Mark Wielaard 652537
@@ -1994,7 +1995,7 @@ edit_info (DSO *dso, int phase)
Mark Wielaard 652537
 
Mark Wielaard 652537
       if (endcu > endsec)
Mark Wielaard 652537
 	{
Mark Wielaard 652537
-	  error (0, 0, "%s: .debug_info too small", dso->filename);
Mark Wielaard 652537
+	  error (0, 0, "%s: %s too small", dso->filename, sec->name);
Mark Wielaard 652537
 	  return 1;
Mark Wielaard 652537
 	}
Mark Wielaard 652537
 
Mark Wielaard 652537
@@ -2034,6 +2035,9 @@ edit_info (DSO *dso, int phase)
Mark Wielaard 652537
 	  return 1;
Mark Wielaard 652537
 	}
Mark Wielaard 652537
 
Mark Wielaard 652537
+      if (sec != &debug_sections[DEBUG_INFO])
Mark Wielaard 652537
+	ptr += 12; /* Skip type_signature and type_offset.  */
Mark Wielaard 652537
+
Mark Wielaard 652537
       abbrev = read_abbrev (dso,
Mark Wielaard 652537
 			    debug_sections[DEBUG_ABBREV].data + value);
Mark Wielaard 652537
       if (abbrev == NULL)
Mark Wielaard 652537
@@ -2095,7 +2099,7 @@ edit_dwarf2 (DSO *dso)
Mark Wielaard 652537
 		  struct debug_section *debug_sec = &debug_sections[j];
Mark Wielaard 652537
 		  if (debug_sections[j].data)
Mark Wielaard 652537
 		    {
Mark Wielaard 652537
-		      if (j != DEBUG_MACRO)
Mark Wielaard 652537
+		      if (j != DEBUG_MACRO && j != DEBUG_TYPES)
Mark Wielaard 652537
 			{
Mark Wielaard 652537
 			  error (0, 0, "%s: Found two copies of %s section",
Mark Wielaard 652537
 				 dso->filename, name);
Mark Wielaard 652537
@@ -2103,22 +2107,21 @@ edit_dwarf2 (DSO *dso)
Mark Wielaard 652537
 			}
Mark Wielaard 652537
 		      else
Mark Wielaard 652537
 			{
Mark Wielaard 652537
-			  /* In relocatable files .debug_macro might
Mark Wielaard 652537
-			     appear multiple times as COMDAT
Mark Wielaard 652537
-			     section.  */
Mark Wielaard 652537
+			  /* In relocatable files .debug_macro and .debug_types
Mark Wielaard 652537
+			     might appear multiple times as COMDAT section.  */
Mark Wielaard 652537
 			  struct debug_section *sec;
Mark Wielaard 652537
 			  sec = calloc (sizeof (struct debug_section), 1);
Mark Wielaard 652537
 			  if (sec == NULL)
Mark Wielaard 652537
 			    error (1, errno,
Mark Wielaard 652537
-				   "%s: Could not allocate more macro sections",
Mark Wielaard 652537
-				   dso->filename);
Mark Wielaard 652537
-			  sec->name = ".debug_macro";
Mark Wielaard 652537
+				   "%s: Could not allocate more %s sections",
Mark Wielaard 652537
+				   dso->filename, name);
Mark Wielaard 652537
+			  sec->name = name;
Mark Wielaard 652537
 
Mark Wielaard 652537
-			  struct debug_section *macro_sec = debug_sec;
Mark Wielaard 652537
-			  while (macro_sec->next != NULL)
Mark Wielaard 652537
-			    macro_sec = macro_sec->next;
Mark Wielaard 652537
+			  struct debug_section *multi_sec = debug_sec;
Mark Wielaard 652537
+			  while (multi_sec->next != NULL)
Mark Wielaard 652537
+			    multi_sec = multi_sec->next;
Mark Wielaard 652537
 
Mark Wielaard 652537
-			  macro_sec->next = sec;
Mark Wielaard 652537
+			  multi_sec->next = sec;
Mark Wielaard 652537
 			  debug_sec = sec;
Mark Wielaard 652537
 			}
Mark Wielaard 652537
 		    }
Mark Wielaard 652537
@@ -2155,23 +2158,23 @@ edit_dwarf2 (DSO *dso)
Mark Wielaard 652537
 			  + (dso->shdr[i].sh_type == SHT_RELA),
Mark Wielaard 652537
 			  debug_sections[j].name) == 0)
Mark Wielaard 652537
 	 	{
Mark Wielaard 652537
-		  if (j == DEBUG_MACRO)
Mark Wielaard 652537
+		  if (j == DEBUG_MACRO || j == DEBUG_TYPES)
Mark Wielaard 652537
 		    {
Mark Wielaard 652537
 		      /* Pick the correct one.  */
Mark Wielaard 652537
 		      int rel_target = dso->shdr[i].sh_info;
Mark Wielaard 652537
-		      struct debug_section *macro_sec = &debug_sections[j];
Mark Wielaard 652537
-		      while (macro_sec != NULL)
Mark Wielaard 652537
+		      struct debug_section *multi_sec = &debug_sections[j];
Mark Wielaard 652537
+		      while (multi_sec != NULL)
Mark Wielaard 652537
 			{
Mark Wielaard 652537
-			  if (macro_sec->sec == rel_target)
Mark Wielaard 652537
+			  if (multi_sec->sec == rel_target)
Mark Wielaard 652537
 			    {
Mark Wielaard 652537
-			      macro_sec->relsec = i;
Mark Wielaard 652537
+			      multi_sec->relsec = i;
Mark Wielaard 652537
 			      break;
Mark Wielaard 652537
 			    }
Mark Wielaard 652537
-			  macro_sec = macro_sec->next;
Mark Wielaard 652537
+			  multi_sec = multi_sec->next;
Mark Wielaard 652537
 			}
Mark Wielaard 652537
-		      if (macro_sec == NULL)
Mark Wielaard 652537
-			error (0, 1, "No .debug_macro reloc section: %s",
Mark Wielaard 652537
-			       dso->filename);
Mark Wielaard 652537
+		      if (multi_sec == NULL)
Mark Wielaard 652537
+			error (0, 1, "No %s reloc section: %s",
Mark Wielaard 652537
+			       debug_sections[j].name, dso->filename);
Mark Wielaard 652537
 		    }
Mark Wielaard 652537
 		  else
Mark Wielaard 652537
 		    debug_sections[j].relsec = i;
Mark Wielaard 652537
@@ -2203,12 +2206,10 @@ edit_dwarf2 (DSO *dso)
Mark Wielaard 652537
   if (debug_sections[DEBUG_INFO].data == NULL)
Mark Wielaard 652537
     return 0;
Mark Wielaard 652537
 
Mark Wielaard 652537
-  unsigned char *ptr, *endcu, *endsec;
Mark Wielaard 652537
-  uint32_t value;
Mark Wielaard 652537
-  htab_t abbrev;
Mark Wielaard 652537
-  struct abbrev_tag tag, *t;
Mark Wielaard 652537
+  unsigned char *ptr, *endsec;
Mark Wielaard 652537
   int phase;
Mark Wielaard 652537
   bool info_rel_updated = false;
Mark Wielaard 652537
+  bool types_rel_updated = false;
Mark Wielaard 652537
   bool macro_rel_updated = false;
Mark Wielaard 652537
 
Mark Wielaard 652537
   for (phase = 0; phase < 2; phase++)
Mark Wielaard 652537
@@ -2221,13 +2222,26 @@ edit_dwarf2 (DSO *dso)
Mark Wielaard 652537
 	break;
Mark Wielaard 652537
 
Mark Wielaard 652537
       rel_updated = false;
Mark Wielaard 652537
-      if (edit_info (dso, phase))
Mark Wielaard 652537
-       return 1;
Mark Wielaard 652537
+      if (edit_info (dso, phase, &debug_sections[DEBUG_INFO]))
Mark Wielaard 652537
+	return 1;
Mark Wielaard 652537
 
Mark Wielaard 652537
       /* Remember whether any .debug_info relocations might need
Mark Wielaard 652537
 	 to be updated. */
Mark Wielaard 652537
       info_rel_updated = rel_updated;
Mark Wielaard 652537
 
Mark Wielaard 652537
+      rel_updated = false;
Mark Wielaard 652537
+      struct debug_section *types_sec = &debug_sections[DEBUG_TYPES];
Mark Wielaard 652537
+      while (types_sec != NULL)
Mark Wielaard 652537
+	{
Mark Wielaard 652537
+	  if (edit_info (dso, phase, types_sec))
Mark Wielaard 652537
+	    return 1;
Mark Wielaard 652537
+	  types_sec = types_sec->next;
Mark Wielaard 652537
+	}
Mark Wielaard 652537
+
Mark Wielaard 652537
+      /* Remember whether any .debug_types relocations might need
Mark Wielaard 652537
+	 to be updated. */
Mark Wielaard 652537
+      types_rel_updated = rel_updated;
Mark Wielaard 652537
+
Mark Wielaard 652537
       /* We might have to recalculate/rewrite the debug_line
Mark Wielaard 652537
 	 section.  We need to do that before going into phase one
Mark Wielaard 652537
 	 so we have all new offsets.  We do this separately from
Mark Wielaard 652537
@@ -2475,8 +2489,11 @@ edit_dwarf2 (DSO *dso)
Mark Wielaard 652537
 
Mark Wielaard 652537
   /* After phase 1 we might have rewritten the debug_info with
Mark Wielaard 652537
      new strp, strings and/or linep offsets.  */
Mark Wielaard 652537
-  if (need_strp_update || need_string_replacement || need_stmt_update)
Mark Wielaard 652537
+  if (need_strp_update || need_string_replacement || need_stmt_update) {
Mark Wielaard 652537
     dirty_section (DEBUG_INFO);
Mark Wielaard 652537
+    if (debug_sections[DEBUG_TYPES].data != NULL)
Mark Wielaard 652537
+      dirty_section (DEBUG_TYPES);
Mark Wielaard 652537
+  }
Mark Wielaard 652537
   if (need_strp_update || need_stmt_update)
Mark Wielaard 652537
     dirty_section (DEBUG_MACRO);
Mark Wielaard 652537
   if (need_stmt_update)
Mark Wielaard 652537
@@ -2485,6 +2502,15 @@ edit_dwarf2 (DSO *dso)
Mark Wielaard 652537
   /* Update any relocations addends we might have touched. */
Mark Wielaard 652537
   if (info_rel_updated)
Mark Wielaard 652537
     update_rela_data (dso, &debug_sections[DEBUG_INFO]);
Mark Wielaard 652537
+  if (types_rel_updated)
Mark Wielaard 652537
+    {
Mark Wielaard 652537
+      struct debug_section *types_sec = &debug_sections[DEBUG_TYPES];
Mark Wielaard 652537
+      while (types_sec != NULL)
Mark Wielaard 652537
+	{
Mark Wielaard 652537
+	  update_rela_data (dso, types_sec);
Mark Wielaard 652537
+	  types_sec = types_sec->next;
Mark Wielaard 652537
+	}
Mark Wielaard 652537
+    }
Mark Wielaard 652537
 
Mark Wielaard 652537
   if (macro_rel_updated)
Mark Wielaard 652537
     {
Mark Wielaard 652537
@@ -3037,6 +3063,17 @@ main (int argc, char *argv[])
Mark Wielaard 652537
       macro_sec = next;
Mark Wielaard 652537
     }
Mark Wielaard 652537
 
Mark Wielaard 652537
+  /* In case there were multiple (COMDAT) .debug_types sections,
Mark Wielaard 652537
+     free them.  */
Mark Wielaard 652537
+  struct debug_section *types_sec = &debug_sections[DEBUG_TYPES];
Mark Wielaard 652537
+  types_sec = types_sec->next;
Mark Wielaard 652537
+  while (types_sec != NULL)
Mark Wielaard 652537
+    {
Mark Wielaard 652537
+      struct debug_section *next = types_sec->next;
Mark Wielaard 652537
+      free (types_sec);
Mark Wielaard 652537
+      types_sec = next;
Mark Wielaard 652537
+    }
Mark Wielaard 652537
+
Mark Wielaard 652537
   poptFreeContext (optCon);
Mark Wielaard 652537
 
Mark Wielaard 652537
   return 0;
Mark Wielaard 652537
-- 
Mark Wielaard 652537
2.18.4
Mark Wielaard 652537