[BFD, LD, AArch64, 3/3] Add --pac-plt to enable PLTs protected with PAC.
[deliverable/binutils-gdb.git] / binutils / readelf.c
index 739367d899bc1332242a3f6e48ff370ea2751b03..5a9d9ff433d5438e073e871b9c92d307d9f279d3 100644 (file)
@@ -1,5 +1,5 @@
 /* readelf.c -- display contents of an ELF format file
-   Copyright (C) 1998-2017 Free Software Foundation, Inc.
+   Copyright (C) 1998-2019 Free Software Foundation, Inc.
 
    Originally developed by Eric Youngdale <eric@andante.jic.com>
    Modifications by Nick Clifton <nickc@redhat.com>
@@ -98,6 +98,7 @@
 #include "elf/cr16.h"
 #include "elf/cris.h"
 #include "elf/crx.h"
+#include "elf/csky.h"
 #include "elf/d10v.h"
 #include "elf/d30v.h"
 #include "elf/dlx.h"
 #include "elf/m32r.h"
 #include "elf/m68k.h"
 #include "elf/m68hc11.h"
+#include "elf/s12z.h"
 #include "elf/mcore.h"
 #include "elf/mep.h"
 #include "elf/metag.h"
 #include "elf/mt.h"
 #include "elf/msp430.h"
 #include "elf/nds32.h"
+#include "elf/nfp.h"
 #include "elf/nios2.h"
 #include "elf/or1k.h"
 #include "elf/pj.h"
@@ -395,10 +398,11 @@ get_data (void *         var,
       return NULL;
     }
 
-  /* Be kind to memory chekers (eg valgrind, address sanitizer) by not
+  /* Be kind to memory checkers (eg valgrind, address sanitizer) by not
      attempting to allocate memory when the read is bound to fail.  */
-  if (amt > filedata->file_size
-      || offset + archive_file_offset + amt > filedata->file_size)
+  if (archive_file_offset > filedata->file_size
+      || offset > filedata->file_size - archive_file_offset
+      || amt > filedata->file_size - archive_file_offset - offset)
     {
       if (reason)
        error (_("Reading %s bytes extends past end of file for %s\n"),
@@ -515,7 +519,8 @@ print_symbol (signed int width, const char *symbol)
       width = - width;
       extra_padding = TRUE;
     }
-  assert (width != 0);
+  else if (width == 0)
+    return 0;
 
   if (do_wide)
     /* Set the remaining width to a very large value.
@@ -655,7 +660,8 @@ find_section (Filedata * filedata, const char * name)
 {
   unsigned int i;
 
-  assert (filedata->section_headers != NULL);
+  if (filedata->section_headers == NULL)
+    return NULL;
 
   for (i = 0; i < filedata->file_header.e_shnum; i++)
     if (streq (SECTION_NAME (filedata->section_headers + i), name))
@@ -672,6 +678,9 @@ find_section_by_address (Filedata * filedata, bfd_vma addr)
 {
   unsigned int i;
 
+  if (filedata->section_headers == NULL)
+    return NULL;
+
   for (i = 0; i < filedata->file_header.e_shnum; i++)
     {
       Elf_Internal_Shdr *sec = filedata->section_headers + i;
@@ -688,6 +697,9 @@ find_section_by_type (Filedata * filedata, unsigned int type)
 {
   unsigned int i;
 
+  if (filedata->section_headers == NULL)
+    return NULL;
+
   for (i = 0; i < filedata->file_header.e_shnum; i++)
     {
       Elf_Internal_Shdr *sec = filedata->section_headers + i;
@@ -707,6 +719,9 @@ find_section_in_set (Filedata * filedata, const char * name, unsigned int * set)
 {
   unsigned int i;
 
+  if (filedata->section_headers == NULL)
+    return NULL;
+
   if (set != NULL)
     {
       while ((i = *set++) > 0)
@@ -765,6 +780,7 @@ guess_is_rela (unsigned int e_machine)
     case EM_CYGNUS_M32R:
     case EM_SCORE:
     case EM_XGATE:
+    case EM_NFP:
       return FALSE;
 
       /* Targets that use RELA relocations.  */
@@ -783,6 +799,7 @@ guess_is_rela (unsigned int e_machine)
     case EM_CR16:
     case EM_CRIS:
     case EM_CRX:
+    case EM_CSKY:
     case EM_D30V:
     case EM_CYGNUS_D30V:
     case EM_FR30:
@@ -1261,6 +1278,10 @@ dump_relocations (Filedata *          filedata,
          rtype = elf_m68hc11_reloc_type (type);
          break;
 
+       case EM_S12Z:
+         rtype = elf_s12z_reloc_type (type);
+         break;
+
        case EM_68K:
          rtype = elf_m68k_reloc_type (type);
          break;
@@ -1330,6 +1351,10 @@ dump_relocations (Filedata *          filedata,
          rtype = elf_frv_reloc_type (type);
          break;
 
+       case EM_CSKY:
+         rtype = elf_csky_reloc_type (type);
+         break;
+
        case EM_FT32:
          rtype = elf_ft32_reloc_type (type);
          break;
@@ -1549,6 +1574,13 @@ dump_relocations (Filedata *          filedata,
        case EM_TI_PRU:
          rtype = elf_pru_reloc_type (type);
          break;
+
+       case EM_NFP:
+         if (EF_NFP_MACH (filedata->file_header.e_flags) == E_NFP_MACH_3200)
+           rtype = elf_nfp3200_reloc_type (type);
+         else
+           rtype = elf_nfp_reloc_type (type);
+         break;
        }
 
       if (rtype == NULL)
@@ -1765,6 +1797,18 @@ dump_relocations (Filedata *          filedata,
   return res;
 }
 
+static const char *
+get_aarch64_dynamic_type (unsigned long type)
+{
+  switch (type)
+    {
+    case DT_AARCH64_BTI_PLT:  return "AARCH64_BTI_PLT";
+    case DT_AARCH64_PAC_PLT:  return "AARCH64_PAC_PLT";
+    default:
+      return NULL;
+    }
+}
+
 static const char *
 get_mips_dynamic_type (unsigned long type)
 {
@@ -2138,6 +2182,9 @@ get_dynamic_type (Filedata * filedata, unsigned long type)
 
          switch (filedata->file_header.e_machine)
            {
+           case EM_AARCH64:
+             result = get_aarch64_dynamic_type (type);
+             break;
            case EM_MIPS:
            case EM_MIPS_RS3_LE:
              result = get_mips_dynamic_type (type);
@@ -2263,7 +2310,7 @@ get_machine_name (unsigned e_machine)
     case EM_PARISC:            return "HPPA";
     case EM_VPP550:            return "Fujitsu VPP500";
     case EM_SPARC32PLUS:       return "Sparc v8+" ;
-    case EM_960:               return "Intel 90860";
+    case EM_960:               return "Intel 80960";
     case EM_PPC:               return "PowerPC";
       /* 20 */
     case EM_PPC64:             return "PowerPC64";
@@ -2461,6 +2508,7 @@ get_machine_name (unsigned e_machine)
     case EM_RISCV:             return "RISC-V";
     case EM_LANAI:             return "Lanai 32-bit processor";
     case EM_BPF:               return "Linux BPF";
+    case EM_NFP:               return "Netronome Flow Processor";
 
       /* Large numbers...  */
     case EM_MT:                 return "Morpho Techologies MT processor";
@@ -2474,6 +2522,8 @@ get_machine_name (unsigned e_machine)
     case EM_CYGNUS_MEP:         return "Toshiba MeP Media Engine";
     case EM_ADAPTEVA_EPIPHANY: return "Adapteva EPIPHANY";
     case EM_CYGNUS_FRV:                return "Fujitsu FR-V";
+    case EM_S12Z:               return "Freescale S12Z";
+    case EM_CSKY:              return "C-SKY";
 
     default:
       snprintf (buff, sizeof (buff), _("<unknown>: 0x%x"), e_machine);
@@ -2567,6 +2617,12 @@ decode_ARM_machine_flags (unsigned e_flags, char buf[])
       e_flags &= ~ EF_ARM_RELEXEC;
     }
 
+  if (e_flags & EF_ARM_PIC)
+    {
+      strcat (buf, ", position independent");
+      e_flags &= ~ EF_ARM_PIC;
+    }
+
   /* Now handle EABI specific flags.  */
   switch (eabi)
     {
@@ -3364,7 +3420,9 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine)
            case E_MIPS_MACH_9000: strcat (buf, ", 9000"); break;
            case E_MIPS_MACH_LS2E: strcat (buf, ", loongson-2e"); break;
            case E_MIPS_MACH_LS2F: strcat (buf, ", loongson-2f"); break;
-           case E_MIPS_MACH_LS3A: strcat (buf, ", loongson-3a"); break;
+           case E_MIPS_MACH_GS464: strcat (buf, ", gs464"); break;
+           case E_MIPS_MACH_GS464E: strcat (buf, ", gs464e"); break;
+           case E_MIPS_MACH_GS264E: strcat (buf, ", gs264e"); break;
            case E_MIPS_MACH_OCTEON: strcat (buf, ", octeon"); break;
            case E_MIPS_MACH_OCTEON2: strcat (buf, ", octeon2"); break;
            case E_MIPS_MACH_OCTEON3: strcat (buf, ", octeon3"); break;
@@ -3423,10 +3481,25 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine)
          decode_NDS32_machine_flags (e_flags, buf, sizeof buf);
          break;
 
+       case EM_NFP:
+         switch (EF_NFP_MACH (e_flags))
+           {
+           case E_NFP_MACH_3200:
+             strcat (buf, ", NFP-32xx");
+             break;
+           case E_NFP_MACH_6000:
+             strcat (buf, ", NFP-6xxx");
+             break;
+           }
+         break;
+
        case EM_RISCV:
          if (e_flags & EF_RISCV_RVC)
            strcat (buf, ", RVC");
 
+         if (e_flags & EF_RISCV_RVE)
+           strcat (buf, ", RVE");
+
          switch (e_flags & EF_RISCV_FLOAT_ABI)
            {
            case EF_RISCV_FLOAT_ABI_SOFT:
@@ -3632,6 +3705,8 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine)
                    ? ", uses String instructions" : ", bans String instructions");
          if (e_flags & E_FLAG_RX_V2)
            strcat (buf, ", V2");
+         if (e_flags & E_FLAG_RX_V3)
+           strcat (buf, ", V3");
          break;
 
        case EM_S390:
@@ -3707,6 +3782,7 @@ get_osabi_name (Filedata * filedata, unsigned int osabi)
            switch (osabi)
              {
              case ELFOSABI_ARM:        return "ARM";
+             case ELFOSABI_ARM_FDPIC:  return "ARM FDPIC";
              default:
                break;
              }
@@ -3872,6 +3948,7 @@ get_segment_type (Filedata * filedata, unsigned long p_type)
     case PT_GNU_EH_FRAME: return "GNU_EH_FRAME";
     case PT_GNU_STACK: return "GNU_STACK";
     case PT_GNU_RELRO:  return "GNU_RELRO";
+    case PT_GNU_PROPERTY: return "GNU_PROPERTY";
 
     default:
       if (p_type >= PT_GNU_MBIND_LO && p_type <= PT_GNU_MBIND_HI)
@@ -4117,6 +4194,18 @@ get_msp430x_section_type_name (unsigned int sh_type)
     }
 }
 
+static const char *
+get_nfp_section_type_name (unsigned int sh_type)
+{
+  switch (sh_type)
+    {
+    case SHT_NFP_MECONFIG:     return "NFP_MECONFIG";
+    case SHT_NFP_INITREG:      return "NFP_INITREG";
+    case SHT_NFP_UDEBUG:       return "NFP_UDEBUG";
+    default:                   return NULL;
+    }
+}
+
 static const char *
 get_v850_section_type_name (unsigned int sh_type)
 {
@@ -4131,6 +4220,16 @@ get_v850_section_type_name (unsigned int sh_type)
     }
 }
 
+static const char *
+get_riscv_section_type_name (unsigned int sh_type)
+{
+  switch (sh_type)
+    {
+    case SHT_RISCV_ATTRIBUTES:  return "RISCV_ATTRIBUTES";
+    default: return NULL;
+    }
+}
+
 static const char *
 get_section_type_name (Filedata * filedata, unsigned int sh_type)
 {
@@ -4156,7 +4255,7 @@ get_section_type_name (Filedata * filedata, unsigned int sh_type)
     case SHT_PREINIT_ARRAY:    return "PREINIT_ARRAY";
     case SHT_GNU_HASH:         return "GNU_HASH";
     case SHT_GROUP:            return "GROUP";
-    case SHT_SYMTAB_SHNDX:     return "SYMTAB SECTION INDICIES";
+    case SHT_SYMTAB_SHNDX:     return "SYMTAB SECTION INDICES";
     case SHT_GNU_verdef:       return "VERDEF";
     case SHT_GNU_verneed:      return "VERNEED";
     case SHT_GNU_versym:       return "VERSYM";
@@ -4203,11 +4302,17 @@ get_section_type_name (Filedata * filedata, unsigned int sh_type)
            case EM_MSP430:
              result = get_msp430x_section_type_name (sh_type);
              break;
+           case EM_NFP:
+             result = get_nfp_section_type_name (sh_type);
+             break;
            case EM_V800:
            case EM_V850:
            case EM_CYGNUS_V850:
              result = get_v850_section_type_name (sh_type);
              break;
+           case EM_RISCV:
+             result = get_riscv_section_type_name (sh_type);
+             break;
            default:
              result = NULL;
              break;
@@ -4694,12 +4799,12 @@ process_file_header (Filedata * filedata)
              get_elf_class (header->e_ident[EI_CLASS]));
       printf (_("  Data:                              %s\n"),
              get_data_encoding (header->e_ident[EI_DATA]));
-      printf (_("  Version:                           %d %s\n"),
+      printf (_("  Version:                           %d%s\n"),
              header->e_ident[EI_VERSION],
              (header->e_ident[EI_VERSION] == EV_CURRENT
-              ? "(current)"
+              ? _(" (current)")
               : (header->e_ident[EI_VERSION] != EV_NONE
-                 ? _("<unknown: %lx>")
+                 ? _(" <unknown>")
                  : "")));
       printf (_("  OS/ABI:                            %s\n"),
              get_osabi_name (filedata, header->e_ident[EI_OSABI]));
@@ -4710,45 +4815,57 @@ process_file_header (Filedata * filedata)
       printf (_("  Machine:                           %s\n"),
              get_machine_name (header->e_machine));
       printf (_("  Version:                           0x%lx\n"),
-             (unsigned long) header->e_version);
+             header->e_version);
 
       printf (_("  Entry point address:               "));
-      print_vma ((bfd_vma) header->e_entry, PREFIX_HEX);
+      print_vma (header->e_entry, PREFIX_HEX);
       printf (_("\n  Start of program headers:          "));
-      print_vma ((bfd_vma) header->e_phoff, DEC);
+      print_vma (header->e_phoff, DEC);
       printf (_(" (bytes into file)\n  Start of section headers:          "));
-      print_vma ((bfd_vma) header->e_shoff, DEC);
+      print_vma (header->e_shoff, DEC);
       printf (_(" (bytes into file)\n"));
 
       printf (_("  Flags:                             0x%lx%s\n"),
-             (unsigned long) header->e_flags,
+             header->e_flags,
              get_machine_flags (filedata, header->e_flags, header->e_machine));
-      printf (_("  Size of this header:               %ld (bytes)\n"),
-             (long) header->e_ehsize);
-      printf (_("  Size of program headers:           %ld (bytes)\n"),
-             (long) header->e_phentsize);
-      printf (_("  Number of program headers:         %ld"),
-             (long) header->e_phnum);
+      printf (_("  Size of this header:               %u (bytes)\n"),
+             header->e_ehsize);
+      printf (_("  Size of program headers:           %u (bytes)\n"),
+             header->e_phentsize);
+      printf (_("  Number of program headers:         %u"),
+             header->e_phnum);
       if (filedata->section_headers != NULL
          && header->e_phnum == PN_XNUM
          && filedata->section_headers[0].sh_info != 0)
-       printf (" (%ld)", (long) filedata->section_headers[0].sh_info);
+       {
+         header->e_phnum = filedata->section_headers[0].sh_info;
+         printf (" (%u)", header->e_phnum);
+       }
       putc ('\n', stdout);
-      printf (_("  Size of section headers:           %ld (bytes)\n"),
-             (long) header->e_shentsize);
-      printf (_("  Number of section headers:         %ld"),
-             (long) header->e_shnum);
+      printf (_("  Size of section headers:           %u (bytes)\n"),
+             header->e_shentsize);
+      printf (_("  Number of section headers:         %u"),
+             header->e_shnum);
       if (filedata->section_headers != NULL && header->e_shnum == SHN_UNDEF)
-       printf (" (%ld)", (long) filedata->section_headers[0].sh_size);
+       {
+         header->e_shnum = filedata->section_headers[0].sh_size;
+         printf (" (%u)", header->e_shnum);
+       }
       putc ('\n', stdout);
-      printf (_("  Section header string table index: %ld"),
-             (long) header->e_shstrndx);
+      printf (_("  Section header string table index: %u"),
+             header->e_shstrndx);
       if (filedata->section_headers != NULL
          && header->e_shstrndx == (SHN_XINDEX & 0xffff))
-       printf (" (%u)", filedata->section_headers[0].sh_link);
-      else if (header->e_shstrndx != SHN_UNDEF
-              && header->e_shstrndx >= header->e_shnum)
-       printf (_(" <corrupt: out of range>"));
+       {
+         header->e_shstrndx = filedata->section_headers[0].sh_link;
+         printf (" (%u)", header->e_shstrndx);
+       }
+      if (header->e_shstrndx != SHN_UNDEF
+         && header->e_shstrndx >= header->e_shnum)
+       {
+         header->e_shstrndx = SHN_UNDEF;
+         printf (_(" <corrupt: out of range>"));
+       }
       putc ('\n', stdout);
     }
 
@@ -4761,7 +4878,7 @@ process_file_header (Filedata * filedata)
        header->e_shnum = filedata->section_headers[0].sh_size;
       if (header->e_shstrndx == (SHN_XINDEX & 0xffff))
        header->e_shstrndx = filedata->section_headers[0].sh_link;
-      else if (header->e_shstrndx >= header->e_shnum)
+      if (header->e_shstrndx >= header->e_shnum)
        header->e_shstrndx = SHN_UNDEF;
       free (filedata->section_headers);
       filedata->section_headers = NULL;
@@ -5134,7 +5251,8 @@ process_program_headers (Filedata * filedata)
             segment.  Check this after matching against the section headers
             so we don't warn on debuginfo file (which have NOBITS .dynamic
             sections).  */
-         if (dynamic_addr + dynamic_size >= filedata->file_size)
+         if (dynamic_addr > filedata->file_size
+             || dynamic_size > filedata->file_size - dynamic_addr)
            {
              error (_("the dynamic segment offset + size exceeds the size of the file\n"));
              dynamic_addr = dynamic_size = 0;
@@ -5266,6 +5384,7 @@ get_32bit_section_headers (Filedata * filedata, bfd_boolean probe)
     {
       if (!probe)
        error (_("Out of memory reading %u section headers\n"), num);
+      free (shdrs);
       return FALSE;
     }
 
@@ -5332,6 +5451,7 @@ get_64bit_section_headers (Filedata * filedata, bfd_boolean probe)
     {
       if (! probe)
        error (_("Out of memory reading %u section headers\n"), num);
+      free (shdrs);
       return FALSE;
     }
 
@@ -5370,6 +5490,7 @@ get_32bit_elf_symbols (Filedata *           filedata,
   Elf_Internal_Sym * isyms = NULL;
   Elf_Internal_Sym * psym;
   unsigned int j;
+  elf_section_list * entry;
 
   if (section->sh_size == 0)
     {
@@ -5411,30 +5532,35 @@ get_32bit_elf_symbols (Filedata *           filedata,
   if (esyms == NULL)
     goto exit_point;
 
-  {
-    elf_section_list * entry;
-
-    shndx = NULL;
-    for (entry = symtab_shndx_list; entry != NULL; entry = entry->next)
-      if (entry->hdr->sh_link == (unsigned long) (section - filedata->section_headers))
-       {
-         shndx = (Elf_External_Sym_Shndx *) get_data (NULL, filedata,
-                                                      entry->hdr->sh_offset,
-                                                      1, entry->hdr->sh_size,
-                                                      _("symbol table section indicies"));
-         if (shndx == NULL)
-           goto exit_point;
-         /* PR17531: file: heap-buffer-overflow */
-         else if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
-           {
-             error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"),
-                    printable_section_name (filedata, entry->hdr),
-                    (unsigned long) entry->hdr->sh_size,
-                    (unsigned long) section->sh_size);
-             goto exit_point;
-           }
+  shndx = NULL;
+  for (entry = symtab_shndx_list; entry != NULL; entry = entry->next)
+    {
+      if (entry->hdr->sh_link != (unsigned long) (section - filedata->section_headers))
+       continue;
+
+      if (shndx != NULL)
+       {
+         error (_("Multiple symbol table index sections associated with the same symbol section\n"));
+         free (shndx);
+       }
+
+      shndx = (Elf_External_Sym_Shndx *) get_data (NULL, filedata,
+                                                  entry->hdr->sh_offset,
+                                                  1, entry->hdr->sh_size,
+                                                  _("symbol table section indices"));
+      if (shndx == NULL)
+       goto exit_point;
+
+      /* PR17531: file: heap-buffer-overflow */
+      if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
+       {
+         error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"),
+                printable_section_name (filedata, entry->hdr),
+                (unsigned long) entry->hdr->sh_size,
+                (unsigned long) section->sh_size);
+         goto exit_point;
        }
-  }
+    }
 
   isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
 
@@ -5461,10 +5587,8 @@ get_32bit_elf_symbols (Filedata *           filedata,
     }
 
  exit_point:
-  if (shndx != NULL)
-    free (shndx);
-  if (esyms != NULL)
-    free (esyms);
+  free (shndx);
+  free (esyms);
 
   if (num_syms_return != NULL)
     * num_syms_return = isyms == NULL ? 0 : number;
@@ -5483,6 +5607,7 @@ get_64bit_elf_symbols (Filedata *           filedata,
   Elf_Internal_Sym * isyms = NULL;
   Elf_Internal_Sym * psym;
   unsigned int j;
+  elf_section_list * entry;
 
   if (section->sh_size == 0)
     {
@@ -5524,30 +5649,35 @@ get_64bit_elf_symbols (Filedata *           filedata,
   if (!esyms)
     goto exit_point;
 
-  {
-    elf_section_list * entry;
-
-    shndx = NULL;
-    for (entry = symtab_shndx_list; entry != NULL; entry = entry->next)
-      if (entry->hdr->sh_link == (unsigned long) (section - filedata->section_headers))
-       {
-         shndx = (Elf_External_Sym_Shndx *) get_data (NULL, filedata,
-                                                      entry->hdr->sh_offset,
-                                                      1, entry->hdr->sh_size,
-                                                      _("symbol table section indicies"));
-         if (shndx == NULL)
-           goto exit_point;
-         /* PR17531: file: heap-buffer-overflow */
-         else if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
-           {
-             error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"),
-                    printable_section_name (filedata, entry->hdr),
-                    (unsigned long) entry->hdr->sh_size,
-                    (unsigned long) section->sh_size);
-             goto exit_point;
-           }
+  shndx = NULL;
+  for (entry = symtab_shndx_list; entry != NULL; entry = entry->next)
+    {
+      if (entry->hdr->sh_link != (unsigned long) (section - filedata->section_headers))
+       continue;
+
+      if (shndx != NULL)
+       {
+         error (_("Multiple symbol table index sections associated with the same symbol section\n"));
+         free (shndx);
+       }
+
+      shndx = (Elf_External_Sym_Shndx *) get_data (NULL, filedata,
+                                                  entry->hdr->sh_offset,
+                                                  1, entry->hdr->sh_size,
+                                                  _("symbol table section indices"));
+      if (shndx == NULL)
+       goto exit_point;
+
+      /* PR17531: file: heap-buffer-overflow */
+      if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
+       {
+         error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"),
+                printable_section_name (filedata, entry->hdr),
+                (unsigned long) entry->hdr->sh_size,
+                (unsigned long) section->sh_size);
+         goto exit_point;
        }
-  }
+    }
 
   isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
 
@@ -5576,10 +5706,8 @@ get_64bit_elf_symbols (Filedata *           filedata,
     }
 
  exit_point:
-  if (shndx != NULL)
-    free (shndx);
-  if (esyms != NULL)
-    free (esyms);
+  free (shndx);
+  free (esyms);
 
   if (num_syms_return != NULL)
     * num_syms_return = isyms == NULL ? 0 : number;
@@ -6204,14 +6332,21 @@ process_section_headers (Filedata * filedata)
       /* Check the sh_link field.  */
       switch (section->sh_type)
        {
+       case SHT_REL:
+       case SHT_RELA:
+         if (section->sh_link == 0
+             && (filedata->file_header.e_type == ET_EXEC
+                 || filedata->file_header.e_type == ET_DYN))
+           /* A dynamic relocation section where all entries use a
+              zero symbol index need not specify a symtab section.  */
+           break;
+         /* Fall through.  */
        case SHT_SYMTAB_SHNDX:
        case SHT_GROUP:
        case SHT_HASH:
        case SHT_GNU_HASH:
        case SHT_GNU_versym:
-       case SHT_REL:
-       case SHT_RELA:
-         if (section->sh_link < 1
+         if (section->sh_link == 0
              || section->sh_link >= filedata->file_header.e_shnum
              || (filedata->section_headers[section->sh_link].sh_type != SHT_SYMTAB
                  && filedata->section_headers[section->sh_link].sh_type != SHT_DYNSYM))
@@ -6225,7 +6360,7 @@ process_section_headers (Filedata * filedata)
        case SHT_GNU_verneed:
        case SHT_GNU_verdef:
        case SHT_GNU_LIBLIST:
-         if (section->sh_link < 1
+         if (section->sh_link == 0
              || section->sh_link >= filedata->file_header.e_shnum
              || filedata->section_headers[section->sh_link].sh_type != SHT_STRTAB)
            warn (_("[%2u]: Link field (%u) should index a string section.\n"),
@@ -6258,26 +6393,24 @@ process_section_headers (Filedata * filedata)
        {
        case SHT_REL:
        case SHT_RELA:
-         if (section->sh_info < 1
+         if (section->sh_info == 0
+             && (filedata->file_header.e_type == ET_EXEC
+                 || filedata->file_header.e_type == ET_DYN))
+           /* Dynamic relocations apply to segments, so they do not
+              need to specify the section they relocate.  */
+           break;
+         if (section->sh_info == 0
              || section->sh_info >= filedata->file_header.e_shnum
              || (filedata->section_headers[section->sh_info].sh_type != SHT_PROGBITS
                  && filedata->section_headers[section->sh_info].sh_type != SHT_NOBITS
                  && filedata->section_headers[section->sh_info].sh_type != SHT_NOTE
                  && filedata->section_headers[section->sh_info].sh_type != SHT_INIT_ARRAY
+                 && filedata->section_headers[section->sh_info].sh_type != SHT_FINI_ARRAY
+                 && filedata->section_headers[section->sh_info].sh_type != SHT_PREINIT_ARRAY
                  /* FIXME: Are other section types valid ?  */
                  && filedata->section_headers[section->sh_info].sh_type < SHT_LOOS))
-           {
-             if (section->sh_info == 0
-                 && (streq (SECTION_NAME (section), ".rel.dyn")
-                     || streq (SECTION_NAME (section), ".rela.dyn")))
-               /* The .rel.dyn and .rela.dyn sections have an sh_info field
-                  of zero.  The relocations in these sections may apply
-                  to many different sections.  */
-                  ;
-             else
-               warn (_("[%2u]: Info field (%u) should index a relocatable section.\n"),
-                     i, section->sh_info);
-           }
+           warn (_("[%2u]: Info field (%u) should index a relocatable section.\n"),
+                 i, section->sh_info);
          break;
 
        case SHT_DYNAMIC:
@@ -6441,8 +6574,7 @@ process_section_headers (Filedata * filedata)
        }
       else if (do_section_details)
        {
-         printf ("       %-15.15s  ",
-                 get_section_type_name (filedata, section->sh_type));
+         putchar (' ');
          print_vma (section->sh_addr, LONG_HEX);
          if ((long) section->sh_offset == section->sh_offset)
            printf ("  %16.16lx", (unsigned long) section->sh_offset);
@@ -6776,7 +6908,7 @@ process_section_groups (Filedata * filedata)
                      error (_("section [%5u] in group section [%5u] > maximum section [%5u]\n"),
                             entry, i, filedata->file_header.e_shnum - 1);
                      if (num_group_errors == 10)
-                       warn (_("Further error messages about overlarge group section indicies suppressed\n"));
+                       warn (_("Further error messages about overlarge group section indices suppressed\n"));
                    }
                  continue;
                }
@@ -7498,14 +7630,14 @@ slurp_ia64_unwind_table (Filedata *                  filedata,
 
       for (rp = rela; rp < rela + nrelas; ++rp)
        {
-         relname = elf_ia64_reloc_type (get_reloc_type (filedata, rp->r_info));
-         sym = aux->symtab + get_reloc_symindex (rp->r_info);
+         unsigned int sym_ndx;
+         unsigned int r_type = get_reloc_type (filedata, rp->r_info);
+         relname = elf_ia64_reloc_type (r_type);
 
          /* PR 17531: file: 9fa67536.  */
          if (relname == NULL)
            {
-             warn (_("Skipping unknown relocation type: %u\n"),
-                   get_reloc_type (filedata, rp->r_info));
+             warn (_("Skipping unknown relocation type: %u\n"), r_type);
              continue;
            }
 
@@ -7524,6 +7656,15 @@ slurp_ia64_unwind_table (Filedata *                  filedata,
              continue;
            }
 
+         sym_ndx = get_reloc_symindex (rp->r_info);
+         if (sym_ndx >= aux->nsyms)
+           {
+             warn (_("Skipping reloc with invalid symbol index: %u\n"),
+                   sym_ndx);
+             continue;
+           }
+         sym = aux->symtab + sym_ndx;
+
          switch (rp->r_offset / eh_addr_size % 3)
            {
            case 0:
@@ -7954,19 +8095,40 @@ slurp_hppa_unwind_table (Filedata *                  filedata,
 
       for (rp = rela; rp < rela + nrelas; ++rp)
        {
-         relname = elf_hppa_reloc_type (get_reloc_type (filedata, rp->r_info));
-         sym = aux->symtab + get_reloc_symindex (rp->r_info);
+         unsigned int sym_ndx;
+         unsigned int r_type = get_reloc_type (filedata, rp->r_info);
+         relname = elf_hppa_reloc_type (r_type);
+
+         if (relname == NULL)
+           {
+             warn (_("Skipping unknown relocation type: %u\n"), r_type);
+             continue;
+           }
 
          /* R_PARISC_SEGREL32 or R_PARISC_SEGREL64.  */
          if (! const_strneq (relname, "R_PARISC_SEGREL"))
            {
-             warn (_("Skipping unexpected relocation type %s\n"), relname);
+             warn (_("Skipping unexpected relocation type: %s\n"), relname);
              continue;
            }
 
          i = rp->r_offset / unw_ent_size;
+         if (i >= aux->table_len)
+           {
+             warn (_("Skipping reloc with overlarge offset: %lx\n"), i);
+             continue;
+           }
+
+         sym_ndx = get_reloc_symindex (rp->r_info);
+         if (sym_ndx >= aux->nsyms)
+           {
+             warn (_("Skipping reloc with invalid symbol index: %u\n"),
+                   sym_ndx);
+             continue;
+           }
+         sym = aux->symtab + sym_ndx;
 
-         switch ((rp->r_offset % unw_ent_size) / eh_addr_size)
+         switch ((rp->r_offset % unw_ent_size) / 4)
            {
            case 0:
              aux->table[i].start.section = sym->st_shndx;
@@ -8034,7 +8196,7 @@ hppa_process_unwind (Filedata * filedata)
     {
       if (streq (SECTION_NAME (sec), ".PARISC.unwind"))
        {
-         unsigned long num_unwind = sec->sh_size / (2 * eh_addr_size + 8);
+         unsigned long num_unwind = sec->sh_size / 16;
 
          printf (ngettext ("\nUnwind section '%s' at offset 0x%lx "
                            "contains %lu entry:\n",
@@ -8047,8 +8209,8 @@ hppa_process_unwind (Filedata * filedata)
 
           if (! slurp_hppa_unwind_table (filedata, &aux, sec))
            res = FALSE;
-       
-         if (aux.table_len > 0)
+
+         if (res && aux.table_len > 0)
            {
              if (! dump_hppa_unwind (filedata, &aux))
                res = FALSE;
@@ -8707,21 +8869,28 @@ decode_tic6x_unwind_bytecode (Filedata *                 filedata,
            }
 
          printf (_("pop frame {"));
-         reg = nregs - 1;
-         for (i = i * 2; i > 0; i--)
+         if (nregs == 0)
            {
-             if (regpos[reg].offset == i - 1)
+             printf (_("*corrupt* - no registers specified"));
+           }
+         else
+           {
+             reg = nregs - 1;
+             for (i = i * 2; i > 0; i--)
                {
-                 name = tic6x_unwind_regnames[regpos[reg].reg];
-                 if (reg > 0)
-                   reg--;
-               }
-             else
-               name = _("[pad]");
+                 if (regpos[reg].offset == i - 1)
+                   {
+                     name = tic6x_unwind_regnames[regpos[reg].reg];
+                     if (reg > 0)
+                       reg--;
+                   }
+                 else
+                   name = _("[pad]");
 
-             fputs (name, stdout);
-             if (i > 1)
-               printf (", ");
+                 fputs (name, stdout);
+                 if (i > 1)
+                   printf (", ");
+               }
            }
 
          printf ("}");
@@ -9190,6 +9359,21 @@ process_unwind (Filedata * filedata)
   return TRUE;
 }
 
+static void
+dynamic_section_aarch64_val (Elf_Internal_Dyn * entry)
+{
+  switch (entry->d_tag)
+    {
+    case DT_AARCH64_BTI_PLT:
+    case DT_AARCH64_PAC_PLT:
+      break;
+    default:
+      print_vma (entry->d_un.d_ptr, PREFIX_HEX);
+      break;
+    }
+  putchar ('\n');
+}
+
 static void
 dynamic_section_mips_val (Elf_Internal_Dyn * entry)
 {
@@ -9606,6 +9790,11 @@ process_dynamic_section (Filedata * filedata)
            section.sh_entsize = sizeof (Elf64_External_Sym);
          section.sh_name = filedata->string_table_length;
 
+         if (dynamic_symbols != NULL)
+           {
+             error (_("Multiple dynamic symbol table sections found\n"));
+             free (dynamic_symbols);
+           }
          dynamic_symbols = GET_ELF_SYMBOLS (filedata, &section, & num_dynamic_syms);
          if (num_dynamic_syms < 1)
            {
@@ -9640,7 +9829,7 @@ process_dynamic_section (Filedata * filedata)
          if (archive_file_offset != 0)
            str_tab_len = archive_file_size - offset;
          else
-           str_tab_len = filedata->file_size;
+           str_tab_len = filedata->file_size - offset;
 
          if (str_tab_len < 1)
            {
@@ -9649,11 +9838,16 @@ process_dynamic_section (Filedata * filedata)
              continue;
            }
 
+         if (dynamic_strings != NULL)
+           {
+             error (_("Multiple dynamic string tables found\n"));
+             free (dynamic_strings);
+           }
+
          dynamic_strings = (char *) get_data (NULL, filedata, offset, 1,
                                                str_tab_len,
                                                _("dynamic string table"));
          dynamic_strings_length = dynamic_strings == NULL ? 0 : str_tab_len;
-         break;
        }
     }
 
@@ -9696,6 +9890,11 @@ process_dynamic_section (Filedata * filedata)
          if (!extsyminfo)
            return FALSE;
 
+         if (dynamic_syminfo != NULL)
+           {
+             error (_("Multiple dynamic symbol information sections found\n"));
+             free (dynamic_syminfo);
+           }
          dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz);
          if (dynamic_syminfo == NULL)
            {
@@ -9996,6 +10195,21 @@ process_dynamic_section (Filedata * filedata)
                      printf (" PIE");
                      val ^= DF_1_PIE;
                    }
+                 if (val & DF_1_KMOD)
+                   {
+                     printf (" KMOD");
+                     val ^= DF_1_KMOD;
+                   }
+                 if (val & DF_1_WEAKFILTER)
+                   {
+                     printf (" WEAKFILTER");
+                     val ^= DF_1_WEAKFILTER;
+                   }
+                 if (val & DF_1_NOCOMMON)
+                   {
+                     printf (" NOCOMMON");
+                     val ^= DF_1_NOCOMMON;
+                   }
                  if (val != 0)
                    printf (" %lx", val);
                  puts ("");
@@ -10174,6 +10388,9 @@ process_dynamic_section (Filedata * filedata)
            {
              switch (filedata->file_header.e_machine)
                {
+               case EM_AARCH64:
+                 dynamic_section_aarch64_val (entry);
+                 break;
                case EM_MIPS:
                case EM_MIPS_RS3_LE:
                  dynamic_section_mips_val (entry);
@@ -10199,7 +10416,7 @@ process_dynamic_section (Filedata * filedata)
 static char *
 get_ver_flags (unsigned int flags)
 {
-  static char buff[32];
+  static char buff[128];
 
   buff[0] = 0;
 
@@ -10963,11 +11180,16 @@ get_ia64_symbol_other (Filedata * filedata, unsigned int other)
 static const char *
 get_ppc64_symbol_other (unsigned int other)
 {
-  if (PPC64_LOCAL_ENTRY_OFFSET (other) != 0)
+  if ((other & ~STO_PPC64_LOCAL_MASK) != 0)
+    return NULL;
+
+  other >>= STO_PPC64_LOCAL_BIT;
+  if (other <= 6)
     {
       static char buf[32];
-      snprintf (buf, sizeof buf, _("<localentry>: %d"),
-               PPC64_LOCAL_ENTRY_OFFSET (other));
+      if (other >= 2)
+       other = ppc64_decode_local_entry (other);
+      snprintf (buf, sizeof buf, _("<localentry>: %d"), other);
       return buf;
     }
   return NULL;
@@ -11170,6 +11392,7 @@ get_symbol_version_string (Filedata *                   filedata,
   unsigned char data[2];
   unsigned short vers_data;
   unsigned long offset;
+  unsigned short max_vd_ndx;
 
   if (!is_dynsym
       || version_info[DT_VERSIONTAGIDX (DT_VERSYM)] == 0)
@@ -11184,9 +11407,11 @@ get_symbol_version_string (Filedata *                   filedata,
 
   vers_data = byte_get (data, 2);
 
-  if ((vers_data & VERSYM_HIDDEN) == 0 && vers_data <= 1)
+  if ((vers_data & VERSYM_HIDDEN) == 0 && vers_data == 0)
     return NULL;
 
+  max_vd_ndx = 0;
+
   /* Usually we'd only see verdef for defined symbols, and verneed for
      undefined symbols.  However, symbols defined by the linker in
      .dynbss for variables copied from a shared library in order to
@@ -11219,20 +11444,28 @@ get_symbol_version_string (Filedata *                   filedata,
              ivd.vd_ndx = 0;
              ivd.vd_aux = 0;
              ivd.vd_next = 0;
+             ivd.vd_flags = 0;
            }
          else
            {
              ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
              ivd.vd_aux = BYTE_GET (evd.vd_aux);
              ivd.vd_next = BYTE_GET (evd.vd_next);
+             ivd.vd_flags = BYTE_GET (evd.vd_flags);
            }
 
+         if ((ivd.vd_ndx & VERSYM_VERSION) > max_vd_ndx)
+           max_vd_ndx = ivd.vd_ndx & VERSYM_VERSION;
+
          off += ivd.vd_next;
        }
       while (ivd.vd_ndx != (vers_data & VERSYM_VERSION) && ivd.vd_next != 0);
 
       if (ivd.vd_ndx == (vers_data & VERSYM_VERSION))
        {
+         if (ivd.vd_ndx == 1 && ivd.vd_flags == VER_FLG_BASE) 
+           return NULL;
+
          off -= ivd.vd_next;
          off += ivd.vd_aux;
 
@@ -11315,6 +11548,9 @@ get_symbol_version_string (Filedata *                   filedata,
          return (ivna.vna_name < strtab_size
                  ? strtab + ivna.vna_name : _("<corrupt>"));
        }
+      else if ((max_vd_ndx || (vers_data & VERSYM_VERSION) != 1)
+              && (vers_data & VERSYM_VERSION) > max_vd_ndx)
+       return _("<corrupt>");
     }
   return NULL;
 }
@@ -12196,6 +12432,8 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
       return reloc_type == 3; /* R_CR16_NUM32.  */
     case EM_CRX:
       return reloc_type == 15; /* R_CRX_NUM32.  */
+    case EM_CSKY:
+      return reloc_type == 1; /* R_CKCORE_ADDR32.  */
     case EM_CYGNUS_FRV:
       return reloc_type == 1;
     case EM_CYGNUS_D10V:
@@ -12235,6 +12473,9 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
     case EM_68HC11:
     case EM_68HC12:
       return reloc_type == 6; /* R_M68HC11_32.  */
+    case EM_S12Z:
+      return reloc_type == 7 || /* R_S12Z_EXT32 */
+       reloc_type == 6;        /* R_S12Z_CW32.  */
     case EM_MCORE:
       return reloc_type == 1; /* R_MCORE_ADDR32.  */
     case EM_CYGNUS_MEP:
@@ -12269,7 +12510,8 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
     case EM_OR1K:
       return reloc_type == 1; /* R_OR1K_32.  */
     case EM_PARISC:
-      return (reloc_type == 1 /* R_PARISC_DIR32.  */
+      return (reloc_type == 1 /* R_PARISC_DIR32.  */         
+             || reloc_type == 2 /* R_PARISC_DIR21L.  */
              || reloc_type == 41); /* R_PARISC_SECREL32.  */
     case EM_PJ:
     case EM_PJ_OLD:
@@ -12385,6 +12627,8 @@ is_32bit_pcrel_reloc (Filedata * filedata, unsigned int reloc_type)
       return reloc_type == 26; /* R_PPC_REL32.  */
     case EM_PPC64:
       return reloc_type == 26; /* R_PPC64_REL32.  */
+    case EM_RISCV:
+      return reloc_type == 57; /* R_RISCV_32_PCREL.  */
     case EM_S390_OLD:
     case EM_S390:
       return reloc_type == 5;  /* R_390_PC32.  */
@@ -12569,6 +12813,8 @@ is_16bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
       return reloc_type == 9; /* R_NIOS_16.  */
     case EM_OR1K:
       return reloc_type == 2; /* R_OR1K_16.  */
+    case EM_RISCV:
+      return reloc_type == 55; /* R_RISCV_SET16.  */
     case EM_TI_PRU:
       return reloc_type == 8; /* R_PRU_BFD_RELOC_16.  */
     case EM_TI_C6000:
@@ -12585,6 +12831,36 @@ is_16bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
     }
 }
 
+/* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is
+   a 8-bit absolute RELA relocation used in DWARF debug sections.  */
+
+static bfd_boolean
+is_8bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
+{
+  switch (filedata->file_header.e_machine)
+    {
+    case EM_RISCV:
+      return reloc_type == 54; /* R_RISCV_SET8.  */
+    default:
+      return FALSE;
+    }
+}
+
+/* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is
+   a 6-bit absolute RELA relocation used in DWARF debug sections.  */
+
+static bfd_boolean
+is_6bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
+{
+  switch (filedata->file_header.e_machine)
+    {
+    case EM_RISCV:
+      return reloc_type == 53; /* R_RISCV_SET6.  */
+    default:
+      return FALSE;
+    }
+}
+
 /* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is
    a 32-bit inplace add RELA relocation used in DWARF debug sections.  */
 
@@ -12713,6 +12989,21 @@ is_8bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type)
     }
 }
 
+/* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is
+   a 6-bit inplace sub RELA relocation used in DWARF debug sections.  */
+
+static bfd_boolean
+is_6bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type)
+{
+  switch (filedata->file_header.e_machine)
+    {
+    case EM_RISCV:
+      return reloc_type == 52; /* R_RISCV_SUB6.  */
+    default:
+      return FALSE;
+    }
+}
+
 /* Returns TRUE iff RELOC_TYPE is a NONE relocation used for discarded
    relocation entries (possibly formerly used for SHT_GROUP sections).  */
 
@@ -12832,7 +13123,6 @@ apply_relocations (Filedata *                 filedata,
 {
   Elf_Internal_Shdr * relsec;
   unsigned char * end = start + size;
-  bfd_boolean res = TRUE;
 
   if (relocs_return != NULL)
     {
@@ -12916,6 +13206,9 @@ apply_relocations (Filedata *                 filedata,
            reloc_size = 3;
          else if (is_16bit_abs_reloc (filedata, reloc_type))
            reloc_size = 2;
+         else if (is_8bit_abs_reloc (filedata, reloc_type)
+                  || is_6bit_abs_reloc (filedata, reloc_type))
+           reloc_size = 1;
          else if ((reloc_subtract = is_32bit_inplace_sub_reloc (filedata,
                                                                 reloc_type))
                   || is_32bit_inplace_add_reloc (filedata, reloc_type))
@@ -12944,6 +13237,12 @@ apply_relocations (Filedata *                 filedata,
              reloc_size = 1;
              reloc_inplace = TRUE;
            }
+         else if ((reloc_subtract = is_6bit_inplace_sub_reloc (filedata,
+                                                               reloc_type)))
+           {
+             reloc_size = 1;
+             reloc_inplace = TRUE;
+           }
          else
            {
              static unsigned int prev_reloc = 0;
@@ -12952,7 +13251,6 @@ apply_relocations (Filedata *                 filedata,
                warn (_("unable to apply unsupported reloc type %d to section %s\n"),
                      reloc_type, printable_section_name (filedata, section));
              prev_reloc = reloc_type;
-             res = FALSE;
              continue;
            }
 
@@ -12962,7 +13260,6 @@ apply_relocations (Filedata *                 filedata,
              warn (_("skipping invalid relocation offset 0x%lx in section %s\n"),
                    (unsigned long) rp->r_offset,
                    printable_section_name (filedata, section));
-             res = FALSE;
              continue;
            }
 
@@ -12971,7 +13268,6 @@ apply_relocations (Filedata *                 filedata,
            {
              warn (_("skipping invalid relocation symbol index 0x%lx in section %s\n"),
                    sym_index, printable_section_name (filedata, section));
-             res = FALSE;
              continue;
            }
          sym = symtab + sym_index;
@@ -12997,7 +13293,6 @@ apply_relocations (Filedata *                 filedata,
                    get_symbol_type (filedata, ELF_ST_TYPE (sym->st_info)),
                    printable_section_name (filedata, relsec),
                    (long int)(rp - relocs));
-             res = FALSE;
              continue;
            }
 
@@ -13016,7 +13311,12 @@ apply_relocations (Filedata *                 filedata,
                   || filedata->file_header.e_machine == EM_CYGNUS_D30V)
                  && reloc_type == 12)
              || reloc_inplace)
-           addend += byte_get (rloc, reloc_size);
+           {
+             if (is_6bit_inplace_sub_reloc (filedata, reloc_type))
+               addend += byte_get (rloc, reloc_size) & 0x3f;
+             else
+               addend += byte_get (rloc, reloc_size);
+           }
 
          if (is_32bit_pcrel_reloc (filedata, reloc_type)
              || is_64bit_pcrel_reloc (filedata, reloc_type))
@@ -13027,6 +13327,16 @@ apply_relocations (Filedata *                 filedata,
              byte_put (rloc, (addend + sym->st_value) - rp->r_offset,
                        reloc_size);
            }
+         else if (is_6bit_abs_reloc (filedata, reloc_type)
+                  || is_6bit_inplace_sub_reloc (filedata, reloc_type))
+           {
+             if (reloc_subtract)
+               addend -= sym->st_value;
+             else
+               addend += sym->st_value;
+             addend = (addend & 0x3f) | (byte_get (rloc, reloc_size) & 0xc0);
+             byte_put (rloc, addend, reloc_size);
+           }
          else if (reloc_subtract)
            byte_put (rloc, addend - sym->st_value, reloc_size);
          else
@@ -13049,7 +13359,7 @@ apply_relocations (Filedata *                 filedata,
       break;
     }
 
-  return res;
+  return TRUE;
 }
 
 #ifdef SUPPORT_DISASSEMBLY
@@ -13175,12 +13485,6 @@ dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata)
                    printable_section_name (filedata, section), chdr.ch_type);
              return FALSE;
            }
-         else if (chdr.ch_addralign != section->sh_addralign)
-           {
-             warn (_("compressed section '%s' is corrupted\n"),
-                   printable_section_name (filedata, section));
-             return FALSE;
-           }
          uncompressed_size = chdr.ch_size;
          start += compression_header_size;
          new_size -= compression_header_size;
@@ -13322,12 +13626,6 @@ dump_section_as_bytes (Elf_Internal_Shdr *  section,
                    printable_section_name (filedata, section), chdr.ch_type);
              return FALSE;
            }
-         else if (chdr.ch_addralign != section->sh_addralign)
-           {
-             warn (_("compressed section '%s' is corrupted\n"),
-                   printable_section_name (filedata, section));
-             return FALSE;
-           }
          uncompressed_size = chdr.ch_size;
          start += compression_header_size;
          new_size -= compression_header_size;
@@ -13497,12 +13795,6 @@ load_specific_debug_section (enum dwarf_section_display_enum  debug,
                    section->name, chdr.ch_type);
              return FALSE;
            }
-         else if (chdr.ch_addralign != sec->sh_addralign)
-           {
-             warn (_("compressed section '%s' is corrupted\n"),
-                   section->name);
-             return FALSE;
-           }
          uncompressed_size = chdr.ch_size;
          start += compression_header_size;
          size -= compression_header_size;
@@ -13574,20 +13866,27 @@ load_debug_section (enum dwarf_section_display_enum debug, void * data)
   Elf_Internal_Shdr * sec;
   Filedata * filedata = (Filedata *) data;
 
-  if (filedata->string_table == NULL)
+  /* Without section headers we cannot find any sections.  */
+  if (filedata->section_headers == NULL)
+    return FALSE;
+
+  if (filedata->string_table == NULL
+      && filedata->file_header.e_shstrndx != SHN_UNDEF
+      && filedata->file_header.e_shstrndx < filedata->file_header.e_shnum)
     {
       Elf_Internal_Shdr * strs;
 
       /* Read in the string table, so that we have section names to scan.  */
       strs = filedata->section_headers + filedata->file_header.e_shstrndx;
 
-      if (strs->sh_size != 0)
+      if (strs != NULL && strs->sh_size != 0)
        {
-         filedata->string_table = (char *) get_data (NULL, filedata, strs->sh_offset,
-                                                     1, strs->sh_size,
-                                                     _("string table"));
+         filedata->string_table
+           = (char *) get_data (NULL, filedata, strs->sh_offset,
+                                1, strs->sh_size, _("string table"));
 
-         filedata->string_table_length = filedata->string_table != NULL ? strs->sh_size : 0;
+         filedata->string_table_length
+           = filedata->string_table != NULL ? strs->sh_size : 0;
        }
     }
 
@@ -14045,6 +14344,12 @@ display_arc_attribute (unsigned char * p,
       printf ("  Tag_ARC_ISA_mpy_option: %d\n", val);
       break;
 
+    case Tag_ARC_ATR_version:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ATR_version: %d\n", val);
+      break;
+
     default:
       return display_tag_value (tag & 1, p, end);
     }
@@ -14987,7 +15292,7 @@ display_raw_attribute (unsigned char * p, unsigned char const * const end)
   unsigned long addr = 0;
   size_t bytes = end - p;
 
-  assert (end > p);
+  assert (end >= p);
   while (bytes)
     {
       int j;
@@ -15112,14 +15417,96 @@ display_msp430x_attribute (unsigned char * p,
   return p;
 }
 
-static bfd_boolean
-process_attributes (Filedata * filedata,
-                   const char * public_name,
-                   unsigned int proc_type,
-                   unsigned char * (* display_pub_attribute) (unsigned char *, const unsigned char * const),
-                   unsigned char * (* display_proc_gnu_attribute) (unsigned char *, unsigned int, const unsigned char * const))
+struct riscv_attr_tag_t {
+  const char *name;
+  int tag;
+};
+
+static struct riscv_attr_tag_t riscv_attr_tag[] =
 {
-  Elf_Internal_Shdr * sect;
+#define T(tag) {"Tag_RISCV_" #tag, Tag_RISCV_##tag}
+  T(arch),
+  T(priv_spec),
+  T(priv_spec_minor),
+  T(priv_spec_revision),
+  T(unaligned_access),
+  T(stack_align),
+#undef T
+};
+
+static unsigned char *
+display_riscv_attribute (unsigned char *p,
+                        const unsigned char * const end)
+{
+  unsigned int len;
+  int val;
+  int tag;
+  struct riscv_attr_tag_t *attr = NULL;
+  unsigned i;
+
+  tag = read_uleb128 (p, &len, end);
+  p += len;
+
+  /* Find the name of attribute. */
+  for (i = 0; i < ARRAY_SIZE (riscv_attr_tag); i++)
+    {
+      if (riscv_attr_tag[i].tag == tag)
+       {
+         attr = &riscv_attr_tag[i];
+         break;
+       }
+    }
+
+  if (attr)
+    printf ("  %s: ", attr->name);
+  else
+    return display_tag_value (tag, p, end);
+
+  switch (tag)
+    {
+    case Tag_RISCV_priv_spec:
+    case Tag_RISCV_priv_spec_minor:
+    case Tag_RISCV_priv_spec_revision:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf (_("%d\n"), val);
+      break;
+    case Tag_RISCV_unaligned_access:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      switch (val)
+       {
+       case 0:
+         printf (_("No unaligned access\n"));
+         break;
+       case 1:
+         printf (_("Unaligned access\n"));
+         break;
+       }
+      break;
+    case Tag_RISCV_stack_align:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf (_("%d-bytes\n"), val);
+      break;
+    case Tag_RISCV_arch:
+      p = display_tag_value (-1, p, end);
+      break;
+    default:
+      return display_tag_value (tag, p, end);
+    }
+
+  return p;
+}
+
+static bfd_boolean
+process_attributes (Filedata * filedata,
+                   const char * public_name,
+                   unsigned int proc_type,
+                   unsigned char * (* display_pub_attribute) (unsigned char *, const unsigned char * const),
+                   unsigned char * (* display_proc_gnu_attribute) (unsigned char *, unsigned int, const unsigned char * const))
+{
+  Elf_Internal_Shdr * sect;
   unsigned i;
   bfd_boolean res = TRUE;
 
@@ -15412,6 +15799,18 @@ print_mips_ases (unsigned int mask)
     fputs ("\n\tXPA ASE", stdout);
   if (mask & AFL_ASE_MIPS16E2)
     fputs ("\n\tMIPS16e2 ASE", stdout);
+  if (mask & AFL_ASE_CRC)
+    fputs ("\n\tCRC ASE", stdout);
+  if (mask & AFL_ASE_GINV)
+    fputs ("\n\tGINV ASE", stdout);
+  if (mask & AFL_ASE_LOONGSON_MMI)
+    fputs ("\n\tLoongson MMI ASE", stdout);
+  if (mask & AFL_ASE_LOONGSON_CAM)
+    fputs ("\n\tLoongson CAM ASE", stdout);
+  if (mask & AFL_ASE_LOONGSON_EXT)
+    fputs ("\n\tLoongson EXT ASE", stdout);
+  if (mask & AFL_ASE_LOONGSON_EXT2)
+    fputs ("\n\tLoongson EXT2 ASE", stdout);
   if (mask == 0)
     fprintf (stdout, "\n\t%s", _("None"));
   else if ((mask & ~AFL_ASE_MASK) != 0)
@@ -15438,9 +15837,6 @@ print_mips_isa_ext (unsigned int isa_ext)
     case AFL_EXT_OCTEONP:
       fputs ("Cavium Networks OcteonP", stdout);
       break;
-    case AFL_EXT_LOONGSON_3A:
-      fputs ("Loongson 3A", stdout);
-      break;
     case AFL_EXT_OCTEON:
       fputs ("Cavium Networks Octeon", stdout);
       break;
@@ -15824,6 +16220,12 @@ process_mips_specific (Filedata * filedata)
          error (_("No MIPS_OPTIONS header found\n"));
          return FALSE;
        }
+      /* PR 24243  */
+      if (sect->sh_size < sizeof (* eopt))
+       {
+         error (_("The MIPS options section is too small.\n"));
+         return FALSE;
+       }
 
       eopt = (Elf_External_Options *) get_data (NULL, filedata, options_offset, 1,
                                                 sect->sh_size, _("options"));
@@ -16508,7 +16910,7 @@ get_note_type (Filedata * filedata, unsigned e_type)
       case NT_PPC_TM_CVMX:
        return _("NT_PPC_TM_CVMX (ppc checkpointed Altivec registers)");
       case NT_PPC_TM_CVSX:
-       return _("NT_PPC_TM_VSX (ppc checkpointed VSX registers)");
+       return _("NT_PPC_TM_CVSX (ppc checkpointed VSX registers)");
       case NT_PPC_TM_SPR:
        return _("NT_PPC_TM_SPR (ppc TM special purpose registers)");
       case NT_PPC_TM_CTAR:
@@ -16584,9 +16986,9 @@ get_note_type (Filedata * filedata, unsigned e_type)
       case NT_ARCH:
        return _("NT_ARCH (architecture)");
       case NT_GNU_BUILD_ATTRIBUTE_OPEN:
-       return _("NT_GNU_BUILD_ATTRIBUTE_OPEN");
+       return _("OPEN");
       case NT_GNU_BUILD_ATTRIBUTE_FUNC:
-       return _("NT_GNU_BUILD_ATTRIBUTE_FUNC");
+       return _("func");
       default:
        break;
       }
@@ -16716,9 +17118,88 @@ get_gnu_elf_note_type (unsigned e_type)
     }
 }
 
+static void
+decode_x86_compat_isa (unsigned int bitmask)
+{
+  while (bitmask)
+    {
+      unsigned int bit = bitmask & (- bitmask);
+
+      bitmask &= ~ bit;
+      switch (bit)
+       {
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_486:
+         printf ("i486");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_586:
+         printf ("586");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_686:
+         printf ("686");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_SSE:
+         printf ("SSE");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_SSE2:
+         printf ("SSE2");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_SSE3:
+         printf ("SSE3");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_SSSE3:
+         printf ("SSSE3");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_SSE4_1:
+         printf ("SSE4_1");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_SSE4_2:
+         printf ("SSE4_2");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX:
+         printf ("AVX");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX2:
+         printf ("AVX2");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX512F:
+         printf ("AVX512F");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX512CD:
+         printf ("AVX512CD");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX512ER:
+         printf ("AVX512ER");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX512PF:
+         printf ("AVX512PF");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX512VL:
+         printf ("AVX512VL");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX512DQ:
+         printf ("AVX512DQ");
+         break;
+       case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX512BW:
+         printf ("AVX512BW");
+         break;
+       default:
+         printf (_("<unknown: %x>"), bit);
+         break;
+       }
+      if (bitmask)
+       printf (", ");
+    }
+}
+
 static void
 decode_x86_isa (unsigned int bitmask)
 {
+  if (!bitmask)
+    {
+      printf (_("<None>"));
+      return;
+    }
+
   while (bitmask)
     {
       unsigned int bit = bitmask & (- bitmask);
@@ -16726,25 +17207,81 @@ decode_x86_isa (unsigned int bitmask)
       bitmask &= ~ bit;
       switch (bit)
        {
-       case GNU_PROPERTY_X86_ISA_1_486: printf ("i486"); break;
-       case GNU_PROPERTY_X86_ISA_1_586: printf ("586"); break;
-       case GNU_PROPERTY_X86_ISA_1_686: printf ("686"); break;
-       case GNU_PROPERTY_X86_ISA_1_SSE: printf ("SSE"); break;
-       case GNU_PROPERTY_X86_ISA_1_SSE2: printf ("SSE2"); break;
-       case GNU_PROPERTY_X86_ISA_1_SSE3: printf ("SSE3"); break;
-       case GNU_PROPERTY_X86_ISA_1_SSSE3: printf ("SSSE3"); break;
-       case GNU_PROPERTY_X86_ISA_1_SSE4_1: printf ("SSE4_1"); break;
-       case GNU_PROPERTY_X86_ISA_1_SSE4_2: printf ("SSE4_2"); break;
-       case GNU_PROPERTY_X86_ISA_1_AVX: printf ("AVX"); break;
-       case GNU_PROPERTY_X86_ISA_1_AVX2: printf ("AVX2"); break;
-       case GNU_PROPERTY_X86_ISA_1_AVX512F: printf ("AVX512F"); break;
-       case GNU_PROPERTY_X86_ISA_1_AVX512CD: printf ("AVX512CD"); break;
-       case GNU_PROPERTY_X86_ISA_1_AVX512ER: printf ("AVX512ER"); break;
-       case GNU_PROPERTY_X86_ISA_1_AVX512PF: printf ("AVX512PF"); break;
-       case GNU_PROPERTY_X86_ISA_1_AVX512VL: printf ("AVX512VL"); break;
-       case GNU_PROPERTY_X86_ISA_1_AVX512DQ: printf ("AVX512DQ"); break;
-       case GNU_PROPERTY_X86_ISA_1_AVX512BW: printf ("AVX512BW"); break;
-       default: printf (_("<unknown: %x>"), bit); break;
+       case GNU_PROPERTY_X86_ISA_1_CMOV:
+         printf ("CMOV");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_SSE:
+         printf ("SSE");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_SSE2:
+         printf ("SSE2");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_SSE3:
+         printf ("SSE3");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_SSSE3:
+         printf ("SSSE3");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_SSE4_1:
+         printf ("SSE4_1");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_SSE4_2:
+         printf ("SSE4_2");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX:
+         printf ("AVX");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX2:
+         printf ("AVX2");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_FMA:
+         printf ("FMA");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512F:
+         printf ("AVX512F");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512CD:
+         printf ("AVX512CD");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512ER:
+         printf ("AVX512ER");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512PF:
+         printf ("AVX512PF");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512VL:
+         printf ("AVX512VL");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512DQ:
+         printf ("AVX512DQ");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512BW:
+         printf ("AVX512BW");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512_4FMAPS:
+         printf ("AVX512_4FMAPS");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512_4VNNIW:
+         printf ("AVX512_4VNNIW");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512_BITALG:
+         printf ("AVX512_BITALG");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512_IFMA:
+         printf ("AVX512_IFMA");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512_VBMI:
+         printf ("AVX512_VBMI");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512_VBMI2:
+         printf ("AVX512_VBMI2");
+         break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512_VNNI:
+         printf ("AVX512_VNNI");
+         break;
+       default:
+         printf (_("<unknown: %x>"), bit);
+         break;
        }
       if (bitmask)
        printf (", ");
@@ -16752,8 +17289,14 @@ decode_x86_isa (unsigned int bitmask)
 }
 
 static void
-decode_x86_feature (unsigned int type, unsigned int bitmask)
+decode_x86_feature_1 (unsigned int bitmask)
 {
+  if (!bitmask)
+    {
+      printf (_("<None>"));
+      return;
+    }
+
   while (bitmask)
     {
       unsigned int bit = bitmask & (- bitmask);
@@ -16762,26 +17305,10 @@ decode_x86_feature (unsigned int type, unsigned int bitmask)
       switch (bit)
        {
        case GNU_PROPERTY_X86_FEATURE_1_IBT:
-         switch (type)
-           {
-           case GNU_PROPERTY_X86_FEATURE_1_AND:
-             printf ("IBT");
-             break;
-           default:
-             /* This should never happen.  */
-             abort ();
-           }
+         printf ("IBT");
          break;
        case GNU_PROPERTY_X86_FEATURE_1_SHSTK:
-         switch (type)
-           {
-           case GNU_PROPERTY_X86_FEATURE_1_AND:
-             printf ("SHSTK");
-             break;
-           default:
-             /* This should never happen.  */
-             abort ();
-           }
+         printf ("SHSTK");
          break;
        default:
          printf (_("<unknown: %x>"), bit);
@@ -16792,6 +17319,88 @@ decode_x86_feature (unsigned int type, unsigned int bitmask)
     }
 }
 
+static void
+decode_x86_feature_2 (unsigned int bitmask)
+{
+  if (!bitmask)
+    {
+      printf (_("<None>"));
+      return;
+    }
+
+  while (bitmask)
+    {
+      unsigned int bit = bitmask & (- bitmask);
+
+      bitmask &= ~ bit;
+      switch (bit)
+       {
+       case GNU_PROPERTY_X86_FEATURE_2_X86:
+         printf ("x86");
+         break;
+       case GNU_PROPERTY_X86_FEATURE_2_X87:
+         printf ("x87");
+         break;
+       case GNU_PROPERTY_X86_FEATURE_2_MMX:
+         printf ("MMX");
+         break;
+       case GNU_PROPERTY_X86_FEATURE_2_XMM:
+         printf ("XMM");
+         break;
+       case GNU_PROPERTY_X86_FEATURE_2_YMM:
+         printf ("YMM");
+         break;
+       case GNU_PROPERTY_X86_FEATURE_2_ZMM:
+         printf ("ZMM");
+         break;
+       case GNU_PROPERTY_X86_FEATURE_2_FXSR:
+         printf ("FXSR");
+         break;
+       case GNU_PROPERTY_X86_FEATURE_2_XSAVE:
+         printf ("XSAVE");
+         break;
+       case GNU_PROPERTY_X86_FEATURE_2_XSAVEOPT:
+         printf ("XSAVEOPT");
+         break;
+       case GNU_PROPERTY_X86_FEATURE_2_XSAVEC:
+         printf ("XSAVEC");
+         break;
+       default:
+         printf (_("<unknown: %x>"), bit);
+         break;
+       }
+      if (bitmask)
+       printf (", ");
+    }
+}
+
+static void
+decode_aarch64_feature_1_and (unsigned int bitmask)
+{
+  while (bitmask)
+    {
+      unsigned int bit = bitmask & (- bitmask);
+
+      bitmask &= ~ bit;
+      switch (bit)
+       {
+       case GNU_PROPERTY_AARCH64_FEATURE_1_BTI:
+         printf ("BTI");
+         break;
+
+       case GNU_PROPERTY_AARCH64_FEATURE_1_PAC:
+         printf ("PAC");
+         break;
+
+       default:
+         printf (_("<unknown: %x>"), bit);
+         break;
+       }
+      if (bitmask)
+       printf (", ");
+    }
+}
+
 static void
 print_gnu_property_note (Filedata * filedata, Elf_Internal_Note * pnote)
 {
@@ -16837,36 +17446,107 @@ print_gnu_property_note (Filedata * filedata, Elf_Internal_Note * pnote)
              || filedata->file_header.e_machine == EM_IAMCU
              || filedata->file_header.e_machine == EM_386)
            {
+             unsigned int bitmask;
+
+             if (datasz == 4)
+               bitmask = byte_get (ptr, 4);
+             else
+               bitmask = 0;
+
              switch (type)
                {
                case GNU_PROPERTY_X86_ISA_1_USED:
-                 printf ("x86 ISA used: ");
                  if (datasz != 4)
-                   printf (_("<corrupt length: %#x> "), datasz);
+                   printf (_("x86 ISA used: <corrupt length: %#x> "),
+                           datasz);
                  else
-                   decode_x86_isa (byte_get (ptr, 4));
+                   {
+                     printf ("x86 ISA used: ");
+                     decode_x86_isa (bitmask);
+                   }
                  goto next;
 
                case GNU_PROPERTY_X86_ISA_1_NEEDED:
-                 printf ("x86 ISA needed: ");
                  if (datasz != 4)
-                   printf (_("<corrupt length: %#x> "), datasz);
+                   printf (_("x86 ISA needed: <corrupt length: %#x> "),
+                           datasz);
                  else
-                   decode_x86_isa (byte_get (ptr, 4));
+                   {
+                     printf ("x86 ISA needed: ");
+                     decode_x86_isa (bitmask);
+                   }
                  goto next;
 
                case GNU_PROPERTY_X86_FEATURE_1_AND:
-                 printf ("x86 feature: ");
                  if (datasz != 4)
-                   printf (_("<corrupt length: %#x> "), datasz);
+                   printf (_("x86 feature: <corrupt length: %#x> "),
+                           datasz);
+                 else
+                   {
+                     printf ("x86 feature: ");
+                     decode_x86_feature_1 (bitmask);
+                   }
+                 goto next;
+
+               case GNU_PROPERTY_X86_FEATURE_2_USED:
+                 if (datasz != 4)
+                   printf (_("x86 feature used: <corrupt length: %#x> "),
+                           datasz);
                  else
-                   decode_x86_feature (type, byte_get (ptr, 4));
+                   {
+                     printf ("x86 feature used: ");
+                     decode_x86_feature_2 (bitmask);
+                   }
+                 goto next;
+
+               case GNU_PROPERTY_X86_FEATURE_2_NEEDED:
+                 if (datasz != 4)
+                   printf (_("x86 feature needed: <corrupt length: %#x> "), datasz);
+                 else
+                   {
+                     printf ("x86 feature needed: ");
+                     decode_x86_feature_2 (bitmask);
+                   }
+                 goto next;
+
+               case GNU_PROPERTY_X86_COMPAT_ISA_1_USED:
+                 if (datasz != 4)
+                   printf (_("x86 ISA used: <corrupt length: %#x> "),
+                           datasz);
+                 else
+                   {
+                     printf ("x86 ISA used: ");
+                     decode_x86_compat_isa (bitmask);
+                   }
+                 goto next;
+
+               case GNU_PROPERTY_X86_COMPAT_ISA_1_NEEDED:
+                 if (datasz != 4)
+                   printf (_("x86 ISA needed: <corrupt length: %#x> "),
+                           datasz);
+                 else
+                   {
+                     printf ("x86 ISA needed: ");
+                     decode_x86_compat_isa (bitmask);
+                   }
                  goto next;
 
                default:
                  break;
                }
            }
+         else if (filedata->file_header.e_machine == EM_AARCH64)
+           {
+             if (type == GNU_PROPERTY_AARCH64_FEATURE_1_AND)
+               {
+                 printf ("AArch64 feature: ");
+                 if (datasz != 4)
+                   printf (_("<corrupt length: %#x> "), datasz);
+                 else
+                   decode_aarch64_feature_1_and (byte_get (ptr, 4));
+                 goto next;
+               }
+           }
        }
       else
        {
@@ -17260,25 +17940,60 @@ get_stapsdt_note_type (unsigned e_type)
 static bfd_boolean
 print_stapsdt_note (Elf_Internal_Note *pnote)
 {
-  int addr_size = is_32bit_elf ? 4 : 8;
+  size_t len, maxlen;
+  unsigned long addr_size = is_32bit_elf ? 4 : 8;
   char *data = pnote->descdata;
   char *data_end = pnote->descdata + pnote->descsz;
   bfd_vma pc, base_addr, semaphore;
   char *provider, *probe, *arg_fmt;
 
+  if (pnote->descsz < (addr_size * 3))
+    goto stapdt_note_too_small;
+
   pc = byte_get ((unsigned char *) data, addr_size);
   data += addr_size;
+
   base_addr = byte_get ((unsigned char *) data, addr_size);
   data += addr_size;
+
   semaphore = byte_get ((unsigned char *) data, addr_size);
   data += addr_size;
 
-  provider = data;
-  data += strlen (data) + 1;
-  probe = data;
-  data += strlen (data) + 1;
-  arg_fmt = data;
-  data += strlen (data) + 1;
+  if (data >= data_end)
+    goto stapdt_note_too_small;
+  maxlen = data_end - data;
+  len = strnlen (data, maxlen);
+  if (len < maxlen)
+    {
+      provider = data;
+      data += len + 1;
+    }
+  else
+    goto stapdt_note_too_small;
+
+  if (data >= data_end)
+    goto stapdt_note_too_small;
+  maxlen = data_end - data;
+  len = strnlen (data, maxlen);
+  if (len < maxlen)
+    {
+      probe = data;
+      data += len + 1;
+    }
+  else
+    goto stapdt_note_too_small;
+  
+  if (data >= data_end)
+    goto stapdt_note_too_small;
+  maxlen = data_end - data;
+  len = strnlen (data, maxlen);
+  if (len < maxlen)
+    {
+      arg_fmt = data;
+      data += len + 1;
+    }
+  else
+    goto stapdt_note_too_small;
 
   printf (_("    Provider: %s\n"), provider);
   printf (_("    Name: %s\n"), probe);
@@ -17292,6 +18007,11 @@ print_stapsdt_note (Elf_Internal_Note *pnote)
   printf (_("    Arguments: %s\n"), arg_fmt);
 
   return data == data_end;
+
+ stapdt_note_too_small:
+  printf (_("  <corrupt - note is too small>\n"));
+  error (_("corrupt stapdt note - the data size is too small\n"));
+  return FALSE;
 }
 
 static const char *
@@ -17338,42 +18058,77 @@ get_ia64_vms_note_type (unsigned e_type)
 static bfd_boolean
 print_ia64_vms_note (Elf_Internal_Note * pnote)
 {
+  int maxlen = pnote->descsz;
+
+  if (maxlen < 2 || (unsigned long) maxlen != pnote->descsz)
+    goto desc_size_fail;
+
   switch (pnote->type)
     {
     case NT_VMS_MHD:
-      if (pnote->descsz > 36)
-        {
-          size_t l = strlen (pnote->descdata + 34);
-          printf (_("    Creation date  : %.17s\n"), pnote->descdata);
-          printf (_("    Last patch date: %.17s\n"), pnote->descdata + 17);
-          printf (_("    Module name    : %s\n"), pnote->descdata + 34);
-          printf (_("    Module version : %s\n"), pnote->descdata + 34 + l + 1);
-        }
+      if (maxlen <= 36)
+       goto desc_size_fail;
+
+      int l = (int) strnlen (pnote->descdata + 34, maxlen - 34);
+
+      printf (_("    Creation date  : %.17s\n"), pnote->descdata);
+      printf (_("    Last patch date: %.17s\n"), pnote->descdata + 17);
+      if (l + 34 < maxlen)
+       {
+         printf (_("    Module name    : %s\n"), pnote->descdata + 34);
+         if (l + 35 < maxlen)
+           printf (_("    Module version : %s\n"), pnote->descdata + 34 + l + 1);
+         else
+           printf (_("    Module version : <missing>\n"));
+       }
       else
-        printf (_("    Invalid size\n"));
+       {
+         printf (_("    Module name    : <missing>\n"));
+         printf (_("    Module version : <missing>\n"));
+       }
       break;
+
     case NT_VMS_LNM:
-      printf (_("   Language: %s\n"), pnote->descdata);
+      printf (_("   Language: %.*s\n"), maxlen, pnote->descdata);
       break;
+
 #ifdef BFD64
     case NT_VMS_FPMODE:
       printf (_("   Floating Point mode: "));
+      if (maxlen < 8)
+       goto desc_size_fail;
+      /* FIXME: Generate an error if descsz > 8 ?  */
+
       printf ("0x%016" BFD_VMA_FMT "x\n",
-              (bfd_vma) byte_get ((unsigned char *)pnote->descdata, 8));
+             (bfd_vma) byte_get ((unsigned char *)pnote->descdata, 8));
       break;
+
     case NT_VMS_LINKTIME:
       printf (_("   Link time: "));
+      if (maxlen < 8)
+       goto desc_size_fail;
+      /* FIXME: Generate an error if descsz > 8 ?  */
+
       print_vms_time
-        ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata, 8));
+       ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata, 8));
       printf ("\n");
       break;
+
     case NT_VMS_PATCHTIME:
       printf (_("   Patch time: "));
+      if (maxlen < 8)
+       goto desc_size_fail;
+      /* FIXME: Generate an error if descsz > 8 ?  */
+
       print_vms_time
-        ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata, 8));
+       ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata, 8));
       printf ("\n");
       break;
+
     case NT_VMS_ORIG_DYN:
+      if (maxlen < 34)
+       goto desc_size_fail;
+
       printf (_("   Major id: %u,  minor id: %u\n"),
               (unsigned) byte_get ((unsigned char *)pnote->descdata, 4),
               (unsigned) byte_get ((unsigned char *)pnote->descdata + 4, 4));
@@ -17385,34 +18140,48 @@ print_ia64_vms_note (Elf_Internal_Note * pnote)
               (bfd_vma) byte_get ((unsigned char *)pnote->descdata + 16, 8));
       printf (_("   Header flags: 0x%08x\n"),
               (unsigned) byte_get ((unsigned char *)pnote->descdata + 24, 4));
-      printf (_("   Image id    : %s\n"), pnote->descdata + 32);
+      printf (_("   Image id    : %.*s\n"), maxlen - 32, pnote->descdata + 32);
       break;
 #endif
+
     case NT_VMS_IMGNAM:
-      printf (_("    Image name: %s\n"), pnote->descdata);
+      printf (_("    Image name: %.*s\n"), maxlen, pnote->descdata);
       break;
+
     case NT_VMS_GSTNAM:
-      printf (_("    Global symbol table name: %s\n"), pnote->descdata);
+      printf (_("    Global symbol table name: %.*s\n"), maxlen, pnote->descdata);
       break;
+
     case NT_VMS_IMGID:
-      printf (_("    Image id: %s\n"), pnote->descdata);
+      printf (_("    Image id: %.*s\n"), maxlen, pnote->descdata);
       break;
+
     case NT_VMS_LINKID:
-      printf (_("    Linker id: %s\n"), pnote->descdata);
+      printf (_("    Linker id: %.*s\n"), maxlen, pnote->descdata);
       break;
+
     default:
       return FALSE;
     }
+
   return TRUE;
+
+ desc_size_fail:
+  printf (_("  <corrupt - data size is too small>\n"));
+  error (_("corrupt IA64 note: data size is too small\n"));
+  return FALSE;
 }
 
-/* Print the name of the symbol associated with a build attribute
-   that is attached to address OFFSET.  */
+/* Find the symbol associated with a build attribute that is attached
+   to address OFFSET.  If PNAME is non-NULL then store the name of
+   the symbol (if found) in the provided pointer,  Returns NULL if a
+   symbol could not be found.  */
 
-static bfd_boolean
-print_symbol_for_build_attribute (Filedata *     filedata,
-                                 unsigned long  offset,
-                                 bfd_boolean    is_open_attr)
+static Elf_Internal_Sym *
+get_symbol_for_build_attribute (Filedata *       filedata,
+                               unsigned long    offset,
+                               bfd_boolean      is_open_attr,
+                               const char **    pname)
 {
   static Filedata *         saved_filedata = NULL;
   static char *             strtab;
@@ -17451,10 +18220,7 @@ print_symbol_for_build_attribute (Filedata *     filedata,
     }
 
   if (symtab == NULL || strtab == NULL)
-    {
-      printf ("\n");
-      return FALSE;
-    }
+    return NULL;
 
   /* Find a symbol whose value matches offset.  */
   for (sym = symtab; sym < symtab + nsyms; sym ++)
@@ -17467,6 +18233,13 @@ print_symbol_for_build_attribute (Filedata *     filedata,
        if (strtab[sym->st_name] == 0)
          continue;
 
+       /* The AArch64 and ARM architectures define mapping symbols
+          (eg $d, $x, $t) which we want to ignore.  */
+       if (strtab[sym->st_name] == '$'
+           && strtab[sym->st_name + 1] != 0
+           && strtab[sym->st_name + 2] == 0)
+         continue;
+
        if (is_open_attr)
          {
            /* For OPEN attributes we prefer GLOBAL over LOCAL symbols
@@ -17474,14 +18247,15 @@ print_symbol_for_build_attribute (Filedata *     filedata,
               FUNC symbols entirely.  */
            switch (ELF_ST_TYPE (sym->st_info))
              {
-             case STT_FILE:
-               saved_sym = sym;
-               /* We can stop searching now.  */
-               sym = symtab + nsyms;
-               continue;
-
              case STT_OBJECT:
+             case STT_FILE:
                saved_sym = sym;
+               if (sym->st_size)
+                 {
+                   /* If the symbol has a size associated
+                      with it then we can stop searching.  */
+                   sym = symtab + nsyms;
+                 }
                continue;
 
              case STT_FUNC:
@@ -17519,55 +18293,144 @@ print_symbol_for_build_attribute (Filedata *     filedata,
          }
       }
 
-  printf (" (%s: %s)\n",
-         is_open_attr ? _("file") : _("func"),
-         saved_sym ? strtab + saved_sym->st_name : _("<no symbol found>)"));
-  return TRUE;
+  if (saved_sym && pname)
+    * pname = strtab + saved_sym->st_name;
+
+  return saved_sym;
+}
+
+/* Returns true iff addr1 and addr2 are in the same section.  */
+
+static bfd_boolean
+same_section (Filedata * filedata, unsigned long addr1, unsigned long addr2)
+{
+  Elf_Internal_Shdr * a1;
+  Elf_Internal_Shdr * a2;
+
+  a1 = find_section_by_address (filedata, addr1);
+  a2 = find_section_by_address (filedata, addr2);
+  
+  return a1 == a2 && a1 != NULL;
 }
 
 static bfd_boolean
 print_gnu_build_attribute_description (Elf_Internal_Note *  pnote,
                                       Filedata *           filedata)
 {
-  static unsigned long global_offset = 0;
-  unsigned long        offset;
-  unsigned int         desc_size = is_32bit_elf ? 4 : 8;
-  bfd_boolean          is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN;
+  static unsigned long  global_offset = 0;
+  static unsigned long  global_end = 0;
+  static unsigned long  func_offset = 0;
+  static unsigned long  func_end = 0;
+
+  Elf_Internal_Sym *    sym;
+  const char *          name;
+  unsigned long         start;
+  unsigned long         end;
+  bfd_boolean           is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN;
 
-  if (pnote->descsz == 0)
+  switch (pnote->descsz)
     {
+    case 0:
+      /* A zero-length description means that the range of
+        the previous note of the same type should be used.  */
       if (is_open_attr)
        {
-         printf (_("    Applies from offset %#lx\n"), global_offset);
-         return TRUE;
+         if (global_end > global_offset)
+           printf (_("    Applies to region from %#lx to %#lx\n"),
+                   global_offset, global_end);
+         else
+           printf (_("    Applies to region from %#lx\n"), global_offset);
        }
       else
        {
-         printf (_("    Applies to func at %#lx"), global_offset);
-         return print_symbol_for_build_attribute (filedata, global_offset, is_open_attr);
+         if (func_end > func_offset)
+           printf (_("    Applies to region from %#lx to %#lx\n"), func_offset, func_end);
+         else
+           printf (_("    Applies to region from %#lx\n"), func_offset);
        }
-    }
+      return TRUE;
 
-  if (pnote->descsz != desc_size)
-    {
+    case 4:
+      start = byte_get ((unsigned char *) pnote->descdata, 4);
+      end = 0;
+      break;
+
+    case 8:
+      if (is_32bit_elf)
+       {
+         /* FIXME: We should check that version 3+ notes are being used here...  */
+         start = byte_get ((unsigned char *) pnote->descdata, 4);
+         end = byte_get ((unsigned char *) pnote->descdata + 4, 4);
+       }
+      else
+       {
+         start = byte_get ((unsigned char *) pnote->descdata, 8);
+         end = 0;
+       }
+      break;
+
+    case 16:
+      start = byte_get ((unsigned char *) pnote->descdata, 8);
+      end = byte_get ((unsigned char *) pnote->descdata + 8, 8);
+      break;
+      
+    default:
       error (_("    <invalid description size: %lx>\n"), pnote->descsz);
       printf (_("    <invalid descsz>"));
       return FALSE;
     }
 
-  offset = byte_get ((unsigned char *) pnote->descdata, desc_size);
+  name = NULL;
+  sym = get_symbol_for_build_attribute (filedata, start, is_open_attr, & name);
+  /* As of version 5 of the annobin plugin, filename symbols are biased by 2
+     in order to avoid them being confused with the start address of the
+     first function in the file...  */
+  if (sym == NULL && is_open_attr)
+    sym = get_symbol_for_build_attribute (filedata, start + 2, is_open_attr,
+                                         & name);
+
+  if (end == 0 && sym != NULL && sym->st_size > 0)
+    end = start + sym->st_size;
 
   if (is_open_attr)
     {
-      printf (_("    Applies from offset %#lx"), offset);
-      global_offset = offset;
+      /* FIXME: Need to properly allow for section alignment.
+        16 is just the alignment used on x86_64.  */
+      if (global_end > 0
+         && start > BFD_ALIGN (global_end, 16)
+         /* Build notes are not guaranteed to be organised in order of
+            increasing address, but we should find the all of the notes
+            for one section in the same place.  */
+         && same_section (filedata, start, global_end))
+       warn (_("Gap in build notes detected from %#lx to %#lx\n"),
+             global_end + 1, start - 1);
+
+      printf (_("    Applies to region from %#lx"), start);
+      global_offset = start;
+
+      if (end)
+       {
+         printf (_(" to %#lx"), end);
+         global_end = end;
+       }
     }
   else
     {
-      printf (_("    Applies to func at %#lx"), offset);
+      printf (_("    Applies to region from %#lx"), start);
+      func_offset = start;
+
+      if (end)
+       {
+         printf (_(" to %#lx"), end);
+         func_end = end;
+       }
     }
 
-  return print_symbol_for_build_attribute (filedata, offset, is_open_attr);
+  if (sym && name)
+    printf (_(" (%s)"), name);
+
+  printf ("\n");
+  return TRUE;
 }
 
 static bfd_boolean
@@ -17590,11 +18453,21 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
       return FALSE;
     }
 
-  left = 20;
+  if (do_wide)
+    left = 28;
+  else
+    left = 20;
 
   /* Version 2 of the spec adds a "GA" prefix to the name field.  */
   if (name[0] == 'G' && name[1] == 'A')
     {
+      if (pnote->namesz < 4)
+       {
+         error (_("corrupt name field in GNU build attribute note: size = %ld\n"), pnote->namesz);
+         print_symbol (-20, _("  <corrupt name>"));
+         return FALSE;
+       }
+
       printf ("GA");
       name += 2;
       left -= 2;
@@ -17904,12 +18777,13 @@ static bfd_boolean
 process_notes_at (Filedata *           filedata,
                  Elf_Internal_Shdr *  section,
                  bfd_vma              offset,
-                 bfd_vma              length)
+                 bfd_vma              length,
+                 bfd_vma              align)
 {
   Elf_External_Note * pnotes;
   Elf_External_Note * external;
-  char * end;
-  bfd_boolean res = TRUE;
+  char *              end;
+  bfd_boolean         res = TRUE;
 
   if (length <= 0)
     return FALSE;
@@ -17926,6 +18800,7 @@ process_notes_at (Filedata *           filedata,
   else
     pnotes = (Elf_External_Note *) get_data (NULL, filedata, offset, 1, length,
                                             _("notes"));
+
   if (pnotes == NULL)
     return FALSE;
 
@@ -17937,6 +18812,20 @@ process_notes_at (Filedata *           filedata,
     printf (_("\nDisplaying notes found at file offset 0x%08lx with length 0x%08lx:\n"),
            (unsigned long) offset, (unsigned long) length);
 
+  /* NB: Some note sections may have alignment value of 0 or 1.  gABI
+     specifies that notes should be aligned to 4 bytes in 32-bit
+     objects and to 8 bytes in 64-bit objects.  As a Linux extension,
+     we also support 4 byte alignment in 64-bit objects.  If section
+     alignment is less than 4, we treate alignment as 4 bytes.   */
+  if (align < 4)
+    align = 4;
+  else if (align != 4 && align != 8)
+    {
+      warn (_("Corrupt note: alignment %ld, expecting 4 or 8\n"),
+           (long) align);
+      return FALSE;
+    }
+
   printf (_("  %-20s %10s\tDescription\n"), _("Owner"), _("Data size"));
 
   end = (char *) pnotes + length;
@@ -17944,7 +18833,7 @@ process_notes_at (Filedata *           filedata,
     {
       Elf_Internal_Note inote;
       size_t min_notesz;
-      char *next;
+      char * next;
       char * temp = NULL;
       size_t data_remaining = end - (char *) external;
 
@@ -17970,12 +18859,10 @@ process_notes_at (Filedata *           filedata,
          inote.namedata = external->name;
          inote.descsz   = BYTE_GET (external->descsz);
          inote.descdata = ((char *) external
-                           + ELF_NOTE_DESC_OFFSET (inote.namesz,
-                                                   section->sh_addralign));
+                           + ELF_NOTE_DESC_OFFSET (inote.namesz, align));
          inote.descpos  = offset + (inote.descdata - (char *) pnotes);
          next = ((char *) external
-                 + ELF_NOTE_NEXT_OFFSET (inote.namesz, inote.descsz,
-                                         section->sh_addralign));
+                 + ELF_NOTE_NEXT_OFFSET (inote.namesz, inote.descsz, align));
        }
       else
        {
@@ -18016,8 +18903,8 @@ process_notes_at (Filedata *           filedata,
        {
          warn (_("note with invalid namesz and/or descsz found at offset 0x%lx\n"),
                (unsigned long) ((char *) external - (char *) pnotes));
-         warn (_(" type: 0x%lx, namesize: 0x%08lx, descsize: 0x%08lx\n"),
-               inote.type, inote.namesz, inote.descsz);
+         warn (_(" type: 0x%lx, namesize: 0x%08lx, descsize: 0x%08lx, alignment: %u\n"),
+               inote.type, inote.namesz, inote.descsz, (int) align);
          break;
        }
 
@@ -18027,7 +18914,7 @@ process_notes_at (Filedata *           filedata,
         one version of Linux (RedHat 6.0) generates corefiles that don't
         comply with the ELF spec by failing to include the null byte in
         namesz.  */
-      if (inote.namedata[inote.namesz - 1] != '\0')
+      if (inote.namesz > 0 && inote.namedata[inote.namesz - 1] != '\0')
        {
          if ((size_t) (inote.descdata - inote.namedata) == inote.namesz)
            {
@@ -18077,7 +18964,8 @@ process_corefile_note_segments (Filedata * filedata)
       if (segment->p_type == PT_NOTE)
        if (! process_notes_at (filedata, NULL,
                                (bfd_vma) segment->p_offset,
-                               (bfd_vma) segment->p_filesz))
+                               (bfd_vma) segment->p_filesz,
+                               (bfd_vma) segment->p_align))
          res = FALSE;
     }
 
@@ -18181,7 +19069,8 @@ process_note_sections (Filedata * filedata)
        {
          if (! process_notes_at (filedata, section,
                                  (bfd_vma) section->sh_offset,
-                                 (bfd_vma) section->sh_size))
+                                 (bfd_vma) section->sh_size,
+                                 (bfd_vma) section->sh_addralign))
            res = FALSE;
          n++;
        }
@@ -18275,6 +19164,11 @@ process_arch_specific (Filedata * filedata)
                                display_msp430x_attribute,
                                display_generic_attribute);
 
+    case EM_RISCV:
+     return process_attributes (filedata, "riscv", SHT_RISCV_ATTRIBUTES,
+                               display_riscv_attribute,
+                               display_generic_attribute);
+
     case EM_NDS32:
       return process_nds32_specific (filedata);
 
@@ -18480,7 +19374,7 @@ open_debug_file (const char * pathname)
 static bfd_boolean
 process_object (Filedata * filedata)
 {
-  Filedata * separates;
+  bfd_boolean  have_separate_files;
   unsigned int i;
   bfd_boolean res = TRUE;
 
@@ -18556,17 +19450,27 @@ process_object (Filedata * filedata)
   if (! process_version_sections (filedata))
     res = FALSE;
 
-  separates = load_separate_debug_file (filedata, filedata->file_name);
+  if (filedata->file_header.e_shstrndx != SHN_UNDEF)
+    have_separate_files = load_separate_debug_files (filedata, filedata->file_name);
+  else
+    have_separate_files = FALSE;
 
   if (! process_section_contents (filedata))
     res = FALSE;
 
-  if (separates)
+  if (have_separate_files)
     {
-      if (! process_section_headers (separates))
-       res = FALSE;
-      else if (! process_section_contents (separates))
-       res = FALSE;
+      separate_info * d;
+
+      for (d = first_separate_info; d != NULL; d = d->next)
+       {
+         if (! process_section_headers (d->handle))
+           res = FALSE;
+         else if (! process_section_contents (d->handle))
+           res = FALSE;
+       }
+
+      /* The file handles are closed by the call to free_debug_memory() below.  */
     }
 
   if (! process_notes (filedata))
@@ -18728,7 +19632,7 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive)
              l += strnlen (arch.sym_table + l, arch.sym_size - l) + 1;
            }
 
-         if (arch.uses_64bit_indicies)
+         if (arch.uses_64bit_indices)
            l = (l + 7) & ~ 7;
          else
            l += l & 1;
@@ -18774,7 +19678,7 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive)
       /* Read the next archive header.  */
       if (fseek (filedata->handle, arch.next_arhdr_offset, SEEK_SET) != 0)
         {
-          error (_("%s: failed to seek to next archive header\n"), filedata->file_name);
+          error (_("%s: failed to seek to next archive header\n"), arch.file_name);
           return FALSE;
         }
       got = fread (&arch.arhdr, 1, sizeof arch.arhdr, filedata->handle);
@@ -18782,7 +19686,10 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive)
         {
           if (got == 0)
            break;
-          error (_("%s: failed to read archive header\n"), filedata->file_name);
+         /* PR 24049 - we cannot use filedata->file_name as this will
+            have already been freed.  */
+         error (_("%s: failed to read archive header\n"), arch.file_name);
+           
           ret = FALSE;
           break;
         }
@@ -18802,7 +19709,7 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive)
       name = get_archive_member_name (&arch, &nested_arch);
       if (name == NULL)
        {
-         error (_("%s: bad archive file name\n"), filedata->file_name);
+         error (_("%s: bad archive file name\n"), arch.file_name);
          ret = FALSE;
          break;
        }
@@ -18811,7 +19718,7 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive)
       qualified_name = make_qualified_name (&arch, &nested_arch, name);
       if (qualified_name == NULL)
        {
-         error (_("%s: bad archive file name\n"), filedata->file_name);
+         error (_("%s: bad archive file name\n"), arch.file_name);
          ret = FALSE;
          break;
        }
@@ -18857,7 +19764,7 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive)
          if (nested_arch.file == NULL)
            {
              error (_("%s: contains corrupt thin archive: %s\n"),
-                    filedata->file_name, name);
+                    qualified_name, name);
              ret = FALSE;
              break;
            }
This page took 0.085466 seconds and 4 git commands to generate.