Add initial support for .debug_sup sections.
authorNick Clifton <nickc@redhat.com>
Thu, 25 Feb 2021 17:50:44 +0000 (17:50 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 25 Feb 2021 17:50:44 +0000 (17:50 +0000)
* dwarf.c (get_type_abbrev_from_form): Accept but ignore sup
forms.
(read_and_display_attr_value): Handle sup forms.
(display_debug_sup): New function.  Displays the contents of a
.debug_sup section.
(load_debug_sup_file): New function.  Loads the contents of a file
referenced by a .debug_sup section.
(check_for_and_load_links): Call load_debug_sup_file.
(debug_displays): Add entry for .debug_sup.
* dwarf.h (enum dwarf_section_display_enum): Add debug_sup.
* readelf.c (process_section_headers): Add support for debug_sup.
* doc/debug.options.texi: Note that the =links option will display
the contents of .debug_sup sections.
* NEWS: Mention the new support.

binutils/ChangeLog
binutils/NEWS
binutils/doc/debug.options.texi
binutils/dwarf.c
binutils/dwarf.h
binutils/readelf.c

index 7d47631f28ff9d5ac5e2b211df41ddf53213784f..332bf8f426b358ab1e493a73ea6b684e374937e1 100644 (file)
@@ -1,3 +1,20 @@
+2021-02-25  Nick Clifton  <nickc@redhat.com>
+
+       * dwarf.c (get_type_abbrev_from_form): Accept but ignore sup
+       forms.
+       (read_and_display_attr_value): Handle sup forms.
+       (display_debug_sup): New function.  Displays the contents of a
+       .debug_sup section.
+       (load_debug_sup_file): New function.  Loads the contents of a file
+       referenced by a .debug_sup section.
+       (check_for_and_load_links): Call load_debug_sup_file.
+       (debug_displays): Add entry for .debug_sup.
+       * dwarf.h (enum dwarf_section_display_enum): Add debug_sup.
+       * readelf.c (process_section_headers): Add support for debug_sup.
+       * doc/debug.options.texi: Note that the =links option will display
+       the contents of .debug_sup sections.
+       * NEWS: Mention the new support.
+
 2021-02-25  Alan Modra  <amodra@gmail.com>
 
        PR 27456
index b0d55623738eb2c7cbf1c6fded0db2dd7742a127..61aca952f2de69dcd67d94d1456cc6138fa11271 100644 (file)
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Readelf and objdump can now display and use the contents of .debug_sup
+  sections.
+
 * Readelf and objdump will now follow links to separate debug info files by
   default.  This behaviour can be stopped via the use of the new -wN or
   --debug-dump=no-follow-links options for readelf and the -WN or
index 2ad8f03626d259bed8608e569a6934467cb1dbdc..3f0234ab0cc397406d6205acc48733586fb7829e 100644 (file)
@@ -44,11 +44,11 @@ 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.  Also displays any links to
-separate dwarf object files (dwo), if they are specified by the 
-DW_AT_GNU_dwo_name or DW_AT_dwo_name attributes in the
-@samp{.debug_info} section.
+Displays the contents of the @samp{.gnu_debuglink},
+@samp{.gnu_debugaltlink} and @samp{.debug_sup} sections, if any of
+them are present.  Also displays any links to separate dwarf object
+files (dwo), if they are 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
index ce2602b6cb0d7db002d3ae443f9fe12c0f6be1d8..3d279079380f3b4df37f9e63f7135bd659630e15 100644 (file)
@@ -2131,6 +2131,10 @@ get_type_abbrev_from_form (unsigned long                 form,
        }
       break;
 
+    case DW_FORM_ref_sup4:
+    case DW_FORM_ref_sup8:
+      break;
+
     case DW_FORM_ref1:
     case DW_FORM_ref2:
     case DW_FORM_ref4:
@@ -2387,7 +2391,7 @@ display_discr_list (unsigned long          form,
 
        default:
          printf ("<corrupt>\n");
-         warn (_("corrupt discr_list - unrecognised discriminant byte %#x\n"),
+         warn (_("corrupt discr_list - unrecognized discriminant byte %#x\n"),
                discriminant);
          return;
        }
@@ -2460,6 +2464,7 @@ read_and_display_attr_value (unsigned long           attribute,
       SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
       break;
 
+    case DW_FORM_strp_sup:
     case DW_FORM_strp:
     case DW_FORM_line_strp:
     case DW_FORM_sec_offset:
@@ -2483,6 +2488,7 @@ read_and_display_attr_value (unsigned long           attribute,
       SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
       break;
 
+    case DW_FORM_ref_sup4:
     case DW_FORM_ref4:
     case DW_FORM_data4:
       SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
@@ -2536,6 +2542,7 @@ read_and_display_attr_value (unsigned long           attribute,
     case DW_FORM_ref1:
     case DW_FORM_ref2:
     case DW_FORM_ref4:
+    case DW_FORM_ref_sup4:
     case DW_FORM_ref_udata:
       if (!do_loc)
        printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue + cu_offset));
@@ -2563,6 +2570,7 @@ read_and_display_attr_value (unsigned long           attribute,
        printf ("%c%s", delimiter, dwarf_vmatoa ("d", implicit_const));
       break;
 
+    case DW_FORM_ref_sup8:
     case DW_FORM_ref8:
     case DW_FORM_data8:
       if (!do_loc)
@@ -2755,8 +2763,13 @@ read_and_display_attr_value (unsigned long           attribute,
        }
       break;
 
+    case DW_FORM_strp_sup:
+      if (!do_loc)
+       printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue + cu_offset));
+      break;
+      
     default:
-      warn (_("Unrecognized form: %lu\n"), form);
+      warn (_("Unrecognized form: 0x%lx\n"), form);
       break;
     }
 
@@ -4334,6 +4347,81 @@ display_formatted_table (unsigned char *                   data,
   return data;
 }
 
+static int
+display_debug_sup (struct dwarf_section *  section,
+                  void *                  file ATTRIBUTE_UNUSED)
+{
+  unsigned char * start = section->start;
+  unsigned char * end = section->start + section->size;
+  unsigned int version;
+  char is_supplementary;
+  const unsigned char * sup_filename;
+  size_t sup_filename_len;
+  unsigned int num_read;
+  int status;
+  dwarf_vma checksum_len;
+
+
+  introduce (section, TRUE);
+  if (section->size < 4)
+    {
+      error (_("corrupt .debug_sup section: size is too small\n"));
+      return 0;
+    }
+
+  /* Read the data.  */
+  SAFE_BYTE_GET_AND_INC (version, start, 2, end);
+  if (version < 5)
+    warn (_("corrupt .debug_sup section: version < 5"));
+
+  SAFE_BYTE_GET_AND_INC (is_supplementary, start, 1, end);
+  if (is_supplementary != 0 && is_supplementary != 1)
+    warn (_("corrupt .debug_sup section: is_supplementary not 0 or 1\n"));    
+
+  sup_filename = start;
+  if (is_supplementary && sup_filename[0] != 0)
+    warn (_("corrupt .debug_sup section: filename not empty in supplementary section\n"));
+
+  sup_filename_len = strnlen ((const char *) start, end - start);
+  if (sup_filename_len == (size_t) (end - start))
+    {
+      error (_("corrupt .debug_sup section: filename is not NUL terminated\n"));
+      return 0;
+    }
+  start += sup_filename_len + 1;
+
+  checksum_len = read_leb128 (start, end, FALSE /* unsigned */, & num_read, & status);
+  if (status)
+    {
+      error (_("corrupt .debug_sup section: bad LEB128 field for checksum length\n"));
+      checksum_len = 0;
+    }
+  start += num_read;
+  if (checksum_len > (dwarf_vma) (end - start))
+    {
+      error (_("corrupt .debug_sup section: checksum length is longer than the remaining section length\n"));
+      checksum_len = end - start;
+    }
+  else if (checksum_len < (dwarf_vma) (end - start))
+    {
+      warn (_("corrupt .debug_sup section: there are 0x%lx extra, unused bytes at the end of the section\n"),
+           (long) ((end - start) - checksum_len));
+    }
+
+  printf (_("  Version:      %u\n"), version);
+  printf (_("  Is Supp:      %u\n"), is_supplementary);
+  printf (_("  Filename:     %s\n"), sup_filename);
+  printf (_("  Checksum Len: %lu\n"), (long) checksum_len);
+  if (checksum_len > 0)
+    {
+      printf (_("  Checksum:     "));
+      while (checksum_len--)
+       printf ("0x%x ", * start++ );
+      printf ("\n");
+    }
+  return 1;
+}
+
 static int
 display_debug_lines_raw (struct dwarf_section *  section,
                         unsigned char *         data,
@@ -11131,9 +11219,62 @@ load_dwo_file (const char * main_filename, const char * name, const char * dir,
   return separate_handle;
 }
 
+static void
+load_debug_sup_file (const char * main_filename, void * file)
+{
+  if (! load_debug_section (debug_sup, file))
+    return; /* No .debug_sup section.  */
+
+  struct dwarf_section * section;
+  section = & debug_displays [debug_sup].section;
+  assert (section != NULL);
+
+  if (section->start == NULL || section->size < 5)
+    {
+      warn (_(".debug_sup section is corrupt/empty\n"));
+      return;
+    }
+
+  if (section->start[2] != 0)
+    return; /* This is a supplementary file.  */
+
+  const char * filename = (const char *) section->start + 3;
+  if (strnlen (filename, section->size - 3) == section->size - 3)
+    {
+      warn (_("filename in .debug_sup section is corrupt\n"));
+      return;
+    }
+
+  if (filename[0] != '/' && strchr (main_filename, '/'))
+    {
+      char * new_name;
+      if (asprintf (& new_name, "%.*s/%s",
+                   (int) (strrchr (main_filename, '/') - main_filename),
+                   main_filename,
+                   filename) < 3)
+       warn (_("unable to construct path for supplementary debug file"));
+      else
+       filename = new_name;
+    }
+
+  void * handle;
+  handle = open_debug_file (filename);
+  if (handle == NULL)
+    {
+      warn (_("unable to open file '%s' referenced from .debug_sup section\n"), filename);
+      return;
+    }
+
+  printf (_("%s: Found supplementary debug file: %s\n\n"), main_filename, filename);
+
+  /* FIXME: Compare the checksums, if present.  */
+  add_separate_debug_file (filename, handle);
+}
+
 /* Load a debuglink section and/or a debugaltlink section, if either are present.
    Recursively check the loaded files for more of these sections.
-   FIXME: Should also check for DWO_* entries in the newlu loaded files.  */
+   Also follow any links in .debug_sup sections.
+   FIXME: Should also check for DWO_* entries in the newly loaded files.  */
 
 static void
 check_for_and_load_links (void * file, const char * filename)
@@ -11175,6 +11316,8 @@ check_for_and_load_links (void * file, const char * filename)
                                    first_separate_info->filename);
        }
     }
+
+  load_debug_sup_file (filename, file);
 }
 
 /* Load the separate debug info file(s) attached to FILE, if any exist.
@@ -11541,6 +11684,7 @@ struct dwarf_section_display debug_displays[] =
   { { ".debug_tu_index",    "",                        NO_ABBREVS },      display_cu_index,       &do_debug_cu_index,  FALSE },
   { { ".gnu_debuglink",     "",                 NO_ABBREVS },      display_debug_links,    &do_debug_links,     FALSE },
   { { ".gnu_debugaltlink",  "",                 NO_ABBREVS },      display_debug_links,    &do_debug_links,     FALSE },
+  { { ".debug_sup",         "",                        NO_ABBREVS },      display_debug_sup,      &do_debug_links,     FALSE },
   /* Separate debug info files can containt their own .debug_str section,
      and this might be in *addition* to a .debug_str section already present
      in the main file.  Hence we need to have two entries for .debug_str.  */
index 98fbef8183dde6e25dc40db1dcaef98d5dae23f1..043d3f9c9d0c74094a9d8a2276e1db866d568f1e 100644 (file)
@@ -120,6 +120,7 @@ enum dwarf_section_display_enum
   dwp_tu_index,
   gnu_debuglink,
   gnu_debugaltlink,
+  debug_sup,
   separate_debug_str,
   max
 };
index 811c529986a4623223ba88d686d799ce13c9cde9..7c8496c17ae5449a8ac4048043b3eb9ba198321d 100644 (file)
@@ -6556,7 +6556,8 @@ process_section_headers (Filedata * filedata)
       if ((do_debugging || do_debug_info || do_debug_abbrevs
           || do_debug_lines || do_debug_pubnames || do_debug_pubtypes
           || do_debug_aranges || do_debug_frames || do_debug_macinfo
-          || do_debug_str || do_debug_str_offsets || do_debug_loc || do_debug_ranges
+          || do_debug_str || do_debug_str_offsets || do_debug_loc
+          || do_debug_ranges
           || do_debug_addr || do_debug_cu_index || do_debug_links)
          && (const_strneq (name, ".debug_")
              || const_strneq (name, ".zdebug_")))
@@ -6583,6 +6584,7 @@ process_section_headers (Filedata * filedata)
              || (do_debug_macinfo  && const_strneq (name, "macinfo"))
              || (do_debug_macinfo  && const_strneq (name, "macro"))
              || (do_debug_str      && const_strneq (name, "str"))
+             || (do_debug_links    && const_strneq (name, "sup"))
              || (do_debug_str_offsets && const_strneq (name, "str_offsets"))
              || (do_debug_loc      && const_strneq (name, "loc"))
              || (do_debug_loc      && const_strneq (name, "loclists"))