]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - binutils/readelf.c
x86: Support Intel Shadow Stack with SHSTK property
[thirdparty/binutils-gdb.git] / binutils / readelf.c
index 3bae045ec8b27eb4139c99f796ed5460e1a8b952..d23a020c2e78b6a7a2e385d6b44e1b0f055a78fc 100644 (file)
 #include "elf/v850.h"
 #include "elf/vax.h"
 #include "elf/visium.h"
+#include "elf/wasm32.h"
 #include "elf/x86-64.h"
 #include "elf/xc16x.h"
 #include "elf/xgate.h"
@@ -809,6 +810,7 @@ guess_is_rela (unsigned int e_machine)
     case EM_XTENSA_OLD:
     case EM_MICROBLAZE:
     case EM_MICROBLAZE_OLD:
+    case EM_WEBASSEMBLY:
       return TRUE;
 
     case EM_68HC05:
@@ -1498,6 +1500,10 @@ dump_relocations (FILE * file,
          rtype = elf_tilepro_reloc_type (type);
          break;
 
+       case EM_WEBASSEMBLY:
+         rtype = elf_wasm32_reloc_type (type);
+         break;
+
        case EM_XGATE:
          rtype = elf_xgate_reloc_type (type);
          break;
@@ -2205,11 +2211,11 @@ get_machine_name (unsigned e_machine)
 
   switch (e_machine)
     {
+      /* Please keep this switch table sorted by increasing EM_ value.  */
+      /* 0 */
     case EM_NONE:              return _("None");
-    case EM_AARCH64:           return "AArch64";
     case EM_M32:               return "WE32100";
     case EM_SPARC:             return "Sparc";
-    case EM_SPU:               return "SPU";
     case EM_386:               return "Intel 80386";
     case EM_68K:               return "MC68000";
     case EM_88K:               return "MC88000";
@@ -2217,61 +2223,50 @@ get_machine_name (unsigned e_machine)
     case EM_860:               return "Intel 80860";
     case EM_MIPS:              return "MIPS R3000";
     case EM_S370:              return "IBM System/370";
+      /* 10 */
     case EM_MIPS_RS3_LE:       return "MIPS R4000 big-endian";
     case EM_OLD_SPARCV9:       return "Sparc v9 (old)";
     case EM_PARISC:            return "HPPA";
-    case EM_PPC_OLD:           return "Power PC (old)";
+    case EM_VPP550:            return "Fujitsu VPP500";
     case EM_SPARC32PLUS:       return "Sparc v8+" ;
     case EM_960:               return "Intel 90860";
     case EM_PPC:               return "PowerPC";
+      /* 20 */
     case EM_PPC64:             return "PowerPC64";
+    case EM_S390_OLD:
+    case EM_S390:              return "IBM S/390";
+    case EM_SPU:               return "SPU";
+      /* 30 */
+    case EM_V800:              return "Renesas V850 (using RH850 ABI)";
     case EM_FR20:              return "Fujitsu FR20";
-    case EM_FT32:              return "FTDI FT32";
     case EM_RH32:              return "TRW RH32";
     case EM_MCORE:             return "MCORE";
+      /* 40 */
     case EM_ARM:               return "ARM";
     case EM_OLD_ALPHA:         return "Digital Alpha (old)";
     case EM_SH:                        return "Renesas / SuperH SH";
     case EM_SPARCV9:           return "Sparc v9";
     case EM_TRICORE:           return "Siemens Tricore";
     case EM_ARC:               return "ARC";
-    case EM_ARC_COMPACT:       return "ARCompact";
-    case EM_ARC_COMPACT2:      return "ARCv2";
     case EM_H8_300:            return "Renesas H8/300";
     case EM_H8_300H:           return "Renesas H8/300H";
     case EM_H8S:               return "Renesas H8S";
     case EM_H8_500:            return "Renesas H8/500";
+      /* 50 */
     case EM_IA_64:             return "Intel IA-64";
     case EM_MIPS_X:            return "Stanford MIPS-X";
     case EM_COLDFIRE:          return "Motorola Coldfire";
-    case EM_ALPHA:             return "Alpha";
-    case EM_CYGNUS_D10V:
-    case EM_D10V:              return "d10v";
-    case EM_CYGNUS_D30V:
-    case EM_D30V:              return "d30v";
-    case EM_CYGNUS_M32R:
-    case EM_M32R:              return "Renesas M32R (formerly Mitsubishi M32r)";
-    case EM_CYGNUS_V850:
-    case EM_V800:              return "Renesas V850 (using RH850 ABI)";
-    case EM_V850:              return "Renesas V850";
-    case EM_CYGNUS_MN10300:
-    case EM_MN10300:           return "mn10300";
-    case EM_CYGNUS_MN10200:
-    case EM_MN10200:           return "mn10200";
-    case EM_MOXIE:             return "Moxie";
-    case EM_CYGNUS_FR30:
-    case EM_FR30:              return "Fujitsu FR30";
-    case EM_CYGNUS_FRV:                return "Fujitsu FR-V";
-    case EM_PJ_OLD:
-    case EM_PJ:                        return "picoJava";
+    case EM_68HC12:            return "Motorola MC68HC12 Microcontroller";
     case EM_MMA:               return "Fujitsu Multimedia Accelerator";
     case EM_PCP:               return "Siemens PCP";
     case EM_NCPU:              return "Sony nCPU embedded RISC processor";
     case EM_NDR1:              return "Denso NDR1 microprocesspr";
     case EM_STARCORE:          return "Motorola Star*Core processor";
     case EM_ME16:              return "Toyota ME16 processor";
+      /* 60 */
     case EM_ST100:             return "STMicroelectronics ST100 processor";
     case EM_TINYJ:             return "Advanced Logic Corp. TinyJ embedded processor";
+    case EM_X86_64:            return "Advanced Micro Devices X86-64";
     case EM_PDSP:              return "Sony DSP processor";
     case EM_PDP10:             return "Digital Equipment Corp. PDP-10";
     case EM_PDP11:             return "Digital Equipment Corp. PDP-11";
@@ -2279,75 +2274,89 @@ get_machine_name (unsigned e_machine)
     case EM_ST9PLUS:           return "STMicroelectronics ST9+ 8/16 bit microcontroller";
     case EM_ST7:               return "STMicroelectronics ST7 8-bit microcontroller";
     case EM_68HC16:            return "Motorola MC68HC16 Microcontroller";
-    case EM_68HC12:            return "Motorola MC68HC12 Microcontroller";
+      /* 70 */
     case EM_68HC11:            return "Motorola MC68HC11 Microcontroller";
     case EM_68HC08:            return "Motorola MC68HC08 Microcontroller";
     case EM_68HC05:            return "Motorola MC68HC05 Microcontroller";
     case EM_SVX:               return "Silicon Graphics SVx";
     case EM_ST19:              return "STMicroelectronics ST19 8-bit microcontroller";
     case EM_VAX:               return "Digital VAX";
-    case EM_VISIUM:            return "CDS VISIUMcore processor";
-    case EM_AVR_OLD:
-    case EM_AVR:               return "Atmel AVR 8-bit microcontroller";
     case EM_CRIS:              return "Axis Communications 32-bit embedded processor";
     case EM_JAVELIN:           return "Infineon Technologies 32-bit embedded cpu";
     case EM_FIREPATH:          return "Element 14 64-bit DSP processor";
     case EM_ZSP:               return "LSI Logic's 16-bit DSP processor";
+      /* 80 */
     case EM_MMIX:              return "Donald Knuth's educational 64-bit processor";
     case EM_HUANY:             return "Harvard Universitys's machine-independent object format";
     case EM_PRISM:             return "Vitesse Prism";
-    case EM_X86_64:            return "Advanced Micro Devices X86-64";
-    case EM_L1OM:              return "Intel L1OM";
-    case EM_K1OM:              return "Intel K1OM";
-    case EM_S390_OLD:
-    case EM_S390:              return "IBM S/390";
-    case EM_SCORE:             return "SUNPLUS S+Core";
-    case EM_XSTORMY16:         return "Sanyo XStormy16 CPU core";
+    case EM_AVR_OLD:
+    case EM_AVR:               return "Atmel AVR 8-bit microcontroller";
+    case EM_CYGNUS_FR30:
+    case EM_FR30:              return "Fujitsu FR30";
+    case EM_CYGNUS_D10V:
+    case EM_D10V:              return "d10v";
+    case EM_CYGNUS_D30V:
+    case EM_D30V:              return "d30v";
+    case EM_CYGNUS_V850:
+    case EM_V850:              return "Renesas V850";
+    case EM_CYGNUS_M32R:
+    case EM_M32R:              return "Renesas M32R (formerly Mitsubishi M32r)";
+    case EM_CYGNUS_MN10300:
+    case EM_MN10300:           return "mn10300";
+      /* 90 */
+    case EM_CYGNUS_MN10200:
+    case EM_MN10200:           return "mn10200";
+    case EM_PJ:                        return "picoJava";
     case EM_OR1K:              return "OpenRISC 1000";
-    case EM_CRX:               return "National Semiconductor CRX microprocessor";
-    case EM_ADAPTEVA_EPIPHANY: return "Adapteva EPIPHANY";
-    case EM_DLX:               return "OpenDLX";
-    case EM_IP2K_OLD:
-    case EM_IP2K:              return "Ubicom IP2xxx 8-bit microcontrollers";
-    case EM_IQ2000:            return "Vitesse IQ2000";
+    case EM_ARC_COMPACT:       return "ARCompact";
     case EM_XTENSA_OLD:
     case EM_XTENSA:            return "Tensilica Xtensa Processor";
     case EM_VIDEOCORE:         return "Alphamosaic VideoCore processor";
     case EM_TMM_GPP:           return "Thompson Multimedia General Purpose Processor";
     case EM_NS32K:             return "National Semiconductor 32000 series";
     case EM_TPC:               return "Tenor Network TPC processor";
-    case EM_ST200:             return "STMicroelectronics ST200 microcontroller";
+    case EM_SNP1K:             return "Trebia SNP 1000 processor";
+      /* 100 */
+    case EM_ST200:             return "STMicroelectronics ST200 microcontroller";  
+    case EM_IP2K_OLD:
+    case EM_IP2K:              return "Ubicom IP2xxx 8-bit microcontrollers";
     case EM_MAX:               return "MAX Processor";
     case EM_CR:                        return "National Semiconductor CompactRISC";
     case EM_F2MC16:            return "Fujitsu F2MC16";
     case EM_MSP430:            return "Texas Instruments msp430 microcontroller";
-    case EM_LATTICEMICO32:     return "Lattice Mico32";
-    case EM_M32C_OLD:
-    case EM_M32C:              return "Renesas M32c";
-    case EM_MT:                 return "Morpho Techologies MT processor";
     case EM_BLACKFIN:          return "Analog Devices Blackfin";
     case EM_SE_C33:            return "S1C33 Family of Seiko Epson processors";
     case EM_SEP:               return "Sharp embedded microprocessor";
     case EM_ARCA:              return "Arca RISC microprocessor";
+      /* 110 */
     case EM_UNICORE:           return "Unicore";
     case EM_EXCESS:            return "eXcess 16/32/64-bit configurable embedded CPU";
     case EM_DXP:               return "Icera Semiconductor Inc. Deep Execution Processor";
-    case EM_NIOS32:            return "Altera Nios";
     case EM_ALTERA_NIOS2:      return "Altera Nios II";
+    case EM_CRX:               return "National Semiconductor CRX microprocessor";
+    case EM_XGATE:             return "Motorola XGATE embedded processor";
     case EM_C166:
     case EM_XC16X:             return "Infineon Technologies xc16x";
     case EM_M16C:              return "Renesas M16C series microprocessors";
     case EM_DSPIC30F:          return "Microchip Technology dsPIC30F Digital Signal Controller";
     case EM_CE:                        return "Freescale Communication Engine RISC core";
+      /* 120 */
+    case EM_M32C:              return "Renesas M32c";
+      /* 130 */
     case EM_TSK3000:           return "Altium TSK3000 core";
     case EM_RS08:              return "Freescale RS08 embedded processor";
     case EM_ECOG2:             return "Cyan Technology eCOG2 microprocessor";
+    case EM_SCORE:             return "SUNPLUS S+Core";
     case EM_DSP24:             return "New Japan Radio (NJR) 24-bit DSP Processor";
     case EM_VIDEOCORE3:                return "Broadcom VideoCore III processor";
+    case EM_LATTICEMICO32:     return "Lattice Mico32";
     case EM_SE_C17:            return "Seiko Epson C17 family";
+      /* 140 */
     case EM_TI_C6000:          return "Texas Instruments TMS320C6000 DSP family";
     case EM_TI_C2000:          return "Texas Instruments TMS320C2000 DSP family";
     case EM_TI_C5500:          return "Texas Instruments TMS320C55x DSP family";
+    case EM_TI_PRU:            return "TI PRU I/O processor";
+      /* 160 */
     case EM_MMDSP_PLUS:                return "STMicroelectronics 64bit VLIW Data Signal Processor";
     case EM_CYPRESS_M8C:       return "Cypress M8C microprocessor";
     case EM_R32C:              return "Renesas R32C series microprocessors";
@@ -2358,38 +2367,47 @@ get_machine_name (unsigned e_machine)
     case EM_NDS32:             return "Andes Technology compact code size embedded RISC processor family";
     case EM_ECOG1X:            return "Cyan Technology eCOG1X family";
     case EM_MAXQ30:            return "Dallas Semiconductor MAXQ30 Core microcontrollers";
+      /* 170 */
     case EM_XIMO16:            return "New Japan Radio (NJR) 16-bit DSP Processor";
     case EM_MANIK:             return "M2000 Reconfigurable RISC Microprocessor";
     case EM_CRAYNV2:           return "Cray Inc. NV2 vector architecture";
-    case EM_CYGNUS_MEP:         return "Toshiba MeP Media Engine";
-    case EM_CR16:
-    case EM_MICROBLAZE:
-    case EM_MICROBLAZE_OLD:    return "Xilinx MicroBlaze";
-    case EM_RISCV:             return "RISC-V";
-    case EM_RL78:              return "Renesas RL78";
     case EM_RX:                        return "Renesas RX";
     case EM_METAG:             return "Imagination Technologies Meta processor architecture";
     case EM_MCST_ELBRUS:       return "MCST Elbrus general purpose hardware architecture";
     case EM_ECOG16:            return "Cyan Technology eCOG16 family";
+    case EM_CR16:
+    case EM_MICROBLAZE:
+    case EM_MICROBLAZE_OLD:    return "Xilinx MicroBlaze";
     case EM_ETPU:              return "Freescale Extended Time Processing Unit";
     case EM_SLE9X:             return "Infineon Technologies SLE9X core";
-    case EM_AVR32:             return "Atmel Corporation 32-bit microprocessor family";
+      /* 180 */
+    case EM_L1OM:              return "Intel L1OM";
+    case EM_K1OM:              return "Intel K1OM";
+    case EM_INTEL182:          return "Intel (reserved)";
+    case EM_AARCH64:           return "AArch64";
+    case EM_ARM184:            return "ARM (reserved)";
+    case EM_AVR32:             return "Atmel Corporation 32-bit microprocessor";
     case EM_STM8:              return "STMicroeletronics STM8 8-bit microcontroller";
     case EM_TILE64:            return "Tilera TILE64 multicore architecture family";
     case EM_TILEPRO:           return "Tilera TILEPro multicore architecture family";
-    case EM_TILEGX:            return "Tilera TILE-Gx multicore architecture family";
+      /* 190 */
     case EM_CUDA:              return "NVIDIA CUDA architecture";
-    case EM_XGATE:             return "Motorola XGATE embedded processor";
+    case EM_TILEGX:            return "Tilera TILE-Gx multicore architecture family";
     case EM_CLOUDSHIELD:       return "CloudShield architecture family";
     case EM_COREA_1ST:         return "KIPO-KAIST Core-A 1st generation processor family";
     case EM_COREA_2ND:         return "KIPO-KAIST Core-A 2nd generation processor family";
+    case EM_ARC_COMPACT2:      return "ARCv2";
     case EM_OPEN8:             return "Open8 8-bit RISC soft processor core";
+    case EM_RL78:              return "Renesas RL78";
     case EM_VIDEOCORE5:                return "Broadcom VideoCore V processor";
+    case EM_78K0R:             return "Renesas 78K0R";
+      /* 200 */
     case EM_56800EX:           return "Freescale 56800EX Digital Signal Controller (DSC)";
     case EM_BA1:               return "Beyond BA1 CPU architecture";
     case EM_BA2:               return "Beyond BA2 CPU architecture";
     case EM_XCORE:             return "XMOS xCORE processor family";
     case EM_MCHP_PIC:          return "Microchip 8-bit PIC(r) family";
+      /* 210 */
     case EM_KM32:              return "KM211 KM32 32-bit processor";
     case EM_KMX32:             return "KM211 KMX32 32-bit processor";
     case EM_KMX16:             return "KM211 KMX16 16-bit processor";
@@ -2400,9 +2418,29 @@ get_machine_name (unsigned e_machine)
     case EM_COOL:              return "Bluechip Systems CoolEngine";
     case EM_NORC:              return "Nanoradio Optimized RISC";
     case EM_CSR_KALIMBA:       return "CSR Kalimba architecture family";
+      /* 220 */
     case EM_Z80:               return "Zilog Z80";
-    case EM_AMDGPU:            return "AMD GPU architecture";
-    case EM_TI_PRU:            return "TI PRU I/O processor";
+    case EM_VISIUM:            return "CDS VISIUMcore processor";
+    case EM_FT32:               return "FTDI Chip FT32";
+    case EM_MOXIE:              return "Moxie";
+    case EM_AMDGPU:            return "AMD GPU";
+    case EM_RISCV:             return "RISC-V";
+    case EM_LANAI:             return "Lanai 32-bit processor";
+    case EM_BPF:               return "Linux BPF";
+
+      /* Large numbers...  */
+    case EM_MT:                 return "Morpho Techologies MT processor";
+    case EM_ALPHA:             return "Alpha";
+    case EM_WEBASSEMBLY:       return "Web Assembly";
+    case EM_DLX:               return "OpenDLX";  
+    case EM_XSTORMY16:         return "Sanyo XStormy16 CPU core";
+    case EM_IQ2000:            return "Vitesse IQ2000";
+    case EM_M32C_OLD:
+    case EM_NIOS32:            return "Altera Nios";
+    case EM_CYGNUS_MEP:         return "Toshiba MeP Media Engine";
+    case EM_ADAPTEVA_EPIPHANY: return "Adapteva EPIPHANY";
+    case EM_CYGNUS_FRV:                return "Fujitsu FR-V";
+
     default:
       snprintf (buff, sizeof (buff), _("<unknown>: 0x%x"), e_machine);
       return buff;
@@ -2470,6 +2508,9 @@ decode_ARC_machine_flags (unsigned e_flags, unsigned e_machine, char buf[])
     case E_ARC_OSABI_V3:
       strcat (buf, ", v3 no-legacy-syscalls ABI");
       break;
+    case E_ARC_OSABI_V4:
+      strcat (buf, ", v4 ABI");
+      break;
     default:
       strcat (buf, ", unrecognised ARC OSABI flag");
       break;
@@ -3787,7 +3828,12 @@ get_segment_type (unsigned long p_type)
     case PT_GNU_RELRO:  return "GNU_RELRO";
 
     default:
-      if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
+      if (p_type >= PT_GNU_MBIND_LO && p_type <= PT_GNU_MBIND_HI)
+       {
+         sprintf (buff, "GNU_MBIND+%#lx",
+                  p_type - PT_GNU_MBIND_LO);
+       }
+      else if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
        {
          const char * result;
 
@@ -3854,6 +3900,18 @@ get_segment_type (unsigned long p_type)
     }
 }
 
+static const char *
+get_arc_section_type_name (unsigned int sh_type)
+{
+  switch (sh_type)
+    {
+    case SHT_ARC_ATTRIBUTES:      return "ARC_ATTRIBUTES";
+    default:
+      break;
+    }
+  return NULL;
+}
+
 static const char *
 get_mips_section_type_name (unsigned int sh_type)
 {
@@ -4063,6 +4121,11 @@ get_section_type_name (unsigned int sh_type)
        {
          switch (elf_header.e_machine)
            {
+           case EM_ARC:
+           case EM_ARC_COMPACT:
+           case EM_ARC_COMPACT2:
+             result = get_arc_section_type_name (sh_type);
+             break;
            case EM_MIPS:
            case EM_MIPS_RS3_LE:
              result = get_mips_section_type_name (sh_type);
@@ -4756,9 +4819,19 @@ get_program_headers (FILE * file)
   if (program_headers != NULL)
     return TRUE;
 
-  phdrs = (Elf_Internal_Phdr *) cmalloc (elf_header.e_phnum,
-                                         sizeof (Elf_Internal_Phdr));
+  /* Be kind to memory checkers by looking for
+     e_phnum values which we know must be invalid.  */
+  if (elf_header.e_phnum
+      * (is_32bit_elf ? sizeof (Elf32_External_Phdr) : sizeof (Elf64_External_Phdr))
+      >= current_file_size)
+    {
+      error (_("Too many program headers - %#x - the file is not that big\n"),
+            elf_header.e_phnum);
+      return FALSE;
+    }
 
+  phdrs = (Elf_Internal_Phdr *) cmalloc (elf_header.e_phnum,
+                                        sizeof (Elf_Internal_Phdr));
   if (phdrs == NULL)
     {
       error (_("Out of memory reading %u program headers\n"),
@@ -4965,12 +5038,6 @@ process_program_headers (FILE * file)
             section in the DYNAMIC segment.  */
          dynamic_addr = segment->p_offset;
          dynamic_size = segment->p_filesz;
-         /* PR binutils/17512: Avoid corrupt dynamic section info in the segment.  */
-         if (dynamic_addr + dynamic_size >= current_file_size)
-           {
-             error (_("the dynamic segment offset + size exceeds the size of the file\n"));
-             dynamic_addr = dynamic_size = 0;
-           }
 
          /* Try to locate the .dynamic section. If there is
             a section header table, we can easily locate it.  */
@@ -5005,6 +5072,16 @@ process_program_headers (FILE * file)
                warn (_("the .dynamic section is not the first section"
                        " in the dynamic segment.\n"));
            }
+
+         /* PR binutils/17512: Avoid corrupt dynamic section info in the
+            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 >= current_file_size)
+           {
+             error (_("the dynamic segment offset + size exceeds the size of the file\n"));
+             dynamic_addr = dynamic_size = 0;
+           }
          break;
 
        case PT_INTERP:
@@ -5492,7 +5569,9 @@ get_elf_section_flags (bfd_vma sh_flags)
       /* ARM specific.  */
       /* 21 */ { STRING_COMMA_LEN ("ENTRYSECT") },
       /* 22 */ { STRING_COMMA_LEN ("ARM_PURECODE") },
-      /* 23 */ { STRING_COMMA_LEN ("COMDEF") }
+      /* 23 */ { STRING_COMMA_LEN ("COMDEF") },
+      /* GNU specific.  */
+      /* 24 */ { STRING_COMMA_LEN ("GNU_MBIND") },
     };
 
   if (do_section_details)
@@ -5525,6 +5604,7 @@ get_elf_section_flags (bfd_vma sh_flags)
            case SHF_TLS:               sindex = 9; break;
            case SHF_EXCLUDE:           sindex = 18; break;
            case SHF_COMPRESSED:        sindex = 20; break;
+           case SHF_GNU_MBIND:         sindex = 24; break;
 
            default:
              sindex = -1;
@@ -5618,6 +5698,7 @@ get_elf_section_flags (bfd_vma sh_flags)
            case SHF_TLS:               *p = 'T'; break;
            case SHF_EXCLUDE:           *p = 'E'; break;
            case SHF_COMPRESSED:        *p = 'C'; break;
+           case SHF_GNU_MBIND:         *p = 'D'; break;
 
            default:
              if ((elf_header.e_machine == EM_X86_64
@@ -6146,12 +6227,21 @@ process_section_headers (FILE * file)
              if (section->sh_info < 1 || section->sh_info >= elf_header.e_shnum)
                warn (_("[%2u]: Expected link to another section in info field"), i);
            }
-         else if (section->sh_type < SHT_LOOS && section->sh_info != 0)
+         else if (section->sh_type < SHT_LOOS
+                  && (section->sh_flags & SHF_GNU_MBIND) == 0
+                  && section->sh_info != 0)
            warn (_("[%2u]: Unexpected value (%u) in info field.\n"),
                  i, section->sh_info);
          break;
        }
 
+      /* Check the sh_size field.  */
+      if (section->sh_size > current_file_size
+         && section->sh_type != SHT_NOBITS
+         && section->sh_type != SHT_NULL
+         && section->sh_type < SHT_LOOS)
+       warn (_("Size of section %u is larger than the entire file!\n"), i);
+
       printf ("  [%2u] ", i);
       if (do_section_details)
        printf ("%s\n      ", printable_section_name (section));
@@ -8011,9 +8101,9 @@ get_unwind_section_word (struct arm_unw_aux_info *  aux,
     return FALSE;
 
   /* If the offset is invalid then fail.  */
-  if (word_offset > (sec->sh_size - 4)
-      /* PR 18879 */
-      || (sec->sh_size < 5 && word_offset >= sec->sh_size)
+  if (/* PR 21343 *//* PR 18879 */
+      sec->sh_size < 4
+      || word_offset > (sec->sh_size - 4)
       || ((bfd_signed_vma) word_offset) < 0)
     return FALSE;
 
@@ -9373,6 +9463,12 @@ process_dynamic_section (FILE * file)
             processing that.  This is overkill, I know, but it
             should work.  */
          section.sh_offset = offset_from_vma (file, entry->d_un.d_val, 0);
+         if ((bfd_size_type) section.sh_offset > current_file_size)
+           {
+             /* See PR 21379 for a reproducer.  */
+             error (_("Invalid DT_SYMTAB entry: %lx"), (long) section.sh_offset);
+             return FALSE;
+           }
 
          if (archive_file_offset != 0)
            section.sh_size = archive_file_size - section.sh_offset;
@@ -10102,8 +10198,9 @@ process_version_sections (FILE * file)
                printf (_("  Index: %d  Cnt: %d  "),
                        ent.vd_ndx, ent.vd_cnt);
 
-               /* Check for overflow.  */
-               if (ent.vd_aux + sizeof (* eaux) > (size_t) (endbuf - vstart))
+               /* Check for overflow and underflow.  */
+               if (ent.vd_aux + sizeof (* eaux) > (size_t) (endbuf - vstart)
+                   || (vstart + ent.vd_aux < vstart))
                  break;
 
                vstart += ent.vd_aux;
@@ -12055,6 +12152,8 @@ is_32bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 1; /* R_VAX_32.  */
     case EM_VISIUM:
       return reloc_type == 3;  /* R_VISIUM_32. */
+    case EM_WEBASSEMBLY:
+      return reloc_type == 1;  /* R_WASM32_32.  */
     case EM_X86_64:
     case EM_L1OM:
     case EM_K1OM:
@@ -12360,6 +12459,7 @@ is_none_reloc (unsigned int reloc_type)
     case EM_TI_C6000:/* R_C6000_NONE.  */
     case EM_X86_64:  /* R_X86_64_NONE.  */
     case EM_XC16X:
+    case EM_WEBASSEMBLY: /* R_WASM32_NONE.  */
       return reloc_type == 0;
 
     case EM_AARCH64:
@@ -13411,6 +13511,181 @@ display_tag_value (signed int tag,
   return p;
 }
 
+/* ARC ABI attributes section.  */
+
+static unsigned char *
+display_arc_attribute (unsigned char * p,
+                      const unsigned char * const end)
+{
+  unsigned int tag;
+  unsigned int len;
+  unsigned int val;
+
+  tag = read_uleb128 (p, &len, end);
+  p += len;
+
+  switch (tag)
+    {
+    case Tag_ARC_PCS_config:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_PCS_config: ");
+      switch (val)
+       {
+       case 0:
+         printf (_("Absent/Non standard\n"));
+         break;
+       case 1:
+         printf (_("Bare metal/mwdt\n"));
+         break;
+       case 2:
+         printf (_("Bare metal/newlib\n"));
+         break;
+       case 3:
+         printf (_("Linux/uclibc\n"));
+         break;
+       case 4:
+         printf (_("Linux/glibc\n"));
+         break;
+       default:
+         printf (_("Unknown\n"));
+         break;
+       }
+      break;
+
+    case Tag_ARC_CPU_base:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_CPU_base: ");
+      switch (val)
+       {
+       default:
+       case TAG_CPU_NONE:
+         printf (_("Absent\n"));
+         break;
+       case TAG_CPU_ARC6xx:
+         printf ("ARC6xx\n");
+         break;
+       case TAG_CPU_ARC7xx:
+         printf ("ARC7xx\n");
+         break;
+       case TAG_CPU_ARCEM:
+         printf ("ARCEM\n");
+         break;
+       case TAG_CPU_ARCHS:
+         printf ("ARCHS\n");
+         break;
+       }
+      break;
+
+    case Tag_ARC_CPU_variation:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_CPU_variation: ");
+      switch (val)
+       {
+       default:
+         if (val > 0 && val < 16)
+             printf ("Core%d\n", val);
+         else
+             printf ("Unknown\n");
+         break;
+
+       case 0:
+         printf (_("Absent\n"));
+         break;
+       }
+      break;
+
+    case Tag_ARC_CPU_name:
+      printf ("  Tag_ARC_CPU_name: ");
+      p = display_tag_value (-1, p, end);
+      break;
+
+    case Tag_ARC_ABI_rf16:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ABI_rf16: %s\n", val ? _("yes") : _("no"));
+      break;
+
+    case Tag_ARC_ABI_osver:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ABI_osver: v%d\n", val);
+      break;
+
+    case Tag_ARC_ABI_pic:
+    case Tag_ARC_ABI_sda:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf (tag == Tag_ARC_ABI_sda ? "  Tag_ARC_ABI_sda: "
+             : "  Tag_ARC_ABI_pic: ");
+      switch (val)
+       {
+       case 0:
+         printf (_("Absent\n"));
+         break;
+       case 1:
+         printf ("MWDT\n");
+         break;
+       case 2:
+         printf ("GNU\n");
+         break;
+       default:
+         printf (_("Unknown\n"));
+         break;
+       }
+      break;
+
+    case Tag_ARC_ABI_tls:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ABI_tls: %s\n", val ? "r25": "none");
+      break;
+
+    case Tag_ARC_ABI_enumsize:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ABI_enumsize: %s\n", val ? _("default") :
+             _("smallest"));
+      break;
+
+    case Tag_ARC_ABI_exceptions:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ABI_exceptions: %s\n", val ? _("OPTFP")
+             : _("default"));
+      break;
+
+    case Tag_ARC_ABI_double_size:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ABI_double_size: %d\n", val);
+      break;
+
+    case Tag_ARC_ISA_config:
+      printf ("  Tag_ARC_ISA_config: ");
+      p = display_tag_value (-1, p, end);
+      break;
+
+    case Tag_ARC_ISA_apex:
+      printf ("  Tag_ARC_ISA_apex: ");
+      p = display_tag_value (-1, p, end);
+      break;
+
+    case Tag_ARC_ISA_mpy_option:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ISA_mpy_option: %d\n", val);
+      break;
+
+    default:
+      return display_tag_value (tag & 1, p, end);
+    }
+
+  return p;
+}
+
 /* ARM EABI attributes section.  */
 typedef struct
 {
@@ -14769,6 +15044,8 @@ print_mips_ases (unsigned int mask)
     fputs ("\n\tMICROMIPS ASE", stdout);
   if (mask & AFL_ASE_XPA)
     fputs ("\n\tXPA ASE", stdout);
+  if (mask & AFL_ASE_MIPS16E2)
+    fputs ("\n\tMIPS16e2 ASE", stdout);
   if (mask == 0)
     fprintf (stdout, "\n\t%s", _("None"));
   else if ((mask & ~AFL_ASE_MASK) != 0)
@@ -14935,8 +15212,93 @@ process_mips_specific (FILE * file)
 
   /* We have a lot of special sections.  Thanks SGI!  */
   if (dynamic_section == NULL)
-    /* No information available.  */
-    return res;
+    {
+      /* No dynamic information available.  See if there is static GOT.  */
+      sect = find_section (".got");
+      if (sect != NULL)
+       {
+         unsigned char *data_end;
+         unsigned char *data;
+         bfd_vma ent, end;
+         int addr_size;
+
+         pltgot = sect->sh_addr;
+
+         ent = pltgot;
+         addr_size = (is_32bit_elf ? 4 : 8);
+         end = pltgot + sect->sh_size;
+
+         data = (unsigned char *) get_data (NULL, file, sect->sh_offset,
+                                            end - pltgot, 1,
+                                            _("Global Offset Table data"));
+         /* PR 12855: Null data is handled gracefully throughout.  */
+         data_end = data + (end - pltgot);
+
+         printf (_("\nStatic GOT:\n"));
+         printf (_(" Canonical gp value: "));
+         print_vma (ent + 0x7ff0, LONG_HEX);
+         printf ("\n\n");
+
+         /* In a dynamic binary GOT[0] is reserved for the dynamic
+            loader to store the lazy resolver pointer, however in
+            a static binary it may well have been omitted and GOT
+            reduced to a table of addresses.
+            PR 21344: Check for the entry being fully available
+            before fetching it.  */
+         if (data
+             && data + ent - pltgot + addr_size <= data_end
+             && byte_get (data + ent - pltgot, addr_size) == 0)
+           {
+             printf (_(" Reserved entries:\n"));
+             printf (_("  %*s %10s %*s\n"),
+                     addr_size * 2, _("Address"), _("Access"),
+                     addr_size * 2, _("Value"));
+             ent = print_mips_got_entry (data, pltgot, ent, data_end);
+             printf ("\n");
+             if (ent == (bfd_vma) -1)
+               goto sgot_print_fail;
+
+             /* Check for the MSB of GOT[1] being set, identifying a
+                GNU object.  This entry will be used by some runtime
+                loaders, to store the module pointer.  Otherwise this
+                is an ordinary local entry.
+                PR 21344: Check for the entry being fully available
+                before fetching it.  */
+             if (data
+                 && data + ent - pltgot + addr_size <= data_end
+                 && (byte_get (data + ent - pltgot, addr_size)
+                     >> (addr_size * 8 - 1)) != 0)
+               {
+                 ent = print_mips_got_entry (data, pltgot, ent, data_end);
+                 printf ("\n");
+                 if (ent == (bfd_vma) -1)
+                   goto sgot_print_fail;
+               }
+             printf ("\n");
+           }
+
+         if (ent < end)
+           {
+             printf (_(" Local entries:\n"));
+             printf ("  %*s %10s %*s\n",
+                     addr_size * 2, _("Address"), _("Access"),
+                     addr_size * 2, _("Value"));
+             while (ent < end)
+               {
+                 ent = print_mips_got_entry (data, pltgot, ent, data_end);
+                 printf ("\n");
+                 if (ent == (bfd_vma) -1)
+                   goto sgot_print_fail;
+               }
+             printf ("\n");
+           }
+
+       sgot_print_fail:
+         if (data)
+           free (data);
+       }
+      return res;
+    }
 
   for (entry = dynamic_section;
        /* PR 17531 file: 012-50589-0.004.  */
@@ -15304,6 +15666,15 @@ process_mips_specific (FILE * file)
          return FALSE;
        }
 
+      /* PR 21345 - print a slightly more helpful error message
+        if we are sure that the cmalloc will fail.  */
+      if (conflictsno * sizeof (* iconf) > current_file_size)
+       {
+         error (_("Overlarge number of conflicts detected: %lx\n"),
+                (long) conflictsno);
+         return FALSE;
+       }
+
       iconf = (Elf32_Conflict *) cmalloc (conflictsno, sizeof (* iconf));
       if (iconf == NULL)
        {
@@ -15402,8 +15773,7 @@ process_mips_specific (FILE * file)
       data = (unsigned char *) get_data (NULL, file, offset,
                                          global_end - pltgot, 1,
                                         _("Global Offset Table data"));
-      if (data == NULL)
-       return FALSE;
+      /* PR 12855: Null data is handled gracefully throughout.  */
       data_end = data + (global_end - pltgot);
 
       printf (_("\nPrimary GOT:\n"));
@@ -15419,7 +15789,14 @@ process_mips_specific (FILE * file)
       printf (_(" Lazy resolver\n"));
       if (ent == (bfd_vma) -1)
        goto got_print_fail;
+
+      /* Check for the MSB of GOT[1] being set, denoting a GNU object.
+        This entry will be used by some runtime loaders, to store the
+        module pointer.  Otherwise this is an ordinary local entry.
+        PR 21344: Check for the entry being fully available before
+        fetching it.  */
       if (data
+         && data + ent - pltgot + addr_size <= data_end
          && (byte_get (data + ent - pltgot, addr_size)
              >> (addr_size * 8 - 1)) != 0)
        {
@@ -15926,11 +16303,11 @@ get_gnu_elf_note_type (unsigned e_type)
 }
 
 static void
-decode_x86_isa (unsigned long bitmask)
+decode_x86_isa (unsigned int bitmask)
 {
   while (bitmask)
     {
-      unsigned long bit = bitmask & (- bitmask);
+      unsigned int bit = bitmask & (- bitmask);
 
       bitmask &= ~ bit;
       switch (bit)
@@ -15953,7 +16330,48 @@ decode_x86_isa (unsigned long bitmask)
        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: %lx>"), bit); break;
+       default: printf (_("<unknown: %x>"), bit); break;
+       }
+      if (bitmask)
+       printf (", ");
+    }
+}
+
+static void
+decode_x86_feature (unsigned int type, unsigned int bitmask)
+{
+  while (bitmask)
+    {
+      unsigned int bit = bitmask & (- bitmask);
+
+      bitmask &= ~ bit;
+      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 ();
+           }
+         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 ();
+           }
+         break;
+       default:
+         printf (_("<unknown: %x>"), bit);
+         break;
        }
       if (bitmask)
        printf (", ");
@@ -15969,73 +16387,114 @@ print_gnu_property_note (Elf_Internal_Note * pnote)
 
   printf (_("      Properties: "));
 
-  if (pnote->descsz % size)
+  if (pnote->descsz < 8 || (pnote->descsz % size) != 0)
     {
       printf (_("<corrupt GNU_PROPERTY_TYPE, size = %#lx>\n"), pnote->descsz);
       return;
     }
 
-  while (ptr < (ptr_end - (size * 2)))
+  while (1)
     {
-      unsigned long j;
-      unsigned long type = byte_get (ptr, size);
-      unsigned long datasz = byte_get (ptr + size, size);
+      unsigned int j;
+      unsigned int type = byte_get (ptr, 4);
+      unsigned int datasz = byte_get (ptr + 4, 4);
 
-      ptr += 2 * size;
+      ptr += 8;
 
-      switch (type)
+      if ((ptr + datasz) > ptr_end)
        {
-       case GNU_PROPERTY_STACK_SIZE:
-         printf (_("stack size: "));
-         if (datasz != size || (ptr + size  > ptr_end))
-           printf (_("<corrupt length: %#lx> "), datasz);
-         else
-           printf ("%#lx", (unsigned long) byte_get (ptr, size));
+         printf (_("<corrupt type (%#x) datasz: %#x>\n"),
+                 type, datasz);
          break;
+       }
 
-       case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
-         printf ("no copy on protected ");
-         if (datasz)
-           printf (_("<corrupt length: %#lx> "), datasz);
-         break;
+      if (type >= GNU_PROPERTY_LOPROC && type <= GNU_PROPERTY_HIPROC)
+       {
+         if (elf_header.e_machine == EM_X86_64
+             || elf_header.e_machine == EM_IAMCU
+             || elf_header.e_machine == EM_386)
+           {
+             switch (type)
+               {
+               case GNU_PROPERTY_X86_ISA_1_USED:
+                 printf ("x86 ISA used: ");
+                 if (datasz != 4)
+                   printf (_("<corrupt length: %#x> "), datasz);
+                 else
+                   decode_x86_isa (byte_get (ptr, 4));
+                 goto next;
 
-       case GNU_PROPERTY_X86_ISA_1_USED:
-         printf ("x86 ISA used: ");
-         if (datasz != size  || (ptr + size > ptr_end))
-           printf (_("<corrupt length: %#lx> "), datasz);
-         else
-           decode_x86_isa (byte_get (ptr, size));
-         break;
+               case GNU_PROPERTY_X86_ISA_1_NEEDED:
+                 printf ("x86 ISA needed: ");
+                 if (datasz != 4)
+                   printf (_("<corrupt length: %#x> "), datasz);
+                 else
+                   decode_x86_isa (byte_get (ptr, 4));
+                 goto next;
 
-       case GNU_PROPERTY_X86_ISA_1_NEEDED:
-         printf ("x86 ISA needed: ");
-         if (datasz != size  || (ptr + size > ptr_end))
-           printf (_("<corrupt length: %#lx> "), datasz);
-         else
-           decode_x86_isa (byte_get (ptr, size));
-         break;
+               case GNU_PROPERTY_X86_FEATURE_1_AND:
+                 printf ("x86 feature: ");
+                 if (datasz != 4)
+                   printf (_("<corrupt length: %#x> "), datasz);
+                 else
+                   decode_x86_feature (type, byte_get (ptr, 4));
+                 goto next;
 
-       default:
-         printf (_("<unknown type %#lx data: "), type);
-         if (ptr + datasz > ptr_end)
+               default:
+                 break;
+               }
+           }
+       }
+      else
+       {
+         switch (type)
            {
-             printf (_("corrupt datasz: %#lx>\n"), datasz);
+           case GNU_PROPERTY_STACK_SIZE:
+             printf (_("stack size: "));
+             if (datasz != size)
+               printf (_("<corrupt length: %#x> "), datasz);
+             else
+               printf ("%#lx", (unsigned long) byte_get (ptr, size));
+             goto next;
+
+           case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
+             printf ("no copy on protected ");
+             if (datasz)
+               printf (_("<corrupt length: %#x> "), datasz);
+             goto next;
+
+           default:
              break;
            }
-         for (j = 0; j < datasz; ++j)
-           printf ("%02x ", ptr[j] & 0xff);
-         printf (">");
-         break;
        }
 
+      if (type < GNU_PROPERTY_LOPROC)
+       printf (_("<unknown type %#x data: "), type);
+      else if (type < GNU_PROPERTY_LOUSER)
+       printf (_("<procesor-specific type %#x data: "), type);
+      else
+       printf (_("<application-specific type %#x data: "), type);
+      for (j = 0; j < datasz; ++j)
+       printf ("%02x ", ptr[j] & 0xff);
+      printf (">");
+
+next:
       ptr += ((datasz + (size - 1)) & ~ (size - 1));
-      if (ptr < (ptr_end - (size * 2)))
+      if (ptr == ptr_end)
+       break;
+      else
        {
          if (do_wide)
            printf (", ");
          else
            printf ("\n\t");
        }
+
+      if (ptr > (ptr_end - 8))
+       {
+         printf (_("<corrupt descsz: %#lx>\n"), pnote->descsz);
+         break;
+       }
     }
 
   printf ("\n");
@@ -16533,123 +16992,179 @@ print_ia64_vms_note (Elf_Internal_Note * pnote)
   return TRUE;
 }
 
+/* Print the name of the symbol associated with a build attribute
+   that is attached to address OFFSET.  */
+
 static bfd_boolean
-print_gnu_build_attribute_description (Elf_Internal_Note * pnote,
-                                      FILE *              file,
-                                      Elf_Internal_Shdr * section ATTRIBUTE_UNUSED)
+print_symbol_for_build_attribute (FILE *         file,
+                                 unsigned long  offset,
+                                 bfd_boolean    is_open_attr)
 {
-  static unsigned long global_offset = 0;
-  unsigned long       i;
-  unsigned long       strtab_size = 0;
-  char *              strtab = NULL;
-  Elf_Internal_Sym *  symtab = NULL;
-  unsigned long       nsyms = 0;
-  Elf_Internal_Shdr * symsec = NULL;
-  unsigned int        desc_size = is_32bit_elf ? 4 : 8;
+  static FILE *             saved_file = NULL;
+  static char *             strtab;
+  static unsigned long      strtablen;
+  static Elf_Internal_Sym * symtab;
+  static unsigned long      nsyms;
+  Elf_Internal_Sym *        saved_sym = NULL;
+  Elf_Internal_Sym *        sym;
 
-  if (pnote->descsz  == 0)
+  if (section_headers != NULL
+      && (saved_file == NULL || file != saved_file))
     {
-      printf (_("    Applies from offset %#lx\n"), global_offset);
-      return TRUE;
-    }
-
-  if (pnote->descsz != desc_size)
-    {
-      error (_("    <invalid description size: %lx>\n"), pnote->descsz);
-      printf (_("    <invalid descsz>"));
-      return FALSE;
-    }
+      Elf_Internal_Shdr * symsec;
 
-  /* Load the symbols.  */
-  for (symsec = section_headers;
-       symsec < section_headers + elf_header.e_shnum;
-       symsec ++)
-    {
-      if (symsec->sh_type == SHT_SYMTAB)
+      /* Load the symbol and string sections.  */
+      for (symsec = section_headers;
+          symsec < section_headers + elf_header.e_shnum;
+          symsec ++)
        {
-         symtab = GET_ELF_SYMBOLS (file, symsec, & nsyms);
-
-         if (symsec->sh_link < elf_header.e_shnum)
+         if (symsec->sh_type == SHT_SYMTAB)
            {
-             Elf_Internal_Shdr * strtab_sec = section_headers + symsec->sh_link;
+             symtab = GET_ELF_SYMBOLS (file, symsec, & nsyms);
 
-             strtab = (char *) get_data (NULL, file, strtab_sec->sh_offset,
-                                         1, strtab_sec->sh_size,
-                                         _("string table"));
-             strtab_size = strtab != NULL ? strtab_sec->sh_size : 0;
+             if (symsec->sh_link < elf_header.e_shnum)
+               {
+                 Elf_Internal_Shdr * strtab_sec = section_headers + symsec->sh_link;
+
+                 strtab = (char *) get_data (NULL, file, strtab_sec->sh_offset,
+                                             1, strtab_sec->sh_size,
+                                             _("string table"));
+                 strtablen = strtab != NULL ? strtab_sec->sh_size : 0;
+               }
            }
        }
+      saved_file = file;
     }
 
-  printf (_("    Applies from offset"));
-
-  for (i = 0; i < pnote->descsz; i += desc_size)
+  if (symtab == NULL || strtab == NULL)
     {
-      Elf_Internal_Sym * saved_sym = NULL;
-      Elf_Internal_Sym * sym;
-      unsigned long offset;
+      printf ("\n");
+      return FALSE;
+    }
 
-      offset = byte_get ((unsigned char *) pnote->descdata + i, desc_size);
+  /* Find a symbol whose value matches offset.  */
+  for (sym = symtab; sym < symtab + nsyms; sym ++)
+    if (sym->st_value == offset)
+      {
+       if (sym->st_name >= strtablen)
+         /* Huh ?  This should not happen.  */
+         continue;
 
-      if (i + desc_size == pnote->descsz)
-       printf (_(" %#lx"), offset);
-      else
-       printf (_(" %#lx, "), offset);
+       if (strtab[sym->st_name] == 0)
+         continue;
 
-      if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN)
-       global_offset = offset;
+       if (is_open_attr)
+         {
+           /* For OPEN attributes we prefer GLOBAL over LOCAL symbols
+              and FILE or OBJECT symbols over NOTYPE symbols.  We skip
+              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;
 
-      if (symtab == NULL || strtab == NULL)
-       continue;
+             case STT_OBJECT:
+               saved_sym = sym;
+               continue;
 
-      /* Find a symbol whose value matches offset.  */
-      for (sym = symtab; sym < symtab + nsyms; sym ++)
-       if (sym->st_value == offset)
-         {
-           if (sym->st_name < strtab_size)
+             case STT_FUNC:
+               /* Ignore function symbols.  */
+               continue;
+
+             default:
+               break;
+             }
+
+           switch (ELF_ST_BIND (sym->st_info))
              {
-               if (strtab[sym->st_name] == 0)
-                 continue;
+             case STB_GLOBAL:
+               if (saved_sym == NULL
+                   || ELF_ST_TYPE (saved_sym->st_info) != STT_OBJECT)
+                 saved_sym = sym;
+               break;
 
-               if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN)
-                 {
-                   /* For OPEN attributes we prefer GLOBAL symbols, if there
-                      is one that matches.  But keep a record of a matching
-                      LOCAL symbol, just in case that is all that we can find.  */
-                   if (ELF_ST_BIND (sym->st_info) == STB_LOCAL)
-                     {
-                       saved_sym = sym;
-                       continue;
-                     }
-                   printf (_(" (file: %s)"), strtab + sym->st_name);
-                 }
-               else if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
-                 continue;
-               else
-                 printf (_(" (function: %s)"), strtab + sym->st_name);
+             case STB_LOCAL:
+               if (saved_sym == NULL)
+                 saved_sym = sym;
+               break;
+
+             default:
                break;
              }
          }
+       else
+         {
+           if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
+             continue;
+
+           saved_sym = sym;
+           break;
+         }
+      }
 
-      if (sym == symtab + nsyms)
+  printf (" (%s: %s)\n",
+         is_open_attr ? _("file") : _("func"),
+         saved_sym ? strtab + saved_sym->st_name : _("<no symbol found>)"));
+  return TRUE;
+}
+
+static bfd_boolean
+print_gnu_build_attribute_description (Elf_Internal_Note * pnote,
+                                      FILE *              file)
+{
+  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;
+
+  if (pnote->descsz == 0)
+    {
+      if (is_open_attr)
        {
-         if (saved_sym)
-           printf (_(" (file: %s)"), strtab + saved_sym->st_name);
-         else
-           printf (_(" (<symbol name unknown>)"));
+         printf (_("    Applies from offset %#lx\n"), global_offset);
+         return TRUE;
+       }
+      else
+       {
+         printf (_("    Applies to func at %#lx"), global_offset);
+         return print_symbol_for_build_attribute (file, global_offset, is_open_attr);
        }
     }
 
-  printf ("\n");
-  return TRUE;
+  if (pnote->descsz != desc_size)
+    {
+      error (_("    <invalid description size: %lx>\n"), pnote->descsz);
+      printf (_("    <invalid descsz>"));
+      return FALSE;
+    }
+
+  offset = byte_get ((unsigned char *) pnote->descdata, desc_size);
+
+  if (is_open_attr)
+    {
+      printf (_("    Applies from offset %#lx"), offset);
+      global_offset = offset;
+    }
+  else
+    {
+      printf (_("    Applies to func at %#lx"), offset);
+    }
+
+  return print_symbol_for_build_attribute (file, offset, is_open_attr);
 }
 
 static bfd_boolean
 print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
 {
+  static const char string_expected [2] = { GNU_BUILD_ATTRIBUTE_TYPE_STRING, 0 };
+  static const char number_expected [2] = { GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC, 0 };
+  static const char bool_expected [3] = { GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE, GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE, 0 };
   char         name_type;
   char         name_attribute;
-  char *       expected_types;
+  const char * expected_types;
   const char * name = pnote->namedata;
   const char * text;
   int          left;
@@ -16657,7 +17172,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
   if (name == NULL || pnote->namesz < 2)
     {
       error (_("corrupt name field in GNU build attribute note: size = %ld\n"), pnote->namesz);
-      print_symbol (-20, _("  <corrupt name field>"));
+      print_symbol (-20, _("  <corrupt name>"));
       return FALSE;
     }
 
@@ -16683,27 +17198,27 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
     {
     case GNU_BUILD_ATTRIBUTE_VERSION:
       text = _("<version>");
-      expected_types = "$";
+      expected_types = string_expected;
       ++ name;
       break;
     case GNU_BUILD_ATTRIBUTE_STACK_PROT:
       text = _("<stack prot>");
-      expected_types = "!+";
+      expected_types = "!+*";
       ++ name;
       break;
     case GNU_BUILD_ATTRIBUTE_RELRO:
       text = _("<relro>");
-      expected_types = "!+";
+      expected_types = bool_expected;
       ++ name;
       break;
     case GNU_BUILD_ATTRIBUTE_STACK_SIZE:
       text = _("<stack size>");
-      expected_types = "*";
+      expected_types = number_expected;
       ++ name;
       break;
     case GNU_BUILD_ATTRIBUTE_TOOL:
       text = _("<tool>");
-      expected_types = "$";
+      expected_types = string_expected;
       ++ name;
       break;
     case GNU_BUILD_ATTRIBUTE_ABI:
@@ -16713,10 +17228,14 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
       break;
     case GNU_BUILD_ATTRIBUTE_PIC:
       text = _("<PIC>");
-      expected_types = "*";
+      expected_types = number_expected;
+      ++ name;
+      break;
+    case GNU_BUILD_ATTRIBUTE_SHORT_ENUM:
+      text = _("<short enum>");
+      expected_types = bool_expected;
       ++ name;
       break;
-
     default:
       if (ISPRINT (* name))
        {
@@ -16724,15 +17243,17 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
 
          if (len > left && ! do_wide)
            len = left;
-         printf ("%.*s ", len, name);
+         printf ("%.*s:", len, name);
          left -= len;
-         name += len + 1;
+         name += len;
        }
       else
        {
-         error (_("unexpected character in name field\n"));
-         print_symbol (- left, _("<unknown attribute>"));
-         return 0;
+         static char tmpbuf [128];
+         error (_("unrecognised byte in name field: %d\n"), * name);
+         sprintf (tmpbuf, _("<unknown:_%d>"), * name);
+         text = tmpbuf;
+         name ++;
        }
       expected_types = "*$!+";
       break;
@@ -16745,7 +17266,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
     }
 
   if (strchr (expected_types, name_type) == NULL)
-    warn (_("attribute does not have the expected type\n"));
+    warn (_("attribute does not have an expected type (%c)\n"), name_type);
 
   if ((unsigned long)(name - pnote->namedata) > pnote->namesz)
     {
@@ -16762,43 +17283,83 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
     {
     case GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC:
       {
-       unsigned int bytes = pnote->namesz - (name - pnote->namedata);
-       unsigned long val = 0;
-       unsigned int shift = 0;
+       unsigned int        bytes;
+       unsigned long long  val = 0;
+       unsigned int        shift = 0;
+       char *              decoded = NULL;
+
+       bytes = pnote->namesz - (name - pnote->namedata);
+       if (bytes > 0)
+         /* The -1 is because the name field is always 0 terminated, and we
+            want to be able to ensure that the shift in the while loop below
+            will not overflow.  */
+         -- bytes;
+
+       if (bytes > sizeof (val))
+         {
+           fprintf (stderr, "namesz %lx name %p namedata %p\n",
+                    pnote->namesz, name, pnote->namedata);
+           error (_("corrupt numeric name field: too many bytes in the value: %x\n"),
+                  bytes);
+           bytes = sizeof (val);
+         }
+       /* We do not bother to warn if bytes == 0 as this can
+          happen with some early versions of the gcc plugin.  */
 
        while (bytes --)
          {
-           val |= ((* name ++) << shift);
+           unsigned long byte = (* name ++) & 0xff;
+
+           val |= byte << shift;
            shift += 8;
          }
 
-       if (name_attribute == GNU_BUILD_ATTRIBUTE_PIC)
+       switch (name_attribute)
          {
-           char * pic_type = NULL;
-
+         case GNU_BUILD_ATTRIBUTE_PIC:
            switch (val)
              {
-             case 0: pic_type = "static"; break;
-             case 1: pic_type = "pic"; break;
-             case 2: pic_type = "PIC"; break;
-             case 3: pic_type = "pie"; break;
-             case 4: pic_type = "PIE"; break;
+             case 0: decoded = "static"; break;
+             case 1: decoded = "pic"; break;
+             case 2: decoded = "PIC"; break;
+             case 3: decoded = "pie"; break;
+             case 4: decoded = "PIE"; break;
+             default: break;
              }
-
-           if (pic_type != NULL)
+           break;
+         case GNU_BUILD_ATTRIBUTE_STACK_PROT:
+           switch (val)
              {
-               if (do_wide)
-                 left -= printf ("%s", pic_type);
-               else
-                 left -= printf ("%-.*s", left, pic_type);
-               break;
+               /* Based upon the SPCT_FLAG_xxx enum values in gcc/cfgexpand.c.  */
+             case 0: decoded = "off"; break;
+             case 1: decoded = "on"; break;
+             case 2: decoded = "all"; break;
+             case 3: decoded = "strong"; break;
+             case 4: decoded = "explicit"; break;
+             default: break;
              }
+           break;
+         default:
+           break;
          }
 
-       if (do_wide)
-         left -= printf ("0x%lx", val);
+       if (decoded != NULL)
+         {
+           print_symbol (-left, decoded);
+           left = 0;
+         }
+       else if (val == 0)
+         {
+           printf ("0x0");
+           left -= 3;
+         }
        else
-         left -= printf ("0x%-.*lx", left, val);
+         {
+           if (do_wide)
+             left -= printf ("0x%llx", val);
+           else
+             left -= printf ("0x%-.*llx", left, val);
+         }
       }
       break;
     case GNU_BUILD_ATTRIBUTE_TYPE_STRING:
@@ -16826,8 +17387,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
 
 static bfd_boolean
 process_note (Elf_Internal_Note *  pnote,
-             FILE *               file,
-             Elf_Internal_Shdr *  section)
+             FILE *               file)
 {
   const char * name = pnote->namesz ? pnote->namedata : "(NONE)";
   const char * nt;
@@ -16895,7 +17455,7 @@ process_note (Elf_Internal_Note *  pnote,
     return print_core_note (pnote);
   else if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN
           || pnote->type == NT_GNU_BUILD_ATTRIBUTE_FUNC)
-    return print_gnu_build_attribute_description (pnote, file, section);
+    return print_gnu_build_attribute_description (pnote, file);
 
   if (pnote->descsz)
     {
@@ -17042,14 +17602,14 @@ process_notes_at (FILE *              file,
              break;
            }
 
-         strncpy (temp, inote.namedata, inote.namesz);
+         memcpy (temp, inote.namedata, inote.namesz);
          temp[inote.namesz] = 0;
 
          /* warn (_("'%s' NOTE name not properly null terminated\n"), temp);  */
          inote.namedata = temp;
        }
 
-      if (! process_note (& inote, file, section))
+      if (! process_note (& inote, file))
        res = FALSE;
 
       if (temp != NULL)
@@ -17259,6 +17819,12 @@ process_arch_specific (FILE * file)
 
   switch (elf_header.e_machine)
     {
+    case EM_ARC:
+    case EM_ARC_COMPACT:
+    case EM_ARC_COMPACT2:
+      return process_attributes (file, "ARC", SHT_ARC_ATTRIBUTES,
+                                display_arc_attribute,
+                                display_generic_attribute);
     case EM_ARM:
       return process_attributes (file, "aeabi", SHT_ARM_ATTRIBUTES,
                                 display_arm_attribute,
@@ -17269,7 +17835,7 @@ process_arch_specific (FILE * file)
       return process_mips_specific (file);
 
     case EM_MSP430:
-      return process_attributes (file, "mspabi", SHT_MSP430_ATTRIBUTES,
+     return process_attributes (file, "mspabi", SHT_MSP430_ATTRIBUTES,
                                 display_msp430x_attribute,
                                 display_generic_attribute);