richardphibel / rpms / rpm

Forked from rpms/rpm 2 years ago
Clone
Blob Blame History Raw
From de119ea9797f3ccfa3842e3926b6ea8198607207 Mon Sep 17 00:00:00 2001
From: Jan Kratochvil <jan.kratochvil@redhat.com>
Date: Sat, 1 Aug 2020 10:43:12 +0200
Subject: [PATCH 2/6] [NFC] debugedit: Move code from edit_dwarf2() to
 edit_info().

---
 tools/debugedit.c | 672 +++++++++++++++++++++++-----------------------
 1 file changed, 343 insertions(+), 329 deletions(-)

diff --git a/tools/debugedit.c b/tools/debugedit.c
index a351adec8..cad0cc349 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -1964,6 +1964,106 @@ line_rel_cmp (const void *a, const void *b)
   return 0;
 }
 
+static int
+edit_info (DSO *dso, int phase)
+{
+  unsigned char *ptr, *endcu, *endsec;
+  uint32_t value;
+  htab_t abbrev;
+  struct abbrev_tag tag, *t;
+
+  ptr = debug_sections[DEBUG_INFO].data;
+  setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
+  endsec = ptr + debug_sections[DEBUG_INFO].size;
+  while (ptr < endsec)
+    {
+      if (ptr + 11 > endsec)
+	{
+	  error (0, 0, "%s: .debug_info CU header too small",
+		 dso->filename);
+	  return 1;
+	}
+
+      endcu = ptr + 4;
+      endcu += read_32 (ptr);
+      if (endcu == ptr + 0xffffffff)
+	{
+	  error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
+	  return 1;
+	}
+
+      if (endcu > endsec)
+	{
+	  error (0, 0, "%s: .debug_info too small", dso->filename);
+	  return 1;
+	}
+
+      cu_version = read_16 (ptr);
+      if (cu_version != 2 && cu_version != 3 && cu_version != 4)
+	{
+	  error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
+		 cu_version);
+	  return 1;
+	}
+
+      value = read_32_relocated (ptr);
+      if (value >= debug_sections[DEBUG_ABBREV].size)
+	{
+	  if (debug_sections[DEBUG_ABBREV].data == NULL)
+	    error (0, 0, "%s: .debug_abbrev not present", dso->filename);
+	  else
+	    error (0, 0, "%s: DWARF CU abbrev offset too large",
+		   dso->filename);
+	  return 1;
+	}
+
+      if (ptr_size == 0)
+	{
+	  ptr_size = read_8 (ptr);
+	  if (ptr_size != 4 && ptr_size != 8)
+	    {
+	      error (0, 0, "%s: Invalid DWARF pointer size %d",
+		     dso->filename, ptr_size);
+	      return 1;
+	    }
+	}
+      else if (read_8 (ptr) != ptr_size)
+	{
+	  error (0, 0, "%s: DWARF pointer size differs between CUs",
+		 dso->filename);
+	  return 1;
+	}
+
+      abbrev = read_abbrev (dso,
+			    debug_sections[DEBUG_ABBREV].data + value);
+      if (abbrev == NULL)
+	return 1;
+
+      while (ptr < endcu)
+	{
+	  tag.entry = read_uleb128 (ptr);
+	  if (tag.entry == 0)
+	    continue;
+	  t = htab_find_with_hash (abbrev, &tag, tag.entry);
+	  if (t == NULL)
+	    {
+	      error (0, 0, "%s: Could not find DWARF abbreviation %d",
+		     dso->filename, tag.entry);
+	      htab_delete (abbrev);
+	      return 1;
+	    }
+
+	  ptr = edit_attributes (dso, ptr, t, phase);
+	  if (ptr == NULL)
+	    break;
+	}
+
+      htab_delete (abbrev);
+    }
+
+  return 0;
+}
+
 static int
 edit_dwarf2 (DSO *dso)
 {
@@ -2100,385 +2200,299 @@ edit_dwarf2 (DSO *dso)
       return 1;
     }
 
-  if (debug_sections[DEBUG_INFO].data != NULL)
+  if (debug_sections[DEBUG_INFO].data == NULL)
+    return 0;
+
+  unsigned char *ptr, *endcu, *endsec;
+  uint32_t value;
+  htab_t abbrev;
+  struct abbrev_tag tag, *t;
+  int phase;
+  bool info_rel_updated = false;
+  bool macro_rel_updated = false;
+
+  for (phase = 0; phase < 2; phase++)
     {
-      unsigned char *ptr, *endcu, *endsec;
-      uint32_t value;
-      htab_t abbrev;
-      struct abbrev_tag tag, *t;
-      int phase;
-      bool info_rel_updated = false;
-      bool macro_rel_updated = false;
+      /* If we don't need to update anyhing, skip phase 1. */
+      if (phase == 1
+	  && !need_strp_update
+	  && !need_string_replacement
+	  && !need_stmt_update)
+	break;
 
-      for (phase = 0; phase < 2; phase++)
+      rel_updated = false;
+      if (edit_info (dso, phase))
+       return 1;
+
+      /* Remember whether any .debug_info relocations might need
+	 to be updated. */
+      info_rel_updated = rel_updated;
+
+      /* We might have to recalculate/rewrite the debug_line
+	 section.  We need to do that before going into phase one
+	 so we have all new offsets.  We do this separately from
+	 scanning the dirs/file names because the DW_AT_stmt_lists
+	 might not be in order or skip some padding we might have
+	 to (re)move. */
+      if (phase == 0 && need_stmt_update)
 	{
-	  /* If we don't need to update anyhing, skip phase 1. */
-	  if (phase == 1
-	      && !need_strp_update
-	      && !need_string_replacement
-	      && !need_stmt_update)
-	    break;
+	  edit_dwarf2_line (dso);
 
-	  ptr = debug_sections[DEBUG_INFO].data;
-	  setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype);
-	  rel_updated = false;
-	  endsec = ptr + debug_sections[DEBUG_INFO].size;
-	  while (ptr < endsec)
+	  /* The line table programs will be moved
+	     forward/backwards a bit in the new data. Update the
+	     debug_line relocations to the new offsets. */
+	  int rndx = debug_sections[DEBUG_LINE].relsec;
+	  if (rndx != 0)
 	    {
-	      if (ptr + 11 > endsec)
-		{
-		  error (0, 0, "%s: .debug_info CU header too small",
-			 dso->filename);
-		  return 1;
-		}
-
-	      endcu = ptr + 4;
-	      endcu += read_32 (ptr);
-	      if (endcu == ptr + 0xffffffff)
-		{
-		  error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
-		  return 1;
-		}
-
-	      if (endcu > endsec)
-		{
-		  error (0, 0, "%s: .debug_info too small", dso->filename);
-		  return 1;
-		}
-
-	      cu_version = read_16 (ptr);
-	      if (cu_version != 2 && cu_version != 3 && cu_version != 4)
-		{
-		  error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
-			 cu_version);
-		  return 1;
-		}
-
-	      value = read_32_relocated (ptr);
-	      if (value >= debug_sections[DEBUG_ABBREV].size)
+	      LINE_REL *rbuf;
+	      size_t rels;
+	      Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL);
+	      int rtype = dso->shdr[rndx].sh_type;
+	      rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize;
+	      rbuf = malloc (rels * sizeof (LINE_REL));
+	      if (rbuf == NULL)
+		error (1, errno, "%s: Could not allocate line relocations",
+		       dso->filename);
+
+	      /* Sort them by offset into section. */
+	      for (size_t i = 0; i < rels; i++)
 		{
-		  if (debug_sections[DEBUG_ABBREV].data == NULL)
-		    error (0, 0, "%s: .debug_abbrev not present", dso->filename);
+		  if (rtype == SHT_RELA)
+		    {
+		      GElf_Rela rela;
+		      if (gelf_getrela (rdata, i, &rela) == NULL)
+			error (1, 0, "Couldn't get relocation: %s",
+			       elf_errmsg (-1));
+		      rbuf[i].r_offset = rela.r_offset;
+		      rbuf[i].ndx = i;
+		    }
 		  else
-		    error (0, 0, "%s: DWARF CU abbrev offset too large",
-			   dso->filename);
-		  return 1;
-		}
-
-	      if (ptr_size == 0)
-		{
-		  ptr_size = read_8 (ptr);
-		  if (ptr_size != 4 && ptr_size != 8)
 		    {
-		      error (0, 0, "%s: Invalid DWARF pointer size %d",
-			     dso->filename, ptr_size);
-		      return 1;
+		      GElf_Rel rel;
+		      if (gelf_getrel (rdata, i, &rel) == NULL)
+			error (1, 0, "Couldn't get relocation: %s",
+			       elf_errmsg (-1));
+		      rbuf[i].r_offset = rel.r_offset;
+		      rbuf[i].ndx = i;
 		    }
 		}
-	      else if (read_8 (ptr) != ptr_size)
-		{
-		  error (0, 0, "%s: DWARF pointer size differs between CUs",
-			 dso->filename);
-		  return 1;
-		}
+	      qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp);
 
-	      abbrev = read_abbrev (dso,
-				    debug_sections[DEBUG_ABBREV].data + value);
-	      if (abbrev == NULL)
-		return 1;
-
-	      while (ptr < endcu)
+	      size_t lndx = 0;
+	      for (size_t i = 0; i < rels; i++)
 		{
-		  tag.entry = read_uleb128 (ptr);
-		  if (tag.entry == 0)
-		    continue;
-		  t = htab_find_with_hash (abbrev, &tag, tag.entry);
-		  if (t == NULL)
+		  /* These relocations only happen in ET_REL files
+		     and are section offsets. */
+		  GElf_Addr r_offset;
+		  size_t ndx = rbuf[i].ndx;
+
+		  GElf_Rel rel;
+		  GElf_Rela rela;
+		  if (rtype == SHT_RELA)
 		    {
-		      error (0, 0, "%s: Could not find DWARF abbreviation %d",
-			     dso->filename, tag.entry);
-		      htab_delete (abbrev);
-		      return 1;
+		      if (gelf_getrela (rdata, ndx, &rela) == NULL)
+			error (1, 0, "Couldn't get relocation: %s",
+			       elf_errmsg (-1));
+		      r_offset = rela.r_offset;
+		    }
+		  else
+		    {
+		      if (gelf_getrel (rdata, ndx, &rel) == NULL)
+			error (1, 0, "Couldn't get relocation: %s",
+			       elf_errmsg (-1));
+		      r_offset = rel.r_offset;
 		    }
 
-		  ptr = edit_attributes (dso, ptr, t, phase);
-		  if (ptr == NULL)
-		    break;
-		}
+		  while (lndx < dso->lines.used
+			 && r_offset > (dso->lines.table[lndx].old_idx
+					+ 4
+					+ dso->lines.table[lndx].unit_length))
+		    lndx++;
 
-	      htab_delete (abbrev);
-	    }
+		  if (lndx >= dso->lines.used)
+		    error (1, 0,
+			   ".debug_line relocation offset out of range");
 
-	  /* Remember whether any .debug_info relocations might need
-	     to be updated. */
-	  info_rel_updated = rel_updated;
-
-	  /* We might have to recalculate/rewrite the debug_line
-	     section.  We need to do that before going into phase one
-	     so we have all new offsets.  We do this separately from
-	     scanning the dirs/file names because the DW_AT_stmt_lists
-	     might not be in order or skip some padding we might have
-	     to (re)move. */
-	  if (phase == 0 && need_stmt_update)
-	    {
-	      edit_dwarf2_line (dso);
+		  /* Offset (pointing into the line program) moves
+		     from old to new index including the header
+		     size diff. */
+		  r_offset += (ssize_t)((dso->lines.table[lndx].new_idx
+					 - dso->lines.table[lndx].old_idx)
+					+ dso->lines.table[lndx].size_diff);
 
-	      /* The line table programs will be moved
-		 forward/backwards a bit in the new data. Update the
-		 debug_line relocations to the new offsets. */
-	      int rndx = debug_sections[DEBUG_LINE].relsec;
-	      if (rndx != 0)
-		{
-		  LINE_REL *rbuf;
-		  size_t rels;
-		  Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL);
-		  int rtype = dso->shdr[rndx].sh_type;
-		  rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize;
-		  rbuf = malloc (rels * sizeof (LINE_REL));
-		  if (rbuf == NULL)
-		    error (1, errno, "%s: Could not allocate line relocations",
-			   dso->filename);
-
-		  /* Sort them by offset into section. */
-		  for (size_t i = 0; i < rels; i++)
+		  if (rtype == SHT_RELA)
 		    {
-		      if (rtype == SHT_RELA)
-			{
-			  GElf_Rela rela;
-			  if (gelf_getrela (rdata, i, &rela) == NULL)
-			    error (1, 0, "Couldn't get relocation: %s",
-				   elf_errmsg (-1));
-			  rbuf[i].r_offset = rela.r_offset;
-			  rbuf[i].ndx = i;
-			}
-		      else
-			{
-			  GElf_Rel rel;
-			  if (gelf_getrel (rdata, i, &rel) == NULL)
-			    error (1, 0, "Couldn't get relocation: %s",
-				   elf_errmsg (-1));
-			  rbuf[i].r_offset = rel.r_offset;
-			  rbuf[i].ndx = i;
-			}
+		      rela.r_offset = r_offset;
+		      if (gelf_update_rela (rdata, ndx, &rela) == 0)
+			error (1, 0, "Couldn't update relocation: %s",
+			       elf_errmsg (-1));
 		    }
-		  qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp);
-
-		  size_t lndx = 0;
-		  for (size_t i = 0; i < rels; i++)
+		  else
 		    {
-		      /* These relocations only happen in ET_REL files
-			 and are section offsets. */
-		      GElf_Addr r_offset;
-		      size_t ndx = rbuf[i].ndx;
-
-		      GElf_Rel rel;
-		      GElf_Rela rela;
-		      if (rtype == SHT_RELA)
-			{
-			  if (gelf_getrela (rdata, ndx, &rela) == NULL)
-			    error (1, 0, "Couldn't get relocation: %s",
-				   elf_errmsg (-1));
-			  r_offset = rela.r_offset;
-			}
-		      else
-			{
-			  if (gelf_getrel (rdata, ndx, &rel) == NULL)
-			    error (1, 0, "Couldn't get relocation: %s",
-				   elf_errmsg (-1));
-			  r_offset = rel.r_offset;
-			}
-
-		      while (lndx < dso->lines.used
-			     && r_offset > (dso->lines.table[lndx].old_idx
-					    + 4
-					    + dso->lines.table[lndx].unit_length))
-			lndx++;
-
-		      if (lndx >= dso->lines.used)
-			error (1, 0,
-			       ".debug_line relocation offset out of range");
-
-		      /* Offset (pointing into the line program) moves
-			 from old to new index including the header
-			 size diff. */
-		      r_offset += (ssize_t)((dso->lines.table[lndx].new_idx
-					     - dso->lines.table[lndx].old_idx)
-					    + dso->lines.table[lndx].size_diff);
-
-		      if (rtype == SHT_RELA)
-			{
-			  rela.r_offset = r_offset;
-			  if (gelf_update_rela (rdata, ndx, &rela) == 0)
-			    error (1, 0, "Couldn't update relocation: %s",
-				   elf_errmsg (-1));
-			}
-		      else
-			{
-			  rel.r_offset = r_offset;
-			  if (gelf_update_rel (rdata, ndx, &rel) == 0)
-			    error (1, 0, "Couldn't update relocation: %s",
-				   elf_errmsg (-1));
-			}
+		      rel.r_offset = r_offset;
+		      if (gelf_update_rel (rdata, ndx, &rel) == 0)
+			error (1, 0, "Couldn't update relocation: %s",
+			       elf_errmsg (-1));
 		    }
-
-		  elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY);
-		  free (rbuf);
 		}
+
+	      elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY);
+	      free (rbuf);
 	    }
+	}
 
-	  /* The .debug_macro section also contains offsets into the
-	     .debug_str section and references to the .debug_line
-	     tables, so we need to update those as well if we update
-	     the strings or the stmts.  */
-	  if ((need_strp_update || need_stmt_update)
-	      && debug_sections[DEBUG_MACRO].data)
+      /* The .debug_macro section also contains offsets into the
+	 .debug_str section and references to the .debug_line
+	 tables, so we need to update those as well if we update
+	 the strings or the stmts.  */
+      if ((need_strp_update || need_stmt_update)
+	  && debug_sections[DEBUG_MACRO].data)
+	{
+	  /* There might be multiple (COMDAT) .debug_macro sections.  */
+	  struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
+	  while (macro_sec != NULL)
 	    {
-	      /* There might be multiple (COMDAT) .debug_macro sections.  */
-	      struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
-	      while (macro_sec != NULL)
-		{
-		  setup_relbuf(dso, macro_sec, &reltype);
-		  rel_updated = false;
+	      setup_relbuf(dso, macro_sec, &reltype);
+	      rel_updated = false;
 
-		  ptr = macro_sec->data;
-		  endsec = ptr + macro_sec->size;
-		  int op = 0, macro_version, macro_flags;
-		  int offset_len = 4, line_offset = 0;
+	      ptr = macro_sec->data;
+	      endsec = ptr + macro_sec->size;
+	      int op = 0, macro_version, macro_flags;
+	      int offset_len = 4, line_offset = 0;
 
-		  while (ptr < endsec)
+	      while (ptr < endsec)
+		{
+		  if (!op)
 		    {
-		      if (!op)
-			{
-			  macro_version = read_16 (ptr);
-			  macro_flags = read_8 (ptr);
-			  if (macro_version < 4 || macro_version > 5)
-			    error (1, 0, "unhandled .debug_macro version: %d",
-				   macro_version);
-			  if ((macro_flags & ~2) != 0)
-			    error (1, 0, "unhandled .debug_macro flags: 0x%x",
-				   macro_flags);
-
-			  offset_len = (macro_flags & 0x01) ? 8 : 4;
-			  line_offset = (macro_flags & 0x02) ? 1 : 0;
-
-			  if (offset_len != 4)
-			    error (0, 1,
-				   "Cannot handle 8 byte macro offsets: %s",
-				   dso->filename);
-
-			  /* Update the line_offset if it is there.  */
-			  if (line_offset)
-			    {
-			      if (phase == 0)
-				ptr += offset_len;
-			      else
-				{
-				  size_t idx, new_idx;
-				  idx = do_read_32_relocated (ptr);
-				  new_idx = find_new_list_offs (&dso->lines,
-								idx);
-				  write_32_relocated (ptr, new_idx);
-				}
-			    }
-			}
+		      macro_version = read_16 (ptr);
+		      macro_flags = read_8 (ptr);
+		      if (macro_version < 4 || macro_version > 5)
+			error (1, 0, "unhandled .debug_macro version: %d",
+			       macro_version);
+		      if ((macro_flags & ~2) != 0)
+			error (1, 0, "unhandled .debug_macro flags: 0x%x",
+			       macro_flags);
+
+		      offset_len = (macro_flags & 0x01) ? 8 : 4;
+		      line_offset = (macro_flags & 0x02) ? 1 : 0;
+
+		      if (offset_len != 4)
+			error (0, 1,
+			       "Cannot handle 8 byte macro offsets: %s",
+			       dso->filename);
 
-		      op = read_8 (ptr);
-		      if (!op)
-			continue;
-		      switch(op)
+		      /* Update the line_offset if it is there.  */
+		      if (line_offset)
 			{
-			case DW_MACRO_GNU_define:
-			case DW_MACRO_GNU_undef:
-			  read_uleb128 (ptr);
-			  ptr = ((unsigned char *) strchr ((char *) ptr, '\0')
-				 + 1);
-			  break;
-			case DW_MACRO_GNU_start_file:
-			  read_uleb128 (ptr);
-			  read_uleb128 (ptr);
-			  break;
-			case DW_MACRO_GNU_end_file:
-			  break;
-			case DW_MACRO_GNU_define_indirect:
-			case DW_MACRO_GNU_undef_indirect:
-			  read_uleb128 (ptr);
 			  if (phase == 0)
-			    {
-			      size_t idx = read_32_relocated (ptr);
-			      record_existing_string_entry_idx (&dso->strings,
-								idx);
-			    }
+			    ptr += offset_len;
 			  else
 			    {
-			      struct stridxentry *entry;
 			      size_t idx, new_idx;
 			      idx = do_read_32_relocated (ptr);
-			      entry = string_find_entry (&dso->strings, idx);
-			      new_idx = strent_offset (entry->entry);
+			      new_idx = find_new_list_offs (&dso->lines,
+							    idx);
 			      write_32_relocated (ptr, new_idx);
 			    }
-			  break;
-			case DW_MACRO_GNU_transparent_include:
-			  ptr += offset_len;
-			  break;
-			default:
-			  error (1, 0, "Unhandled DW_MACRO op 0x%x", op);
-			  break;
 			}
 		    }
 
-		  if (rel_updated)
-		    macro_rel_updated = true;
-		  macro_sec = macro_sec->next;
+		  op = read_8 (ptr);
+		  if (!op)
+		    continue;
+		  switch(op)
+		    {
+		    case DW_MACRO_GNU_define:
+		    case DW_MACRO_GNU_undef:
+		      read_uleb128 (ptr);
+		      ptr = ((unsigned char *) strchr ((char *) ptr, '\0')
+			     + 1);
+		      break;
+		    case DW_MACRO_GNU_start_file:
+		      read_uleb128 (ptr);
+		      read_uleb128 (ptr);
+		      break;
+		    case DW_MACRO_GNU_end_file:
+		      break;
+		    case DW_MACRO_GNU_define_indirect:
+		    case DW_MACRO_GNU_undef_indirect:
+		      read_uleb128 (ptr);
+		      if (phase == 0)
+			{
+			  size_t idx = read_32_relocated (ptr);
+			  record_existing_string_entry_idx (&dso->strings,
+							    idx);
+			}
+		      else
+			{
+			  struct stridxentry *entry;
+			  size_t idx, new_idx;
+			  idx = do_read_32_relocated (ptr);
+			  entry = string_find_entry (&dso->strings, idx);
+			  new_idx = strent_offset (entry->entry);
+			  write_32_relocated (ptr, new_idx);
+			}
+		      break;
+		    case DW_MACRO_GNU_transparent_include:
+		      ptr += offset_len;
+		      break;
+		    default:
+		      error (1, 0, "Unhandled DW_MACRO op 0x%x", op);
+		      break;
+		    }
 		}
-	    }
 
-	  /* Same for the debug_str section. Make sure everything is
-	     in place for phase 1 updating of debug_info
-	     references. */
-	  if (phase == 0 && need_strp_update)
-	    {
-	      Strtab *strtab = dso->strings.str_tab;
-	      Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
-	      int strndx = debug_sections[DEBUG_STR].sec;
-	      Elf_Scn *strscn = dso->scn[strndx];
-
-	      /* Out with the old. */
-	      strdata->d_size = 0;
-	      /* In with the new. */
-	      strdata = elf_newdata (strscn);
-
-	      /* We really should check whether we had enough memory,
-		 but the old ebl version will just abort on out of
-		 memory... */
-	      strtab_finalize (strtab, strdata);
-	      debug_sections[DEBUG_STR].size = strdata->d_size;
-	      dso->strings.str_buf = strdata->d_buf;
+	      if (rel_updated)
+		macro_rel_updated = true;
+	      macro_sec = macro_sec->next;
 	    }
+	}
 
+      /* Same for the debug_str section. Make sure everything is
+	 in place for phase 1 updating of debug_info
+	 references. */
+      if (phase == 0 && need_strp_update)
+	{
+	  Strtab *strtab = dso->strings.str_tab;
+	  Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
+	  int strndx = debug_sections[DEBUG_STR].sec;
+	  Elf_Scn *strscn = dso->scn[strndx];
+
+	  /* Out with the old. */
+	  strdata->d_size = 0;
+	  /* In with the new. */
+	  strdata = elf_newdata (strscn);
+
+	  /* We really should check whether we had enough memory,
+	     but the old ebl version will just abort on out of
+	     memory... */
+	  strtab_finalize (strtab, strdata);
+	  debug_sections[DEBUG_STR].size = strdata->d_size;
+	  dso->strings.str_buf = strdata->d_buf;
 	}
 
-      /* After phase 1 we might have rewritten the debug_info with
-	 new strp, strings and/or linep offsets.  */
-      if (need_strp_update || need_string_replacement || need_stmt_update)
-	dirty_section (DEBUG_INFO);
-      if (need_strp_update || need_stmt_update)
-	dirty_section (DEBUG_MACRO);
-      if (need_stmt_update)
-	dirty_section (DEBUG_LINE);
+    }
+
+  /* After phase 1 we might have rewritten the debug_info with
+     new strp, strings and/or linep offsets.  */
+  if (need_strp_update || need_string_replacement || need_stmt_update)
+    dirty_section (DEBUG_INFO);
+  if (need_strp_update || need_stmt_update)
+    dirty_section (DEBUG_MACRO);
+  if (need_stmt_update)
+    dirty_section (DEBUG_LINE);
 
-      /* Update any relocations addends we might have touched. */
-      if (info_rel_updated)
-	update_rela_data (dso, &debug_sections[DEBUG_INFO]);
+  /* Update any relocations addends we might have touched. */
+  if (info_rel_updated)
+    update_rela_data (dso, &debug_sections[DEBUG_INFO]);
 
-      if (macro_rel_updated)
+  if (macro_rel_updated)
+    {
+      struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
+      while (macro_sec != NULL)
 	{
-	  struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO];
-	  while (macro_sec != NULL)
-	    {
-	      update_rela_data (dso, macro_sec);
-	      macro_sec = macro_sec->next;
-	    }
+	  update_rela_data (dso, macro_sec);
+	  macro_sec = macro_sec->next;
 	}
     }
 
-- 
2.18.4