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