This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Commit: Add ability to follow dwo links to readelf & objdump


Hi Guys,

  I have now extended the --debug=follow-links option of readelf and
  objdump so that it can also follow links to separate dwarf object
  files (dwo).  Next up - the BFD library ...

Cheers
  Nick

binutils/ChangeLog
2017-11-21  Nick Clifton  <nickc@redhat.com>

	* dwarf.c (dwo_name, dwo_dir, dwo_id, dwo_id_len): New variables.
	(read_and_display_attr_value): Record dwo variables if requested.
	(display_augmentation_data): Rename to display_data and make
	generic.
	(load_dwo_file): New function.  Loads a separate dwarf object
	file.
	(load_separate_debug_file): Add reporting and loading of separate
	dwarf objet files.
	* readelf.c (process_section_headers): Add do_debug_links to list
	of flags requiring a debug dump.
	(display_debug_section): Tidy up code.
	* doc/debug.options.texi: Add note that dwo links will also be
	followed.
	* testsuite/binutils-all/debuglink.s: Tidy code.
	* testsuite/binutils-all/dwo.s: New test file.
	* testsuite/binutils-all/readelf.wk2: New file - expected output
	from readelf.
	* testsuite/binutils-all/readelf.exp: Run the new test.

diff --git a/binutils/doc/debug.options.texi b/binutils/doc/debug.options.texi
index 9204b2bec4..57945654d2 100644
--- a/binutils/doc/debug.options.texi
+++ b/binutils/doc/debug.options.texi
@@ -45,7 +45,10 @@ output from this option can also be restricted by the use of the
 @item k
 @itemx =links
 Displays the contents of the @samp{.gnu_debuglink} and/or
-@samp{.gnu_debugaltlink} sections.
+@samp{.gnu_debugaltlink} sections.  Also displays the link to a
+separate dwarf object file (dwo), if one is specified by the 
+DW_AT_GNU_dwo_name or DW_AT_dwo_name attributes in the
+@samp{.debug_info} section.
 
 @item K
 @itemx =follow-links
@@ -55,9 +58,9 @@ versions of the same debug section being displayed if both the main
 file and the separate debug info file contain sections with the same
 name.
 
-When displaying other debug information, if a link is encountered to
-a separate debug info file, then attempt to follow the link and
-display the referenced contents.
+In addition, when displaying DWARF attributes, if a form is found that
+references the separate debug info file, then the referenced contents
+will also be displayed.
 
 @item l
 @itemx =rawline
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index e6f6a43ef6..4be380d095 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -48,6 +48,12 @@ static debug_info *debug_information = NULL;
    that the .debug_info section could not be loaded/parsed.  */
 #define DEBUG_INFO_UNAVAILABLE  (unsigned int) -1
 
+static const char *           dwo_name;
+static const char *           dwo_dir;
+static const unsigned char *  dwo_id;
+static bfd_size_type          dwo_id_len;
+static bfd_boolean            need_dwo_info;
+
 unsigned int eh_addr_size;
 
 int do_debug_info;
@@ -731,7 +737,7 @@ fetch_indirect_line_string (dwarf_vma offset)
 
 static const char *
 fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set,
-		      dwarf_vma offset_size, int dwo)
+		      dwarf_vma offset_size, bfd_boolean dwo)
 {
   enum dwarf_section_display_enum str_sec_idx = dwo ? str_dwo : str;
   enum dwarf_section_display_enum idx_sec_idx = dwo ? str_index_dwo : str_index;
@@ -1369,21 +1375,21 @@ decode_location_expression (unsigned char * data,
 	  printf ("DW_OP_push_object_address");
 	  break;
 	case DW_OP_call2:
-	  /* XXX: Strictly speaking for 64-bit DWARF3 files
+	  /* FIXME: Strictly speaking for 64-bit DWARF3 files
 	     this ought to be an 8-byte wide computation.  */
 	  SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end);
 	  printf ("DW_OP_call2: <0x%s>",
 		  dwarf_vmatoa ("x", svalue + cu_offset));
 	  break;
 	case DW_OP_call4:
-	  /* XXX: Strictly speaking for 64-bit DWARF3 files
+	  /* FIXME: Strictly speaking for 64-bit DWARF3 files
 	     this ought to be an 8-byte wide computation.  */
 	  SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 4, end);
 	  printf ("DW_OP_call4: <0x%s>",
 		  dwarf_vmatoa ("x", svalue + cu_offset));
 	  break;
 	case DW_OP_call_ref:
-	  /* XXX: Strictly speaking for 64-bit DWARF3 files
+	  /* FIXME: Strictly speaking for 64-bit DWARF3 files
 	     this ought to be an 8-byte wide computation.  */
 	  if (dwarf_version == -1)
 	    {
@@ -1452,7 +1458,7 @@ decode_location_expression (unsigned char * data,
 	  break;
 	case DW_OP_implicit_pointer:
 	case DW_OP_GNU_implicit_pointer:
-	  /* XXX: Strictly speaking for 64-bit DWARF3 files
+	  /* FIXME: Strictly speaking for 64-bit DWARF3 files
 	     this ought to be an 8-byte wide computation.  */
 	  if (dwarf_version == -1)
 	    {
@@ -1713,6 +1719,32 @@ fetch_alt_indirect_string (dwarf_vma offset)
   return ret;
 }
 	
+static const char *
+get_AT_name (unsigned long attribute)
+{
+  const char *name;
+
+  if (attribute == 0)
+    return "DW_AT value: 0";
+
+  /* One value is shared by the MIPS and HP extensions:  */
+  if (attribute == DW_AT_MIPS_fde)
+    return "DW_AT_MIPS_fde or DW_AT_HP_unmodifiable";
+
+  name = get_DW_AT_name (attribute);
+
+  if (name == NULL)
+    {
+      static char buffer[100];
+
+      snprintf (buffer, sizeof (buffer), _("Unknown AT value: %lx"),
+		attribute);
+      return buffer;
+    }
+
+  return name;
+}
+
 static unsigned char *
 read_and_display_attr_value (unsigned long           attribute,
 			     unsigned long           form,
@@ -2036,8 +2068,8 @@ read_and_display_attr_value (unsigned long           attribute,
     case DW_FORM_GNU_str_index:
       if (!do_loc)
 	{
-	  const char *suffix = strrchr (section->name, '.');
-	  int dwo = (suffix && strcmp (suffix, ".dwo") == 0) ? 1 : 0;
+	  const char * suffix = strrchr (section->name, '.');
+	  bfd_boolean  dwo = (suffix && strcmp (suffix, ".dwo") == 0) ? TRUE : FALSE;
 
 	  printf (_("%c(indexed string: 0x%s): %s"), delimiter,
 		  dwarf_vmatoa ("x", uvalue),
@@ -2188,6 +2220,63 @@ read_and_display_attr_value (unsigned long           attribute,
 	    }
 	  break;
 
+	case DW_AT_GNU_dwo_name:
+	case DW_AT_dwo_name:
+	  if (need_dwo_info)
+	    switch (form)
+	      {
+	      case DW_FORM_strp:
+		dwo_name = (const char *) fetch_indirect_string (uvalue);
+		break;
+	      case DW_FORM_GNU_str_index:
+		dwo_name = fetch_indexed_string (uvalue, this_set, offset_size, FALSE);
+		break;
+	      default:
+		warn (_("Unsupported form (%s) for attribute %s\n"),
+		      get_FORM_name (form), get_AT_name (attribute));
+		dwo_name = _("<unknown>");
+		break;
+	      }
+	  break;
+	      
+	case DW_AT_comp_dir:
+	  /* FIXME: Also extract a build-id in a CU/TU.  */
+	  if (need_dwo_info)
+	    switch (form)
+	      {
+	      case DW_FORM_strp:
+		dwo_dir = (const char *) fetch_indirect_string (uvalue);
+		break;
+	      case DW_FORM_line_strp:
+		dwo_dir = (const char *) fetch_indirect_line_string (uvalue);
+		break;
+	      case DW_FORM_GNU_str_index:
+		dwo_dir = fetch_indexed_string (uvalue, this_set, offset_size, FALSE);
+		break;
+	      default:
+		warn (_("Unsupported form (%s) for attribute %s\n"),
+		      get_FORM_name (form), get_AT_name (attribute));
+		dwo_dir = _("<unknown>");
+		break;
+	      }
+	  break;
+	      
+	case DW_AT_GNU_dwo_id:
+	  if (need_dwo_info)
+	    switch (form)
+	      {
+	      case DW_FORM_data8:
+		dwo_id = data - 8;
+		dwo_id_len = 8;
+		break;
+	      default:
+		warn (_("Unsupported form (%s) for attribute %s\n"),
+		      get_FORM_name (form), get_AT_name (attribute));
+		dwo_id = NULL;
+		break;
+	      }
+	  break;
+	      
 	default:
 	  break;
 	}
@@ -2540,32 +2629,6 @@ read_and_display_attr_value (unsigned long           attribute,
   return data;
 }
 
-static const char *
-get_AT_name (unsigned long attribute)
-{
-  const char *name;
-
-  if (attribute == 0)
-    return "DW_AT value: 0";
-
-  /* One value is shared by the MIPS and HP extensions:  */
-  if (attribute == DW_AT_MIPS_fde)
-    return "DW_AT_MIPS_fde or DW_AT_HP_unmodifiable";
-
-  name = get_DW_AT_name (attribute);
-
-  if (name == NULL)
-    {
-      static char buffer[100];
-
-      snprintf (buffer, sizeof (buffer), _("Unknown AT value: %lx"),
-		attribute);
-      return buffer;
-    }
-
-  return name;
-}
-
 static unsigned char *
 read_and_display_attr (unsigned long           attribute,
 		       unsigned long           form,
@@ -2642,17 +2705,22 @@ introduce (struct dwarf_section * section, bfd_boolean raw)
     }
 }
   
-/* Process the contents of a .debug_info section.  If do_loc is non-zero
-   then we are scanning for location lists and we do not want to display
-   anything to the user.  If do_types is non-zero, we are processing
-   a .debug_types section instead of a .debug_info section.  */
+/* Process the contents of a .debug_info section.
+   If do_loc is TRUE then we are scanning for location lists and dwo tags
+   and we do not want to display anything to the user.
+   If do_types is TRUE, we are processing a .debug_types section instead of
+   a .debug_info section.
+   The information displayed is restricted by the values in DWARF_START_DIE
+   and DWARF_CUTOFF_LEVEL.
+   Returns TRUE upon success.  Otherwise an error or warning message is
+   printed and FALSE is returned.  */
 
-static int
-process_debug_info (struct dwarf_section *section,
-		    void *file,
-		    enum dwarf_section_display_enum abbrev_sec,
-		    int do_loc,
-		    int do_types)
+static bfd_boolean
+process_debug_info (struct dwarf_section *           section,
+		    void *                           file,
+		    enum dwarf_section_display_enum  abbrev_sec,
+		    bfd_boolean                      do_loc,
+		    bfd_boolean                      do_types)
 {
   unsigned char *start = section->start;
   unsigned char *end = start + section->size;
@@ -2684,7 +2752,7 @@ process_debug_info (struct dwarf_section *section,
 	    {
 	      warn (_("Reserved length value (0x%s) found in section %s\n"),
 		    dwarf_vmatoa ("x", length), section->name);
-	      return 0;
+	      return FALSE;
 	    }
 	  else
 	    section_begin += length + 4;
@@ -2696,14 +2764,14 @@ process_debug_info (struct dwarf_section *section,
 	    {
 	      warn (_("Corrupt unit length (0x%s) found in section %s\n"),
 		    dwarf_vmatoa ("x", length), section->name);
-	      return 0;
+	      return FALSE;
 	    }
 	}
 
       if (num_units == 0)
 	{
 	  error (_("No comp units in %s section ?\n"), section->name);
-	  return 0;
+	  return FALSE;
 	}
 
       /* Then allocate an array to hold the information.  */
@@ -2714,8 +2782,9 @@ process_debug_info (struct dwarf_section *section,
 	  error (_("Not enough memory for a debug info array of %u entries\n"),
 		 num_units);
 	  alloc_num_debug_info_entries = num_debug_info_entries = 0;
-	  return 0;
+	  return FALSE;
 	}
+
       /* PR 17531: file: 92ca3797.
 	 We cannot rely upon the debug_information array being initialised
 	 before it is used.  A corrupt file could easily contain references
@@ -2741,7 +2810,7 @@ process_debug_info (struct dwarf_section *section,
     {
       warn (_("Unable to locate %s section!\n"),
 	    debug_displays [abbrev_sec].section.uncompressed_name);
-      return 0;
+      return FALSE;
     }
 
   if (!do_loc && dwarf_start_die == 0)
@@ -3008,7 +3077,7 @@ process_debug_info (struct dwarf_section *section,
 		    }
 		}
 	      if (dwarf_start_die != 0 && level < saved_level)
-		return 1;
+		return TRUE;
 	      continue;
 	    }
 
@@ -3048,7 +3117,7 @@ process_debug_info (struct dwarf_section *section,
 		}
 	      warn (_("DIE at offset 0x%lx refers to abbreviation number %lu which does not exist\n"),
 		    die_offset, abbrev_number);
-	      return 0;
+	      return FALSE;
 	    }
 
 	  if (!do_loc && do_printing)
@@ -3060,7 +3129,8 @@ process_debug_info (struct dwarf_section *section,
 	      need_base_address = 0;
 	      break;
 	    case DW_TAG_compile_unit:
-	      need_base_address = 1;
+	      need_base_address = 1;	
+	      need_dwo_info = do_loc;
 	      break;
 	    case DW_TAG_entry_point:
 	    case DW_TAG_subprogram:
@@ -3146,7 +3216,7 @@ process_debug_info (struct dwarf_section *section,
   if (!do_loc)
     printf ("\n");
 
-  return 1;
+  return TRUE;
 }
 
 /* Locate and scan the .debug_info section in the file and record the pointer
@@ -3171,12 +3241,12 @@ load_debug_info (void * file)
   (void) load_cu_tu_indexes (file);
 
   if (load_debug_section_with_follow (info, file)
-      && process_debug_info (&debug_displays [info].section, file, abbrev, 1, 0))
+      && process_debug_info (&debug_displays [info].section, file, abbrev, TRUE, FALSE))
     return num_debug_info_entries;
 
   if (load_debug_section_with_follow (info_dwo, file)
       && process_debug_info (&debug_displays [info_dwo].section, file,
-			     abbrev_dwo, 1, 0))
+			     abbrev_dwo, TRUE, FALSE))
     return num_debug_info_entries;
 
   num_debug_info_entries = DEBUG_INFO_UNAVAILABLE;
@@ -6161,19 +6231,19 @@ display_debug_str (struct dwarf_section *section,
 static int
 display_debug_info (struct dwarf_section *section, void *file)
 {
-  return process_debug_info (section, file, section->abbrev_sec, 0, 0);
+  return process_debug_info (section, file, section->abbrev_sec, FALSE, FALSE);
 }
 
 static int
 display_debug_types (struct dwarf_section *section, void *file)
 {
-  return process_debug_info (section, file, section->abbrev_sec, 0, 1);
+  return process_debug_info (section, file, section->abbrev_sec, FALSE, TRUE);
 }
 
 static int
 display_trace_info (struct dwarf_section *section, void *file)
 {
-  return process_debug_info (section, file, section->abbrev_sec, 0, 0);
+  return process_debug_info (section, file, section->abbrev_sec, FALSE, TRUE);
 }
 
 static int
@@ -7227,29 +7297,40 @@ read_cie (unsigned char *start, unsigned char *end,
   return start;
 }
 
-/* Prints out the contents on the augmentation data array.
-   If do_wide is not enabled, then formats the output to fit into 80 columns.  */
+/* Prints out the contents on the DATA array formatted as unsigned bytes.
+   If do_wide is not enabled, then formats the output to fit into 80 columns.
+   PRINTED contains the number of characters already written to the current
+   output line.  */
 
 static void
-display_augmentation_data (const unsigned char * data, const bfd_size_type len)
+display_data (bfd_size_type          printed,
+	      const unsigned char *  data,
+	      const bfd_size_type    len)
 {
-  bfd_size_type i;
-
-  i = printf (_("  Augmentation data:    "));
-
-  if (do_wide || len < ((80 - i) / 3))
-    for (i = 0; i < len; ++i)
-      printf (" %02x", data[i]);
+  if (do_wide || len < ((80 - printed) / 3))
+    for (printed = 0; printed < len; ++printed)
+      printf (" %02x", data[printed]);
   else
     {
-      for (i = 0; i < len; ++i)
+      for (printed = 0; printed < len; ++printed)
 	{
-	  if (i % (80 / 3) == 0)
+	  if (printed % (80 / 3) == 0)
 	    putchar ('\n');
-	  printf (" %02x", data[i]);
+	  printf (" %02x", data[printed]);
 	}
     }
-  putchar ('\n');
+}
+
+/* Prints out the contents on the augmentation data array.
+   If do_wide is not enabled, then formats the output to fit into 80 columns.  */
+
+static void
+display_augmentation_data (const unsigned char * data, const bfd_size_type len)
+{
+  bfd_size_type i;
+
+  i = printf (_("  Augmentation data:    "));
+  display_data (i, data, len);
 }
 
 static int
@@ -8550,8 +8631,8 @@ display_debug_names (struct dwarf_section *section, void *file)
 }
 
 static int
-display_debug_links (struct dwarf_section * section,
-		     void * file ATTRIBUTE_UNUSED)
+display_debug_links (struct dwarf_section *  section,
+		     void *                  file ATTRIBUTE_UNUSED)
 {
   const unsigned char * filename;
   unsigned int          filelen;
@@ -8615,19 +8696,7 @@ display_debug_links (struct dwarf_section * section,
 	}
 
       printed = printf (_("  Build-ID (%#lx bytes):"), (long) build_id_len);
-
-      if (do_wide || build_id_len < ((80 - printed) / 3))
-	for (printed = 0; printed < build_id_len; ++printed)
-	  printf (" %02x", build_id[printed]);
-      else
-	{
-	  for (printed = 0; printed < build_id_len; ++printed)
-	    {
-	      if (printed % (80 / 3) == 0)
-		putchar ('\n');
-	      printf (" %02x", build_id[printed]);
-	    }
-	}
+      display_data (printed, build_id, build_id_len);
       putchar ('\n');
     }
 
@@ -9723,6 +9792,33 @@ load_separate_debug_info (const char *            main_filename,
   return separate_debug_file;
 }
 
+/* Attempt to load a separate dwarf object file.  */
+
+static void *
+load_dwo_file (const char * main_filename)
+{
+  char * filename;
+
+  /* FIXME: Skip adding / if dwo_dir ends in /.  */
+  filename = concat (dwo_dir, "/", dwo_name, NULL);
+  if (filename == NULL)
+    {
+      warn (_("Out of memory allocating dwo filename\n"));
+      return NULL;
+    }
+
+  if ((separate_debug_file = open_debug_file (filename)) == NULL)
+    {
+      warn (_("Unable to load dwo file: %s\n"), filename);
+      free (filename);
+      return NULL;
+    }
+
+  printf (_("%s: Found separate debug object file: %s\n\n"), main_filename, filename);
+  separate_debug_filename = filename;
+  return separate_debug_file;
+}
+
 /* Load a separate debug info file, if it exists.
    Returns the data pointer that is the result of calling open_debug_file
    on the separate debug info file.  */
@@ -9730,6 +9826,38 @@ load_separate_debug_info (const char *            main_filename,
 void *
 load_separate_debug_file (void * file, const char * filename)
 {
+  /* See if there is a dwo link.  */
+  if (load_debug_section (str, file)
+      && load_debug_section (abbrev, file)
+      && load_debug_section (info, file))
+    {
+      dwo_name = dwo_dir = NULL;
+      dwo_id = NULL;
+      dwo_id_len = 0;
+
+      if (process_debug_info (& debug_displays[info].section, file, abbrev, TRUE, FALSE))
+	{
+	  if (dwo_name != NULL)
+	    {
+	      if (do_debug_links)
+		{
+		  printf (_("The %s section contains a link to a dwo file:\n"),
+			  debug_displays [info].section.uncompressed_name);
+		  printf (_("  Name:      %s\n"), dwo_name);
+		  printf (_("  Directory: %s\n"), dwo_dir ? dwo_dir : _("<not-found>"));
+		  if (dwo_id != NULL)
+		    display_data (printf (_("  ID:       ")), dwo_id, dwo_id_len);
+		  else
+		    printf (_("  ID: <unknown>\n"));
+		  printf ("\n\n");
+		}
+
+	      if (do_follow_links)
+		return load_dwo_file (filename);
+	    }
+	}
+    }
+
   if (! do_follow_links)
     return NULL;
 
@@ -9737,7 +9865,6 @@ load_separate_debug_file (void * file, const char * filename)
   /* FIXME: We do not check the separate debug info file to see if it too contains debuglinks.  */
   /* FIXME: We do not check for the presence of multiple, same-name debuglink sections.  */
 
-  /* We try the alt version first as that is blessed by the DWARF5 standard.  */
   if (load_debug_section (gnu_debugaltlink, file))
     {
       Build_id_data * build_id_data;
diff --git a/binutils/readelf.c b/binutils/readelf.c
index b1130a77e6..481673a208 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -6084,7 +6084,7 @@ process_section_headers (Filedata * filedata)
 		|| do_debug_lines || do_debug_pubnames || do_debug_pubtypes
 		|| do_debug_aranges || do_debug_frames || do_debug_macinfo
 		|| do_debug_str || do_debug_loc || do_debug_ranges
-		|| do_debug_addr || do_debug_cu_index)
+		|| do_debug_addr || do_debug_cu_index || do_debug_links)
 	       && (const_strneq (name, ".debug_")
                    || const_strneq (name, ".zdebug_")))
 	{
@@ -13497,40 +13497,43 @@ display_debug_section (int shndx, Elf_Internal_Shdr * section, Filedata * fileda
 
   /* See if we know how to display the contents of this section.  */
   for (i = 0; i < max; i++)
-    if (streq (debug_displays[i].section.uncompressed_name, name)
-	|| (i == line && const_strneq (name, ".debug_line."))
-        || streq (debug_displays[i].section.compressed_name, name))
-      {
-	struct dwarf_section * sec = &debug_displays [i].section;
-	int secondary = (section != find_section (filedata, name));
+    {
+      enum dwarf_section_display_enum  id = (enum dwarf_section_display_enum) i;
+      struct dwarf_section_display *   display = debug_displays + i;
+      struct dwarf_section *           sec = & display->section;
 
-	if (secondary)
-	  free_debug_section ((enum dwarf_section_display_enum) i);
+      if (streq (sec->uncompressed_name, name)
+	  || (id == line && const_strneq (name, ".debug_line."))
+	  || streq (sec->compressed_name, name))
+	{
+	  bfd_boolean secondary = (section != find_section (filedata, name));
 
-	if (i == line && const_strneq (name, ".debug_line."))
-	  sec->name = name;
-	else if (streq (sec->uncompressed_name, name))
-	  sec->name = sec->uncompressed_name;
-	else
-	  sec->name = sec->compressed_name;
+	  if (secondary)
+	    free_debug_section (id);
 
-	if (load_specific_debug_section ((enum dwarf_section_display_enum) i,
-                                         section, filedata))
-	  {
-	    /* If this debug section is part of a CU/TU set in a .dwp file,
-	       restrict load_debug_section to the sections in that set.  */
-	    section_subset = find_cu_tu_set (filedata, shndx);
+	  if (i == line && const_strneq (name, ".debug_line."))
+	    sec->name = name;
+	  else if (streq (sec->uncompressed_name, name))
+	    sec->name = sec->uncompressed_name;
+	  else
+	    sec->name = sec->compressed_name;
 
-	    result &= debug_displays[i].display (sec, filedata);
+	  if (load_specific_debug_section (id, section, filedata))
+	    {
+	      /* If this debug section is part of a CU/TU set in a .dwp file,
+		 restrict load_debug_section to the sections in that set.  */
+	      section_subset = find_cu_tu_set (filedata, shndx);
 
-	    section_subset = NULL;
+	      result &= display->display (sec, filedata);
 
-	    if (secondary || (i != info && i != abbrev))
-	      free_debug_section ((enum dwarf_section_display_enum) i);
-	  }
+	      section_subset = NULL;
 
-	break;
-      }
+	      if (secondary || (id != info && id != abbrev))
+		free_debug_section (id);
+	    }
+	  break;
+	}
+    }
 
   if (i == max)
     {
diff --git a/binutils/testsuite/binutils-all/debuglink.s b/binutils/testsuite/binutils-all/debuglink.s
index a3691a03c3..8d52de2eac 100644
--- a/binutils/testsuite/binutils-all/debuglink.s
+++ b/binutils/testsuite/binutils-all/debuglink.s
@@ -17,14 +17,14 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 	
-/* Create a fake .gnu_debuglink section.  */
+	/* Create a fake .gnu_debuglink section.  */
 
 	.section .gnu_debuglink,"",%progbits
 	.asciz "this_is_a_debuglink.debug"
 	.balign 4
 	.4byte 0x12345678
 
-/* Create a fake .gnu_debugaltlink section.  */
+	/* Create a fake .gnu_debugaltlink section.  */
 
 	.section .gnu_debugaltlink,"",%progbits
 	.asciz "linkdebug.debug"
@@ -32,9 +32,9 @@
 	.dc.b 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
 	.dc.b 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
    
-/* Create a .debug_str section for local use.  This is also to check
-   the ability to dump the same section twice, if it exists in
-   both the main file and the separate debug info file.  */
+	/* Create a .debug_str section for local use.  This is also to check
+	   the ability to dump the same section twice, if it exists in
+	   both the main file and the separate debug info file.  */
 
 	.section	.debug_str,"MS",%progbits,1
 string1:
@@ -43,9 +43,9 @@ string1:
 	.balign	2
 string_end:
 	
-/* Create a .debug_info section that contains strings references into the
-   separate debug info file.  Plus the abbreviations are stored in the
-   separate file too...  */
+	/* Create a .debug_info section that contains strings references into
+	   the separate debug info file.  Plus the abbreviations are stored
+	   in the separate file too...  */
 
 	.section	.debug_info,"",%progbits
 	.4byte	debugE - debugS	;# Length of Compilation Unit Info

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]