chantra / rpms / rpm

Forked from rpms/rpm 2 years ago
Clone
DistroBaker 6ff1af
From d9947f2dc0c2cd812f8e64380d5f6f53705a5280 Mon Sep 17 00:00:00 2001
DistroBaker 6ff1af
From: Mark Wielaard <mark@klomp.org>
DistroBaker 6ff1af
Date: Tue, 19 Jan 2021 04:12:33 +0100
DistroBaker 6ff1af
Subject: [PATCH 6/6] debugedit: Handle DWARF-5 debug_line and debug_line_str.
DistroBaker 6ff1af
DistroBaker 6ff1af
Handle the new DWARF5 .debug_line tables and the new DW_FORM_line_strp.
DistroBaker 6ff1af
DWARF5 tables are handled separately from the earlier tables. They
DistroBaker 6ff1af
will never change size, but they do need updates to the .debug_str
DistroBaker 6ff1af
or .debug_line_str references.
DistroBaker 6ff1af
DistroBaker 6ff1af
Based on a patch from Jan Kratochvil <jan.kratochvil@redhat.com>
DistroBaker 6ff1af
---
DistroBaker 6ff1af
 tools/debugedit.c | 471 ++++++++++++++++++++++++++++++++++++++++------
DistroBaker 6ff1af
 1 file changed, 410 insertions(+), 61 deletions(-)
DistroBaker 6ff1af
DistroBaker 6ff1af
diff --git a/tools/debugedit.c b/tools/debugedit.c
DistroBaker 6ff1af
index be5fee85b..d6a0058e9 100644
DistroBaker 6ff1af
--- a/tools/debugedit.c
DistroBaker 6ff1af
+++ b/tools/debugedit.c
DistroBaker 6ff1af
@@ -103,6 +103,8 @@ static bool need_string_replacement = false;
DistroBaker 6ff1af
 /* Whether we need to do any updates of the string indexes (DW_FORM_strp)
DistroBaker 6ff1af
    in debug_info for string indexes. */
DistroBaker 6ff1af
 static bool need_strp_update = false;
DistroBaker 6ff1af
+/* Likewise for DW_FORM_line_strp. */
DistroBaker 6ff1af
+static bool need_line_strp_update = false;
DistroBaker 6ff1af
 /* If the debug_line changes size we will need to update the
DistroBaker 6ff1af
    DW_AT_stmt_list attributes indexes in the debug_info. */
DistroBaker 6ff1af
 static bool need_stmt_update = false;
DistroBaker 6ff1af
@@ -192,7 +194,7 @@ typedef struct
DistroBaker 6ff1af
   const char *filename;
DistroBaker 6ff1af
   int lastscn;
DistroBaker 6ff1af
   size_t phnum;
DistroBaker 6ff1af
-  struct strings strings;
DistroBaker 6ff1af
+  struct strings debug_str, debug_line_str;
DistroBaker 6ff1af
   struct debug_lines lines;
DistroBaker 6ff1af
   GElf_Shdr shdr[0];
DistroBaker 6ff1af
 } DSO;
DistroBaker 6ff1af
@@ -553,10 +555,11 @@ setup_relbuf (DSO *dso, debug_section *sec, int *reltype)
DistroBaker 6ff1af
       /* Relocations against section symbols are uninteresting in REL.  */
DistroBaker 6ff1af
       if (dso->shdr[i].sh_type == SHT_REL && sym.st_value == 0)
DistroBaker 6ff1af
 	continue;
DistroBaker 6ff1af
-      /* Only consider relocations against .debug_str, .debug_line
DistroBaker 6ff1af
-	 and .debug_abbrev.  */
DistroBaker 6ff1af
+      /* Only consider relocations against .debug_str, .debug_line,
DistroBaker 6ff1af
+	 .debug_line_str, and .debug_abbrev.  */
DistroBaker 6ff1af
       if (sym.st_shndx != debug_sections[DEBUG_STR].sec
DistroBaker 6ff1af
 	  && sym.st_shndx != debug_sections[DEBUG_LINE].sec
DistroBaker 6ff1af
+	  && sym.st_shndx != debug_sections[DEBUG_LINE_STR].sec
DistroBaker 6ff1af
 	  && sym.st_shndx != debug_sections[DEBUG_ABBREV].sec)
DistroBaker 6ff1af
 	continue;
DistroBaker 6ff1af
       rela.r_addend += sym.st_value;
DistroBaker 6ff1af
@@ -768,6 +771,7 @@ no_memory:
DistroBaker 6ff1af
 	      || (form > DW_FORM_flag_present
DistroBaker 6ff1af
 		  && !(form == DW_FORM_ref_sig8
DistroBaker 6ff1af
 		       || form == DW_FORM_data16
DistroBaker 6ff1af
+		       || form == DW_FORM_line_strp
DistroBaker 6ff1af
 		       || form == DW_FORM_implicit_const
DistroBaker 6ff1af
 		       || form == DW_FORM_addrx
DistroBaker 6ff1af
 		       || form == DW_FORM_loclistx
DistroBaker 6ff1af
@@ -1049,17 +1053,20 @@ string_find_entry (struct strings *strings, size_t old_idx)
DistroBaker 6ff1af
    a replacement file string has been recorded for it, otherwise
DistroBaker 6ff1af
    returns false.  */
DistroBaker 6ff1af
 static bool
DistroBaker 6ff1af
-record_file_string_entry_idx (struct strings *strings, size_t old_idx)
DistroBaker 6ff1af
+record_file_string_entry_idx (bool line_strp, DSO *dso, size_t old_idx)
DistroBaker 6ff1af
 {
DistroBaker 6ff1af
+  struct strings *strings = line_strp ? &dso->debug_line_str : &dso->debug_str;
DistroBaker 6ff1af
   bool ret = false;
DistroBaker 6ff1af
   struct stridxentry *entry = string_find_new_entry (strings, old_idx);
DistroBaker 6ff1af
   if (entry != NULL)
DistroBaker 6ff1af
     {
DistroBaker 6ff1af
-      if (old_idx >= debug_sections[DEBUG_STR].size)
DistroBaker 6ff1af
-	error (1, 0, "Bad string pointer index %zd", old_idx);
DistroBaker 6ff1af
+      debug_section *sec = &debug_sections[line_strp
DistroBaker 6ff1af
+					   ? DEBUG_LINE_STR : DEBUG_STR];
DistroBaker 6ff1af
+      if (old_idx >= sec->size)
DistroBaker 6ff1af
+	error (1, 0, "Bad string pointer index %zd (%s)", old_idx, sec->name);
DistroBaker 6ff1af
 
DistroBaker 6ff1af
       Strent *strent;
DistroBaker 6ff1af
-      const char *old_str = (char *)debug_sections[DEBUG_STR].data + old_idx;
DistroBaker 6ff1af
+      const char *old_str = (char *)sec->data + old_idx;
DistroBaker 6ff1af
       const char *file = skip_dir_prefix (old_str, base_dir);
DistroBaker 6ff1af
       if (file == NULL)
DistroBaker 6ff1af
 	{
DistroBaker 6ff1af
@@ -1103,15 +1110,18 @@ record_file_string_entry_idx (struct strings *strings, size_t old_idx)
DistroBaker 6ff1af
    base_dir with dest_dir, just records the existing string associated
DistroBaker 6ff1af
    with the index. */
DistroBaker 6ff1af
 static void
DistroBaker 6ff1af
-record_existing_string_entry_idx (struct strings *strings, size_t old_idx)
DistroBaker 6ff1af
+record_existing_string_entry_idx (bool line_strp, DSO *dso, size_t old_idx)
DistroBaker 6ff1af
 {
DistroBaker 6ff1af
+  struct strings *strings = line_strp ? &dso->debug_line_str : &dso->debug_str;
DistroBaker 6ff1af
   struct stridxentry *entry = string_find_new_entry (strings, old_idx);
DistroBaker 6ff1af
   if (entry != NULL)
DistroBaker 6ff1af
     {
DistroBaker 6ff1af
-      if (old_idx >= debug_sections[DEBUG_STR].size)
DistroBaker 6ff1af
-	error (1, 0, "Bad string pointer index %zd", old_idx);
DistroBaker 6ff1af
+      debug_section *sec = &debug_sections[line_strp
DistroBaker 6ff1af
+					   ? DEBUG_LINE_STR : DEBUG_STR];
DistroBaker 6ff1af
+      if (old_idx >= sec->size)
DistroBaker 6ff1af
+	error (1, 0, "Bad string pointer index %zd (%s)", old_idx, sec->name);
DistroBaker 6ff1af
 
DistroBaker 6ff1af
-      const char *str = (char *)debug_sections[DEBUG_STR].data + old_idx;
DistroBaker 6ff1af
+      const char *str = (char *)sec->data + old_idx;
DistroBaker 6ff1af
       Strent *strent = strtab_add_len (strings->str_tab,
DistroBaker 6ff1af
 				       str, strlen (str) + 1);
DistroBaker 6ff1af
       if (strent == NULL)
DistroBaker 6ff1af
@@ -1244,13 +1254,28 @@ get_line_table (DSO *dso, size_t off, struct line_table **table)
DistroBaker 6ff1af
 
DistroBaker 6ff1af
   /* version */
DistroBaker 6ff1af
   t->version = read_16 (ptr);
DistroBaker 6ff1af
-  if (t->version != 2 && t->version != 3 && t->version != 4)
DistroBaker 6ff1af
+  if (t->version != 2 && t->version != 3 && t->version != 4 && t->version != 5)
DistroBaker 6ff1af
     {
DistroBaker 6ff1af
       error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
DistroBaker 6ff1af
 	     t->version);
DistroBaker 6ff1af
       return false;
DistroBaker 6ff1af
     }
DistroBaker 6ff1af
 
DistroBaker 6ff1af
+  if (t->version >= 5)
DistroBaker 6ff1af
+    {
DistroBaker 6ff1af
+      /* address_size */
DistroBaker 6ff1af
+      assert (ptr_size != 0);
DistroBaker 6ff1af
+      if (ptr_size != read_8 (ptr))
DistroBaker 6ff1af
+	{
DistroBaker 6ff1af
+	  error (0, 0, "%s: .debug_line address size differs from .debug_info",
DistroBaker 6ff1af
+		 dso->filename);
DistroBaker 6ff1af
+	  return false;
DistroBaker 6ff1af
+	}
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+      /* segment_selector_size */
DistroBaker 6ff1af
+      (void) read_8 (ptr);
DistroBaker 6ff1af
+    }
DistroBaker 6ff1af
+
DistroBaker 6ff1af
   /* header_length */
DistroBaker 6ff1af
   unsigned char *endprol = ptr + 4;
DistroBaker 6ff1af
   t->header_length = read_32 (ptr);
DistroBaker 6ff1af
@@ -1343,7 +1368,9 @@ edit_dwarf2_line (DSO *dso)
DistroBaker 6ff1af
 
DistroBaker 6ff1af
   linedata->d_size = dso->lines.debug_lines_len;
DistroBaker 6ff1af
   linedata->d_buf = dso->lines.line_buf;
DistroBaker 6ff1af
+  debug_sections[DEBUG_LINE].data = linedata->d_buf;
DistroBaker 6ff1af
   debug_sections[DEBUG_LINE].size = linedata->d_size;
DistroBaker 6ff1af
+  debug_sections[DEBUG_LINE].elf_data = linedata;
DistroBaker 6ff1af
 
DistroBaker 6ff1af
   /* Make sure the line tables are sorted on the old index. */
DistroBaker 6ff1af
   qsort (dso->lines.table, dso->lines.used, sizeof (struct line_table),
DistroBaker 6ff1af
@@ -1483,9 +1510,10 @@ edit_dwarf2_line (DSO *dso)
DistroBaker 6ff1af
     }
DistroBaker 6ff1af
 }
DistroBaker 6ff1af
 
DistroBaker 6ff1af
-/* Record or adjust (according to phase) DW_FORM_strp.  */
DistroBaker 6ff1af
+/* Record or adjust (according to phase) DW_FORM_strp or DW_FORM_line_strp.  */
DistroBaker 6ff1af
 static void
DistroBaker 6ff1af
-edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp)
DistroBaker 6ff1af
+edit_strp (DSO *dso, bool line_strp, unsigned char *ptr, int phase,
DistroBaker 6ff1af
+	   bool handled_strp)
DistroBaker 6ff1af
 {
DistroBaker 6ff1af
   unsigned char *ptr_orig = ptr;
DistroBaker 6ff1af
 
DistroBaker 6ff1af
@@ -1500,15 +1528,18 @@ edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp)
DistroBaker 6ff1af
       if (! handled_strp)
DistroBaker 6ff1af
 	{
DistroBaker 6ff1af
 	  size_t idx = do_read_32_relocated (ptr);
DistroBaker 6ff1af
-	  record_existing_string_entry_idx (&dso->strings, idx);
DistroBaker 6ff1af
+	  record_existing_string_entry_idx (line_strp, dso, idx);
DistroBaker 6ff1af
 	}
DistroBaker 6ff1af
     }
DistroBaker 6ff1af
-  else if (need_strp_update) /* && phase == 1 */
DistroBaker 6ff1af
+  else if (line_strp
DistroBaker 6ff1af
+	   ? need_line_strp_update : need_strp_update) /* && phase == 1 */
DistroBaker 6ff1af
     {
DistroBaker 6ff1af
       struct stridxentry *entry;
DistroBaker 6ff1af
       size_t idx, new_idx;
DistroBaker 6ff1af
+      struct strings *strings = (line_strp
DistroBaker 6ff1af
+				 ? &dso->debug_line_str : &dso->debug_str);
DistroBaker 6ff1af
       idx = do_read_32_relocated (ptr);
DistroBaker 6ff1af
-      entry = string_find_entry (&dso->strings, idx);
DistroBaker 6ff1af
+      entry = string_find_entry (strings, idx);
DistroBaker 6ff1af
       new_idx = strent_offset (entry->entry);
DistroBaker 6ff1af
       do_write_32_relocated (ptr, new_idx);
DistroBaker 6ff1af
     }
DistroBaker 6ff1af
@@ -1759,6 +1790,254 @@ read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir,
DistroBaker 6ff1af
   return true;
DistroBaker 6ff1af
 }
DistroBaker 6ff1af
 
DistroBaker 6ff1af
+/* Called by read_dwarf5_line first for directories and then file
DistroBaker 6ff1af
+   names as they both have the same format.  */
DistroBaker 6ff1af
+static bool
DistroBaker 6ff1af
+read_dwarf5_line_entries (DSO *dso, unsigned char **ptrp,
DistroBaker 6ff1af
+			  struct line_table *table, int phase,
DistroBaker 6ff1af
+			  char ***dirs, int *ndir,
DistroBaker 6ff1af
+			  const char *entry_name)
DistroBaker 6ff1af
+{
DistroBaker 6ff1af
+  /* directory_entry_format_count */
DistroBaker 6ff1af
+  /* file_name_entry_format_count */
DistroBaker 6ff1af
+  unsigned format_count = read_8 (*ptrp);
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+  unsigned char *formats = *ptrp;
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+  /* directory_entry_format */
DistroBaker 6ff1af
+  /* file_name_entry_format */
DistroBaker 6ff1af
+  for (unsigned formati = 0; formati < format_count; ++formati)
DistroBaker 6ff1af
+    {
DistroBaker 6ff1af
+      read_uleb128 (*ptrp);
DistroBaker 6ff1af
+      read_uleb128 (*ptrp);
DistroBaker 6ff1af
+    }
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+  /* directories_count */
DistroBaker 6ff1af
+  /* file_names_count */
DistroBaker 6ff1af
+  unsigned entry_count = read_uleb128 (*ptrp);
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+  bool collecting_dirs = dest_dir && phase == 0 && *dirs == NULL;
DistroBaker 6ff1af
+  bool writing_files = dest_dir && phase == 0 && *dirs != NULL;
DistroBaker 6ff1af
+  if (collecting_dirs)
DistroBaker 6ff1af
+    {
DistroBaker 6ff1af
+      *ndir = entry_count;
DistroBaker 6ff1af
+      *dirs = malloc (entry_count * sizeof (char *));
DistroBaker 6ff1af
+      if (*dirs == NULL)
DistroBaker 6ff1af
+	error (1, errno, "%s: Could not allocate debug_line dirs",
DistroBaker 6ff1af
+	       dso->filename);
DistroBaker 6ff1af
+    }
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+  /* directories */
DistroBaker 6ff1af
+  /* file_names */
DistroBaker 6ff1af
+  for (unsigned entryi = 0; entryi < entry_count; ++entryi)
DistroBaker 6ff1af
+    {
DistroBaker 6ff1af
+      char *dir = NULL;
DistroBaker 6ff1af
+      char *file = NULL;;
DistroBaker 6ff1af
+      unsigned char *format_ptr = formats;
DistroBaker 6ff1af
+      for (unsigned formati = 0; formati < format_count; ++formati)
DistroBaker 6ff1af
+	{
DistroBaker 6ff1af
+	  unsigned lnct = read_uleb128 (format_ptr);
DistroBaker 6ff1af
+	  unsigned form = read_uleb128 (format_ptr);
DistroBaker 6ff1af
+	  bool handled_form = false;
DistroBaker 6ff1af
+	  bool handled_strp = false;
DistroBaker 6ff1af
+	  bool line_strp = form == DW_FORM_line_strp;
DistroBaker 6ff1af
+	  if (lnct == DW_LNCT_path)
DistroBaker 6ff1af
+	    {
DistroBaker 6ff1af
+	      switch (form)
DistroBaker 6ff1af
+		{
DistroBaker 6ff1af
+		case DW_FORM_strp:
DistroBaker 6ff1af
+		case DW_FORM_line_strp:
DistroBaker 6ff1af
+		  if (dest_dir && phase == 0)
DistroBaker 6ff1af
+		    {
DistroBaker 6ff1af
+		      size_t idx = do_read_32_relocated (*ptrp);
DistroBaker 6ff1af
+		      if (record_file_string_entry_idx (line_strp, dso, idx))
DistroBaker 6ff1af
+			{
DistroBaker 6ff1af
+			  if (line_strp)
DistroBaker 6ff1af
+			    need_line_strp_update = true;
DistroBaker 6ff1af
+			  else
DistroBaker 6ff1af
+			    need_strp_update = true;
DistroBaker 6ff1af
+			}
DistroBaker 6ff1af
+		      handled_strp = true;
DistroBaker 6ff1af
+		      if (collecting_dirs || writing_files)
DistroBaker 6ff1af
+			{
DistroBaker 6ff1af
+			  debug_section *sec = &debug_sections[line_strp
DistroBaker 6ff1af
+                                           ? DEBUG_LINE_STR : DEBUG_STR];
DistroBaker 6ff1af
+			  if (collecting_dirs)
DistroBaker 6ff1af
+			    dir = (char *)sec->data + idx;
DistroBaker 6ff1af
+			  if (writing_files)
DistroBaker 6ff1af
+			    file = (char *)sec->data + idx;
DistroBaker 6ff1af
+			}
DistroBaker 6ff1af
+		    }
DistroBaker 6ff1af
+		  break;
DistroBaker 6ff1af
+		default:
DistroBaker 6ff1af
+		  error (0, 0, "%s: Unsupported "
DistroBaker 6ff1af
+			 ".debug_line %s %u path DW_FORM_0x%x",
DistroBaker 6ff1af
+			 dso->filename, entry_name, entryi, form);
DistroBaker 6ff1af
+		  return false;
DistroBaker 6ff1af
+		}
DistroBaker 6ff1af
+	    }
DistroBaker 6ff1af
+	  if (writing_files && lnct == DW_LNCT_directory_index)
DistroBaker 6ff1af
+	    {
DistroBaker 6ff1af
+	      int dirndx;
DistroBaker 6ff1af
+	      switch (form)
DistroBaker 6ff1af
+		{
DistroBaker 6ff1af
+		case DW_FORM_udata:
DistroBaker 6ff1af
+		  handled_form = true;
DistroBaker 6ff1af
+		  dirndx = read_uleb128 (*ptrp);
DistroBaker 6ff1af
+		  break;
DistroBaker 6ff1af
+		case DW_FORM_data1:
DistroBaker 6ff1af
+		  dirndx = **ptrp;
DistroBaker 6ff1af
+		  break;
DistroBaker 6ff1af
+		case DW_FORM_data2:
DistroBaker 6ff1af
+		  dirndx = do_read_16 (*ptrp);
DistroBaker 6ff1af
+		  break;
DistroBaker 6ff1af
+		case DW_FORM_data4:
DistroBaker 6ff1af
+		  dirndx = do_read_32 (*ptrp);
DistroBaker 6ff1af
+		  break;
DistroBaker 6ff1af
+		default:
DistroBaker 6ff1af
+		  error (0, 0, "%s: Unsupported "
DistroBaker 6ff1af
+			 ".debug_line %s %u dirndx DW_FORM_0x%x",
DistroBaker 6ff1af
+			 dso->filename, entry_name, entryi, form);
DistroBaker 6ff1af
+		  return false;
DistroBaker 6ff1af
+		}
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+	      if (dirndx > *ndir)
DistroBaker 6ff1af
+		{
DistroBaker 6ff1af
+		  error (0, 0, "%s: Bad dir number %u in .debug_line %s",
DistroBaker 6ff1af
+			 dso->filename, entryi, entry_name);
DistroBaker 6ff1af
+		  return false;
DistroBaker 6ff1af
+		}
DistroBaker 6ff1af
+	      dir = (*dirs)[dirndx];
DistroBaker 6ff1af
+	    }
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+	  switch (form)
DistroBaker 6ff1af
+	    {
DistroBaker 6ff1af
+	    case DW_FORM_strp:
DistroBaker 6ff1af
+	    case DW_FORM_line_strp:
DistroBaker 6ff1af
+	      edit_strp (dso, line_strp, *ptrp, phase, handled_strp);
DistroBaker 6ff1af
+	      break;
DistroBaker 6ff1af
+	    }
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+	  if (!handled_form)
DistroBaker 6ff1af
+	    {
DistroBaker 6ff1af
+	      switch (skip_form (dso, &form, ptrp))
DistroBaker 6ff1af
+		{
DistroBaker 6ff1af
+		case FORM_OK:
DistroBaker 6ff1af
+		  break;
DistroBaker 6ff1af
+		case FORM_ERROR:
DistroBaker 6ff1af
+		  return false;
DistroBaker 6ff1af
+		case FORM_INDIRECT:
DistroBaker 6ff1af
+		  error (0, 0, "%s: Unsupported "
DistroBaker 6ff1af
+			 ".debug_line %s %u DW_FORM_indirect",
DistroBaker 6ff1af
+			 dso->filename, entry_name, entryi);
DistroBaker 6ff1af
+		  return false;
DistroBaker 6ff1af
+		}
DistroBaker 6ff1af
+	    }
DistroBaker 6ff1af
+	}
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+      if (collecting_dirs)
DistroBaker 6ff1af
+	(*dirs)[entryi] = dir;
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+      if (writing_files)
DistroBaker 6ff1af
+	{
DistroBaker 6ff1af
+	  char *comp_dir = (*dirs)[0];
DistroBaker 6ff1af
+	  size_t comp_dir_len = strlen(comp_dir);
DistroBaker 6ff1af
+	  size_t file_len = strlen (file);
DistroBaker 6ff1af
+	  size_t dir_len = strlen (dir);
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+	  char *s = malloc (comp_dir_len + 1 + file_len + 1 + dir_len + 1);
DistroBaker 6ff1af
+	  if (s == NULL)
DistroBaker 6ff1af
+	    {
DistroBaker 6ff1af
+	      error (0, ENOMEM, "%s: Reading file table", dso->filename);
DistroBaker 6ff1af
+	      return false;
DistroBaker 6ff1af
+	    }
DistroBaker 6ff1af
+	  if (file[0] == '/')
DistroBaker 6ff1af
+	    {
DistroBaker 6ff1af
+	      memcpy (s, file, file_len + 1);
DistroBaker 6ff1af
+	    }
DistroBaker 6ff1af
+	  else if (dir[0] == '/')
DistroBaker 6ff1af
+	    {
DistroBaker 6ff1af
+	      memcpy (s, dir, dir_len);
DistroBaker 6ff1af
+	      s[dir_len] = '/';
DistroBaker 6ff1af
+	      memcpy (s + dir_len + 1, file, file_len + 1);
DistroBaker 6ff1af
+	    }
DistroBaker 6ff1af
+	  else
DistroBaker 6ff1af
+	    {
DistroBaker 6ff1af
+	      char *p = s;
DistroBaker 6ff1af
+	      if (comp_dir_len != 0)
DistroBaker 6ff1af
+		{
DistroBaker 6ff1af
+		  memcpy (s, comp_dir, comp_dir_len);
DistroBaker 6ff1af
+		  s[comp_dir_len] = '/';
DistroBaker 6ff1af
+		  p += comp_dir_len + 1;
DistroBaker 6ff1af
+		}
DistroBaker 6ff1af
+	      memcpy (p, dir, dir_len);
DistroBaker 6ff1af
+	      p[dir_len] = '/';
DistroBaker 6ff1af
+	      memcpy (p + dir_len + 1, file, file_len + 1);
DistroBaker 6ff1af
+	    }
DistroBaker 6ff1af
+	  canonicalize_path (s, s);
DistroBaker 6ff1af
+	  if (list_file_fd != -1)
DistroBaker 6ff1af
+	    {
DistroBaker 6ff1af
+	      const char *p = NULL;
DistroBaker 6ff1af
+	      if (base_dir == NULL)
DistroBaker 6ff1af
+		p = s;
DistroBaker 6ff1af
+	      else
DistroBaker 6ff1af
+		{
DistroBaker 6ff1af
+		  p = skip_dir_prefix (s, base_dir);
DistroBaker 6ff1af
+		  if (p == NULL && dest_dir != NULL)
DistroBaker 6ff1af
+		    p = skip_dir_prefix (s, dest_dir);
DistroBaker 6ff1af
+		}
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+	      if (p)
DistroBaker 6ff1af
+		{
DistroBaker 6ff1af
+		  size_t size = strlen (p) + 1;
DistroBaker 6ff1af
+		  while (size > 0)
DistroBaker 6ff1af
+		    {
DistroBaker 6ff1af
+		      ssize_t ret = write (list_file_fd, p, size);
DistroBaker 6ff1af
+		      if (ret == -1)
DistroBaker 6ff1af
+			break;
DistroBaker 6ff1af
+		      size -= ret;
DistroBaker 6ff1af
+		      p += ret;
DistroBaker 6ff1af
+		    }
DistroBaker 6ff1af
+		}
DistroBaker 6ff1af
+	    }
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+	  free (s);
DistroBaker 6ff1af
+	}
DistroBaker 6ff1af
+    }
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+  return true;
DistroBaker 6ff1af
+}
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+/* Part of read_dwarf2_line processing DWARF-5.  */
DistroBaker 6ff1af
+static bool
DistroBaker 6ff1af
+read_dwarf5_line (DSO *dso, unsigned char *ptr, struct line_table *table,
DistroBaker 6ff1af
+		  int phase)
DistroBaker 6ff1af
+{
DistroBaker 6ff1af
+  char **dirs = NULL;
DistroBaker 6ff1af
+  int ndir;
DistroBaker 6ff1af
+  /* Skip header.  */
DistroBaker 6ff1af
+  ptr += (4 /* unit len */
DistroBaker 6ff1af
+          + 2 /* version */
DistroBaker 6ff1af
+          + (table->version < 5 ? 0 : 0
DistroBaker 6ff1af
+             + 1 /* address_size */
DistroBaker 6ff1af
+             + 1 /* segment_selector*/)
DistroBaker 6ff1af
+          + 4 /* header len */
DistroBaker 6ff1af
+          + 1 /* min instr len */
DistroBaker 6ff1af
+          + (table->version >= 4) /* max op per instr, if version >= 4 */
DistroBaker 6ff1af
+          + 1 /* default is stmt */
DistroBaker 6ff1af
+          + 1 /* line base */
DistroBaker 6ff1af
+          + 1 /* line range */
DistroBaker 6ff1af
+          + 1 /* opcode base */
DistroBaker 6ff1af
+          + table->opcode_base - 1); /* opcode len table */
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+  bool retval = (read_dwarf5_line_entries (dso, &ptr, table, phase,
DistroBaker 6ff1af
+					   &dirs, &ndir, "directory")
DistroBaker 6ff1af
+		 && read_dwarf5_line_entries (dso, &ptr, table, phase,
DistroBaker 6ff1af
+					      &dirs, &ndir, "file name"));
DistroBaker 6ff1af
+  free (dirs);
DistroBaker 6ff1af
+  return retval;
DistroBaker 6ff1af
+}
DistroBaker 6ff1af
+
DistroBaker 6ff1af
 /* Called during phase zero for each debug_line table referenced from
DistroBaker 6ff1af
    .debug_info.  Outputs all source files seen and records any
DistroBaker 6ff1af
    adjustments needed in the debug_list data structures. Returns true
DistroBaker 6ff1af
@@ -1778,6 +2057,9 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
DistroBaker 6ff1af
   ptr = debug_sections[DEBUG_LINE].data + off;
DistroBaker 6ff1af
   ptr += (4 /* unit len */
DistroBaker 6ff1af
 	  + 2 /* version */
DistroBaker 6ff1af
+	  + (table->version < 5 ? 0 : 0
DistroBaker 6ff1af
+	     + 1 /* address_size */
DistroBaker 6ff1af
+	     + 1 /* segment_selector*/)
DistroBaker 6ff1af
 	  + 4 /* header len */
DistroBaker 6ff1af
 	  + 1 /* min instr len */
DistroBaker 6ff1af
 	  + (table->version >= 4) /* max op per instr, if version >= 4 */
DistroBaker 6ff1af
@@ -1787,8 +2069,13 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
DistroBaker 6ff1af
 	  + 1 /* opcode base */
DistroBaker 6ff1af
 	  + table->opcode_base - 1); /* opcode len table */
DistroBaker 6ff1af
 
DistroBaker 6ff1af
-  if (! read_dwarf4_line (dso, ptr, comp_dir, table))
DistroBaker 6ff1af
-   return false;
DistroBaker 6ff1af
+  /* DWARF version 5 line tables won't change size. But they might need
DistroBaker 6ff1af
+     [line]strp recording/updates. Handle that part later.  */
DistroBaker 6ff1af
+  if (table->version < 5)
DistroBaker 6ff1af
+    {
DistroBaker 6ff1af
+      if (! read_dwarf4_line (dso, ptr, comp_dir, table))
DistroBaker 6ff1af
+	return false;
DistroBaker 6ff1af
+    }
DistroBaker 6ff1af
 
DistroBaker 6ff1af
   dso->lines.debug_lines_len += 4 + table->unit_length + table->size_diff;
DistroBaker 6ff1af
   return table->replace_dirs || table->replace_files;
DistroBaker 6ff1af
@@ -1807,20 +2094,22 @@ find_new_list_offs (struct debug_lines *lines, size_t idx)
DistroBaker 6ff1af
   return table->new_idx;
DistroBaker 6ff1af
 }
DistroBaker 6ff1af
 
DistroBaker 6ff1af
-/* Read DW_FORM_strp collecting compilation directory.  */
DistroBaker 6ff1af
+/* Read DW_FORM_strp or DW_FORM_line_strp collecting compilation directory.  */
DistroBaker 6ff1af
 static void
DistroBaker 6ff1af
-edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase,
DistroBaker 6ff1af
-			      char **comp_dirp, bool *handled_strpp)
DistroBaker 6ff1af
+edit_attributes_str_comp_dir (bool line_strp, DSO *dso, unsigned char **ptrp,
DistroBaker 6ff1af
+			      int phase, char **comp_dirp, bool *handled_strpp)
DistroBaker 6ff1af
 {
DistroBaker 6ff1af
   const char *dir;
DistroBaker 6ff1af
   size_t idx = do_read_32_relocated (*ptrp);
DistroBaker 6ff1af
   /* In phase zero we collect the comp_dir.  */
DistroBaker 6ff1af
   if (phase == 0)
DistroBaker 6ff1af
     {
DistroBaker 6ff1af
-      if (idx >= debug_sections[DEBUG_STR].size)
DistroBaker 6ff1af
-	error (1, 0, "%s: Bad string pointer index %zd for comp_dir",
DistroBaker 6ff1af
-	       dso->filename, idx);
DistroBaker 6ff1af
-      dir = (char *) debug_sections[DEBUG_STR].data + idx;
DistroBaker 6ff1af
+      debug_section *sec = &debug_sections[line_strp
DistroBaker 6ff1af
+					   ? DEBUG_LINE_STR : DEBUG_STR];
DistroBaker 7a85b5
+      if (sec->data == NULL || idx >= sec->size)
DistroBaker 6ff1af
+	error (1, 0, "%s: Bad string pointer index %zd for comp_dir (%s)",
DistroBaker 6ff1af
+	       dso->filename, idx, sec->name);
DistroBaker 6ff1af
+      dir = (char *) sec->data + idx;
DistroBaker 6ff1af
 
DistroBaker 6ff1af
       free (*comp_dirp);
DistroBaker 6ff1af
       *comp_dirp = strdup (dir);
DistroBaker 6ff1af
@@ -1828,8 +2117,13 @@ edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase,
DistroBaker 6ff1af
 
DistroBaker 6ff1af
   if (dest_dir != NULL && phase == 0)
DistroBaker 6ff1af
     {
DistroBaker 6ff1af
-      if (record_file_string_entry_idx (&dso->strings, idx))
DistroBaker 6ff1af
-	need_strp_update = true;
DistroBaker 6ff1af
+      if (record_file_string_entry_idx (line_strp, dso, idx))
DistroBaker 6ff1af
+	{
DistroBaker 6ff1af
+	  if (line_strp)
DistroBaker 6ff1af
+	    need_line_strp_update = true;
DistroBaker 6ff1af
+	  else
DistroBaker 6ff1af
+	    need_strp_update = true;
DistroBaker 6ff1af
+	}
DistroBaker 6ff1af
       *handled_strpp = true;
DistroBaker 6ff1af
     }
DistroBaker 6ff1af
 }
DistroBaker 6ff1af
@@ -1937,17 +2231,24 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
DistroBaker 6ff1af
 			}
DistroBaker 6ff1af
 		    }
DistroBaker 6ff1af
 		}
DistroBaker 6ff1af
-	      else if (form == DW_FORM_strp &&
DistroBaker 6ff1af
-		       debug_sections[DEBUG_STR].data)
DistroBaker 6ff1af
-		edit_attributes_str_comp_dir (dso, &ptr, phase, &comp_dir,
DistroBaker 6ff1af
+	      else if (form == DW_FORM_strp)
DistroBaker 6ff1af
+		edit_attributes_str_comp_dir (false /* line_strp */, dso,
DistroBaker 6ff1af
+					      &ptr, phase, &comp_dir,
DistroBaker 6ff1af
 					      &handled_strp);
DistroBaker 6ff1af
+	      else if (form == DW_FORM_line_strp)
DistroBaker 6ff1af
+		edit_attributes_str_comp_dir (true /* line_strp */, dso, &ptr,
DistroBaker 6ff1af
+					      phase, &comp_dir, &handled_strp);
DistroBaker 6ff1af
 	    }
DistroBaker 6ff1af
 	  else if ((t->tag == DW_TAG_compile_unit
DistroBaker 6ff1af
 		    || t->tag == DW_TAG_partial_unit)
DistroBaker 6ff1af
-		   && t->attr[i].attr == DW_AT_name
DistroBaker 6ff1af
-		   && form == DW_FORM_strp
DistroBaker 6ff1af
-		   && debug_sections[DEBUG_STR].data)
DistroBaker 6ff1af
+		   && ((form == DW_FORM_strp
DistroBaker 6ff1af
+			&& debug_sections[DEBUG_STR].data)
DistroBaker 6ff1af
+		       || (form == DW_FORM_line_strp
DistroBaker 6ff1af
+			   && debug_sections[DEBUG_LINE_STR].data))
DistroBaker 6ff1af
+		   && t->attr[i].attr == DW_AT_name)
DistroBaker 6ff1af
 	    {
DistroBaker 6ff1af
+	      bool line_strp = form == DW_FORM_line_strp;
DistroBaker 6ff1af
+
DistroBaker 6ff1af
 	      /* DW_AT_name is the primary file for this compile
DistroBaker 6ff1af
 		 unit. If starting with / it is a full path name.
DistroBaker 6ff1af
 		 Note that we don't handle DW_FORM_string in this
DistroBaker 6ff1af
@@ -1957,11 +2258,14 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
DistroBaker 6ff1af
 	      /* In phase zero we will look for a comp_dir to use.  */
DistroBaker 6ff1af
 	      if (phase == 0)
DistroBaker 6ff1af
 		{
DistroBaker 6ff1af
-		  if (idx >= debug_sections[DEBUG_STR].size)
DistroBaker 6ff1af
+		  debug_section *sec = &debug_sections[line_strp
DistroBaker 6ff1af
+						       ? DEBUG_LINE_STR
DistroBaker 6ff1af
+						       : DEBUG_STR];
DistroBaker 6ff1af
+		  if (idx >= sec->size)
DistroBaker 6ff1af
 		    error (1, 0,
DistroBaker 6ff1af
-			   "%s: Bad string pointer index %zd for unit name",
DistroBaker 6ff1af
-			   dso->filename, idx);
DistroBaker 6ff1af
-		  char *name = (char *) debug_sections[DEBUG_STR].data + idx;
DistroBaker 6ff1af
+			   "%s: Bad string pointer index %zd for unit name (%s)",
DistroBaker 6ff1af
+			   dso->filename, idx, sec->name);
DistroBaker 6ff1af
+		  char *name = (char *) sec->data + idx;
DistroBaker 6ff1af
 		  if (*name == '/' && comp_dir == NULL)
DistroBaker 6ff1af
 		    {
DistroBaker 6ff1af
 		      char *enddir = strrchr (name, '/');
DistroBaker 6ff1af
@@ -1982,8 +2286,13 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
DistroBaker 6ff1af
 		 pass (1) stores it (the new index). */
DistroBaker 6ff1af
 	      if (dest_dir && phase == 0)
DistroBaker 6ff1af
 		{
DistroBaker 6ff1af
-		  if (record_file_string_entry_idx (&dso->strings, idx))
DistroBaker 6ff1af
-		    need_strp_update = true;
DistroBaker 6ff1af
+		  if (record_file_string_entry_idx (line_strp, dso, idx))
DistroBaker 6ff1af
+		    {
DistroBaker 6ff1af
+		      if (line_strp)
DistroBaker 6ff1af
+			need_line_strp_update = true;
DistroBaker 6ff1af
+		      else
DistroBaker 6ff1af
+			need_strp_update = true;
DistroBaker 6ff1af
+		    }
DistroBaker 6ff1af
 		  handled_strp = true;
DistroBaker 6ff1af
 		}
DistroBaker 6ff1af
 	    }
DistroBaker 6ff1af
@@ -1991,7 +2300,10 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
DistroBaker 6ff1af
 	  switch (form)
DistroBaker 6ff1af
 	    {
DistroBaker 6ff1af
 	    case DW_FORM_strp:
DistroBaker 6ff1af
-	      edit_strp (dso, ptr, phase, handled_strp);
DistroBaker 6ff1af
+	      edit_strp (dso, false /* line_strp */, ptr, phase, handled_strp);
DistroBaker 6ff1af
+	      break;
DistroBaker 6ff1af
+	    case DW_FORM_line_strp:
DistroBaker 6ff1af
+	      edit_strp (dso, true /* line_strp */, ptr, phase, handled_strp);
DistroBaker 6ff1af
 	      break;
DistroBaker 6ff1af
 	    }
DistroBaker 6ff1af
 
DistroBaker 6ff1af
@@ -2196,11 +2508,11 @@ edit_info (DSO *dso, int phase, struct debug_section *sec)
DistroBaker 6ff1af
 
DistroBaker 6ff1af
 /* Rebuild .debug_str.  */
DistroBaker 6ff1af
 static void
DistroBaker 6ff1af
-edit_dwarf2_any_str (DSO *dso)
DistroBaker 6ff1af
+edit_dwarf2_any_str (DSO *dso, struct strings *strings, debug_section *secp)
DistroBaker 6ff1af
 {
DistroBaker 6ff1af
-  Strtab *strtab = dso->strings.str_tab;
DistroBaker 6ff1af
-  Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data;
DistroBaker 6ff1af
-  int strndx = debug_sections[DEBUG_STR].sec;
DistroBaker 6ff1af
+  Strtab *strtab = strings->str_tab;
DistroBaker 6ff1af
+  Elf_Data *strdata = secp->elf_data;
DistroBaker 6ff1af
+  int strndx = secp->sec;
DistroBaker 6ff1af
   Elf_Scn *strscn = dso->scn[strndx];
DistroBaker 6ff1af
 
DistroBaker 6ff1af
   /* Out with the old. */
DistroBaker 6ff1af
@@ -2212,8 +2524,8 @@ edit_dwarf2_any_str (DSO *dso)
DistroBaker 6ff1af
      but the old ebl version will just abort on out of
DistroBaker 6ff1af
      memory... */
DistroBaker 6ff1af
   strtab_finalize (strtab, strdata);
DistroBaker 6ff1af
-  debug_sections[DEBUG_STR].size = strdata->d_size;
DistroBaker 6ff1af
-  dso->strings.str_buf = strdata->d_buf;
DistroBaker 6ff1af
+  secp->size = strdata->d_size;
DistroBaker 6ff1af
+  strings->str_buf = strdata->d_buf;
DistroBaker 6ff1af
 }
DistroBaker 6ff1af
 
DistroBaker 6ff1af
 static int
DistroBaker 6ff1af
@@ -2359,12 +2671,14 @@ edit_dwarf2 (DSO *dso)
DistroBaker 6ff1af
   bool info_rel_updated = false;
DistroBaker 6ff1af
   bool types_rel_updated = false;
DistroBaker 6ff1af
   bool macro_rel_updated = false;
DistroBaker 6ff1af
+  bool line_rel_updated = false;
DistroBaker 6ff1af
 
DistroBaker 6ff1af
   for (phase = 0; phase < 2; phase++)
DistroBaker 6ff1af
     {
DistroBaker 6ff1af
       /* If we don't need to update anyhing, skip phase 1. */
DistroBaker 6ff1af
       if (phase == 1
DistroBaker 6ff1af
 	  && !need_strp_update
DistroBaker 6ff1af
+	  && !need_line_strp_update
DistroBaker 6ff1af
 	  && !need_string_replacement
DistroBaker 6ff1af
 	  && !need_stmt_update)
DistroBaker 6ff1af
 	break;
DistroBaker 6ff1af
@@ -2582,15 +2896,14 @@ edit_dwarf2 (DSO *dso)
DistroBaker 6ff1af
 		      if (phase == 0)
DistroBaker 6ff1af
 			{
DistroBaker 6ff1af
 			  size_t idx = read_32_relocated (ptr);
DistroBaker 6ff1af
-			  record_existing_string_entry_idx (&dso->strings,
DistroBaker 6ff1af
-							    idx);
DistroBaker 6ff1af
+			  record_existing_string_entry_idx (false, dso, idx);
DistroBaker 6ff1af
 			}
DistroBaker 6ff1af
 		      else
DistroBaker 6ff1af
 			{
DistroBaker 6ff1af
 			  struct stridxentry *entry;
DistroBaker 6ff1af
 			  size_t idx, new_idx;
DistroBaker 6ff1af
 			  idx = do_read_32_relocated (ptr);
DistroBaker 6ff1af
-			  entry = string_find_entry (&dso->strings, idx);
DistroBaker 6ff1af
+			  entry = string_find_entry (&dso->debug_str, idx);
DistroBaker 6ff1af
 			  new_idx = strent_offset (entry->entry);
DistroBaker 6ff1af
 			  write_32_relocated (ptr, new_idx);
DistroBaker 6ff1af
 			}
DistroBaker 6ff1af
@@ -2610,24 +2923,50 @@ edit_dwarf2 (DSO *dso)
DistroBaker 6ff1af
 	    }
DistroBaker 6ff1af
 	}
DistroBaker 6ff1af
 
DistroBaker 6ff1af
-      /* Same for the debug_str section. Make sure everything is
DistroBaker 6ff1af
-	 in place for phase 1 updating of debug_info
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+      /* Now handle all the DWARF5 line tables, they contain strp
DistroBaker 6ff1af
+	 and/or line_strp entries that need to be registered/rewritten.  */
DistroBaker 6ff1af
+      setup_relbuf(dso, &debug_sections[DEBUG_LINE], &reltype);
DistroBaker 6ff1af
+      rel_updated = false;
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+      /* edit_dwarf2_line will have set this up, unless there are no
DistroBaker 6ff1af
+	 moved/resized (DWARF4) lines. In which case we can just use
DistroBaker 6ff1af
+	 the original section data. new_idx will have been setup
DistroBaker 6ff1af
+	 correctly, even if it is the same as old_idx.  */
DistroBaker 6ff1af
+      unsigned char *line_buf = (unsigned char *)dso->lines.line_buf;
DistroBaker 6ff1af
+      if (line_buf == NULL)
DistroBaker 6ff1af
+	line_buf = debug_sections[DEBUG_LINE].data;
DistroBaker 6ff1af
+      for (int ldx = 0; ldx < dso->lines.used; ldx++)
DistroBaker 6ff1af
+	{
DistroBaker 6ff1af
+	  struct line_table *t = &dso->lines.table[ldx];
DistroBaker 6ff1af
+	  if (t->version >= 5)
DistroBaker 6ff1af
+	    read_dwarf5_line (dso, line_buf + t->new_idx, t, phase);
DistroBaker 6ff1af
+	}
DistroBaker 6ff1af
+      if (rel_updated)
DistroBaker 6ff1af
+	line_rel_updated = true;
DistroBaker 6ff1af
+
DistroBaker 6ff1af
+      /* Same for the debug_str and debug_line_str sections.
DistroBaker 6ff1af
+	 Make sure everything is in place for phase 1 updating of debug_info
DistroBaker 6ff1af
 	 references. */
DistroBaker 6ff1af
       if (phase == 0 && need_strp_update)
DistroBaker 6ff1af
-	edit_dwarf2_any_str (dso);
DistroBaker 6ff1af
-
DistroBaker 6ff1af
+	edit_dwarf2_any_str (dso, &dso->debug_str,
DistroBaker 6ff1af
+			     &debug_sections[DEBUG_STR]);
DistroBaker 6ff1af
+      if (phase == 0 && need_line_strp_update)
DistroBaker 6ff1af
+	edit_dwarf2_any_str (dso, &dso->debug_line_str,
DistroBaker 6ff1af
+			     &debug_sections[DEBUG_LINE_STR]);
DistroBaker 6ff1af
     }
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_line_strp_update
DistroBaker 6ff1af
+      || 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
+  if (need_stmt_update || need_line_strp_update)
DistroBaker 6ff1af
     dirty_section (DEBUG_LINE);
DistroBaker 6ff1af
 
DistroBaker 6ff1af
   /* Update any relocations addends we might have touched. */
DistroBaker 6ff1af
@@ -2653,6 +2992,9 @@ edit_dwarf2 (DSO *dso)
DistroBaker 6ff1af
 	}
DistroBaker 6ff1af
     }
DistroBaker 6ff1af
 
DistroBaker 6ff1af
+  if (line_rel_updated)
DistroBaker 6ff1af
+    update_rela_data (dso, &debug_sections[DEBUG_LINE]);
DistroBaker 6ff1af
+
DistroBaker 6ff1af
   return 0;
DistroBaker 6ff1af
 }
DistroBaker 6ff1af
 
DistroBaker 6ff1af
@@ -2745,7 +3087,8 @@ fdopen_dso (int fd, const char *name)
DistroBaker 6ff1af
     }
DistroBaker 6ff1af
 
DistroBaker 6ff1af
   dso->filename = (const char *) strdup (name);
DistroBaker 6ff1af
-  setup_strings (&dso->strings);
DistroBaker 6ff1af
+  setup_strings (&dso->debug_str);
DistroBaker 6ff1af
+  setup_strings (&dso->debug_line_str);
DistroBaker 6ff1af
   setup_lines (&dso->lines);
DistroBaker 6ff1af
   return dso;
DistroBaker 6ff1af
 
DistroBaker 6ff1af
@@ -2753,7 +3096,8 @@ error_out:
DistroBaker 6ff1af
   if (dso)
DistroBaker 6ff1af
     {
DistroBaker 6ff1af
       free ((char *) dso->filename);
DistroBaker 6ff1af
-      destroy_strings (&dso->strings);
DistroBaker 6ff1af
+      destroy_strings (&dso->debug_str);
DistroBaker 6ff1af
+      destroy_strings (&dso->debug_line_str);
DistroBaker 6ff1af
       destroy_lines (&dso->lines);
DistroBaker 6ff1af
       free (dso);
DistroBaker 6ff1af
     }
DistroBaker 6ff1af
@@ -3034,7 +3378,9 @@ main (int argc, char *argv[])
DistroBaker 6ff1af
      in elfutils before 0.169 we will have to update and write out all
DistroBaker 6ff1af
      section data if any data has changed (when ELF_F_LAYOUT was
DistroBaker 6ff1af
      set). https://sourceware.org/bugzilla/show_bug.cgi?id=21199 */
DistroBaker 6ff1af
-  bool need_update = need_strp_update || need_stmt_update;
DistroBaker 6ff1af
+  bool need_update = (need_strp_update
DistroBaker 6ff1af
+		      || need_line_strp_update
DistroBaker 6ff1af
+		      || need_stmt_update);
DistroBaker 6ff1af
 
DistroBaker 6ff1af
 #if !_ELFUTILS_PREREQ (0, 169)
DistroBaker 6ff1af
   /* string replacements or build_id updates don't change section size. */
DistroBaker 6ff1af
@@ -3106,10 +3452,12 @@ main (int argc, char *argv[])
DistroBaker 6ff1af
 	      GElf_Xword sec_size = shdr->sh_size;
DistroBaker 6ff1af
 
DistroBaker 6ff1af
 	      /* We might have changed the size (and content) of the
DistroBaker 6ff1af
-		 debug_str or debug_line section. */
DistroBaker 6ff1af
+		 debug_str, debug_line_str or debug_line section. */
DistroBaker 6ff1af
 	      size_t secnum = elf_ndxscn (scn);
DistroBaker 6ff1af
 	      if (secnum == debug_sections[DEBUG_STR].sec)
DistroBaker 6ff1af
 		sec_size = debug_sections[DEBUG_STR].size;
DistroBaker 6ff1af
+	      if (secnum == debug_sections[DEBUG_LINE_STR].sec)
DistroBaker 6ff1af
+		sec_size = debug_sections[DEBUG_LINE_STR].size;
DistroBaker 6ff1af
 	      if (secnum == debug_sections[DEBUG_LINE].sec)
DistroBaker 6ff1af
 		sec_size = debug_sections[DEBUG_LINE].size;
DistroBaker 6ff1af
 
DistroBaker 6ff1af
@@ -3179,7 +3527,8 @@ main (int argc, char *argv[])
DistroBaker 6ff1af
   chmod (file, stat_buf.st_mode);
DistroBaker 6ff1af
 
DistroBaker 6ff1af
   free ((char *) dso->filename);
DistroBaker 6ff1af
-  destroy_strings (&dso->strings);
DistroBaker 6ff1af
+  destroy_strings (&dso->debug_str);
DistroBaker 6ff1af
+  destroy_strings (&dso->debug_line_str);
DistroBaker 6ff1af
   destroy_lines (&dso->lines);
DistroBaker 6ff1af
   free (dso);
DistroBaker 6ff1af
 
DistroBaker 6ff1af
-- 
DistroBaker 6ff1af
2.18.4
DistroBaker 6ff1af