dcavalca / rpms / rpm

Forked from rpms/rpm a year ago
Clone
James Antill ee2eaf
From 201a71ce18734b1cebc337225f345fd754a6414f Mon Sep 17 00:00:00 2001
James Antill ee2eaf
Message-Id: <201a71ce18734b1cebc337225f345fd754a6414f.1573552234.git.pmatilai@redhat.com>
James Antill ee2eaf
In-Reply-To: <ce6e8556a8f93327d6de0446f21ac5e549861d82.1573552234.git.pmatilai@redhat.com>
James Antill ee2eaf
References: <ce6e8556a8f93327d6de0446f21ac5e549861d82.1573552234.git.pmatilai@redhat.com>
James Antill ee2eaf
From: Mark Wielaard <mark@klomp.org>
James Antill ee2eaf
Date: Mon, 17 Jun 2019 11:23:25 +0200
James Antill ee2eaf
Subject: [PATCH 2/3] Handle .debug_macro in debugedit.
James Antill ee2eaf
James Antill ee2eaf
When compiling with -g3 gcc will generate a .debug_macro section
James Antill ee2eaf
which has pointers to the .debug_str section. Since we might rewrite
James Antill ee2eaf
the .debug_str section, we also need to update any .debug_macro
James Antill ee2eaf
pointers.
James Antill ee2eaf
James Antill ee2eaf
Updated the debugedit.at testcase by building everything with -g
James Antill ee2eaf
and add various checks to see the .debug_macro section looks OK
James Antill ee2eaf
after running debugedit. Added a new rpmbuild.at testcase to check
James Antill ee2eaf
handing of .debug_macro in the whole rpmbuild debuginfo pipeline
James Antill ee2eaf
to double check the separate .debug file also contains the macros.
James Antill ee2eaf
James Antill ee2eaf
Original patch by Michael Schroeder <mls@suse.de>. Extended by
James Antill ee2eaf
Mark Wielaard <mark@klomp.org> to deal with relocations and possible
James Antill ee2eaf
multiple COMDAT .debug_macro sections.
James Antill ee2eaf
---
James Antill ee2eaf
 tests/Makefile.am              |   1 +
James Antill ee2eaf
 tests/data/SPECS/hello-g3.spec |  60 ++++++++++
James Antill ee2eaf
 tests/debugedit.at             |  79 ++++++++++++-
James Antill ee2eaf
 tests/rpmbuild.at              |  33 ++++++
James Antill ee2eaf
 tools/debugedit.c              | 196 +++++++++++++++++++++++++++++++--
James Antill ee2eaf
 5 files changed, 356 insertions(+), 13 deletions(-)
James Antill ee2eaf
 create mode 100644 tests/data/SPECS/hello-g3.spec
James Antill ee2eaf
James Antill ee2eaf
[ test-suite part edited out, too painful to backport ]
James Antill ee2eaf
James Antill ee2eaf
diff --git a/tools/debugedit.c b/tools/debugedit.c
James Antill ee2eaf
index cf9cc3ca9..84483ef5e 100644
James Antill ee2eaf
--- a/tools/debugedit.c
James Antill ee2eaf
+++ b/tools/debugedit.c
James Antill ee2eaf
@@ -41,6 +41,7 @@
James Antill ee2eaf
 #include <gelf.h>
James Antill ee2eaf
 #include <dwarf.h>
James Antill ee2eaf
 
James Antill ee2eaf
+
James Antill ee2eaf
 /* Unfortunately strtab manipulation functions were only officially added
James Antill ee2eaf
    to elfutils libdw in 0.167.  Before that there were internal unsupported
James Antill ee2eaf
    ebl variants.  While libebl.h isn't supported we'll try to use it anyway
James Antill ee2eaf
@@ -432,6 +433,7 @@ typedef struct debug_section
James Antill ee2eaf
     int sec, relsec;
James Antill ee2eaf
     REL *relbuf;
James Antill ee2eaf
     REL *relend;
James Antill ee2eaf
+    struct debug_section *next; /* Only happens for COMDAT .debug_macro.  */
James Antill ee2eaf
   } debug_section;
James Antill ee2eaf
 
James Antill ee2eaf
 static debug_section debug_sections[] =
James Antill ee2eaf
@@ -1989,11 +1991,35 @@ edit_dwarf2 (DSO *dso)
James Antill ee2eaf
 	    for (j = 0; debug_sections[j].name; ++j)
James Antill ee2eaf
 	      if (strcmp (name, debug_sections[j].name) == 0)
James Antill ee2eaf
 	 	{
James Antill ee2eaf
+		  struct debug_section *debug_sec = &debug_sections[j];
James Antill ee2eaf
 		  if (debug_sections[j].data)
James Antill ee2eaf
 		    {
James Antill ee2eaf
-		      error (0, 0, "%s: Found two copies of %s section",
James Antill ee2eaf
-			     dso->filename, name);
James Antill ee2eaf
-		      return 1;
James Antill ee2eaf
+		      if (j != DEBUG_MACRO)
James Antill ee2eaf
+			{
James Antill ee2eaf
+			  error (0, 0, "%s: Found two copies of %s section",
James Antill ee2eaf
+				 dso->filename, name);
James Antill ee2eaf
+			  return 1;
James Antill ee2eaf
+			}
James Antill ee2eaf
+		      else
James Antill ee2eaf
+			{
James Antill ee2eaf
+			  /* In relocatable files .debug_macro might
James Antill ee2eaf
+			     appear multiple times as COMDAT
James Antill ee2eaf
+			     section.  */
James Antill ee2eaf
+			  struct debug_section *sec;
James Antill ee2eaf
+			  sec = calloc (sizeof (struct debug_section), 1);
James Antill ee2eaf
+			  if (sec == NULL)
James Antill ee2eaf
+			    error (1, errno,
James Antill ee2eaf
+				   "%s: Could not allocate more macro sections",
James Antill ee2eaf
+				   dso->filename);
James Antill ee2eaf
+			  sec->name = ".debug_macro";
James Antill ee2eaf
+
James Antill ee2eaf
+			  struct debug_section *macro_sec = debug_sec;
James Antill ee2eaf
+			  while (macro_sec->next != NULL)
James Antill ee2eaf
+			    macro_sec = macro_sec->next;
James Antill ee2eaf
+
James Antill ee2eaf
+			  macro_sec->next = sec;
James Antill ee2eaf
+			  debug_sec = sec;
James Antill ee2eaf
+			}
James Antill ee2eaf
 		    }
James Antill ee2eaf
 
James Antill ee2eaf
 		  scn = dso->scn[i];
James Antill ee2eaf
@@ -2002,10 +2028,10 @@ edit_dwarf2 (DSO *dso)
James Antill ee2eaf
 		  assert (elf_getdata (scn, data) == NULL);
James Antill ee2eaf
 		  assert (data->d_off == 0);
James Antill ee2eaf
 		  assert (data->d_size == dso->shdr[i].sh_size);
James Antill ee2eaf
-		  debug_sections[j].data = data->d_buf;
James Antill ee2eaf
-		  debug_sections[j].elf_data = data;
James Antill ee2eaf
-		  debug_sections[j].size = data->d_size;
James Antill ee2eaf
-		  debug_sections[j].sec = i;
James Antill ee2eaf
+		  debug_sec->data = data->d_buf;
James Antill ee2eaf
+		  debug_sec->elf_data = data;
James Antill ee2eaf
+		  debug_sec->size = data->d_size;
James Antill ee2eaf
+		  debug_sec->sec = i;
James Antill ee2eaf
 		  break;
James Antill ee2eaf
 		}
James Antill ee2eaf
 
James Antill ee2eaf
@@ -2028,7 +2054,26 @@ edit_dwarf2 (DSO *dso)
James Antill ee2eaf
 			  + (dso->shdr[i].sh_type == SHT_RELA),
James Antill ee2eaf
 			  debug_sections[j].name) == 0)
James Antill ee2eaf
 	 	{
James Antill ee2eaf
-		  debug_sections[j].relsec = i;
James Antill ee2eaf
+		  if (j == DEBUG_MACRO)
James Antill ee2eaf
+		    {
James Antill ee2eaf
+		      /* Pick the correct one.  */
James Antill ee2eaf
+		      int rel_target = dso->shdr[i].sh_info;
James Antill ee2eaf
+		      struct debug_section *macro_sec = &debug_sections[j];
James Antill ee2eaf
+		      while (macro_sec != NULL)
James Antill ee2eaf
+			{
James Antill ee2eaf
+			  if (macro_sec->sec == rel_target)
James Antill ee2eaf
+			    {
James Antill ee2eaf
+			      macro_sec->relsec = i;
James Antill ee2eaf
+			      break;
James Antill ee2eaf
+			    }
James Antill ee2eaf
+			  macro_sec = macro_sec->next;
James Antill ee2eaf
+			}
James Antill ee2eaf
+		      if (macro_sec == NULL)
James Antill ee2eaf
+			error (0, 1, "No .debug_macro reloc section: %s",
James Antill ee2eaf
+			       dso->filename);
James Antill ee2eaf
+		    }
James Antill ee2eaf
+		  else
James Antill ee2eaf
+		    debug_sections[j].relsec = i;
James Antill ee2eaf
 		  break;
James Antill ee2eaf
 		}
James Antill ee2eaf
 	  }
James Antill ee2eaf
@@ -2062,6 +2107,7 @@ edit_dwarf2 (DSO *dso)
James Antill ee2eaf
       struct abbrev_tag tag, *t;
James Antill ee2eaf
       int phase;
James Antill ee2eaf
       bool info_rel_updated = false;
James Antill ee2eaf
+      bool macro_rel_updated = false;
James Antill ee2eaf
 
James Antill ee2eaf
       for (phase = 0; phase < 2; phase++)
James Antill ee2eaf
 	{
James Antill ee2eaf
@@ -2279,6 +2325,113 @@ edit_dwarf2 (DSO *dso)
James Antill ee2eaf
 		}
James Antill ee2eaf
 	    }
James Antill ee2eaf
 
James Antill ee2eaf
+	  /* The .debug_macro section also contains offsets into the
James Antill ee2eaf
+	     .debug_str section and references to the .debug_line
James Antill ee2eaf
+	     tables, so we need to update those as well if we update
James Antill ee2eaf
+	     the strings or the stmts.  */
James Antill ee2eaf
+	  if ((need_strp_update || need_stmt_update)
James Antill ee2eaf
+	      && debug_sections[DEBUG_MACRO].data)
James Antill ee2eaf
+	    {
James Antill ee2eaf
+	      /* There might be multiple (COMDAT) .debug_macro sections.  */
James Antill ee2eaf
+	      struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
James Antill ee2eaf
+	      while (macro_sec != NULL)
James Antill ee2eaf
+		{
James Antill ee2eaf
+		  setup_relbuf(dso, macro_sec, &reltype);
James Antill ee2eaf
+		  rel_updated = false;
James Antill ee2eaf
+
James Antill ee2eaf
+		  ptr = macro_sec->data;
James Antill ee2eaf
+		  endsec = ptr + macro_sec->size;
James Antill ee2eaf
+		  int op = 0, macro_version, macro_flags;
James Antill ee2eaf
+		  int offset_len = 4, line_offset = 0;
James Antill ee2eaf
+
James Antill ee2eaf
+		  while (ptr < endsec)
James Antill ee2eaf
+		    {
James Antill ee2eaf
+		      if (!op)
James Antill ee2eaf
+			{
James Antill ee2eaf
+			  macro_version = read_16 (ptr);
James Antill ee2eaf
+			  macro_flags = read_8 (ptr);
James Antill ee2eaf
+			  if (macro_version < 4 || macro_version > 5)
James Antill ee2eaf
+			    error (1, 0, "unhandled .debug_macro version: %d",
James Antill ee2eaf
+				   macro_version);
James Antill ee2eaf
+			  if ((macro_flags & ~2) != 0)
James Antill ee2eaf
+			    error (1, 0, "unhandled .debug_macro flags: 0x%x",
James Antill ee2eaf
+				   macro_flags);
James Antill ee2eaf
+
James Antill ee2eaf
+			  offset_len = (macro_flags & 0x01) ? 8 : 4;
James Antill ee2eaf
+			  line_offset = (macro_flags & 0x02) ? 1 : 0;
James Antill ee2eaf
+
James Antill ee2eaf
+			  if (offset_len != 4)
James Antill ee2eaf
+			    error (0, 1,
James Antill ee2eaf
+				   "Cannot handle 8 byte macro offsets: %s",
James Antill ee2eaf
+				   dso->filename);
James Antill ee2eaf
+
James Antill ee2eaf
+			  /* Update the line_offset if it is there.  */
James Antill ee2eaf
+			  if (line_offset)
James Antill ee2eaf
+			    {
James Antill ee2eaf
+			      if (phase == 0)
James Antill ee2eaf
+				ptr += offset_len;
James Antill ee2eaf
+			      else
James Antill ee2eaf
+				{
James Antill ee2eaf
+				  size_t idx, new_idx;
James Antill ee2eaf
+				  idx = do_read_32_relocated (ptr);
James Antill ee2eaf
+				  new_idx = find_new_list_offs (&dso->lines,
James Antill ee2eaf
+								idx);
James Antill ee2eaf
+				  write_32_relocated (ptr, new_idx);
James Antill ee2eaf
+				}
James Antill ee2eaf
+			    }
James Antill ee2eaf
+			}
James Antill ee2eaf
+
James Antill ee2eaf
+		      op = read_8 (ptr);
James Antill ee2eaf
+		      if (!op)
James Antill ee2eaf
+			continue;
James Antill ee2eaf
+		      switch(op)
James Antill ee2eaf
+			{
James Antill ee2eaf
+			case DW_MACRO_GNU_define:
James Antill ee2eaf
+			case DW_MACRO_GNU_undef:
James Antill ee2eaf
+			  read_uleb128 (ptr);
James Antill ee2eaf
+			  ptr = ((unsigned char *) strchr ((char *) ptr, '\0')
James Antill ee2eaf
+				 + 1);
James Antill ee2eaf
+			  break;
James Antill ee2eaf
+			case DW_MACRO_GNU_start_file:
James Antill ee2eaf
+			  read_uleb128 (ptr);
James Antill ee2eaf
+			  read_uleb128 (ptr);
James Antill ee2eaf
+			  break;
James Antill ee2eaf
+			case DW_MACRO_GNU_end_file:
James Antill ee2eaf
+			  break;
James Antill ee2eaf
+			case DW_MACRO_GNU_define_indirect:
James Antill ee2eaf
+			case DW_MACRO_GNU_undef_indirect:
James Antill ee2eaf
+			  read_uleb128 (ptr);
James Antill ee2eaf
+			  if (phase == 0)
James Antill ee2eaf
+			    {
James Antill ee2eaf
+			      size_t idx = read_32_relocated (ptr);
James Antill ee2eaf
+			      record_existing_string_entry_idx (&dso->strings,
James Antill ee2eaf
+								idx);
James Antill ee2eaf
+			    }
James Antill ee2eaf
+			  else
James Antill ee2eaf
+			    {
James Antill ee2eaf
+			      struct stridxentry *entry;
James Antill ee2eaf
+			      size_t idx, new_idx;
James Antill ee2eaf
+			      idx = do_read_32_relocated (ptr);
James Antill ee2eaf
+			      entry = string_find_entry (&dso->strings, idx);
James Antill ee2eaf
+			      new_idx = strent_offset (entry->entry);
James Antill ee2eaf
+			      write_32_relocated (ptr, new_idx);
James Antill ee2eaf
+			    }
James Antill ee2eaf
+			  break;
James Antill ee2eaf
+			case DW_MACRO_GNU_transparent_include:
James Antill ee2eaf
+			  ptr += offset_len;
James Antill ee2eaf
+			  break;
James Antill ee2eaf
+			default:
James Antill ee2eaf
+			  error (1, 0, "Unhandled DW_MACRO op 0x%x", op);
James Antill ee2eaf
+			  break;
James Antill ee2eaf
+			}
James Antill ee2eaf
+		    }
James Antill ee2eaf
+
James Antill ee2eaf
+		  if (rel_updated)
James Antill ee2eaf
+		    macro_rel_updated = true;
James Antill ee2eaf
+		  macro_sec = macro_sec->next;
James Antill ee2eaf
+		}
James Antill ee2eaf
+	    }
James Antill ee2eaf
+
James Antill ee2eaf
 	  /* Same for the debug_str section. Make sure everything is
James Antill ee2eaf
 	     in place for phase 1 updating of debug_info
James Antill ee2eaf
 	     references. */
James Antill ee2eaf
@@ -2308,10 +2461,24 @@ edit_dwarf2 (DSO *dso)
James Antill ee2eaf
 	 new strp, strings and/or linep offsets.  */
James Antill ee2eaf
       if (need_strp_update || need_string_replacement || need_stmt_update)
James Antill ee2eaf
 	dirty_section (DEBUG_INFO);
James Antill ee2eaf
+      if (need_strp_update || need_stmt_update)
James Antill ee2eaf
+	dirty_section (DEBUG_MACRO);
James Antill ee2eaf
+      if (need_stmt_update)
James Antill ee2eaf
+	dirty_section (DEBUG_LINE);
James Antill ee2eaf
 
James Antill ee2eaf
-      /* Update any debug_info relocations addends we might have touched. */
James Antill ee2eaf
+      /* Update any relocations addends we might have touched. */
James Antill ee2eaf
       if (info_rel_updated)
James Antill ee2eaf
 	update_rela_data (dso, &debug_sections[DEBUG_INFO]);
James Antill ee2eaf
+
James Antill ee2eaf
+      if (macro_rel_updated)
James Antill ee2eaf
+	{
James Antill ee2eaf
+	  struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
James Antill ee2eaf
+	  while (macro_sec != NULL)
James Antill ee2eaf
+	    {
James Antill ee2eaf
+	      update_rela_data (dso, macro_sec);
James Antill ee2eaf
+	      macro_sec = macro_sec->next;
James Antill ee2eaf
+	    }
James Antill ee2eaf
+	}
James Antill ee2eaf
     }
James Antill ee2eaf
 
James Antill ee2eaf
   return 0;
James Antill ee2eaf
@@ -2843,6 +3010,17 @@ main (int argc, char *argv[])
James Antill ee2eaf
   destroy_lines (&dso->lines);
James Antill ee2eaf
   free (dso);
James Antill ee2eaf
 
James Antill ee2eaf
+  /* In case there were multiple (COMDAT) .debug_macro sections,
James Antill ee2eaf
+     free them.  */
James Antill ee2eaf
+  struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
James Antill ee2eaf
+  macro_sec = macro_sec->next;
James Antill ee2eaf
+  while (macro_sec != NULL)
James Antill ee2eaf
+    {
James Antill ee2eaf
+      struct debug_section *next = macro_sec->next;
James Antill ee2eaf
+      free (macro_sec);
James Antill ee2eaf
+      macro_sec = next;
James Antill ee2eaf
+    }
James Antill ee2eaf
+
James Antill ee2eaf
   poptFreeContext (optCon);
James Antill ee2eaf
 
James Antill ee2eaf
   return 0;
James Antill ee2eaf
-- 
James Antill ee2eaf
2.23.0
James Antill ee2eaf