Add ability to follow dwo links to readelf/objdump.
authorNick Clifton <nickc@redhat.com>
Tue, 21 Nov 2017 13:12:04 +0000 (13:12 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 21 Nov 2017 13:12:04 +0000 (13:12 +0000)
* 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.

binutils/ChangeLog
binutils/doc/debug.options.texi
binutils/dwarf.c
binutils/readelf.c
binutils/testsuite/binutils-all/debuglink.s
binutils/testsuite/binutils-all/dwo.s [new file with mode: 0644]
binutils/testsuite/binutils-all/readelf.exp
binutils/testsuite/binutils-all/readelf.k2 [new file with mode: 0644]

index 2f4c0d80a5b7c1e7d8b7af40ed361c26e436800f..c6a20e100583ec51a250333add24e5560a238506 100644 (file)
@@ -1,3 +1,24 @@
+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.
+
 2017-11-18  Alan Modra  <amodra@gmail.com>
 
        PR 22443
index 9204b2bec4ab64cf52d77a7bf521a13c9afb1e17..57945654d2d86fb0abcc05f16adbe1da2c965521 100644 (file)
@@ -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
index e6f6a43ef6bda2117bbb7698c337bd2bcbd79880..8b968797af5c4275add5e79a8bf4fd2d5a209eba 100644 (file)
@@ -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,69 @@ 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;
+             case DW_FORM_string:
+               dwo_name = (const char *) orig_data;
+               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;
+             case DW_FORM_string:
+               dwo_dir = (const char *) orig_data;
+               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 +2635,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 +2711,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 +2758,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 +2770,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 +2788,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 +2816,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 +3083,7 @@ process_debug_info (struct dwarf_section *section,
                    }
                }
              if (dwarf_start_die != 0 && level < saved_level)
-               return 1;
+               return TRUE;
              continue;
            }
 
@@ -3048,7 +3123,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 +3135,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 +3222,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 +3247,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 +6237,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 +7303,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 +8637,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 +8702,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,21 +9798,84 @@ 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;
+    }
+
+  /* FIXME: We should check the dwo_id.  */
+
+  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.  */
+   on the separate debug info file, or NULL if there were problems or there
+   is no such file.  */
 
 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");
+               }
+
+             /* FIXME: We do not check to see if there are any more dwo links in the file...  */
+             if (do_follow_links)
+               return load_dwo_file (filename);
+           }
+       }
+    }
+
   if (! do_follow_links)
     return NULL;
 
   /* FIXME: We do not check for the presence of both link sections in the same file.  */
   /* 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.  */
+  /* FIXME: We do not check for the presence of a dwo link as well as a debuglink.  */
 
-  /* 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;
index a372620c660fb81e19d3d5044497b72f9cea4488..ea7cc3e18eefe110b1fc0b03592346731f8399c8 100644 (file)
@@ -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_")))
        {
@@ -13658,40 +13658,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)
     {
index a3691a03c39a603d21f63d560f25a75ac1aca7a4..daabf7a3f1180167a07c494ad1f72334d659343c 100644 (file)
    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 string 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
diff --git a/binutils/testsuite/binutils-all/dwo.s b/binutils/testsuite/binutils-all/dwo.s
new file mode 100644 (file)
index 0000000..0d13471
--- /dev/null
@@ -0,0 +1,84 @@
+/* Assembler source used to create an object file for testing readelf's
+   and objdump's ability to process separate dwarf object files.
+
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+       
+       /* 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:
+       .asciz  "debugfile.dwo"
+string2:
+       .asciz  "/path/to/dwo/files"
+string3:
+       .asciz  "/another/path/"
+       .balign 2
+string_end:
+       
+       /* Create a .debug_info section that contains the dwo links.  */
+
+       .section        .debug_info,"",%progbits
+       .4byte  debugE - debugS ;# Length of Compilation Unit Info
+debugS:
+       .short  0x4     ;# DWARF version number.
+       .4byte  0x0     ;# Offset into .debug_abbrev section.
+       .byte   0x4     ;# Pointer Size (in bytes).
+
+       .uleb128 0x1    ;# Use abbrev #1.  This needs strings from the .debug_str section.
+       .4byte  string1
+       .4byte  string2
+
+       .uleb128 0x2    ;# Use abbrev #2.
+       .asciz   "file.dwo"
+       .4byte   string3
+       .8byte   0x12345678aabbccdd
+
+       ;# Minimal section alignment on alpha-* is 2, so ensure no new invalid CU
+       ;# will be started.
+       .balign 2, 0
+debugE:
+
+       .section        .debug_abbrev,"",%progbits
+
+       /* Create an abbrev containing a DWARF5 style dwo link.  */
+       .uleb128 0x01   ;# Abbrev code.
+       .uleb128 0x11   ;# DW_TAG_compile_unit
+       .byte    0x00   ;# DW_children_no
+       .uleb128 0x76   ;# DW_AT_dwo_name
+       .uleb128 0x0e   ;# DW_FORM_strp
+       .uleb128 0x1b   ;# DW_AT_comp_dir
+       .uleb128 0x0e   ;# DW_FORM_strp
+       .byte    0x00   ;# End of abbrev
+       .byte    0x00
+
+       /* Create an abbrev containing a GNU style dwo link.  */
+       .uleb128 0x02   ;# Abbrev code.
+       .uleb128 0x11   ;# DW_TAG_compile_unit
+       .byte    0x00   ;# DW_children_no
+       .uleb128 0x2130 ;# DW_AT_GNU_dwo_name
+       .uleb128 0x08   ;# DW_FORM_string
+       .uleb128 0x1b   ;# DW_AT_comp_dir
+       .uleb128 0x0e   ;# DW_FORM_strp
+       .uleb128 0x2131 ;# DW_AT_GNU_dwo_id
+       .uleb128 0x07   ;# DW_FORM_data8        
+       .byte    0x00   ;# End of abbrev
+       .byte    0x00
+
+       .byte    0x0    ;# Abbrevs terminator
+
index fdb310ca193111248fa04b44d055e20bcc30183a..f12625501a97663dbc0c369eaa176ae4b517a472 100644 (file)
@@ -469,7 +469,7 @@ if {![binutils_assemble_flags $srcdir/$subdir/dwarf-attributes.S tmpdir/dwarf-at
 
 # Check that debug link sections can be dumped.
 if {![binutils_assemble $srcdir/$subdir/debuglink.s tmpdir/debuglink.o]} then {
-    unresolved "readelf --debug-dump=links (failed to assemble)"
+    unresolved "readelf --debug-dump=links (failed to assemble debuglink.s)"
 } else {
     if ![is_remote host] {
        set tempfile tmpdir/debuglink.o
@@ -478,23 +478,29 @@ if {![binutils_assemble $srcdir/$subdir/debuglink.s tmpdir/debuglink.o]} then {
     }
 
     readelf_test {--debug-dump=links} $tempfile readelf.k  {}
-}
 
-# Check that debug link sections can be followed.
-if {![binutils_assemble $srcdir/$subdir/debuglink.s tmpdir/debuglink.o]} then {
-    unresolved "readelf --debug-dump=follow-links (failed to assemble1)"
-} else {
+    # Check that debug link sections can be followed.
     if {![binutils_assemble $srcdir/$subdir/linkdebug.s tmpdir/linkdebug.debug]} then {
-       unresolved "readelf --debug-dump=follow-links (failed to assemble2)"
+       unresolved "readelf --debug-dump=follow-links (failed to assemble linkdebug.s)"
     } else {
-       if ![is_remote host] {
-           set tempfile tmpdir/debuglink.o
-       } else {
-           set tempfile [remote_download host tmpdir/linkdebug.debug]
-           set tempfile [remote_download host tmpdir/debuglink.o]
+       if [is_remote host] {
+           set tempfile2 [remote_download host tmpdir/linkdebug.debug]
        }
 
        readelf_test {-wKis} $tempfile objdump.WK2  {}
     }
 }
 
+if {![binutils_assemble $srcdir/$subdir/dwo.s tmpdir/dwo.o]} then {
+    unresolved "readelf --debug-dump=links (failed to assemble dwo.s)"
+} else {
+    if ![is_remote host] {
+       set tempfile tmpdir/dwo.o
+    } else {
+       set tempfile [remote_download host tmpdir/dwo.o]
+    }
+
+    readelf_test {--debug-dump=links} $tempfile readelf.k2  {}
+}
+
+
diff --git a/binutils/testsuite/binutils-all/readelf.k2 b/binutils/testsuite/binutils-all/readelf.k2
new file mode 100644 (file)
index 0000000..89ee4b4
--- /dev/null
@@ -0,0 +1,4 @@
+The \.debug_info section contains a link to a dwo file:
+  Name:      file\.dwo
+  Directory: /another/path/
+  ID:        (12|dd) (34|cc) (56|bb) (78|aa) (78|aa) (56|bb) (34|cc) (12|dd)
This page took 0.040322 seconds and 4 git commands to generate.