gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / binutils / dwarf.c
index 130ba10be3eb6be7fbf22a3e4a2a4ea90ab7c9f3..598f8562abf2bee8b8a9240ec3cf118f6ba12fc2 100644 (file)
 #include "safe-ctype.h"
 #include <assert.h>
 
+#ifdef HAVE_LIBDEBUGINFOD
+#include <elfutils/debuginfod.h>
+#endif
+
 #undef MAX
 #undef MIN
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
@@ -94,6 +98,7 @@ int do_debug_cu_index;
 int do_wide;
 int do_debug_links;
 int do_follow_links;
+bfd_boolean do_checks;
 
 int dwarf_cutoff_level = -1;
 unsigned long dwarf_start_die;
@@ -2004,7 +2009,7 @@ read_and_print_leb128 (unsigned char *        data,
   int status;
   dwarf_vma val = read_leb128 (data, end, is_signed, bytes_read, &status);
   if (status != 0)
-    report_leb_status (status);
+    report_leb_status (status, __FILE__, __LINE__);
   else
     printf ("%s", dwarf_vmatoa (is_signed ? "d" : "u", val));
 }
@@ -3618,7 +3623,6 @@ read_debug_line_header (struct dwarf_section * section,
 {
   unsigned char *hdrptr;
   unsigned int initial_length_size;
-  unsigned char address_size, segment_selector_size;
 
   /* Extract information from the Line Number Program Header.
      (section 6.2.4 in the Dwarf3 doc).  */
@@ -3675,15 +3679,15 @@ read_debug_line_header (struct dwarf_section * section,
 
   if (linfo->li_version >= 5)
     {
-      SAFE_BYTE_GET_AND_INC (address_size, hdrptr, 1, end);
+      SAFE_BYTE_GET_AND_INC (linfo->li_address_size, hdrptr, 1, end);
 
-      SAFE_BYTE_GET_AND_INC (segment_selector_size, hdrptr, 1, end);
-      if (segment_selector_size != 0)
+      SAFE_BYTE_GET_AND_INC (linfo->li_segment_size, hdrptr, 1, end);
+      if (linfo->li_segment_size != 0)
        {
          warn (_("The %s section contains "
                  "unsupported segment selector size: %d.\n"),
-               section->name, segment_selector_size);
-         return 0;
+               section->name, linfo->li_segment_size);
+         return NULL;
        }
     }
 
@@ -3733,8 +3737,13 @@ display_formatted_table (unsigned char *                   data,
   unsigned char *format_start, format_count, *format, formati;
   dwarf_vma data_count, datai;
   unsigned int namepass, last_entry = 0;
-
+  const char * table_name = is_dir ? N_("Directory Table") : N_("File Name Table");
+  
   SAFE_BYTE_GET_AND_INC (format_count, data, 1, end);
+  if (do_checks && format_count > 5)
+    warn (_("Unexpectedly large number of columns in the %s (%u)\n"),
+         table_name, format_count);
+
   format_start = data;
   for (formati = 0; formati < format_count; formati++)
     {
@@ -3742,39 +3751,34 @@ display_formatted_table (unsigned char *                   data,
       SKIP_ULEB (data, end);
       if (data == end)
        {
-         if (is_dir)
-           warn (_("Corrupt directory format table entry\n"));
-         else
-           warn (_("Corrupt file name format table entry\n"));
+         warn (_("%s: Corrupt format description entry\n"), table_name);
          return data;
        }
     }
 
   READ_ULEB (data_count, data, end);
-  if (data == end)
+  if (data_count == 0)
     {
-      if (is_dir)
-       warn (_("Corrupt directory list\n"));
-      else
-       warn (_("Corrupt file name list\n"));
+      printf (_("\n The %s is empty.\n"), table_name);
       return data;
     }
-
-  if (data_count == 0)
+  else if (data == end)
     {
-      if (is_dir)
-       printf (_("\n The Directory Table is empty.\n"));
-      else
-       printf (_("\n The File Name Table is empty.\n"));
+      warn (_("%s: Corrupt entry count - expected %s but none found\n"),
+           table_name, dwarf_vmatoa ("x", data_count));
       return data;
     }
 
-  if (is_dir)
-    printf (_("\n The Directory Table (offset 0x%lx):\n"),
-           (long) (data - start));
-  else
-    printf (_("\n The File Name Table (offset 0x%lx):\n"),
-           (long) (data - start));
+  else if (format_count == 0)
+    {
+      warn (_("%s: format count is zero, but the table is not empty\n"),
+           table_name);
+      return end;
+    }
+
+  printf (_("\n The %s (offset 0x%lx, lines %s, columns %u):\n"),
+         table_name, (long) (data - start), dwarf_vmatoa ("u", data_count),
+         format_count);
 
   printf (_("  Entry"));
   /* Delay displaying name as the last entry for better screen layout.  */ 
@@ -3802,7 +3806,7 @@ display_formatted_table (unsigned char *                   data,
                printf (_("\tSize"));
                break;
              case DW_LNCT_MD5:
-               printf (_("\tMD5"));
+               printf (_("\tMD5\t\t\t"));
                break;
              default:
                printf (_("\t(Unknown format content type %s)"),
@@ -3836,12 +3840,10 @@ display_formatted_table (unsigned char *                   data,
                                                  section, NULL, '\t', -1);
            }
        }
-      if (data == end)
+
+      if (data == end && (datai < data_count - 1))
        {
-         if (is_dir)
-           warn (_("Corrupt directory entries list\n"));
-         else
-           warn (_("Corrupt file name entries list\n"));
+         warn (_("\n%s: Corrupt entries list\n"), table_name);
          return data;
        }
       putchar ('\n');
@@ -3905,6 +3907,11 @@ display_debug_lines_raw (struct dwarf_section *  section,
          printf (_("  Offset:                      0x%lx\n"), (long)(data - start));
          printf (_("  Length:                      %ld\n"), (long) linfo.li_length);
          printf (_("  DWARF Version:               %d\n"), linfo.li_version);
+         if (linfo.li_version >= 5)
+           {
+             printf (_("  Address size (bytes):        %d\n"), linfo.li_address_size);
+             printf (_("  Segment selector (bytes):    %d\n"), linfo.li_segment_size);
+           }
          printf (_("  Prologue Length:             %d\n"), (int) linfo.li_prologue_length);
          printf (_("  Minimum Instruction Length:  %d\n"), linfo.li_min_insn_length);
          if (linfo.li_version >= 4)
@@ -4342,6 +4349,9 @@ display_debug_lines_decoded (struct dwarf_section *  section,
 
              /* Skip directories format.  */
              SAFE_BYTE_GET_AND_INC (format_count, data, 1, end);
+             if (do_checks && format_count > 1)
+               warn (_("Unexpectedly large number of columns in the directory name table (%u)\n"),
+                     format_count);
              format_start = data;
              for (formati = 0; formati < format_count; formati++)
                {
@@ -4356,8 +4366,11 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                  break;
                }
 
-             directory_table = (unsigned char **)
-               xmalloc (n_directories * sizeof (unsigned char *));
+             if (n_directories == 0)
+               directory_table = NULL;
+             else
+               directory_table = (unsigned char **)
+                 xmalloc (n_directories * sizeof (unsigned char *));
 
              for (entryi = 0; entryi < n_directories; entryi++)
                {
@@ -4410,6 +4423,9 @@ display_debug_lines_decoded (struct dwarf_section *  section,
 
              /* Skip files format.  */
              SAFE_BYTE_GET_AND_INC (format_count, data, 1, end);
+             if (do_checks && format_count > 5)
+               warn (_("Unexpectedly large number of columns in the file name table (%u)\n"),
+                     format_count);
              format_start = data;
              for (formati = 0; formati < format_count; formati++)
                {
@@ -4418,14 +4434,17 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                }
 
              READ_ULEB (n_files, data, end);
-             if (data == end)
+             if (data == end && n_files > 0)
                {
                  warn (_("Corrupt file name list\n"));
                  break;
                }
 
-             file_table = (File_Entry *) xcalloc (1, n_files
-                                                     * sizeof (File_Entry));
+             if (n_files == 0)
+               file_table = NULL;
+             else
+               file_table = (File_Entry *) xcalloc (1, n_files
+                                                    * sizeof (File_Entry));
 
              for (entryi = 0; entryi < n_files; entryi++)
                {
@@ -4581,7 +4600,7 @@ display_debug_lines_decoded (struct dwarf_section *  section,
 
          /* Print the Compilation Unit's name and a header.  */
          if (file_table == NULL)
-           ;
+           printf (_("CU: No directory table\n"));
          else if (directory_table == NULL)
            printf (_("CU: %s:\n"), file_table[0].name);
          else
@@ -4609,7 +4628,10 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                printf ("%s:\n", file_table[0].name);
            }
 
-         printf (_("File name                            Line number    Starting address    View    Stmt\n"));
+         if (n_files > 0)
+           printf (_("File name                            Line number    Starting address    View    Stmt\n"));
+         else
+           printf (_("CU: Empty file name table\n"));
          saved_linfo = linfo;
        }
 
@@ -4901,6 +4923,11 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                  strncpy (newFileName,
                           fileName + fileNameLength - MAX_FILENAME_LENGTH,
                           MAX_FILENAME_LENGTH + 1);
+                 /* FIXME: This is to pacify gcc-10 which can warn that the
+                    strncpy above might leave a non-NUL terminated string
+                    in newFileName.  It won't, but gcc's analysis doesn't
+                    quite go far enough to discover this.  */
+                 newFileName[MAX_FILENAME_LENGTH] = 0;
                }
              else
                {
@@ -6917,6 +6944,7 @@ display_debug_ranges (struct dwarf_section *section,
   int is_rnglists = strstr (section->name, "debug_rnglists") != NULL;
   /* Initialize it due to a false compiler warning.  */
   unsigned char address_size = 0;
+  dwarf_vma last_offset = 0;
 
   if (bytes == 0)
     {
@@ -7072,6 +7100,15 @@ display_debug_ranges (struct dwarf_section *section,
          continue;
        }
 
+      /* If multiple DWARF entities reference the same range then we will
+         have multiple entries in the `range_entries' list for the same
+         offset.  Thanks to the sort above these will all be consecutive in
+         the `range_entries' list, so we can easily ignore duplicates
+         here.  */
+      if (i > 0 && last_offset == offset)
+        continue;
+      last_offset = offset;
+
       if (dwarf_check != 0 && i > 0)
        {
          if (start < next)
@@ -7372,7 +7409,8 @@ regname_internal_riscv (unsigned int regno)
         document.  */
       switch (regno)
        {
-#define DECLARE_CSR(NAME,VALUE) case VALUE + 4096: name = #NAME; break;
+#define DECLARE_CSR(NAME,VALUE,CLASS,DEFINE_VER,ABORT_VER) \
+  case VALUE + 4096: name = #NAME; break;
 #include "opcode/riscv-opc.h"
 #undef DECLARE_CSR
 
@@ -7797,6 +7835,7 @@ display_debug_frames (struct dwarf_section *section,
       unsigned int offset_size;
       unsigned int initial_length_size;
       bfd_boolean all_nops;
+      static Frame_Chunk fde_fc;
 
       saved_start = start;
 
@@ -7894,7 +7933,6 @@ display_debug_frames (struct dwarf_section *section,
       else
        {
          unsigned char *look_for;
-         static Frame_Chunk fde_fc;
          unsigned long segment_selector;
 
          if (is_eh)
@@ -8701,6 +8739,17 @@ display_debug_frames (struct dwarf_section *section,
       if (do_debug_frames_interp && ! all_nops)
        frame_display_row (fc, &need_col_headers, &max_regs);
 
+      if (fde_fc.col_type != NULL)
+       {
+         free (fde_fc.col_type);
+         fde_fc.col_type = NULL;
+       }
+      if (fde_fc.col_offset != NULL)
+       {
+         free (fde_fc.col_offset);
+         fde_fc.col_offset = NULL;
+       }
+
       start = block_end;
       eh_addr_size = saved_eh_addr_size;
     }
@@ -10128,12 +10177,83 @@ add_separate_debug_file (const char * filename, void * handle)
   first_separate_info = i;
 }
 
+#if HAVE_LIBDEBUGINFOD
+/* Query debuginfod servers for the target debuglink or debugaltlink
+   file. If successful, store the path of the file in filename and
+   return TRUE, otherwise return FALSE.  */
+
+static bfd_boolean
+debuginfod_fetch_separate_debug_info (struct dwarf_section * section,
+                                      char ** filename,
+                                      void * file)
+{
+  size_t build_id_len;
+  unsigned char * build_id;
+
+  if (strcmp (section->uncompressed_name, ".gnu_debuglink") == 0)
+    {
+      /* Get the build-id of file.  */
+      build_id = get_build_id (file);
+      build_id_len = 0;
+    }
+  else if (strcmp (section->uncompressed_name, ".gnu_debugaltlink") == 0)
+    {
+      /* Get the build-id of the debugaltlink file.  */
+      unsigned int filelen;
+
+      filelen = strnlen ((const char *)section->start, section->size);
+      if (filelen == section->size)
+        /* Corrupt debugaltlink.  */
+        return FALSE;
+
+      build_id = section->start + filelen + 1;
+      build_id_len = section->size - (filelen + 1);
+
+      if (build_id_len == 0)
+        return FALSE;
+    }
+  else
+    return FALSE;
+
+  if (build_id)
+    {
+      int fd;
+      debuginfod_client * client;
+
+      client = debuginfod_begin ();
+      if (client == NULL)
+        return FALSE;
+
+      /* Query debuginfod servers for the target file. If found its path
+         will be stored in filename.  */
+      fd = debuginfod_find_debuginfo (client, build_id, build_id_len, filename);
+      debuginfod_end (client);
+
+      /* Only free build_id if we allocated space for a hex string
+         in get_build_id ().  */
+      if (build_id_len == 0)
+        free (build_id);
+
+      if (fd >= 0)
+        {
+          /* File successfully retrieved. Close fd since we want to
+             use open_debug_file () on filename instead.  */
+          close (fd);
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+#endif
+
 static void *
 load_separate_debug_info (const char *            main_filename,
                          struct dwarf_section *  xlink,
                          parse_func_type         parse_func,
                          check_func_type         check_func,
-                         void *                  func_data)
+                         void *                  func_data,
+                          void *                  file ATTRIBUTE_UNUSED)
 {
   const char *   separate_filename;
   char *         debug_filename;
@@ -10235,6 +10355,23 @@ load_separate_debug_info (const char *            main_filename,
   if (check_func (debug_filename, func_data))
     goto found;
 
+#if HAVE_LIBDEBUGINFOD
+  {
+    char * tmp_filename;
+
+    if (debuginfod_fetch_separate_debug_info (xlink,
+                                              & tmp_filename,
+                                              file))
+      {
+        /* File successfully downloaded from server, replace
+           debug_filename with the file's path.  */
+        free (debug_filename);
+        debug_filename = tmp_filename;
+        goto found;
+      }
+  }
+#endif
+
   /* Failed to find the file.  */
   warn (_("could not find separate debug file '%s'\n"), separate_filename);
   warn (_("tried: %s\n"), debug_filename);
@@ -10264,6 +10401,16 @@ load_separate_debug_info (const char *            main_filename,
   sprintf (debug_filename, "%s", separate_filename);
   warn (_("tried: %s\n"), debug_filename);
 
+#if HAVE_LIBDEBUGINFOD
+  {
+    char *urls = getenv (DEBUGINFOD_URLS_ENV_VAR);
+    if (urls == NULL)
+      urls = "";
+
+    warn (_("tried: DEBUGINFOD_URLS=%s\n"), urls);
+  }
+#endif
+
   free (canon_dir);
   free (debug_filename);
   return NULL;
@@ -10410,7 +10557,8 @@ load_separate_debug_files (void * file, const char * filename)
                                & debug_displays[gnu_debugaltlink].section,
                                parse_gnu_debugaltlink,
                                check_gnu_debugaltlink,
-                               & build_id_data);
+                               & build_id_data,
+                               file);
     }
 
   if (load_debug_section (gnu_debuglink, file))
@@ -10421,7 +10569,8 @@ load_separate_debug_files (void * file, const char * filename)
                                & debug_displays[gnu_debuglink].section,
                                parse_gnu_debuglink,
                                check_gnu_debuglink,
-                               & crc32);
+                               & crc32,
+                               file);
     }
 
   if (first_separate_info != NULL)
This page took 0.029656 seconds and 4 git commands to generate.