Change regcache list to be an hash map
[deliverable/binutils-gdb.git] / binutils / dwarf.c
index 27685183e0188918ea2308e4b3848e8546c9a478..06ef1f7285e55c120fd21736c97b46d004067613 100644 (file)
@@ -38,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;
@@ -120,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;
@@ -132,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
@@ -1842,16 +1849,9 @@ check_uvalue (const unsigned char * start,
 {
   dwarf_vma max_uvalue = end - start;
 
-  /* FIXME: Testing "(start + uvalue) < start" miscompiles with gcc 4.8.3
-     running on an x86_64 host in 32-bit mode.  So we pre-compute the value
-     here.  */
-  const unsigned char * ptr = start + uvalue;
-
   /* 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
-      || ptr > end
-      || ptr < start)
+  if (uvalue > max_uvalue)
     {
       warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
       uvalue = max_uvalue;
@@ -1860,10 +1860,335 @@ check_uvalue (const unsigned char * start,
   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,
@@ -1874,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))
     {
@@ -1960,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;
@@ -2397,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)
@@ -2646,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:
@@ -2768,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,
@@ -2777,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;
@@ -3310,6 +3647,7 @@ process_debug_info (struct dwarf_section *           section,
              tags = read_and_display_attr (attr->attribute,
                                            attr->form,
                                            attr->implicit_const,
+                                           section_begin,
                                            tags,
                                            end,
                                            cu_offset,
@@ -3319,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,
@@ -3636,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)
@@ -4080,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)
@@ -4213,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)
                    {
@@ -4303,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)
                    {
@@ -4835,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;
@@ -5440,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 (",");
                    }
@@ -7021,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)
@@ -7039,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;
 
@@ -7050,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;
@@ -7125,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[] =
@@ -7171,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[] =
@@ -7198,11 +7544,12 @@ static const char *const dwarf_regnames_aarch64[] =
   "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[] =
@@ -7222,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[] =
@@ -7243,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:
@@ -7286,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;
 
-  if (dwarf_regnames
+       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;
+
+    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);
@@ -8880,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;
            }
This page took 0.032048 seconds and 4 git commands to generate.