public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Commit: Add initial support for .debug_sup sections
@ 2021-02-25 17:50 Nick Clifton
  0 siblings, 0 replies; only message in thread
From: Nick Clifton @ 2021-02-25 17:50 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 1317 bytes --]

Hi Guys,

  I am checking in the attached patch to add initial support for the
  DWARF-5 .debug_sup section to readelf & objdump.  The patch allows
  the contents of the new section to be dumped with the
  --debug-dump=links option, and followed with the --debug-dump=follow
  option.  (Or automatically now that this last option is enabled by
  default).

  The patch recognizes the new DW_FORM_ref_sup4, DW_FORM_ref_sup8 and
  DW_FORM_strp_sup forms, but it does not process them correctly at
  the moment.  This will be the subject of a follow-up patch.

Cheers
  Nick

binutils/ChangeLog
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.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: debug_sup.patch --]
[-- Type: text/x-patch, Size: 10830 bytes --]

diff --git a/binutils/NEWS b/binutils/NEWS
index b0d5562373..61aca952f2 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -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
diff --git a/binutils/doc/debug.options.texi b/binutils/doc/debug.options.texi
index 2ad8f03626..3f0234ab0c 100644
--- a/binutils/doc/debug.options.texi
+++ b/binutils/doc/debug.options.texi
@@ -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
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index ce2602b6cb..3d27907938 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -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.  */
diff --git a/binutils/dwarf.h b/binutils/dwarf.h
index 98fbef8183..043d3f9c9d 100644
--- a/binutils/dwarf.h
+++ b/binutils/dwarf.h
@@ -120,6 +120,7 @@ enum dwarf_section_display_enum
   dwp_tu_index,
   gnu_debuglink,
   gnu_debugaltlink,
+  debug_sup,
   separate_debug_str,
   max
 };
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 811c529986..7c8496c17a 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -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"))

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-02-25 17:50 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-25 17:50 Commit: Add initial support for .debug_sup sections Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).