]> 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 af1a00208f2e7f47c83cdffb6e7cee646506705e..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,20 +271,29 @@ 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
    already been called and verified that the string exists.  */
 #define GET_DYNAMIC_NAME(offset)       (dynamic_strings + offset)
 
-#define REMOVE_ARCH_BITS(ADDR) do {            \
-    if (elf_header.e_machine == EM_ARM)                \
-      (ADDR) &= ~1;                            \
-  } while (0)
+#define REMOVE_ARCH_BITS(ADDR)                 \
+  do                                           \
+    {                                          \
+      if (elf_header.e_machine == EM_ARM)      \
+       (ADDR) &= ~1;                           \
+    }                                          \
+  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)
@@ -589,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:
@@ -640,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;
 
@@ -670,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;
 
@@ -738,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;
 
@@ -767,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;
 
@@ -1125,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;
 
@@ -1210,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)
@@ -1301,14 +1324,17 @@ dump_relocations (FILE * file,
                        sec_name = "ABS";
                      else if (psym->st_shndx == SHN_COMMON)
                        sec_name = "COMMON";
-                     else if (elf_header.e_machine == EM_MIPS
-                              && psym->st_shndx == SHN_MIPS_SCOMMON)
+                     else if ((elf_header.e_machine == EM_MIPS
+                               && psym->st_shndx == SHN_MIPS_SCOMMON)
+                              || (elf_header.e_machine == EM_TI_C6000
+                                  && psym->st_shndx == SHN_TIC6X_SCOMMON))
                        sec_name = "SCOMMON";
                      else if (elf_header.e_machine == EM_MIPS
                               && 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
@@ -1833,7 +1859,7 @@ get_machine_name (unsigned e_machine)
     case EM_CYGNUS_M32R:
     case EM_M32R:              return "Renesas M32R (formerly Mitsubishi M32r)";
     case EM_CYGNUS_V850:
-    case EM_V850:              return "NEC v850";
+    case EM_V850:              return "Renesas v850";
     case EM_CYGNUS_MN10300:
     case EM_MN10300:           return "mn10300";
     case EM_CYGNUS_MN10200:
@@ -1876,10 +1902,11 @@ 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";
-    case EM_XSTORMY16:         return "Sanyo Xstormy16 CPU core";
+    case EM_XSTORMY16:         return "Sanyo XStormy16 CPU core";
     case EM_OPENRISC:
     case EM_OR32:              return "OpenRISC";
     case EM_ARC_A5:            return "ARC International ARCompact processor";
@@ -1954,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);
@@ -2400,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;
@@ -2564,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;
        }
     }
 
@@ -2588,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";
@@ -3020,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:
@@ -3060,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;
     }
@@ -3068,6 +3106,8 @@ get_section_type_name (unsigned int sh_type)
 
 #define OPTION_DEBUG_DUMP      512
 #define OPTION_DYN_SYMS                513
+#define OPTION_DWARF_DEPTH     514
+#define OPTION_DWARF_START     515
 
 static struct option options[] =
 {
@@ -3101,6 +3141,9 @@ static struct option options[] =
 #endif
   {"debug-dump",       optional_argument, 0, OPTION_DEBUG_DUMP},
 
+  {"dwarf-depth",      required_argument, 0, OPTION_DWARF_DEPTH},
+  {"dwarf-start",      required_argument, 0, OPTION_DWARF_START},
+
   {"version",         no_argument, 0, 'v'},
   {"wide",            no_argument, 0, 'W'},
   {"help",            no_argument, 0, 'H'},
@@ -3144,6 +3187,10 @@ usage (FILE * stream)
                =frames-interp,=str,=loc,=Ranges,=pubtypes,\n\
                =gdb_index,=trace_info,=trace_abbrev,=trace_aranges]\n\
                          Display the contents of DWARF2 debug sections\n"));
+  fprintf (stream, _("\
+  --dwarf-depth=N        Do not display DIEs at depth N or greater\n\
+  --dwarf-start=N        Display DIEs starting with N, at the same depth\n\
+                         or deeper\n"));
 #ifdef SUPPORT_DISASSEMBLY
   fprintf (stream, _("\
   -i --instruction-dump=<number|name>\n\
@@ -3350,6 +3397,20 @@ parse_args (int argc, char ** argv)
              dwarf_select_sections_by_names (optarg);
            }
          break;
+       case OPTION_DWARF_DEPTH:
+         {
+           char *cp;
+
+           dwarf_cutoff_level = strtoul (optarg, & cp, 0);
+         }
+         break;
+       case OPTION_DWARF_START:
+         {
+           char *cp;
+
+           dwarf_start_die = strtoul (optarg, & cp, 0);
+         }
+         break;
        case OPTION_DYN_SYMS:
          do_dyn_syms++;
          break;
@@ -3638,7 +3699,11 @@ process_program_headers (FILE * file)
 
   if (elf_header.e_phnum == 0)
     {
-      if (do_segments)
+      /* PR binutils/12467.  */
+      if (elf_header.e_phoff != 0)
+       warn (_("possibly corrupt ELF header - it has a non-zero program"
+               " header offset, but no program headers"));
+      else if (do_segments)
        printf (_("\nThere are no program headers in this file.\n"));
       return 0;
     }
@@ -3985,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;
@@ -3998,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;
@@ -4006,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
@@ -4022,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;
     }
@@ -4051,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;
 
@@ -4073,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;
@@ -4081,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)))
@@ -4097,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));
@@ -4110,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;
 }
@@ -4242,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:
@@ -4293,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)
@@ -4377,7 +4449,11 @@ process_section_headers (FILE * file)
 
   if (elf_header.e_shnum == 0)
     {
-      if (do_sections)
+      /* PR binutils/12467.  */
+      if (elf_header.e_shoff != 0)
+       warn (_("possibly corrupt ELF file header - it has a non-zero"
+               " section header offset, but no section headers\n"));
+      else if (do_sections)
        printf (_("\nThere are no sections in this file.\n"));
 
       return 1;
@@ -4497,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"))
@@ -4512,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)
        {
@@ -4554,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"))
              )
@@ -4679,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:
@@ -4807,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\
@@ -4850,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;
 
@@ -4860,7 +4939,7 @@ process_section_groups (FILE * file)
   if (elf_header.e_shnum == 0)
     {
       if (do_section_groups)
-       printf (_("\nThere are no sections in this file.\n"));
+       printf (_("\nThere are no sections to group in this file.\n"));
 
       return 1;
     }
@@ -4907,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;
@@ -4937,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)
@@ -4946,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)
@@ -4993,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;
@@ -5154,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;
 
@@ -5360,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));
@@ -5381,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;
@@ -5694,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"));
@@ -5780,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 "));
 
@@ -6107,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"));
@@ -6237,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;
 
@@ -6298,12 +6384,26 @@ arm_section_get_word (struct arm_unw_aux_info *aux,
       if (rp->r_offset < word_offset)
        continue;
 
-      relname = elf_arm_reloc_type (ELF32_R_TYPE (rp->r_info));
+      switch (elf_header.e_machine)
+       {
+       case EM_ARM:
+         relname = elf_arm_reloc_type (ELF32_R_TYPE (rp->r_info));
+         break;
+
+       case EM_TI_C6000:
+         relname = elf_tic6x_reloc_type (ELF32_R_TYPE (rp->r_info));
+         break;
+
+       default:
+           abort();
+       }
 
-      if (streq (relname, "R_ARM_NONE"))
+      if (streq (relname, "R_ARM_NONE")
+         || streq (relname, "R_C6000_NONE"))
        continue;
 
-      if (! streq (relname, "R_ARM_PREL31"))
+      if (!(streq (relname, "R_ARM_PREL31")
+           || streq (relname, "R_C6000_PREL31")))
        {
          warn (_("Skipping unexpected relocation type %s\n"), relname);
          continue;
@@ -6323,6 +6423,9 @@ arm_section_get_word (struct arm_unw_aux_info *aux,
       offset += sym->st_value;
       prelval = offset - (arm_sec->sec->sh_addr + rp->r_offset);
 
+      if (streq (relname, "R_C6000_PREL31"))
+       prelval >>= 1;
+
       word = (word & ~ (bfd_vma) 0x7fffffff) | (prelval & 0x7fffffff);
       addr->section = sym->st_shndx;
       addr->offset = offset;
@@ -6335,15 +6438,26 @@ arm_section_get_word (struct arm_unw_aux_info *aux,
   return 1;
 }
 
+static const char *tic6x_unwind_regnames[16] = {
+    "A15", "B15", "B14", "B13", "B12", "B11", "B10", "B3", 
+    "A14", "A13", "A12", "A11", "A10", 
+    "[invalid reg 13]", "[invalid reg 14]", "[invalid reg 15]"};
+
 static void
-decode_arm_unwind (struct arm_unw_aux_info *aux,
-                  unsigned int word, unsigned int remaining,
-                  bfd_vma data_offset, Elf_Internal_Shdr *data_sec,
-                  struct arm_section *data_arm_sec)
+decode_tic6x_unwind_regmask (unsigned int mask)
 {
-  int per_index;
-  unsigned int more_words;
-  struct absaddr addr;
+  int i;
+
+  for (i = 12; mask; mask >>= 1, i--)
+    {
+      if (mask & 1)
+       {
+         fputs (tic6x_unwind_regnames[i], stdout);
+         if (mask > 1)
+           fputs (", ", stdout);
+       }
+    }
+}
 
 #define ADVANCE                                                        \
   if (remaining == 0 && more_words)                            \
@@ -6371,77 +6485,14 @@ decode_arm_unwind (struct arm_unw_aux_info *aux,
     }                                  \
   printf ("0x%02x ", OP)
 
-  if (remaining == 0)
-    {
-      /* Fetch the first word.  */
-      if (!arm_section_get_word (aux, data_arm_sec, data_sec, data_offset,
-                                &word, &addr))
-       return;
-      remaining = 4;
-    }
-
-  if ((word & 0x80000000) == 0)
-    {
-      /* Expand prel31 for personality routine.  */
-      bfd_vma fn;
-      const char *procname;
-
-      fn = word;
-      if (fn & 0x40000000)
-       fn |= ~ (bfd_vma) 0x7fffffff;
-      fn = fn + data_sec->sh_addr + data_offset;
-
-      printf (_("  Personality routine: "));
-      procname = arm_print_vma_and_name (aux, fn, addr);
-      fputc ('\n', stdout);
-
-      /* The GCC personality routines use the standard compact
-        encoding, starting with one byte giving the number of
-        words.  */
-      if (procname != NULL
-         && (const_strneq (procname, "__gcc_personality_v0")
-             || const_strneq (procname, "__gxx_personality_v0")
-             || const_strneq (procname, "__gcj_personality_v0")
-             || const_strneq (procname, "__gnu_objc_personality_v0")))
-       {
-         remaining = 0;
-         more_words = 1;
-         ADVANCE;
-         if (!remaining)
-           {
-             printf (_("  [Truncated data]\n"));
-             return;
-           }
-         more_words = word >> 24;
-         word <<= 8;
-         remaining--;
-       }
-      else
-       return;
-    }
-  else
-    {
-      per_index = (word >> 24) & 0x7f;
-      if (per_index != 0 && per_index != 1 && per_index != 2)
-       {
-         printf (_("  [reserved compact index %d]\n"), per_index);
-         return;
-       }
-
-      printf (_("  Compact model %d\n"), per_index);
-      if (per_index == 0)
-       {
-         more_words = 0;
-         word <<= 8;
-         remaining--;
-       }
-      else
-       {
-         more_words = (word >> 16) & 0xff;
-         word <<= 16;
-         remaining -= 2;
-       }
-    }
+static void
+decode_arm_unwind_bytecode (struct arm_unw_aux_info *aux,
+                           unsigned int word, unsigned int remaining,
+                           unsigned int more_words,
+                           bfd_vma data_offset, Elf_Internal_Shdr *data_sec,
+                           struct arm_section *data_arm_sec)
+{
+  struct absaddr addr;
 
   /* Decode the unwinding instructions.  */
   while (1)
@@ -6460,11 +6511,13 @@ decode_arm_unwind (struct arm_unw_aux_info *aux,
       if ((op & 0xc0) == 0x00)
        {
          int offset = ((op & 0x3f) << 2) + 4;
+
          printf ("     vsp = vsp + %d", offset);
        }
       else if ((op & 0xc0) == 0x40)
        {
          int offset = ((op & 0x3f) << 2) + 4;
+
          printf ("     vsp = vsp - %d", offset);
        }
       else if ((op & 0xf0) == 0x80)
@@ -6503,6 +6556,7 @@ decode_arm_unwind (struct arm_unw_aux_info *aux,
          int end = 4 + (op & 0x07);
          int first = 1;
          int i;
+
          printf ("     pop {");
          for (i = 4; i <= end; i++)
            {
@@ -6532,6 +6586,7 @@ decode_arm_unwind (struct arm_unw_aux_info *aux,
              unsigned int mask = op2 & 0x0f;
              int first = 1;
              int i;
+
              printf ("pop {");
              for (i = 0; i < 12; i++)
                if (mask & (1 << i))
@@ -6550,6 +6605,7 @@ decode_arm_unwind (struct arm_unw_aux_info *aux,
          unsigned char buf[9];
          unsigned int i, len;
          unsigned long offset;
+
          for (i = 0; i < sizeof (buf); i++)
            {
              GET_OP (buf[i]);
@@ -6562,82 +6618,399 @@ decode_arm_unwind (struct arm_unw_aux_info *aux,
          offset = offset * 4 + 0x204;
          printf ("vsp = vsp + %ld", offset);
        }
-      else
+      else if (op == 0xb3 || op == 0xc8 || op == 0xc9)
        {
-         if (op == 0xb3 || op == 0xc6 || op == 0xc7 || op == 0xc8 || op == 0xc9)
-           {
-             GET_OP (op2);
-             printf (_("[unsupported two-byte opcode]"));
-           }
+         unsigned int first, last;
+
+         GET_OP (op2);
+         first = op2 >> 4;
+         last = op2 & 0x0f;
+         if (op == 0xc8)
+           first = first + 16;
+         printf ("pop {D%d", first);
+         if (last)
+           printf ("-D%d", first + last);
+         printf ("}");
+       }
+      else if ((op & 0xf8) == 0xb8 || (op & 0xf8) == 0xd0)
+       {
+         unsigned int count = op & 0x07;
+
+         printf ("pop {D8");
+         if (count)
+           printf ("-D%d", 8 + count);
+         printf ("}");
+       }
+      else if (op >= 0xc0 && op <= 0xc5)
+       {
+         unsigned int count = op & 0x07;
+
+         printf ("     pop {wR10");
+         if (count)
+           printf ("-wR%d", 10 + count);
+         printf ("}");
+       }
+      else if (op == 0xc6)
+       {
+         unsigned int first, last;
+
+         GET_OP (op2);
+         first = op2 >> 4;
+         last = op2 & 0x0f;
+         printf ("pop {wR%d", first);
+         if (last)
+           printf ("-wR%d", first + last);
+         printf ("}");
+       }
+      else if (op == 0xc7)
+       {
+         GET_OP (op2);
+         if (op2 == 0 || (op2 & 0xf0) != 0)
+           printf (_("[Spare]"));
          else
            {
-             printf (_("     [unsupported opcode]"));
+             unsigned int mask = op2 & 0x0f;
+             int first = 1;
+             int i;
+
+             printf ("pop {");
+             for (i = 0; i < 4; i++)
+               if (mask & (1 << i))
+                 {
+                   if (first)
+                     first = 0;
+                   else
+                     printf (", ");
+                   printf ("wCGR%d", i);
+                 }
+             printf ("}");
            }
        }
+      else
+       printf (_("     [unsupported opcode]"));
       printf ("\n");
     }
-
-  /* Decode the descriptors.  Not implemented.  */
 }
 
 static void
-dump_arm_unwind (struct arm_unw_aux_info *aux, Elf_Internal_Shdr *exidx_sec)
+decode_tic6x_unwind_bytecode (struct arm_unw_aux_info *aux,
+                           unsigned int word, unsigned int remaining,
+                           unsigned int more_words,
+                           bfd_vma data_offset, Elf_Internal_Shdr *data_sec,
+                           struct arm_section *data_arm_sec)
 {
-  struct arm_section exidx_arm_sec, extab_arm_sec;
-  unsigned int i, exidx_len;
-
-  memset (&exidx_arm_sec, 0, sizeof (exidx_arm_sec));
-  memset (&extab_arm_sec, 0, sizeof (extab_arm_sec));
-  exidx_len = exidx_sec->sh_size / 8;
+  struct absaddr addr;
 
-  for (i = 0; i < exidx_len; i++)
+  /* Decode the unwinding instructions.  */
+  while (1)
     {
-      unsigned int exidx_fn, exidx_entry;
-      struct absaddr fn_addr, entry_addr;
-      bfd_vma fn;
-
-      fputc ('\n', stdout);
-
-      if (!arm_section_get_word (aux, &exidx_arm_sec, exidx_sec,
-                                8 * i, &exidx_fn, &fn_addr)
-         || !arm_section_get_word (aux, &exidx_arm_sec, exidx_sec,
-                                   8 * i + 4, &exidx_entry, &entry_addr))
-       {
-         arm_free_section (&exidx_arm_sec);
-         arm_free_section (&extab_arm_sec);
-         return;
-       }
+      unsigned int op, op2;
 
-      fn = exidx_fn & 0x7fffffff;
-      if (fn & 0x40000000)
-       fn |= ~ (bfd_vma) 0x7fffffff;
-      fn = fn + exidx_sec->sh_addr + 8 * i;
+      ADVANCE;
+      if (remaining == 0)
+       break;
+      remaining--;
+      op = word >> 24;
+      word <<= 8;
 
-      arm_print_vma_and_name (aux, fn, entry_addr);
-      fputs (": ", stdout);
+      printf ("  0x%02x ", op);
 
-      if (exidx_entry == 1)
+      if ((op & 0xc0) == 0x00)
        {
-         print_vma (exidx_entry, PREFIX_HEX);
-         fputs (" [cantunwind]\n", stdout);
+         int offset = ((op & 0x3f) << 3) + 8;
+         printf ("     sp = sp + %d", offset);
        }
-      else if (exidx_entry & 0x80000000)
+      else if ((op & 0xc0) == 0x80)
        {
-         print_vma (exidx_entry, PREFIX_HEX);
-         fputc ('\n', stdout);
-         decode_arm_unwind (aux, exidx_entry, 4, 0, NULL, NULL);
+         GET_OP (op2);
+         if (op == 0x80 && op2 == 0)
+           printf (_("Refuse to unwind"));
+         else
+           {
+             unsigned int mask = ((op & 0x1f) << 8) | op2;
+             if (op & 0x20)
+               printf ("pop compact {");
+             else
+               printf ("pop {");
+
+             decode_tic6x_unwind_regmask (mask);
+             printf("}");
+           }
        }
-      else
-       {
-         bfd_vma table, table_offset = 0;
-         Elf_Internal_Shdr *table_sec;
+      else if ((op & 0xf0) == 0xc0)
+       {
+         unsigned int reg;
+         unsigned int nregs;
+         unsigned int i;
+         const char *name;
+         struct {
+             unsigned int offset;
+             unsigned int reg;
+         } regpos[16];
+
+         /* Scan entire instruction first so that GET_OP output is not
+            interleaved with disassembly.  */
+         nregs = 0;
+         for (i = 0; nregs < (op & 0xf); i++)
+           {
+             GET_OP (op2);
+             reg = op2 >> 4;
+             if (reg != 0xf)
+               {
+                 regpos[nregs].offset = i * 2;
+                 regpos[nregs].reg = reg;
+                 nregs++;
+               }
 
-         fputs ("@", stdout);
-         table = exidx_entry;
-         if (table & 0x40000000)
-           table |= ~ (bfd_vma) 0x7fffffff;
-         table = table + exidx_sec->sh_addr + 8 * i + 4;
-         print_vma (table, PREFIX_HEX);
+             reg = op2 & 0xf;
+             if (reg != 0xf)
+               {
+                 regpos[nregs].offset = i * 2 + 1;
+                 regpos[nregs].reg = reg;
+                 nregs++;
+               }
+           }
+
+         printf (_("pop frame {"));
+         reg = nregs - 1;
+         for (i = i * 2; i > 0; i--)
+           {
+             if (regpos[reg].offset == i - 1)
+               {
+                 name = tic6x_unwind_regnames[regpos[reg].reg];
+                 if (reg > 0)
+                   reg--;
+               }
+             else
+               name = _("[pad]");
+
+             fputs (name, stdout);
+             if (i > 1)
+               printf (", ");
+           }
+
+         printf ("}");
+       }
+      else if (op == 0xd0)
+       printf ("     MOV FP, SP");
+      else if (op == 0xd1)
+       printf ("     __c6xabi_pop_rts");
+      else if (op == 0xd2)
+       {
+         unsigned char buf[9];
+         unsigned int i, len;
+         unsigned long offset;
+         for (i = 0; i < sizeof (buf); i++)
+           {
+             GET_OP (buf[i]);
+             if ((buf[i] & 0x80) == 0)
+               break;
+           }
+         assert (i < sizeof (buf));
+         offset = read_uleb128 (buf, &len);
+         assert (len == i + 1);
+         offset = offset * 8 + 0x408;
+         printf (_("sp = sp + %ld"), offset);
+       }
+      else if ((op & 0xf0) == 0xe0)
+       {
+         if ((op & 0x0f) == 7)
+           printf ("     RETURN");
+         else
+           printf ("     MV %s, B3", tic6x_unwind_regnames[op & 0x0f]);
+       }
+      else
+       {
+         printf (_("     [unsupported opcode]"));
+       }
+      putchar ('\n');
+    }
+}
+
+static bfd_vma
+expand_prel31 (bfd_vma word, bfd_vma where)
+{
+  bfd_vma offset;
+
+  offset = word & 0x7fffffff;
+  if (offset & 0x40000000)
+    offset |= ~ (bfd_vma) 0x7fffffff;
+
+  if (elf_header.e_machine == EM_TI_C6000)
+    offset <<= 1;
+
+  return offset + where;
+}
+
+static void
+decode_arm_unwind (struct arm_unw_aux_info *aux,
+                  unsigned int word, unsigned int remaining,
+                  bfd_vma data_offset, Elf_Internal_Shdr *data_sec,
+                  struct arm_section *data_arm_sec)
+{
+  int per_index;
+  unsigned int more_words = 0;
+  struct absaddr addr;
+
+  if (remaining == 0)
+    {
+      /* Fetch the first word.  */
+      if (!arm_section_get_word (aux, data_arm_sec, data_sec, data_offset,
+                                &word, &addr))
+       return;
+      remaining = 4;
+    }
+
+  if ((word & 0x80000000) == 0)
+    {
+      /* Expand prel31 for personality routine.  */
+      bfd_vma fn;
+      const char *procname;
+
+      fn = expand_prel31 (word, data_sec->sh_addr + data_offset);
+      printf (_("  Personality routine: "));
+      procname = arm_print_vma_and_name (aux, fn, addr);
+      fputc ('\n', stdout);
+
+      /* The GCC personality routines use the standard compact
+        encoding, starting with one byte giving the number of
+        words.  */
+      if (procname != NULL
+         && (const_strneq (procname, "__gcc_personality_v0")
+             || const_strneq (procname, "__gxx_personality_v0")
+             || const_strneq (procname, "__gcj_personality_v0")
+             || const_strneq (procname, "__gnu_objc_personality_v0")))
+       {
+         remaining = 0;
+         more_words = 1;
+         ADVANCE;
+         if (!remaining)
+           {
+             printf (_("  [Truncated data]\n"));
+             return;
+           }
+         more_words = word >> 24;
+         word <<= 8;
+         remaining--;
+         per_index = -1;
+       }
+      else
+       return;
+    }
+  else
+    {
+      
+      per_index = (word >> 24) & 0x7f;
+      printf (_("  Compact model %d\n"), per_index);
+      if (per_index == 0)
+       {
+         more_words = 0;
+         word <<= 8;
+         remaining--;
+       }
+      else if (per_index < 3)
+       {
+         more_words = (word >> 16) & 0xff;
+         word <<= 16;
+         remaining -= 2;
+       }
+    }
+
+  switch (elf_header.e_machine)
+    {
+    case EM_ARM:
+      if (per_index < 3)
+       {
+         decode_arm_unwind_bytecode (aux, word, remaining, more_words,
+                                     data_offset, data_sec, data_arm_sec);
+       }
+      else
+       printf ("  [reserved]\n");
+      break;
+
+    case EM_TI_C6000:
+      if (per_index < 3)
+       {
+         decode_tic6x_unwind_bytecode (aux, word, remaining, more_words,
+                                     data_offset, data_sec, data_arm_sec);
+       }
+      else if (per_index < 5)
+       {
+         if (((word >> 17) & 0x7f) == 0x7f)
+           printf (_("  Restore stack from frame pointer\n"));
+         else
+           printf (_("  Stack increment %d\n"), (word >> 14) & 0x1fc);
+         printf (_("  Registers restored: "));
+         if (per_index == 4)
+           printf (" (compact) ");
+         decode_tic6x_unwind_regmask ((word >> 4) & 0x1fff);
+         putchar ('\n');
+         printf (_("  Return register: %s\n"),
+                 tic6x_unwind_regnames[word & 0xf]);
+       }
+      else
+       printf ("  [reserved]\n");
+      break;
+
+    default:
+      abort ();
+    }
+
+  /* Decode the descriptors.  Not implemented.  */
+}
+
+static void
+dump_arm_unwind (struct arm_unw_aux_info *aux, Elf_Internal_Shdr *exidx_sec)
+{
+  struct arm_section exidx_arm_sec, extab_arm_sec;
+  unsigned int i, exidx_len;
+
+  memset (&exidx_arm_sec, 0, sizeof (exidx_arm_sec));
+  memset (&extab_arm_sec, 0, sizeof (extab_arm_sec));
+  exidx_len = exidx_sec->sh_size / 8;
+
+  for (i = 0; i < exidx_len; i++)
+    {
+      unsigned int exidx_fn, exidx_entry;
+      struct absaddr fn_addr, entry_addr;
+      bfd_vma fn;
+
+      fputc ('\n', stdout);
+
+      if (!arm_section_get_word (aux, &exidx_arm_sec, exidx_sec,
+                                8 * i, &exidx_fn, &fn_addr)
+         || !arm_section_get_word (aux, &exidx_arm_sec, exidx_sec,
+                                   8 * i + 4, &exidx_entry, &entry_addr))
+       {
+         arm_free_section (&exidx_arm_sec);
+         arm_free_section (&extab_arm_sec);
+         return;
+       }
+
+      fn = expand_prel31 (exidx_fn, exidx_sec->sh_addr + 8 * i);
+
+      arm_print_vma_and_name (aux, fn, entry_addr);
+      fputs (": ", stdout);
+
+      if (exidx_entry == 1)
+       {
+         print_vma (exidx_entry, PREFIX_HEX);
+         fputs (" [cantunwind]\n", stdout);
+       }
+      else if (exidx_entry & 0x80000000)
+       {
+         print_vma (exidx_entry, PREFIX_HEX);
+         fputc ('\n', stdout);
+         decode_arm_unwind (aux, exidx_entry, 4, 0, NULL, NULL);
+       }
+      else
+       {
+         bfd_vma table, table_offset = 0;
+         Elf_Internal_Shdr *table_sec;
+
+         fputs ("@", stdout);
+         table = expand_prel31 (exidx_entry, exidx_sec->sh_addr + 8 * i + 4);
+         print_vma (table, PREFIX_HEX);
          printf ("\n");
 
          /* Locate the matching .ARM.extab.  */
@@ -6670,6 +7043,7 @@ dump_arm_unwind (struct arm_unw_aux_info *aux, Elf_Internal_Shdr *exidx_sec)
   arm_free_section (&extab_arm_sec);
 }
 
+/* Used for both ARM and C6X unwinding tables.  */
 static int
 arm_process_unwind (FILE *file)
 {
@@ -6678,10 +7052,25 @@ arm_process_unwind (FILE *file)
   Elf_Internal_Shdr *strsec;
   Elf_Internal_Shdr *sec;
   unsigned long i;
+  unsigned int sec_type;
 
   memset (& aux, 0, sizeof (aux));
   aux.file = file;
 
+  switch (elf_header.e_machine)
+    {
+    case EM_ARM:
+      sec_type = SHT_ARM_EXIDX;
+      break;
+
+    case EM_TI_C6000:
+      sec_type = SHT_C6000_UNWIND;
+      break;
+
+    default:
+       abort();
+    }
+
   if (string_table == NULL)
     return 1;
 
@@ -6689,15 +7078,15 @@ 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;
        }
-      else if (sec->sh_type == SHT_ARM_EXIDX)
+      else if (sec->sh_type == sec_type)
        unwsec = sec;
     }
 
@@ -6706,7 +7095,7 @@ arm_process_unwind (FILE *file)
 
   for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
     {
-      if (sec->sh_type == SHT_ARM_EXIDX)
+      if (sec->sh_type == sec_type)
        {
          printf (_("\nUnwind table index '%s' at offset 0x%lx contains %lu entries:\n"),
                  SECTION_NAME (sec),
@@ -6737,6 +7126,7 @@ process_unwind (FILE * file)
     { EM_ARM, arm_process_unwind },
     { EM_IA_64, ia64_process_unwind },
     { EM_PARISC, hppa_process_unwind },
+    { EM_TI_C6000, arm_process_unwind },
     { 0, 0 }
   };
   int i;
@@ -7149,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);
        }
     }
 
@@ -7201,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;
        }
     }
@@ -7739,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)
              {
@@ -7857,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)
              {
@@ -7934,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);
          }
@@ -7956,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)
@@ -7969,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;
 
@@ -7979,7 +8370,10 @@ process_version_sections (FILE * file)
                                         string_sec->sh_size,
                                         _("version string table"));
            if (!strtab)
-             break;
+             {
+               free (symbols);
+               break;
+             }
 
            printf (_("\nVersion symbols section '%s' contains %d entries:\n"),
                    SECTION_NAME (section), total);
@@ -7999,6 +8393,7 @@ process_version_sections (FILE * file)
            if (!edata)
              {
                free (strtab);
+               free (symbols);
                break;
              }
 
@@ -8034,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;
@@ -8072,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);
 
@@ -8082,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;
                                }
@@ -8127,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;
                            }
@@ -8145,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);
 
@@ -8204,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);
@@ -8257,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";
 
@@ -8288,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;
     }
 }
 
@@ -8401,11 +8817,14 @@ 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
-              && elf_header.e_machine == EM_MIPS)
+      else if ((type == SHN_MIPS_SCOMMON
+               && elf_header.e_machine == EM_MIPS)
+              || (type == SHN_TIC6X_SCOMMON
+                  && elf_header.e_machine == EM_TI_C6000))
        return "SCOM";
       else if (type == SHN_MIPS_SUNDEFINED
               && elf_header.e_machine == EM_MIPS)
@@ -8743,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)
@@ -8766,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;
 
@@ -8787,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);
@@ -8807,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;
@@ -8820,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);
 
@@ -8849,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);
@@ -8861,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;
                                }
@@ -8914,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;
                                }
@@ -8929,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);
 
@@ -9339,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.  */
@@ -9346,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:
@@ -9398,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:
@@ -9436,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;
     }
@@ -9456,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;
     }
@@ -9560,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;
@@ -9604,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)
@@ -9633,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)
        {
@@ -9641,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);
 
@@ -9674,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.
@@ -10015,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;
@@ -10643,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)
 {
@@ -11091,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)
 {
@@ -11231,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"),
@@ -11587,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);
@@ -11628,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++)
            {
@@ -11683,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"));
@@ -11753,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;
@@ -11762,14 +12336,14 @@ 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))
            {
              free (elib);
+             free (strtab);
              break;
            }
+         strtab_size = string_sec->sh_size;
 
          printf (_("\nLibrary list section '%s' contains %lu entries:\n"),
                  SECTION_NAME (section),
@@ -11809,6 +12383,7 @@ process_gnu_liblist (FILE * file)
            }
 
          free (elib);
+         free (strtab);
        }
     }
 
@@ -11853,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:
@@ -11906,6 +12483,63 @@ get_gnu_elf_note_type (unsigned e_type)
   return buff;
 }
 
+static int
+print_gnu_note (Elf_Internal_Note *pnote)
+{
+  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;
+
+       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";
+           break;
+         case GNU_ABI_TAG_NETBSD:
+           osname = "NetBSD";
+           break;
+         default:
+           osname = "Unknown";
+           break;
+         }
+
+       printf (_("    OS: %s, ABI: %ld.%ld.%ld\n"), osname,
+               major, minor, subminor);
+      }
+      break;
+    }
+
+  return 1;
+}
+
 static const char *
 get_netbsd_elfcore_note_type (unsigned e_type)
 {
@@ -11963,11 +12597,178 @@ 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;
 }
 
+static const char *
+get_stapsdt_note_type (unsigned e_type)
+{
+  static char buff[64];
+
+  switch (e_type)
+    {
+    case NT_STAPSDT:
+      return _("NT_STAPSDT (SystemTap probe descriptors)");
+
+    default:
+      break;
+    }
+
+  snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
+  return buff;
+}
+
+static int
+print_stapsdt_note (Elf_Internal_Note *pnote)
+{
+  int addr_size = is_32bit_elf ? 4 : 8;
+  char *data = pnote->descdata;
+  char *data_end = pnote->descdata + pnote->descsz;
+  bfd_vma pc, base_addr, semaphore;
+  char *provider, *probe, *arg_fmt;
+
+  pc = byte_get ((unsigned char *) data, addr_size);
+  data += addr_size;
+  base_addr = byte_get ((unsigned char *) data, addr_size);
+  data += addr_size;
+  semaphore = byte_get ((unsigned char *) data, addr_size);
+  data += addr_size;
+
+  provider = data;
+  data += strlen (data) + 1;
+  probe = data;
+  data += strlen (data) + 1;
+  arg_fmt = data;
+  data += strlen (data) + 1;
+
+  printf (_("    Provider: %s\n"), provider);
+  printf (_("    Name: %s\n"), probe);
+  printf (_("    Location: "));
+  print_vma (pc, FULL_HEX);
+  printf (_(", Base: "));
+  print_vma (base_addr, FULL_HEX);
+  printf (_(", Semaphore: "));
+  print_vma (semaphore, FULL_HEX);
+  printf ("\n");
+  printf (_("    Arguments: %s\n"), arg_fmt);
+
+  return data == data_end;
+}
+
+static const char *
+get_ia64_vms_note_type (unsigned e_type)
+{
+  static char buff[64];
+
+  switch (e_type)
+    {
+    case NT_VMS_MHD:
+      return _("NT_VMS_MHD (module header)");
+    case NT_VMS_LNM:
+      return _("NT_VMS_LNM (language name)");
+    case NT_VMS_SRC:
+      return _("NT_VMS_SRC (source files)");
+    case 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";
+    case NT_VMS_IMGNAM:
+      return _("NT_VMS_IMGNAM (image name)");
+    case NT_VMS_IMGID:
+      return _("NT_VMS_IMGID (image id)");
+    case NT_VMS_LINKID:
+      return _("NT_VMS_LINKID (link id)");
+    case NT_VMS_IMGBID:
+      return _("NT_VMS_IMGBID (build id)");
+    case NT_VMS_GSTNAM:
+      return _("NT_VMS_GSTNAM (sym table name)");
+    case NT_VMS_ORIG_DYN:
+      return "NT_VMS_ORIG_DYN";
+    case NT_VMS_PATCHTIME:
+      return "NT_VMS_PATCHTIME";
+    default:
+      snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
+      return buff;
+    }
+}
+
+static int
+print_ia64_vms_note (Elf_Internal_Note * pnote)
+{
+  switch (pnote->type)
+    {
+    case NT_VMS_MHD:
+      if (pnote->descsz > 36)
+        {
+          size_t l = strlen (pnote->descdata + 34);
+          printf (_("    Creation date  : %.17s\n"), pnote->descdata);
+          printf (_("    Last patch date: %.17s\n"), pnote->descdata + 17);
+          printf (_("    Module name    : %s\n"), pnote->descdata + 34);
+          printf (_("    Module version : %s\n"), pnote->descdata + 34 + l + 1);
+        }
+      else
+        printf (_("    Invalid size\n"));
+      break;
+    case NT_VMS_LNM:
+      printf (_("   Language: %s\n"), pnote->descdata);
+      break;
+#ifdef BFD64
+    case NT_VMS_FPMODE:
+      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:
+      printf (_("   Link time: "));
+      print_vms_time
+        ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata, 8));
+      printf ("\n");
+      break;
+    case NT_VMS_PATCHTIME:
+      printf (_("   Patch time: "));
+      print_vms_time
+        ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata, 8));
+      printf ("\n");
+      break;
+    case NT_VMS_ORIG_DYN:
+      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 (_("   Last modified  : "));
+      print_vms_time
+        ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata + 8, 8));
+      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));
+      printf (_("   Image id    : %s\n"), pnote->descdata + 32);
+      break;
+#endif
+    case NT_VMS_IMGNAM:
+      printf (_("    Image name: %s\n"), pnote->descdata);
+      break;
+    case NT_VMS_GSTNAM:
+      printf (_("    Global symbol table name: %s\n"), pnote->descdata);
+      break;
+    case NT_VMS_IMGID:
+      printf (_("    Image id: %s\n"), pnote->descdata);
+      break;
+    case NT_VMS_LINKID:
+      printf (_("    Linker id: %s\n"), pnote->descdata);
+      break;
+    default:
+      break;
+    }
+  return 1;
+}
+
 /* 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.
@@ -11999,13 +12800,28 @@ process_note (Elf_Internal_Note * pnote)
       name = "SPU";
     }
 
+  else if (const_strneq (pnote->namedata, "IPF/VMS"))
+    /* VMS/ia64-specific file notes.  */
+    nt = get_ia64_vms_note_type (pnote->type);
+
+  else if (const_strneq (pnote->namedata, "stapsdt"))
+    nt = get_stapsdt_note_type (pnote->type);
+
   else
     /* Don't recognize this note name; just use the default set of
        note type strings.  */
-      nt = get_note_type (pnote->type);
+    nt = get_note_type (pnote->type);
 
-  printf ("  %s\t\t0x%08lx\t%s\n", name, pnote->descsz, nt);
-  return 1;
+  printf ("  %-20s 0x%08lx\t%s\n", name, pnote->descsz, nt);
+
+  if (const_strneq (pnote->namedata, "IPF/VMS"))
+    return print_ia64_vms_note (pnote);
+  else if (const_strneq (pnote->namedata, "GNU"))
+    return print_gnu_note (pnote);
+  else if (const_strneq (pnote->namedata, "stapsdt"))
+    return print_stapsdt_note (pnote);
+  else
+    return 1;
 }
 
 
@@ -12028,7 +12844,7 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
 
   printf (_("\nNotes at offset 0x%08lx with length 0x%08lx:\n"),
          (unsigned long) offset, (unsigned long) length);
-  printf (_("  Owner\t\tData size\tDescription\n"));
+  printf (_("  %-20s %10s\tDescription\n"), _("Owner"), _("Data size"));
 
   while (external < (Elf_External_Note *) ((char *) pnotes + length))
     {
@@ -12036,14 +12852,32 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
       Elf_Internal_Note inote;
       char * temp = NULL;
 
-      inote.type     = BYTE_GET (external->type);
-      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.descpos  = offset + (inote.descdata - (char *) pnotes);
-
-      next = (Elf_External_Note *) (inote.descdata + align_power (inote.descsz, 2));
+      if (!is_ia64_vms ())
+        {
+          inote.type     = BYTE_GET (external->type);
+          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.descpos  = offset + (inote.descdata - (char *) pnotes);
+
+          next = (Elf_External_Note *) (inote.descdata + align_power (inote.descsz, 2));
+        }
+      else
+        {
+          Elf64_External_VMS_Note *vms_external;
+
+          vms_external = (Elf64_External_VMS_Note *)external;
+          inote.type     = BYTE_GET (vms_external->type);
+          inote.namesz   = BYTE_GET (vms_external->namesz);
+          inote.namedata = vms_external->name;
+          inote.descsz   = BYTE_GET (vms_external->descsz);
+          inote.descdata = inote.namedata + align_power (inote.namesz, 3);
+          inote.descpos  = offset + (inote.descdata - (char *) pnotes);
+
+          next = (Elf_External_Note *)
+            (inote.descdata + align_power (inote.descsz, 3));
+        }
 
       if (   ((char *) next > ((char *) pnotes) + length)
          || ((char *) next <  (char *) pnotes))
@@ -12180,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;
@@ -12303,6 +13142,7 @@ process_object (char * file_name, FILE * file)
 
   for (i = ARRAY_SIZE (dynamic_info); i--;)
     dynamic_info[i] = 0;
+  dynamic_info_DT_GNU_HASH = 0;
 
   /* Process the file.  */
   if (show_name)