aarch64: add STO_AARCH64_VARIANT_PCS and DT_AARCH64_VARIANT_PCS
[deliverable/binutils-gdb.git] / binutils / readelf.c
index 92353c596f4bd2bef7a2bc280ad3a7f472dacda9..23ffd8660031b233a42a98a9e9b3e2aff4b052ae 100644 (file)
@@ -1,5 +1,5 @@
 /* readelf.c -- display contents of an ELF format file
-   Copyright (C) 1998-2018 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>
 #include "elf/d10v.h"
 #include "elf/d30v.h"
 #include "elf/dlx.h"
+#include "elf/bpf.h"
 #include "elf/epiphany.h"
 #include "elf/fr30.h"
 #include "elf/frv.h"
@@ -398,10 +399,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"),
@@ -780,6 +782,7 @@ guess_is_rela (unsigned int e_machine)
     case EM_SCORE:
     case EM_XGATE:
     case EM_NFP:
+    case EM_BPF:
       return FALSE;
 
       /* Targets that use RELA relocations.  */
@@ -1481,6 +1484,10 @@ dump_relocations (Filedata *          filedata,
          rtype = elf_visium_reloc_type (type);
          break;
 
+        case EM_BPF:
+          rtype = elf_bpf_reloc_type (type);
+          break;
+
        case EM_ADAPTEVA_EPIPHANY:
          rtype = elf_epiphany_reloc_type (type);
          break;
@@ -1796,6 +1803,19 @@ 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";
+    case DT_AARCH64_VARIANT_PCS:  return "AARCH64_VARIANT_PCS";
+    default:
+      return NULL;
+    }
+}
+
 static const char *
 get_mips_dynamic_type (unsigned long type)
 {
@@ -2169,6 +2189,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);
@@ -3404,7 +3427,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;
@@ -3687,6 +3712,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:
@@ -3928,6 +3955,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)
@@ -4199,6 +4227,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)
 {
@@ -4279,6 +4317,9 @@ get_section_type_name (Filedata * filedata, unsigned int sh_type)
            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;
@@ -5217,7 +5258,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;
@@ -6297,14 +6339,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))
@@ -6318,7 +6367,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"),
@@ -6351,29 +6400,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
-                 && (filedata->file_header.e_type == ET_EXEC
-                     || filedata->file_header.e_type == ET_DYN
-                     /* These next two tests may be redundant, but
-                        they have been left in for paranoia's sake.  */
-                     || streq (SECTION_NAME (section), ".rel.dyn")
-                     || streq (SECTION_NAME (section), ".rela.dyn")))
-               /* Dynamic relocations apply to segments, not sections, so
-                  they do not need an sh_info value.  */
-               ;
-             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:
@@ -7593,14 +7637,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;
            }
 
@@ -7619,6 +7663,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:
@@ -8049,19 +8102,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;
@@ -8129,7 +8203,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",
@@ -8802,21 +8876,28 @@ decode_tic6x_unwind_bytecode (Filedata *                 filedata,
            }
 
          printf (_("pop frame {"));
-         reg = nregs - 1;
-         for (i = i * 2; i > 0; i--)
+         if (nregs == 0)
+           {
+             printf (_("*corrupt* - no registers specified"));
+           }
+         else
            {
-             if (regpos[reg].offset == i - 1)
+             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 ("}");
@@ -9285,6 +9366,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)
 {
@@ -10299,6 +10395,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);
@@ -11003,6 +11102,22 @@ get_solaris_symbol_visibility (unsigned int visibility)
     }
 }
 
+static const char *
+get_aarch64_symbol_other (unsigned int other)
+{
+  static char buf[32];
+
+  if (other & STO_AARCH64_VARIANT_PCS)
+    {
+      other &= ~STO_AARCH64_VARIANT_PCS;
+      if (other == 0)
+       return "VARIANT_PCS";
+      snprintf (buf, sizeof buf, "VARIANT_PCS | %x", other);
+      return buf;
+    }
+  return NULL;
+}
+
 static const char *
 get_mips_symbol_other (unsigned int other)
 {
@@ -11114,6 +11229,9 @@ get_symbol_other (Filedata * filedata, unsigned int other)
 
   switch (filedata->file_header.e_machine)
     {
+    case EM_AARCH64:
+      result = get_aarch64_symbol_other (other);
+      break;
     case EM_MIPS:
       result = get_mips_symbol_other (other);
       break;
@@ -12318,6 +12436,8 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
     case EM_AARCH64:
       return (reloc_type == 258
              || reloc_type == 1); /* R_AARCH64_ABS32 || R_AARCH64_P32_ABS32 */
+    case EM_BPF:
+      return reloc_type == 11; /* R_BPF_DATA_32 */
     case EM_ADAPTEVA_EPIPHANY:
       return reloc_type == 3;
     case EM_ALPHA:
@@ -12382,7 +12502,8 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
     case EM_68HC12:
       return reloc_type == 6; /* R_M68HC11_32.  */
     case EM_S12Z:
-      return reloc_type == 6; /* R_S12Z_EXT32.  */
+      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:
@@ -12534,6 +12655,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.  */
@@ -13028,7 +13151,6 @@ apply_relocations (Filedata *                 filedata,
 {
   Elf_Internal_Shdr * relsec;
   unsigned char * end = start + size;
-  bfd_boolean res = TRUE;
 
   if (relocs_return != NULL)
     {
@@ -13157,7 +13279,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;
            }
 
@@ -13167,7 +13288,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;
            }
 
@@ -13176,7 +13296,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;
@@ -13202,7 +13321,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;
            }
 
@@ -13269,7 +13387,7 @@ apply_relocations (Filedata *                 filedata,
       break;
     }
 
-  return res;
+  return TRUE;
 }
 
 #ifdef SUPPORT_DISASSEMBLY
@@ -13395,12 +13513,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;
@@ -13542,12 +13654,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;
@@ -13717,12 +13823,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;
@@ -14298,7 +14398,7 @@ typedef struct
 static const char * arm_attr_tag_CPU_arch[] =
   {"Pre-v4", "v4", "v4T", "v5T", "v5TE", "v5TEJ", "v6", "v6KZ", "v6T2",
    "v6K", "v7", "v6-M", "v6S-M", "v7E-M", "v8", "v8-R", "v8-M.baseline",
-   "v8-M.mainline"};
+   "v8-M.mainline", "", "", "", "v8.1-M.mainline"};
 static const char * arm_attr_tag_ARM_ISA_use[] = {"No", "Yes"};
 static const char * arm_attr_tag_THUMB_ISA_use[] =
   {"No", "Thumb-1", "Thumb-2", "Yes"};
@@ -14362,6 +14462,9 @@ static const char * arm_attr_tag_Virtualization_use[] =
 static const char * arm_attr_tag_MPextension_use_legacy[] =
   {"Not Allowed", "Allowed"};
 
+static const char * arm_attr_tag_MVE_arch[] =
+  {"No MVE", "MVE Integer only", "MVE Integer and FP"};
+
 #define LOOKUP(id, name) \
   {id, #name, 0x80 | ARRAY_SIZE(arm_attr_tag_##name), arm_attr_tag_##name}
 static arm_attr_public_tag arm_attr_public_tags[] =
@@ -14401,6 +14504,7 @@ static arm_attr_public_tag arm_attr_public_tags[] =
   LOOKUP(42, MPextension_use),
   LOOKUP(44, DIV_use),
   LOOKUP(46, DSP_extension),
+  LOOKUP(48, MVE_arch),
   {64, "nodefaults", 0, NULL},
   {65, "also_compatible_with", 0, NULL},
   LOOKUP(66, T2EE_use),
@@ -15220,7 +15324,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;
@@ -15345,6 +15449,88 @@ display_msp430x_attribute (unsigned char * p,
   return p;
 }
 
+struct riscv_attr_tag_t {
+  const char *name;
+  int tag;
+};
+
+static struct riscv_attr_tag_t riscv_attr_tag[] =
+{
+#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,
@@ -15655,6 +15841,8 @@ print_mips_ases (unsigned int mask)
     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)
@@ -15681,9 +15869,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;
@@ -16067,6 +16252,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"));
@@ -17035,13 +17226,11 @@ decode_x86_compat_isa (unsigned int bitmask)
 static void
 decode_x86_isa (unsigned int bitmask)
 {
-  if (bitmask == GNU_PROPERTY_X86_UINT32_VALID)
+  if (!bitmask)
     {
       printf (_("<None>"));
       return;
     }
-  else
-    bitmask &= ~GNU_PROPERTY_X86_UINT32_VALID;
 
   while (bitmask)
     {
@@ -17122,6 +17311,9 @@ decode_x86_isa (unsigned int bitmask)
        case GNU_PROPERTY_X86_ISA_1_AVX512_VNNI:
          printf ("AVX512_VNNI");
          break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512_BF16:
+         printf ("AVX512_BF16");
+         break;
        default:
          printf (_("<unknown: %x>"), bit);
          break;
@@ -17134,13 +17326,11 @@ decode_x86_isa (unsigned int bitmask)
 static void
 decode_x86_feature_1 (unsigned int bitmask)
 {
-  if (bitmask == GNU_PROPERTY_X86_UINT32_VALID)
+  if (!bitmask)
     {
       printf (_("<None>"));
       return;
     }
-  else
-    bitmask &= ~GNU_PROPERTY_X86_UINT32_VALID;
 
   while (bitmask)
     {
@@ -17167,13 +17357,11 @@ decode_x86_feature_1 (unsigned int bitmask)
 static void
 decode_x86_feature_2 (unsigned int bitmask)
 {
-  if (bitmask == GNU_PROPERTY_X86_UINT32_VALID)
+  if (!bitmask)
     {
       printf (_("<None>"));
       return;
     }
-  else
-    bitmask &= ~GNU_PROPERTY_X86_UINT32_VALID;
 
   while (bitmask)
     {
@@ -17221,6 +17409,33 @@ decode_x86_feature_2 (unsigned int bitmask)
     }
 }
 
+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)
 {
@@ -17269,13 +17484,7 @@ print_gnu_property_note (Filedata * filedata, Elf_Internal_Note * pnote)
              unsigned int bitmask;
 
              if (datasz == 4)
-               {
-                 bitmask = byte_get (ptr, 4);
-                 if ((filedata->file_header.e_type == ET_EXEC
-                      || filedata->file_header.e_type == ET_DYN)
-                     && !(bitmask & GNU_PROPERTY_X86_UINT32_VALID))
-                   printf ("Invalid ");
-               }
+               bitmask = byte_get (ptr, 4);
              else
                bitmask = 0;
 
@@ -17361,6 +17570,18 @@ print_gnu_property_note (Filedata * filedata, Elf_Internal_Note * pnote)
                  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
        {
@@ -17754,25 +17975,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);
@@ -17786,6 +18042,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 *
@@ -17832,42 +18093,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));
@@ -17879,25 +18175,36 @@ 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;
 }
 
 /* Find the symbol associated with a build attribute that is attached
@@ -18642,7 +18949,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)
            {
@@ -18892,6 +19199,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);
 
@@ -19097,7 +19409,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;
 
@@ -19174,19 +19486,26 @@ process_object (Filedata * filedata)
     res = FALSE;
 
   if (filedata->file_header.e_shstrndx != SHN_UNDEF)
-    separates = load_separate_debug_file (filedata, filedata->file_name);
+    have_separate_files = load_separate_debug_files (filedata, filedata->file_name);
   else
-    separates = NULL;
+    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))
@@ -19394,7 +19713,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);
@@ -19402,7 +19721,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;
         }
@@ -19422,7 +19744,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;
        }
@@ -19431,7 +19753,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;
        }
@@ -19477,7 +19799,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.039565 seconds and 4 git commands to generate.