]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - binutils/readelf.c
merge from gcc
[thirdparty/binutils-gdb.git] / binutils / readelf.c
index b16fa7a3d4690d922994ff5f537680179b084dad..1682e0a26ceb6af009b8bb6841f49c2b24e958fd 100644 (file)
 #include "elf/mmix.h"
 #include "elf/mn10200.h"
 #include "elf/mn10300.h"
+#include "elf/moxie.h"
 #include "elf/mt.h"
 #include "elf/msp430.h"
 #include "elf/or32.h"
@@ -271,7 +272,8 @@ static void (* byte_put) (unsigned char *, bfd_vma, int);
 
 #define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag)) /* Reverse order!  */
 
-#define BYTE_GET(field)        byte_get (field, sizeof (field))
+#define BYTE_GET(field)                byte_get (field, sizeof (field))
+#define BYTE_GET_SIGNED(field) byte_get_signed (field, sizeof (field))
 
 #define GET_ELF_SYMBOLS(file, section)                 \
   (is_32bit_elf ? get_32bit_elf_symbols (file, section)        \
@@ -646,6 +648,7 @@ guess_is_rela (unsigned int e_machine)
     case EM_CYGNUS_MN10200:
     case EM_MN10300:
     case EM_CYGNUS_MN10300:
+    case EM_MOXIE:
     case EM_MSP430:
     case EM_MSP430_OLD:
     case EM_MT:
@@ -732,7 +735,7 @@ slurp_rela_relocs (FILE * file,
        {
          relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
          relas[i].r_info   = BYTE_GET (erelas[i].r_info);
-         relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
+         relas[i].r_addend = BYTE_GET_SIGNED (erelas[i].r_addend);
        }
 
       free (erelas);
@@ -762,7 +765,7 @@ slurp_rela_relocs (FILE * file,
        {
          relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
          relas[i].r_info   = BYTE_GET (erelas[i].r_info);
-         relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
+         relas[i].r_addend = BYTE_GET_SIGNED (erelas[i].r_addend);
 
          /* The #ifdef BFD64 below is to prevent a compile time
             warning.  We know that if we do not have a 64 bit data
@@ -1130,6 +1133,10 @@ dump_relocations (FILE * file,
          rtype = elf_mmix_reloc_type (type);
          break;
 
+       case EM_MOXIE:
+         rtype = elf_moxie_reloc_type (type);
+         break;
+
        case EM_MSP430:
        case EM_MSP430_OLD:
          rtype = elf_msp430_reloc_type (type);
@@ -1260,7 +1267,7 @@ dump_relocations (FILE * file,
        case EM_CR16_OLD:
          rtype = elf_cr16_reloc_type (type);
          break;
-       
+
        case EM_MICROBLAZE:
        case EM_MICROBLAZE_OLD:
          rtype = elf_microblaze_reloc_type (type);
@@ -1404,12 +1411,12 @@ dump_relocations (FILE * file,
 
              if (is_rela)
                {
-                 long off = (long) (bfd_signed_vma) rels[i].r_addend;
+                 bfd_signed_vma off = rels[i].r_addend;
 
                  if (off < 0)
-                   printf (" - %lx", - off);
+                   printf (" - %" BFD_VMA_FMT "x", - off);
                  else
-                   printf (" + %lx", off);
+                   printf (" + %" BFD_VMA_FMT "x", off);
                }
            }
        }
@@ -1906,6 +1913,7 @@ get_machine_name (unsigned e_machine)
     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";
@@ -2230,6 +2238,21 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
          decode_ARM_machine_flags (e_flags, buf);
          break;
 
+       case EM_BLACKFIN:
+         if (e_flags & EF_BFIN_PIC)
+           strcat (buf, ", PIC");
+
+         if (e_flags & EF_BFIN_FDPIC)
+           strcat (buf, ", FDPIC");
+
+         if (e_flags & EF_BFIN_CODE_IN_L1)
+           strcat (buf, ", code in L1");
+
+         if (e_flags & EF_BFIN_DATA_IN_L1)
+           strcat (buf, ", data in L1");
+
+         break;
+
        case EM_CYGNUS_FRV:
          switch (e_flags & EF_FRV_CPU_MASK)
            {
@@ -2303,6 +2326,13 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
                case EF_M68K_CF_ISA_B:
                  isa = "B";
                  break;
+               case EF_M68K_CF_ISA_C:
+                 isa = "C";
+                 break;
+               case EF_M68K_CF_ISA_C_NODIV:
+                 isa = "C";
+                 additional = ", nodiv";
+                 break;
                }
              strcat (buf, ", cf, isa ");
              strcat (buf, isa);
@@ -2321,6 +2351,9 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
                case EF_M68K_CF_EMAC:
                  mac = "emac";
                  break;
+               case EF_M68K_CF_EMAC_B:
+                 mac = "emac_b";
+                 break;
                }
              if (mac)
                {
@@ -2345,8 +2378,14 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
        case EM_CYGNUS_V850:
          switch (e_flags & EF_V850_ARCH)
            {
-           case E_V850E1_ARCH:
-             strcat (buf, ", v850e1");
+           case E_V850E2V3_ARCH:
+             strcat (buf, ", v850e2v3");
+             break;
+           case E_V850E2_ARCH:
+             strcat (buf, ", v850e2");
+             break;
+            case E_V850E1_ARCH:
+              strcat (buf, ", v850e1");
              break;
            case E_V850E_ARCH:
              strcat (buf, ", v850e");
@@ -2403,6 +2442,7 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
            case E_MIPS_MACH_9000: strcat (buf, ", 9000"); break;
            case E_MIPS_MACH_LS2E: strcat (buf, ", loongson-2e"); break;
            case E_MIPS_MACH_LS2F: strcat (buf, ", loongson-2f"); break;
+           case E_MIPS_MACH_LS3A: strcat (buf, ", loongson-3a"); break;
            case E_MIPS_MACH_OCTEON: strcat (buf, ", octeon"); break;
            case E_MIPS_MACH_OCTEON2: strcat (buf, ", octeon2"); break;
            case E_MIPS_MACH_XLR:  strcat (buf, ", xlr"); break;
@@ -2598,7 +2638,7 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
          if (e_flags & E_FLAG_RX_64BIT_DOUBLES)
            strcat (buf, ", 64-bit doubles");
          if (e_flags & E_FLAG_RX_DSP)
-           strcat (buf, ", dsp");        
+           strcat (buf, ", dsp");
 
        case EM_S390:
          if (e_flags & EF_S390_HIGH_GPRS)
@@ -3889,8 +3929,8 @@ process_program_headers (FILE * file)
 
          for (j = 1; j < elf_header.e_shnum; j++, section++)
            {
-             if (ELF_SECTION_SIZE (section, segment) != 0
-                 && ELF_SECTION_IN_SEGMENT (section, segment))
+             if (!ELF_TBSS_SPECIAL (section, segment)
+                 && ELF_SECTION_IN_SEGMENT_STRICT (section, segment))
                printf ("%s ", SECTION_NAME (section));
            }
 
@@ -4023,15 +4063,30 @@ static Elf_Internal_Sym *
 get_32bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
 {
   unsigned long number;
-  Elf32_External_Sym * esyms;
+  Elf32_External_Sym * esyms = NULL;
   Elf_External_Sym_Shndx * shndx;
-  Elf_Internal_Sym * isyms;
+  Elf_Internal_Sym * isyms = NULL;
   Elf_Internal_Sym * psym;
   unsigned int j;
 
+  /* Run some sanity checks first.  */
+  if (section->sh_entsize == 0)
+    {
+      error (_("sh_entsize is zero\n"));
+      return NULL;
+    }
+
+  number = section->sh_size / section->sh_entsize;
+
+  if (number * sizeof (Elf32_External_Sym) > section->sh_size + 1)
+    {
+      error (_("Invalid sh_entsize\n"));
+      return NULL;
+    }
+
   esyms = (Elf32_External_Sym *) get_data (NULL, file, section->sh_offset, 1,
                                            section->sh_size, _("symbols"));
-  if (!esyms)
+  if (esyms == NULL)
     return NULL;
 
   shndx = NULL;
@@ -4043,28 +4098,19 @@ get_32bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
                                                    symtab_shndx_hdr->sh_offset,
                                                    1, symtab_shndx_hdr->sh_size,
                                                    _("symtab shndx"));
-      if (!shndx)
-       {
-         free (esyms);
-         return NULL;
-       }
+      if (shndx == NULL)
+       goto exit_point;
     }
 
-  number = section->sh_size / section->sh_entsize;
   isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
 
   if (isyms == NULL)
     {
       error (_("Out of memory\n"));
-      if (shndx)
-       free (shndx);
-      free (esyms);
-      return NULL;
+      goto exit_point;
     }
 
-  for (j = 0, psym = isyms;
-       j < number;
-       j++, psym++)
+  for (j = 0, psym = isyms; j < number; j++, psym++)
     {
       psym->st_name  = BYTE_GET (esyms[j].st_name);
       psym->st_value = BYTE_GET (esyms[j].st_value);
@@ -4079,9 +4125,11 @@ get_32bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
       psym->st_other = BYTE_GET (esyms[j].st_other);
     }
 
+ exit_point:
   if (shndx)
     free (shndx);
-  free (esyms);
+  if (esyms)
+    free (esyms);
 
   return isyms;
 }
@@ -4096,6 +4144,21 @@ get_64bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
   Elf_Internal_Sym * psym;
   unsigned int j;
 
+  /* Run some sanity checks first.  */
+  if (section->sh_entsize == 0)
+    {
+      error (_("sh_entsize is zero\n"));
+      return NULL;
+    }
+
+  number = section->sh_size / section->sh_entsize;
+
+  if (number * sizeof (Elf64_External_Sym) > section->sh_size + 1)
+    {
+      error (_("Invalid sh_entsize\n"));
+      return NULL;
+    }
+
   esyms = (Elf64_External_Sym *) get_data (NULL, file, section->sh_offset, 1,
                                            section->sh_size, _("symbols"));
   if (!esyms)
@@ -4117,7 +4180,6 @@ get_64bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
        }
     }
 
-  number = section->sh_size / section->sh_entsize;
   isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
 
   if (isyms == NULL)
@@ -4816,10 +4878,19 @@ process_section_headers (FILE * file)
     }
 
   if (!do_section_details)
-    printf (_("Key to Flags:\n\
+    {
+      if (elf_header.e_machine == EM_X86_64
+         || elf_header.e_machine == EM_L1OM)
+       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), x (unknown)\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"));
+    }  
 
   return 1;
 }
@@ -4942,6 +5013,12 @@ process_section_groups (FILE * file)
              symtab = GET_ELF_SYMBOLS (file, symtab_sec);
            }
 
+         if (symtab == NULL)
+           {
+             error (_("Corrupt header in group section `%s'\n"), name);
+             continue;
+           }
+
          sym = symtab + section->sh_info;
 
          if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
@@ -6417,7 +6494,6 @@ decode_arm_unwind (struct arm_unw_aux_info *aux,
     }
   else
     {
-      
       per_index = (word >> 24) & 0x7f;
       if (per_index != 0 && per_index != 1 && per_index != 2)
        {
@@ -7750,6 +7826,10 @@ process_version_sections (FILE * file)
                int j;
                int isum;
 
+               /* Check for negative or very large indicies.  */
+               if ((unsigned char *) edefs + idx < (unsigned char *) edefs)
+                 break;
+
                vstart = ((char *) edefs) + idx;
                if (vstart + sizeof (*edef) > endbuf)
                  break;
@@ -7770,6 +7850,11 @@ process_version_sections (FILE * file)
                printf (_("  Index: %d  Cnt: %d  "),
                        ent.vd_ndx, ent.vd_cnt);
 
+               /* Check for overflow.  */
+               if ((unsigned char *)(vstart + ent.vd_aux) < (unsigned char *) vstart
+                   || (unsigned char *)(vstart + ent.vd_aux) > (unsigned char *) endbuf)
+                 break;
+
                vstart += ent.vd_aux;
 
                eaux = (Elf_External_Verdaux *) vstart;
@@ -7786,6 +7871,11 @@ process_version_sections (FILE * file)
 
                for (j = 1; j < ent.vd_cnt; j++)
                  {
+                   /* Check for overflow.  */
+                   if ((unsigned char *)(vstart + aux.vda_next) < (unsigned char *) vstart
+                       || (unsigned char *)(vstart + aux.vda_next) > (unsigned char *) endbuf)
+                     break;
+
                    isum   += aux.vda_next;
                    vstart += aux.vda_next;
 
@@ -7803,11 +7893,13 @@ process_version_sections (FILE * file)
                      printf (_("  %#06x: Parent %d, name index: %ld\n"),
                              isum, j, aux.vda_name);
                  }
+
                if (j < ent.vd_cnt)
                  printf (_("  Version def aux past end of section\n"));
 
                idx += ent.vd_next;
              }
+
            if (cnt < section->sh_info)
              printf (_("  Version definition past end of section\n"));
 
@@ -7851,6 +7943,9 @@ process_version_sections (FILE * file)
                int isum;
                char * vstart;
 
+               if ((unsigned char *) eneed + idx < (unsigned char *) eneed)
+                 break;
+
                vstart = ((char *) eneed) + idx;
                if (vstart + sizeof (*entry) > endbuf)
                  break;
@@ -7872,6 +7967,11 @@ process_version_sections (FILE * file)
 
                printf (_("  Cnt: %d\n"), ent.vn_cnt);
 
+               /* Check for overflow.  */
+               if ((unsigned char *)(vstart + ent.vn_aux) < (unsigned char *) vstart
+                   || (unsigned char *)(vstart + ent.vn_aux) > (unsigned char *) endbuf)
+                 break;
+
                vstart += ent.vn_aux;
 
                for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
@@ -7899,6 +7999,11 @@ process_version_sections (FILE * file)
                    printf (_("  Flags: %s  Version: %d\n"),
                            get_ver_flags (aux.vna_flags), aux.vna_other);
 
+                   /* Check for overflow.  */
+                   if ((unsigned char *)(vstart + aux.vna_next) < (unsigned char *) vstart
+                       || (unsigned char *)(vstart + aux.vna_next) > (unsigned char *) endbuf)
+                     break;
+
                    isum   += aux.vna_next;
                    vstart += aux.vna_next;
                  }
@@ -7938,6 +8043,8 @@ process_version_sections (FILE * file)
            found = 1;
 
            symbols = GET_ELF_SYMBOLS (file, link_section);
+           if (symbols == NULL)
+             break;
 
            string_sec = section_headers + link_section->sh_link;
 
@@ -7999,6 +8106,16 @@ process_version_sections (FILE * file)
                      nn = printf ("%4x%c", data[cnt + j] & VERSYM_VERSION,
                                   data[cnt + j] & VERSYM_HIDDEN ? 'h' : ' ');
 
+                     /* If this index value is greater than the size of the symbols
+                        array, break to avoid an out-of-bounds read,  */
+                     if ((unsigned long)(cnt + j) >=
+                        ((unsigned long)link_section->sh_size /
+                         (unsigned long)link_section->sh_entsize))
+                       {
+                         warn (_("invalid index into symbol array\n"));
+                         break;
+                       }
+
                      check_def = 1;
                      check_need = 1;
                      if (symbols[cnt + j].st_shndx >= elf_header.e_shnum
@@ -8706,9 +8823,17 @@ process_symbol_table (FILE * file)
                  && section->sh_type == SHT_SYMTAB))
            continue;
 
+         if (section->sh_entsize == 0)
+           {
+             printf (_("\nSymbol table '%s' has a sh_entsize of zero!\n"),
+                     SECTION_NAME (section));
+             continue;
+           }
+
          printf (_("\nSymbol table '%s' contains %lu entries:\n"),
                  SECTION_NAME (section),
                  (unsigned long) (section->sh_size / section->sh_entsize));
+
          if (is_32bit_elf)
            printf (_("   Num:    Value  Size Type    Bind   Vis      Ndx Name\n"));
          else
@@ -9177,8 +9302,10 @@ is_32bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 1; /* R_68K_32.  */
     case EM_860:
       return reloc_type == 1; /* R_860_32.  */
+    case EM_960:
+      return reloc_type == 2; /* R_960_32.  */
     case EM_ALPHA:
-      return reloc_type == 1; /* XXX Is this right ?  */
+      return reloc_type == 1; /* R_ALPHA_REFLONG.  */
     case EM_ARC:
       return reloc_type == 1; /* R_ARC_32.  */
     case EM_ARM:
@@ -9230,6 +9357,8 @@ is_32bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 1; /* R_MCORE_ADDR32.  */
     case EM_CYGNUS_MEP:
       return reloc_type == 4; /* R_MEP_32.  */
+    case EM_MICROBLAZE:
+      return reloc_type == 1; /* R_MICROBLAZE_32.  */
     case EM_MIPS:
       return reloc_type == 2; /* R_MIPS_32.  */
     case EM_MMIX:
@@ -9240,6 +9369,8 @@ is_32bit_abs_reloc (unsigned int reloc_type)
     case EM_CYGNUS_MN10300:
     case EM_MN10300:
       return reloc_type == 1; /* R_MN10300_32.  */
+    case EM_MOXIE:
+      return reloc_type == 1; /* R_MOXIE_32.  */
     case EM_MSP430_OLD:
     case EM_MSP430:
       return reloc_type == 1; /* R_MSP43_32.  */
@@ -9321,6 +9452,8 @@ is_32bit_pcrel_reloc (unsigned int reloc_type)
       return reloc_type == 10; /* R_ALPHA_SREL32.  */
     case EM_ARM:
       return reloc_type == 3;  /* R_ARM_REL32 */
+    case EM_MICROBLAZE:
+      return reloc_type == 2;  /* R_MICROBLAZE_32_PCREL.  */
     case EM_PARISC:
       return reloc_type == 9;  /* R_PARISC_PCREL32.  */
     case EM_PPC:
@@ -9501,6 +9634,7 @@ is_none_reloc (unsigned int reloc_type)
     case EM_X86_64:  /* R_X86_64_NONE.  */
     case EM_L1OM:    /* R_X86_64_NONE.  */
     case EM_MN10300: /* R_MN10300_NONE.  */
+    case EM_MOXIE:   /* R_MOXIE_NONE.  */
     case EM_M32R:    /* R_M32R_NONE.  */
     case EM_TI_C6000:/* R_C6000_NONE.  */
     case EM_XC16X:
@@ -9641,13 +9775,17 @@ apply_relocations (void * file,
          addend = 0;
          if (is_rela)
            addend += rp->r_addend;
-         /* R_XTENSA_32 and R_PJ_DATA_DIR32 are partial_inplace.  */
+         /* R_XTENSA_32, R_PJ_DATA_DIR32 and R_D30V_32_NORMAL are
+            partial_inplace.  */
          if (!is_rela
              || (elf_header.e_machine == EM_XTENSA
                  && reloc_type == 1)
              || ((elf_header.e_machine == EM_PJ
                   || elf_header.e_machine == EM_PJ_OLD)
-                 && reloc_type == 1))
+                 && reloc_type == 1)
+             || ((elf_header.e_machine == EM_D30V
+                  || elf_header.e_machine == EM_CYGNUS_D30V)
+                 && reloc_type == 12))
            addend += byte_get (rloc, reloc_size);
 
          if (is_32bit_pcrel_reloc (reloc_type)
@@ -9703,7 +9841,7 @@ get_section_contents (Elf_Internal_Shdr * section, FILE * file)
                              _("section contents"));
 }
 
-                     
+
 static void
 dump_section_as_strings (Elf_Internal_Shdr * section, FILE * file)
 {
@@ -9865,8 +10003,7 @@ dump_section_as_bytes (Elf_Internal_Shdr * section,
   putchar ('\n');
 }
 
-/* Uncompresses a section that was compressed using zlib, in place.
-   This is a copy of bfd_uncompress_section_contents, in bfd/compress.c  */
+/* Uncompresses a section that was compressed using zlib, in place.  */
 
 static int
 uncompress_section_contents (unsigned char **buffer ATTRIBUTE_UNUSED,
@@ -9932,6 +10069,8 @@ uncompress_section_contents (unsigned char **buffer ATTRIBUTE_UNUSED,
 
  fail:
   free (uncompressed_buffer);
+  /* Indicate decompression failure.  */
+  *buffer = NULL;
   return 0;
 #endif  /* HAVE_ZLIB_H */
 }
@@ -9942,30 +10081,23 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
 {
   struct dwarf_section * section = &debug_displays [debug].section;
   char buf [64];
-  int section_is_compressed;
 
   /* If it is already loaded, do nothing.  */
   if (section->start != NULL)
     return 1;
 
-  section_is_compressed = section->name == section->compressed_name;
-
   snprintf (buf, sizeof (buf), _("%s section data"), section->name);
   section->address = sec->sh_addr;
   section->size = sec->sh_size;
   section->start = (unsigned char *) get_data (NULL, (FILE *) file,
                                                sec->sh_offset, 1,
                                                sec->sh_size, buf);
+  if (uncompress_section_contents (&section->start, &section->size))
+    sec->sh_size = section->size;
+
   if (section->start == NULL)
     return 0;
 
-  if (section_is_compressed)
-    {
-      if (! uncompress_section_contents (&section->start, &section->size))
-        return 0;
-      sec->sh_size = section->size;
-    }
-
   if (debug_displays [debug].relocate)
     apply_relocations ((FILE *) file, sec, section->start);
 
@@ -10176,7 +10308,7 @@ static const char * arm_attr_tag_THUMB_ISA_use[] =
 static const char * arm_attr_tag_FP_arch[] =
   {"No", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16", "VFPv4", "VFPv4-D16"};
 static const char * arm_attr_tag_WMMX_arch[] = {"No", "WMMXv1", "WMMXv2"};
-static const char * arm_attr_tag_Advanced_SIMD_arch[] = 
+static const char * arm_attr_tag_Advanced_SIMD_arch[] =
   {"No", "NEONv1", "NEONv1 with Fused-MAC"};
 static const char * arm_attr_tag_PCS_config[] =
   {"None", "Bare platform", "Linux application", "Linux DSO", "PalmOS 2004",
@@ -10217,16 +10349,16 @@ 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_MPextension_use[] = 
+static const char * arm_attr_tag_MPextension_use[] =
   {"Not Allowed", "Allowed"};
 static const char * arm_attr_tag_DIV_use[] =
-  {"Allowed in Thumb-ISA, v7-R or v7-M", "Not allowed", 
+  {"Allowed in Thumb-ISA, v7-R or v7-M", "Not allowed",
     "Allowed in v7-A with integer division extension"};
 static const char * arm_attr_tag_T2EE_use[] = {"Not Allowed", "Allowed"};
 static const char * arm_attr_tag_Virtualization_use[] =
-  {"Not Allowed", "TrustZone", "Virtualization Extensions", 
+  {"Not Allowed", "TrustZone", "Virtualization Extensions",
     "TrustZone and Virtualization Extensions"};
-static const char * arm_attr_tag_MPextension_use_legacy[] = 
+static const char * arm_attr_tag_MPextension_use_legacy[] =
   {"Not Allowed", "Allowed"};
 
 #define LOOKUP(id, name) \
@@ -10331,7 +10463,7 @@ display_arm_attribute (unsigned char * p)
                case 3: printf ("??? 3\n"); break;
                default:
                  if (val <= 12)
-                   printf (_("8-byte and up to %d-byte extended\n"), 
+                   printf (_("8-byte and up to %d-byte extended\n"),
                            1 << val);
                  else
                    printf ("??? (%d)\n", val);
@@ -10350,7 +10482,7 @@ display_arm_attribute (unsigned char * p)
                case 3: printf ("??? 3\n"); break;
                default:
                  if (val <= 12)
-                   printf (_("8-byte and up to %d-byte extended\n"), 
+                   printf (_("8-byte and up to %d-byte extended\n"),
                            1 << val);
                  else
                    printf ("??? (%d)\n", val);
@@ -10612,7 +10744,7 @@ display_mips_gnu_attribute (unsigned char * p, int tag)
          printf (_("Soft float\n"));
          break;
        case 4:
-         printf (_("64-bit float (-mips32r2 -mfp64)\n"));
+         printf (_("Hard float (MIPS32r2 64-bit FPU)\n"));
          break;
        default:
          printf ("??? (%d)\n", val);
@@ -10654,32 +10786,32 @@ display_tic6x_attribute (unsigned char * p)
 
   switch (tag)
     {
-    case Tag_C6XABI_Tag_CPU_arch:
+    case Tag_ISA:
       val = read_uleb128 (p, &len);
       p += len;
-      printf ("  Tag_C6XABI_Tag_CPU_arch: ");
+      printf ("  Tag_ISA: ");
 
       switch (val)
        {
-       case C6XABI_Tag_CPU_arch_none:
+       case C6XABI_Tag_ISA_none:
          printf (_("None\n"));
          break;
-       case C6XABI_Tag_CPU_arch_C62X:
+       case C6XABI_Tag_ISA_C62X:
          printf ("C62x\n");
          break;
-       case C6XABI_Tag_CPU_arch_C67X:
+       case C6XABI_Tag_ISA_C67X:
          printf ("C67x\n");
          break;
-       case C6XABI_Tag_CPU_arch_C67XP:
+       case C6XABI_Tag_ISA_C67XP:
          printf ("C67x+\n");
          break;
-       case C6XABI_Tag_CPU_arch_C64X:
+       case C6XABI_Tag_ISA_C64X:
          printf ("C64x\n");
          break;
-       case C6XABI_Tag_CPU_arch_C64XP:
+       case C6XABI_Tag_ISA_C64XP:
          printf ("C64x+\n");
          break;
-       case C6XABI_Tag_CPU_arch_C674X:
+       case C6XABI_Tag_ISA_C674X:
          printf ("C674x\n");
          break;
        default:
@@ -10688,23 +10820,190 @@ display_tic6x_attribute (unsigned char * p)
        }
       return p;
 
-    case 32:
-      /* Tag_compatibility - treated as generic by binutils for now
-        although not currently specified for C6X.  */
+    case Tag_ABI_wchar_t:
       val = read_uleb128 (p, &len);
       p += len;
+      printf ("  Tag_ABI_wchar_t: ");
+      switch (val)
+       {
+       case 0:
+         printf (_("Not used\n"));
+         break;
+       case 1:
+         printf (_("2 bytes\n"));
+         break;
+       case 2:
+         printf (_("4 bytes\n"));
+         break;
+       default:
+         printf ("??? (%d)\n", val);
+         break;
+       }
+      return p;
+
+    case Tag_ABI_stack_align_needed:
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("  Tag_ABI_stack_align_needed: ");
+      switch (val)
+       {
+       case 0:
+         printf (_("8-byte\n"));
+         break;
+       case 1:
+         printf (_("16-byte\n"));
+         break;
+       default:
+         printf ("??? (%d)\n", val);
+         break;
+       }
+      return p;
+
+    case Tag_ABI_stack_align_preserved:
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("  Tag_ABI_stack_align_preserved: ");
+      switch (val)
+       {
+       case 0:
+         printf (_("8-byte\n"));
+         break;
+       case 1:
+         printf (_("16-byte\n"));
+         break;
+       default:
+         printf ("??? (%d)\n", val);
+         break;
+       }
+      return p;
+
+    case Tag_ABI_DSBT:
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("  Tag_ABI_DSBT: ");
+      switch (val)
+       {
+       case 0:
+         printf (_("DSBT addressing not used\n"));
+         break;
+       case 1:
+         printf (_("DSBT addressing used\n"));
+         break;
+       default:
+         printf ("??? (%d)\n", val);
+         break;
+       }
+      return p;
+
+    case Tag_ABI_PID:
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("  Tag_ABI_PID: ");
+      switch (val)
+       {
+       case 0:
+         printf (_("Data addressing position-dependent\n"));
+         break;
+       case 1:
+         printf (_("Data addressing position-independent, GOT near DP\n"));
+         break;
+       case 2:
+         printf (_("Data addressing position-independent, GOT far from DP\n"));
+         break;
+       default:
+         printf ("??? (%d)\n", val);
+         break;
+       }
+      return p;
+
+    case Tag_ABI_PIC:
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("  Tag_ABI_PIC: ");
+      switch (val)
+       {
+       case 0:
+         printf (_("Code addressing position-dependent\n"));
+         break;
+       case 1:
+         printf (_("Code addressing position-independent\n"));
+         break;
+       default:
+         printf ("??? (%d)\n", val);
+         break;
+       }
+      return p;
+
+    case Tag_ABI_array_object_alignment:
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("  Tag_ABI_array_object_alignment: ");
+      switch (val)
+       {
+       case 0:
+         printf (_("8-byte\n"));
+         break;
+       case 1:
+         printf (_("4-byte\n"));
+         break;
+       case 2:
+         printf (_("16-byte\n"));
+         break;
+       default:
+         printf ("??? (%d)\n", val);
+         break;
+       }
+      return p;
+
+    case Tag_ABI_array_object_align_expected:
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("  Tag_ABI_array_object_align_expected: ");
+      switch (val)
+       {
+       case 0:
+         printf (_("8-byte\n"));
+         break;
+       case 1:
+         printf (_("4-byte\n"));
+         break;
+       case 2:
+         printf (_("16-byte\n"));
+         break;
+       default:
+         printf ("??? (%d)\n", val);
+         break;
+       }
+      return p;
+
+    case Tag_ABI_compatibility:
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("  Tag_ABI_compatibility: ");
       printf (_("flag = %d, vendor = %s\n"), val, p);
       p += strlen ((char *) p) + 1;
       return p;
+
+    case Tag_ABI_conformance:
+      printf ("  Tag_ABI_conformance: ");
+      printf ("\"%s\"\n", p);
+      p += strlen ((char *) p) + 1;
+      return p;
     }
 
   printf ("  Tag_unknown_%d: ", tag);
 
-  /* No general documentation of handling unknown attributes, treat as
-     ULEB128 for now.  */
-  val = read_uleb128 (p, &len);
-  p += len;
-  printf ("%d (0x%x)\n", val, val);
+  if (tag & 1)
+    {
+      printf ("\"%s\"\n", p);
+      p += strlen ((char *) p) + 1;
+    }
+  else
+    {
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("%d (0x%x)\n", val, val);
+    }
 
   return p;
 }
@@ -11795,7 +12094,7 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
 
   pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length,
                                            _("notes"));
-  if (!pnotes)
+  if (pnotes == NULL)
     return 0;
 
   external = pnotes;
@@ -11819,7 +12118,8 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
 
       next = (Elf_External_Note *) (inote.descdata + align_power (inote.descsz, 2));
 
-      if (((char *) next) > (((char *) pnotes) + length))
+      if (   ((char *) next > ((char *) pnotes) + length)
+         || ((char *) next <  (char *) pnotes))
        {
          warn (_("corrupt note found at offset %lx into core notes\n"),
                (unsigned long) ((char *) external - (char *) pnotes));
@@ -11830,6 +12130,17 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
 
       external = next;
 
+      /* Prevent out-of-bounds indexing.  */
+      if (inote.namedata + inote.namesz >= (char *) pnotes + length
+         || inote.namedata + inote.namesz < inote.namedata)
+        {
+          warn (_("corrupt note found at offset %lx into core notes\n"),
+                (unsigned long) ((char *) external - (char *) pnotes));
+          warn (_(" type: %lx, namesize: %08lx, descsize: %08lx\n"),
+                inote.type, inote.namesz, inote.descsz);
+          break;
+        }
+
       /* Verify that name is null terminated.  It appears that at least
         one version of Linux (RedHat 6.0) generates corefiles that don't
         comply with the ELF spec by failing to include the null byte in
@@ -12536,7 +12847,8 @@ get_archive_member_name (struct archive_info *  arch,
 
   /* We have a normal (short) name.  */
   j = 0;
-  while ((arch->arhdr.ar_name[j] != '/') && (j < 16))
+  while ((arch->arhdr.ar_name[j] != '/')
+        && (j < sizeof (arch->arhdr.ar_name) - 1))
     j++;
   arch->arhdr.ar_name[j] = '\0';
   return arch->arhdr.ar_name;