]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - binutils/readelf.c
2011-10-13 Nick Clifton <nickc@redhat.com>
[thirdparty/binutils-gdb.git] / binutils / readelf.c
index 6c8b9668d2c3ad9860ae39dcb90798259f7b2413..f6fd38d2f83d179cdc798069c44f4874b3de0ef9 100644 (file)
 #include "elf/sparc.h"
 #include "elf/spu.h"
 #include "elf/tic6x.h"
+#include "elf/tilegx.h"
+#include "elf/tilepro.h"
 #include "elf/v850.h"
 #include "elf/vax.h"
 #include "elf/x86-64.h"
@@ -269,9 +271,9 @@ print_mode;
 
 #define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag)) /* Reverse order!  */
 
-#define GET_ELF_SYMBOLS(file, section)                 \
-  (is_32bit_elf ? get_32bit_elf_symbols (file, section)        \
-   : get_64bit_elf_symbols (file, section))
+#define GET_ELF_SYMBOLS(file, section, sym_count)                      \
+  (is_32bit_elf ? get_32bit_elf_symbols (file, section, sym_count)     \
+   : get_64bit_elf_symbols (file, section, sym_count))
 
 #define VALID_DYNAMIC_NAME(offset)     ((dynamic_strings != NULL) && (offset < dynamic_strings_length))
 /* GET_DYNAMIC_NAME asssumes that VALID_DYNAMIC_NAME has
@@ -286,6 +288,12 @@ print_mode;
     }                                          \
   while (0)
 \f
+/* Retrieve NMEMB structures, each SIZE bytes long from FILE starting at OFFSET.
+   Put the retrieved data into VAR, if it is not NULL.  Otherwise allocate a buffer
+   using malloc and fill that.  In either case return the pointer to the start of
+   the retrieved data or NULL if something went wrong.  If something does go wrong
+   emit an error message using REASON as part of the context.  */
+
 static void *
 get_data (void * var, FILE * file, long offset, size_t size, size_t nmemb,
          const char * reason)
@@ -592,11 +600,14 @@ guess_is_rela (unsigned int e_machine)
     case EM_SPARCV9:
     case EM_SPU:
     case EM_TI_C6000:
+    case EM_TILEGX:
+    case EM_TILEPRO:
     case EM_V850:
     case EM_CYGNUS_V850:
     case EM_VAX:
     case EM_X86_64:
     case EM_L1OM:
+    case EM_K1OM:
     case EM_XSTORMY16:
     case EM_XTENSA:
     case EM_XTENSA_OLD:
@@ -643,7 +654,7 @@ slurp_rela_relocs (FILE * file,
       Elf32_External_Rela * erelas;
 
       erelas = (Elf32_External_Rela *) get_data (NULL, file, rel_offset, 1,
-                                                 rel_size, _("relocs"));
+                                                 rel_size, _("32-bit relocation data"));
       if (!erelas)
        return 0;
 
@@ -673,7 +684,7 @@ slurp_rela_relocs (FILE * file,
       Elf64_External_Rela * erelas;
 
       erelas = (Elf64_External_Rela *) get_data (NULL, file, rel_offset, 1,
-                                                 rel_size, _("relocs"));
+                                                 rel_size, _("64-bit relocation data"));
       if (!erelas)
        return 0;
 
@@ -741,7 +752,7 @@ slurp_rel_relocs (FILE * file,
       Elf32_External_Rel * erels;
 
       erels = (Elf32_External_Rel *) get_data (NULL, file, rel_offset, 1,
-                                               rel_size, _("relocs"));
+                                               rel_size, _("32-bit relocation data"));
       if (!erels)
        return 0;
 
@@ -770,7 +781,7 @@ slurp_rel_relocs (FILE * file,
       Elf64_External_Rel * erels;
 
       erels = (Elf64_External_Rel *) get_data (NULL, file, rel_offset, 1,
-                                               rel_size, _("relocs"));
+                                               rel_size, _("64-bit relocation data"));
       if (!erels)
        return 0;
 
@@ -1128,6 +1139,7 @@ dump_relocations (FILE * file,
 
        case EM_X86_64:
        case EM_L1OM:
+       case EM_K1OM:
          rtype = elf_x86_64_reloc_type (type);
          break;
 
@@ -1213,6 +1225,14 @@ dump_relocations (FILE * file,
        case EM_TI_C6000:
          rtype = elf_tic6x_reloc_type (type);
          break;
+
+       case EM_TILEGX:
+         rtype = elf_tilegx_reloc_type (type);
+         break;
+
+       case EM_TILEPRO:
+         rtype = elf_tilepro_reloc_type (type);
+         break;
        }
 
       if (rtype == NULL)
@@ -1313,7 +1333,8 @@ dump_relocations (FILE * file,
                               && psym->st_shndx == SHN_MIPS_SUNDEFINED)
                        sec_name = "SUNDEF";
                      else if ((elf_header.e_machine == EM_X86_64
-                               || elf_header.e_machine == EM_L1OM)
+                               || elf_header.e_machine == EM_L1OM
+                               || elf_header.e_machine == EM_K1OM)
                               && psym->st_shndx == SHN_X86_64_LCOMMON)
                        sec_name = "LARGE_COMMON";
                      else if (elf_header.e_machine == EM_IA_64
@@ -1881,6 +1902,7 @@ get_machine_name (unsigned e_machine)
     case EM_PRISM:             return "Vitesse Prism";
     case EM_X86_64:            return "Advanced Micro Devices X86-64";
     case EM_L1OM:              return "Intel L1OM";
+    case EM_K1OM:              return "Intel K1OM";
     case EM_S390_OLD:
     case EM_S390:              return "IBM S/390";
     case EM_SCORE:             return "SUNPLUS S+Core";
@@ -1959,6 +1981,7 @@ get_machine_name (unsigned e_machine)
     case EM_STM8:              return "STMicroeletronics STM8 8-bit microcontroller";
     case EM_TILE64:            return "Tilera TILE64 multicore architecture family";
     case EM_TILEPRO:           return "Tilera TILEPro multicore architecture family";
+    case EM_TILEGX:            return "Tilera TILE-Gx multicore architecture family";
     case EM_CUDA:              return "NVIDIA CUDA architecture";
     default:
       snprintf (buff, sizeof (buff), _("<unknown>: 0x%x"), e_machine);
@@ -2405,6 +2428,9 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
          if (e_flags & EF_MIPS_ARCH_ASE_M16)
            strcat (buf, ", mips16");
 
+         if (e_flags & EF_MIPS_ARCH_ASE_MICROMIPS)
+           strcat (buf, ", micromips");
+
          switch ((e_flags & EF_MIPS_ARCH))
            {
            case E_MIPS_ARCH_1: strcat (buf, ", mips1"); break;
@@ -2569,14 +2595,19 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
            strcat (buf, ", 64-bit doubles");
          if (e_flags & E_FLAG_RX_DSP)
            strcat (buf, ", dsp");
+         if (e_flags & E_FLAG_RX_PID)
+           strcat (buf, ", pid");        
+         break;
 
        case EM_S390:
          if (e_flags & EF_S390_HIGH_GPRS)
            strcat (buf, ", highgprs");
+         break;
 
        case EM_TI_C6000:
          if ((e_flags & EF_C6000_REL))
            strcat (buf, ", relocatable module");
+         break;
        }
     }
 
@@ -2593,8 +2624,7 @@ get_osabi_name (unsigned int osabi)
     case ELFOSABI_NONE:                return "UNIX - System V";
     case ELFOSABI_HPUX:                return "UNIX - HP-UX";
     case ELFOSABI_NETBSD:      return "UNIX - NetBSD";
-    case ELFOSABI_LINUX:       return "UNIX - Linux";
-    case ELFOSABI_HURD:                return "GNU/Hurd";
+    case ELFOSABI_GNU:         return "UNIX - GNU";
     case ELFOSABI_SOLARIS:     return "UNIX - Solaris";
     case ELFOSABI_AIX:         return "UNIX - AIX";
     case ELFOSABI_IRIX:                return "UNIX - IRIX";
@@ -3025,6 +3055,7 @@ get_section_type_name (unsigned int sh_type)
              break;
            case EM_X86_64:
            case EM_L1OM:
+           case EM_K1OM:
              result = get_x86_64_section_type_name (sh_type);
              break;
            case EM_ARM:
@@ -3065,7 +3096,9 @@ get_section_type_name (unsigned int sh_type)
       else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
        sprintf (buff, "LOUSER+%x", sh_type - SHT_LOUSER);
       else
-       snprintf (buff, sizeof (buff), _("<unknown>: %x"), sh_type);
+       /* This message is probably going to be displayed in a 15
+          character wide field, so put the hex value first.  */
+       snprintf (buff, sizeof (buff), _("%08x: <unknown>"), sh_type);
 
       return buff;
     }
@@ -4017,11 +4050,13 @@ get_64bit_section_headers (FILE * file, unsigned int num)
 }
 
 static Elf_Internal_Sym *
-get_32bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
+get_32bit_elf_symbols (FILE * file,
+                      Elf_Internal_Shdr * section,
+                      unsigned long * num_syms_return)
 {
-  unsigned long number;
+  unsigned long number = 0;
   Elf32_External_Sym * esyms = NULL;
-  Elf_External_Sym_Shndx * shndx;
+  Elf_External_Sym_Shndx * shndx = NULL;
   Elf_Internal_Sym * isyms = NULL;
   Elf_Internal_Sym * psym;
   unsigned int j;
@@ -4030,7 +4065,7 @@ get_32bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
   if (section->sh_entsize == 0)
     {
       error (_("sh_entsize is zero\n"));
-      return NULL;
+      goto exit_point;
     }
 
   number = section->sh_size / section->sh_entsize;
@@ -4038,13 +4073,13 @@ get_32bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
   if (number * sizeof (Elf32_External_Sym) > section->sh_size + 1)
     {
       error (_("Invalid sh_entsize\n"));
-      return NULL;
+      goto exit_point;
     }
 
   esyms = (Elf32_External_Sym *) get_data (NULL, file, section->sh_offset, 1,
                                            section->sh_size, _("symbols"));
   if (esyms == NULL)
-    return NULL;
+    goto exit_point;
 
   shndx = NULL;
   if (symtab_shndx_hdr != NULL
@@ -4054,7 +4089,7 @@ get_32bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
       shndx = (Elf_External_Sym_Shndx *) get_data (NULL, file,
                                                    symtab_shndx_hdr->sh_offset,
                                                    1, symtab_shndx_hdr->sh_size,
-                                                   _("symtab shndx"));
+                                                   _("symbol table section indicies"));
       if (shndx == NULL)
        goto exit_point;
     }
@@ -4083,21 +4118,26 @@ get_32bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
     }
 
  exit_point:
-  if (shndx)
+  if (shndx != NULL)
     free (shndx);
-  if (esyms)
+  if (esyms != NULL)
     free (esyms);
 
+  if (num_syms_return != NULL)
+    * num_syms_return = isyms == NULL ? 0 : number;
+
   return isyms;
 }
 
 static Elf_Internal_Sym *
-get_64bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
+get_64bit_elf_symbols (FILE * file,
+                      Elf_Internal_Shdr * section,
+                      unsigned long * num_syms_return)
 {
-  unsigned long number;
-  Elf64_External_Sym * esyms;
-  Elf_External_Sym_Shndx * shndx;
-  Elf_Internal_Sym * isyms;
+  unsigned long number = 0;
+  Elf64_External_Sym * esyms = NULL;
+  Elf_External_Sym_Shndx * shndx = NULL;
+  Elf_Internal_Sym * isyms = NULL;
   Elf_Internal_Sym * psym;
   unsigned int j;
 
@@ -4105,7 +4145,7 @@ get_64bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
   if (section->sh_entsize == 0)
     {
       error (_("sh_entsize is zero\n"));
-      return NULL;
+      goto exit_point;
     }
 
   number = section->sh_size / section->sh_entsize;
@@ -4113,15 +4153,14 @@ get_64bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
   if (number * sizeof (Elf64_External_Sym) > section->sh_size + 1)
     {
       error (_("Invalid sh_entsize\n"));
-      return NULL;
+      goto exit_point;
     }
 
   esyms = (Elf64_External_Sym *) get_data (NULL, file, section->sh_offset, 1,
                                            section->sh_size, _("symbols"));
   if (!esyms)
-    return NULL;
+    goto exit_point;
 
-  shndx = NULL;
   if (symtab_shndx_hdr != NULL
       && (symtab_shndx_hdr->sh_link
          == (unsigned long) (section - section_headers)))
@@ -4129,12 +4168,9 @@ get_64bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
       shndx = (Elf_External_Sym_Shndx *) get_data (NULL, file,
                                                    symtab_shndx_hdr->sh_offset,
                                                    1, symtab_shndx_hdr->sh_size,
-                                                   _("symtab shndx"));
-      if (!shndx)
-       {
-         free (esyms);
-         return NULL;
-       }
+                                                   _("symbol table section indicies"));
+      if (shndx == NULL)
+       goto exit_point;
     }
 
   isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
@@ -4142,32 +4178,34 @@ get_64bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
   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_info  = BYTE_GET (esyms[j].st_info);
       psym->st_other = BYTE_GET (esyms[j].st_other);
       psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
+
       if (psym->st_shndx == (SHN_XINDEX & 0xffff) && shndx != NULL)
        psym->st_shndx
          = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j]));
       else if (psym->st_shndx >= (SHN_LORESERVE & 0xffff))
        psym->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
+
       psym->st_value = BYTE_GET (esyms[j].st_value);
       psym->st_size  = BYTE_GET (esyms[j].st_size);
     }
 
-  if (shndx)
+ exit_point:
+  if (shndx != NULL)
     free (shndx);
-  free (esyms);
+  if (esyms != NULL)
+    free (esyms);
+
+  if (num_syms_return != NULL)
+    * num_syms_return = isyms == NULL ? 0 : number;
 
   return isyms;
 }
@@ -4274,6 +4312,7 @@ get_elf_section_flags (bfd_vma sh_flags)
                case EM_486:
                case EM_X86_64:
                case EM_L1OM:
+               case EM_K1OM:
                case EM_OLD_SPARCV9:
                case EM_SPARC32PLUS:
                case EM_SPARCV9:
@@ -4325,7 +4364,8 @@ get_elf_section_flags (bfd_vma sh_flags)
 
            default:
              if ((elf_header.e_machine == EM_X86_64
-                  || elf_header.e_machine == EM_L1OM)
+                  || elf_header.e_machine == EM_L1OM
+                  || elf_header.e_machine == EM_K1OM)
                  && flag == SHF_X86_64_LARGE)
                *p = 'l';
              else if (flag & SHF_MASKOS)
@@ -4533,8 +4573,7 @@ process_section_headers (FILE * file)
            }
 
          CHECK_ENTSIZE (section, i, Sym);
-         num_dynamic_syms = section->sh_size / section->sh_entsize;
-         dynamic_symbols = GET_ELF_SYMBOLS (file, section);
+         dynamic_symbols = GET_ELF_SYMBOLS (file, section, & num_dynamic_syms);
        }
       else if (section->sh_type == SHT_STRTAB
               && streq (name, ".dynstr"))
@@ -4548,7 +4587,7 @@ process_section_headers (FILE * file)
          dynamic_strings = (char *) get_data (NULL, file, section->sh_offset,
                                                1, section->sh_size,
                                                _("dynamic strings"));
-         dynamic_strings_length = section->sh_size;
+         dynamic_strings_length = dynamic_strings == NULL ? 0 : section->sh_size;
        }
       else if (section->sh_type == SHT_SYMTAB_SHNDX)
        {
@@ -4590,6 +4629,7 @@ process_section_headers (FILE * file)
              || (do_debug_ranges   && streq (name, "ranges"))
              || (do_debug_frames   && streq (name, "frame"))
              || (do_debug_macinfo  && streq (name, "macinfo"))
+             || (do_debug_macinfo  && streq (name, "macro"))
              || (do_debug_str      && streq (name, "str"))
              || (do_debug_loc      && streq (name, "loc"))
              )
@@ -4715,6 +4755,7 @@ process_section_headers (FILE * file)
                case EM_486:
                case EM_X86_64:
                case EM_L1OM:
+               case EM_K1OM:
                case EM_OLD_SPARCV9:
                case EM_SPARC32PLUS:
                case EM_SPARCV9:
@@ -4843,7 +4884,8 @@ process_section_headers (FILE * file)
   if (!do_section_details)
     {
       if (elf_header.e_machine == EM_X86_64
-         || elf_header.e_machine == EM_L1OM)
+         || 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\
@@ -4886,6 +4928,7 @@ process_section_groups (FILE * file)
   Elf_Internal_Shdr * symtab_sec;
   Elf_Internal_Shdr * strtab_sec;
   Elf_Internal_Sym * symtab;
+  unsigned long num_syms;
   char * strtab;
   size_t strtab_size;
 
@@ -4943,6 +4986,7 @@ process_section_groups (FILE * file)
   symtab_sec = NULL;
   strtab_sec = NULL;
   symtab = NULL;
+  num_syms = 0;
   strtab = NULL;
   strtab_size = 0;
   for (i = 0, section = section_headers, group = section_groups;
@@ -4973,7 +5017,7 @@ process_section_groups (FILE * file)
              symtab_sec = sec;
              if (symtab)
                free (symtab);
-             symtab = GET_ELF_SYMBOLS (file, symtab_sec);
+             symtab = GET_ELF_SYMBOLS (file, symtab_sec, & num_syms);
            }
 
          if (symtab == NULL)
@@ -4982,6 +5026,12 @@ process_section_groups (FILE * file)
              continue;
            }
 
+         if (section->sh_info >= num_syms)
+           {
+             error (_("Bad sh_info in group section `%s'\n"), name);
+             continue;
+           }
+
          sym = symtab + section->sh_info;
 
          if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
@@ -5029,6 +5079,8 @@ process_section_groups (FILE * file)
          start = (unsigned char *) get_data (NULL, file, section->sh_offset,
                                               1, section->sh_size,
                                               _("section data"));
+         if (start == NULL)
+           continue;
 
          indices = start;
          size = (section->sh_size / section->sh_entsize) - 1;
@@ -5190,7 +5242,7 @@ dump_ia64_vms_dynamic_relocs (FILE *file, struct ia64_vms_dynimgrela *imgrela)
 
   imrs = get_data (NULL, file, dynamic_addr + imgrela->img_rela_off,
                   1, imgrela->img_rela_cnt * sizeof (*imrs),
-                  _("dynamic section image relas"));
+                  _("dynamic section image relocations"));
   if (!imrs)
     return;
 
@@ -5396,7 +5448,7 @@ process_relocs (FILE * file)
              if (string_table == NULL)
                printf ("%d", section->sh_name);
              else
-               printf (_("'%s'"), SECTION_NAME (section));
+               printf ("'%s'", SECTION_NAME (section));
 
              printf (_(" at offset 0x%lx contains %lu entries:\n"),
                 rel_offset, (unsigned long) (rel_size / section->sh_entsize));
@@ -5417,8 +5469,7 @@ process_relocs (FILE * file)
                      && symsec->sh_type != SHT_DYNSYM)
                     continue;
 
-                 nsyms = symsec->sh_size / symsec->sh_entsize;
-                 symtab = GET_ELF_SYMBOLS (file, symsec);
+                 symtab = GET_ELF_SYMBOLS (file, symsec, & nsyms);
 
                  if (symtab == NULL)
                    continue;
@@ -5730,10 +5781,10 @@ ia64_process_unwind (FILE * file)
       if (sec->sh_type == SHT_SYMTAB
          && sec->sh_link < elf_header.e_shnum)
        {
-         aux.nsyms = sec->sh_size / sec->sh_entsize;
-         aux.symtab = GET_ELF_SYMBOLS (file, sec);
+         aux.symtab = GET_ELF_SYMBOLS (file, sec, & aux.nsyms);
 
          strsec = section_headers + sec->sh_link;
+         assert (aux.strtab == NULL);
          aux.strtab = (char *) get_data (NULL, file, strsec->sh_offset,
                                           1, strsec->sh_size,
                                           _("string table"));
@@ -5816,11 +5867,11 @@ ia64_process_unwind (FILE * file)
        }
       else
        {
-         aux.info_size = sec->sh_size;
          aux.info_addr = sec->sh_addr;
          aux.info = (unsigned char *) get_data (NULL, file, sec->sh_offset, 1,
-                                                 aux.info_size,
+                                                 sec->sh_size,
                                                  _("unwind info"));
+         aux.info_size = aux.info == NULL ? 0 : sec->sh_size;
 
          printf (_("\nUnwind section "));
 
@@ -6143,10 +6194,10 @@ hppa_process_unwind (FILE * file)
       if (sec->sh_type == SHT_SYMTAB
          && sec->sh_link < elf_header.e_shnum)
        {
-         aux.nsyms = sec->sh_size / sec->sh_entsize;
-         aux.symtab = GET_ELF_SYMBOLS (file, sec);
+         aux.symtab = GET_ELF_SYMBOLS (file, sec, & aux.nsyms);
 
          strsec = section_headers + sec->sh_link;
+         assert (aux.strtab == NULL);
          aux.strtab = (char *) get_data (NULL, file, strsec->sh_offset,
                                           1, strsec->sh_size,
                                           _("string table"));
@@ -6273,7 +6324,6 @@ arm_section_get_word (struct arm_unw_aux_info *aux,
       arm_sec->sec = sec;
       arm_sec->data = get_data (NULL, aux->file, sec->sh_offset, 1,
                                sec->sh_size, _("unwind data"));
-
       arm_sec->rela = NULL;
       arm_sec->nrelas = 0;
 
@@ -6663,12 +6713,12 @@ decode_tic6x_unwind_bytecode (struct arm_unw_aux_info *aux,
       op = word >> 24;
       word <<= 8;
 
-      printf (_("  0x%02x "), op);
+      printf ("  0x%02x ", op);
 
       if ((op & 0xc0) == 0x00)
        {
          int offset = ((op & 0x3f) << 3) + 8;
-         printf (_("     sp = sp + %d"), offset);
+         printf ("     sp = sp + %d", offset);
        }
       else if ((op & 0xc0) == 0x80)
        {
@@ -7028,10 +7078,10 @@ arm_process_unwind (FILE *file)
     {
       if (sec->sh_type == SHT_SYMTAB && sec->sh_link < elf_header.e_shnum)
        {
-         aux.nsyms = sec->sh_size / sec->sh_entsize;
-         aux.symtab = GET_ELF_SYMBOLS (file, sec);
+         aux.symtab = GET_ELF_SYMBOLS (file, sec, & aux.nsyms);
 
          strsec = section_headers + sec->sh_link;
+         assert (aux.strtab == NULL);
          aux.strtab = get_data (NULL, file, strsec->sh_offset,
                                 1, strsec->sh_size, _("string table"));
          aux.strtab_size = aux.strtab != NULL ? strsec->sh_size : 0;
@@ -7489,14 +7539,12 @@ process_dynamic_section (FILE * file)
          else
            section.sh_entsize = sizeof (Elf64_External_Sym);
 
-         num_dynamic_syms = section.sh_size / section.sh_entsize;
+         dynamic_symbols = GET_ELF_SYMBOLS (file, &section, & num_dynamic_syms);
          if (num_dynamic_syms < 1)
            {
              error (_("Unable to determine the number of symbols to load\n"));
              continue;
            }
-
-         dynamic_symbols = GET_ELF_SYMBOLS (file, &section);
        }
     }
 
@@ -7541,7 +7589,7 @@ process_dynamic_section (FILE * file)
          dynamic_strings = (char *) get_data (NULL, file, offset, 1,
                                                str_tab_len,
                                                _("dynamic string table"));
-         dynamic_strings_length = str_tab_len;
+         dynamic_strings_length = dynamic_strings == NULL ? 0 : str_tab_len;
          break;
        }
     }
@@ -8079,9 +8127,9 @@ process_version_sections (FILE * file)
            edefs = (Elf_External_Verdef *)
                 get_data (NULL, file, section->sh_offset, 1,section->sh_size,
                           _("version definition section"));
-           endbuf = (char *) edefs + section->sh_size;
            if (!edefs)
              break;
+           endbuf = (char *) edefs + section->sh_size;
 
            for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
              {
@@ -8197,10 +8245,10 @@ process_version_sections (FILE * file)
            eneed = (Elf_External_Verneed *) get_data (NULL, file,
                                                        section->sh_offset, 1,
                                                        section->sh_size,
-                                                       _("version need section"));
-           endbuf = (char *) eneed + section->sh_size;
+                                                       _("Version Needs section"));
            if (!eneed)
              break;
+           endbuf = (char *) eneed + section->sh_size;
 
            for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
              {
@@ -8274,13 +8322,15 @@ process_version_sections (FILE * file)
                    isum   += aux.vna_next;
                    vstart += aux.vna_next;
                  }
+
                if (j < ent.vn_cnt)
-                 printf (_("  Version need aux past end of section\n"));
+                 warn (_("Missing Version Needs auxillary information\n"));
 
                idx += ent.vn_next;
              }
+
            if (cnt < section->sh_info)
-             printf (_("  Version need past end of section\n"));
+             warn (_("Missing Version Needs information\n"));
 
            free (eneed);
          }
@@ -8296,6 +8346,7 @@ process_version_sections (FILE * file)
            char * strtab;
            Elf_Internal_Sym * symbols;
            Elf_Internal_Shdr * string_sec;
+           unsigned long num_syms;
            long off;
 
            if (section->sh_link >= elf_header.e_shnum)
@@ -8309,7 +8360,7 @@ process_version_sections (FILE * file)
 
            found = 1;
 
-           symbols = GET_ELF_SYMBOLS (file, link_section);
+           symbols = GET_ELF_SYMBOLS (file, link_section, & num_syms);
            if (symbols == NULL)
              break;
 
@@ -8378,10 +8429,8 @@ process_version_sections (FILE * file)
                                   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))
+                        array, break to avoid an out-of-bounds read.  */
+                     if ((unsigned long)(cnt + j) >= num_syms)
                        {
                          warn (_("invalid index into symbol array\n"));
                          break;
@@ -8416,9 +8465,10 @@ process_version_sections (FILE * file)
                              Elf_External_Vernaux evna;
                              unsigned long a_off;
 
-                             get_data (&evn, file, offset, sizeof (evn), 1,
-                                       _("version need"));
-
+                             if (get_data (&evn, file, offset, sizeof (evn), 1,
+                                           _("version need")) == NULL)
+                               break;
+                             
                              ivn.vn_aux  = BYTE_GET (evn.vn_aux);
                              ivn.vn_next = BYTE_GET (evn.vn_next);
 
@@ -8426,11 +8476,17 @@ process_version_sections (FILE * file)
 
                              do
                                {
-                                 get_data (&evna, file, a_off, sizeof (evna),
-                                           1, _("version need aux (2)"));
-
-                                 ivna.vna_next  = BYTE_GET (evna.vna_next);
-                                 ivna.vna_other = BYTE_GET (evna.vna_other);
+                                 if (get_data (&evna, file, a_off, sizeof (evna),
+                                               1, _("version need aux (2)")) == NULL)
+                                   {
+                                     ivna.vna_next  = 0;
+                                     ivna.vna_other = 0;
+                                   }
+                                 else
+                                   {
+                                     ivna.vna_next  = BYTE_GET (evna.vna_next);
+                                     ivna.vna_other = BYTE_GET (evna.vna_other);
+                                   }
 
                                  a_off += ivna.vna_next;
                                }
@@ -8471,11 +8527,17 @@ process_version_sections (FILE * file)
 
                          do
                            {
-                             get_data (&evd, file, offset, sizeof (evd), 1,
-                                       _("version def"));
-
-                             ivd.vd_next = BYTE_GET (evd.vd_next);
-                             ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
+                             if (get_data (&evd, file, offset, sizeof (evd), 1,
+                                           _("version def")) == NULL)
+                               {
+                                 ivd.vd_next = 0;
+                                 ivd.vd_ndx  = 0;
+                               }
+                             else
+                               {
+                                 ivd.vd_next = BYTE_GET (evd.vd_next);
+                                 ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
+                               }
 
                              offset += ivd.vd_next;
                            }
@@ -8489,10 +8551,11 @@ process_version_sections (FILE * file)
 
                              ivd.vd_aux = BYTE_GET (evd.vd_aux);
 
-                             get_data (&evda, file,
-                                       offset - ivd.vd_next + ivd.vd_aux,
-                                       sizeof (evda), 1,
-                                       _("version def aux"));
+                             if (get_data (&evda, file,
+                                           offset - ivd.vd_next + ivd.vd_aux,
+                                           sizeof (evda), 1,
+                                           _("version def aux")) == NULL)
+                               break;
 
                              ivda.vda_name = BYTE_GET (evda.vda_name);
 
@@ -8548,8 +8611,8 @@ get_symbol_binding (unsigned int binding)
       else if (binding >= STB_LOOS && binding <= STB_HIOS)
        {
          if (binding == STB_GNU_UNIQUE
-             && (elf_header.e_ident[EI_OSABI] == ELFOSABI_LINUX
-                 /* GNU/Linux is still using the default value 0.  */
+             && (elf_header.e_ident[EI_OSABI] == ELFOSABI_GNU
+                 /* GNU is still using the default value 0.  */
                  || elf_header.e_ident[EI_OSABI] == ELFOSABI_NONE))
            return "UNIQUE";
          snprintf (buff, sizeof (buff), _("<OS specific>: %d"), binding);
@@ -8601,8 +8664,8 @@ get_symbol_type (unsigned int type)
            }
 
          if (type == STT_GNU_IFUNC
-             && (elf_header.e_ident[EI_OSABI] == ELFOSABI_LINUX
-                 /* GNU/Linux is still using the default value 0.  */
+             && (elf_header.e_ident[EI_OSABI] == ELFOSABI_GNU
+                 /* GNU is still using the default value 0.  */
                  || elf_header.e_ident[EI_OSABI] == ELFOSABI_NONE))
            return "IFUNC";
 
@@ -8632,11 +8695,20 @@ get_mips_symbol_other (unsigned int other)
 {
   switch (other)
     {
-    case STO_OPTIONAL:  return "OPTIONAL";
-    case STO_MIPS16:    return "MIPS16";
-    case STO_MIPS_PLT: return "MIPS PLT";
-    case STO_MIPS_PIC: return "MIPS PIC";
-    default:           return NULL;
+    case STO_OPTIONAL:
+      return "OPTIONAL";
+    case STO_MIPS_PLT:
+      return "MIPS PLT";
+    case STO_MIPS_PIC:
+      return "MIPS PIC";
+    case STO_MICROMIPS:
+      return "MICROMIPS";
+    case STO_MICROMIPS | STO_MIPS_PIC:
+      return "MICROMIPS, MIPS PIC";
+    case STO_MIPS16:
+      return "MIPS16";
+    default:
+      return NULL;
     }
 }
 
@@ -8745,7 +8817,8 @@ get_symbol_index_type (unsigned int type)
          && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX)
        return "ANSI_COM";
       else if ((elf_header.e_machine == EM_X86_64
-               || elf_header.e_machine == EM_L1OM)
+               || elf_header.e_machine == EM_L1OM
+               || elf_header.e_machine == EM_K1OM)
               && type == SHN_X86_64_LCOMMON)
        return "LARGE_COM";
       else if ((type == SHN_MIPS_SCOMMON
@@ -9089,6 +9162,7 @@ process_symbol_table (FILE * file)
          unsigned long int strtab_size = 0;
          Elf_Internal_Sym * symtab;
          Elf_Internal_Sym * psym;
+         unsigned long num_syms;
 
          if ((section->sh_type != SHT_SYMTAB
               && section->sh_type != SHT_DYNSYM)
@@ -9112,7 +9186,7 @@ process_symbol_table (FILE * file)
          else
            printf (_("   Num:    Value          Size Type    Bind   Vis      Ndx Name\n"));
 
-         symtab = GET_ELF_SYMBOLS (file, section);
+         symtab = GET_ELF_SYMBOLS (file, section, & num_syms);
          if (symtab == NULL)
            continue;
 
@@ -9133,9 +9207,7 @@ process_symbol_table (FILE * file)
              strtab_size = strtab != NULL ? string_sec->sh_size : 0;
            }
 
-         for (si = 0, psym = symtab;
-              si < section->sh_size / section->sh_entsize;
-              si++, psym++)
+         for (si = 0, psym = symtab; si < num_syms; si++, psym++)
            {
              printf ("%6d: ", si);
              print_vma (psym->st_value, LONG_HEX);
@@ -9153,8 +9225,8 @@ process_symbol_table (FILE * file)
              print_symbol (25, psym->st_name < strtab_size
                            ? strtab + psym->st_name : _("<corrupt>"));
 
-             if (section->sh_type == SHT_DYNSYM &&
-                 version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
+             if (section->sh_type == SHT_DYNSYM
+                 && version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
                {
                  unsigned char data[2];
                  unsigned short vers_data;
@@ -9166,8 +9238,9 @@ process_symbol_table (FILE * file)
                    (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
                     sizeof data + si * sizeof (vers_data));
 
-                 get_data (&data, file, offset + si * sizeof (vers_data),
-                           sizeof (data), 1, _("version data"));
+                 if (get_data (&data, file, offset + si * sizeof (vers_data),
+                               sizeof (data), 1, _("version data")) == NULL)
+                   break;
 
                  vers_data = byte_get (data, 2);
 
@@ -9195,8 +9268,14 @@ process_symbol_table (FILE * file)
                            {
                              unsigned long vna_off;
 
-                             get_data (&evn, file, offset, sizeof (evn), 1,
-                                       _("version need"));
+                             if (get_data (&evn, file, offset, sizeof (evn), 1,
+                                           _("version need")) == NULL)
+                               {
+                                 ivna.vna_next = 0;
+                                 ivna.vna_other = 0;
+                                 ivna.vna_name = 0;
+                                 break;
+                               }
 
                              ivn.vn_aux  = BYTE_GET (evn.vn_aux);
                              ivn.vn_next = BYTE_GET (evn.vn_next);
@@ -9207,13 +9286,20 @@ process_symbol_table (FILE * file)
                                {
                                  Elf_External_Vernaux evna;
 
-                                 get_data (&evna, file, vna_off,
-                                           sizeof (evna), 1,
-                                           _("version need aux (3)"));
-
-                                 ivna.vna_other = BYTE_GET (evna.vna_other);
-                                 ivna.vna_next  = BYTE_GET (evna.vna_next);
-                                 ivna.vna_name  = BYTE_GET (evna.vna_name);
+                                 if (get_data (&evna, file, vna_off,
+                                               sizeof (evna), 1,
+                                               _("version need aux (3)")) == NULL)
+                                   {
+                                     ivna.vna_next = 0;
+                                     ivna.vna_other = 0;
+                                     ivna.vna_name = 0;
+                                   }
+                                 else
+                                   {
+                                     ivna.vna_other = BYTE_GET (evna.vna_other);
+                                     ivna.vna_next  = BYTE_GET (evna.vna_next);
+                                     ivna.vna_name  = BYTE_GET (evna.vna_name);
+                                   }
 
                                  vna_off += ivna.vna_next;
                                }
@@ -9260,12 +9346,19 @@ process_symbol_table (FILE * file)
                                {
                                  Elf_External_Verdef evd;
 
-                                 get_data (&evd, file, off, sizeof (evd),
-                                           1, _("version def"));
-
-                                 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
-                                 ivd.vd_aux = BYTE_GET (evd.vd_aux);
-                                 ivd.vd_next = BYTE_GET (evd.vd_next);
+                                 if (get_data (&evd, file, off, sizeof (evd),
+                                               1, _("version def")) == NULL)
+                                   {
+                                     ivd.vd_ndx = 0;
+                                     ivd.vd_aux = 0;
+                                     ivd.vd_next = 0;
+                                   }
+                                 else
+                                   {
+                                     ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
+                                     ivd.vd_aux = BYTE_GET (evd.vd_aux);
+                                     ivd.vd_next = BYTE_GET (evd.vd_next);
+                                   }
 
                                  off += ivd.vd_next;
                                }
@@ -9275,8 +9368,9 @@ process_symbol_table (FILE * file)
                              off -= ivd.vd_next;
                              off += ivd.vd_aux;
 
-                             get_data (&evda, file, off, sizeof (evda),
-                                       1, _("version def aux"));
+                             if (get_data (&evda, file, off, sizeof (evda),
+                                           1, _("version def aux")) == NULL)
+                               break;
 
                              ivda.vda_name = BYTE_GET (evda.vda_name);
 
@@ -9685,6 +9779,10 @@ is_32bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 6; /* R_SPU_ADDR32 */
     case EM_TI_C6000:
       return reloc_type == 1; /* R_C6000_ABS32.  */
+    case EM_TILEGX:
+      return reloc_type == 2; /* R_TILEGX_32.  */
+    case EM_TILEPRO:
+      return reloc_type == 1; /* R_TILEPRO_32.  */
     case EM_CYGNUS_V850:
     case EM_V850:
       return reloc_type == 6; /* R_V850_ABS32.  */
@@ -9692,6 +9790,7 @@ is_32bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 1; /* R_VAX_32.  */
     case EM_X86_64:
     case EM_L1OM:
+    case EM_K1OM:
       return reloc_type == 10; /* R_X86_64_32.  */
     case EM_XC16X:
     case EM_C166:
@@ -9744,8 +9843,13 @@ is_32bit_pcrel_reloc (unsigned int reloc_type)
       return reloc_type == 6;  /* R_SPARC_DISP32.  */
     case EM_SPU:
       return reloc_type == 13; /* R_SPU_REL32.  */
+    case EM_TILEGX:
+      return reloc_type == 6; /* R_TILEGX_32_PCREL.  */
+    case EM_TILEPRO:
+      return reloc_type == 4; /* R_TILEPRO_32_PCREL.  */
     case EM_X86_64:
     case EM_L1OM:
+    case EM_K1OM:
       return reloc_type == 2;  /* R_X86_64_PC32.  */
     case EM_XTENSA_OLD:
     case EM_XTENSA:
@@ -9782,12 +9886,15 @@ is_64bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 54; /* R_SPARC_UA64.  */
     case EM_X86_64:
     case EM_L1OM:
+    case EM_K1OM:
       return reloc_type == 1; /* R_X86_64_64.  */
     case EM_S390_OLD:
     case EM_S390:
-      return reloc_type == 22; /* R_S390_64 */
+      return reloc_type == 22; /* R_S390_64.  */
+    case EM_TILEGX:
+      return reloc_type == 1; /* R_TILEGX_64.  */
     case EM_MIPS:
-      return reloc_type == 18; /* R_MIPS_64 */
+      return reloc_type == 18; /* R_MIPS_64 */
     default:
       return FALSE;
     }
@@ -9802,23 +9909,26 @@ is_64bit_pcrel_reloc (unsigned int reloc_type)
   switch (elf_header.e_machine)
     {
     case EM_ALPHA:
-      return reloc_type == 11; /* R_ALPHA_SREL64 */
+      return reloc_type == 11; /* R_ALPHA_SREL64 */
     case EM_IA_64:
-      return reloc_type == 0x4f; /* R_IA64_PCREL64LSB */
+      return reloc_type == 0x4f; /* R_IA64_PCREL64LSB */
     case EM_PARISC:
-      return reloc_type == 72; /* R_PARISC_PCREL64 */
+      return reloc_type == 72; /* R_PARISC_PCREL64 */
     case EM_PPC64:
-      return reloc_type == 44; /* R_PPC64_REL64 */
+      return reloc_type == 44; /* R_PPC64_REL64 */
     case EM_SPARC32PLUS:
     case EM_SPARCV9:
     case EM_SPARC:
-      return reloc_type == 46; /* R_SPARC_DISP64 */
+      return reloc_type == 46; /* R_SPARC_DISP64 */
     case EM_X86_64:
     case EM_L1OM:
-      return reloc_type == 24; /* R_X86_64_PC64 */
+    case EM_K1OM:
+      return reloc_type == 24; /* R_X86_64_PC64.  */
     case EM_S390_OLD:
     case EM_S390:
-      return reloc_type == 23; /* R_S390_PC64 */
+      return reloc_type == 23; /* R_S390_PC64.  */
+    case EM_TILEGX:
+      return reloc_type == 5;  /* R_TILEGX_64_PCREL.  */
     default:
       return FALSE;
     }
@@ -9906,10 +10016,13 @@ is_none_reloc (unsigned int reloc_type)
     case EM_CRIS:    /* R_CRIS_NONE.  */
     case EM_X86_64:  /* R_X86_64_NONE.  */
     case EM_L1OM:    /* R_X86_64_NONE.  */
+    case EM_K1OM:    /* 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_TILEGX:  /* R_TILEGX_NONE.  */
+    case EM_TILEPRO: /* R_TILEPRO_NONE.  */
     case EM_XC16X:
     case EM_C166:    /* R_XC16X_NONE.  */
       return reloc_type == 0;
@@ -9950,6 +10063,7 @@ apply_relocations (void * file,
       Elf_Internal_Rela * rp;
       Elf_Internal_Shdr * symsec;
       Elf_Internal_Sym * symtab;
+      unsigned long num_syms;
       Elf_Internal_Sym * sym;
 
       if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
@@ -9979,7 +10093,7 @@ apply_relocations (void * file,
        is_rela = FALSE;
 
       symsec = section_headers + relsec->sh_link;
-      symtab = GET_ELF_SYMBOLS ((FILE *) file, symsec);
+      symtab = GET_ELF_SYMBOLS ((FILE *) file, symsec, & num_syms);
 
       for (rp = relocs; rp < relocs + num_relocs; ++rp)
        {
@@ -9987,6 +10101,7 @@ apply_relocations (void * file,
          unsigned int    reloc_type;
          unsigned int    reloc_size;
          unsigned char * rloc;
+         unsigned long   sym_index;
 
          reloc_type = get_reloc_type (rp->r_info);
 
@@ -10020,7 +10135,14 @@ apply_relocations (void * file,
              continue;
            }
 
-         sym = symtab + get_reloc_symindex (rp->r_info);
+         sym_index = (unsigned long) get_reloc_symindex (rp->r_info);
+         if (sym_index >= num_syms)
+           {
+             warn (_("skipping invalid relocation symbol index 0x%lx in section %s\n"),
+                   sym_index, SECTION_NAME (section));
+             continue;
+           }
+         sym = symtab + sym_index;
 
          /* If the reloc has a symbol associated with it,
             make sure that it is of an appropriate type.
@@ -10361,12 +10483,17 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
 
   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)
+    section->size = 0;
+  else
+    {
+      section->size = sec->sh_size;
+      if (uncompress_section_contents (&section->start, &section->size))
+       sec->sh_size = section->size;
+    }
 
   if (section->start == NULL)
     return 0;
@@ -10989,6 +11116,88 @@ display_power_gnu_attribute (unsigned char * p, int tag)
   return p;
 }
 
+static void
+display_sparc_hwcaps (int mask)
+{
+  if (mask)
+    {
+      int first = 1;
+      if (mask & ELF_SPARC_HWCAP_MUL32)
+       fputs ("mul32", stdout), first = 0;
+      if (mask & ELF_SPARC_HWCAP_DIV32)
+       printf ("%sdiv32", first ? "" : "|"), first = 0;
+      if (mask & ELF_SPARC_HWCAP_FSMULD)
+       printf ("%sfsmuld", first ? "" : "|"), first = 0;
+      if (mask & ELF_SPARC_HWCAP_V8PLUS)
+       printf ("%sv8plus", first ? "" : "|"), first = 0;
+      if (mask & ELF_SPARC_HWCAP_POPC)
+       printf ("%spopc", first ? "" : "|"), first = 0;
+      if (mask & ELF_SPARC_HWCAP_VIS)
+       printf ("%svis", first ? "" : "|"), first = 0;
+      if (mask & ELF_SPARC_HWCAP_VIS2)
+       printf ("%svis2", first ? "" : "|"), first = 0;
+      if (mask & ELF_SPARC_HWCAP_ASI_BLK_INIT)
+       printf ("%sASIBlkInit", first ? "" : "|"), first = 0;
+      if (mask & ELF_SPARC_HWCAP_FMAF)
+       printf ("%sfmaf", first ? "" : "|"), first = 0;
+      if (mask & ELF_SPARC_HWCAP_VIS3)
+       printf ("%svis3", first ? "" : "|"), first = 0;
+      if (mask & ELF_SPARC_HWCAP_HPC)
+       printf ("%shpc", first ? "" : "|"), first = 0;
+      if (mask & ELF_SPARC_HWCAP_RANDOM)
+       printf ("%srandom", first ? "" : "|"), first = 0;
+      if (mask & ELF_SPARC_HWCAP_TRANS)
+       printf ("%strans", first ? "" : "|"), first = 0;
+      if (mask & ELF_SPARC_HWCAP_FJFMAU)
+       printf ("%sfjfmau", first ? "" : "|"), first = 0;
+      if (mask & ELF_SPARC_HWCAP_IMA)
+       printf ("%sima", first ? "" : "|"), first = 0;
+      if (mask & ELF_SPARC_HWCAP_ASI_CACHE_SPARING)
+       printf ("%scspare", first ? "" : "|"), first = 0;
+    }
+  else
+    fputc('0', stdout);
+  fputc('\n', stdout);
+}
+
+static unsigned char *
+display_sparc_gnu_attribute (unsigned char * p, int tag)
+{
+  int type;
+  unsigned int len;
+  int val;
+
+  if (tag == Tag_GNU_Sparc_HWCAPS)
+    {
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("  Tag_GNU_Sparc_HWCAPS: ");
+
+      display_sparc_hwcaps (val);
+      return p;
+   }
+
+  if (tag & 1)
+    type = 1; /* String.  */
+  else
+    type = 2; /* uleb128.  */
+  printf ("  Tag_unknown_%d: ", tag);
+
+  if (type == 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;
+}
+
 static unsigned char *
 display_mips_gnu_attribute (unsigned char * p, int tag)
 {
@@ -11437,6 +11646,13 @@ process_power_specific (FILE * file)
                             display_power_gnu_attribute);
 }
 
+static int
+process_sparc_specific (FILE * file)
+{
+  return process_attributes (file, NULL, SHT_GNU_ATTRIBUTES, NULL,
+                            display_sparc_gnu_attribute);
+}
+
 static int
 process_tic6x_specific (FILE * file)
 {
@@ -11577,7 +11793,7 @@ process_mips_specific (FILE * file)
       elib = (Elf32_External_Lib *) get_data (NULL, file, liblist_offset,
                                               liblistno,
                                               sizeof (Elf32_External_Lib),
-                                              _("liblist"));
+                                              _("liblist section data"));
       if (elib)
        {
          printf (_("\nSection '.liblist' contains %lu entries:\n"),
@@ -11933,7 +12149,11 @@ process_mips_specific (FILE * file)
 
       offset = offset_from_vma (file, pltgot, global_end - pltgot);
       data = (unsigned char *) get_data (NULL, file, offset,
-                                         global_end - pltgot, 1, _("GOT"));
+                                         global_end - pltgot, 1,
+                                        _("Global Offset Table data"));
+      if (data == NULL)
+       return 0;
+
       printf (_("\nPrimary GOT:\n"));
       printf (_(" Canonical gp value: "));
       print_vma (pltgot + 0x7ff0, LONG_HEX);
@@ -11974,9 +12194,14 @@ process_mips_specific (FILE * file)
 
          printf (_(" Global entries:\n"));
          printf ("  %*s %10s %*s %*s %-7s %3s %s\n",
-                 addr_size * 2, _("Address"), _("Access"),
+                 addr_size * 2, _("Address"),
+                 _("Access"),
                  addr_size * 2, _("Initial"),
-                 addr_size * 2, _("Sym.Val."), _("Type"), _("Ndx"), _("Name"));
+                 addr_size * 2, _("Sym.Val."),
+                 _("Type"),
+                 /* Note for translators: "Ndx" = abbreviated form of "Index".  */
+                 _("Ndx"), _("Name"));
+         
          sym_width = (is_32bit_elf ? 80 : 160) - 28 - addr_size * 6 - 1;
          for (i = gotsym; i < symtabno; i++)
            {
@@ -12029,8 +12254,11 @@ process_mips_specific (FILE * file)
 
       offset = offset_from_vma (file, mips_pltgot, end - mips_pltgot);
       data = (unsigned char *) get_data (NULL, file, offset, end - mips_pltgot,
-                                         1, _("PLT GOT"));
-      printf (_("\nPLT GOT:\n\n"));
+                                         1, _("Procedure Linkage Table data"));
+      if (data == NULL)
+       return 0;
+
+      printf ("\nPLT GOT:\n\n");
       printf (_(" Reserved entries:\n"));
       printf (_("  %*s %*s Purpose\n"),
              addr_size * 2, _("Address"), addr_size * 2, _("Initial"));
@@ -12099,7 +12327,7 @@ process_gnu_liblist (FILE * file)
 
          elib = (Elf32_External_Lib *)
               get_data (NULL, file, section->sh_offset, 1, section->sh_size,
-                        _("liblist"));
+                        _("liblist section data"));
 
          if (elib == NULL)
            break;
@@ -12108,8 +12336,6 @@ process_gnu_liblist (FILE * file)
          strtab = (char *) get_data (NULL, file, string_sec->sh_offset, 1,
                                       string_sec->sh_size,
                                       _("liblist string table"));
-         strtab_size = string_sec->sh_size;
-
          if (strtab == NULL
              || section->sh_entsize != sizeof (Elf32_External_Lib))
            {
@@ -12117,6 +12343,7 @@ process_gnu_liblist (FILE * file)
              free (strtab);
              break;
            }
+         strtab_size = string_sec->sh_size;
 
          printf (_("\nLibrary list section '%s' contains %lu entries:\n"),
                  SECTION_NAME (section),
@@ -12201,6 +12428,8 @@ get_note_type (unsigned e_type)
        return _("NT_S390_CTRS (s390 control registers)");
       case NT_S390_PREFIX:
        return _("NT_S390_PREFIX (s390 prefix register)");
+      case NT_ARM_VFP:
+       return _("NT_ARM_VFP (arm VFP registers)");
       case NT_PSTATUS:
        return _("NT_PSTATUS (pstatus structure)");
       case NT_FPREGS:
@@ -12266,7 +12495,7 @@ print_gnu_note (Elf_Internal_Note *pnote)
        printf (_("    Build ID: "));
        for (i = 0; i < pnote->descsz; ++i)
          printf ("%02x", pnote->descdata[i] & 0xff);
-       printf (_("\n"));
+       printf ("\n");
       }
       break;
 
@@ -12368,7 +12597,7 @@ get_netbsd_elfcore_note_type (unsigned e_type)
        }
     }
 
-  snprintf (buff, sizeof (buff), _("PT_FIRSTMACH+%d"),
+  snprintf (buff, sizeof (buff), "PT_FIRSTMACH+%d",
            e_type - NT_NETBSDCORE_FIRSTMACH);
   return buff;
 }
@@ -12422,7 +12651,7 @@ print_stapsdt_note (Elf_Internal_Note *pnote)
   print_vma (base_addr, FULL_HEX);
   printf (_(", Semaphore: "));
   print_vma (semaphore, FULL_HEX);
-  printf (_("\n"));
+  printf ("\n");
   printf (_("    Arguments: %s\n"), arg_fmt);
 
   return data == data_end;
@@ -12442,13 +12671,13 @@ get_ia64_vms_note_type (unsigned e_type)
     case NT_VMS_SRC:
       return _("NT_VMS_SRC (source files)");
     case NT_VMS_TITLE:
-      return _("NT_VMS_TITLE");
+      return "NT_VMS_TITLE";
     case NT_VMS_EIDC:
       return _("NT_VMS_EIDC (consistency check)");
     case NT_VMS_FPMODE:
       return _("NT_VMS_FPMODE (FP mode)");
     case NT_VMS_LINKTIME:
-      return _("NT_VMS_LINKTIME");
+      return "NT_VMS_LINKTIME";
     case NT_VMS_IMGNAM:
       return _("NT_VMS_IMGNAM (image name)");
     case NT_VMS_IMGID:
@@ -12460,9 +12689,9 @@ get_ia64_vms_note_type (unsigned e_type)
     case NT_VMS_GSTNAM:
       return _("NT_VMS_GSTNAM (sym table name)");
     case NT_VMS_ORIG_DYN:
-      return _("NT_VMS_ORIG_DYN");
+      return "NT_VMS_ORIG_DYN";
     case NT_VMS_PATCHTIME:
-      return _("NT_VMS_PATCHTIME");
+      return "NT_VMS_PATCHTIME";
     default:
       snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
       return buff;
@@ -12491,7 +12720,8 @@ print_ia64_vms_note (Elf_Internal_Note * pnote)
       break;
 #ifdef BFD64
     case NT_VMS_FPMODE:
-      printf (_("   FP mode: 0x%016" BFD_VMA_FMT "x\n"),
+      printf (_("   Floating Point mode: "));
+      printf ("0x%016" BFD_VMA_FMT "x\n",
               (bfd_vma)byte_get ((unsigned char *)pnote->descdata, 8));
       break;
     case NT_VMS_LINKTIME:
@@ -12510,11 +12740,11 @@ print_ia64_vms_note (Elf_Internal_Note * pnote)
       printf (_("   Major id: %u,  minor id: %u\n"),
               (unsigned) byte_get ((unsigned char *)pnote->descdata, 4),
               (unsigned) byte_get ((unsigned char *)pnote->descdata + 4, 4));
-      printf (_("   Manip date  : "));
+      printf (_("   Last modified  : "));
       print_vms_time
         ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata + 8, 8));
-      printf (_("\n"
-                "   Link flags  : 0x%016" BFD_VMA_FMT "x\n"),
+      printf (_("\n   Link flags  : "));
+      printf ("0x%016" BFD_VMA_FMT "x\n",
               (bfd_vma)byte_get ((unsigned char *)pnote->descdata + 16, 8));
       printf (_("   Header flags: 0x%08x\n"),
               (unsigned)byte_get ((unsigned char *)pnote->descdata + 24, 4));
@@ -12784,6 +13014,11 @@ process_arch_specific (FILE * file)
     case EM_PPC:
       return process_power_specific (file);
       break;
+    case EM_SPARC:
+    case EM_SPARC32PLUS:
+    case EM_SPARCV9:
+      return process_sparc_specific (file);
+      break;
     case EM_TI_C6000:
       return process_tic6x_specific (file);
       break;