Add .note.gnu.property runtime verification and merge support
[external/binutils.git] / binutils / readelf.c
index 7391334..9212a8f 100644 (file)
@@ -60,6 +60,7 @@
 #include "bucomm.h"
 #include "elfcomm.h"
 #include "dwarf.h"
+#include "libbfd.h"
 
 #include "elf/common.h"
 #include "elf/external.h"
@@ -287,7 +288,7 @@ enum versioned_symbol_info
   symbol_public
 };
 
-static const char *get_symbol_version_string
+static const char * get_symbol_version_string
   (FILE *file, int is_dynsym, const char *strtab,
    unsigned long int strtab_size, unsigned int si,
    Elf_Internal_Sym *psym, enum versioned_symbol_info *sym_info,
@@ -346,8 +347,9 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size,
          || (bfd_size_type) ((size_t) nmemb) != nmemb))
     {
       if (reason)
-       error (_("Size truncation prevents reading 0x%llx elements of size 0x%llx for %s\n"),
-              (unsigned long long) nmemb, (unsigned long long) size, reason);
+       error (_("Size truncation prevents reading 0x%" BFD_VMA_FMT "x"
+                " elements of size 0x%" BFD_VMA_FMT "x for %s\n"),
+              nmemb, size, reason);
       return NULL;
     }
 
@@ -355,8 +357,9 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size,
   if (amt < nmemb)
     {
       if (reason)
-       error (_("Size overflow prevents reading 0x%llx elements of size 0x%llx for %s\n"),
-              (unsigned long long) nmemb, (unsigned long long) size, reason);
+       error (_("Size overflow prevents reading 0x%" BFD_VMA_FMT "x"
+                " elements of size 0x%" BFD_VMA_FMT "x for %s\n"),
+              nmemb, size, reason);
       return NULL;
     }
 
@@ -366,8 +369,9 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size,
       || offset + archive_file_offset + amt > current_file_size)
     {
       if (reason)
-       error (_("Reading 0x%llx bytes extends past end of file for %s\n"),
-              (unsigned long long) amt, reason);
+       error (_("Reading 0x%" BFD_VMA_FMT "x"
+                " bytes extends past end of file for %s\n"),
+              amt, reason);
       return NULL;
     }
 
@@ -375,7 +379,7 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size,
     {
       if (reason)
        error (_("Unable to seek to 0x%lx for %s\n"),
-              (unsigned long) archive_file_offset + offset, reason);
+              archive_file_offset + offset, reason);
       return NULL;
     }
 
@@ -390,8 +394,9 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size,
       if (mvar == NULL)
        {
          if (reason)
-           error (_("Out of memory allocating 0x%llx bytes for %s\n"),
-                  (unsigned long long) amt, reason);
+           error (_("Out of memory allocating 0x%" BFD_VMA_FMT "x"
+                    " bytes for %s\n"),
+                  amt, reason);
          return NULL;
        }
 
@@ -401,8 +406,8 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size,
   if (fread (mvar, (size_t) size, (size_t) nmemb, file) != nmemb)
     {
       if (reason)
-       error (_("Unable to read in 0x%llx bytes of %s\n"),
-              (unsigned long long) amt, reason);
+       error (_("Unable to read in 0x%" BFD_VMA_FMT "x bytes of %s\n"),
+              amt, reason);
       if (mvar != var)
        free (mvar);
       return NULL;
@@ -475,7 +480,7 @@ print_symbol (int width, const char *symbol)
 
   if (width < 0)
     {
-      /* Keep the width positive.  This also helps.  */
+      /* Keep the width positive.  This helps the code below.  */
       width = - width;
       extra_padding = TRUE;
     }
@@ -552,7 +557,7 @@ print_symbol (int width, const char *symbol)
   return num_printed;
 }
 
-/* Returns a pointer to a static buffer containing a  printable version of
+/* Returns a pointer to a static buffer containing a printable version of
    the given section's name.  Like print_symbol, except that it does not try
    to print multibyte characters, it just interprets them as hex values.  */
 
@@ -1847,6 +1852,34 @@ get_ia64_dynamic_type (unsigned long type)
 }
 
 static const char *
+get_solaris_section_type (unsigned long type)
+{
+  switch (type)
+    {
+    case 0x6fffffee: return "SUNW_ancillary";
+    case 0x6fffffef: return "SUNW_capchain";
+    case 0x6ffffff0: return "SUNW_capinfo";
+    case 0x6ffffff1: return "SUNW_symsort";
+    case 0x6ffffff2: return "SUNW_tlssort";
+    case 0x6ffffff3: return "SUNW_LDYNSYM";
+    case 0x6ffffff4: return "SUNW_dof";
+    case 0x6ffffff5: return "SUNW_cap";
+    case 0x6ffffff6: return "SUNW_SIGNATURE";
+    case 0x6ffffff7: return "SUNW_ANNOTATE";
+    case 0x6ffffff8: return "SUNW_DEBUGSTR";
+    case 0x6ffffff9: return "SUNW_DEBUG";
+    case 0x6ffffffa: return "SUNW_move";
+    case 0x6ffffffb: return "SUNW_COMDAT";
+    case 0x6ffffffc: return "SUNW_syminfo";
+    case 0x6ffffffd: return "SUNW_verdef";
+    case 0x6ffffffe: return "SUNW_verneed";
+    case 0x6fffffff: return "SUNW_versym";
+    case 0x70000000: return "SPARC_GOTDATA";
+    default: return NULL;
+    }
+}
+
+static const char *
 get_alpha_dynamic_type (unsigned long type)
 {
   switch (type)
@@ -1901,6 +1934,43 @@ get_nios2_dynamic_type (unsigned long type)
 }
 
 static const char *
+get_solaris_dynamic_type (unsigned long type)
+{
+  switch (type)
+    {
+    case 0x6000000d: return "SUNW_AUXILIARY";
+    case 0x6000000e: return "SUNW_RTLDINF";
+    case 0x6000000f: return "SUNW_FILTER";
+    case 0x60000010: return "SUNW_CAP";
+    case 0x60000011: return "SUNW_SYMTAB";
+    case 0x60000012: return "SUNW_SYMSZ";
+    case 0x60000013: return "SUNW_SORTENT";
+    case 0x60000014: return "SUNW_SYMSORT";
+    case 0x60000015: return "SUNW_SYMSORTSZ";
+    case 0x60000016: return "SUNW_TLSSORT";
+    case 0x60000017: return "SUNW_TLSSORTSZ";
+    case 0x60000018: return "SUNW_CAPINFO";
+    case 0x60000019: return "SUNW_STRPAD";
+    case 0x6000001a: return "SUNW_CAPCHAIN";
+    case 0x6000001b: return "SUNW_LDMACH";
+    case 0x6000001d: return "SUNW_CAPCHAINENT";
+    case 0x6000001f: return "SUNW_CAPCHAINSZ";
+    case 0x60000021: return "SUNW_PARENT";
+    case 0x60000023: return "SUNW_ASLR";
+    case 0x60000025: return "SUNW_RELAX";
+    case 0x60000029: return "SUNW_NXHEAP";
+    case 0x6000002b: return "SUNW_NXSTACK";
+
+    case 0x70000001: return "SPARC_REGISTER";
+    case 0x7ffffffd: return "AUXILIARY";
+    case 0x7ffffffe: return "USED";
+    case 0x7fffffff: return "FILTER";
+
+    default: return NULL;      
+    }
+}
+
+static const char *
 get_dynamic_type (unsigned long type)
 {
   static char buff[64];
@@ -2018,7 +2088,10 @@ get_dynamic_type (unsigned long type)
              result = get_nios2_dynamic_type (type);
              break;
            default:
-             result = NULL;
+             if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
+               result = get_solaris_dynamic_type (type);
+             else
+               result = NULL;
              break;
            }
 
@@ -2042,7 +2115,10 @@ get_dynamic_type (unsigned long type)
              result = get_ia64_dynamic_type (type);
              break;
            default:
-             result = NULL;
+             if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
+               result = get_solaris_dynamic_type (type);
+             else
+               result = NULL;
              break;
            }
 
@@ -2271,6 +2347,73 @@ get_machine_name (unsigned e_machine)
 }
 
 static void
+decode_ARC_machine_flags (unsigned e_flags, unsigned e_machine, char buf[])
+{
+  /* ARC has two machine types EM_ARC_COMPACT and EM_ARC_COMPACT2.  Some
+     other compilers don't a specific architecture type in the e_flags, and
+     instead use EM_ARC_COMPACT for old ARC600, ARC601, and ARC700
+     architectures, and switch to EM_ARC_COMPACT2 for newer ARCEM and ARCHS
+     architectures.
+
+     Th GNU tools follows this use of EM_ARC_COMPACT and EM_ARC_COMPACT2,
+     but also sets a specific architecture type in the e_flags field.
+
+     However, when decoding the flags we don't worry if we see an
+     unexpected pairing, for example EM_ARC_COMPACT machine type, with
+     ARCEM architecture type.  */
+
+  switch (e_flags & EF_ARC_MACH_MSK)
+    {
+      /* We only expect these to occur for EM_ARC_COMPACT2.  */
+    case EF_ARC_CPU_ARCV2EM:
+      strcat (buf, ", ARC EM");
+      break;
+    case EF_ARC_CPU_ARCV2HS:
+      strcat (buf, ", ARC HS");
+      break;
+
+      /* We only expect these to occur for EM_ARC_COMPACT.  */
+    case E_ARC_MACH_ARC600:
+      strcat (buf, ", ARC600");
+      break;
+    case E_ARC_MACH_ARC601:
+      strcat (buf, ", ARC601");
+      break;
+    case E_ARC_MACH_ARC700:
+      strcat (buf, ", ARC700");
+      break;
+
+      /* The only times we should end up here are (a) A corrupt ELF, (b) A
+         new ELF with new architecture being read by an old version of
+         readelf, or (c) An ELF built with non-GNU compiler that does not
+         set the architecture in the e_flags.  */
+    default:
+      if (e_machine == EM_ARC_COMPACT)
+        strcat (buf, ", Unknown ARCompact");
+      else
+        strcat (buf, ", Unknown ARC");
+      break;
+    }
+
+  switch (e_flags & EF_ARC_OSABI_MSK)
+    {
+    case E_ARC_OSABI_ORIG:
+      strcat (buf, ", (ABI:legacy)");
+      break;
+    case E_ARC_OSABI_V2:
+      strcat (buf, ", (ABI:v2)");
+      break;
+      /* Only upstream 3.9+ kernels will support ARCv2 ISA.  */
+    case E_ARC_OSABI_V3:
+      strcat (buf, ", v3 no-legacy-syscalls ABI");
+      break;
+    default:
+      strcat (buf, ", unrecognised ARC OSABI flag");
+      break;
+    }
+}
+
+static void
 decode_ARM_machine_flags (unsigned e_flags, char buf[])
 {
   unsigned eabi;
@@ -2768,81 +2911,9 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
          break;
 
        case EM_ARC_COMPACT2:
-         switch (e_flags & EF_ARC_MACH_MSK)
-           {
-           case EF_ARC_CPU_ARCV2EM:
-             strcat (buf, ", ARC EM");
-             break;
-           case EF_ARC_CPU_ARCV2HS:
-             strcat (buf, ", ARC HS");
-             break;
-           case EF_ARC_CPU_GENERIC:
-             strcat (buf, ", ARC generic");
-             break;
-           case E_ARC_MACH_ARC600:
-             strcat (buf, ", ARC600");
-             break;
-           case E_ARC_MACH_ARC601:
-             strcat (buf, ", ARC601");
-             break;
-           case E_ARC_MACH_ARC700:
-             strcat (buf, ", ARC700");
-             break;
-           default:
-             strcat (buf, ", unrecognized cpu flag for ARCv2");
-             break;
-           }
-         switch (e_flags & EF_ARC_OSABI_MSK)
-           {
-           case E_ARC_OSABI_ORIG:
-             strcat (buf, ", (ABI:legacy)");
-             break;
-           case E_ARC_OSABI_V2:
-             strcat (buf, ", (ABI:v2)");
-             break;
-             /* Only upstream 3.9+ kernels will support ARCv2 ISA.  */
-           case E_ARC_OSABI_V3:
-             strcat (buf, ", v3 no-legacy-syscalls ABI");
-             break;
-           default:
-             strcat (buf, ", unrecognised ARC OSABI flag");
-             break;
-           }
-         break;
-
        case EM_ARC_COMPACT:
-         switch (e_flags & EF_ARC_MACH_MSK)
-           {
-           case E_ARC_MACH_ARC600:
-             strcat (buf, ", ARC 600");
-             break;
-           case E_ARC_MACH_ARC601:
-             strcat (buf, ", ARC 601");
-             break;
-           case E_ARC_MACH_ARC700:
-             strcat (buf, ", ARC 700");
-             break;
-           default:
-             strcat (buf, ", Generic ARCompact");
-             break;
-           }
-         switch (e_flags & EF_ARC_OSABI_MSK)
-           {
-           case E_ARC_OSABI_ORIG:
-             strcat (buf, ", legacy syscall ABI");
-             break;
-           case E_ARC_OSABI_V2:
-             /* For 3.2+ Linux kernels which use asm-generic
-                hdrs.  */
-             strcat (buf, ", v2 syscall ABI");
-             break;
-           case E_ARC_OSABI_V3:
-             /* Upstream 3.9+ kernels which don't use any legacy
-                syscalls.  */
-             strcat (buf, ", v3 no-legacy-syscalls ABI");
-             break;
-           }
-         break;
+          decode_ARC_machine_flags (e_flags, e_machine, buf);
+          break;
 
        case EM_ARM:
          decode_ARM_machine_flags (e_flags, buf);
@@ -3616,6 +3687,23 @@ get_tic6x_segment_type (unsigned long type)
 }
 
 static const char *
+get_solaris_segment_type (unsigned long type)
+{
+  switch (type)
+    {
+    case 0x6464e550: return "PT_SUNW_UNWIND";
+    case 0x6474e550: return "PT_SUNW_EH_FRAME";
+    case 0x6ffffff7: return "PT_LOSUNW";
+    case 0x6ffffffa: return "PT_SUNWBSS";
+    case 0x6ffffffb: return "PT_SUNWSTACK";
+    case 0x6ffffffc: return "PT_SUNWDTRACE";
+    case 0x6ffffffd: return "PT_SUNWCAP";
+    case 0x6fffffff: return "PT_HISUNW";
+    default: return NULL;
+    }
+}
+
+static const char *
 get_segment_type (unsigned long p_type)
 {
   static char buff[32];
@@ -3685,7 +3773,10 @@ get_segment_type (unsigned long p_type)
              result = get_ia64_segment_type (p_type);
              break;
            default:
-             result = NULL;
+             if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
+               result = get_solaris_segment_type (p_type);
+             else
+               result = NULL;
              break;
            }
 
@@ -3893,6 +3984,7 @@ static const char *
 get_section_type_name (unsigned int sh_type)
 {
   static char buff[32];
+  const char * result;
 
   switch (sh_type)
     {
@@ -3926,8 +4018,6 @@ get_section_type_name (unsigned int sh_type)
     default:
       if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC))
        {
-         const char * result;
-
          switch (elf_header.e_machine)
            {
            case EM_MIPS:
@@ -3970,26 +4060,27 @@ get_section_type_name (unsigned int sh_type)
          if (result != NULL)
            return result;
 
-         sprintf (buff, "LOPROC+%x", sh_type - SHT_LOPROC);
+         sprintf (buff, "LOPROC+%#x", sh_type - SHT_LOPROC);
        }
       else if ((sh_type >= SHT_LOOS) && (sh_type <= SHT_HIOS))
        {
-         const char * result;
-
          switch (elf_header.e_machine)
            {
            case EM_IA_64:
              result = get_ia64_section_type_name (sh_type);
              break;
            default:
-             result = NULL;
+             if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
+               result = get_solaris_section_type (sh_type);
+             else
+               result = NULL;
              break;
            }
 
          if (result != NULL)
            return result;
 
-         sprintf (buff, "LOOS+%x", sh_type - SHT_LOOS);
+         sprintf (buff, "LOOS+%#x", sh_type - SHT_LOOS);
        }
       else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
        {
@@ -3998,12 +4089,17 @@ get_section_type_name (unsigned int sh_type)
            case EM_V800:
            case EM_V850:
            case EM_CYGNUS_V850:
-             return get_v850_section_type_name (sh_type);
+             result = get_v850_section_type_name (sh_type);
+             break;
            default:
+             result = NULL;
              break;
            }
 
-         sprintf (buff, "LOUSER+%x", sh_type - SHT_LOUSER);
+         if (result != NULL)
+           return result;
+
+         sprintf (buff, "LOUSER+%#x", sh_type - SHT_LOUSER);
        }
       else
        /* This message is probably going to be displayed in a 15
@@ -4961,6 +5057,10 @@ get_32bit_section_headers (FILE * file, bfd_boolean probe)
       internal->sh_info      = BYTE_GET (shdrs[i].sh_info);
       internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
       internal->sh_entsize   = BYTE_GET (shdrs[i].sh_entsize);
+      if (!probe && internal->sh_link > num)
+       warn (_("Section %u has an out of range sh_link value of %u\n"), i, internal->sh_link);
+      if (!probe && internal->sh_flags & SHF_INFO_LINK && internal->sh_info > num)
+       warn (_("Section %u has an out of range sh_info value of %u\n"), i, internal->sh_info);
     }
 
   free (shdrs);
@@ -5019,6 +5119,10 @@ get_64bit_section_headers (FILE * file, bfd_boolean probe)
       internal->sh_info      = BYTE_GET (shdrs[i].sh_info);
       internal->sh_offset    = BYTE_GET (shdrs[i].sh_offset);
       internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
+      if (!probe && internal->sh_link > num)
+       warn (_("Section %u has an out of range sh_link value of %u\n"), i, internal->sh_link);
+      if (!probe && internal->sh_flags & SHF_INFO_LINK && internal->sh_info > num)
+       warn (_("Section %u has an out of range sh_info value of %u\n"), i, internal->sh_info);
     }
 
   free (shdrs);
@@ -5430,6 +5534,9 @@ get_elf_section_flags (bfd_vma sh_flags)
                   || elf_header.e_machine == EM_K1OM)
                  && flag == SHF_X86_64_LARGE)
                *p = 'l';
+             else if (elf_header.e_machine == EM_ARM
+                      && flag == SHF_ARM_NOREAD)
+                 *p = 'y';
              else if (flag & SHF_MASKOS)
                {
                  *p = 'o';
@@ -5814,6 +5921,13 @@ process_section_headers (FILE * file)
        i < elf_header.e_shnum;
        i++, section++)
     {
+      /* 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));
@@ -6000,18 +6114,20 @@ process_section_headers (FILE * file)
 
   if (!do_section_details)
     {
+      /* The ordering of the letters shown here matches the ordering of the
+        corresponding SHF_xxx values, and hence the order in which these
+        letters will be displayed to the user.  */
+      printf (_("Key to Flags:\n\
+  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),\n\
+  L (link order), O (extra OS processing required), G (group), T (TLS),\n\
+  C (compressed), x (unknown), o (OS specific), E (exclude),\n  "));
       if (elf_header.e_machine == EM_X86_64
          || elf_header.e_machine == EM_L1OM
          || elf_header.e_machine == EM_K1OM)
-       printf (_("Key to Flags:\n\
-  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)\n\
-  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)\n\
-  O (extra OS processing required) o (OS specific), p (processor specific)\n"));
-      else
-       printf (_("Key to Flags:\n\
-  W (write), A (alloc), X (execute), M (merge), S (strings)\n\
-  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)\n\
-  O (extra OS processing required) o (OS specific), p (processor specific)\n"));
+       printf (_("l (large), "));
+      else if (elf_header.e_machine == EM_ARM)
+       printf (_("y (noread), "));
+      printf ("p (processor specific)\n");
     }
 
   return 1;
@@ -6020,7 +6136,7 @@ process_section_headers (FILE * file)
 static const char *
 get_group_flags (unsigned int flags)
 {
-  static char buff[32];
+  static char buff[128];
   switch (flags)
     {
     case 0:
@@ -7630,9 +7746,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;
 
@@ -8603,7 +8719,7 @@ dynamic_section_mips_val (Elf_Internal_Dyn * entry)
 
     case DT_MIPS_TIME_STAMP:
       {
-       char timebuf[20];
+       char timebuf[128];
        struct tm * tmp;
        time_t atime = entry->d_un.d_val;
 
@@ -8632,7 +8748,7 @@ dynamic_section_mips_val (Elf_Internal_Dyn * entry)
     case DT_MIPS_DELTA_SYM_NO:
     case DT_MIPS_DELTA_CLASSSYM_NO:
     case DT_MIPS_COMPACT_SIZE:
-      print_vma (entry->d_un.d_ptr, DEC);
+      print_vma (entry->d_un.d_val, DEC);
       break;
 
     default:
@@ -10200,6 +10316,18 @@ get_symbol_visibility (unsigned int visibility)
 }
 
 static const char *
+get_solaris_symbol_visibility (unsigned int visibility)
+{
+  switch (visibility)
+    {
+    case 4: return "EXPORTED";
+    case 5: return "SINGLETON";
+    case 6: return "ELIMINATE";
+    default: return get_symbol_visibility (visibility);
+    }
+}
+
+static const char *
 get_mips_symbol_other (unsigned int other)
 {
   switch (other)
@@ -10322,6 +10450,7 @@ get_symbol_other (unsigned int other)
       result = get_ppc64_symbol_other (other);
       break;
     default:
+      result = NULL;
       break;
     }
 
@@ -10388,8 +10517,9 @@ get_dynamic_data (FILE * file, bfd_size_type number, unsigned int ent_size)
   if (sizeof (size_t) < sizeof (bfd_size_type)
       && (bfd_size_type) ((size_t) number) != number)
     {
-      error (_("Size truncation prevents reading %llu elements of size %u\n"),
-            (unsigned long long) number, ent_size);
+      error (_("Size truncation prevents reading %" BFD_VMA_FMT "u"
+              " elements of size %u\n"),
+            number, ent_size);
       return NULL;
     }
 
@@ -10397,23 +10527,23 @@ get_dynamic_data (FILE * file, bfd_size_type number, unsigned int ent_size)
      attempting to allocate memory when the read is bound to fail.  */
   if (ent_size * number > current_file_size)
     {
-      error (_("Invalid number of dynamic entries: %llu\n"),
-            (unsigned long long) number);
+      error (_("Invalid number of dynamic entries: %" BFD_VMA_FMT "u\n"),
+            number);
       return NULL;
     }
 
   e_data = (unsigned char *) cmalloc ((size_t) number, ent_size);
   if (e_data == NULL)
     {
-      error (_("Out of memory reading %llu dynamic entries\n"),
-            (unsigned long long) number);
+      error (_("Out of memory reading %" BFD_VMA_FMT "u dynamic entries\n"),
+            number);
       return NULL;
     }
 
   if (fread (e_data, ent_size, (size_t) number, file) != number)
     {
-      error (_("Unable to read in %llu bytes of dynamic data\n"),
-            (unsigned long long) (number * ent_size));
+      error (_("Unable to read in %" BFD_VMA_FMT "u bytes of dynamic data\n"),
+            number * ent_size);
       free (e_data);
       return NULL;
     }
@@ -10421,8 +10551,9 @@ get_dynamic_data (FILE * file, bfd_size_type number, unsigned int ent_size)
   i_data = (bfd_vma *) cmalloc ((size_t) number, sizeof (*i_data));
   if (i_data == NULL)
     {
-      error (_("Out of memory allocating space for %llu dynamic entries\n"),
-            (unsigned long long) number);
+      error (_("Out of memory allocating space for %" BFD_VMA_FMT "u"
+              " dynamic entries\n"),
+            number);
       free (e_data);
       return NULL;
     }
@@ -10460,13 +10591,22 @@ print_dynamic_symbol (bfd_vma si, unsigned long hn)
 
   printf (" %-7s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
   printf (" %-6s",  get_symbol_binding (ELF_ST_BIND (psym->st_info)));
-  printf (" %-7s",  get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
-  /* Check to see if any other bits in the st_other field are set.
-     Note - displaying this information disrupts the layout of the
-     table being generated, but for the moment this case is very
-     rare.  */
-  if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))
-    printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)));
+
+  if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
+    printf (" %-7s",  get_solaris_symbol_visibility (psym->st_other));
+  else
+    {
+      unsigned int vis = ELF_ST_VISIBILITY (psym->st_other);
+
+      printf (" %-7s",  get_symbol_visibility (vis));
+      /* Check to see if any other bits in the st_other field are set.
+        Note - displaying this information disrupts the layout of the
+        table being generated, but for the moment this case is very
+        rare.  */
+      if (psym->st_other ^ vis)
+       printf (" [%s] ", get_symbol_other (psym->st_other ^ vis));
+    }
+
   printf (" %3.3s ", get_symbol_index_type (psym->st_shndx));
   if (VALID_DYNAMIC_NAME (psym->st_name))
     print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
@@ -10476,12 +10616,14 @@ print_dynamic_symbol (bfd_vma si, unsigned long hn)
 }
 
 static const char *
-get_symbol_version_string (FILE *file, int is_dynsym,
-                          const char *strtab,
-                          unsigned long int strtab_size,
-                          unsigned int si, Elf_Internal_Sym *psym,
-                          enum versioned_symbol_info *sym_info,
-                          unsigned short *vna_other)
+get_symbol_version_string (FILE *                       file,
+                          bfd_boolean                  is_dynsym,
+                          const char *                 strtab,
+                          unsigned long int            strtab_size,
+                          unsigned int                 si,
+                          Elf_Internal_Sym *           psym,
+                          enum versioned_symbol_info * sym_info,
+                          unsigned short *             vna_other)
 {
   unsigned char data[2];
   unsigned short vers_data;
@@ -10945,12 +11087,19 @@ process_symbol_table (FILE * file)
              print_vma (psym->st_size, DEC_5);
              printf (" %-7s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
              printf (" %-6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));
-             printf (" %-7s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
-             /* Check to see if any other bits in the st_other field are set.
-                Note - displaying this information disrupts the layout of the
-                table being generated, but for the moment this case is very rare.  */
-             if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))
-               printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)));
+             if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
+               printf (" %-7s",  get_solaris_symbol_visibility (psym->st_other));
+             else
+               {
+                 unsigned int vis = ELF_ST_VISIBILITY (psym->st_other);
+
+                 printf (" %-7s", get_symbol_visibility (vis));
+                 /* Check to see if any other bits in the st_other field are set.
+                    Note - displaying this information disrupts the layout of the
+                    table being generated, but for the moment this case is very rare.  */
+                 if (psym->st_other ^ vis)
+                   printf (" [%s] ", get_symbol_other (psym->st_other ^ vis));
+               }
              printf (" %4s ", get_symbol_index_type (psym->st_shndx));
              print_symbol (25, psym->st_name < strtab_size
                            ? strtab + psym->st_name : _("<corrupt>"));
@@ -11355,6 +11504,7 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
 static bfd_boolean
 is_32bit_abs_reloc (unsigned int reloc_type)
 {
+  /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (elf_header.e_machine)
     {
     case EM_386:
@@ -11368,6 +11518,8 @@ is_32bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 2; /* R_960_32.  */
     case EM_AARCH64:
       return reloc_type == 258; /* R_AARCH64_ABS32 */
+    case EM_ADAPTEVA_EPIPHANY:
+      return reloc_type == 3;
     case EM_ALPHA:
       return reloc_type == 1; /* R_ALPHA_REFLONG.  */
     case EM_ARC:
@@ -11380,8 +11532,6 @@ is_32bit_abs_reloc (unsigned int reloc_type)
     case EM_AVR_OLD:
     case EM_AVR:
       return reloc_type == 1;
-    case EM_ADAPTEVA_EPIPHANY:
-      return reloc_type == 3;
     case EM_BLACKFIN:
       return reloc_type == 0x12; /* R_byte4_data.  */
     case EM_CRIS:
@@ -11540,6 +11690,7 @@ static bfd_boolean
 is_32bit_pcrel_reloc (unsigned int reloc_type)
 {
   switch (elf_header.e_machine)
+  /* Please keep this table alpha-sorted for ease of visual lookup.  */
     {
     case EM_386:
     case EM_IAMCU:
@@ -11552,8 +11703,14 @@ is_32bit_pcrel_reloc (unsigned int reloc_type)
       return reloc_type == 6;
     case EM_ALPHA:
       return reloc_type == 10; /* R_ALPHA_SREL32.  */
+    case EM_ARC_COMPACT:
+    case EM_ARC_COMPACT2:
+      return reloc_type == 49; /* R_ARC_32_PCREL.  */
     case EM_ARM:
       return reloc_type == 3;  /* R_ARM_REL32 */
+    case EM_AVR_OLD:
+    case EM_AVR:
+      return reloc_type == 36; /* R_AVR_32_PCREL.  */
     case EM_MICROBLAZE:
       return reloc_type == 2;  /* R_MICROBLAZE_32_PCREL.  */
     case EM_OR1K:
@@ -11619,7 +11776,8 @@ is_64bit_abs_reloc (unsigned int reloc_type)
     case EM_SPARC32PLUS:
     case EM_SPARCV9:
     case EM_SPARC:
-      return reloc_type == 54; /* R_SPARC_UA64.  */
+      return reloc_type == 32 /* R_SPARC_64.  */
+       || reloc_type == 54; /* R_SPARC_UA64.  */
     case EM_X86_64:
     case EM_L1OM:
     case EM_K1OM:
@@ -11683,6 +11841,8 @@ is_24bit_abs_reloc (unsigned int reloc_type)
     case EM_CYGNUS_MN10200:
     case EM_MN10200:
       return reloc_type == 4; /* R_MN10200_24.  */
+    case EM_FT32:
+      return reloc_type == 5; /* R_FT32_20.  */
     default:
       return FALSE;
     }
@@ -11694,17 +11854,18 @@ is_24bit_abs_reloc (unsigned int reloc_type)
 static bfd_boolean
 is_16bit_abs_reloc (unsigned int reloc_type)
 {
+  /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (elf_header.e_machine)
     {
     case EM_ARC:
     case EM_ARC_COMPACT:
     case EM_ARC_COMPACT2:
       return reloc_type == 2; /* R_ARC_16.  */
+    case EM_ADAPTEVA_EPIPHANY:
+      return reloc_type == 5;
     case EM_AVR_OLD:
     case EM_AVR:
       return reloc_type == 4; /* R_AVR_16.  */
-    case EM_ADAPTEVA_EPIPHANY:
-      return reloc_type == 5;
     case EM_CYGNUS_D10V:
     case EM_D10V:
       return reloc_type == 3; /* R_D10V_16.  */
@@ -11718,6 +11879,12 @@ is_16bit_abs_reloc (unsigned int reloc_type)
     case EM_M32C_OLD:
     case EM_M32C:
       return reloc_type == 1; /* R_M32C_16 */
+    case EM_CYGNUS_MN10200:
+    case EM_MN10200:
+      return reloc_type == 2; /* R_MN10200_16.  */
+    case EM_CYGNUS_MN10300:
+    case EM_MN10300:
+      return reloc_type == 2; /* R_MN10300_16.  */
     case EM_MSP430:
       if (uses_msp430x_relocs ())
        return reloc_type == 2; /* R_MSP430_ABS16.  */
@@ -11733,17 +11900,11 @@ is_16bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 2; /* R_OR1K_16.  */
     case EM_TI_C6000:
       return reloc_type == 2; /* R_C6000_ABS16.  */
+    case EM_VISIUM:
+      return reloc_type == 2; /* R_VISIUM_16. */
     case EM_XC16X:
     case EM_C166:
       return reloc_type == 2; /* R_XC16C_ABS_16.  */
-    case EM_CYGNUS_MN10200:
-    case EM_MN10200:
-      return reloc_type == 2; /* R_MN10200_16.  */
-    case EM_CYGNUS_MN10300:
-    case EM_MN10300:
-      return reloc_type == 2; /* R_MN10300_16.  */
-    case EM_VISIUM:
-      return reloc_type == 2; /* R_VISIUM_16. */
     case EM_XGATE:
       return reloc_type == 3; /* R_XGATE_16.  */
     default:
@@ -11759,44 +11920,53 @@ is_none_reloc (unsigned int reloc_type)
 {
   switch (elf_header.e_machine)
     {
-    case EM_68K:     /* R_68K_NONE.  */
     case EM_386:     /* R_386_NONE.  */
-    case EM_SPARC32PLUS:
-    case EM_SPARCV9:
-    case EM_SPARC:   /* R_SPARC_NONE.  */
-    case EM_MIPS:    /* R_MIPS_NONE.  */
-    case EM_PARISC:  /* R_PARISC_NONE.  */
-    case EM_ALPHA:   /* R_ALPHA_NONE.  */
+    case EM_68K:     /* R_68K_NONE.  */
     case EM_ADAPTEVA_EPIPHANY:
-    case EM_PPC:     /* R_PPC_NONE.  */
-    case EM_PPC64:   /* R_PPC64_NONE.  */
+    case EM_ALPHA:   /* R_ALPHA_NONE.  */
+    case EM_ALTERA_NIOS2: /* R_NIOS2_NONE.  */
     case EM_ARC:     /* R_ARC_NONE.  */
-    case EM_ARC_COMPACT: /* R_ARC_NONE.  */
     case EM_ARC_COMPACT2: /* R_ARC_NONE.  */
+    case EM_ARC_COMPACT: /* R_ARC_NONE.  */
     case EM_ARM:     /* R_ARM_NONE.  */
-    case EM_IA_64:   /* R_IA64_NONE.  */
-    case EM_SH:      /* R_SH_NONE.  */
-    case EM_S390_OLD:
-    case EM_S390:    /* R_390_NONE.  */
+    case EM_C166:    /* R_XC16X_NONE.  */
     case EM_CRIS:    /* R_CRIS_NONE.  */
-    case EM_X86_64:  /* R_X86_64_NONE.  */
-    case EM_L1OM:    /* R_X86_64_NONE.  */
+    case EM_FT32:    /* R_FT32_NONE.  */
+    case EM_IA_64:   /* R_IA64_NONE.  */
     case EM_K1OM:    /* R_X86_64_NONE.  */
+    case EM_L1OM:    /* R_X86_64_NONE.  */
+    case EM_M32R:    /* R_M32R_NONE.  */
+    case EM_MIPS:    /* R_MIPS_NONE.  */
     case EM_MN10300: /* R_MN10300_NONE.  */
-    case EM_FT32:    /* R_FT32_NONE.  */
     case EM_MOXIE:   /* R_MOXIE_NONE.  */
-    case EM_M32R:    /* R_M32R_NONE.  */
-    case EM_TI_C6000:/* R_C6000_NONE.  */
+    case EM_NIOS32:  /* R_NIOS_NONE.  */
+    case EM_OR1K:    /* R_OR1K_NONE. */
+    case EM_PARISC:  /* R_PARISC_NONE.  */
+    case EM_PPC64:   /* R_PPC64_NONE.  */
+    case EM_PPC:     /* R_PPC_NONE.  */
+    case EM_S390:    /* R_390_NONE.  */
+    case EM_S390_OLD:
+    case EM_SH:      /* R_SH_NONE.  */
+    case EM_SPARC32PLUS:
+    case EM_SPARC:   /* R_SPARC_NONE.  */
+    case EM_SPARCV9:
     case EM_TILEGX:  /* R_TILEGX_NONE.  */
     case EM_TILEPRO: /* R_TILEPRO_NONE.  */
+    case EM_TI_C6000:/* R_C6000_NONE.  */
+    case EM_X86_64:  /* R_X86_64_NONE.  */
     case EM_XC16X:
-    case EM_C166:    /* R_XC16X_NONE.  */
-    case EM_ALTERA_NIOS2: /* R_NIOS2_NONE.  */
-    case EM_NIOS32:  /* R_NIOS_NONE.  */
-    case EM_OR1K:    /* R_OR1K_NONE. */
       return reloc_type == 0;
+
     case EM_AARCH64:
       return reloc_type == 0 || reloc_type == 256;
+    case EM_AVR_OLD:
+    case EM_AVR:
+      return (reloc_type == 0 /* R_AVR_NONE.  */
+             || reloc_type == 30 /* R_AVR_DIFF8.  */
+             || reloc_type == 31 /* R_AVR_DIFF16.  */
+             || reloc_type == 32 /* R_AVR_DIFF32.  */);
+    case EM_METAG:
+      return reloc_type == 3; /* R_METAG_NONE.  */
     case EM_NDS32:
       return (reloc_type == 0       /* R_XTENSA_NONE.  */
              || reloc_type == 204  /* R_NDS32_DIFF8.  */
@@ -11809,8 +11979,6 @@ is_none_reloc (unsigned int reloc_type)
              || reloc_type == 17  /* R_XTENSA_DIFF8.  */
              || reloc_type == 18  /* R_XTENSA_DIFF16.  */
              || reloc_type == 19  /* R_XTENSA_DIFF32.  */);
-    case EM_METAG:
-      return reloc_type == 3; /* R_METAG_NONE.  */
     }
   return FALSE;
 }
@@ -11848,7 +12016,7 @@ apply_relocations (void *                     file,
                   const Elf_Internal_Shdr *  section,
                   unsigned char *            start,
                   bfd_size_type              size,
-                  void **                     relocs_return,
+                  void **                    relocs_return,
                   unsigned long *            num_relocs_return)
 {
   Elf_Internal_Shdr * relsec;
@@ -11904,6 +12072,9 @@ apply_relocations (void *                     file,
        is_rela = FALSE;
 
       symsec = section_headers + relsec->sh_link;
+      if (symsec->sh_type != SHT_SYMTAB
+         && symsec->sh_type != SHT_DYNSYM)
+       return;
       symtab = GET_ELF_SYMBOLS ((FILE *) file, symsec, & num_syms);
 
       for (rp = relocs; rp < relocs + num_relocs; ++rp)
@@ -11972,6 +12143,7 @@ apply_relocations (void *                     file,
             referencing a global array.  For an example of this see
             the _clz.o binary in libgcc.a.  */
          if (sym != symtab
+             && ELF_ST_TYPE (sym->st_info) != STT_COMMON
              && ELF_ST_TYPE (sym->st_info) > STT_SECTION)
            {
              warn (_("skipping unexpected symbol type %s in %ld'th relocation in section %s\n"),
@@ -12764,7 +12936,8 @@ static const char * arm_attr_tag_FP_arch[] =
    "FP for ARMv8", "FPv5/FP-D16 for ARMv8"};
 static const char * arm_attr_tag_WMMX_arch[] = {"No", "WMMXv1", "WMMXv2"};
 static const char * arm_attr_tag_Advanced_SIMD_arch[] =
-  {"No", "NEONv1", "NEONv1 with Fused-MAC", "NEON for ARMv8"};
+  {"No", "NEONv1", "NEONv1 with Fused-MAC", "NEON for ARMv8",
+   "NEON for ARMv8.1"};
 static const char * arm_attr_tag_PCS_config[] =
   {"None", "Bare platform", "Linux application", "Linux DSO", "PalmOS 2004",
    "PalmOS (reserved)", "SymbianOS 2004", "SymbianOS (reserved)"};
@@ -12804,6 +12977,8 @@ static const char * arm_attr_tag_FP_HP_extension[] =
   {"Not Allowed", "Allowed"};
 static const char * arm_attr_tag_ABI_FP_16bit_format[] =
   {"None", "IEEE 754", "Alternative Format"};
+static const char * arm_attr_tag_DSP_extension[] =
+  {"Follow architecture", "Allowed"};
 static const char * arm_attr_tag_MPextension_use[] =
   {"Not Allowed", "Allowed"};
 static const char * arm_attr_tag_DIV_use[] =
@@ -12854,6 +13029,7 @@ static arm_attr_public_tag arm_attr_public_tags[] =
   LOOKUP(38, ABI_FP_16bit_format),
   LOOKUP(42, MPextension_use),
   LOOKUP(44, DIV_use),
+  LOOKUP(46, DSP_extension),
   {64, "nodefaults", 0, NULL},
   {65, "also_compatible_with", 0, NULL},
   LOOKUP(66, T2EE_use),
@@ -14066,6 +14242,8 @@ print_mips_ases (unsigned int mask)
     fputs ("\n\tDSP ASE", stdout);
   if (mask & AFL_ASE_DSPR2)
     fputs ("\n\tDSP R2 ASE", stdout);
+  if (mask & AFL_ASE_DSPR3)
+    fputs ("\n\tDSP R3 ASE", stdout);
   if (mask & AFL_ASE_EVA)
     fputs ("\n\tEnhanced VA Scheme", stdout);
   if (mask & AFL_ASE_MCU)
@@ -14325,7 +14503,7 @@ process_mips_specific (FILE * file)
            {
              Elf32_Lib liblist;
              time_t atime;
-             char timebuf[20];
+             char timebuf[128];
              struct tm * tmp;
 
              liblist.l_name = BYTE_GET (elib[cnt].l_name);
@@ -14979,7 +15157,7 @@ process_gnu_liblist (FILE * file)
            {
              Elf32_Lib liblist;
              time_t atime;
-             char timebuf[20];
+             char timebuf[128];
              struct tm * tmp;
 
              liblist.l_name = BYTE_GET (elib[cnt].l_name);
@@ -15099,6 +15277,10 @@ get_note_type (unsigned e_type)
        return _("NT_VERSION (version)");
       case NT_ARCH:
        return _("NT_ARCH (architecture)");
+      case NT_GNU_BUILD_ATTRIBUTE_OPEN:
+       return _("OPEN");
+      case NT_GNU_BUILD_ATTRIBUTE_FUNC:
+       return _("func");
       default:
        break;
       }
@@ -15196,8 +15378,7 @@ print_core_note (Elf_Internal_Note *pnote)
 static const char *
 get_gnu_elf_note_type (unsigned e_type)
 {
-  static char buff[64];
-
+  /* NB/ Keep this switch statement in sync with print_gnu_note ().  */
   switch (e_type)
     {
     case NT_GNU_ABI_TAG:
@@ -15208,57 +15389,243 @@ get_gnu_elf_note_type (unsigned e_type)
       return _("NT_GNU_BUILD_ID (unique build ID bitstring)");
     case NT_GNU_GOLD_VERSION:
       return _("NT_GNU_GOLD_VERSION (gold version)");
+    case NT_GNU_PROPERTY_TYPE_0:
+      return _("NT_GNU_PROPERTY_TYPE_0");
+    case NT_GNU_BUILD_ATTRIBUTE_OPEN:
+      return _("NT_GNU_BUILD_ATTRIBUTE_OPEN");
+    case NT_GNU_BUILD_ATTRIBUTE_FUNC:
+      return _("NT_GNU_BUILD_ATTRIBUTE_FUNC");
     default:
-      break;
+      {
+       static char buff[64];
+
+       snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
+       return buff;
+      }
     }
+}
 
-  snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
-  return buff;
+static void
+decode_x86_isa (unsigned int bitmask)
+{
+  while (bitmask)
+    {
+      unsigned int bit = bitmask & (- bitmask);
+
+      bitmask &= ~ bit;
+      switch (bit)
+       {
+       case GNU_PROPERTY_X86_ISA_1_486: printf ("i486"); break;
+       case GNU_PROPERTY_X86_ISA_1_586: printf ("586"); break;
+       case GNU_PROPERTY_X86_ISA_1_686: printf ("686"); break;
+       case GNU_PROPERTY_X86_ISA_1_SSE: printf ("SSE"); break;
+       case GNU_PROPERTY_X86_ISA_1_SSE2: printf ("SSE2"); break;
+       case GNU_PROPERTY_X86_ISA_1_SSE3: printf ("SSE3"); break;
+       case GNU_PROPERTY_X86_ISA_1_SSSE3: printf ("SSSE3"); break;
+       case GNU_PROPERTY_X86_ISA_1_SSE4_1: printf ("SSE4_1"); break;
+       case GNU_PROPERTY_X86_ISA_1_SSE4_2: printf ("SSE4_2"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX: printf ("AVX"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX2: printf ("AVX2"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512F: printf ("AVX512F"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512CD: printf ("AVX512CD"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512ER: printf ("AVX512ER"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512PF: printf ("AVX512PF"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512VL: printf ("AVX512VL"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512DQ: printf ("AVX512DQ"); break;
+       case GNU_PROPERTY_X86_ISA_1_AVX512BW: printf ("AVX512BW"); break;
+       default: printf (_("<unknown: %x>"), bit); break;
+       }
+      if (bitmask)
+       printf (", ");
+    }
 }
 
-static int
-print_gnu_note (Elf_Internal_Note *pnote)
+static void
+decode_compiler_flags_notes (unsigned long bitmask)
 {
-  switch (pnote->type)
-    {
-    case NT_GNU_BUILD_ID:
-      {
-       unsigned long i;
+  printf("%#lx [", bitmask);
 
-       printf (_("    Build ID: "));
-       for (i = 0; i < pnote->descsz; ++i)
-         printf ("%02x", pnote->descdata[i] & 0xff);
-       printf ("\n");
-      }
-      break;
+  printf("%c%ccxx11, ", bitmask & GNU_PROPERTY_USECXX_VALIDATION ? '=' : '~',
+        bitmask & GNU_PROPERTY_USECXX11_ABI ? '+' : '!');
 
-    case NT_GNU_ABI_TAG:
-      {
-       unsigned long os, major, minor, subminor;
-       const char *osname;
+  printf("%c%casan", bitmask & GNU_PROPERTY_SANITIZE_VALIDATION ? '=' : '~',
+        bitmask & GNU_PROPERTY_SANITIZE_ADDRESS ? '+' : '!');
 
-       /* PR 17531: file: 030-599401-0.004.  */
-       if (pnote->descsz < 16)
-         {
-           printf (_("    <corrupt GNU_ABI_TAG>\n"));
-           break;
-         }
+  printf("]");
+}
 
-       os = byte_get ((unsigned char *) pnote->descdata, 4);
-       major = byte_get ((unsigned char *) pnote->descdata + 4, 4);
-       minor = byte_get ((unsigned char *) pnote->descdata + 8, 4);
-       subminor = byte_get ((unsigned char *) pnote->descdata + 12, 4);
+static void
+print_gnu_property_note (Elf_Internal_Note * pnote)
+{
+  unsigned char * ptr = (unsigned char *) pnote->descdata;
+  unsigned char * ptr_end = ptr + pnote->descsz;
+  unsigned int    size = is_32bit_elf ? 4 : 8;
 
-       switch (os)
-         {
-         case GNU_ABI_TAG_LINUX:
-           osname = "Linux";
-           break;
-         case GNU_ABI_TAG_HURD:
-           osname = "Hurd";
-           break;
-         case GNU_ABI_TAG_SOLARIS:
-           osname = "Solaris";
+  printf (_("      Properties: "));
+
+  if (pnote->descsz < 8 || (pnote->descsz % size) != 0)
+    {
+      printf (_("<corrupt GNU_PROPERTY_TYPE, size = %#lx>\n"), pnote->descsz);
+      return;
+    }
+
+  while (ptr < ptr_end)
+    {
+      unsigned int j;
+      unsigned int type;
+      unsigned int datasz;
+
+      if ((size_t) (ptr_end - ptr) < 8)
+       {
+         printf (_("<corrupt descsz: %#lx>\n"), pnote->descsz);
+         break;
+       }
+
+      type = byte_get (ptr, 4);
+      datasz = byte_get (ptr + 4, 4);
+
+      ptr += 8;
+
+      if (datasz > (size_t) (ptr_end - ptr))
+       {
+         printf (_("<corrupt type (%#x) datasz: %#x>\n"),
+                 type, 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_NEEDED:
+                 printf ("x86 ISA needed: ");
+                 if (datasz != 4)
+                   printf (_("<corrupt length: %#x> "), datasz);
+                 else
+                   decode_x86_isa (byte_get (ptr, 4));
+                 goto next;
+
+               default:
+                 break;
+               }
+           }
+       }
+      else
+       {
+         switch (type)
+           {
+           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;
+
+           case GNU_PROPERTY_COMPILER_FLAGS:
+             printf ("compilations flags: ");
+             if ((datasz != 4) && (datasz != 8))
+               printf (_("<corrupt length: %#x> "), datasz);
+             else
+               {
+                 unsigned long bitmask_flags;
+                 bitmask_flags = (unsigned long) byte_get (ptr, size);
+                 decode_compiler_flags_notes (bitmask_flags);
+               }
+             goto next;
+
+           default:
+             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)
+       break;
+
+      if (do_wide)
+       printf (", ");
+      else
+       printf ("\n\t");
+    }
+
+  printf ("\n");
+}
+
+
+static int
+print_gnu_note (Elf_Internal_Note *pnote)
+{
+  /* NB/ Keep this switch statement in sync with get_gnu_elf_note_type ().  */
+  switch (pnote->type)
+    {
+    case NT_GNU_BUILD_ID:
+      {
+       unsigned long i;
+
+       printf (_("    Build ID: "));
+       for (i = 0; i < pnote->descsz; ++i)
+         printf ("%02x", pnote->descdata[i] & 0xff);
+       printf ("\n");
+      }
+      break;
+
+    case NT_GNU_ABI_TAG:
+      {
+       unsigned long os, major, minor, subminor;
+       const char *osname;
+
+       /* PR 17531: file: 030-599401-0.004.  */
+       if (pnote->descsz < 16)
+         {
+           printf (_("    <corrupt GNU_ABI_TAG>\n"));
+           break;
+         }
+
+       os = byte_get ((unsigned char *) pnote->descdata, 4);
+       major = byte_get ((unsigned char *) pnote->descdata + 4, 4);
+       minor = byte_get ((unsigned char *) pnote->descdata + 8, 4);
+       subminor = byte_get ((unsigned char *) pnote->descdata + 12, 4);
+
+       switch (os)
+         {
+         case GNU_ABI_TAG_LINUX:
+           osname = "Linux";
+           break;
+         case GNU_ABI_TAG_HURD:
+           osname = "Hurd";
+           break;
+         case GNU_ABI_TAG_SOLARIS:
+           osname = "Solaris";
            break;
          case GNU_ABI_TAG_FREEBSD:
            osname = "FreeBSD";
@@ -15292,6 +15659,46 @@ print_gnu_note (Elf_Internal_Note *pnote)
        printf ("\n");
       }
       break;
+
+    case NT_GNU_HWCAP:
+      {
+       unsigned long num_entries, mask;
+
+       /* Hardware capabilities information.  Word 0 is the number of entries.
+          Word 1 is a bitmask of enabled entries.  The rest of the descriptor
+          is a series of entries, where each entry is a single byte followed
+          by a nul terminated string.  The byte gives the bit number to test
+          if enabled in the bitmask.  */
+       printf (_("      Hardware Capabilities: "));
+       if (pnote->descsz < 8)
+         {
+           printf (_("<corrupt GNU_HWCAP>\n"));
+           break;
+         }
+       num_entries = byte_get ((unsigned char *) pnote->descdata, 4);
+       mask = byte_get ((unsigned char *) pnote->descdata + 4, 4);
+       printf (_("num entries: %ld, enabled mask: %lx\n"), num_entries, mask);
+       /* FIXME: Add code to display the entries... */
+      }
+      break;
+
+    case NT_GNU_PROPERTY_TYPE_0:
+      print_gnu_property_note (pnote);
+      break;
+
+    default:
+      /* Handle unrecognised types.  An error message should have already been
+        created by get_gnu_elf_note_type(), so all that we need to do is to
+        display the data.  */
+      {
+       unsigned long i;
+
+       printf (_("    Description data: "));
+       for (i = 0; i < pnote->descsz; ++i)
+         printf ("%02x ", pnote->descdata[i] & 0xff);
+       printf ("\n");
+      }
+      break;
     }
 
   return 1;
@@ -15411,6 +15818,35 @@ process_netbsd_elf_note (Elf_Internal_Note * pnote)
 }
 
 static const char *
+get_freebsd_elfcore_note_type (unsigned e_type)
+{
+  switch (e_type)
+    {
+    case NT_FREEBSD_THRMISC:
+      return _("NT_THRMISC (thrmisc structure)");
+    case NT_FREEBSD_PROCSTAT_PROC:
+      return _("NT_PROCSTAT_PROC (proc data)");
+    case NT_FREEBSD_PROCSTAT_FILES:
+      return _("NT_PROCSTAT_FILES (files data)");
+    case NT_FREEBSD_PROCSTAT_VMMAP:
+      return _("NT_PROCSTAT_VMMAP (vmmap data)");
+    case NT_FREEBSD_PROCSTAT_GROUPS:
+      return _("NT_PROCSTAT_GROUPS (groups data)");
+    case NT_FREEBSD_PROCSTAT_UMASK:
+      return _("NT_PROCSTAT_UMASK (umask data)");
+    case NT_FREEBSD_PROCSTAT_RLIMIT:
+      return _("NT_PROCSTAT_RLIMIT (rlimit data)");
+    case NT_FREEBSD_PROCSTAT_OSREL:
+      return _("NT_PROCSTAT_OSREL (osreldate data)");
+    case NT_FREEBSD_PROCSTAT_PSSTRINGS:
+      return _("NT_PROCSTAT_PSSTRINGS (ps_strings data)");
+    case NT_FREEBSD_PROCSTAT_AUXV:
+      return _("NT_PROCSTAT_AUXV (auxv data)");
+    }
+  return get_note_type (e_type);
+}
+
+static const char *
 get_netbsd_elfcore_note_type (unsigned e_type)
 {
   static char buff[64];
@@ -15639,13 +16075,496 @@ print_ia64_vms_note (Elf_Internal_Note * pnote)
   return 1;
 }
 
+/* Find the symbol associated with a build attribute that is attached
+   to address OFFSET.  If PNAME is non-NULL then store the name of
+   the symbol (if found) in the provided pointer,  Returns NULL if a
+   symbol could not be found.  */
+
+static Elf_Internal_Sym *
+get_symbol_for_build_attribute (FILE *         file,
+                               unsigned long  offset,
+                               bfd_boolean    is_open_attr,
+                               const char **  pname)
+{
+  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 (saved_file == NULL || file != saved_file)
+    {
+      Elf_Internal_Shdr * symsec;
+
+      /* Load the symbol and string sections.  */
+      for (symsec = section_headers;
+          symsec < section_headers + elf_header.e_shnum;
+          symsec ++)
+       {
+         if (symsec->sh_type == SHT_SYMTAB)
+           {
+             symtab = GET_ELF_SYMBOLS (file, symsec, & nsyms);
+
+             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;
+    }
+
+  if (symtab == NULL || strtab == NULL)
+    return NULL;
+
+  /* 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 (strtab[sym->st_name] == 0)
+         continue;
+
+       /* The AArch64 and ARM architectures define mapping symbols
+          (eg $d, $x, $t) which we want to ignore.  */
+       if (strtab[sym->st_name] == '$'
+           && strtab[sym->st_name + 1] != 0
+           && strtab[sym->st_name + 2] == 0)
+         continue;
+
+       if (is_open_attr)
+         {
+           /* For OPEN attributes we prefer GLOBAL over LOCAL symbols
+              and FILE or OBJECT symbols over NOTYPE symbols.  We skip
+              FUNC symbols entirely.  */
+           switch (ELF_ST_TYPE (sym->st_info))
+             {
+             case STT_OBJECT:
+             case STT_FILE:
+               saved_sym = sym;
+               if (sym->st_size)
+                 {
+                   /* If the symbol has a size associated
+                      with it then we can stop searching.  */
+                   sym = symtab + nsyms;
+                 }
+               continue;
+
+             case STT_FUNC:
+               /* Ignore function symbols.  */
+               continue;
+
+             default:
+               break;
+             }
+
+           switch (ELF_ST_BIND (sym->st_info))
+             {
+             case STB_GLOBAL:
+               if (saved_sym == NULL
+                   || ELF_ST_TYPE (saved_sym->st_info) != STT_OBJECT)
+                 saved_sym = sym;
+               break;
+
+             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 (saved_sym && pname)
+    * pname = strtab + saved_sym->st_name;
+
+  return saved_sym;
+}
+
+static bfd_boolean
+print_gnu_build_attribute_description (Elf_Internal_Note * pnote,
+                                      FILE *              file)
+{
+  static unsigned long  global_offset = 0;
+  static unsigned long  global_end = 0;
+  static unsigned long  func_offset = 0;
+  static unsigned long  func_end = 0;
+
+  Elf_Internal_Sym *    sym;
+  const char *          name;
+  unsigned long         start;
+  unsigned long         end;
+  bfd_boolean           is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN;
+
+  switch (pnote->descsz)
+    {
+    case 0:
+      /* A zero-length description means that the range of
+        the previous note of the same type should be used.  */
+      if (is_open_attr)
+       {
+         if (global_end > global_offset)
+           printf (_("    Applies to region from %#lx to %#lx\n"),
+                   global_offset, global_end);
+         else
+           printf (_("    Applies to region from %#lx\n"), global_offset);
+       }
+      else
+       {
+         if (func_end > func_offset)
+           printf (_("    Applies to region from %#lx to %#lx\n"), func_offset, func_end);
+         else
+           printf (_("    Applies to region from %#lx\n"), func_offset);
+       }
+      return TRUE;
+
+    case 4:
+      start = byte_get ((unsigned char *) pnote->descdata, 4);
+      end = 0;
+      break;
+
+    case 8:
+      if (is_32bit_elf)
+       {
+         /* FIXME: We should check that version 3+ notes are being used here...  */
+         start = byte_get ((unsigned char *) pnote->descdata, 4);
+         end = byte_get ((unsigned char *) pnote->descdata + 4, 4);
+       }
+      else
+       {
+         start = byte_get ((unsigned char *) pnote->descdata, 8);
+         end = 0;
+       }
+      break;
+
+    case 16:
+      start = byte_get ((unsigned char *) pnote->descdata, 8);
+      end = byte_get ((unsigned char *) pnote->descdata + 8, 8);
+      break;
+      
+    default:
+      error (_("    <invalid description size: %lx>\n"), pnote->descsz);
+      printf (_("    <invalid descsz>"));
+      return FALSE;
+    }
+
+  name = NULL;
+  sym = get_symbol_for_build_attribute (file, start, is_open_attr, & name);
+  /* As of version 5 of the annobin plugin, filename symbols are biased by 2
+     in order to avoid them being confused with the start address of the
+     first function in the file...  */
+  if (sym == NULL && is_open_attr)
+    sym = get_symbol_for_build_attribute (file, start + 2, is_open_attr,
+                                         & name);
+
+  if (end == 0 && sym != NULL && sym->st_size > 0)
+    end = start + sym->st_size;
+
+  if (is_open_attr)
+    {
+      /* FIXME: Need to properly allow for section alignment.  16 is just the alignment used on x86_64.  */
+      if (global_end > 0 && start > BFD_ALIGN (global_end, 16))
+       warn (_("Gap in build notes detected from %#lx to %#lx\n"),
+             global_end + 1, start - 1);
+
+      printf (_("    Applies to region from %#lx"), start);
+      global_offset = start;
+
+      if (end)
+       {
+         printf (_(" to %#lx"), end);
+         global_end = end;
+       }
+    }
+  else
+    {
+      printf (_("    Applies to region from %#lx"), start);
+      func_offset = start;
+
+      if (end)
+       {
+         printf (_(" to %#lx"), end);
+         func_end = end;
+       }
+    }
+
+  if (sym && name)
+    printf (_(" (%s)"), name);
+
+  printf ("\n");
+  return TRUE;
+}
+
+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;
+  const char * expected_types;
+  const char * name = pnote->namedata;
+  const char * text;
+  signed int   left;
+
+  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>"));
+      return FALSE;
+    }
+
+  if (do_wide)
+    left = 28;
+  else
+    left = 20;
+
+  /* Version 2 of the spec adds a "GA" prefix to the name field.  */
+  if (name[0] == 'G' && name[1] == 'A')
+    {
+      if (pnote->namesz < 4)
+       {
+         error (_("corrupt name field in GNU build attribute note: size = %ld\n"), pnote->namesz);
+         print_symbol (-20, _("  <corrupt name>"));
+         return FALSE;
+       }
+
+      printf ("GA");
+      name += 2;
+      left -= 2;
+    }
+
+  switch ((name_type = * name))
+    {
+    case GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC:
+    case GNU_BUILD_ATTRIBUTE_TYPE_STRING:
+    case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE:
+    case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE:
+      printf ("%c", * name);
+      left --;
+      break;
+    default:
+      error (_("unrecognised attribute type in name field: %d\n"), name_type);
+      print_symbol (-20, _("<unknown name type>"));
+      return FALSE;
+    }
+
+  ++ name;
+  text = NULL;
+
+  switch ((name_attribute = * name))
+    {
+    case GNU_BUILD_ATTRIBUTE_VERSION:
+      text = _("<version>");
+      expected_types = string_expected;
+      ++ name;
+      break;
+    case GNU_BUILD_ATTRIBUTE_STACK_PROT:
+      text = _("<stack prot>");
+      expected_types = "!+*";
+      ++ name;
+      break;
+    case GNU_BUILD_ATTRIBUTE_RELRO:
+      text = _("<relro>");
+      expected_types = bool_expected;
+      ++ name;
+      break;
+    case GNU_BUILD_ATTRIBUTE_STACK_SIZE:
+      text = _("<stack size>");
+      expected_types = number_expected;
+      ++ name;
+      break;
+    case GNU_BUILD_ATTRIBUTE_TOOL:
+      text = _("<tool>");
+      expected_types = string_expected;
+      ++ name;
+      break;
+    case GNU_BUILD_ATTRIBUTE_ABI:
+      text = _("<ABI>");
+      expected_types = "$*";
+      ++ name;
+      break;
+    case GNU_BUILD_ATTRIBUTE_PIC:
+      text = _("<PIC>");
+      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))
+       {
+         int len = strnlen (name, pnote->namesz - (name - pnote->namedata)) + 1;
+
+         if (len > left && ! do_wide)
+           len = left;
+         printf ("%.*s:", len, name);
+         left -= len;
+         name += len;
+       }
+      else
+       {
+         static char tmpbuf [128];
+
+         error (_("unrecognised byte in name field: %d\n"), * name);
+         sprintf (tmpbuf, _("<unknown:_%d>"), * name);
+         text = tmpbuf;
+         name ++;
+       }
+      expected_types = "*$!+";
+      break;
+    }
+
+  if (text)
+    left -= printf ("%s", text);
+
+  if (strchr (expected_types, name_type) == NULL)
+    warn (_("attribute does not have an expected type (%c)\n"), name_type);
+
+  if ((unsigned long)(name - pnote->namedata) > pnote->namesz)
+    {
+      error (_("corrupt name field: namesz: %lu but parsing gets to %ld\n"),
+            (unsigned long) pnote->namesz,
+            (long) (name - pnote->namedata));
+      return FALSE;
+    }
+
+  if (left < 1 && ! do_wide)
+    return TRUE;
+
+  switch (name_type)
+    {
+    case GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC:
+      {
+       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 --)
+         {
+           unsigned long byte = (* name ++) & 0xff;
+
+           val |= byte << shift;
+           shift += 8;
+         }
+
+       switch (name_attribute)
+         {
+         case GNU_BUILD_ATTRIBUTE_PIC:
+           switch (val)
+             {
+             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;
+             }
+           break;
+         case GNU_BUILD_ATTRIBUTE_STACK_PROT:
+           switch (val)
+             {
+               /* 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 (decoded != NULL)
+         {
+           print_symbol (-left, decoded);
+           left = 0;
+         }
+       else if (val == 0)
+         {
+           printf ("0x0");
+           left -= 3;
+         }
+       else
+         {
+           if (do_wide)
+             left -= printf ("0x%llx", val);
+           else
+             left -= printf ("0x%-.*llx", left, val);
+         }
+      }
+      break;
+    case GNU_BUILD_ATTRIBUTE_TYPE_STRING:
+      left -= print_symbol (- left, name);
+      break;
+    case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE:
+      left -= print_symbol (- left, "true");
+      break;
+    case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE:
+      left -= print_symbol (- left, "false");
+      break;
+    }
+
+  if (do_wide && left > 0)
+    printf ("%-*s", left, " ");
+    
+  return TRUE;
+}
+
 /* Note that by the ELF standard, the name field is already null byte
    terminated, and namesz includes the terminating null byte.
    I.E. the value of namesz for the name "FSF" is 4.
 
    If the value of namesz is zero, there is no name present.  */
+
 static int
-process_note (Elf_Internal_Note * pnote)
+process_note (Elf_Internal_Note * pnote,
+             FILE * file)
 {
   const char * name = pnote->namesz ? pnote->namedata : "(NONE)";
   const char * nt;
@@ -15659,6 +16578,10 @@ process_note (Elf_Internal_Note * pnote)
     /* GNU-specific object file notes.  */
     nt = get_gnu_elf_note_type (pnote->type);
 
+  else if (const_strneq (pnote->namedata, "FreeBSD"))
+    /* FreeBSD-specific core file notes.  */
+    nt = get_freebsd_elfcore_note_type (pnote->type);
+
   else if (const_strneq (pnote->namedata, "NetBSD-CORE"))
     /* NetBSD-specific core file notes.  */
     nt = get_netbsd_elfcore_note_type (pnote->type);
@@ -15686,7 +16609,18 @@ process_note (Elf_Internal_Note * pnote)
        note type strings.  */
     nt = get_note_type (pnote->type);
 
-  printf ("  %-20s 0x%08lx\t%s\n", name, pnote->descsz, nt);
+  printf ("  ");
+
+  if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN
+      || pnote->type == NT_GNU_BUILD_ATTRIBUTE_FUNC)
+    print_gnu_build_attribute_name (pnote);
+  else
+    print_symbol (-20, name);
+
+  if (do_wide)
+    printf (" 0x%08lx\t%s\t", pnote->descsz, nt);
+  else
+    printf (" 0x%08lx\t%s\n", pnote->descsz, nt);
 
   if (const_strneq (pnote->namedata, "IPF/VMS"))
     return print_ia64_vms_note (pnote);
@@ -15696,31 +16630,84 @@ process_note (Elf_Internal_Note * pnote)
     return print_stapsdt_note (pnote);
   else if (const_strneq (pnote->namedata, "CORE"))
     return print_core_note (pnote);
-  else
-    return 1;
-}
+  else if (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN
+          || pnote->type == NT_GNU_BUILD_ATTRIBUTE_FUNC)
+    return print_gnu_build_attribute_description (pnote, file);
+
+  if (pnote->descsz)
+    {
+      unsigned long i;
+
+      printf (_("   description data: "));
+      for (i = 0; i < pnote->descsz; i++)
+       printf ("%02x ", pnote->descdata[i]);
+    }
+
+  if (do_wide)
+    printf ("\n");
 
+  return 1;
+}
 
 static int
-process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
+process_notes_at (FILE *              file,
+                 Elf_Internal_Shdr * section,
+                 bfd_vma             offset,
+                 bfd_vma             length,
+                 bfd_vma             align)
 {
   Elf_External_Note * pnotes;
   Elf_External_Note * external;
-  char * end;
-  int res = 1;
+  char *              end;
+  bfd_boolean         res = TRUE;
 
   if (length <= 0)
     return 0;
 
-  pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length,
-                                          _("notes"));
+  if (section)
+    {
+      pnotes = (Elf_External_Note *) get_section_contents (section, file);
+      if (pnotes)
+       apply_relocations (file, section, (unsigned char *) pnotes, length, NULL, NULL);
+
+    }
+  else
+    {
+      pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length,
+                                              _("notes"));
+
+      /* FIXME: Core notes seem to be produced with
+        4-byte alignment even on 64-bit systems.  */
+      if (elf_header.e_type == ET_CORE)
+       align = 4;
+      else
+       align = is_32bit_elf ? 4 : 4;
+    }
   if (pnotes == NULL)
     return 0;
 
   external = pnotes;
 
-  printf (_("\nDisplaying notes found at file offset 0x%08lx with length 0x%08lx:\n"),
-         (unsigned long) offset, (unsigned long) length);
+  if (section)
+    printf (_("\nDisplaying notes found in: %s\n"), printable_section_name (section));
+  else
+    printf (_("\nDisplaying notes found at file offset 0x%08lx with length 0x%08lx:\n"),
+           (unsigned long) offset, (unsigned long) length);
+
+  /* NB: Some note sections may have alignment value of 0 or 1.  gABI
+     specifies that notes should be aligned to 4 bytes in 32-bit
+     objects and to 8 bytes in 64-bit objects.  As a Linux extension,
+     we also support 4 byte alignment in 64-bit objects.  If section
+     alignment is less than 4, we treate alignment as 4 bytes.   */
+  if (align < 4)
+    align = 4;
+  else if (align != 4 && align != 8)
+    {
+      warn (_("Corrupt note: alignment %ld, expecting 4 or 8\n"),
+           (long) align);
+      return FALSE;
+    }
+
   printf (_("  %-20s %10s\tDescription\n"), _("Owner"), _("Data size"));
 
   end = (char *) pnotes + length;
@@ -15728,7 +16715,7 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
     {
       Elf_Internal_Note inote;
       size_t min_notesz;
-      char *next;
+      char * next;
       char * temp = NULL;
       size_t data_remaining = end - (char *) external;
 
@@ -15747,17 +16734,20 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
          inote.namesz   = BYTE_GET (external->namesz);
          inote.namedata = external->name;
          inote.descsz   = BYTE_GET (external->descsz);
-         inote.descdata = inote.namedata + align_power (inote.namesz, 2);
+         inote.descdata = ((char *) external
+                           + ELF_NOTE_DESC_OFFSET (inote.namesz, align));
          /* PR 17531: file: 3443835e.  */
          if (inote.descdata < (char *) pnotes || inote.descdata > end)
            {
-             warn (_("Corrupt note: name size is too big: %lx\n"), inote.namesz);
+             warn (_("Corrupt note: name size is too big: (got: %lx, expected no more than: %lx)\n"),
+                   inote.namesz, (long)(end - inote.namedata));
              inote.descdata = inote.namedata;
              inote.namesz   = 0;
            }
 
          inote.descpos  = offset + (inote.descdata - (char *) pnotes);
-         next = inote.descdata + align_power (inote.descsz, 2);
+         next = ((char *) external
+                 + ELF_NOTE_NEXT_OFFSET (inote.namesz, inote.descsz, align));
        }
       else
        {
@@ -15792,8 +16782,8 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
        {
          warn (_("note with invalid namesz and/or descsz found at offset 0x%lx\n"),
                (unsigned long) ((char *) external - (char *) pnotes));
-         warn (_(" type: 0x%lx, namesize: 0x%08lx, descsize: 0x%08lx\n"),
-               inote.type, inote.namesz, inote.descsz);
+         warn (_(" type: 0x%lx, namesize: 0x%08lx, descsize: 0x%08lx, alignment: %u\n"),
+               inote.type, inote.namesz, inote.descsz, (int) align);
          break;
        }
 
@@ -15813,14 +16803,14 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
              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;
        }
 
-      res &= process_note (& inote);
+      res &= process_note (& inote, file);
 
       if (temp != NULL)
        {
@@ -15849,9 +16839,10 @@ process_corefile_note_segments (FILE * file)
        i++, segment++)
     {
       if (segment->p_type == PT_NOTE)
-       res &= process_corefile_note_segment (file,
-                                             (bfd_vma) segment->p_offset,
-                                             (bfd_vma) segment->p_filesz);
+       res &= process_notes_at (file, NULL,
+                                (bfd_vma) segment->p_offset,
+                                (bfd_vma) segment->p_filesz,
+                                (bfd_vma) segment->p_align);
     }
 
   return res;
@@ -15952,9 +16943,10 @@ process_note_sections (FILE * file)
     {
       if (section->sh_type == SHT_NOTE)
        {
-         res &= process_corefile_note_segment (file,
-                                               (bfd_vma) section->sh_offset,
-                                               (bfd_vma) section->sh_size);
+         res &= process_notes_at (file, section,
+                                  (bfd_vma) section->sh_offset,
+                                  (bfd_vma) section->sh_size,
+                                  (bfd_vma) section->sh_addralign);
          n++;
        }