[readelf] Handle .gdb_index section version 9
[binutils-gdb.git] / binutils / dwarf.c
index a20d546e21092878b0770ab3e79e0c6b93084ca7..2f4bb30ffd344fb816e2bcfc7c9b999d45ed0125 100644 (file)
@@ -1,5 +1,5 @@
 /* dwarf.c -- display DWARF contents of a BFD binary file
-   Copyright (C) 2005-2022 Free Software Foundation, Inc.
+   Copyright (C) 2005-2023 Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
 
@@ -67,9 +67,9 @@ static debug_info *debug_information = NULL;
    DWO object files.  We use these structures to record these links.  */
 typedef enum dwo_type
 {
- DWO_NAME,
- DWO_DIR,
- DWO_ID
 DWO_NAME,
 DWO_DIR,
 DWO_ID
 } dwo_type;
 
 typedef struct dwo_info
@@ -255,6 +255,14 @@ print_view (uint64_t value, unsigned num_bytes)
          value & ~(~(uint64_t) 0 << num_bytes * 4 << num_bytes * 4));
 }
 
+static const char *
+null_name (const char *p)
+{
+  if (p == NULL)
+    p = _("unknown");
+  return p;
+}
+
 /* Read in a LEB128 encoded value starting at address DATA.
    If SIGN is true, return a signed LEB128 value.
    If LENGTH_RETURN is not NULL, return in it the number of bytes read.
@@ -443,7 +451,7 @@ process_extended_line_op (unsigned char * data,
        }
       else
        SAFE_BYTE_GET (adr, data, len - 1, end);
-      printf (_("set Address to 0x%" PRIx64 "\n"), adr);
+      printf (_("set Address to %#" PRIx64 "\n"), adr);
       state_machine_regs.address = adr;
       state_machine_regs.view = 0;
       state_machine_regs.op_index = 0;
@@ -651,14 +659,13 @@ fetch_indexed_string (uint64_t idx,
     return (dwo ? _("<no .debug_str.dwo section>")
                : _("<no .debug_str section>"));
 
-  index_offset = idx * offset_size;
-
-  if (this_set != NULL)
-    index_offset += this_set->section_offsets [DW_SECT_STR_OFFSETS];
-
-  index_offset += str_offsets_base;
-
-  if (index_offset + offset_size > index_section->size)
+  if (_mul_overflow (idx, offset_size, &index_offset)
+      || (this_set != NULL
+         && ((index_offset += this_set->section_offsets [DW_SECT_STR_OFFSETS])
+             < this_set->section_offsets [DW_SECT_STR_OFFSETS]))
+      || (index_offset += str_offsets_base) < str_offsets_base
+      || index_offset + offset_size < offset_size
+      || index_offset + offset_size > index_section->size)
     {
       warn (_("string index of %" PRIu64 " converts to an offset of %#" PRIx64
              " which is too big for section %s"),
@@ -667,11 +674,6 @@ fetch_indexed_string (uint64_t idx,
       return _("<string index too big>");
     }
 
-  /* FIXME: If we are being paranoid then we should also check to see if
-     IDX references an entry beyond the end of the string table pointed to
-     by STR_OFFSETS_BASE.  (Since there can be more than one string table
-     in a DWARF string section).  */
-
   str_offset = byte_get (index_section->start + index_offset, offset_size);
 
   str_offset -= str_section->address;
@@ -714,15 +716,22 @@ fetch_indexed_addr (uint64_t offset, uint32_t num_bytes)
   return byte_get (section->start + offset, num_bytes);
 }
 
-/* Fetch a value from a debug section that has been indexed by
-   something in another section (eg DW_FORM_loclistx or DW_FORM_rnglistx).
-   Returns -1 if the value could not be found.  */
+/* This is for resolving DW_FORM_rnglistx and DW_FORM_loclistx.
+
+   The memory layout is: base_address (taken from the CU's top DIE) points at a table of offsets,
+   relative to the section start.
+   The table of offsets contains the offsets of objects of interest relative to the table of offsets.
+   IDX is the index of the desired object in said table of offsets.
+
+   This returns the offset of the desired object relative to the section start or -1 upon failure.  */
 
 static uint64_t
-fetch_indexed_value (uint64_t idx,
-                    enum dwarf_section_display_enum sec_enum,
-                    uint64_t base_address)
+fetch_indexed_offset (uint64_t                         idx,
+                     enum dwarf_section_display_enum  sec_enum,
+                     uint64_t                         base_address,
+                     uint64_t                         offset_size)
 {
+  uint64_t offset_of_offset = base_address + idx * offset_size;
   struct dwarf_section *section = &debug_displays [sec_enum].section;
 
   if (section->start == NULL)
@@ -731,36 +740,21 @@ fetch_indexed_value (uint64_t idx,
       return -1;
     }
 
-  uint32_t pointer_size, bias;
-
-  if (byte_get (section->start, 4) == 0xffffffff)
-    {
-      pointer_size = 8;
-      bias = 20;
-    }
-  else
+  if (section->size < 4)
     {
-      pointer_size = 4;
-      bias = 12;
+      warn (_("Section %s is too small to contain an value indexed from another section!\n"),
+           section->name);
+      return -1;
     }
 
-  uint64_t offset = idx * pointer_size;
-
-  /* Offsets are biased by the size of the section header
-     or base address.  */
-  if (base_address)
-    offset += base_address;
-  else
-    offset += bias;
-
-  if (offset + pointer_size > section->size)
+  if (offset_of_offset + offset_size >= section->size)
     {
-      warn (_("Offset into section %s too big: %#" PRIx64 "\n"),
-           section->name, offset);
+      warn (_("Offset of %#" PRIx64 " is too big for section %s\n"),
+           offset_of_offset, section->name);
       return -1;
     }
-
-  return byte_get (section->start + offset, pointer_size);
+  
+  return base_address + byte_get (section->start + offset_of_offset, offset_size);
 }
 
 /* FIXME:  There are better and more efficient ways to handle
@@ -975,6 +969,7 @@ process_abbrev_set (struct dwarf_section *section,
   list->first_abbrev = NULL;
   list->last_abbrev = NULL;
   list->raw = start;
+  list->next = NULL;
 
   while (start < end)
     {
@@ -990,17 +985,13 @@ process_abbrev_set (struct dwarf_section *section,
         the caller.  */
       if (start == end || entry == 0)
        {
-         list->next = NULL;
          list->start_of_next_abbrevs = start != end ? start : NULL;
          return list;
        }
 
       READ_ULEB (tag, start, end);
       if (start == end)
-       {
-         free (list);
-         return NULL;
-       }
+       return free_abbrev_list (list);
 
       children = *start++;
 
@@ -1035,8 +1026,7 @@ process_abbrev_set (struct dwarf_section *section,
   /* Report the missing single zero which ends the section.  */
   error (_("%s section not zero terminated\n"), section->name);
 
-  free (list);
-  return NULL;
+  return free_abbrev_list (list);
 }
 
 /* Return a sequence of abbrevs in SECTION starting at ABBREV_BASE
@@ -1481,13 +1471,13 @@ decode_location_expression (unsigned char * data,
          /* FIXME: Strictly speaking for 64-bit DWARF3 files
             this ought to be an 8-byte wide computation.  */
          SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end);
-         printf ("DW_OP_call2: <0x%" PRIx64 ">", svalue + cu_offset);
+         printf ("DW_OP_call2: <%#" PRIx64 ">", svalue + cu_offset);
          break;
        case DW_OP_call4:
          /* FIXME: Strictly speaking for 64-bit DWARF3 files
             this ought to be an 8-byte wide computation.  */
          SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 4, end);
-         printf ("DW_OP_call4: <0x%" PRIx64 ">", svalue + cu_offset);
+         printf ("DW_OP_call4: <%#" PRIx64 ">", svalue + cu_offset);
          break;
        case DW_OP_call_ref:
          /* FIXME: Strictly speaking for 64-bit DWARF3 files
@@ -1506,7 +1496,7 @@ decode_location_expression (unsigned char * data,
            {
              SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
            }
-         printf ("DW_OP_call_ref: <0x%" PRIx64 ">", uvalue);
+         printf ("DW_OP_call_ref: <%#" PRIx64 ">", uvalue);
          break;
        case DW_OP_form_tls_address:
          printf ("DW_OP_form_tls_address");
@@ -1551,7 +1541,7 @@ decode_location_expression (unsigned char * data,
            addr = get_encoded_value (&data, encoding, section, end);
 
            printf ("DW_OP_GNU_encoded_addr: fmt:%02x addr:", encoding);
-           print_hex (addr, pointer_size);
+           print_hex_ns (addr, pointer_size);
          }
          break;
        case DW_OP_implicit_pointer:
@@ -1576,7 +1566,7 @@ decode_location_expression (unsigned char * data,
              SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
            }
          READ_SLEB (svalue, data, end);
-         printf ("%s: <0x%" PRIx64 "> %" PRId64,
+         printf ("%s: <%#" PRIx64 "> %" PRId64,
                  (op == DW_OP_implicit_pointer
                   ? "DW_OP_implicit_pointer" : "DW_OP_GNU_implicit_pointer"),
                  uvalue, svalue);
@@ -1599,7 +1589,7 @@ decode_location_expression (unsigned char * data,
        case DW_OP_const_type:
        case DW_OP_GNU_const_type:
          READ_ULEB (uvalue, data, end);
-         printf ("%s: <0x%" PRIx64 "> ",
+         printf ("%s: <%#" PRIx64 "> ",
                  (op == DW_OP_const_type ? "DW_OP_const_type"
                                          : "DW_OP_GNU_const_type"),
                  cu_offset + uvalue);
@@ -1614,7 +1604,7 @@ decode_location_expression (unsigned char * data,
                                           : "DW_OP_GNU_regval_type"),
                  uvalue, regname (uvalue, 1));
          READ_ULEB (uvalue, data, end);
-         printf (" <0x%" PRIx64 ">", cu_offset + uvalue);
+         printf (" <%#" PRIx64 ">", cu_offset + uvalue);
          break;
        case DW_OP_deref_type:
        case DW_OP_GNU_deref_type:
@@ -1624,39 +1614,39 @@ decode_location_expression (unsigned char * data,
                                          : "DW_OP_GNU_deref_type"),
                  uvalue);
          READ_ULEB (uvalue, data, end);
-         printf (" <0x%" PRIx64 ">", cu_offset + uvalue);
+         printf (" <%#" PRIx64 ">", cu_offset + uvalue);
          break;
        case DW_OP_convert:
        case DW_OP_GNU_convert:
          READ_ULEB (uvalue, data, end);
-         printf ("%s <0x%" PRIx64 ">",
+         printf ("%s <%#" PRIx64 ">",
                  (op == DW_OP_convert ? "DW_OP_convert" : "DW_OP_GNU_convert"),
                  uvalue ? cu_offset + uvalue : uvalue);
          break;
        case DW_OP_reinterpret:
        case DW_OP_GNU_reinterpret:
          READ_ULEB (uvalue, data, end);
-         printf ("%s <0x%" PRIx64 ">",
+         printf ("%s <%#" PRIx64 ">",
                  (op == DW_OP_reinterpret ? "DW_OP_reinterpret"
                                           : "DW_OP_GNU_reinterpret"),
                  uvalue ? cu_offset + uvalue : uvalue);
          break;
        case DW_OP_GNU_parameter_ref:
          SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
-         printf ("DW_OP_GNU_parameter_ref: <0x%" PRIx64 ">",
+         printf ("DW_OP_GNU_parameter_ref: <%#" PRIx64 ">",
                  cu_offset + uvalue);
          break;
        case DW_OP_addrx:
          READ_ULEB (uvalue, data, end);
-         printf ("DW_OP_addrx <0x%" PRIx64 ">", uvalue);
+         printf ("DW_OP_addrx <%#" PRIx64 ">", uvalue);
          break;
        case DW_OP_GNU_addr_index:
          READ_ULEB (uvalue, data, end);
-         printf ("DW_OP_GNU_addr_index <0x%" PRIx64 ">", uvalue);
+         printf ("DW_OP_GNU_addr_index <%#" PRIx64 ">", uvalue);
          break;
        case DW_OP_GNU_const_index:
          READ_ULEB (uvalue, data, end);
-         printf ("DW_OP_GNU_const_index <0x%" PRIx64 ">", uvalue);
+         printf ("DW_OP_GNU_const_index <%#" PRIx64 ">", uvalue);
          break;
        case DW_OP_GNU_variable_value:
          /* FIXME: Strictly speaking for 64-bit DWARF3 files
@@ -1675,7 +1665,7 @@ decode_location_expression (unsigned char * data,
            {
              SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
            }
-         printf ("DW_OP_GNU_variable_value: <0x%" PRIx64 ">", uvalue);
+         printf ("DW_OP_GNU_variable_value: <%#" PRIx64 ">", uvalue);
          break;
 
          /* HP extensions.  */
@@ -1716,9 +1706,9 @@ decode_location_expression (unsigned char * data,
        default:
          if (op >= DW_OP_lo_user
              && op <= DW_OP_hi_user)
-           printf (_("(User defined location op 0x%x)"), op);
+           printf (_("(User defined location op %#x)"), op);
          else
-           printf (_("(Unknown location op 0x%x)"), op);
+           printf (_("(Unknown location op %#x)"), op);
          /* No way to tell where the next op is, so just bail.  */
          return need_frame_base;
        }
@@ -2352,6 +2342,72 @@ display_discr_list (unsigned long form,
     printf (")(unsigned)");
 }
 
+static void
+display_lang (uint64_t uvalue)
+{
+  switch (uvalue)
+    {
+      /* Ordered by the numeric value of these constants.  */
+    case DW_LANG_C89:                  printf ("ANSI C"); break;
+    case DW_LANG_C:                    printf ("non-ANSI C"); break;
+    case DW_LANG_Ada83:                        printf ("Ada"); break;
+    case DW_LANG_C_plus_plus:          printf ("C++"); break;
+    case DW_LANG_Cobol74:              printf ("Cobol 74"); break;
+    case DW_LANG_Cobol85:              printf ("Cobol 85"); break;
+    case DW_LANG_Fortran77:            printf ("FORTRAN 77"); break;
+    case DW_LANG_Fortran90:            printf ("Fortran 90"); break;
+    case DW_LANG_Pascal83:             printf ("ANSI Pascal"); break;
+    case DW_LANG_Modula2:              printf ("Modula 2"); break;
+
+      /* DWARF 2.1 values.     */
+    case DW_LANG_Java:                 printf ("Java"); break;
+    case DW_LANG_C99:                  printf ("ANSI C99"); break;
+    case DW_LANG_Ada95:                        printf ("ADA 95"); break;
+    case DW_LANG_Fortran95:            printf ("Fortran 95"); break;
+
+      /* DWARF 3 values.  */
+    case DW_LANG_PLI:                  printf ("PLI"); break;
+    case DW_LANG_ObjC:                 printf ("Objective C"); break;
+    case DW_LANG_ObjC_plus_plus:       printf ("Objective C++"); break;
+    case DW_LANG_UPC:                  printf ("Unified Parallel C"); break;
+    case DW_LANG_D:                    printf ("D"); break;
+
+      /* DWARF 4 values.  */
+    case DW_LANG_Python:               printf ("Python"); break;
+
+      /* DWARF 5 values.  */
+    case DW_LANG_OpenCL:               printf ("OpenCL"); break;
+    case DW_LANG_Go:                   printf ("Go"); break;
+    case DW_LANG_Modula3:              printf ("Modula 3"); break;
+    case DW_LANG_Haskell:              printf ("Haskell"); break;
+    case DW_LANG_C_plus_plus_03:       printf ("C++03"); break;
+    case DW_LANG_C_plus_plus_11:       printf ("C++11"); break;
+    case DW_LANG_OCaml:                        printf ("OCaml"); break;
+    case DW_LANG_Rust:                 printf ("Rust"); break;
+    case DW_LANG_C11:                  printf ("C11"); break;
+    case DW_LANG_Swift:                        printf ("Swift"); break;
+    case DW_LANG_Julia:                        printf ("Julia"); break;
+    case DW_LANG_Dylan:                        printf ("Dylan"); break;
+    case DW_LANG_C_plus_plus_14:       printf ("C++14"); break;
+    case DW_LANG_Fortran03:            printf ("Fortran 03"); break;
+    case DW_LANG_Fortran08:            printf ("Fortran 08"); break;
+    case DW_LANG_RenderScript:         printf ("RenderScript"); break;
+
+      /* MIPS extension.  */
+    case DW_LANG_Mips_Assembler:       printf ("MIPS assembler"); break;
+
+      /* UPC extension.  */
+    case DW_LANG_Upc:                  printf ("Unified Parallel C"); break;
+
+    default:
+      if (uvalue >= DW_LANG_lo_user && uvalue <= DW_LANG_hi_user)
+       printf (_("implementation defined: %#" PRIx64 ""), uvalue);
+      else
+       printf (_("unknown: %#" PRIx64 ""), uvalue);
+      break;
+    }
+}
+
 static unsigned char *
 read_and_display_attr_value (unsigned long attribute,
                             unsigned long form,
@@ -2508,7 +2564,7 @@ read_and_display_attr_value (unsigned long attribute,
     {
     case DW_FORM_ref_addr:
       if (!do_loc)
-       printf ("%c<0x%" PRIx64 ">", delimiter, uvalue);
+       printf ("%c<%#" PRIx64 ">", delimiter, uvalue);
       break;
 
     case DW_FORM_GNU_ref_alt:
@@ -2516,9 +2572,9 @@ read_and_display_attr_value (unsigned long attribute,
        {
          if (do_wide)
            /* We have already printed the form name.  */
-           printf ("%c<0x%" PRIx64 ">", delimiter, uvalue);
+           printf ("%c<%#" PRIx64 ">", delimiter, uvalue);
          else
-           printf ("%c<alt 0x%" PRIx64 ">", delimiter, uvalue);
+           printf ("%c<alt %#" PRIx64 ">", delimiter, uvalue);
        }
       /* FIXME: Follow the reference...  */
       break;
@@ -2529,14 +2585,14 @@ read_and_display_attr_value (unsigned long attribute,
     case DW_FORM_ref_sup4:
     case DW_FORM_ref_udata:
       if (!do_loc)
-       printf ("%c<0x%" PRIx64 ">", delimiter, uvalue + cu_offset);
+       printf ("%c<%#" PRIx64 ">", delimiter, uvalue + cu_offset);
       break;
 
     case DW_FORM_data4:
     case DW_FORM_addr:
     case DW_FORM_sec_offset:
       if (!do_loc)
-       printf ("%c0x%" PRIx64, delimiter, uvalue);
+       printf ("%c%#" PRIx64, delimiter, uvalue);
       break;
 
     case DW_FORM_flag_present:
@@ -2566,7 +2622,7 @@ read_and_display_attr_value (unsigned long attribute,
          uint64_t utmp = uvalue;
          if (form == DW_FORM_ref8)
            utmp += cu_offset;
-         printf ("%c0x%" PRIx64, delimiter, utmp);
+         printf ("%c%#" PRIx64, delimiter, utmp);
        }
       break;
 
@@ -2574,9 +2630,9 @@ read_and_display_attr_value (unsigned long attribute,
       if (!do_loc)
        {
          if (uvalue_hi == 0)
-           printf (" 0x%" PRIx64, uvalue);
+           printf (" %#" PRIx64, uvalue);
          else
-           printf (" 0x%" PRIx64 "%016" PRIx64, uvalue_hi, uvalue);
+           printf (" %#" PRIx64 "%016" PRIx64, uvalue_hi, uvalue);
        }
       break;
 
@@ -2630,10 +2686,10 @@ read_and_display_attr_value (unsigned long attribute,
        {
          if (do_wide)
            /* We have already displayed the form name.  */
-           printf (_("%c(offset: 0x%" PRIx64 "): %s"),
+           printf (_("%c(offset: %#" PRIx64 "): %s"),
                    delimiter, uvalue, fetch_indirect_string (uvalue));
          else
-           printf (_("%c(indirect string, offset: 0x%" PRIx64 "): %s"),
+           printf (_("%c(indirect string, offset: %#" PRIx64 "): %s"),
                    delimiter, uvalue, fetch_indirect_string (uvalue));
        }
       break;
@@ -2643,10 +2699,10 @@ read_and_display_attr_value (unsigned long attribute,
        {
          if (do_wide)
            /* We have already displayed the form name.  */
-           printf (_("%c(offset: 0x%" PRIx64 "): %s"),
+           printf (_("%c(offset: %#" PRIx64 "): %s"),
                    delimiter, uvalue, fetch_indirect_line_string (uvalue));
          else
-           printf (_("%c(indirect line string, offset: 0x%" PRIx64 "): %s"),
+           printf (_("%c(indirect line string, offset: %#" PRIx64 "): %s"),
                    delimiter, uvalue, fetch_indirect_line_string (uvalue));
        }
       break;
@@ -2667,10 +2723,10 @@ read_and_display_attr_value (unsigned long attribute,
                                        debug_info_p ? debug_info_p->str_offsets_base : 0);
          if (do_wide)
            /* We have already displayed the form name.  */
-           printf (_("%c(offset: 0x%" PRIx64 "): %s"),
+           printf (_("%c(offset: %#" PRIx64 "): %s"),
                    delimiter, uvalue, strng);
          else
-           printf (_("%c(indexed string: 0x%" PRIx64 "): %s"),
+           printf (_("%c(indexed string: %#" PRIx64 "): %s"),
                    delimiter, uvalue, strng);
        }
       break;
@@ -2680,10 +2736,10 @@ read_and_display_attr_value (unsigned long attribute,
        {
          if (do_wide)
            /* We have already displayed the form name.  */
-           printf (_("%c(offset: 0x%" PRIx64 ") %s"),
+           printf (_("%c(offset: %#" PRIx64 ") %s"),
                    delimiter, uvalue, fetch_alt_indirect_string (uvalue));
          else
-           printf (_("%c(alt indirect string, offset: 0x%" PRIx64 ") %s"),
+           printf (_("%c(alt indirect string, offset: %#" PRIx64 ") %s"),
                    delimiter, uvalue, fetch_alt_indirect_string (uvalue));
        }
       break;
@@ -2694,7 +2750,7 @@ read_and_display_attr_value (unsigned long attribute,
 
     case DW_FORM_ref_sig8:
       if (!do_loc)
-       printf ("%c%s: 0x%" PRIx64, delimiter, do_wide ? "" : "signature",
+       printf ("%c%s: %#" PRIx64, delimiter, do_wide ? "" : "signature",
                uvalue);
       break;
 
@@ -2716,18 +2772,23 @@ read_and_display_attr_value (unsigned long attribute,
            {
              if (dwo)
                {
-                 idx = fetch_indexed_value (uvalue, loclists_dwo, 0);
+                 idx = fetch_indexed_offset (uvalue, loclists_dwo,
+                                             debug_info_p->loclists_base,
+                                             debug_info_p->offset_size);
                  if (idx != (uint64_t) -1)
                    idx += (offset_size == 8) ? 20 : 12;
                }
-             else if (debug_info_p == NULL)
+             else if (debug_info_p == NULL || dwarf_version > 4)
                {
-                 idx = fetch_indexed_value (uvalue, loclists, 0);
+                 idx = fetch_indexed_offset (uvalue, loclists,
+                                             debug_info_p->loclists_base,
+                                             debug_info_p->offset_size);
                }
              else
                {
                  /* We want to compute:
-                      idx = fetch_indexed_value (uvalue, loclists, debug_info_p->loclists_base);
+                      idx = fetch_indexed_value (uvalue, loclists,
+                                            debug_info_p->loclists_base);
                       idx += debug_info_p->loclists_base;
                      Fortunately we already have that sum cached in the
                      loc_offsets array.  */
@@ -2744,9 +2805,9 @@ read_and_display_attr_value (unsigned long attribute,
            {
              if (dwo)
                {
-                 idx = fetch_indexed_value (uvalue, rnglists_dwo, 0);
-                 if (idx != (uint64_t) -1)
-                   idx += (offset_size == 8) ? 20 : 12;
+                 idx = fetch_indexed_offset (uvalue, rnglists,
+                                             debug_info_p->rnglists_base,
+                                             debug_info_p->offset_size);
                }
              else
                {
@@ -2754,11 +2815,8 @@ read_and_display_attr_value (unsigned long attribute,
                    base = 0;
                  else
                    base = debug_info_p->rnglists_base;
-                 /* We do not have a cached value this time, so we perform the
-                    computation manually.  */
-                 idx = fetch_indexed_value (uvalue, rnglists, base);
-                 if (idx != (uint64_t) -1)
-                   idx += base;
+                 idx = fetch_indexed_offset (uvalue, rnglists, base,
+                                             debug_info_p->offset_size);
                }
            }
          else
@@ -2776,18 +2834,18 @@ read_and_display_attr_value (unsigned long attribute,
 
          /* We have already displayed the form name.  */
          if (idx != (uint64_t) -1)
-           printf (_("%c(index: 0x%" PRIx64 "): %" PRIx64),
+           printf (_("%c(index: %#" PRIx64 "): %#" PRIx64),
                    delimiter, uvalue, idx);
        }
       break;
 
     case DW_FORM_strp_sup:
       if (!do_loc)
-       printf ("%c<0x%" PRIx64 ">", delimiter, uvalue + cu_offset);
+       printf ("%c<%#" PRIx64 ">", delimiter, uvalue + cu_offset);
       break;
 
     default:
-      warn (_("Unrecognized form: 0x%lx\n"), form);
+      warn (_("Unrecognized form: %#lx"), form);
       /* What to do?  Consume a byte maybe?  */
       ++data;
       break;
@@ -2805,22 +2863,35 @@ read_and_display_attr_value (unsigned long attribute,
                    "(%#" PRIx64 " and %#" PRIx64 ")"),
                  debug_info_p->cu_offset,
                  debug_info_p->loclists_base, uvalue);
+         svalue = uvalue;
+         if (svalue < 0)
+           {
+             warn (_("CU @ %#" PRIx64 " has has a negative loclists_base "
+                     "value of %#" PRIx64 " - treating as zero"),
+                   debug_info_p->cu_offset, svalue);
+             uvalue = 0;
+           }
          debug_info_p->loclists_base = uvalue;
          break;
-       case DW_AT_rnglists_base:
-         if (debug_info_p->rnglists_base)
-           warn (_("CU @ %#" PRIx64 " has multiple rnglists_base values "
-                   "(%#" PRIx64 " and %#" PRIx64 ")"),
-                 debug_info_p->cu_offset,
-                 debug_info_p->rnglists_base, uvalue);
-         debug_info_p->rnglists_base = uvalue;
-         break;
+
+       case DW_AT_rnglists_base:
+         /* Assignment to debug_info_p->rnglists_base is now elsewhere.  */
+         break;
+
        case DW_AT_str_offsets_base:
          if (debug_info_p->str_offsets_base)
            warn (_("CU @ %#" PRIx64 " has multiple str_offsets_base values "
                    "%#" PRIx64 " and %#" PRIx64 ")"),
                  debug_info_p->cu_offset,
                  debug_info_p->str_offsets_base, uvalue);
+         svalue = uvalue;
+         if (svalue < 0)
+           {
+             warn (_("CU @ %#" PRIx64 " has has a negative stroffsets_base "
+                     "value of %#" PRIx64 " - treating as zero"),
+                   debug_info_p->cu_offset, svalue);
+             uvalue = 0;
+           }
          debug_info_p->str_offsets_base = uvalue;
          break;
 
@@ -2868,7 +2939,9 @@ read_and_display_attr_value (unsigned long attribute,
                  debug_info_p->max_loc_offsets = lmax;
                }
              if (form == DW_FORM_loclistx)
-               uvalue = fetch_indexed_value (num, loclists, debug_info_p->loclists_base);
+               uvalue = fetch_indexed_offset (num, loclists,
+                                              debug_info_p->loclists_base,
+                                              debug_info_p->offset_size);
              else if (this_set != NULL)
                uvalue += this_set->section_offsets [DW_SECT_LOC];
 
@@ -2890,8 +2963,14 @@ read_and_display_attr_value (unsigned long attribute,
                }
              else
                {
-                 assert (debug_info_p->num_loc_views <= num);
-                 num = debug_info_p->num_loc_views;
+                 if (debug_info_p->num_loc_views > num)
+                   {
+                     warn (_("The number of views (%u) is greater than the number of locations (%u)\n"),
+                           debug_info_p->num_loc_views, num);
+                     debug_info_p->num_loc_views = num;
+                   }
+                 else
+                   num = debug_info_p->num_loc_views;
                  if (num > debug_info_p->num_loc_offsets)
                    warn (_("More DW_AT_GNU_locview attributes than location offset attributes\n"));
                  else
@@ -2905,12 +2984,21 @@ read_and_display_attr_value (unsigned long attribute,
 
        case DW_AT_low_pc:
          if (need_base_address)
-           debug_info_p->base_address = uvalue;
+           {
+             if (form == DW_FORM_addrx)
+               uvalue = fetch_indexed_addr (debug_info_p->addr_base
+                                            + uvalue * pointer_size,
+                                            pointer_size);
+
+             debug_info_p->base_address = uvalue;
+           }
          break;
 
        case DW_AT_GNU_addr_base:
        case DW_AT_addr_base:
          debug_info_p->addr_base = uvalue;
+         /* Retrieved elsewhere so that it is in
+            place by the time we read low_pc.  */
          break;
 
        case DW_AT_GNU_ranges_base:
@@ -2937,7 +3025,9 @@ read_and_display_attr_value (unsigned long attribute,
                }
 
              if (form == DW_FORM_rnglistx)
-               uvalue = fetch_indexed_value (uvalue, rnglists, 0);
+               uvalue = fetch_indexed_offset (uvalue, rnglists,
+                                              debug_info_p->rnglists_base,
+                                              debug_info_p->offset_size);
 
              debug_info_p->range_lists [num] = uvalue;
              debug_info_p->num_range_lists++;
@@ -2950,7 +3040,8 @@ read_and_display_attr_value (unsigned long attribute,
            switch (form)
              {
              case DW_FORM_strp:
-               add_dwo_name ((const char *) fetch_indirect_string (uvalue), cu_offset);
+               add_dwo_name ((const char *) fetch_indirect_string (uvalue),
+                             cu_offset);
                break;
              case DW_FORM_GNU_strp_alt:
                add_dwo_name ((const char *) fetch_alt_indirect_string (uvalue), cu_offset);
@@ -2961,7 +3052,8 @@ read_and_display_attr_value (unsigned long attribute,
              case DW_FORM_strx2:
              case DW_FORM_strx3:
              case DW_FORM_strx4:
-               add_dwo_name (fetch_indexed_string (uvalue, this_set, offset_size, false,
+               add_dwo_name (fetch_indexed_string (uvalue, this_set,
+                                                   offset_size, false,
                                                    debug_info_p->str_offsets_base),
                              cu_offset);
                break;
@@ -3084,61 +3176,9 @@ read_and_display_attr_value (unsigned long attribute,
       break;
 
     case DW_AT_language:
-      printf ("\t");
-      switch (uvalue)
-       {
-         /* Ordered by the numeric value of these constants.  */
-       case DW_LANG_C89:               printf ("(ANSI C)"); break;
-       case DW_LANG_C:                 printf ("(non-ANSI C)"); break;
-       case DW_LANG_Ada83:             printf ("(Ada)"); break;
-       case DW_LANG_C_plus_plus:       printf ("(C++)"); break;
-       case DW_LANG_Cobol74:           printf ("(Cobol 74)"); break;
-       case DW_LANG_Cobol85:           printf ("(Cobol 85)"); break;
-       case DW_LANG_Fortran77:         printf ("(FORTRAN 77)"); break;
-       case DW_LANG_Fortran90:         printf ("(Fortran 90)"); break;
-       case DW_LANG_Pascal83:          printf ("(ANSI Pascal)"); break;
-       case DW_LANG_Modula2:           printf ("(Modula 2)"); break;
-         /* DWARF 2.1 values.  */
-       case DW_LANG_Java:              printf ("(Java)"); break;
-       case DW_LANG_C99:               printf ("(ANSI C99)"); break;
-       case DW_LANG_Ada95:             printf ("(ADA 95)"); break;
-       case DW_LANG_Fortran95:         printf ("(Fortran 95)"); break;
-         /* DWARF 3 values.  */
-       case DW_LANG_PLI:               printf ("(PLI)"); break;
-       case DW_LANG_ObjC:              printf ("(Objective C)"); break;
-       case DW_LANG_ObjC_plus_plus:    printf ("(Objective C++)"); break;
-       case DW_LANG_UPC:               printf ("(Unified Parallel C)"); break;
-       case DW_LANG_D:                 printf ("(D)"); break;
-         /* DWARF 4 values.  */
-       case DW_LANG_Python:            printf ("(Python)"); break;
-         /* DWARF 5 values.  */
-       case DW_LANG_OpenCL:            printf ("(OpenCL)"); break;
-       case DW_LANG_Go:                printf ("(Go)"); break;
-       case DW_LANG_Modula3:           printf ("(Modula 3)"); break;
-       case DW_LANG_Haskell:           printf ("(Haskell)"); break;
-       case DW_LANG_C_plus_plus_03:    printf ("(C++03)"); break;
-       case DW_LANG_C_plus_plus_11:    printf ("(C++11)"); break;
-       case DW_LANG_OCaml:             printf ("(OCaml)"); break;
-       case DW_LANG_Rust:              printf ("(Rust)"); break;
-       case DW_LANG_C11:               printf ("(C11)"); break;
-       case DW_LANG_Swift:             printf ("(Swift)"); break;
-       case DW_LANG_Julia:             printf ("(Julia)"); break;
-       case DW_LANG_Dylan:             printf ("(Dylan)"); break;
-       case DW_LANG_C_plus_plus_14:    printf ("(C++14)"); break;
-       case DW_LANG_Fortran03:         printf ("(Fortran 03)"); break;
-       case DW_LANG_Fortran08:         printf ("(Fortran 08)"); break;
-       case DW_LANG_RenderScript:      printf ("(RenderScript)"); break;
-         /* MIPS extension.  */
-       case DW_LANG_Mips_Assembler:    printf ("(MIPS assembler)"); break;
-         /* UPC extension.  */
-       case DW_LANG_Upc:               printf ("(Unified Parallel C)"); break;
-       default:
-         if (uvalue >= DW_LANG_lo_user && uvalue <= DW_LANG_hi_user)
-           printf (_("(implementation defined: %#" PRIx64 ")"), uvalue);
-         else
-           printf (_("(unknown: %#" PRIx64 ")"), uvalue);
-         break;
-       }
+      printf ("\t(");
+      display_lang (uvalue);
+      printf (")");
       break;
 
     case DW_AT_encoding:
@@ -3509,6 +3549,177 @@ introduce (struct dwarf_section * section, bool raw)
     }
 }
 
+/* Free memory allocated for one unit in debug_information.  */
+
+static void
+free_debug_information (debug_info *ent)
+{
+  if (ent->max_loc_offsets)
+    {
+      free (ent->loc_offsets);
+      free (ent->loc_views);
+      free (ent->have_frame_base);
+    }
+  if (ent->max_range_lists)
+    {
+      free (ent->range_lists);
+    }
+}
+
+/* For look-ahead in attributes.  When you want to scan a DIE for one specific
+   attribute and ignore the rest.  */
+
+static unsigned char *
+skip_attribute (unsigned long    form,
+               unsigned char *  data,
+               unsigned char *  end,
+               uint64_t         pointer_size,
+               uint64_t         offset_size,
+               int              dwarf_version)
+{
+  uint64_t temp;
+  int64_t stemp;
+
+  switch (form)
+    {
+    case DW_FORM_ref_addr:
+      data += dwarf_version == 2 ? pointer_size : offset_size;
+      break;
+    case DW_FORM_addr:
+      data += pointer_size;
+      break;
+    case DW_FORM_strp_sup:
+    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:
+      data += offset_size;
+      break;
+    case DW_FORM_ref1:
+    case DW_FORM_flag:
+    case DW_FORM_data1:
+    case DW_FORM_strx1:
+    case DW_FORM_addrx1:      
+      data += 1;
+      break;
+    case DW_FORM_ref2:
+    case DW_FORM_data2:
+    case DW_FORM_strx2:
+    case DW_FORM_addrx2:      
+      data += 2;
+      break;
+    case DW_FORM_strx3:
+    case DW_FORM_addrx3:      
+      data += 3;
+      break;
+    case DW_FORM_ref_sup4:
+    case DW_FORM_ref4:
+    case DW_FORM_data4:
+    case DW_FORM_strx4:
+    case DW_FORM_addrx4:
+      data += 4;
+      break;
+    case DW_FORM_ref_sup8:
+    case DW_FORM_ref8:
+    case DW_FORM_data8:
+    case DW_FORM_ref_sig8:
+      data += 8;
+      break;
+    case DW_FORM_data16:      
+      data += 16;
+      break;
+    case DW_FORM_sdata:
+      READ_SLEB (stemp, data, end);
+      break;
+    case DW_FORM_GNU_str_index:
+    case DW_FORM_strx:
+    case DW_FORM_ref_udata:
+    case DW_FORM_udata:
+    case DW_FORM_GNU_addr_index:
+    case DW_FORM_addrx:
+    case DW_FORM_loclistx:
+    case DW_FORM_rnglistx:
+      READ_ULEB (temp, data, end);
+      break;
+
+    case DW_FORM_indirect:
+      while (form == DW_FORM_indirect)
+        READ_ULEB (form, data, end);
+      return skip_attribute (form, data, end, pointer_size, offset_size, dwarf_version);
+
+    case DW_FORM_string:
+      data += strnlen ((char *) data, end - data);    
+      break;
+    case DW_FORM_block:
+    case DW_FORM_exprloc:
+      READ_ULEB (temp, data, end);
+      data += temp;
+      break;
+    case DW_FORM_block1:
+      SAFE_BYTE_GET_AND_INC (temp, data, 1, end);
+      data += temp;
+      break;
+    case DW_FORM_block2:
+      SAFE_BYTE_GET_AND_INC (temp, data, 2, end);
+      data += temp;
+      break;
+    case DW_FORM_block4:
+      SAFE_BYTE_GET_AND_INC (temp, data, 4, end);
+      data += temp;
+      break;
+    case DW_FORM_implicit_const:
+    case DW_FORM_flag_present:
+      break;
+    default:
+      warn (_("Unexpected form in top DIE\n"));
+      break;
+    }
+  return data;
+}
+
+static void
+read_bases (abbrev_entry *   entry,
+           unsigned char *  data,
+           unsigned char *  end,
+           int64_t          pointer_size,
+           uint64_t         offset_size,
+           int              dwarf_version,
+           debug_info *     debug_info_p)
+{
+  abbrev_attr *attr;
+
+  for (attr = entry->first_attr;
+       attr && attr->attribute;
+       attr = attr->next)
+    {
+      uint64_t uvalue;
+
+      if (attr->attribute == DW_AT_rnglists_base)
+       {
+         if (attr->form == DW_FORM_sec_offset)
+           {
+             SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+             debug_info_p->rnglists_base = uvalue;
+           }
+         else
+           warn (_("Unexpected form of DW_AT_rnglists_base in the top DIE\n"));
+       }
+      else if(attr->attribute == DW_AT_addr_base || attr->attribute == DW_AT_GNU_addr_base)
+       {
+         if (attr->form == DW_FORM_sec_offset)
+           {
+             SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+             debug_info_p->addr_base = uvalue;
+           }
+         else
+           warn (_("Unexpected form of DW_AT_addr_base in the top DIE\n"));
+       }
+      else
+       data = skip_attribute(attr->form, data, end, pointer_size, offset_size, dwarf_version);
+    }
+}
+
 /* Process the contents of a .debug_info section.
    If do_loc is TRUE then we are scanning for location lists and dwo tags
    and we do not want to display anything to the user.
@@ -3805,32 +4016,21 @@ process_debug_info (struct dwarf_section * section,
          && alloc_num_debug_info_entries > unit
          && ! do_types)
        {
-         debug_information [unit].cu_offset = cu_offset;
-         debug_information [unit].pointer_size
-           = compunit.cu_pointer_size;
-         debug_information [unit].offset_size = offset_size;
-         debug_information [unit].dwarf_version = compunit.cu_version;
-         debug_information [unit].base_address = 0;
-         debug_information [unit].addr_base = DEBUG_INFO_UNAVAILABLE;
-         debug_information [unit].ranges_base = DEBUG_INFO_UNAVAILABLE;
-         debug_information [unit].rnglists_base = 0;
-         debug_information [unit].loc_offsets = NULL;
-         debug_information [unit].have_frame_base = NULL;
-         debug_information [unit].max_loc_offsets = 0;
-         debug_information [unit].num_loc_offsets = 0;
-         debug_information [unit].loclists_base = 0;
-         debug_information [unit].range_lists = NULL;
-         debug_information [unit].max_range_lists= 0;
-         debug_information [unit].num_range_lists = 0;
-         debug_information [unit].rnglists_base = 0;
-         debug_information [unit].str_offsets_base = 0;
+         free_debug_information (&debug_information[unit]);
+         memset (&debug_information[unit], 0, sizeof (*debug_information));
+         debug_information[unit].pointer_size = compunit.cu_pointer_size;
+         debug_information[unit].offset_size = offset_size;
+         debug_information[unit].dwarf_version = compunit.cu_version;
+         debug_information[unit].cu_offset = cu_offset;
+         debug_information[unit].addr_base = DEBUG_INFO_UNAVAILABLE;
+         debug_information[unit].ranges_base = DEBUG_INFO_UNAVAILABLE;
        }
 
       if (!do_loc && dwarf_start_die == 0)
        {
-         printf (_("  Compilation Unit @ offset 0x%" PRIx64 ":\n"),
+         printf (_("  Compilation Unit @ offset %#" PRIx64 ":\n"),
                  cu_offset);
-         printf (_("   Length:        0x%" PRIx64 " (%s)\n"),
+         printf (_("   Length:        %#" PRIx64 " (%s)\n"),
                  compunit.cu_length,
                  offset_size == 8 ? "64-bit" : "32-bit");
          printf (_("   Version:       %d\n"), compunit.cu_version);
@@ -3839,32 +4039,32 @@ process_debug_info (struct dwarf_section * section,
              const char *name = get_DW_UT_name (compunit.cu_unit_type);
 
              printf (_("   Unit Type:     %s (%x)\n"),
-                     name ? name : "???",
+                     null_name (name),
                      compunit.cu_unit_type);
            }
-         printf (_("   Abbrev Offset: 0x%" PRIx64 "\n"),
+         printf (_("   Abbrev Offset: %#" PRIx64 "\n"),
                  compunit.cu_abbrev_offset);
          printf (_("   Pointer Size:  %d\n"), compunit.cu_pointer_size);
          if (do_types)
            {
-             printf (_("   Signature:     0x%" PRIx64 "\n"), signature);
-             printf (_("   Type Offset:   0x%" PRIx64 "\n"), type_offset);
+             printf (_("   Signature:     %#" PRIx64 "\n"), signature);
+             printf (_("   Type Offset:   %#" PRIx64 "\n"), type_offset);
            }
          if (do_dwo_id)
-           printf (_("   DWO ID:        0x%" PRIx64 "\n"), dwo_id);
+           printf (_("   DWO ID:        %#" PRIx64 "\n"), dwo_id);
          if (this_set != NULL)
            {
              uint64_t *offsets = this_set->section_offsets;
              size_t *sizes = this_set->section_sizes;
 
              printf (_("   Section contributions:\n"));
-             printf (_("    .debug_abbrev.dwo:       0x%" PRIx64 "  0x%zx\n"),
+             printf (_("    .debug_abbrev.dwo:       %#" PRIx64 "  %#zx\n"),
                      offsets[DW_SECT_ABBREV], sizes[DW_SECT_ABBREV]);
-             printf (_("    .debug_line.dwo:         0x%" PRIx64 "  0x%zx\n"),
+             printf (_("    .debug_line.dwo:         %#" PRIx64 "  %#zx\n"),
                      offsets[DW_SECT_LINE], sizes[DW_SECT_LINE]);
-             printf (_("    .debug_loc.dwo:          0x%" PRIx64 "  0x%zx\n"),
+             printf (_("    .debug_loc.dwo:          %#" PRIx64 "  %#zx\n"),
                      offsets[DW_SECT_LOC], sizes[DW_SECT_LOC]);
-             printf (_("    .debug_str_offsets.dwo:  0x%" PRIx64 "  0x%zx\n"),
+             printf (_("    .debug_str_offsets.dwo:  %#" PRIx64 "  %#zx\n"),
                      offsets[DW_SECT_STR_OFFSETS], sizes[DW_SECT_STR_OFFSETS]);
            }
        }
@@ -3949,7 +4149,11 @@ process_debug_info (struct dwarf_section * section,
                    }
                }
              if (dwarf_start_die != 0 && level < saved_level)
-               return true;
+               {
+                 if (list != NULL)
+                   free_abbrev_list (list);
+                 return true;
+               }
              continue;
            }
 
@@ -3990,6 +4194,8 @@ process_debug_info (struct dwarf_section * section,
                }
              warn (_("DIE at offset %#lx refers to abbreviation number %lu which does not exist\n"),
                    die_offset, abbrev_number);
+             if (list != NULL)
+               free_abbrev_list (list);
              return false;
            }
 
@@ -4022,6 +4228,34 @@ process_debug_info (struct dwarf_section * section,
                  || (debug_info_p->num_loc_offsets
                      == debug_info_p->num_loc_views));
 
+         /* Look ahead so that the values of DW_AT_rnglists_base, DW_AT_[GNU_]addr_base
+            are available before attributes that reference them are parsed in the same DIE.
+            Only needed for the top DIE on DWARFv5+.
+            No simiar treatment for loclists_base because there should be no loclist
+            attributes in top DIE.  */
+         if (compunit.cu_version >= 5 && level == 0)
+           {
+             int64_t stemp;
+
+             read_bases (entry,
+                         tags,
+                         start,
+                         compunit.cu_pointer_size,
+                         offset_size,
+                         compunit.cu_version,
+                         debug_info_p);
+
+             /* This check was in place before, keep it.  */
+             stemp = debug_info_p->rnglists_base;
+             if (stemp < 0)
+               {
+                 warn (_("CU @ %#" PRIx64 " has has a negative rnglists_base "
+                         "value of %#" PRIx64 " - treating as zero"),
+                       debug_info_p->cu_offset, stemp);
+                 debug_info_p->rnglists_base = 0;
+               }
+           }
+
          for (attr = entry->first_attr;
               attr && attr->attribute;
               attr = attr->next)
@@ -4272,10 +4506,10 @@ display_formatted_table (unsigned char *data,
       printf (_("\n The %s is empty.\n"), table_name);
       return data;
     }
-  else if (data >= end)
+  else if (data >= end
+          || data_count > (size_t) (end - data))
     {
-      warn (_("%s: Corrupt entry count - expected %#" PRIx64
-             " but none found\n"), table_name, data_count);
+      warn (_("%s: Corrupt entry count %#" PRIx64 "\n"), table_name, data_count);
       return data;
     }
 
@@ -4286,7 +4520,7 @@ display_formatted_table (unsigned char *data,
       return end;
     }
 
-  printf (_("\n The %s (offset 0x%tx, lines %" PRIu64 ", columns %u):\n"),
+  printf (_("\n The %s (offset %#tx, lines %" PRIu64 ", columns %u):\n"),
          table_name, data - start, data_count, format_count);
 
   printf (_("  Entry"));
@@ -4489,7 +4723,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
                                                & end_of_sequence)) == NULL)
            return 0;
 
-         printf (_("  Offset:                      0x%tx\n"), data - start);
+         printf (_("  Offset:                      %#tx\n"), data - start);
          printf (_("  Length:                      %" PRId64 "\n"), linfo.li_length);
          printf (_("  DWARF Version:               %d\n"), linfo.li_version);
          if (linfo.li_version >= 5)
@@ -4553,7 +4787,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
                {
                  unsigned int last_dir_entry = 0;
 
-                 printf (_("\n The Directory Table (offset 0x%tx):\n"),
+                 printf (_("\n The Directory Table (offset %#tx):\n"),
                          data - start);
 
                  while (data < end && *data != 0)
@@ -4579,7 +4813,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
                printf (_("\n The File Name Table is empty.\n"));
              else
                {
-                 printf (_("\n The File Name Table (offset 0x%tx):\n"),
+                 printf (_("\n The File Name Table (offset %#tx):\n"),
                          data - start);
                  printf (_("  Entry\tDir\tTime\tSize\tName\n"));
 
@@ -4629,7 +4863,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
          while (data < end_of_sequence)
            {
              unsigned char op_code;
-             int64_t adv;
+             int adv;
              uint64_t uladv;
 
              printf ("  [0x%08tx]", data - start);
@@ -4648,7 +4882,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
                        state_machine_regs.view = 0;
                      printf (_("  Special opcode %d: "
                                "advance Address by %" PRIu64
-                               " to 0x%" PRIx64 "%s"),
+                               " to %#" PRIx64 "%s"),
                              op_code, uladv, state_machine_regs.address,
                              verbose_view && uladv
                              ? _(" (reset view)") : "");
@@ -4668,7 +4902,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
                        state_machine_regs.view = 0;
                      printf (_("  Special opcode %d: "
                                "advance Address by %" PRIu64
-                               " to 0x%" PRIx64 "[%d]%s"),
+                               " to %#" PRIx64 "[%d]%s"),
                              op_code, uladv, state_machine_regs.address,
                              state_machine_regs.op_index,
                              verbose_view && addrdelta
@@ -4676,7 +4910,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
                    }
                  adv = (op_code % linfo.li_line_range) + linfo.li_line_base;
                  state_machine_regs.line += adv;
-                 printf (_(" and Line by %" PRId64 " to %d"),
+                 printf (_(" and Line by %d to %d"),
                          adv, state_machine_regs.line);
                  if (verbose_view || state_machine_regs.view)
                    printf (_(" (view %u)\n"), state_machine_regs.view);
@@ -4711,7 +4945,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
                        if (uladv)
                          state_machine_regs.view = 0;
                        printf (_("  Advance PC by %" PRIu64
-                                 " to 0x%" PRIx64 "%s\n"),
+                                 " to %#" PRIx64 "%s\n"),
                                uladv, state_machine_regs.address,
                                verbose_view && uladv
                                ? _(" (reset view)") : "");
@@ -4730,7 +4964,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
                        if (addrdelta)
                          state_machine_regs.view = 0;
                        printf (_("  Advance PC by %" PRIu64
-                                 " to 0x%" PRIx64 "[%d]%s\n"),
+                                 " to %#" PRIx64 "[%d]%s\n"),
                                uladv, state_machine_regs.address,
                                state_machine_regs.op_index,
                                verbose_view && addrdelta
@@ -4741,7 +4975,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
                  case DW_LNS_advance_line:
                    READ_SLEB (adv, data, end);
                    state_machine_regs.line += adv;
-                   printf (_("  Advance Line by %" PRId64 " to %d\n"),
+                   printf (_("  Advance Line by %d to %d\n"),
                            adv, state_machine_regs.line);
                    break;
 
@@ -4761,7 +4995,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
                  case DW_LNS_negate_stmt:
                    adv = state_machine_regs.is_stmt;
                    adv = ! adv;
-                   printf (_("  Set is_stmt to %" PRId64 "\n"), adv);
+                   printf (_("  Set is_stmt to %d\n"), adv);
                    state_machine_regs.is_stmt = adv;
                    break;
 
@@ -4779,7 +5013,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
                        if (uladv)
                          state_machine_regs.view = 0;
                        printf (_("  Advance PC by constant %" PRIu64
-                                 " to 0x%" PRIx64 "%s\n"),
+                                 " to %#" PRIx64 "%s\n"),
                                uladv, state_machine_regs.address,
                                verbose_view && uladv
                                ? _(" (reset view)") : "");
@@ -4798,7 +5032,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
                        if (addrdelta)
                          state_machine_regs.view = 0;
                        printf (_("  Advance PC by constant %" PRIu64
-                                 " to 0x%" PRIx64 "[%d]%s\n"),
+                                 " to %#" PRIx64 "[%d]%s\n"),
                                uladv, state_machine_regs.address,
                                state_machine_regs.op_index,
                                verbose_view && addrdelta
@@ -4811,7 +5045,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
                    state_machine_regs.address += uladv;
                    state_machine_regs.op_index = 0;
                    printf (_("  Advance PC by fixed size amount %" PRIu64
-                             " to 0x%" PRIx64 "\n"),
+                             " to %#" PRIx64 "\n"),
                            uladv, state_machine_regs.address);
                    /* Do NOT reset view.  */
                    break;
@@ -4836,7 +5070,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
                      for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
                        {
                          READ_ULEB (uladv, data, end);
-                         printf ("0x%" PRIx64 "%s", uladv, i == 1 ? "" : ", ");
+                         printf ("%#" PRIx64 "%s", uladv, i == 1 ? "" : ", ");
                        }
                    putchar ('\n');
                    break;
@@ -4851,7 +5085,7 @@ display_debug_lines_raw (struct dwarf_section *  section,
 
 typedef struct
 {
-  unsigned char *name;
+  char *name;
   unsigned int directory_index;
   unsigned int modification_date;
   unsigned int length;
@@ -4879,8 +5113,8 @@ display_debug_lines_decoded (struct dwarf_section *  section,
       int i;
       File_Entry *file_table = NULL;
       unsigned int n_files = 0;
-      unsigned char **directory_table = NULL;
-      uint64_t n_directories = 0;
+      char **directory_table = NULL;
+      unsigned int n_directories = 0;
 
       if (startswith (section->name, ".debug_line.")
          /* Note: the following does not apply to .debug_line.dwo sections.
@@ -4930,8 +5164,8 @@ display_debug_lines_decoded (struct dwarf_section *  section,
 
          if (linfo.li_version >= 5)
            {
-             unsigned char *format_start, format_count, *format;
-             uint64_t formati, entryi;
+             unsigned char *format_start, *format;
+             unsigned int format_count, formati, entryi;
 
              load_debug_section_with_follow (line_str, fileptr);
 
@@ -4956,13 +5190,19 @@ display_debug_lines_decoded (struct dwarf_section *  section,
 
              if (n_directories == 0)
                directory_table = NULL;
+             else if (n_directories > section->size)
+               {
+                 warn (_("number of directories (0x%x) exceeds size of section %s\n"),
+                       n_directories, section->name);
+                 return 0;
+               }
              else
-               directory_table = (unsigned char **)
-                 xmalloc (n_directories * sizeof (unsigned char *));
+               directory_table = (char **)
+                 xcalloc (n_directories, sizeof (unsigned char *));
 
              for (entryi = 0; entryi < n_directories; entryi++)
                {
-                 unsigned char **pathp = &directory_table[entryi];
+                 char **pathp = &directory_table[entryi];
 
                  format = format_start;
                  for (formati = 0; formati < format_count; formati++)
@@ -4983,13 +5223,13 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                          switch (form)
                            {
                            case DW_FORM_string:
-                             *pathp = data;
+                             *pathp = (char *) data;
                              break;
                            case DW_FORM_line_strp:
                              SAFE_BYTE_GET (uvalue, data, linfo.li_offset_size,
                                             end);
                              /* Remove const by the cast.  */
-                             *pathp = (unsigned char *)
+                             *pathp = (char *)
                                       fetch_indirect_line_string (uvalue);
                              break;
                            }
@@ -5014,6 +5254,7 @@ display_debug_lines_decoded (struct dwarf_section *  section,
              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++)
                {
@@ -5030,9 +5271,15 @@ display_debug_lines_decoded (struct dwarf_section *  section,
 
              if (n_files == 0)
                file_table = NULL;
+             else if (n_files > section->size)
+               {
+                 warn (_("number of files (0x%x) exceeds size of section %s\n"),
+                       n_files, section->name);
+                 return 0;
+               }
              else
-               file_table = (File_Entry *) xcalloc (1, n_files
-                                                    sizeof (File_Entry));
+               file_table = (File_Entry *) xcalloc (n_files,
+                                                    sizeof (File_Entry));
 
              for (entryi = 0; entryi < n_files; entryi++)
                {
@@ -5058,13 +5305,13 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                          switch (form)
                            {
                            case DW_FORM_string:
-                             file->name = data;
+                             file->name = (char *) data;
                              break;
                            case DW_FORM_line_strp:
                              SAFE_BYTE_GET (uvalue, data, linfo.li_offset_size,
                                             end);
                              /* Remove const by the cast.  */
-                             file->name = (unsigned char *)
+                             file->name = (char *)
                                           fetch_indirect_line_string (uvalue);
                              break;
                            }
@@ -5105,7 +5352,7 @@ display_debug_lines_decoded (struct dwarf_section *  section,
            {
              if (*data != 0)
                {
-                 unsigned char *ptr_directory_table = data;
+                 char *ptr_directory_table = (char *) data;
 
                  while (data < end && *data != 0)
                    {
@@ -5124,15 +5371,14 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                    }
 
                  /* Go through the directory table again to save the directories.  */
-                 directory_table = (unsigned char **)
+                 directory_table = (char **)
                    xmalloc (n_directories * sizeof (unsigned char *));
 
                  i = 0;
                  while (*ptr_directory_table != 0)
                    {
                      directory_table[i] = ptr_directory_table;
-                     ptr_directory_table
-                       += strlen ((char *) ptr_directory_table) + 1;
+                     ptr_directory_table += strlen (ptr_directory_table) + 1;
                      i++;
                    }
                }
@@ -5170,7 +5416,7 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                  i = 0;
                  while (*ptr_file_name_table != 0)
                    {
-                     file_table[i].name = ptr_file_name_table;
+                     file_table[i].name = (char *) ptr_file_name_table;
                      ptr_file_name_table
                        += strlen ((char *) ptr_file_name_table) + 1;
 
@@ -5194,34 +5440,46 @@ display_debug_lines_decoded (struct dwarf_section *  section,
          if (file_table == NULL)
            printf (_("CU: No directory table\n"));
          else if (directory_table == NULL)
-           printf (_("CU: %s:\n"), file_table[0].name);
+           printf (_("CU: %s:\n"), null_name (file_table[0].name));
          else
            {
              unsigned int ix = file_table[0].directory_index;
              const char *directory;
 
-             if (ix == 0)
+             if (ix == 0 && linfo.li_version < 5)
                directory = ".";
              /* PR 20439 */
              else if (n_directories == 0)
                directory = _("<unknown>");
-             else if (ix > n_directories)
+             else
                {
-                 warn (_("directory index %u > number of directories %" PRIu64 "\n"),
-                       ix, n_directories);
-                 directory = _("<corrupt>");
+                 if (linfo.li_version < 5)
+                   --ix;
+                 if (ix >= n_directories)
+                   {
+                     warn (_("directory index %u "
+                             ">= number of directories %u\n"),
+                           ix, n_directories);
+                     directory = _("<corrupt>");
+                   }
+                 else
+                   directory = directory_table[ix];
                }
-             else
-               directory = (char *) directory_table[ix - 1];
-
              if (do_wide)
-               printf (_("CU: %s/%s:\n"), directory, file_table[0].name);
+               printf (_("CU: %s/%s:\n"),
+                       null_name (directory),
+                       null_name (file_table[0].name));
              else
-               printf ("%s:\n", file_table[0].name);
+               printf ("%s:\n", null_name (file_table[0].name));
            }
 
          if (n_files > 0)
-           printf (_("File name                            Line number    Starting address    View    Stmt\n"));
+           {
+             if (do_wide)
+               printf (_("File name                            Line number    Starting address    View    Stmt\n"));
+             else
+               printf (_("File name                        Line number    Starting address    View    Stmt\n"));
+           }
          else
            printf (_("CU: Empty file name table\n"));
          saved_linfo = linfo;
@@ -5310,7 +5568,7 @@ display_debug_lines_decoded (struct dwarf_section *  section,
 
                      ++state_machine_regs.last_file_entry;
                      /* Source file name.  */
-                     file_table[n_files].name = op_code_data;
+                     file_table[n_files].name = (char *) op_code_data;
                      op_code_data += strlen ((char *) op_code_data) + 1;
                      /* Directory index.  */
                      READ_ULEB (file_table[n_files].directory_index,
@@ -5375,38 +5633,53 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                READ_ULEB (uladv, data, end);
                state_machine_regs.file = uladv;
 
-               {
-                 unsigned file = state_machine_regs.file;
-                 unsigned dir;
+               unsigned file = state_machine_regs.file;
+               if (linfo.li_version < 5)
+                 --file;
 
-                 if (linfo.li_version < 5)
-                   --file;
-                 if (file_table == NULL || n_files == 0)
-                   printf (_("\n [Use file table entry %d]\n"), file);
-                 /* PR 20439 */
-                 else if (file >= n_files)
-                   {
-                     warn (_("file index %u > number of files %u\n"), file, n_files);
-                     printf (_("\n <over large file table index %u>"), file);
-                   }
-                 else if ((dir = file_table[file].directory_index) == 0)
-                   /* If directory index is 0, that means current directory.  */
-                   printf ("\n./%s:[++]\n", file_table[file].name);
-                 else if (directory_table == NULL || n_directories == 0)
-                   printf (_("\n [Use file %s in directory table entry %d]\n"),
-                           file_table[file].name, dir);
-                 /* PR 20439 */
-                 else if (dir > n_directories)
-                   {
-                     warn (_("directory index %u > number of directories %" PRIu64 "\n"),
-                           dir, n_directories);
-                     printf (_("\n <over large directory table entry %u>\n"), dir);
-                   }
-                 else
-                   printf ("\n%s/%s:\n",
-                           /* The directory index starts counting at 1.  */
-                           directory_table[dir - 1], file_table[file].name);
-               }
+               if (file_table == NULL || n_files == 0)
+                 printf (_("\n [Use file table entry %d]\n"), file);
+               /* PR 20439 */
+               else if (file >= n_files)
+                 {
+                   warn (_("file index %u >= number of files %u\n"),
+                         file, n_files);
+                   printf (_("\n <over large file table index %u>"), file);
+                 }
+               else
+                 {
+                   unsigned dir = file_table[file].directory_index;
+                   if (dir == 0 && linfo.li_version < 5)
+                     /* If directory index is 0, that means compilation
+                        current directory.  bfd/dwarf2.c shows
+                        DW_AT_comp_dir here but in keeping with the
+                        readelf practice of minimal interpretation of
+                        file data, we show "./".  */
+                     printf ("\n./%s:[++]\n",
+                             null_name (file_table[file].name));
+                   else if (directory_table == NULL || n_directories == 0)
+                     printf (_("\n [Use file %s "
+                               "in directory table entry %d]\n"),
+                             null_name (file_table[file].name), dir);
+                   else
+                     {
+                       if (linfo.li_version < 5)
+                         --dir;
+                       /* PR 20439 */
+                       if (dir >= n_directories)
+                         {
+                           warn (_("directory index %u "
+                                   ">= number of directories %u\n"),
+                                 dir, n_directories);
+                           printf (_("\n <over large directory table entry "
+                                     "%u>\n"), dir);
+                         }
+                       else
+                         printf ("\n%s/%s:\n",
+                                 null_name (directory_table[dir]),
+                                 null_name (file_table[file].name));
+                     }
+                 }
                break;
 
              case DW_LNS_set_column:
@@ -5476,7 +5749,7 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                      uint64_t val;
 
                      READ_ULEB (val, data, end);
-                     printf ("0x%" PRIx64 "%s", val, i == 1 ? "" : ", ");
+                     printf ("%#" PRIx64 "%s", val, i == 1 ? "" : ", ");
                    }
                putchar ('\n');
                break;
@@ -5488,7 +5761,7 @@ display_debug_lines_decoded (struct dwarf_section *  section,
              || (xop == DW_LNS_copy))
            {
              const unsigned int MAX_FILENAME_LENGTH = 35;
-             char *fileName;
+             char *fileName = NULL;
              char *newFileName = NULL;
              size_t fileNameLength;
 
@@ -5501,13 +5774,14 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                  /* PR 20439  */
                  if (indx >= n_files)
                    {
-                     warn (_("corrupt file index %u encountered\n"), indx);
+                     warn (_("file index %u >= number of files %u\n"),
+                           indx, n_files);
                      fileName = _("<corrupt>");
                    }
                  else
                    fileName = (char *) file_table[indx].name;
                }
-             else
+             if (!fileName)
                fileName = _("<unknown>");
 
              fileNameLength = strlen (fileName);
@@ -5531,23 +5805,23 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                  if (linfo.li_max_ops_per_insn == 1)
                    {
                      if (xop == -DW_LNE_end_sequence)
-                       printf ("%-35s  %11s  %#18" PRIx64,
+                       printf ("%-31s  %11s  %#18" PRIx64,
                                newFileName, "-",
                                state_machine_regs.address);
                      else
-                       printf ("%-35s  %11d  %#18" PRIx64,
+                       printf ("%-31s  %11d  %#18" PRIx64,
                                newFileName, state_machine_regs.line,
                                state_machine_regs.address);
                    }
                  else
                    {
                      if (xop == -DW_LNE_end_sequence)
-                       printf ("%-35s  %11s  %#18" PRIx64 "[%d]",
+                       printf ("%-31s  %11s  %#18" PRIx64 "[%d]",
                                newFileName, "-",
                                state_machine_regs.address,
                                state_machine_regs.op_index);
                      else
-                       printf ("%-35s  %11d  %#18" PRIx64 "[%d]",
+                       printf ("%-31s  %11d  %#18" PRIx64 "[%d]",
                                newFileName, state_machine_regs.line,
                                state_machine_regs.address,
                                state_machine_regs.op_index);
@@ -5740,7 +6014,7 @@ display_debug_pubnames_worker (struct dwarf_section *section,
              names.pn_length);
       printf (_("  Version:                             %d\n"),
              names.pn_version);
-      printf (_("  Offset into .debug_info section:     0x%" PRIx64 "\n"),
+      printf (_("  Offset into .debug_info section:     %#" PRIx64 "\n"),
              names.pn_offset);
       printf (_("  Size of area in .debug_info section: %" PRId64 "\n"),
              names.pn_size);
@@ -6040,13 +6314,13 @@ display_debug_macro (struct dwarf_section *section,
 
       SAFE_BYTE_GET_AND_INC (flags, curr, 1, end);
       offset_size = (flags & 1) ? 8 : 4;
-      printf (_("  Offset:                      0x%" PRIx64 "\n"), sec_offset);
+      printf (_("  Offset:                      %#" PRIx64 "\n"), sec_offset);
       printf (_("  Version:                     %d\n"), version);
       printf (_("  Offset size:                 %d\n"), offset_size);
       if (flags & 2)
        {
          SAFE_BYTE_GET_AND_INC (line_offset, curr, offset_size, end);
-         printf (_("  Offset into .debug_line:     0x%" PRIx64 "\n"),
+         printf (_("  Offset into .debug_line:     %#" PRIx64 "\n"),
                  line_offset);
        }
       if (flags & 4)
@@ -6196,7 +6470,7 @@ display_debug_macro (struct dwarf_section *section,
 
            case DW_MACRO_import:
              SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
-             printf (_(" DW_MACRO_import - offset : 0x%" PRIx64 "\n"),
+             printf (_(" DW_MACRO_import - offset : %#" PRIx64 "\n"),
                      offset);
              break;
 
@@ -6204,7 +6478,7 @@ display_debug_macro (struct dwarf_section *section,
              READ_ULEB (lineno, curr, end);
              SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
              printf (_(" DW_MACRO_define_sup - lineno : %d"
-                       " macro offset : 0x%" PRIx64 "\n"),
+                       " macro offset : %#" PRIx64 "\n"),
                      lineno, offset);
              break;
 
@@ -6212,13 +6486,13 @@ display_debug_macro (struct dwarf_section *section,
              READ_ULEB (lineno, curr, end);
              SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
              printf (_(" DW_MACRO_undef_sup - lineno : %d"
-                       " macro offset : 0x%" PRIx64 "\n"),
+                       " macro offset : %#" PRIx64 "\n"),
                      lineno, offset);
              break;
 
            case DW_MACRO_import_sup:
              SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
-             printf (_(" DW_MACRO_import_sup - offset : 0x%" PRIx64 "\n"),
+             printf (_(" DW_MACRO_import_sup - offset : %#" PRIx64 "\n"),
                      offset);
              break;
 
@@ -6233,7 +6507,7 @@ display_debug_macro (struct dwarf_section *section,
              else
                printf (" DW_MACRO_undef_strx ");
              if (do_wide)
-               printf (_("(with offset %" PRIx64 ") "), offset);
+               printf (_("(with offset %#" PRIx64 ") "), offset);
              printf (_("lineno : %d macro : %s\n"),
                      lineno, string);
              break;
@@ -6308,7 +6582,7 @@ display_debug_abbrev (struct dwarf_section *section,
        break;
 
       if (list->first_abbrev)
-       printf (_("  Number TAG (0x%" PRIx64 ")\n"), offset);
+       printf (_("  Number TAG (%#" PRIx64 ")\n"), offset);
 
       for (entry = list->first_abbrev; entry; entry = entry->next)
        {
@@ -6948,7 +7222,7 @@ display_offset_entry_loclists (struct dwarf_section *section)
       uint32_t i;
       bool is_64bit;
 
-      printf (_("Table at Offset 0x%tx\n"), start - section->start);
+      printf (_("Table at Offset %#tx\n"), start - section->start);
 
       SAFE_BYTE_GET_AND_INC (length, start, 4, end);
       if (length == 0xffffffff)
@@ -6964,7 +7238,7 @@ display_offset_entry_loclists (struct dwarf_section *section)
       SAFE_BYTE_GET_AND_INC (segment_selector_size, start, 1, end);
       SAFE_BYTE_GET_AND_INC (offset_entry_count, start, 4, end);
 
-      printf (_("  Length:          0x%" PRIx64 "\n"), length);
+      printf (_("  Length:          %#" PRIx64 "\n"), length);
       printf (_("  DWARF version:   %u\n"), version);
       printf (_("  Address size:    %u\n"), address_size);
       printf (_("  Segment size:    %u\n"), segment_selector_size);
@@ -6993,7 +7267,7 @@ display_offset_entry_loclists (struct dwarf_section *section)
          return 0;
        }
 
-      printf (_("\n   Offset Entries starting at 0x%tx:\n"),
+      printf (_("\n   Offset Entries starting at %#tx:\n"),
              start - section->start);
 
       for (i = 0; i < offset_entry_count; i++)
@@ -7001,7 +7275,7 @@ display_offset_entry_loclists (struct dwarf_section *section)
          uint64_t entry;
 
          SAFE_BYTE_GET_AND_INC (entry, start, is_64bit ? 8 : 4, end);
-         printf (_("    [%6u] 0x%" PRIx64 "\n"), i, entry);
+         printf (_("    [%6u] %#" PRIx64 "\n"), i, entry);
        }
 
       putchar ('\n');
@@ -7147,7 +7421,7 @@ display_debug_loc (struct dwarf_section *section, void *file)
   const char *suffix = strrchr (section->name, '.');
   bool is_dwo = false;
   int is_loclists = strstr (section->name, "debug_loclists") != NULL;
-  uint64_t expected_start = 0;
+  uint64_t header_size = 0;
 
   if (suffix && strcmp (suffix, ".dwo") == 0)
     is_dwo = true;
@@ -7198,7 +7472,7 @@ display_debug_loc (struct dwarf_section *section, void *file)
       if (offset_entry_count != 0)
        return display_offset_entry_loclists (section);
 
-      expected_start = hdrptr - section_begin;
+      header_size = hdrptr - section_begin;
     }
 
   if (load_debug_info (file) == 0)
@@ -7254,12 +7528,12 @@ display_debug_loc (struct dwarf_section *section, void *file)
     error (_("No location lists in .debug_info section!\n"));
 
   if (debug_information [first].num_loc_offsets > 0
-      && debug_information [first].loc_offsets [0] != expected_start
-      && debug_information [first].loc_views [0] != expected_start)
+      && debug_information [first].loc_offsets [0] != header_size
+      && debug_information [first].loc_views [0] != header_size)
     warn (_("Location lists in %s section start at %#" PRIx64
            " rather than %#" PRIx64 "\n"),
          section->name, debug_information [first].loc_offsets [0],
-         expected_start);
+         header_size);
 
   if (!locs_sorted)
     array = (unsigned int *) xcmalloc (num_loc_list, sizeof (unsigned int));
@@ -7271,10 +7545,9 @@ display_debug_loc (struct dwarf_section *section, void *file)
 
   printf (_("    Offset   Begin            End              Expression\n"));
 
-  seen_first_offset = 0;
   for (i = first; i < num_debug_info_entries; i++)
     {
-      uint64_t offset, voffset;
+      uint64_t offset = 0, voffset = 0;
       uint64_t base_address;
       unsigned int k;
       int has_frame_base;
@@ -7289,6 +7562,24 @@ display_debug_loc (struct dwarf_section *section, void *file)
                 sizeof (*array), loc_offsets_compar);
        }
 
+      /* .debug_loclists has a per-unit header.
+        Update start if we are detecting it.  */
+      if (debug_information [i].dwarf_version == 5)
+       {
+         j = locs_sorted ? 0 : array [0];
+
+         if (debug_information [i].num_loc_offsets)
+           offset = debug_information [i].loc_offsets [j];
+
+         if (debug_information [i].num_loc_views)
+           voffset = debug_information [i].loc_views [j];
+
+         /* Assume that the size of the header is constant across CUs. */
+         if (((start - section_begin) + header_size == offset)
+             || ((start -section_begin) + header_size == voffset))
+           start += header_size;
+       }
+
       int adjacent_view_loclists = 1;
       for (k = 0; k < debug_information [i].num_loc_offsets; k++)
        {
@@ -7319,19 +7610,21 @@ display_debug_loc (struct dwarf_section *section, void *file)
                start = vstart;
            }
 
-         if (!seen_first_offset || !adjacent_view_loclists)
-           seen_first_offset = 1;
-         else
+         if (start < next)
            {
-             if (start < next)
+             if (vnext && vnext < next)
                warn (_("There is a hole [%#tx - %#" PRIx64 "]"
                        " in %s section.\n"),
-                     start - section_begin, offset, section->name);
-             else if (start > next)
-               warn (_("There is an overlap [%#tx - %#" PRIx64 "]"
+                     start - section_begin, voffset, section->name);
+             else
+               warn (_("There is a hole [%#tx - %#" PRIx64 "]"
                        " in %s section.\n"),
                      start - section_begin, offset, section->name);
            }
+         else if (start > next)
+           warn (_("There is an overlap [%#tx - %#" PRIx64 "]"
+                   " in %s section.\n"),
+                 start - section_begin, offset, section->name);
          start = next;
          vstart = vnext;
 
@@ -7545,7 +7838,7 @@ display_debug_aranges (struct dwarf_section *section,
 
       printf (_("  Length:                   %" PRId64 "\n"), arange.ar_length);
       printf (_("  Version:                  %d\n"), arange.ar_version);
-      printf (_("  Offset into .debug_info:  0x%" PRIx64 "\n"),
+      printf (_("  Offset into .debug_info:  %#" PRIx64 "\n"),
              arange.ar_info_offset);
       printf (_("  Pointer Size:             %d\n"), arange.ar_pointer_size);
       printf (_("  Segment Size:             %d\n"), arange.ar_segment_size);
@@ -7588,7 +7881,7 @@ display_debug_aranges (struct dwarf_section *section,
                                 end_ranges);
          printf ("    ");
          print_hex (address, address_size);
-         print_hex (length, address_size);
+         print_hex_ns (length, address_size);
          putchar ('\n');
        }
 
@@ -7667,7 +7960,7 @@ display_debug_addr (struct dwarf_section *section,
       unsigned int idx;
       unsigned int address_size = debug_addr_info [i]->pointer_size;
 
-      printf (_("  For compilation unit at offset 0x%" PRIx64 ":\n"),
+      printf (_("  For compilation unit at offset %#" PRIx64 ":\n"),
              debug_addr_info [i]->cu_offset);
 
       printf (_("\tIndex\tAddress\n"));
@@ -7690,8 +7983,14 @@ display_debug_addr (struct dwarf_section *section,
          SAFE_BYTE_GET_AND_INC (length, curr_header, 4, entry);
          if (length == 0xffffffff)
            SAFE_BYTE_GET_AND_INC (length, curr_header, 8, entry);
+         if (length > (size_t) (section->start + section->size - curr_header)
+             || length < (size_t) (entry - curr_header))
+           {
+             warn (_("Corrupt %s section: unit_length field of %#" PRIx64
+                     " is invalid\n"), section->name, length);
+             return 0;
+           }
          end = curr_header + length;
-
          SAFE_BYTE_GET_AND_INC (version, curr_header, 2, entry);
          if (version != 5)
            warn (_("Corrupt %s section: expecting version number 5 in header but found %d instead\n"),
@@ -7703,13 +8002,22 @@ display_debug_addr (struct dwarf_section *section,
        }
       else
        end = section->start + debug_addr_info [i + 1]->addr_base;
+
       header = end;
       idx = 0;
-      while (entry < end)
+
+      if (address_size < 1 || address_size > sizeof (uint64_t))
+       {
+         warn (_("Corrupt %s section: address size (%x) is wrong"),
+               section->name, address_size);
+         return 0;
+       }
+
+      while ((size_t) (end - entry) >= address_size)
        {
          uint64_t base = byte_get (entry, address_size);
          printf (_("\t%d:\t"), idx);
-         print_hex (base, address_size);
+         print_hex_ns (base, address_size);
          printf ("\n");
          entry += address_size;
          idx++;
@@ -7895,12 +8203,12 @@ display_debug_ranges_list (unsigned char *  start,
        }
 
       print_hex (begin + base_address, pointer_size);
-      print_hex (end + base_address, pointer_size);
+      print_hex_ns (end + base_address, pointer_size);
 
       if (begin == end)
-       fputs (_("(start == end)"), stdout);
+       fputs (_(" (start == end)"), stdout);
       else if (begin > end)
-       fputs (_("(start > end)"), stdout);
+       fputs (_(" (start > end)"), stdout);
 
       putchar ('\n');
     }
@@ -7912,15 +8220,9 @@ display_debug_rnglists_list (unsigned char * start,
                             unsigned int    pointer_size,
                             uint64_t        offset,
                             uint64_t        base_address,
-                            unsigned int    offset_size)
+                            uint64_t        addr_base)
 {
   unsigned char *next = start;
-  unsigned int debug_addr_section_hdr_len;
-
-  if (offset_size == 4)
-    debug_addr_section_hdr_len = 8;
-  else
-    debug_addr_section_hdr_len = 16;
 
   while (1)
     {
@@ -7950,24 +8252,24 @@ display_debug_rnglists_list (unsigned char * start,
          READ_ULEB (base_address, start, finish);
          print_hex (base_address, pointer_size);
          printf (_("(base address index) "));
-         base_address = fetch_indexed_addr ((base_address * pointer_size)
-                                            + debug_addr_section_hdr_len, pointer_size);
+         base_address = fetch_indexed_addr ((base_address * pointer_size) + addr_base,
+                                            pointer_size);
          print_hex (base_address, pointer_size);
          printf (_("(base address)\n"));
          break;
        case DW_RLE_startx_endx:
          READ_ULEB (begin, start, finish);
          READ_ULEB (end, start, finish);
-         begin = fetch_indexed_addr ((begin * pointer_size)
-                                     + debug_addr_section_hdr_len, pointer_size);
-         end   = fetch_indexed_addr ((begin * pointer_size)
-                                     + debug_addr_section_hdr_len, pointer_size);
+         begin = fetch_indexed_addr ((begin * pointer_size) + addr_base,
+                                     pointer_size);
+         end   = fetch_indexed_addr ((begin * pointer_size) + addr_base,
+                                     pointer_size);
          break;
        case DW_RLE_startx_length:
          READ_ULEB (begin, start, finish);
          READ_ULEB (length, start, finish);
-         begin = fetch_indexed_addr ((begin * pointer_size)
-                                     + debug_addr_section_hdr_len, pointer_size);
+         begin = fetch_indexed_addr ((begin * pointer_size) + addr_base,
+                                     pointer_size);
          end = begin + length;
          break;
        case DW_RLE_offset_pair:
@@ -8021,126 +8323,110 @@ display_debug_rnglists_list (unsigned char * start,
 }
 
 static int
-display_debug_rnglists (struct dwarf_section *section)
-{
-  unsigned char *start = section->start;
-  unsigned char *finish = start + section->size;
+display_debug_rnglists_unit_header (struct dwarf_section *  section,
+                                   uint64_t *              unit_offset,
+                                   unsigned char *         poffset_size)
+{
+  uint64_t        start_offset = *unit_offset;
+  unsigned char * p = section->start + start_offset;
+  unsigned char * finish = section->start + section->size;
+  uint64_t        initial_length;
+  unsigned char   segment_selector_size;
+  unsigned int    offset_entry_count;
+  unsigned int    i;
+  unsigned short  version;
+  unsigned char   address_size = 0;
+  unsigned char   offset_size;
 
-  while (start < finish)
-    {
-      unsigned char *table_start;
-      uint64_t offset = start - section->start;
-      unsigned char *end;
-      uint64_t initial_length;
-      unsigned char segment_selector_size;
-      unsigned int offset_entry_count;
-      unsigned int i;
-      unsigned short version;
-      unsigned char address_size = 0;
-      unsigned char offset_size;
+  /* Get and check the length of the block.  */
+  SAFE_BYTE_GET_AND_INC (initial_length, p, 4, finish);
 
-      /* Get and check the length of the block.  */
-      SAFE_BYTE_GET_AND_INC (initial_length, start, 4, finish);
+  if (initial_length == 0xffffffff)
+    {
+      /* This section is 64-bit DWARF 3.  */
+      SAFE_BYTE_GET_AND_INC (initial_length, p, 8, finish);
+      *poffset_size = offset_size = 8;
+    }
+  else
+    *poffset_size = offset_size = 4;
 
-      if (initial_length == 0xffffffff)
-       {
-         /* This section is 64-bit DWARF 3.  */
-         SAFE_BYTE_GET_AND_INC (initial_length, start, 8, finish);
-         offset_size = 8;
-       }
+  if (initial_length > (size_t) (finish - p))
+    {
+      /* If the length field has a relocation against it, then we should
+        not complain if it is inaccurate (and probably negative).
+        It is copied from .debug_line handling code.  */
+      if (reloc_at (section, (p - section->start) - offset_size))
+       initial_length = finish - p;
       else
-       offset_size = 4;
-
-      if (initial_length > (size_t) (finish - start))
        {
-         /* If the length field has a relocation against it, then we should
-            not complain if it is inaccurate (and probably negative).
-            It is copied from .debug_line handling code.  */
-         if (reloc_at (section, (start - section->start) - offset_size))
-           initial_length = finish - start;
-         else
-           {
-             warn (_("The length field (%#" PRIx64
-                     ") in the debug_rnglists header is wrong"
-                     " - the section is too small\n"),
-                   initial_length);
-             return 0;
-           }
-       }
-
-      end = start + initial_length;
-
-      /* Get the other fields in the header.  */
-      SAFE_BYTE_GET_AND_INC (version, start, 2, finish);
-      SAFE_BYTE_GET_AND_INC (address_size, start, 1, finish);
-      SAFE_BYTE_GET_AND_INC (segment_selector_size, start, 1, finish);
-      SAFE_BYTE_GET_AND_INC (offset_entry_count, start, 4, finish);
-
-      printf (_(" Table at Offset: 0x%" PRIx64 ":\n"), offset);
-      printf (_("  Length:          0x%" PRIx64 "\n"), initial_length);
-      printf (_("  DWARF version:   %u\n"), version);
-      printf (_("  Address size:    %u\n"), address_size);
-      printf (_("  Segment size:    %u\n"), segment_selector_size);
-      printf (_("  Offset entries:  %u\n"), offset_entry_count);
-
-      /* Check the fields.  */
-      if (segment_selector_size != 0)
-       {
-         warn (_("The %s section contains "
-                 "unsupported segment selector size: %d.\n"),
-               section->name, segment_selector_size);
+         warn (_("The length field (%#" PRIx64
+                 ") in the debug_rnglists header is wrong"
+                 " - the section is too small\n"),
+               initial_length);
          return 0;
        }
+    }
 
-      if (version < 5)
-       {
-         warn (_("Only DWARF version 5+ debug_rnglists info "
-                 "is currently supported.\n"));
-         return 0;
-       }
+  /* Report the next unit offset to the caller.  */
+  *unit_offset = (p - section->start) + initial_length;
 
-      table_start = start;
+  /* Get the other fields in the header.  */
+  SAFE_BYTE_GET_AND_INC (version, p, 2, finish);
+  SAFE_BYTE_GET_AND_INC (address_size, p, 1, finish);
+  SAFE_BYTE_GET_AND_INC (segment_selector_size, p, 1, finish);
+  SAFE_BYTE_GET_AND_INC (offset_entry_count, p, 4, finish);
 
-      if (offset_entry_count != 0)
-       {
-         printf (_("\n   Offsets starting at 0x%tx:\n"),
-                 start - section->start);
+  printf (_(" Table at Offset: %#" PRIx64 ":\n"), start_offset);
+  printf (_("  Length:          %#" PRIx64 "\n"), initial_length);
+  printf (_("  DWARF version:   %u\n"), version);
+  printf (_("  Address size:    %u\n"), address_size);
+  printf (_("  Segment size:    %u\n"), segment_selector_size);
+  printf (_("  Offset entries:  %u\n"), offset_entry_count);
 
-         for (i = 0; i < offset_entry_count; i++)
-           {
-             uint64_t entry;
+  /* Check the fields.  */
+  if (segment_selector_size != 0)
+    {
+      warn (_("The %s section contains "
+             "unsupported segment selector size: %d.\n"),
+           section->name, segment_selector_size);
+      return 0;
+    }
 
-             SAFE_BYTE_GET_AND_INC (entry, start, offset_size, finish);
-             printf (_("    [%6u] 0x%" PRIx64 "\n"), i, entry);
-           }
-       }
-      else
-       offset_entry_count = 1;
+  if (version < 5)
+    {
+      warn (_("Only DWARF version 5+ debug_rnglists info "
+             "is currently supported.\n"));
+      return 0;
+    }
+
+  if (offset_entry_count != 0)
+    {
+      printf (_("\n   Offsets starting at %#tx:\n"), p - section->start);
 
       for (i = 0; i < offset_entry_count; i++)
        {
-         uint64_t indx = start - table_start;
+         uint64_t entry;
 
-         offset = start - section->start;
-         printf (_("\n  Offset: %" PRIx64 ", Index: 0x%" PRIx64 "\n"),
-                 offset, indx);
-         printf (_("    Offset   Begin    End\n"));
-         start = display_debug_rnglists_list
-           (start, end, address_size, offset, 0, offset_size);
-         if (start >= end)
-           break;
+         SAFE_BYTE_GET_AND_INC (entry, p, offset_size, finish);
+         printf (_("    [%6u] %#" PRIx64 "\n"), i, entry);
        }
-
-      start = end;
-
-      if (start < finish)
-       putchar ('\n');
     }
 
-  putchar ('\n');
   return 1;
 }
 
+static bool
+is_range_list_for_this_section (bool is_rnglists, unsigned int version)
+{
+  if (is_rnglists && version > 4)
+    return true;
+
+  if (! is_rnglists && version < 5)
+    return true;
+
+  return false;
+}
+
 static int
 display_debug_ranges (struct dwarf_section *section,
                      void *file ATTRIBUTE_UNUSED)
@@ -8153,10 +8439,10 @@ display_debug_ranges (struct dwarf_section *section,
   unsigned int num_range_list, i;
   struct range_entry *range_entries;
   struct range_entry *range_entry_fill;
-  int is_rnglists = strstr (section->name, "debug_rnglists") != NULL;
-  /* Initialize it due to a false compiler warning.  */
-  unsigned char address_size = 0;
+  bool is_rnglists = strstr (section->name, "debug_rnglists") != NULL;
   uint64_t last_offset = 0;
+  uint64_t next_rnglists_cu_offset = 0;
+  unsigned char offset_size;
 
   if (bytes == 0)
     {
@@ -8165,10 +8451,7 @@ display_debug_ranges (struct dwarf_section *section,
     }
 
   introduce (section, false);
-
-  if (is_rnglists)
-    return display_debug_rnglists (section);
-
+  
   if (load_debug_info (file) == 0)
     {
       warn (_("Unable to load/parse the .debug_info section, so cannot interpret the %s section.\n"),
@@ -8178,19 +8461,18 @@ display_debug_ranges (struct dwarf_section *section,
 
   num_range_list = 0;
   for (i = 0; i < num_debug_info_entries; i++)
-    num_range_list += debug_information [i].num_range_lists;
+    if (is_range_list_for_this_section (is_rnglists, debug_information [i].dwarf_version))
+      num_range_list += debug_information [i].num_range_lists;
 
   if (num_range_list == 0)
     {
       /* This can happen when the file was compiled with -gsplit-debug
         which removes references to range lists from the primary .o file.  */
-      printf (_("No range lists in .debug_info section.\n"));
+      printf (_("No range lists referenced by .debug_info section.\n"));
       return 1;
     }
 
-  range_entries = (struct range_entry *)
-      xmalloc (sizeof (*range_entries) * num_range_list);
-  range_entry_fill = range_entries;
+  range_entry_fill = range_entries = XNEWVEC (struct range_entry, num_range_list);
 
   for (i = 0; i < num_debug_info_entries; i++)
     {
@@ -8199,12 +8481,18 @@ display_debug_ranges (struct dwarf_section *section,
 
       for (j = 0; j < debug_info_p->num_range_lists; j++)
        {
-         range_entry_fill->ranges_offset = debug_info_p->range_lists[j];
-         range_entry_fill->debug_info_p = debug_info_p;
-         range_entry_fill++;
+         if (is_range_list_for_this_section (is_rnglists, debug_info_p->dwarf_version))
+           {
+             range_entry_fill->ranges_offset = debug_info_p->range_lists[j];
+             range_entry_fill->debug_info_p = debug_info_p;
+             range_entry_fill++;
+           }
        }
     }
 
+  assert (range_entry_fill >= range_entries);
+  assert (num_range_list >= (unsigned int)(range_entry_fill - range_entries));
+  num_range_list = range_entry_fill - range_entries;
   qsort (range_entries, num_range_list, sizeof (*range_entries),
         range_entry_compar);
 
@@ -8213,7 +8501,8 @@ display_debug_ranges (struct dwarf_section *section,
          section->name, range_entries[0].ranges_offset);
 
   putchar ('\n');
-  printf (_("    Offset   Begin    End\n"));
+  if (!is_rnglists)
+    printf (_("    Offset   Begin    End\n"));
 
   for (i = 0; i < num_range_list; i++)
     {
@@ -8224,7 +8513,7 @@ display_debug_ranges (struct dwarf_section *section,
       unsigned char *next;
       uint64_t base_address;
 
-      pointer_size = (is_rnglists ? address_size : debug_info_p->pointer_size);
+      pointer_size = debug_info_p->pointer_size;
       offset = range_entry->ranges_offset;
       base_address = debug_info_p->base_address;
 
@@ -8243,8 +8532,16 @@ display_debug_ranges (struct dwarf_section *section,
          continue;
        }
 
-      next = section_begin + offset + debug_info_p->rnglists_base;
+      /* If we've moved on to the next compile unit in the rnglists section - dump the unit header(s).  */
+      if (is_rnglists && next_rnglists_cu_offset < offset)
+       {
+         while (next_rnglists_cu_offset < offset)
+           display_debug_rnglists_unit_header (section, &next_rnglists_cu_offset, &offset_size);
+         printf (_("    Offset   Begin    End\n"));
+       }
 
+      next = section_begin + offset; /* Offset is from the section start, the base has already been added.  */
+      
       /* 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
@@ -8271,9 +8568,19 @@ display_debug_ranges (struct dwarf_section *section,
       start = next;
       last_start = next;
 
-      display_debug_ranges_list
-       (start, finish, pointer_size, offset, base_address);
+      if (is_rnglists)
+        display_debug_rnglists_list
+         (start, finish, pointer_size, offset, base_address, debug_info_p->addr_base);
+      else
+        display_debug_ranges_list
+         (start, finish, pointer_size, offset, base_address);
     }
+
+  /* Display trailing empty (or unreferenced) compile units, if any.  */
+  if (is_rnglists)
+    while (next_rnglists_cu_offset < section->size)
+      display_debug_rnglists_unit_header (section, &next_rnglists_cu_offset, &offset_size);
+
   putchar ('\n');
 
   free (range_entries);
@@ -8288,7 +8595,7 @@ typedef struct Frame_Chunk
   unsigned int ncols;
   /* DW_CFA_{undefined,same_value,offset,register,unreferenced}  */
   short int *col_type;
-  int *col_offset;
+  int64_t *col_offset;
   char *augmentation;
   unsigned int code_factor;
   int data_factor;
@@ -8345,9 +8652,10 @@ frame_need_space (Frame_Chunk *fc, unsigned int reg)
       return -1;
     }
 
-  fc->col_type = (short int *) xcrealloc (fc->col_type, fc->ncols,
-                                         sizeof (short int));
-  fc->col_offset = (int *) xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
+  fc->col_type = xcrealloc (fc->col_type, fc->ncols,
+                           sizeof (*fc->col_type));
+  fc->col_offset = xcrealloc (fc->col_offset, fc->ncols,
+                             sizeof (*fc->col_offset));
   /* PR 17512: file:002-10025-0.005.  */
   if (fc->col_type == NULL || fc->col_offset == NULL)
     {
@@ -8529,16 +8837,24 @@ init_dwarf_regnames_s390 (void)
 
 static const char *const dwarf_regnames_riscv[] =
 {
- "zero", "ra",   "sp",   "gp",  "tp",  "t0",  "t1",  "t2",  /* 0  - 7 */
- "s0",   "s1",   "a0",   "a1",  "a2",  "a3",  "a4",  "a5",  /* 8  - 15 */
- "a6",   "a7",   "s2",   "s3",  "s4",  "s5",  "s6",  "s7",  /* 16 - 23 */
- "s8",   "s9",   "s10",  "s11", "t3",  "t4",  "t5",  "t6",  /* 24 - 31 */
- "ft0",  "ft1",  "ft2",  "ft3", "ft4", "ft5", "ft6", "ft7", /* 32 - 39 */
- "fs0",  "fs1",                                             /* 40 - 41 */
- "fa0",  "fa1",  "fa2",  "fa3", "fa4", "fa5", "fa6", "fa7", /* 42 - 49 */
- "fs2",  "fs3",  "fs4",  "fs5", "fs6", "fs7", "fs8", "fs9", /* 50 - 57 */
- "fs10", "fs11",                                            /* 58 - 59 */
- "ft8",  "ft9",  "ft10", "ft11"                             /* 60 - 63 */
+ "zero", "ra",   "sp",   "gp",  "tp",  "t0",  "t1",  "t2",  /*   0 -   7 */
+ "s0",   "s1",   "a0",   "a1",  "a2",  "a3",  "a4",  "a5",  /*   8 -  15 */
+ "a6",   "a7",   "s2",   "s3",  "s4",  "s5",  "s6",  "s7",  /*  16 -  23 */
+ "s8",   "s9",   "s10",  "s11", "t3",  "t4",  "t5",  "t6",  /*  24 -  31 */
+ "ft0",  "ft1",  "ft2",  "ft3", "ft4", "ft5", "ft6", "ft7", /*  32 -  39 */
+ "fs0",  "fs1",                                             /*  40 -  41 */
+ "fa0",  "fa1",  "fa2",  "fa3", "fa4", "fa5", "fa6", "fa7", /*  42 -  49 */
+ "fs2",  "fs3",  "fs4",  "fs5", "fs6", "fs7", "fs8", "fs9", /*  50 -  57 */
+ "fs10", "fs11",                                            /*  58 -  59 */
+ "ft8",  "ft9",  "ft10", "ft11",                            /*  60 -  63 */
+ NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,     /*  64 -  71 */
+ NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,     /*  72 -  79 */
+ NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,     /*  80 -  87 */
+ NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,     /*  88 -  95 */
+ "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",     /*  96 - 103 */
+ "v8",  "v9",  "v10", "v11", "v12", "v13", "v14", "v15",    /* 104 - 111 */
+ "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",    /* 112 - 119 */
+ "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",    /* 120 - 127 */
 };
 
 /* A RISC-V replacement for REGNAME_INTERNAL_BY_TABLE_ONLY which handles
@@ -8752,10 +9068,10 @@ frame_display_row (Frame_Chunk *fc, int *need_col_headers, unsigned int *max_reg
              strcpy (tmp, "s");
              break;
            case DW_CFA_offset:
-             sprintf (tmp, "c%+d", fc->col_offset[r]);
+             sprintf (tmp, "c%+" PRId64, fc->col_offset[r]);
              break;
            case DW_CFA_val_offset:
-             sprintf (tmp, "v%+d", fc->col_offset[r]);
+             sprintf (tmp, "v%+" PRId64, fc->col_offset[r]);
              break;
            case DW_CFA_register:
              sprintf (tmp, "%s", regname (fc->col_offset[r], 0));
@@ -8796,8 +9112,8 @@ read_cie (unsigned char *start, unsigned char *end,
   fc = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
   memset (fc, 0, sizeof (Frame_Chunk));
 
-  fc->col_type = (short int *) xmalloc (sizeof (short int));
-  fc->col_offset = (int *) xmalloc (sizeof (int));
+  fc->col_type = xmalloc (sizeof (*fc->col_type));
+  fc->col_offset = xmalloc (sizeof (*fc->col_offset));
 
   version = *start++;
 
@@ -9171,8 +9487,8 @@ display_debug_frames (struct dwarf_section *section,
          if (!cie)
            {
              fc->ncols = 0;
-             fc->col_type = (short int *) xmalloc (sizeof (short int));
-             fc->col_offset = (int *) xmalloc (sizeof (int));
+             fc->col_type = xmalloc (sizeof (*fc->col_type));
+             fc->col_offset = xmalloc (sizeof (*fc->col_offset));
              if (frame_need_space (fc, max_regs > 0 ? max_regs - 1 : 0) < 0)
                {
                  warn (_("Invalid max register\n"));
@@ -9187,10 +9503,12 @@ display_debug_frames (struct dwarf_section *section,
          else
            {
              fc->ncols = cie->ncols;
-             fc->col_type = (short int *) xcmalloc (fc->ncols, sizeof (short int));
-             fc->col_offset =  (int *) xcmalloc (fc->ncols, sizeof (int));
-             memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int));
-             memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int));
+             fc->col_type = xcmalloc (fc->ncols, sizeof (*fc->col_type));
+             fc->col_offset =  xcmalloc (fc->ncols, sizeof (*fc->col_offset));
+             memcpy (fc->col_type, cie->col_type,
+                     fc->ncols * sizeof (*fc->col_type));
+             memcpy (fc->col_offset, cie->col_offset,
+                     fc->ncols * sizeof (*fc->col_offset));
              fc->augmentation = cie->augmentation;
              fc->ptr_size = cie->ptr_size;
              eh_addr_size = cie->ptr_size;
@@ -9435,14 +9753,12 @@ display_debug_frames (struct dwarf_section *section,
       while (start < block_end)
        {
          unsigned op, opa;
-         unsigned long ul, roffs;
          /* Note: It is tempting to use an unsigned long for 'reg' but there
             are various functions, notably frame_space_needed() that assume that
             reg is an unsigned int.  */
          unsigned int reg;
-         int64_t l;
+         int64_t sofs;
          uint64_t ofs;
-         uint64_t vma;
          const char *reg_prefix = "";
 
          op = *start++;
@@ -9459,31 +9775,30 @@ display_debug_frames (struct dwarf_section *section,
          switch (op)
            {
            case DW_CFA_advance_loc:
+             opa *= fc->code_factor;
              if (do_debug_frames_interp)
                frame_display_row (fc, &need_col_headers, &max_regs);
              else
                {
-                 printf ("  DW_CFA_advance_loc: %d to ",
-                       opa * fc->code_factor);
-                 print_hex_ns (fc->pc_begin + opa * fc->code_factor,
-                               fc->ptr_size);
+                 printf ("  DW_CFA_advance_loc: %d to ", opa);
+                 print_hex_ns (fc->pc_begin + opa, fc->ptr_size);
                  printf ("\n");
                }
-             fc->pc_begin += opa * fc->code_factor;
+             fc->pc_begin += opa;
              break;
 
            case DW_CFA_offset:
-             READ_ULEB (roffs, start, block_end);
+             READ_ULEB (ofs, start, block_end);
+             ofs *= fc->data_factor;
              if (opa >= fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
-               printf ("  DW_CFA_offset: %s%s at cfa%+ld\n",
-                       reg_prefix, regname (opa, 0),
-                       roffs * fc->data_factor);
+               printf ("  DW_CFA_offset: %s%s at cfa%+" PRId64 "\n",
+                       reg_prefix, regname (opa, 0), ofs);
              if (*reg_prefix == '\0')
                {
                  fc->col_type[opa] = DW_CFA_offset;
-                 fc->col_offset[opa] = roffs * fc->data_factor;
+                 fc->col_offset[opa] = ofs;
                }
              break;
 
@@ -9510,93 +9825,90 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_set_loc:
-             vma = get_encoded_value (&start, fc->fde_encoding, section,
+             ofs = get_encoded_value (&start, fc->fde_encoding, section,
                                       block_end);
              if (do_debug_frames_interp)
                frame_display_row (fc, &need_col_headers, &max_regs);
              else
                {
                  printf ("  DW_CFA_set_loc: ");
-                 print_hex_ns (vma, fc->ptr_size);
+                 print_hex_ns (ofs, fc->ptr_size);
                  printf ("\n");
                }
-             fc->pc_begin = vma;
+             fc->pc_begin = ofs;
              break;
 
            case DW_CFA_advance_loc1:
              SAFE_BYTE_GET_AND_INC (ofs, start, 1, block_end);
+             ofs *= fc->code_factor;
              if (do_debug_frames_interp)
                frame_display_row (fc, &need_col_headers, &max_regs);
              else
                {
-                 printf ("  DW_CFA_advance_loc1: %" PRId64 " to ",
-                         ofs * fc->code_factor);
-                 print_hex_ns (fc->pc_begin + ofs * fc->code_factor,
-                               fc->ptr_size);
+                 printf ("  DW_CFA_advance_loc1: %" PRId64 " to ", ofs);
+                 print_hex_ns (fc->pc_begin + ofs, fc->ptr_size);
                  printf ("\n");
                }
-             fc->pc_begin += ofs * fc->code_factor;
+             fc->pc_begin += ofs;
              break;
 
            case DW_CFA_advance_loc2:
              SAFE_BYTE_GET_AND_INC (ofs, start, 2, block_end);
+             ofs *= fc->code_factor;
              if (do_debug_frames_interp)
                frame_display_row (fc, &need_col_headers, &max_regs);
              else
                {
-                 printf ("  DW_CFA_advance_loc2: %" PRId64 " to ",
-                         ofs * fc->code_factor);
-                 print_hex_ns (fc->pc_begin + ofs * fc->code_factor,
-                               fc->ptr_size);
+                 printf ("  DW_CFA_advance_loc2: %" PRId64 " to ", ofs);
+                 print_hex_ns (fc->pc_begin + ofs, fc->ptr_size);
                  printf ("\n");
                }
-             fc->pc_begin += ofs * fc->code_factor;
+             fc->pc_begin += ofs;
              break;
 
            case DW_CFA_advance_loc4:
              SAFE_BYTE_GET_AND_INC (ofs, start, 4, block_end);
+             ofs *= fc->code_factor;
              if (do_debug_frames_interp)
                frame_display_row (fc, &need_col_headers, &max_regs);
              else
                {
-                 printf ("  DW_CFA_advance_loc4: %" PRId64 " to ",
-                         ofs * fc->code_factor);
-                 print_hex_ns (fc->pc_begin + ofs * fc->code_factor,
-                               fc->ptr_size);
+                 printf ("  DW_CFA_advance_loc4: %" PRId64 " to ", ofs);
+                 print_hex_ns (fc->pc_begin + ofs, fc->ptr_size);
                  printf ("\n");
                }
-             fc->pc_begin += ofs * fc->code_factor;
+             fc->pc_begin += ofs;
              break;
 
            case DW_CFA_offset_extended:
              READ_ULEB (reg, start, block_end);
-             READ_ULEB (roffs, start, block_end);
+             READ_ULEB (ofs, start, block_end);
+             ofs *= fc->data_factor;
              if (reg >= fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
-               printf ("  DW_CFA_offset_extended: %s%s at cfa%+ld\n",
-                       reg_prefix, regname (reg, 0),
-                       roffs * fc->data_factor);
+               printf ("  DW_CFA_offset_extended: %s%s at cfa%+" PRId64 "\n",
+                       reg_prefix, regname (reg, 0), ofs);
              if (*reg_prefix == '\0')
                {
                  fc->col_type[reg] = DW_CFA_offset;
-                 fc->col_offset[reg] = roffs * fc->data_factor;
+                 fc->col_offset[reg] = ofs;
                }
              break;
 
            case DW_CFA_val_offset:
              READ_ULEB (reg, start, block_end);
-             READ_ULEB (roffs, start, block_end);
+             READ_ULEB (ofs, start, block_end);
+             ofs *= fc->data_factor;
              if (reg >= fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
-               printf ("  DW_CFA_val_offset: %s%s is cfa%+ld\n",
-                       reg_prefix, regname (reg, 0),
-                       roffs * fc->data_factor);
+               printf ("  DW_CFA_val_offset: %s%s is cfa%+" PRId64 "\n",
+                       reg_prefix, regname (reg, 0), ofs);
              if (*reg_prefix == '\0')
                {
                  fc->col_type[reg] = DW_CFA_val_offset;
-                 fc->col_offset[reg] = roffs * fc->data_factor;
+                 fc->col_offset[reg] = ofs;
                }
              break;
 
@@ -9653,19 +9965,19 @@ display_debug_frames (struct dwarf_section *section,
 
            case DW_CFA_register:
              READ_ULEB (reg, start, block_end);
-             READ_ULEB (roffs, start, block_end);
+             READ_ULEB (ofs, start, block_end);
              if (reg >= fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
                {
                  printf ("  DW_CFA_register: %s%s in ",
                          reg_prefix, regname (reg, 0));
-                 puts (regname (roffs, 0));
+                 puts (regname (ofs, 0));
                }
              if (*reg_prefix == '\0')
                {
                  fc->col_type[reg] = DW_CFA_register;
-                 fc->col_offset[reg] = roffs;
+                 fc->col_offset[reg] = ofs;
                }
              break;
 
@@ -9678,11 +9990,12 @@ display_debug_frames (struct dwarf_section *section,
              rs->ra = fc->ra;
              rs->cfa_exp = fc->cfa_exp;
              rs->ncols = fc->ncols;
-             rs->col_type = (short int *) xcmalloc (rs->ncols,
-                                                    sizeof (* rs->col_type));
-             rs->col_offset = (int *) xcmalloc (rs->ncols, sizeof (* rs->col_offset));
-             memcpy (rs->col_type, fc->col_type, rs->ncols * sizeof (* fc->col_type));
-             memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (* fc->col_offset));
+             rs->col_type = xcmalloc (rs->ncols, sizeof (*rs->col_type));
+             rs->col_offset = xcmalloc (rs->ncols, sizeof (*rs->col_offset));
+             memcpy (rs->col_type, fc->col_type,
+                     rs->ncols * sizeof (*fc->col_type));
+             memcpy (rs->col_offset, fc->col_offset,
+                     rs->ncols * sizeof (*fc->col_offset));
              rs->next = remembered_state;
              remembered_state = rs;
              break;
@@ -9702,11 +10015,14 @@ display_debug_frames (struct dwarf_section *section,
                    {
                      warn (_("Invalid column number in saved frame state\n"));
                      fc->ncols = 0;
-                     break;
                    }
-                 memcpy (fc->col_type, rs->col_type, rs->ncols * sizeof (* rs->col_type));
-                 memcpy (fc->col_offset, rs->col_offset,
-                         rs->ncols * sizeof (* rs->col_offset));
+                 else
+                   {
+                     memcpy (fc->col_type, rs->col_type,
+                             rs->ncols * sizeof (*rs->col_type));
+                     memcpy (fc->col_offset, rs->col_offset,
+                             rs->ncols * sizeof (*rs->col_offset));
+                   }
                  free (rs->col_type);
                  free (rs->col_offset);
                  free (rs);
@@ -9744,33 +10060,35 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_def_cfa_expression:
-             READ_ULEB (ul, start, block_end);
-             if (ul > (size_t) (block_end - start))
+             READ_ULEB (ofs, start, block_end);
+             if (ofs > (size_t) (block_end - start))
                {
-                 printf (_("  DW_CFA_def_cfa_expression: <corrupt len %lu>\n"), ul);
+                 printf (_("  %s: <corrupt len %" PRIu64 ">\n"),
+                         "DW_CFA_def_cfa_expression", ofs);
                  break;
                }
              if (! do_debug_frames_interp)
                {
                  printf ("  DW_CFA_def_cfa_expression (");
                  decode_location_expression (start, eh_addr_size, 0, -1,
-                                             ul, 0, section);
+                                             ofs, 0, section);
                  printf (")\n");
                }
              fc->cfa_exp = 1;
-             start += ul;
+             start += ofs;
              break;
 
            case DW_CFA_expression:
              READ_ULEB (reg, start, block_end);
-             READ_ULEB (ul, start, block_end);
+             READ_ULEB (ofs, start, block_end);
              if (reg >= fc->ncols)
                reg_prefix = bad_reg;
              /* PR 17512: file: 069-133014-0.006.  */
              /* PR 17512: file: 98c02eb4.  */
-             if (ul > (size_t) (block_end - start))
+             if (ofs > (size_t) (block_end - start))
                {
-                 printf (_("  DW_CFA_expression: <corrupt len %lu>\n"), ul);
+                 printf (_("  %s: <corrupt len %" PRIu64 ">\n"),
+                         "DW_CFA_expression", ofs);
                  break;
                }
              if (! do_debug_frames_interp || *reg_prefix != '\0')
@@ -9778,22 +10096,23 @@ display_debug_frames (struct dwarf_section *section,
                  printf ("  DW_CFA_expression: %s%s (",
                          reg_prefix, regname (reg, 0));
                  decode_location_expression (start, eh_addr_size, 0, -1,
-                                             ul, 0, section);
+                                             ofs, 0, section);
                  printf (")\n");
                }
              if (*reg_prefix == '\0')
                fc->col_type[reg] = DW_CFA_expression;
-             start += ul;
+             start += ofs;
              break;
 
            case DW_CFA_val_expression:
              READ_ULEB (reg, start, block_end);
-             READ_ULEB (ul, start, block_end);
+             READ_ULEB (ofs, start, block_end);
              if (reg >= fc->ncols)
                reg_prefix = bad_reg;
-             if (ul > (size_t) (block_end - start))
+             if (ofs > (size_t) (block_end - start))
                {
-                 printf ("  DW_CFA_val_expression: <corrupt len %lu>\n", ul);
+                 printf ("  %s: <corrupt len %" PRIu64 ">\n",
+                         "DW_CFA_val_expression", ofs);
                  break;
                }
              if (! do_debug_frames_interp || *reg_prefix != '\0')
@@ -9801,78 +10120,84 @@ display_debug_frames (struct dwarf_section *section,
                  printf ("  DW_CFA_val_expression: %s%s (",
                          reg_prefix, regname (reg, 0));
                  decode_location_expression (start, eh_addr_size, 0, -1,
-                                             ul, 0, section);
+                                             ofs, 0, section);
                  printf (")\n");
                }
              if (*reg_prefix == '\0')
                fc->col_type[reg] = DW_CFA_val_expression;
-             start += ul;
+             start += ofs;
              break;
 
            case DW_CFA_offset_extended_sf:
              READ_ULEB (reg, start, block_end);
-             READ_SLEB (l, start, block_end);
+             READ_SLEB (sofs, start, block_end);
+             /* data_factor multiplicaton done here as unsigned to
+                avoid integer overflow warnings from asan on fuzzed
+                objects.  */
+             ofs = sofs;
+             ofs *= fc->data_factor;
              if (reg >= fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
                printf ("  DW_CFA_offset_extended_sf: %s%s at cfa%+" PRId64 "\n",
-                       reg_prefix, regname (reg, 0),
-                       l * fc->data_factor);
+                       reg_prefix, regname (reg, 0), ofs);
              if (*reg_prefix == '\0')
                {
                  fc->col_type[reg] = DW_CFA_offset;
-                 fc->col_offset[reg] = l * fc->data_factor;
+                 fc->col_offset[reg] = ofs;
                }
              break;
 
            case DW_CFA_val_offset_sf:
              READ_ULEB (reg, start, block_end);
-             READ_SLEB (l, start, block_end);
+             READ_SLEB (sofs, start, block_end);
+             ofs = sofs;
+             ofs *= fc->data_factor;
              if (reg >= fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
                printf ("  DW_CFA_val_offset_sf: %s%s is cfa%+" PRId64 "\n",
-                       reg_prefix, regname (reg, 0),
-                       l * fc->data_factor);
+                       reg_prefix, regname (reg, 0), ofs);
              if (*reg_prefix == '\0')
                {
                  fc->col_type[reg] = DW_CFA_val_offset;
-                 fc->col_offset[reg] = l * fc->data_factor;
+                 fc->col_offset[reg] = ofs;
                }
              break;
 
            case DW_CFA_def_cfa_sf:
              READ_ULEB (fc->cfa_reg, start, block_end);
-             READ_SLEB (l, start, block_end);
-             l *= fc->data_factor;
-             fc->cfa_offset = l;
+             READ_SLEB (sofs, start, block_end);
+             ofs = sofs;
+             ofs *= fc->data_factor;
+             fc->cfa_offset = ofs;
              fc->cfa_exp = 0;
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_def_cfa_sf: %s ofs %" PRId64 "\n",
-                       regname (fc->cfa_reg, 0), l);
+                       regname (fc->cfa_reg, 0), ofs);
              break;
 
            case DW_CFA_def_cfa_offset_sf:
-             READ_SLEB (l, start, block_end);
-             l *= fc->data_factor;
-             fc->cfa_offset = l;
+             READ_SLEB (sofs, start, block_end);
+             ofs = sofs;
+             ofs *= fc->data_factor;
+             fc->cfa_offset = ofs;
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_def_cfa_offset_sf: %" PRId64 "\n", l);
+               printf ("  DW_CFA_def_cfa_offset_sf: %" PRId64 "\n", ofs);
              break;
 
            case DW_CFA_MIPS_advance_loc8:
              SAFE_BYTE_GET_AND_INC (ofs, start, 8, block_end);
+             ofs *= fc->code_factor;
              if (do_debug_frames_interp)
                frame_display_row (fc, &need_col_headers, &max_regs);
              else
                {
-                 printf ("  DW_CFA_MIPS_advance_loc8: %" PRId64 " to ",
-                         ofs * fc->code_factor);
-                 print_hex_ns (fc->pc_begin + ofs * fc->code_factor,
-                               fc->ptr_size);
+                 printf ("  DW_CFA_MIPS_advance_loc8: %" PRId64 " to ", ofs);
+                 print_hex_ns (fc->pc_begin + ofs, fc->ptr_size);
                  printf ("\n");
                }
-             fc->pc_begin += ofs * fc->code_factor;
+             fc->pc_begin += ofs;
              break;
 
            case DW_CFA_GNU_window_save:
@@ -9881,26 +10206,26 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_GNU_args_size:
-             READ_ULEB (ul, start, block_end);
+             READ_ULEB (ofs, start, block_end);
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_GNU_args_size: %ld\n", ul);
+               printf ("  DW_CFA_GNU_args_size: %" PRIu64 "\n", ofs);
              break;
 
            case DW_CFA_GNU_negative_offset_extended:
              READ_ULEB (reg, start, block_end);
-             READ_SLEB (l, start, block_end);
-             l = - l;
+             READ_SLEB (sofs, start, block_end);
+             ofs = sofs;
+             ofs = -ofs * fc->data_factor;
              if (reg >= fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
                printf ("  DW_CFA_GNU_negative_offset_extended: %s%s "
                        "at cfa%+" PRId64 "\n",
-                       reg_prefix, regname (reg, 0),
-                       l * fc->data_factor);
+                       reg_prefix, regname (reg, 0), ofs);
              if (*reg_prefix == '\0')
                {
                  fc->col_type[reg] = DW_CFA_offset;
-                 fc->col_offset[reg] = l * fc->data_factor;
+                 fc->col_offset[reg] = ofs;
                }
              break;
 
@@ -10094,7 +10419,7 @@ display_debug_names (struct dwarf_section *section, void *file)
          uint64_t cu_offset;
 
          SAFE_BYTE_GET_AND_INC (cu_offset, hdrptr, offset_size, unit_end);
-         printf ("[%3u] 0x%" PRIx64 "\n", i, cu_offset);
+         printf ("[%3u] %#" PRIx64 "\n", i, cu_offset);
        }
       putchar ('\n');
 
@@ -10107,7 +10432,7 @@ display_debug_names (struct dwarf_section *section, void *file)
          uint64_t tu_offset;
 
          SAFE_BYTE_GET_AND_INC (tu_offset, hdrptr, offset_size, unit_end);
-         printf ("[%3u] 0x%" PRIx64 "\n", i, tu_offset);
+         printf ("[%3u] %#" PRIx64 "\n", i, tu_offset);
        }
       putchar ('\n');
 
@@ -10121,7 +10446,7 @@ display_debug_names (struct dwarf_section *section, void *file)
 
          SAFE_BYTE_GET_AND_INC (signature, hdrptr, 8, unit_end);
          printf (_("[%3u] "), i);
-         print_hex (signature, 8);
+         print_hex_ns (signature, 8);
          putchar ('\n');
        }
       putchar ('\n');
@@ -10427,29 +10752,31 @@ display_gdb_index (struct dwarf_section *section,
   unsigned char *start = section->start;
   uint32_t version;
   uint32_t cu_list_offset, tu_list_offset;
-  uint32_t address_table_offset, symbol_table_offset, constant_pool_offset;
+  uint32_t address_table_offset, symbol_table_offset, constant_pool_offset,
+    shortcut_table_offset;
   unsigned int cu_list_elements, tu_list_elements;
   unsigned int address_table_elements, symbol_table_slots;
   unsigned char *cu_list, *tu_list;
-  unsigned char *address_table, *symbol_table, *constant_pool;
+  unsigned char *address_table, *symbol_table, *shortcut_table, *constant_pool;
   unsigned int i;
 
   /* The documentation for the format of this file is in gdb/dwarf2read.c.  */
 
   introduce (section, false);
 
-  if (section->size < 6 * sizeof (uint32_t))
+  version = section->size < 4 ? 0 : byte_get_little_endian (start, 4);
+  size_t header_size = (version < 9 ? 6 : 7) * sizeof (uint32_t);
+  if (section->size < header_size)
     {
       warn (_("Truncated header in the %s section.\n"), section->name);
       return 0;
     }
 
-  version = byte_get_little_endian (start, 4);
   printf (_("Version %lu\n"), (unsigned long) version);
 
   /* Prior versions are obsolete, and future versions may not be
      backwards compatible.  */
-  if (version < 3 || version > 8)
+  if (version < 3 || version > 9)
     {
       warn (_("Unsupported version %lu.\n"), (unsigned long) version);
       return 0;
@@ -10471,17 +10798,23 @@ display_gdb_index (struct dwarf_section *section,
   tu_list_offset = byte_get_little_endian (start + 8, 4);
   address_table_offset = byte_get_little_endian (start + 12, 4);
   symbol_table_offset = byte_get_little_endian (start + 16, 4);
-  constant_pool_offset = byte_get_little_endian (start + 20, 4);
+  shortcut_table_offset = byte_get_little_endian (start + 20, 4);
+  if (version < 9)
+    constant_pool_offset = shortcut_table_offset;
+  else
+    constant_pool_offset = byte_get_little_endian (start + 24, 4);
 
   if (cu_list_offset > section->size
       || tu_list_offset > section->size
       || address_table_offset > section->size
       || symbol_table_offset > section->size
+      || shortcut_table_offset > section->size
       || constant_pool_offset > section->size
       || tu_list_offset < cu_list_offset
       || address_table_offset < tu_list_offset
       || symbol_table_offset < address_table_offset
-      || constant_pool_offset < symbol_table_offset)
+      || shortcut_table_offset < symbol_table_offset
+      || constant_pool_offset < shortcut_table_offset)
     {
       warn (_("Corrupt header in the %s section.\n"), section->name);
       return 0;
@@ -10490,12 +10823,13 @@ display_gdb_index (struct dwarf_section *section,
   cu_list_elements = (tu_list_offset - cu_list_offset) / 16;
   tu_list_elements = (address_table_offset - tu_list_offset) / 24;
   address_table_elements = (symbol_table_offset - address_table_offset) / 20;
-  symbol_table_slots = (constant_pool_offset - symbol_table_offset) / 8;
+  symbol_table_slots = (shortcut_table_offset - symbol_table_offset) / 8;
 
   cu_list = start + cu_list_offset;
   tu_list = start + tu_list_offset;
   address_table = start + address_table_offset;
   symbol_table = start + symbol_table_offset;
+  shortcut_table = start + shortcut_table_offset;
   constant_pool = start + constant_pool_offset;
 
   printf (_("\nCU table:\n"));
@@ -10504,7 +10838,7 @@ display_gdb_index (struct dwarf_section *section,
       uint64_t cu_offset = byte_get_little_endian (cu_list + i * 16, 8);
       uint64_t cu_length = byte_get_little_endian (cu_list + i * 16 + 8, 8);
 
-      printf ("[%3u] 0x%" PRIx64 " - 0x%" PRIx64 "\n",
+      printf ("[%3u] %#" PRIx64 " - %#" PRIx64 "\n",
              i, cu_offset, cu_offset + cu_length - 1);
     }
 
@@ -10515,9 +10849,9 @@ display_gdb_index (struct dwarf_section *section,
       uint64_t type_offset = byte_get_little_endian (tu_list + i * 24 + 8, 8);
       uint64_t signature = byte_get_little_endian (tu_list + i * 24 + 16, 8);
 
-      printf ("[%3u] 0x%" PRIx64 " 0x%" PRIx64 " ",
+      printf ("[%3u] %#" PRIx64 " %#" PRIx64 " ",
              i, tu_offset, type_offset);
-      print_hex (signature, 8);
+      print_hex_ns (signature, 8);
       printf ("\n");
     }
 
@@ -10526,7 +10860,7 @@ display_gdb_index (struct dwarf_section *section,
     {
       uint64_t low = byte_get_little_endian (address_table + i * 20, 8);
       uint64_t high = byte_get_little_endian (address_table + i * 20 + 8, 8);
-      uint32_t cu_index = byte_get_little_endian (address_table + i + 20 + 16, 4);
+      uint32_t cu_index = byte_get_little_endian (address_table + i * 20 + 16, 4);
 
       print_hex (low, 8);
       print_hex (high, 8);
@@ -10607,6 +10941,33 @@ display_gdb_index (struct dwarf_section *section,
        }
     }
 
+  if (version >= 9)
+    {
+      printf (_("\nShortcut table:\n"));
+
+      if (shortcut_table_offset + 8 > constant_pool_offset)
+       {
+         warn (_("Corrupt shortcut table in the %s section.\n"), section->name);
+         return 0;
+       }
+
+      uint32_t lang = byte_get_little_endian (shortcut_table, 4);
+      printf (_("Language of main: "));
+      display_lang (lang);
+      printf ("\n");
+
+      uint32_t name_offset = byte_get_little_endian (shortcut_table + 4, 4);
+      printf (_("Name of main: "));
+      if (name_offset >= section->size - constant_pool_offset)
+       {
+         printf (_("<corrupt offset: %x>\n"), name_offset);
+         warn (_("Corrupt name offset of 0x%x found for name of main\n"),
+               name_offset);
+       }
+      else
+       printf ("%s\n", constant_pool + name_offset);
+    }
+
   return 1;
 }
 
@@ -10615,6 +10976,10 @@ display_gdb_index (struct dwarf_section *section,
 static void
 prealloc_cu_tu_list (unsigned int nshndx)
 {
+  if (nshndx == 0)
+    /* Always allocate at least one entry for the end-marker.  */
+    nshndx = 1;
+
   if (shndx_pool == NULL)
     {
       shndx_pool_size = nshndx;
@@ -10633,22 +10998,12 @@ prealloc_cu_tu_list (unsigned int nshndx)
 static void
 add_shndx_to_cu_tu_entry (unsigned int shndx)
 {
-  if (shndx_pool_used >= shndx_pool_size)
-    {
-      error (_("Internal error: out of space in the shndx pool.\n"));
-      return;
-    }
   shndx_pool [shndx_pool_used++] = shndx;
 }
 
 static void
 end_cu_tu_entry (void)
 {
-  if (shndx_pool_used >= shndx_pool_size)
-    {
-      error (_("Internal error: out of space in the shndx pool.\n"));
-      return;
-    }
   shndx_pool [shndx_pool_used++] = 0;
 }
 
@@ -10689,7 +11044,7 @@ get_DW_SECT_short_name (unsigned int dw_sect)
    These sections are extensions for Fission.
    See http://gcc.gnu.org/wiki/DebugFissionDWP.  */
 
-static int
+static bool
 process_cu_tu_index (struct dwarf_section *section, int do_display)
 {
   unsigned char *phdr = section->start;
@@ -10710,14 +11065,14 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
   if (phdr == NULL)
     {
       warn (_("Section %s is empty\n"), section->name);
-      return 0;
+      return false;
     }
   /* PR 17512: file: 002-376-0.004.  */
   if (section->size < 24)
     {
       warn (_("Section %s is too small to contain a CU/TU header\n"),
            section->name);
-      return 0;
+      return false;
     }
 
   phash = phdr;
@@ -10749,58 +11104,60 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
                      "Section %s is too small for %u slots\n",
                      nslots),
            section->name, nslots);
-      return 0;
+      return false;
     }
 
   if (version == 1)
     {
+      unsigned char *shndx_list;
+      unsigned int shndx;
+
       if (!do_display)
-       prealloc_cu_tu_list ((limit - ppool) / 4);
-      for (i = 0; i < nslots; i++)
        {
-         unsigned char *shndx_list;
-         unsigned int shndx;
-
-         SAFE_BYTE_GET (signature, phash, 8, limit);
-         if (signature != 0)
+         prealloc_cu_tu_list ((limit - ppool) / 4);
+         for (shndx_list = ppool + 4; shndx_list <= limit - 4; shndx_list += 4)
            {
-             SAFE_BYTE_GET (j, pindex, 4, limit);
-             shndx_list = ppool + j * 4;
-             /* PR 17531: file: 705e010d.  */
-             if (shndx_list < ppool)
-               {
-                 warn (_("Section index pool located before start of section\n"));
-                 return 0;
-               }
+             shndx = byte_get (shndx_list, 4);
+             add_shndx_to_cu_tu_entry (shndx);
+           }
+         end_cu_tu_entry ();
+       }
+      else
+       for (i = 0; i < nslots; i++)
+         {
+           SAFE_BYTE_GET (signature, phash, 8, limit);
+           if (signature != 0)
+             {
+               SAFE_BYTE_GET (j, pindex, 4, limit);
+               shndx_list = ppool + j * 4;
+               /* PR 17531: file: 705e010d.  */
+               if (shndx_list < ppool)
+                 {
+                   warn (_("Section index pool located before start of section\n"));
+                   return false;
+                 }
 
-             if (do_display)
-               printf (_("  [%3d] Signature:  0x%" PRIx64 "  Sections: "),
+               printf (_("  [%3d] Signature:  %#" PRIx64 "  Sections: "),
                        i, signature);
-             for (;;)
-               {
-                 if (shndx_list >= limit)
-                   {
-                     warn (_("Section %s too small for shndx pool\n"),
-                           section->name);
-                     return 0;
-                   }
-                 SAFE_BYTE_GET (shndx, shndx_list, 4, limit);
-                 if (shndx == 0)
-                   break;
-                 if (do_display)
+               for (;;)
+                 {
+                   if (shndx_list >= limit)
+                     {
+                       warn (_("Section %s too small for shndx pool\n"),
+                             section->name);
+                       return false;
+                     }
+                   SAFE_BYTE_GET (shndx, shndx_list, 4, limit);
+                   if (shndx == 0)
+                     break;
                    printf (" %d", shndx);
-                 else
-                   add_shndx_to_cu_tu_entry (shndx);
-                 shndx_list += 4;
-               }
-             if (do_display)
+                   shndx_list += 4;
+                 }
                printf ("\n");
-             else
-               end_cu_tu_entry ();
-           }
-         phash += 8;
-         pindex += 4;
-       }
+             }
+           phash += 8;
+           pindex += 4;
+         }
     }
   else if (version == 2)
     {
@@ -10824,11 +11181,14 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
       if (nused == -1u
          || _mul_overflow ((size_t) ncols, 4, &temp)
          || _mul_overflow ((size_t) nused + 1, temp, &total)
+         || total > (size_t) (limit - ppool)
+         /* PR 30227: ncols could be 0.  */
+         || _mul_overflow ((size_t) nused + 1, 4, &total)
          || total > (size_t) (limit - ppool))
        {
          warn (_("Section %s too small for offset and size tables\n"),
                section->name);
-         return 0;
+         return false;
        }
 
       if (do_display)
@@ -10876,7 +11236,7 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
                {
                  warn (_("Row index (%u) is larger than number of used entries (%u)\n"),
                        row, nused);
-                 return 0;
+                 return false;
                }
 
              if (!do_display)
@@ -10888,7 +11248,7 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
 
              prow = poffsets + (row - 1) * ncols * 4;
              if (do_display)
-               printf ("  [%3d] 0x%" PRIx64, i, signature);
+               printf ("  [%3d] %#" PRIx64, i, signature);
              for (j = 0; j < ncols; j++)
                {
                  unsigned char *p = prow + j * 4;
@@ -10946,7 +11306,7 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
              prow = psizes + (row - 1) * ncols * 4;
 
              if (do_display)
-               printf ("  [%3d] 0x%" PRIx64, i, signature);
+               printf ("  [%3d] %#" PRIx64, i, signature);
 
              for (j = 0; j < ncols; j++)
                {
@@ -10961,7 +11321,7 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
                        printf ("\n");
                      warn (_("Too many rows/columns in DWARF index section %s\n"),
                            section->name);
-                     return 0;
+                     return false;
                    }
 
                  SAFE_BYTE_GET (val, p, 4, limit);
@@ -10993,7 +11353,7 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
   if (do_display)
       printf ("\n");
 
-  return 1;
+  return true;
 }
 
 static int cu_tu_indexes_read = -1; /* Tri-state variable.  */
@@ -11071,7 +11431,7 @@ display_debug_not_supported (struct dwarf_section *section,
    Note: does *not* initialise the allocated memory to zero.  */
 
 void *
-cmalloc (size_t nmemb, size_t size)
+cmalloc (uint64_t nmemb, size_t size)
 {
   /* Check for overflow.  */
   if (nmemb >= ~(size_t) 0 / size)
@@ -11085,13 +11445,13 @@ cmalloc (size_t nmemb, size_t size)
    Note: does *not* initialise the allocated memory to zero.  */
 
 void *
-xcmalloc (size_t nmemb, size_t size)
+xcmalloc (uint64_t nmemb, size_t size)
 {
   /* Check for overflow.  */
   if (nmemb >= ~(size_t) 0 / size)
     {
       fprintf (stderr,
-              _("Attempt to allocate an array with an excessive number of elements: %#zx\n"),
+              _("Attempt to allocate an array with an excessive number of elements: %#" PRIx64 "\n"),
               nmemb);
       xexit (1);
     }
@@ -11104,12 +11464,12 @@ xcmalloc (size_t nmemb, size_t size)
    Note: does *not* initialise any new memory to zero.  */
 
 void *
-xcrealloc (void *ptr, size_t nmemb, size_t size)
+xcrealloc (void *ptr, uint64_t nmemb, size_t size)
 {
   /* Check for overflow.  */
   if (nmemb >= ~(size_t) 0 / size)
     {
-      error (_("Attempt to re-allocate an array with an excessive number of elements: %#zx\n"),
+      error (_("Attempt to re-allocate an array with an excessive number of elements: %#" PRIx64 "\n"),
             nmemb);
       xexit (1);
     }
@@ -11120,12 +11480,12 @@ xcrealloc (void *ptr, size_t nmemb, size_t size)
 /* Like xcalloc, but verifies that the first parameter is not too large.  */
 
 void *
-xcalloc2 (size_t nmemb, size_t size)
+xcalloc2 (uint64_t nmemb, size_t size)
 {
   /* Check for overflow.  */
   if (nmemb >= ~(size_t) 0 / size)
     {
-      error (_("Attempt to allocate a zero'ed array with an excessive number of elements: %#zx\n"),
+      error (_("Attempt to allocate a zero'ed array with an excessive number of elements: %#" PRIx64 "\n"),
             nmemb);
       xexit (1);
     }
@@ -11708,7 +12068,7 @@ load_build_id_debug_file (const char * main_filename ATTRIBUTE_UNUSED, void * ma
 
   if (build_id_size > (section->size - 16))
     {
-      warn (_(".note.gnu.build-id data size is too bug\n"));
+      warn (_(".note.gnu.build-id data size is too big\n"));
       return;
     }
 
@@ -12021,15 +12381,7 @@ free_debug_memory (void)
   if (debug_information != NULL)
     {
       for (i = 0; i < alloc_num_debug_info_entries; i++)
-       {
-         if (debug_information [i].max_loc_offsets)
-           {
-             free (debug_information [i].loc_offsets);
-             free (debug_information [i].have_frame_base);
-           }
-         if (debug_information [i].max_range_lists)
-           free (debug_information [i].range_lists);
-       }
+       free_debug_information (&debug_information[i]);
       free (debug_information);
       debug_information = NULL;
       alloc_num_debug_info_entries = num_debug_info_entries = 0;