Change regcache list to be an hash map
[deliverable/binutils-gdb.git] / binutils / dwarf.c
index 07142af747e282cc00715e080fd837928c7f06d3..06ef1f7285e55c120fd21736c97b46d004067613 100644 (file)
@@ -29,6 +29,7 @@
 #include "dwarf.h"
 #include "gdb/gdb-index.h"
 #include "filenames.h"
+#include "safe-ctype.h"
 #include <assert.h>
 
 #undef MAX
@@ -37,6 +38,7 @@
 #define MIN(a, b) ((a) < (b) ? (a) : (b))
 
 static const char *regname (unsigned int regno, int row);
+static const char *regname_internal_by_table_only (unsigned int regno);
 
 static int have_frame_base;
 static int need_base_address;
@@ -119,9 +121,9 @@ static unsigned int shndx_pool_used = 0;
 
 struct cu_tu_set
 {
-  uint64_t signature;
-  dwarf_vma section_offsets[DW_SECT_MAX];
-  size_t section_sizes[DW_SECT_MAX];
+  uint64_t   signature;
+  dwarf_vma  section_offsets[DW_SECT_MAX];
+  size_t     section_sizes[DW_SECT_MAX];
 };
 
 static int cu_count = 0;
@@ -131,6 +133,12 @@ static struct cu_tu_set *tu_sets = NULL;
 
 static bfd_boolean load_cu_tu_indexes (void *);
 
+/* An array that indicates for a given level of CU nesting whether
+   the latest DW_AT_type seen for that level was a signed type or
+   an unsigned type.  */
+#define MAX_CU_NESTING (1 << 8)
+static bfd_boolean level_type_signed[MAX_CU_NESTING];
+
 /* Values for do_debug_lines.  */
 #define FLAG_DEBUG_LINES_RAW    1
 #define FLAG_DEBUG_LINES_DECODED 2
@@ -1831,10 +1839,356 @@ free_dwo_info (void)
   first_dwo_info = NULL;
 }
 
+/* Ensure that START + UVALUE is less than END.
+   Return an adjusted UVALUE if necessary to ensure this relationship.  */
+
+static inline dwarf_vma
+check_uvalue (const unsigned char * start,
+             dwarf_vma             uvalue,
+             const unsigned char * end)
+{
+  dwarf_vma max_uvalue = end - start;
+
+  /* See PR 17512: file: 008-103549-0.001:0.1.
+     and PR 24829 for examples of where these tests are triggered.  */
+  if (uvalue > max_uvalue)
+    {
+      warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
+      uvalue = max_uvalue;
+    }
+
+  return uvalue;
+}
+
+static unsigned char *
+skip_attr_bytes (unsigned long          form,
+                unsigned char *        data,
+                unsigned const char *  end,
+                dwarf_vma              pointer_size,
+                dwarf_vma              offset_size,
+                int                    dwarf_version,
+                dwarf_vma *            value_return)
+{
+  unsigned int  bytes_read;
+  dwarf_vma     uvalue = 0;
+
+  * value_return = 0;
+
+  switch (form)
+    {
+    case DW_FORM_ref_addr:
+      if (dwarf_version == 2)
+       SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
+      else if (dwarf_version == 3 || dwarf_version == 4)
+       SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+      else
+       return NULL;
+      break;
+
+    case DW_FORM_addr:
+      SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
+      break;
+
+    case DW_FORM_strp:
+    case DW_FORM_line_strp:
+    case DW_FORM_sec_offset:
+    case DW_FORM_GNU_ref_alt:
+    case DW_FORM_GNU_strp_alt:
+      SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+      break;
+
+    case DW_FORM_flag_present:
+      uvalue = 1;
+      break;
+
+    case DW_FORM_ref1:
+    case DW_FORM_flag:
+    case DW_FORM_data1:
+      SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
+      break;
+
+    case DW_FORM_ref2:
+    case DW_FORM_data2:
+      SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
+      break;
+
+    case DW_FORM_ref4:
+    case DW_FORM_data4:
+      SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
+      break;
+
+    case DW_FORM_sdata:
+      uvalue = read_sleb128 (data, & bytes_read, end);
+      data += bytes_read;
+      break;
+
+    case DW_FORM_ref_udata:
+    case DW_FORM_udata:
+    case DW_FORM_GNU_str_index:
+    case DW_FORM_GNU_addr_index:
+      uvalue = read_uleb128 (data, & bytes_read, end);
+      data += bytes_read;
+      break;
+
+    case DW_FORM_ref8:
+    case DW_FORM_data8:
+      data += 8;
+      break;
+
+    case DW_FORM_data16:
+      data += 16;
+      break;
+
+    case DW_FORM_string:
+      data += strnlen ((char *) data, end - data) + 1;
+      break;
+
+    case DW_FORM_block:
+    case DW_FORM_exprloc:
+      uvalue = read_uleb128 (data, & bytes_read, end);
+      data += bytes_read + uvalue;
+      break;
+
+    case DW_FORM_block1:
+      SAFE_BYTE_GET (uvalue, data, 1, end);
+      data += 1 + uvalue;
+      break;
+
+    case DW_FORM_block2:
+      SAFE_BYTE_GET (uvalue, data, 2, end);
+      data += 2 + uvalue;
+      break;
+
+    case DW_FORM_block4:
+      SAFE_BYTE_GET (uvalue, data, 4, end);
+      data += 4 + uvalue;
+      break;
+
+    case DW_FORM_ref_sig8:
+      data += 8;
+      break;
+
+    case DW_FORM_indirect:
+      /* FIXME: Handle this form.  */
+    default:
+      return NULL;
+    }
+
+  * value_return = uvalue;
+  if (data > end)
+    data = (unsigned char *) end;
+  return data;
+}
+
+/* Return IS_SIGNED set to TRUE if the type at
+   DATA can be determined to be a signed type.  */
+
+static void
+get_type_signedness (unsigned char *        start,
+                    unsigned char *        data,
+                    unsigned const char *  end,
+                    dwarf_vma              pointer_size,
+                    dwarf_vma              offset_size,
+                    int                    dwarf_version,
+                    bfd_boolean *          is_signed,
+                    bfd_boolean            is_nested)
+{
+  unsigned long   abbrev_number;
+  unsigned int    bytes_read;
+  abbrev_entry *  entry;
+  abbrev_attr *   attr;
+
+  * is_signed = FALSE;
+
+  abbrev_number = read_uleb128 (data, & bytes_read, end);
+  data += bytes_read;
+
+  for (entry = first_abbrev;
+       entry != NULL && entry->entry != abbrev_number;
+       entry = entry->next)
+    continue;
+
+  if (entry == NULL)
+    /* FIXME: Issue a warning ?  */
+    return;
+
+  for (attr = entry->first_attr;
+       attr != NULL && attr->attribute;
+       attr = attr->next)
+    {
+      dwarf_vma uvalue = 0;
+
+      data = skip_attr_bytes (attr->form, data, end, pointer_size,
+                             offset_size, dwarf_version, & uvalue);
+      if (data == NULL)
+       return;
+
+      switch (attr->attribute)
+       {
+#if 0 /* FIXME: It would be nice to print the name of the type,
+        but this would mean updating a lot of binutils tests.  */
+       case DW_AT_name:
+         if (attr->form == DW_FORM_strp)
+           printf ("%s", fetch_indirect_string (uvalue));
+         break;
+#endif
+       case DW_AT_type:
+         /* Recurse.  */
+         if (is_nested)
+           {
+             /* FIXME: Warn - or is this expected ?
+                NB/ We need to avoid infinite recursion.  */
+             return;
+           }
+         if (uvalue >= (size_t) (end - start))
+           return;
+         get_type_signedness (start, start + uvalue, end, pointer_size,
+                              offset_size, dwarf_version, is_signed, TRUE);
+         break;
+
+       case DW_AT_encoding:
+         /* Determine signness.  */
+         switch (uvalue)
+           {
+           case DW_ATE_address:
+             /* FIXME - some architectures have signed addresses.  */
+           case DW_ATE_boolean:
+           case DW_ATE_unsigned:
+           case DW_ATE_unsigned_char:
+           case DW_ATE_unsigned_fixed:
+             * is_signed = FALSE;
+             break;
+
+           default:
+           case DW_ATE_complex_float:
+           case DW_ATE_float:
+           case DW_ATE_signed:
+           case DW_ATE_signed_char:
+           case DW_ATE_imaginary_float:
+           case DW_ATE_decimal_float:
+           case DW_ATE_signed_fixed:
+             * is_signed = TRUE;
+             break;
+           }
+         break;
+       }
+    }
+}
+
+static void
+read_and_print_leb128 (unsigned char *        data,
+                      unsigned int *         bytes_read,
+                      unsigned const char *  end,
+                      bfd_boolean            is_signed)
+{
+  if (is_signed)
+    {
+      dwarf_signed_vma sval = read_sleb128 (data, bytes_read, end);
+      printf ("%ld", (long) sval);
+    }
+  else
+    {
+      dwarf_vma uval = read_uleb128 (data, bytes_read, end);
+      printf ("%lu", (unsigned long) uval);
+    }
+}
+
+static void
+display_discr_list (unsigned long          form,
+                   dwarf_vma              uvalue,
+                   unsigned char *        data,
+                   unsigned const char *  end,
+                   int                    level)
+{
+  if (uvalue == 0)
+    {
+      printf ("[default]");
+      return;
+    }
+  
+  switch (form)
+    {
+    case DW_FORM_block:
+    case DW_FORM_block1:
+    case DW_FORM_block2:
+    case DW_FORM_block4:
+      /* Move data pointer back to the start of the byte array.  */
+      data -= uvalue;
+      break;
+    default:
+      printf ("<corrupt>\n");
+      warn (_("corrupt discr_list - not using a block form\n"));
+      return;
+    }
+
+  if (uvalue < 2)
+    {
+      printf ("<corrupt>\n");
+      warn (_("corrupt discr_list - block not long enough\n"));
+      return;
+    }
+
+  bfd_boolean is_signed =
+    (level > 0 && level <= MAX_CU_NESTING)
+    ? level_type_signed [level - 1] : FALSE;
+    
+  printf ("(");
+  while (uvalue)
+    {
+      unsigned char     discriminant;
+      unsigned int      bytes_read;
+
+      SAFE_BYTE_GET (discriminant, data, 1, end);
+      -- uvalue;
+      data ++;
+
+      assert (uvalue > 0);
+      switch (discriminant)
+       {
+       case DW_DSC_label:
+         printf ("label ");
+         read_and_print_leb128 (data, & bytes_read, end, is_signed);
+         assert (bytes_read <= uvalue && bytes_read > 0);
+         uvalue -= bytes_read;
+         data += bytes_read;
+         break;
+
+       case DW_DSC_range:
+         printf ("range ");
+         read_and_print_leb128 (data, & bytes_read, end, is_signed);
+         assert (bytes_read <= uvalue && bytes_read > 0);
+         uvalue -= bytes_read;
+         data += bytes_read;
+
+         printf ("..");
+         read_and_print_leb128 (data, & bytes_read, end, is_signed);
+         assert (bytes_read <= uvalue && bytes_read > 0);
+         uvalue -= bytes_read;
+         data += bytes_read;
+         break;
+
+       default:
+         printf ("<corrupt>\n");
+         warn (_("corrupt discr_list - unrecognised discriminant byte %#x\n"),
+               discriminant);
+         return;
+       }
+
+      if (uvalue)
+       printf (", ");
+    }
+
+  if (is_signed)
+    printf (")(signed)");
+  else
+    printf (")(unsigned)");
+}
+
 static unsigned char *
 read_and_display_attr_value (unsigned long           attribute,
                             unsigned long           form,
                             dwarf_signed_vma        implicit_const,
+                            unsigned char *         start,
                             unsigned char *         data,
                             unsigned char *         end,
                             dwarf_vma               cu_offset,
@@ -1845,12 +2199,13 @@ read_and_display_attr_value (unsigned long           attribute,
                             int                     do_loc,
                             struct dwarf_section *  section,
                             struct cu_tu_set *      this_set,
-                            char                    delimiter)
+                            char                    delimiter,
+                            int                     level)
 {
-  dwarf_vma uvalue = 0;
-  unsigned char *block_start = NULL;
-  unsigned char * orig_data = data;
-  unsigned int bytes_read;
+  dwarf_vma        uvalue = 0;
+  unsigned char *  block_start = NULL;
+  unsigned char *  orig_data = data;
+  unsigned int     bytes_read;
 
   if (data > end || (data == end && form != DW_FORM_flag_present))
     {
@@ -1931,11 +2286,12 @@ read_and_display_attr_value (unsigned long           attribute,
          implicit_const = read_sleb128 (data, & bytes_read, end);
          data += bytes_read;
        }
-      return read_and_display_attr_value (attribute, form, implicit_const, data,
-                                         end, cu_offset, pointer_size,
+      return read_and_display_attr_value (attribute, form, implicit_const,
+                                         start, data, end,
+                                         cu_offset, pointer_size,
                                          offset_size, dwarf_version,
                                          debug_info_p, do_loc,
-                                         section, this_set, delimiter);
+                                         section, this_set, delimiter, level);
     case DW_FORM_GNU_addr_index:
       uvalue = read_uleb128 (data, & bytes_read, end);
       data += bytes_read;
@@ -2055,16 +2411,9 @@ read_and_display_attr_value (unsigned long           attribute,
          uvalue = 0;
          block_start = end;
        }
-      /* FIXME: Testing "(block_start + uvalue) < block_start" miscompiles with
-        gcc 4.8.3 running on an x86_64 host in 32-bit mode.  So we pre-compute
-        block_start + uvalue here.  */
-      data = block_start + uvalue;
-      /* PR 17512: file: 008-103549-0.001:0.1.  */
-      if (block_start + uvalue > end || data < block_start)
-       {
-         warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
-         uvalue = end - block_start;
-       }
+
+      uvalue = check_uvalue (block_start, uvalue, end);
+
       if (do_loc)
        data = block_start + uvalue;
       else
@@ -2080,12 +2429,9 @@ read_and_display_attr_value (unsigned long           attribute,
          uvalue = 0;
          block_start = end;
        }
-      data = block_start + uvalue;
-      if (block_start + uvalue > end || data < block_start)
-       {
-         warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
-         uvalue = end - block_start;
-       }
+
+      uvalue = check_uvalue (block_start, uvalue, end);
+
       if (do_loc)
        data = block_start + uvalue;
       else
@@ -2101,12 +2447,9 @@ read_and_display_attr_value (unsigned long           attribute,
          uvalue = 0;
          block_start = end;
        }
-      data = block_start + uvalue;
-      if (block_start + uvalue > end || data < block_start)
-       {
-         warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
-         uvalue = end - block_start;
-       }
+
+      uvalue = check_uvalue (block_start, uvalue, end);
+
       if (do_loc)
        data = block_start + uvalue;
       else
@@ -2123,14 +2466,9 @@ read_and_display_attr_value (unsigned long           attribute,
          uvalue = 0;
          block_start = end;
        }
-      data = block_start + uvalue;
-      if (block_start + uvalue > end
-         /* PR 17531: file: 5b5f0592.  */
-         || data < block_start)
-       {
-         warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
-         uvalue = end - block_start;
-       }
+
+      uvalue = check_uvalue (block_start, uvalue, end);
+
       if (do_loc)
        data = block_start + uvalue;
       else
@@ -2386,6 +2724,18 @@ read_and_display_attr_value (unsigned long           attribute,
   /* For some attributes we can display further information.  */
   switch (attribute)
     {
+    case DW_AT_type:
+      if (level >= 0 && level < MAX_CU_NESTING
+         && uvalue < (size_t) (end - start))
+       {
+         bfd_boolean is_signed = FALSE;
+
+         get_type_signedness (start, start + uvalue, end, pointer_size,
+                              offset_size, dwarf_version, & is_signed, FALSE);
+         level_type_signed[level] = is_signed;
+       }
+      break;
+      
     case DW_AT_inline:
       printf ("\t");
       switch (uvalue)
@@ -2635,12 +2985,7 @@ read_and_display_attr_value (unsigned long           attribute,
 
     case DW_AT_discr_list:
       printf ("\t");
-      switch (uvalue)
-       {
-       case DW_DSC_label:  printf (_("(label)")); break;
-       case DW_DSC_range:  printf (_("(range)")); break;
-       default:            printf (_("(unrecognised)")); break;
-       }
+      display_discr_list (form, uvalue, data, end, level);
       break;
       
     case DW_AT_frame_base:
@@ -2757,6 +3102,7 @@ static unsigned char *
 read_and_display_attr (unsigned long           attribute,
                       unsigned long           form,
                       dwarf_signed_vma        implicit_const,
+                      unsigned char *         start,
                       unsigned char *         data,
                       unsigned char *         end,
                       dwarf_vma               cu_offset,
@@ -2766,14 +3112,16 @@ read_and_display_attr (unsigned long           attribute,
                       debug_info *            debug_info_p,
                       int                     do_loc,
                       struct dwarf_section *  section,
-                      struct cu_tu_set *      this_set)
+                      struct cu_tu_set *      this_set,
+                      int                     level)
 {
   if (!do_loc)
     printf ("   %-18s:", get_AT_name (attribute));
-  data = read_and_display_attr_value (attribute, form, implicit_const, data, end,
+  data = read_and_display_attr_value (attribute, form, implicit_const,
+                                     start, data, end,
                                      cu_offset, pointer_size, offset_size,
                                      dwarf_version, debug_info_p,
-                                     do_loc, section, this_set, ' ');
+                                     do_loc, section, this_set, ' ', level);
   if (!do_loc)
     printf ("\n");
   return data;
@@ -3296,10 +3644,10 @@ process_debug_info (struct dwarf_section *           section,
              if (! do_loc && do_printing)
                /* Show the offset from where the tag was extracted.  */
                printf ("    <%lx>", (unsigned long)(tags - section_begin));
-
              tags = read_and_display_attr (attr->attribute,
                                            attr->form,
                                            attr->implicit_const,
+                                           section_begin,
                                            tags,
                                            end,
                                            cu_offset,
@@ -3309,7 +3657,8 @@ process_debug_info (struct dwarf_section *           section,
                                            debug_info_p,
                                            do_loc || ! do_printing,
                                            section,
-                                           this_set);
+                                           this_set,
+                                           level);
            }
 
          /* If a locview attribute appears before a location one,
@@ -3626,11 +3975,11 @@ display_formatted_table (unsigned char *                   data,
              format += bytes_read;
              form = read_uleb128 (format, & bytes_read, end);
              format += bytes_read;
-             data = read_and_display_attr_value (0, form, 0, data, end, 0, 0,
+             data = read_and_display_attr_value (0, form, 0, start, data, end, 0, 0,
                                                  linfo->li_offset_size,
                                                  linfo->li_version, NULL,
                            ((content_type == DW_LNCT_path) != (namepass == 1)),
-                                                 section, NULL, '\t');
+                                                 section, NULL, '\t', -1);
            }
        }
       if (data == end)
@@ -4070,6 +4419,7 @@ typedef struct
 
 static int
 display_debug_lines_decoded (struct dwarf_section *  section,
+                            unsigned char *         start,
                             unsigned char *         data,
                             unsigned char *         end,
                             void *                  fileptr)
@@ -4203,12 +4553,12 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                            }
                          break;
                        }
-                     data = read_and_display_attr_value (0, form, 0, data, end,
+                     data = read_and_display_attr_value (0, form, 0, start, data, end,
                                                          0, 0,
                                                          linfo.li_offset_size,
                                                          linfo.li_version,
                                                          NULL, 1, section,
-                                                         NULL, '\t');
+                                                         NULL, '\t', -1);
                    }
                  if (data == end)
                    {
@@ -4293,12 +4643,12 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                            }
                          break;
                        }
-                     data = read_and_display_attr_value (0, form, 0, data, end,
+                     data = read_and_display_attr_value (0, form, 0, start, data, end,
                                                          0, 0,
                                                          linfo.li_offset_size,
                                                          linfo.li_version,
                                                          NULL, 1, section,
-                                                         NULL, '\t');
+                                                         NULL, '\t', -1);
                    }
                  if (data == end)
                    {
@@ -4825,7 +5175,7 @@ display_debug_lines (struct dwarf_section *section, void *file)
     retValRaw = display_debug_lines_raw (section, data, end, file);
 
   if (do_debug_lines & FLAG_DEBUG_LINES_DECODED)
-    retValDecoded = display_debug_lines_decoded (section, data, end, file);
+    retValDecoded = display_debug_lines_decoded (section, data, data, end, file);
 
   if (!retValRaw || !retValDecoded)
     return 0;
@@ -5430,9 +5780,9 @@ display_debug_macro (struct dwarf_section *section,
                      SAFE_BYTE_GET_AND_INC (val, desc, 1, end);
                      curr
                        = read_and_display_attr_value (0, val, 0,
-                                                      curr, end, 0, 0, offset_size,
+                                                      start, curr, end, 0, 0, offset_size,
                                                       version, NULL, 0, NULL,
-                                                      NULL, ' ');
+                                                      NULL, ' ', -1);
                      if (n != nargs - 1)
                        printf (",");
                    }
@@ -6545,8 +6895,8 @@ display_debug_aranges (struct dwarf_section *section,
 static int
 comp_addr_base (const void * v0, const void * v1)
 {
-  debug_info * info0 = (debug_info *) v0;
-  debug_info * info1 = (debug_info *) v1;
+  debug_info *info0 = *(debug_info **) v0;
+  debug_info *info1 = *(debug_info **) v1;
   return info0->addr_base - info1->addr_base;
 }
 
@@ -7011,9 +7361,12 @@ typedef struct Frame_Chunk
 }
 Frame_Chunk;
 
+typedef const char *(*dwarf_regname_lookup_ftype) (unsigned int);
+static dwarf_regname_lookup_ftype dwarf_regnames_lookup_func;
 static const char *const *dwarf_regnames;
 static unsigned int dwarf_regnames_count;
 
+
 /* A marker for a col_type that means this column was never referenced
    in the frame info.  */
 #define DW_CFA_unreferenced (-1)
@@ -7029,7 +7382,7 @@ frame_need_space (Frame_Chunk *fc, unsigned int reg)
   if (reg < (unsigned int) fc->ncols)
     return 0;
 
-  if (dwarf_regnames_count
+  if (dwarf_regnames_count > 0
       && reg > dwarf_regnames_count)
     return -1;
 
@@ -7040,7 +7393,7 @@ frame_need_space (Frame_Chunk *fc, unsigned int reg)
     return -1;
 
   /* PR 17512: file: 2844a11d.  */
-  if (fc->ncols > 1024)
+  if (fc->ncols > 1024 && dwarf_regnames_count == 0)
     {
       error (_("Unfeasibly large register number: %u\n"), reg);
       fc->ncols = 0;
@@ -7115,18 +7468,20 @@ static const char *const dwarf_regnames_iamcu[] =
   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL  /* 93 - 100  */
 };
 
-void
+static void
 init_dwarf_regnames_i386 (void)
 {
   dwarf_regnames = dwarf_regnames_i386;
   dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_i386);
+  dwarf_regnames_lookup_func = regname_internal_by_table_only;
 }
 
-void
+static void
 init_dwarf_regnames_iamcu (void)
 {
   dwarf_regnames = dwarf_regnames_iamcu;
   dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_iamcu);
+  dwarf_regnames_lookup_func = regname_internal_by_table_only;
 }
 
 static const char *const dwarf_regnames_x86_64[] =
@@ -7161,11 +7516,12 @@ static const char *const dwarf_regnames_x86_64[] =
   "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"
 };
 
-void
+static void
 init_dwarf_regnames_x86_64 (void)
 {
   dwarf_regnames = dwarf_regnames_x86_64;
   dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_x86_64);
+  dwarf_regnames_lookup_func = regname_internal_by_table_only;
 }
 
 static const char *const dwarf_regnames_aarch64[] =
@@ -7175,20 +7531,25 @@ static const char *const dwarf_regnames_aarch64[] =
   "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
   "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp",
    NULL, "elr",  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,
-   NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,
-   NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,
-   NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,
+   NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  "vg", "ffr",
+   "p0",  "p1",  "p2",  "p3",  "p4",  "p5",  "p6",  "p7",
+   "p8",  "p9", "p10", "p11", "p12", "p13", "p14", "p15",
    "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",
    "v8",  "v9", "v10", "v11", "v12", "v13", "v14", "v15",
   "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
   "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
+   "z0",  "z1",  "z2",  "z3",  "z4",  "z5",  "z6",  "z7",
+   "z8",  "z9", "z10", "z11", "z12", "z13", "z14", "z15",
+  "z16", "z17", "z18", "z19", "z20", "z21", "z22", "z23",
+  "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
 };
 
-void
+static void
 init_dwarf_regnames_aarch64 (void)
 {
   dwarf_regnames = dwarf_regnames_aarch64;
   dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_aarch64);
+  dwarf_regnames_lookup_func = regname_internal_by_table_only;
 }
 
 static const char *const dwarf_regnames_s390[] =
@@ -7208,11 +7569,12 @@ static const char *const dwarf_regnames_s390[] =
   "v24", "v26", "v28", "v30", "v25", "v27", "v29", "v31",
 };
 
-void
+static void
 init_dwarf_regnames_s390 (void)
 {
   dwarf_regnames = dwarf_regnames_s390;
   dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_s390);
+  dwarf_regnames_lookup_func = regname_internal_by_table_only;
 }
 
 static const char *const dwarf_regnames_riscv[] =
@@ -7229,16 +7591,54 @@ static const char *const dwarf_regnames_riscv[] =
  "ft8",  "ft9",  "ft10", "ft11"                             /* 60 - 63 */
 };
 
-void
+/* A RISC-V replacement for REGNAME_INTERNAL_BY_TABLE_ONLY which handles
+   the large number of CSRs.  */
+
+static const char *
+regname_internal_riscv (unsigned int regno)
+{
+  const char *name = NULL;
+
+  /* Lookup in the table first, this covers GPR and FPR.  */
+  if (regno < ARRAY_SIZE (dwarf_regnames_riscv))
+    name = dwarf_regnames_riscv [regno];
+  else if (regno >= 4096 && regno <= 8191)
+    {
+      /* This might be a CSR, these live in a sparse number space from 4096
+        to 8191  These numbers are defined in the RISC-V ELF ABI
+        document.  */
+      switch (regno)
+       {
+#define DECLARE_CSR(NAME,VALUE) case VALUE + 4096: name = #NAME; break;
+#include "opcode/riscv-opc.h"
+#undef DECLARE_CSR
+
+       default:
+         {
+           static char csr_name[10];
+           snprintf (csr_name, sizeof (csr_name), "csr%d", (regno - 4096));
+           name = csr_name;
+         }
+         break;
+       }
+    }
+
+  return name;
+}
+
+static void
 init_dwarf_regnames_riscv (void)
 {
-  dwarf_regnames = dwarf_regnames_riscv;
-  dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_riscv);
+  dwarf_regnames = NULL;
+  dwarf_regnames_count = 8192;
+  dwarf_regnames_lookup_func = regname_internal_riscv;
 }
 
 void
-init_dwarf_regnames (unsigned int e_machine)
+init_dwarf_regnames_by_elf_machine_code (unsigned int e_machine)
 {
+  dwarf_regnames_lookup_func = NULL;
+
   switch (e_machine)
     {
     case EM_386:
@@ -7272,19 +7672,82 @@ init_dwarf_regnames (unsigned int e_machine)
     }
 }
 
-static const char *
-regname (unsigned int regno, int row)
+/* Initialize the DWARF register name lookup state based on the
+   architecture and specific machine type of a BFD.  */
+
+void
+init_dwarf_regnames_by_bfd_arch_and_mach (enum bfd_architecture arch,
+                                         unsigned long mach)
 {
-  static char reg[64];
+  dwarf_regnames_lookup_func = NULL;
+
+  switch (arch)
+    {
+    case bfd_arch_i386:
+      switch (mach)
+       {
+       case bfd_mach_x86_64:
+       case bfd_mach_x86_64_intel_syntax:
+       case bfd_mach_x86_64_nacl:
+       case bfd_mach_x64_32:
+       case bfd_mach_x64_32_intel_syntax:
+       case bfd_mach_x64_32_nacl:
+         init_dwarf_regnames_x86_64 ();
+         break;
+
+       default:
+         init_dwarf_regnames_i386 ();
+         break;
+       }
+      break;
+
+    case bfd_arch_iamcu:
+      init_dwarf_regnames_iamcu ();
+      break;
+
+    case bfd_arch_aarch64:
+      init_dwarf_regnames_aarch64();
+      break;
+
+    case bfd_arch_s390:
+      init_dwarf_regnames_s390 ();
+      break;
 
-  if (dwarf_regnames
+    case bfd_arch_riscv:
+      init_dwarf_regnames_riscv ();
+      break;
+
+    default:
+      break;
+    }
+}
+
+static const char *
+regname_internal_by_table_only (unsigned int regno)
+{
+  if (dwarf_regnames != NULL
       && regno < dwarf_regnames_count
       && dwarf_regnames [regno] != NULL)
+    return dwarf_regnames [regno];
+
+  return NULL;
+}
+
+static const char *
+regname (unsigned int regno, int name_only_p)
+{
+  static char reg[64];
+
+  const char *name = NULL;
+
+  if (dwarf_regnames_lookup_func != NULL)
+    name = dwarf_regnames_lookup_func (regno);
+
+  if (name != NULL)
     {
-      if (row)
-       return dwarf_regnames [regno];
-      snprintf (reg, sizeof (reg), "r%d (%s)", regno,
-               dwarf_regnames [regno]);
+      if (name_only_p)
+       return name;
+      snprintf (reg, sizeof (reg), "r%d (%s)", regno, name);
     }
   else
     snprintf (reg, sizeof (reg), "r%d", regno);
@@ -7818,18 +8281,18 @@ display_debug_frames (struct dwarf_section *section,
            {
              READ_ULEB (augmentation_data_len);
              augmentation_data = start;
-             start += augmentation_data_len;
              /* PR 17512 file: 722-8446-0.004 and PR 22386.  */
-             if (start >= end
-                 || ((bfd_signed_vma) augmentation_data_len) < 0
-                 || augmentation_data > start)
+             if (augmentation_data_len > (bfd_size_type) (end - start))
                {
-                 warn (_("Corrupt augmentation data length: 0x%s\n"),
-                       dwarf_vmatoa ("x", augmentation_data_len));
+                 warn (_("Augmentation data too long: 0x%s, "
+                         "expected at most %#lx\n"),
+                       dwarf_vmatoa ("x", augmentation_data_len),
+                       (unsigned long) (end - start));
                  start = end;
                  augmentation_data = NULL;
                  augmentation_data_len = 0;
                }
+             start += augmentation_data_len;
            }
 
          printf ("\n%08lx %s %s FDE cie=%08lx pc=",
@@ -8540,6 +9003,8 @@ display_debug_names (struct dwarf_section *section, void *file)
       uint32_t augmentation_string_size;
       unsigned int i;
       unsigned long sec_off;
+      bfd_boolean augmentation_printable;
+      const char *augmentation_string;
 
       unit_start = hdrptr;
 
@@ -8603,15 +9068,32 @@ display_debug_names (struct dwarf_section *section, void *file)
                augmentation_string_size);
          augmentation_string_size += (-augmentation_string_size) & 3;
        }
+
       printf (_("Augmentation string:"));
+
+      augmentation_printable = TRUE;
+      augmentation_string = (const char *) hdrptr;
+
       for (i = 0; i < augmentation_string_size; i++)
        {
          unsigned char uc;
 
          SAFE_BYTE_GET_AND_INC (uc, hdrptr, 1, unit_end);
          printf (" %02x", uc);
+
+         if (uc != 0 && !ISPRINT (uc))
+           augmentation_printable = FALSE;
+       }
+
+      if (augmentation_printable)
+       {
+         printf ("  (\"");
+         for (i = 0;
+              i < augmentation_string_size && augmentation_string[i];
+              ++i)
+           putchar (augmentation_string[i]);
+         printf ("\")");
        }
-      putchar ('\n');
       putchar ('\n');
 
       printf (_("CU table:\n"));
@@ -8847,12 +9329,12 @@ display_debug_names (struct dwarf_section *section, void *file)
 
                  if (tagno >= 0)
                    printf (" %s", get_IDX_name (xindex));
-                 entryptr = read_and_display_attr_value (0, form, 0, entryptr,
-                                                         unit_end, 0, 0,
-                                                         offset_size,
+                 entryptr = read_and_display_attr_value (0, form, 0,
+                                                         unit_start, entryptr, unit_end,
+                                                         0, 0, offset_size,
                                                          dwarf_version, NULL,
                                                          (tagno < 0), NULL,
-                                                         NULL, '=');
+                                                         NULL, '=', -1);
                }
              ++tagno;
            }
@@ -9291,33 +9773,29 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
   SAFE_BYTE_GET (nslots, phdr + 12, 4, limit);
 
   phash = phdr + 16;
-  pindex = phash + nslots * 8;
-  ppool = pindex + nslots * 4;
-
-  /* PR 17531: file: 45d69832.  */
-  if (pindex < phash || ppool < phdr || (pindex == phash && nslots != 0))
-    {
-      warn (ngettext ("Section %s is too small for %d slot\n",
-                     "Section %s is too small for %d slots\n",
-                     nslots),
-           section->name, nslots);
-      return 0;
-    }
+  pindex = phash + (size_t) nslots * 8;
+  ppool = pindex + (size_t) nslots * 4;
 
   if (do_display)
     {
       introduce (section, FALSE);
 
-      printf (_("  Version:                 %d\n"), version);
+      printf (_("  Version:                 %u\n"), version);
       if (version >= 2)
-       printf (_("  Number of columns:       %d\n"), ncols);
-      printf (_("  Number of used entries:  %d\n"), nused);
-      printf (_("  Number of slots:         %d\n\n"), nslots);
+       printf (_("  Number of columns:       %u\n"), ncols);
+      printf (_("  Number of used entries:  %u\n"), nused);
+      printf (_("  Number of slots:         %u\n\n"), nslots);
     }
 
-  if (ppool > limit || ppool < phdr)
+  /* PR 17531: file: 45d69832.  */
+  if ((size_t) nslots * 8 / 8 != nslots
+      || phash < phdr || phash > limit
+      || pindex < phash || pindex > limit
+      || ppool < pindex || ppool > limit)
     {
-      warn (_("Section %s too small for %d hash table entries\n"),
+      warn (ngettext ("Section %s is too small for %u slot\n",
+                     "Section %s is too small for %u slots\n",
+                     nslots),
            section->name, nslots);
       return 0;
     }
@@ -9379,9 +9857,9 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
       unsigned int dw_sect;
       unsigned char *ph = phash;
       unsigned char *pi = pindex;
-      unsigned char *poffsets = ppool + ncols * 4;
-      unsigned char *psizes = poffsets + nused * ncols * 4;
-      unsigned char *pend = psizes + nused * ncols * 4;
+      unsigned char *poffsets = ppool + (size_t) ncols * 4;
+      unsigned char *psizes = poffsets + (size_t) nused * ncols * 4;
+      unsigned char *pend = psizes + (size_t) nused * ncols * 4;
       bfd_boolean is_tu_index;
       struct cu_tu_set *this_set = NULL;
       unsigned int row;
@@ -9390,14 +9868,14 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
       is_tu_index = strcmp (section->name, ".debug_tu_index") == 0;
 
       /* PR 17531: file: 0dd159bf.
-        Check for wraparound with an overlarge ncols value.  */
-      if (poffsets < ppool || (unsigned int) ((poffsets - ppool) / 4) != ncols)
-       {
-         warn (_("Overlarge number of columns: %x\n"), ncols);
-         return 0;
-       }
-
-      if (pend > limit)
+        Check for integer overflow (can occur when size_t is 32-bit)
+        with overlarge ncols or nused values.  */
+      if (ncols > 0
+         && ((size_t) ncols * 4 / 4 != ncols
+             || (size_t) nused * ncols * 4 / ((size_t) ncols * 4) != nused
+             || poffsets < ppool || poffsets > limit
+             || psizes < poffsets || psizes > limit
+             || pend < psizes || pend > limit))
        {
          warn (_("Section %s too small for offset and size tables\n"),
                section->name);
@@ -9826,6 +10304,7 @@ parse_gnu_debuglink (struct dwarf_section * section, void * data)
      The CRC value is stored after the filename, aligned up to 4 bytes.  */
   name = (const char *) section->start;
 
+  
   crc_offset = strnlen (name, section->size) + 1;
   crc_offset = (crc_offset + 3) & ~3;
   if (crc_offset + 4 > section->size)
@@ -9981,6 +10460,11 @@ load_separate_debug_info (const char *            main_filename,
   sprintf (debug_filename, "%s/%s", EXTRA_DEBUG_ROOT1, separate_filename);
   if (check_func (debug_filename, func_data))
     goto found;
+
+  /* Try the first extra debug file root.  */
+  sprintf (debug_filename, "%s/%s/%s", EXTRA_DEBUG_ROOT1, canon_dir, separate_filename);
+  if (check_func (debug_filename, func_data))
+    goto found;
 #endif
 
 #ifdef EXTRA_DEBUG_ROOT2
@@ -10010,6 +10494,9 @@ load_separate_debug_info (const char *            main_filename,
 #endif
 
 #ifdef EXTRA_DEBUG_ROOT1
+  sprintf (debug_filename, "%s/%s/%s", EXTRA_DEBUG_ROOT1, canon_dir, separate_filename);
+  warn (_("tried: %s\n"), debug_filename);
+
   sprintf (debug_filename, "%s/%s", EXTRA_DEBUG_ROOT1, separate_filename);
   warn (_("tried: %s\n"), debug_filename);
 #endif
This page took 0.051778 seconds and 4 git commands to generate.