* readelf.c (slurp_hppa_unwind_table): Fix entry size on hppa64-hpux.
[deliverable/binutils-gdb.git] / binutils / readelf.c
index 75be6c4d4a3f0ec9d47a1bdf55237c730e4558e7..57a6047b70b7885ec18a3eca4f602f71b48ca876 100644 (file)
@@ -19,8 +19,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 \f
 /* The difference between readelf and objdump:
 
@@ -86,6 +86,7 @@
 #include "elf/i960.h"
 #include "elf/ia64.h"
 #include "elf/ip2k.h"
+#include "elf/m32c.h"
 #include "elf/m32r.h"
 #include "elf/m68k.h"
 #include "elf/m68hc11.h"
@@ -94,6 +95,7 @@
 #include "elf/mmix.h"
 #include "elf/mn10200.h"
 #include "elf/mn10300.h"
+#include "elf/ms1.h"
 #include "elf/msp430.h"
 #include "elf/or32.h"
 #include "elf/pj.h"
 #include "libiberty.h"
 
 char *program_name = "readelf";
-long archive_file_offset;
-unsigned long archive_file_size;
-unsigned long dynamic_addr;
-bfd_size_type dynamic_size;
-unsigned int dynamic_nent;
-char *dynamic_strings;
-unsigned long dynamic_strings_length;
-char *string_table;
-unsigned long string_table_length;
-unsigned long num_dynamic_syms;
-Elf_Internal_Sym *dynamic_symbols;
-Elf_Internal_Syminfo *dynamic_syminfo;
-unsigned long dynamic_syminfo_offset;
-unsigned int dynamic_syminfo_nent;
-char program_interpreter[64];
-bfd_vma dynamic_info[DT_JMPREL + 1];
-bfd_vma version_info[16];
-Elf_Internal_Ehdr elf_header;
-Elf_Internal_Shdr *section_headers;
-Elf_Internal_Phdr *program_headers;
-Elf_Internal_Dyn *dynamic_section;
-Elf_Internal_Shdr *symtab_shndx_hdr;
-int show_name;
-int do_dynamic;
-int do_syms;
-int do_reloc;
-int do_sections;
-int do_section_groups;
-int do_segments;
-int do_unwind;
-int do_using_dynamic;
-int do_header;
-int do_dump;
-int do_version;
-int do_wide;
-int do_histogram;
-int do_debugging;
-int do_debug_info;
-int do_debug_abbrevs;
-int do_debug_lines;
-int do_debug_pubnames;
-int do_debug_aranges;
-int do_debug_ranges;
-int do_debug_frames;
-int do_debug_frames_interp;
-int do_debug_macinfo;
-int do_debug_str;
-int do_debug_loc;
-int do_arch;
-int do_notes;
-int is_32bit_elf;
-int have_frame_base;
-int need_base_address;
-bfd_vma eh_addr_size;
+static long archive_file_offset;
+static unsigned long archive_file_size;
+static unsigned long dynamic_addr;
+static bfd_size_type dynamic_size;
+static unsigned int dynamic_nent;
+static char *dynamic_strings;
+static unsigned long dynamic_strings_length;
+static char *string_table;
+static unsigned long string_table_length;
+static unsigned long num_dynamic_syms;
+static Elf_Internal_Sym *dynamic_symbols;
+static Elf_Internal_Syminfo *dynamic_syminfo;
+static unsigned long dynamic_syminfo_offset;
+static unsigned int dynamic_syminfo_nent;
+static char program_interpreter[64];
+static bfd_vma dynamic_info[DT_JMPREL + 1];
+static bfd_vma version_info[16];
+static Elf_Internal_Ehdr elf_header;
+static Elf_Internal_Shdr *section_headers;
+static Elf_Internal_Phdr *program_headers;
+static Elf_Internal_Dyn *dynamic_section;
+static Elf_Internal_Shdr *symtab_shndx_hdr;
+static int show_name;
+static int do_dynamic;
+static int do_syms;
+static int do_reloc;
+static int do_sections;
+static int do_section_groups;
+static int do_section_details;
+static int do_segments;
+static int do_unwind;
+static int do_using_dynamic;
+static int do_header;
+static int do_dump;
+static int do_version;
+static int do_wide;
+static int do_histogram;
+static int do_debugging;
+static int do_debug_info;
+static int do_debug_abbrevs;
+static int do_debug_lines;
+static int do_debug_pubnames;
+static int do_debug_aranges;
+static int do_debug_ranges;
+static int do_debug_frames;
+static int do_debug_frames_interp;
+static int do_debug_macinfo;
+static int do_debug_str;
+static int do_debug_loc;
+static int do_arch;
+static int do_notes;
+static int is_32bit_elf;
+static int have_frame_base;
+static int need_base_address;
+static bfd_vma eh_addr_size;
 
 struct group_list
 {
@@ -184,10 +187,9 @@ struct group
   unsigned int group_index;
 };
 
-struct group *section_groups;
-size_t group_count;
-
-struct group **section_headers_groups;
+static size_t group_count;
+static struct group *section_groups;
+static struct group **section_headers_groups;
 
 /* A dynamic array of flags indicating for which sections a hex dump
    has been requested (via the -x switch) and/or a disassembly dump
@@ -206,7 +208,7 @@ unsigned int num_dump_sects = 0;
 #define DISASS_DUMP    (1 << 1)
 #define DEBUG_DUMP     (1 << 2)
 
-/* How to rpint a vma value.  */
+/* How to print a vma value.  */
 typedef enum print_mode
 {
   HEX,
@@ -263,7 +265,7 @@ static void (*byte_put) (unsigned char *, bfd_vma, int);
 #define streq(a,b)     (strcmp ((a), (b)) == 0)
 #define strneq(a,b,n)  (strncmp ((a), (b), (n)) == 0)
 \f
-static void
+static void ATTRIBUTE_PRINTF_1
 error (const char *message, ...)
 {
   va_list args;
@@ -274,7 +276,7 @@ error (const char *message, ...)
   va_end (args);
 }
 
-static void
+static void ATTRIBUTE_PRINTF_1
 warn (const char *message, ...)
 {
   va_list args;
@@ -286,16 +288,47 @@ warn (const char *message, ...)
 }
 
 static void *
-get_data (void *var, FILE *file, long offset, size_t size, const char *reason)
+cmalloc (size_t nmemb, size_t size)
+{
+  /* Check for overflow.  */
+  if (nmemb >= ~(size_t) 0 / size)
+    return NULL;
+  else
+    return malloc (nmemb * size);
+}
+
+static void *
+xcmalloc (size_t nmemb, size_t size)
+{
+  /* Check for overflow.  */
+  if (nmemb >= ~(size_t) 0 / size)
+    return NULL;
+  else
+    return xmalloc (nmemb * size);
+}
+
+static void *
+xcrealloc (void *ptr, size_t nmemb, size_t size)
+{
+  /* Check for overflow.  */
+  if (nmemb >= ~(size_t) 0 / size)
+    return NULL;
+  else
+    return xrealloc (ptr, nmemb * size);
+}
+
+static void *
+get_data (void *var, FILE *file, long offset, size_t size, size_t nmemb,
+         const char *reason)
 {
   void *mvar;
 
-  if (size == 0)
+  if (size == 0 || nmemb == 0)
     return NULL;
 
   if (fseek (file, archive_file_offset + offset, SEEK_SET))
     {
-      error (_("Unable to seek to 0x%x for %s\n"),
+      error (_("Unable to seek to 0x%lx for %s\n"),
             archive_file_offset + offset, reason);
       return NULL;
     }
@@ -303,19 +336,25 @@ get_data (void *var, FILE *file, long offset, size_t size, const char *reason)
   mvar = var;
   if (mvar == NULL)
     {
-      mvar = malloc (size);
+      /* Check for overflow.  */
+      if (nmemb < (~(size_t) 0 - 1) / size)
+       /* + 1 so that we can '\0' terminate invalid string table sections.  */
+       mvar = malloc (size * nmemb + 1);
 
       if (mvar == NULL)
        {
-         error (_("Out of memory allocating 0x%x bytes for %s\n"),
-                size, reason);
+         error (_("Out of memory allocating 0x%lx bytes for %s\n"),
+                (unsigned long)(size * nmemb), reason);
          return NULL;
        }
+
+      ((char *) mvar)[size * nmemb] = '\0';
     }
 
-  if (fread (mvar, size, 1, file) != 1)
+  if (fread (mvar, size, nmemb, file) != nmemb)
     {
-      error (_("Unable to read in 0x%x bytes of %s\n"), size, reason);
+      error (_("Unable to read in 0x%lx bytes of %s\n"),
+            (unsigned long)(size * nmemb), reason);
       if (mvar != var)
        free (mvar);
       return NULL;
@@ -729,6 +768,8 @@ guess_is_rela (unsigned long e_machine)
     case EM_XTENSA:
     case EM_XTENSA_OLD:
     case EM_M32R:
+    case EM_M32C:
+    case EM_MS1:
       return TRUE;
 
     case EM_MMA:
@@ -769,16 +810,17 @@ slurp_rela_relocs (FILE *file,
     {
       Elf32_External_Rela *erelas;
 
-      erelas = get_data (NULL, file, rel_offset, rel_size, _("relocs"));
+      erelas = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
       if (!erelas)
        return 0;
 
       nrelas = rel_size / sizeof (Elf32_External_Rela);
 
-      relas = malloc (nrelas * sizeof (Elf_Internal_Rela));
+      relas = cmalloc (nrelas, sizeof (Elf_Internal_Rela));
 
       if (relas == NULL)
        {
+         free (erelas);
          error (_("out of memory parsing relocs"));
          return 0;
        }
@@ -796,16 +838,17 @@ slurp_rela_relocs (FILE *file,
     {
       Elf64_External_Rela *erelas;
 
-      erelas = get_data (NULL, file, rel_offset, rel_size, _("relocs"));
+      erelas = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
       if (!erelas)
        return 0;
 
       nrelas = rel_size / sizeof (Elf64_External_Rela);
 
-      relas = malloc (nrelas * sizeof (Elf_Internal_Rela));
+      relas = cmalloc (nrelas, sizeof (Elf_Internal_Rela));
 
       if (relas == NULL)
        {
+         free (erelas);
          error (_("out of memory parsing relocs"));
          return 0;
        }
@@ -839,16 +882,17 @@ slurp_rel_relocs (FILE *file,
     {
       Elf32_External_Rel *erels;
 
-      erels = get_data (NULL, file, rel_offset, rel_size, _("relocs"));
+      erels = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
       if (!erels)
        return 0;
 
       nrels = rel_size / sizeof (Elf32_External_Rel);
 
-      rels = malloc (nrels * sizeof (Elf_Internal_Rela));
+      rels = cmalloc (nrels, sizeof (Elf_Internal_Rela));
 
       if (rels == NULL)
        {
+         free (erels);
          error (_("out of memory parsing relocs"));
          return 0;
        }
@@ -866,16 +910,17 @@ slurp_rel_relocs (FILE *file,
     {
       Elf64_External_Rel *erels;
 
-      erels = get_data (NULL, file, rel_offset, rel_size, _("relocs"));
+      erels = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
       if (!erels)
        return 0;
 
       nrels = rel_size / sizeof (Elf64_External_Rel);
 
-      rels = malloc (nrels * sizeof (Elf_Internal_Rela));
+      rels = cmalloc (nrels, sizeof (Elf_Internal_Rela));
 
       if (rels == NULL)
        {
+         free (erels);
          error (_("out of memory parsing relocs"));
          return 0;
        }
@@ -1232,6 +1277,14 @@ dump_relocations (FILE *file,
        case EM_XTENSA:
          rtype = elf_xtensa_reloc_type (type);
          break;
+
+       case EM_M32C:
+         rtype = elf_m32c_reloc_type (type);
+         break;
+
+       case EM_MS1:
+         rtype = elf_ms1_reloc_type (type);
+         break;
        }
 
       if (rtype == NULL)
@@ -1243,7 +1296,31 @@ dump_relocations (FILE *file,
       else
        printf (do_wide ? "%-22.22s" : "%-17.17s", rtype);
 
-      if (symtab_index)
+      if (elf_header.e_machine == EM_ALPHA
+         && streq (rtype, "R_ALPHA_LITUSE")
+         && is_rela)
+       {
+         switch (rels[i].r_addend)
+           {
+           case LITUSE_ALPHA_ADDR:   rtype = "ADDR";   break;
+           case LITUSE_ALPHA_BASE:   rtype = "BASE";   break;
+           case LITUSE_ALPHA_BYTOFF: rtype = "BYTOFF"; break;
+           case LITUSE_ALPHA_JSR:    rtype = "JSR";    break;
+           case LITUSE_ALPHA_TLSGD:  rtype = "TLSGD";  break;
+           case LITUSE_ALPHA_TLSLDM: rtype = "TLSLDM"; break;
+           case LITUSE_ALPHA_JSRDIRECT: rtype = "JSRDIRECT"; break;
+           default: rtype = NULL;
+           }
+         if (rtype)
+           printf (" (%s)", rtype);
+         else
+           {
+             putchar (' ');
+             printf (_("<unknown addend: %lx>"),
+                     (unsigned long) rels[i].r_addend);
+           }
+       }
+      else if (symtab_index)
        {
          if (symtab == NULL || symtab_index >= nsyms)
            printf (" bad symbol index: %08lx", (unsigned long) symtab_index);
@@ -1278,6 +1355,9 @@ dump_relocations (FILE *file,
                        sec_name = "ABS";
                      else if (psym->st_shndx == SHN_COMMON)
                        sec_name = "COMMON";
+                     else if (elf_header.e_machine == EM_X86_64
+                              && psym->st_shndx == SHN_X86_64_LCOMMON)
+                       sec_name = "LARGE_COMMON";
                      else if (elf_header.e_machine == EM_IA_64
                               && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX
                               && psym->st_shndx == SHN_IA_64_ANSI_COMMON)
@@ -1293,7 +1373,7 @@ dump_relocations (FILE *file,
                }
              else if (strtab == NULL)
                printf (_("<string table index: %3ld>"), psym->st_name);
-             else if (psym->st_name > strtablen)
+             else if (psym->st_name >= strtablen)
                printf (_("<corrupt string table index: %3ld>"), psym->st_name);
              else
                print_symbol (22, strtab + psym->st_name);
@@ -1309,8 +1389,7 @@ dump_relocations (FILE *file,
          print_vma (rels[i].r_addend, LONG_HEX);
        }
 
-      if (elf_header.e_machine == EM_SPARCV9
-         && streq (rtype, "R_SPARC_OLO10"))
+      if (elf_header.e_machine == EM_SPARCV9 && streq (rtype, "R_SPARC_OLO10"))
        printf (" + %lx", (unsigned long) ELF64_R_TYPE_DATA (info));
 
       putchar ('\n');
@@ -1412,6 +1491,17 @@ get_sparc64_dynamic_type (unsigned long type)
     }
 }
 
+static const char *
+get_ppc_dynamic_type (unsigned long type)
+{
+  switch (type)
+    {
+    case DT_PPC_GOT: return "PPC_GOT";
+    default:
+      return NULL;
+    }
+}
+
 static const char *
 get_ppc64_dynamic_type (unsigned long type)
 {
@@ -1443,6 +1533,17 @@ get_parisc_dynamic_type (unsigned long type)
     case DT_HP_GST_SIZE:       return "HP_GST_SIZE";
     case DT_HP_GST_VERSION:    return "HP_GST_VERSION";
     case DT_HP_GST_HASHVAL:    return "HP_GST_HASHVAL";
+    case DT_HP_EPLTREL:                return "HP_GST_EPLTREL";
+    case DT_HP_EPLTRELSZ:      return "HP_GST_EPLTRELSZ";
+    case DT_HP_FILTERED:       return "HP_FILTERED";
+    case DT_HP_FILTER_TLS:     return "HP_FILTER_TLS";
+    case DT_HP_COMPAT_FILTERED:        return "HP_COMPAT_FILTERED";
+    case DT_HP_LAZYLOAD:       return "HP_LAZYLOAD";
+    case DT_HP_BIND_NOW_COUNT: return "HP_BIND_NOW_COUNT";
+    case DT_PLT:               return "PLT";
+    case DT_PLT_SIZE:          return "PLT_SIZE";
+    case DT_DLT:               return "DLT";
+    case DT_DLT_SIZE:          return "DLT_SIZE";
     default:
       return NULL;
     }
@@ -1459,10 +1560,21 @@ get_ia64_dynamic_type (unsigned long type)
     }
 }
 
+static const char *
+get_alpha_dynamic_type (unsigned long type)
+{
+  switch (type)
+    {
+    case DT_ALPHA_PLTRO: return "ALPHA_PLTRO";
+    default:
+      return NULL;
+    }
+}
+
 static const char *
 get_dynamic_type (unsigned long type)
 {
-  static char buff[32];
+  static char buff[64];
 
   switch (type)
     {
@@ -1552,12 +1664,18 @@ get_dynamic_type (unsigned long type)
            case EM_SPARCV9:
              result = get_sparc64_dynamic_type (type);
              break;
+           case EM_PPC:
+             result = get_ppc_dynamic_type (type);
+             break;
            case EM_PPC64:
              result = get_ppc64_dynamic_type (type);
              break;
            case EM_IA_64:
              result = get_ia64_dynamic_type (type);
              break;
+           case EM_ALPHA:
+             result = get_alpha_dynamic_type (type);
+             break;
            default:
              result = NULL;
              break;
@@ -1566,9 +1684,11 @@ get_dynamic_type (unsigned long type)
          if (result != NULL)
            return result;
 
-         sprintf (buff, _("Processor Specific: %lx"), type);
+         snprintf (buff, sizeof (buff), _("Processor Specific: %lx"), type);
        }
-      else if ((type >= DT_LOOS) && (type <= DT_HIOS))
+      else if (((type >= DT_LOOS) && (type <= DT_HIOS))
+              || (elf_header.e_machine == EM_PARISC
+                  && (type >= OLD_DT_LOOS) && (type <= OLD_DT_HIOS)))
        {
          const char *result;
 
@@ -1585,10 +1705,11 @@ get_dynamic_type (unsigned long type)
          if (result != NULL)
            return result;
 
-         sprintf (buff, _("Operating System specific: %lx"), type);
+         snprintf (buff, sizeof (buff), _("Operating System specific: %lx"),
+                   type);
        }
       else
-       sprintf (buff, _("<unknown>: %lx"), type);
+       snprintf (buff, sizeof (buff), _("<unknown>: %lx"), type);
 
       return buff;
     }
@@ -1609,11 +1730,11 @@ get_file_type (unsigned e_type)
 
     default:
       if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC))
-       sprintf (buff, _("Processor Specific: (%x)"), e_type);
+       snprintf (buff, sizeof (buff), _("Processor Specific: (%x)"), e_type);
       else if ((e_type >= ET_LOOS) && (e_type <= ET_HIOS))
-       sprintf (buff, _("OS Specific: (%x)"), e_type);
+       snprintf (buff, sizeof (buff), _("OS Specific: (%x)"), e_type);
       else
-       sprintf (buff, _("<unknown>: %x"), e_type);
+       snprintf (buff, sizeof (buff), _("<unknown>: %x"), e_type);
       return buff;
     }
 }
@@ -1719,8 +1840,10 @@ get_machine_name (unsigned e_machine)
     case EM_IQ2000:            return "Vitesse IQ2000";
     case EM_XTENSA_OLD:
     case EM_XTENSA:            return "Tensilica Xtensa Processor";
+    case EM_M32C:              return "Renesas M32c";
+    case EM_MS1:                return "Morpho Techologies MS1 processor";
     default:
-      sprintf (buff, _("<unknown>: %x"), e_machine);
+      snprintf (buff, sizeof (buff), _("<unknown>: %x"), e_machine);
       return buff;
     }
 }
@@ -2228,11 +2351,25 @@ get_osabi_name (unsigned int osabi)
     case ELFOSABI_STANDALONE:  return _("Standalone App");
     case ELFOSABI_ARM:         return "ARM";
     default:
-      sprintf (buff, _("<unknown: %x>"), osabi);
+      snprintf (buff, sizeof (buff), _("<unknown: %x>"), osabi);
       return buff;
     }
 }
 
+static const char *
+get_arm_segment_type (unsigned long type)
+{
+  switch (type)
+    {
+    case PT_ARM_EXIDX:
+      return "EXIDX";
+    default:
+      break;
+    }
+
+  return NULL;
+}
+
 static const char *
 get_mips_segment_type (unsigned long type)
 {
@@ -2268,8 +2405,13 @@ get_parisc_segment_type (unsigned long type)
     case PT_HP_CORE_MMF:       return "HP_CORE_MMF";
     case PT_HP_PARALLEL:       return "HP_PARALLEL";
     case PT_HP_FASTBIND:       return "HP_FASTBIND";
+    case PT_HP_OPT_ANNOT:      return "HP_OPT_ANNOT";
+    case PT_HP_HSL_ANNOT:      return "HP_HSL_ANNOT";
+    case PT_HP_STACK:          return "HP_STACK";
+    case PT_HP_CORE_UTSNAME:   return "HP_CORE_UTSNAME";
     case PT_PARISC_ARCHEXT:    return "PARISC_ARCHEXT";
     case PT_PARISC_UNWIND:     return "PARISC_UNWIND";
+    case PT_PARISC_WEAKORDER:  return "PARISC_WEAKORDER";
     default:
       break;
     }
@@ -2323,6 +2465,9 @@ get_segment_type (unsigned long p_type)
 
          switch (elf_header.e_machine)
            {
+           case EM_ARM:
+             result = get_arm_segment_type (p_type);
+             break;
            case EM_MIPS:
            case EM_MIPS_RS3_LE:
              result = get_mips_segment_type (p_type);
@@ -2366,7 +2511,7 @@ get_segment_type (unsigned long p_type)
          sprintf (buff, "LOOS+%lx", p_type - PT_LOOS);
        }
       else
-       sprintf (buff, _("<unknown>: %lx"), p_type);
+       snprintf (buff, sizeof (buff), _("<unknown>: %lx"), p_type);
 
       return buff;
     }
@@ -2430,6 +2575,10 @@ get_parisc_section_type_name (unsigned int sh_type)
     case SHT_PARISC_EXT:       return "PARISC_EXT";
     case SHT_PARISC_UNWIND:    return "PARISC_UNWIND";
     case SHT_PARISC_DOC:       return "PARISC_DOC";
+    case SHT_PARISC_ANNOT:     return "PARISC_ANNOT";
+    case SHT_PARISC_SYMEXTN:   return "PARISC_SYMEXTN";
+    case SHT_PARISC_STUBS:     return "PARISC_STUBS";
+    case SHT_PARISC_DLKM:      return "PARISC_DLKM";
     default:
       break;
     }
@@ -2550,7 +2699,7 @@ 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
-       sprintf (buff, _("<unknown>: %x"), sh_type);
+       snprintf (buff, sizeof (buff), _("<unknown>: %x"), sh_type);
 
       return buff;
     }
@@ -2558,7 +2707,7 @@ get_section_type_name (unsigned int sh_type)
 
 #define OPTION_DEBUG_DUMP      512
 
-struct option options[] =
+static struct option options[] =
 {
   {"all",             no_argument, 0, 'a'},
   {"file-header",      no_argument, 0, 'h'},
@@ -2569,6 +2718,8 @@ struct option options[] =
   {"sections",        no_argument, 0, 'S'},
   {"section-headers",  no_argument, 0, 'S'},
   {"section-groups",   no_argument, 0, 'g'},
+  {"section-details",  no_argument, 0, 't'},
+  {"full-section-name",no_argument, 0, 'N'},
   {"symbols",         no_argument, 0, 's'},
   {"syms",            no_argument, 0, 's'},
   {"relocs",          no_argument, 0, 'r'},
@@ -2603,6 +2754,7 @@ usage (void)
   -S --section-headers   Display the sections' header\n\
      --sections          An alias for --section-headers\n\
   -g --section-groups    Display the section groups\n\
+  -t --section-details   Display the section details\n\
   -e --headers           Equivalent to: -h -l -S\n\
   -s --syms              Display the symbol table\n\
       --symbols          An alias for --syms\n\
@@ -2675,7 +2827,7 @@ parse_args (int argc, char **argv)
     usage ();
 
   while ((c = getopt_long
-         (argc, argv, "ersuahnldSDAIgw::x:i:vVWH", options, NULL)) != EOF)
+         (argc, argv, "ersuahnldSDAINtgw::x:i:vVWH", options, NULL)) != EOF)
     {
       char *cp;
       int section;
@@ -2706,6 +2858,11 @@ parse_args (int argc, char **argv)
        case 'g':
          do_section_groups++;
          break;
+       case 't':
+       case 'N':
+         do_sections++;
+         do_section_details++;
+         break;
        case 'e':
          do_header++;
          do_sections++;
@@ -2948,7 +3105,7 @@ get_elf_class (unsigned int elf_class)
     case ELFCLASS32:   return "ELF32";
     case ELFCLASS64:   return "ELF64";
     default:
-      sprintf (buff, _("<unknown: %x>"), elf_class);
+      snprintf (buff, sizeof (buff), _("<unknown: %x>"), elf_class);
       return buff;
     }
 }
@@ -2964,7 +3121,7 @@ get_data_encoding (unsigned int encoding)
     case ELFDATA2LSB: return _("2's complement, little endian");
     case ELFDATA2MSB: return _("2's complement, big endian");
     default:
-      sprintf (buff, _("<unknown: %x>"), encoding);
+      snprintf (buff, sizeof (buff), _("<unknown: %x>"), encoding);
       return buff;
     }
 }
@@ -3069,7 +3226,7 @@ get_32bit_program_headers (FILE *file, Elf_Internal_Phdr *program_headers)
   unsigned int i;
 
   phdrs = get_data (NULL, file, elf_header.e_phoff,
-                   elf_header.e_phentsize * elf_header.e_phnum,
+                   elf_header.e_phentsize, elf_header.e_phnum,
                    _("program headers"));
   if (!phdrs)
     return 0;
@@ -3102,7 +3259,7 @@ get_64bit_program_headers (FILE *file, Elf_Internal_Phdr *program_headers)
   unsigned int i;
 
   phdrs = get_data (NULL, file, elf_header.e_phoff,
-                   elf_header.e_phentsize * elf_header.e_phnum,
+                   elf_header.e_phentsize, elf_header.e_phnum,
                    _("program headers"));
   if (!phdrs)
     return 0;
@@ -3137,7 +3294,7 @@ get_program_headers (FILE *file)
   if (program_headers != NULL)
     return 1;
 
-  phdrs = malloc (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
+  phdrs = cmalloc (elf_header.e_phnum, sizeof (Elf_Internal_Phdr));
 
   if (phdrs == NULL)
     {
@@ -3350,13 +3507,11 @@ process_program_headers (FILE *file)
        putc ('\n', stdout);
     }
 
-  if (do_segments && section_headers != NULL)
+  if (do_segments && section_headers != NULL && string_table != NULL)
     {
       printf (_("\n Section to Segment mapping:\n"));
       printf (_("  Segment Sections...\n"));
 
-      assert (string_table != NULL);
-
       for (i = 0; i < elf_header.e_phnum; i++)
        {
          unsigned int j;
@@ -3434,11 +3589,11 @@ get_32bit_section_headers (FILE *file, unsigned int num)
   unsigned int i;
 
   shdrs = get_data (NULL, file, elf_header.e_shoff,
-                   elf_header.e_shentsize * num, _("section headers"));
+                   elf_header.e_shentsize, num, _("section headers"));
   if (!shdrs)
     return 0;
 
-  section_headers = malloc (num * sizeof (Elf_Internal_Shdr));
+  section_headers = cmalloc (num, sizeof (Elf_Internal_Shdr));
 
   if (section_headers == NULL)
     {
@@ -3475,11 +3630,11 @@ get_64bit_section_headers (FILE *file, unsigned int num)
   unsigned int i;
 
   shdrs = get_data (NULL, file, elf_header.e_shoff,
-                   elf_header.e_shentsize * num, _("section headers"));
+                   elf_header.e_shentsize, num, _("section headers"));
   if (!shdrs)
     return 0;
 
-  section_headers = malloc (num * sizeof (Elf_Internal_Shdr));
+  section_headers = cmalloc (num, sizeof (Elf_Internal_Shdr));
 
   if (section_headers == NULL)
     {
@@ -3518,7 +3673,7 @@ get_32bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
   Elf_Internal_Sym *psym;
   unsigned int j;
 
-  esyms = get_data (NULL, file, section->sh_offset, section->sh_size,
+  esyms = get_data (NULL, file, section->sh_offset, 1, section->sh_size,
                    _("symbols"));
   if (!esyms)
     return NULL;
@@ -3529,7 +3684,7 @@ get_32bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
          == (unsigned long) SECTION_HEADER_NUM (section - section_headers)))
     {
       shndx = get_data (NULL, file, symtab_shndx_hdr->sh_offset,
-                       symtab_shndx_hdr->sh_size, _("symtab shndx"));
+                       1, symtab_shndx_hdr->sh_size, _("symtab shndx"));
       if (!shndx)
        {
          free (esyms);
@@ -3538,7 +3693,7 @@ get_32bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
     }
 
   number = section->sh_size / section->sh_entsize;
-  isyms = malloc (number * sizeof (Elf_Internal_Sym));
+  isyms = cmalloc (number, sizeof (Elf_Internal_Sym));
 
   if (isyms == NULL)
     {
@@ -3581,7 +3736,7 @@ get_64bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
   Elf_Internal_Sym *psym;
   unsigned int j;
 
-  esyms = get_data (NULL, file, section->sh_offset, section->sh_size,
+  esyms = get_data (NULL, file, section->sh_offset, 1, section->sh_size,
                    _("symbols"));
   if (!esyms)
     return NULL;
@@ -3592,7 +3747,7 @@ get_64bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
          == (unsigned long) SECTION_HEADER_NUM (section - section_headers)))
     {
       shndx = get_data (NULL, file, symtab_shndx_hdr->sh_offset,
-                       symtab_shndx_hdr->sh_size, _("symtab shndx"));
+                       1, symtab_shndx_hdr->sh_size, _("symtab shndx"));
       if (!shndx)
        {
          free (esyms);
@@ -3601,7 +3756,7 @@ get_64bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
     }
 
   number = section->sh_size / section->sh_entsize;
-  isyms = malloc (number * sizeof (Elf_Internal_Sym));
+  isyms = cmalloc (number, sizeof (Elf_Internal_Sym));
 
   if (isyms == NULL)
     {
@@ -3637,9 +3792,33 @@ get_64bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
 static const char *
 get_elf_section_flags (bfd_vma sh_flags)
 {
-  static char buff[32];
+  static char buff[1024];
+  char *p = buff;
+  int index, size = sizeof (buff) - (8 + 4 + 1);
+  const struct
+    {
+      const char *str;
+      int len;
+    }
+  flags [] =
+    {
+       { "WRITE", 5 },
+       { "ALLOC", 5 },
+       { "EXEC", 4 },
+       { "MERGE", 5 },
+       { "STRINGS", 7 },
+       { "INFO LINK", 9 },
+       { "LINK ORDER", 10 },
+       { "OS NONCONF", 10 },
+       { "GROUP", 5 },
+       { "TLS", 3 }
+    };
 
-  *buff = 0;
+  if (do_section_details)
+    {
+      sprintf (buff, "[%8.8lx]: ", (unsigned long) sh_flags);
+      p += 8 + 4;
+    }
 
   while (sh_flags)
     {
@@ -3648,36 +3827,97 @@ get_elf_section_flags (bfd_vma sh_flags)
       flag = sh_flags & - sh_flags;
       sh_flags &= ~ flag;
 
-      switch (flag)
+      if (do_section_details)
        {
-       case SHF_WRITE:            strcat (buff, "W"); break;
-       case SHF_ALLOC:            strcat (buff, "A"); break;
-       case SHF_EXECINSTR:        strcat (buff, "X"); break;
-       case SHF_MERGE:            strcat (buff, "M"); break;
-       case SHF_STRINGS:          strcat (buff, "S"); break;
-       case SHF_INFO_LINK:        strcat (buff, "I"); break;
-       case SHF_LINK_ORDER:       strcat (buff, "L"); break;
-       case SHF_OS_NONCONFORMING: strcat (buff, "O"); break;
-       case SHF_GROUP:            strcat (buff, "G"); break;
-       case SHF_TLS:              strcat (buff, "T"); break;
+         switch (flag)
+           {
+           case SHF_WRITE:             index = 0; break;
+           case SHF_ALLOC:             index = 1; break;
+           case SHF_EXECINSTR:         index = 2; break;
+           case SHF_MERGE:             index = 3; break;
+           case SHF_STRINGS:           index = 4; break;
+           case SHF_INFO_LINK:         index = 5; break;
+           case SHF_LINK_ORDER:        index = 6; break;
+           case SHF_OS_NONCONFORMING:  index = 7; break;
+           case SHF_GROUP:             index = 8; break;
+           case SHF_TLS:               index = 9; break;
 
-       default:
-         if (flag & SHF_MASKOS)
+           default:
+             index = -1;
+             break;
+           }
+
+         if (p != buff + 8 + 4)
            {
-             strcat (buff, "o");
-             sh_flags &= ~ SHF_MASKOS;
+             if (size < 10 + 2)
+               abort ();
+             size -= 2;
+             *p++ = ',';
+             *p++ = ' ';
+           }
+
+         if (index != -1)
+           {
+             size -= flags [index].len;
+             p = stpcpy (p, flags [index].str);
+           }
+         else if (flag & SHF_MASKOS)
+           {
+             size -= 5 + 8;
+             sprintf (p, "OS (%8.8lx)", (unsigned long) flag);
+             p += 5 + 8;
            }
          else if (flag & SHF_MASKPROC)
            {
-             strcat (buff, "p");
-             sh_flags &= ~ SHF_MASKPROC;
+             size -= 7 + 8;
+             sprintf (p, "PROC (%8.8lx)", (unsigned long) flag);
+             p += 7 + 8;
            }
          else
-           strcat (buff, "x");
-         break;
+           {
+             size -= 10 + 8;
+             sprintf (p, "UNKNOWN (%8.8lx)", (unsigned long) flag);
+             p += 10 + 8;
+           }
+       }
+      else
+       {
+         switch (flag)
+           {
+           case SHF_WRITE:             *p = 'W'; break;
+           case SHF_ALLOC:             *p = 'A'; break;
+           case SHF_EXECINSTR:         *p = 'X'; break;
+           case SHF_MERGE:             *p = 'M'; break;
+           case SHF_STRINGS:           *p = 'S'; break;
+           case SHF_INFO_LINK:         *p = 'I'; break;
+           case SHF_LINK_ORDER:        *p = 'L'; break;
+           case SHF_OS_NONCONFORMING:  *p = 'O'; break;
+           case SHF_GROUP:             *p = 'G'; break;
+           case SHF_TLS:               *p = 'T'; break;
+
+           default:
+             if (elf_header.e_machine == EM_X86_64
+                 && flag == SHF_X86_64_LARGE)
+               *p = 'l';
+             else if (flag & SHF_MASKOS)
+               {
+                 *p = 'o';
+                 sh_flags &= ~ SHF_MASKOS;
+               }
+             else if (flag & SHF_MASKPROC)
+               {
+                 *p = 'p';
+                 sh_flags &= ~ SHF_MASKPROC;
+               }
+             else
+               *p = 'x';
+             break;
+           }
+         p++;
        }
     }
 
+  *p = '\0';
   return buff;
 }
 
@@ -3710,17 +3950,17 @@ process_section_headers (FILE *file)
     return 0;
 
   /* Read in the string table, so that we have names to display.  */
-  section = SECTION_HEADER (elf_header.e_shstrndx);
-
-  if (section->sh_size != 0)
+  if (SECTION_HEADER_INDEX (elf_header.e_shstrndx) < elf_header.e_shnum)
     {
-      string_table = get_data (NULL, file, section->sh_offset,
-                              section->sh_size, _("string table"));
+      section = SECTION_HEADER (elf_header.e_shstrndx);
 
-      if (string_table == NULL)
-       return 0;
+      if (section->sh_size != 0)
+       {
+         string_table = get_data (NULL, file, section->sh_offset,
+                                  1, section->sh_size, _("string table"));
 
-      string_table_length = section->sh_size;
+         string_table_length = string_table != NULL ? section->sh_size : 0;
+       }
     }
 
   /* Scan the sections for the dynamic symbol table
@@ -3750,6 +3990,22 @@ process_section_headers (FILE *file)
       break;
     }
 
+#define CHECK_ENTSIZE_VALUES(section, i, size32, size64) \
+  do                                                                       \
+    {                                                                      \
+      size_t expected_entsize                                              \
+       = is_32bit_elf ? size32 : size64;                                   \
+      if (section->sh_entsize != expected_entsize)                         \
+       error (_("Section %d has invalid sh_entsize %lx (expected %lx)\n"), \
+              i, (unsigned long int) section->sh_entsize,                  \
+              (unsigned long int) expected_entsize);                       \
+      section->sh_entsize = expected_entsize;                              \
+    }                                                                      \
+  while (0)
+#define CHECK_ENTSIZE(section, i, type) \
+  CHECK_ENTSIZE_VALUES (section, i, sizeof (Elf32_External_##type),        \
+                       sizeof (Elf64_External_##type))
+
   for (i = 0, section = section_headers;
        i < elf_header.e_shnum;
        i++, section++)
@@ -3764,6 +4020,7 @@ process_section_headers (FILE *file)
              continue;
            }
 
+         CHECK_ENTSIZE (section, i, Sym);
          num_dynamic_syms = section->sh_size / section->sh_entsize;
          dynamic_symbols = GET_ELF_SYMBOLS (file, section);
        }
@@ -3777,7 +4034,7 @@ process_section_headers (FILE *file)
            }
 
          dynamic_strings = get_data (NULL, file, section->sh_offset,
-                                     section->sh_size, _("dynamic strings"));
+                                     1, section->sh_size, _("dynamic strings"));
          dynamic_strings_length = section->sh_size;
        }
       else if (section->sh_type == SHT_SYMTAB_SHNDX)
@@ -3789,6 +4046,14 @@ process_section_headers (FILE *file)
            }
          symtab_shndx_hdr = section;
        }
+      else if (section->sh_type == SHT_SYMTAB)
+       CHECK_ENTSIZE (section, i, Sym);
+      else if (section->sh_type == SHT_GROUP)
+       CHECK_ENTSIZE_VALUES (section, i, GRP_ENTRY_SIZE, GRP_ENTRY_SIZE);
+      else if (section->sh_type == SHT_REL)
+       CHECK_ENTSIZE (section, i, Rel);
+      else if (section->sh_type == SHT_RELA)
+       CHECK_ENTSIZE (section, i, Rela);
       else if ((do_debugging || do_debug_info || do_debug_abbrevs
                || do_debug_lines || do_debug_pubnames || do_debug_aranges
                || do_debug_frames || do_debug_macinfo || do_debug_str
@@ -3828,25 +4093,63 @@ process_section_headers (FILE *file)
     printf (_("\nSection Header:\n"));
 
   if (is_32bit_elf)
-    printf
-      (_("  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al\n"));
+    {
+      if (do_section_details)
+       {
+         printf (_("  [Nr] Name\n"));
+         printf (_("       Type            Addr     Off    Size   ES   Lk Inf Al\n"));
+       }
+      else
+       printf
+         (_("  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al\n"));
+    }
   else if (do_wide)
-    printf
-      (_("  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al\n"));
+    {
+      if (do_section_details)
+       {
+         printf (_("  [Nr] Name\n"));
+         printf (_("       Type            Address          Off    Size   ES   Lk Inf Al\n"));
+       }
+      else
+       printf
+         (_("  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al\n"));
+    }
   else
     {
-      printf (_("  [Nr] Name              Type             Address           Offset\n"));
-      printf (_("       Size              EntSize          Flags  Link  Info  Align\n"));
+      if (do_section_details)
+       {
+         printf (_("  [Nr] Name\n"));
+         printf (_("       Type              Address          Offset            Link\n"));
+         printf (_("       Size              EntSize          Info              Align\n"));
+       }
+      else
+       {
+         printf (_("  [Nr] Name              Type             Address           Offset\n"));
+         printf (_("       Size              EntSize          Flags  Link  Info  Align\n"));
+       }
     }
 
+  if (do_section_details)
+    printf (_("       Flags\n"));
+
   for (i = 0, section = section_headers;
        i < elf_header.e_shnum;
        i++, section++)
     {
-      printf ("  [%2u] %-17.17s %-15.15s ",
-             SECTION_HEADER_NUM (i),
-             SECTION_NAME (section),
-             get_section_type_name (section->sh_type));
+      if (do_section_details)
+       {
+         printf ("  [%2u] %s\n",
+                 SECTION_HEADER_NUM (i),
+                 SECTION_NAME (section));
+         if (is_32bit_elf || do_wide)
+           printf ("       %-15.15s ",
+                   get_section_type_name (section->sh_type));
+       }
+      else
+       printf ("  [%2u] %-17.17s %-15.15s ",
+               SECTION_HEADER_NUM (i),
+               SECTION_NAME (section),
+               get_section_type_name (section->sh_type));
 
       if (is_32bit_elf)
        {
@@ -3857,7 +4160,10 @@ process_section_headers (FILE *file)
                   (unsigned long) section->sh_size,
                   (unsigned long) section->sh_entsize);
 
-         printf (" %3s ", get_elf_section_flags (section->sh_flags));
+         if (do_section_details)
+           fputs ("  ", stdout);
+         else
+           printf (" %3s ", get_elf_section_flags (section->sh_flags));
 
          printf ("%2ld %3lu %2ld\n",
                  (unsigned long) section->sh_link,
@@ -3892,7 +4198,10 @@ process_section_headers (FILE *file)
              print_vma (section->sh_entsize, LONG_HEX);
            }
 
-         printf (" %3s ", get_elf_section_flags (section->sh_flags));
+         if (do_section_details)
+           fputs ("  ", stdout);
+         else
+           printf (" %3s ", get_elf_section_flags (section->sh_flags));
 
          printf ("%2ld %3lu ",
                  (unsigned long) section->sh_link,
@@ -3906,6 +4215,27 @@ process_section_headers (FILE *file)
              putchar ('\n');
            }
        }
+      else if (do_section_details)
+       {
+         printf ("       %-15.15s  ",
+                 get_section_type_name (section->sh_type));
+         print_vma (section->sh_addr, LONG_HEX);
+         if ((long) section->sh_offset == section->sh_offset)
+           printf ("  %16.16lx", (unsigned long) section->sh_offset);
+         else
+           {
+             printf ("  ");
+             print_vma (section->sh_offset, LONG_HEX);
+           }
+         printf ("  %ld\n       ", (unsigned long) section->sh_link);
+         print_vma (section->sh_size, LONG_HEX);
+         putchar (' ');
+         print_vma (section->sh_entsize, LONG_HEX);
+
+         printf ("  %-16lu  %ld\n",
+                 (unsigned long) section->sh_info,
+                 (unsigned long) section->sh_addralign);
+       }
       else
        {
          putchar (' ');
@@ -3929,9 +4259,13 @@ process_section_headers (FILE *file)
                  (unsigned long) section->sh_info,
                  (unsigned long) section->sh_addralign);
        }
+
+      if (do_section_details)
+       printf ("       %s\n", get_elf_section_flags (section->sh_flags));
     }
 
-  printf (_("Key to Flags:\n\
+  if (!do_section_details)
+    printf (_("Key to Flags:\n\
   W (write), A (alloc), X (execute), M (merge), S (strings)\n\
   I (info), L (link order), G (group), x (unknown)\n\
   O (extra OS processing required) o (OS specific), p (processor specific)\n"));
@@ -3949,7 +4283,7 @@ get_group_flags (unsigned int flags)
       return "COMDAT";
 
    default:
-      sprintf (buff, _("[<unknown>: 0x%x]"), flags);
+      snprintf (buff, sizeof (buff), _("[<unknown>: 0x%x]"), flags);
       break;
     }
   return buff;
@@ -3964,6 +4298,7 @@ process_section_groups (FILE *file)
   Elf_Internal_Shdr *symtab_sec, *strtab_sec;
   Elf_Internal_Sym *symtab;
   char *strtab;
+  size_t strtab_size;
 
   /* Don't process section groups unless needed.  */
   if (!do_unwind && !do_section_groups)
@@ -4020,6 +4355,7 @@ process_section_groups (FILE *file)
   strtab_sec = NULL;
   symtab = NULL;
   strtab = NULL;
+  strtab_size = 0;
   for (i = 0, section = section_headers, group = section_groups;
        i < elf_header.e_shnum;
        i++, section++)
@@ -4034,8 +4370,9 @@ process_section_groups (FILE *file)
          Elf_Internal_Sym *sym;
 
          /* Get the symbol table.  */
-         sec = SECTION_HEADER (section->sh_link);
-         if (sec->sh_type != SHT_SYMTAB)
+         if (SECTION_HEADER_INDEX (section->sh_link) >= elf_header.e_shnum
+             || ((sec = SECTION_HEADER (section->sh_link))->sh_type
+                 != SHT_SYMTAB))
            {
              error (_("Bad sh_link in group section `%s'\n"), name);
              continue;
@@ -4061,26 +4398,41 @@ process_section_groups (FILE *file)
                }
 
              group_name = SECTION_NAME (section_headers + sec_index);
+             strtab_sec = NULL;
+             if (strtab)
+               free (strtab);
              strtab = NULL;
+             strtab_size = 0;
            }
          else
            {
              /* Get the string table.  */
-             sec = SECTION_HEADER (symtab_sec->sh_link);
-             if (strtab_sec != sec)
+             if (SECTION_HEADER_INDEX (symtab_sec->sh_link)
+                 >= elf_header.e_shnum)
+               {
+                 strtab_sec = NULL;
+                 if (strtab)
+                   free (strtab);
+                 strtab = NULL;
+                 strtab_size = 0;
+               }
+             else if (strtab_sec
+                      != (sec = SECTION_HEADER (symtab_sec->sh_link)))
                {
                  strtab_sec = sec;
                  if (strtab)
                    free (strtab);
                  strtab = get_data (NULL, file, strtab_sec->sh_offset,
-                                    strtab_sec->sh_size,
+                                    1, strtab_sec->sh_size,
                                     _("string table"));
+                 strtab_size = strtab != NULL ? strtab_sec->sh_size : 0;
                }
-             group_name = strtab + sym->st_name;
+             group_name = sym->st_name < strtab_size
+                          ? strtab + sym->st_name : "<corrupt>";
            }
 
          start = get_data (NULL, file, section->sh_offset,
-                           section->sh_size, _("section data"));
+                           1, section->sh_size, _("section data"));
 
          indices = start;
          size = (section->sh_size / section->sh_entsize) - 1;
@@ -4089,8 +4441,8 @@ process_section_groups (FILE *file)
 
          if (do_section_groups)
            {
-             printf ("\n%s group section `%s' [%s] contains %u sections:\n",
-                     get_group_flags (entry), name, group_name, size);
+             printf ("\n%s group section [%5u] `%s' [%s] contains %u sections:\n",
+                     get_group_flags (entry), i, name, group_name, size);
 
              printf (_("   [Index]    Name\n"));
            }
@@ -4104,13 +4456,26 @@ process_section_groups (FILE *file)
              entry = byte_get (indices, 4);
              indices += 4;
 
+             if (SECTION_HEADER_INDEX (entry) >= elf_header.e_shnum)
+               {
+                 error (_("section [%5u] in group section [%5u] > maximum section [%5u]\n"),
+                        entry, i, elf_header.e_shnum - 1);
+                 continue;
+               }
+             else if (entry >= SHN_LORESERVE && entry <= SHN_HIRESERVE)
+               {
+                 error (_("invalid section [%5u] in group section [%5u]\n"),
+                        entry, i);
+                 continue;
+               }
+
              if (section_headers_groups [SECTION_HEADER_INDEX (entry)]
                  != NULL)
                {
                  if (entry)
                    {
-                     error (_("section [%5u] already in group section [%5u]\n"),
-                            entry,
+                     error (_("section [%5u] in group section [%5u] already in group section [%5u]\n"),
+                            entry, i,
                             section_headers_groups [SECTION_HEADER_INDEX (entry)]->group_index);
                      continue;
                    }
@@ -4135,8 +4500,7 @@ process_section_groups (FILE *file)
              if (do_section_groups)
                {
                  sec = SECTION_HEADER (entry);
-                 printf ("   [%5u]   %s\n",
-                         entry, SECTION_NAME (sec));
+                 printf ("   [%5u]   %s\n", entry, SECTION_NAME (sec));
                }
 
              g = xmalloc (sizeof (struct group_list));
@@ -4159,7 +4523,7 @@ process_section_groups (FILE *file)
   return 1;
 }
 
-struct
+static struct
 {
   const char *name;
   int reloc;
@@ -4267,26 +4631,37 @@ process_relocs (FILE *file)
 
              is_rela = section->sh_type == SHT_RELA;
 
-             if (section->sh_link)
+             if (section->sh_link
+                 && SECTION_HEADER_INDEX (section->sh_link)
+                    < elf_header.e_shnum)
                {
                  Elf_Internal_Shdr *symsec;
                  Elf_Internal_Sym *symtab;
                  unsigned long nsyms;
-                 unsigned long strtablen;
+                 unsigned long strtablen = 0;
                  char *strtab = NULL;
 
                  symsec = SECTION_HEADER (section->sh_link);
+                 if (symsec->sh_type != SHT_SYMTAB
+                     && symsec->sh_type != SHT_DYNSYM)
+                    continue;
+
                  nsyms = symsec->sh_size / symsec->sh_entsize;
                  symtab = GET_ELF_SYMBOLS (file, symsec);
 
                  if (symtab == NULL)
                    continue;
 
-                 strsec = SECTION_HEADER (symsec->sh_link);
+                 if (SECTION_HEADER_INDEX (symsec->sh_link)
+                     < elf_header.e_shnum)
+                   {
+                     strsec = SECTION_HEADER (symsec->sh_link);
 
-                 strtab = get_data (NULL, file, strsec->sh_offset,
-                                    strsec->sh_size, _("string table"));
-                 strtablen = strtab == NULL ? 0 : strsec->sh_size;
+                     strtab = get_data (NULL, file, strsec->sh_offset,
+                                        1, strsec->sh_size,
+                                        _("string table"));
+                     strtablen = strtab == NULL ? 0 : strsec->sh_size;
+                   }
 
                  dump_relocations (file, rel_offset, rel_size,
                                    symtab, nsyms, strtab, strtablen, is_rela);
@@ -4416,7 +4791,7 @@ dump_ia64_unwind (struct ia64_unw_aux_info *aux)
              (unsigned long) (tp->info.offset - aux->seg_base));
 
       head = aux->info + (tp->info.offset - aux->info_addr);
-      stamp = BYTE_GET ((unsigned char *) head);
+      stamp = byte_get ((unsigned char *) head, sizeof (stamp));
 
       printf ("  v%u, flags=0x%lx (%s%s), len=%lu bytes\n",
              (unsigned) UNW_VER (stamp),
@@ -4477,11 +4852,11 @@ slurp_ia64_unwind_table (FILE *file,
 
   /* Second, build the unwind table from the contents of the unwind section:  */
   size = sec->sh_size;
-  table = get_data (NULL, file, sec->sh_offset, size, _("unwind table"));
+  table = get_data (NULL, file, sec->sh_offset, 1, size, _("unwind table"));
   if (!table)
     return 0;
 
-  aux->table = xmalloc (size / (3 * eh_addr_size) * sizeof (aux->table[0]));
+  aux->table = xcmalloc (size / (3 * eh_addr_size), sizeof (aux->table[0]));
   tep = aux->table;
   for (tp = table; tp < table + size; tp += 3 * eh_addr_size, ++tep)
     {
@@ -4513,6 +4888,7 @@ slurp_ia64_unwind_table (FILE *file,
        ++relsec)
     {
       if (relsec->sh_type != SHT_RELA
+         || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
          || SECTION_HEADER (relsec->sh_info) != sec)
        continue;
 
@@ -4578,15 +4954,16 @@ ia64_process_unwind (FILE *file)
 
   for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
     {
-      if (sec->sh_type == SHT_SYMTAB)
+      if (sec->sh_type == SHT_SYMTAB
+         && SECTION_HEADER_INDEX (sec->sh_link) < elf_header.e_shnum)
        {
          aux.nsyms = sec->sh_size / sec->sh_entsize;
          aux.symtab = GET_ELF_SYMBOLS (file, sec);
 
          strsec = SECTION_HEADER (sec->sh_link);
-         aux.strtab_size = strsec->sh_size;
          aux.strtab = get_data (NULL, file, strsec->sh_offset,
-                                aux.strtab_size, _("string table"));
+                                1, strsec->sh_size, _("string table"));
+         aux.strtab_size = aux.strtab != NULL ? strsec->sh_size : 0;
        }
       else if (sec->sh_type == SHT_IA_64_UNWIND)
        unwcount++;
@@ -4667,7 +5044,7 @@ ia64_process_unwind (FILE *file)
        {
          aux.info_size = sec->sh_size;
          aux.info_addr = sec->sh_addr;
-         aux.info = get_data (NULL, file, sec->sh_offset, aux.info_size,
+         aux.info = get_data (NULL, file, sec->sh_offset, 1, aux.info_size,
                               _("unwind info"));
 
          printf (_("\nUnwind section "));
@@ -4821,7 +5198,7 @@ slurp_hppa_unwind_table (FILE *file,
                         struct hppa_unw_aux_info *aux,
                         Elf_Internal_Shdr *sec)
 {
-  unsigned long size, unw_ent_size, nrelas, i;
+  unsigned long size, unw_ent_size, nentries, nrelas, i;
   Elf_Internal_Phdr *seg;
   struct hppa_unw_table_entry *tep;
   Elf_Internal_Shdr *relsec;
@@ -4857,35 +5234,30 @@ slurp_hppa_unwind_table (FILE *file,
   /* Second, build the unwind table from the contents of the unwind
      section.  */
   size = sec->sh_size;
-  table = get_data (NULL, file, sec->sh_offset, size, _("unwind table"));
+  table = get_data (NULL, file, sec->sh_offset, 1, size, _("unwind table"));
   if (!table)
     return 0;
 
-  unw_ent_size = 2 * eh_addr_size + 8;
+  unw_ent_size = 16;
+  nentries = size / unw_ent_size;
+  size = unw_ent_size * nentries;
 
-  tep = aux->table = xmalloc (size / unw_ent_size * sizeof (aux->table[0]));
+  tep = aux->table = xcmalloc (nentries, sizeof (aux->table[0]));
 
-  for (tp = table; tp < table + size; tp += (2 * eh_addr_size + 8), ++tep)
+  for (tp = table; tp < table + size; tp += unw_ent_size, ++tep)
     {
       unsigned int tmp1, tmp2;
 
       tep->start.section = SHN_UNDEF;
       tep->end.section   = SHN_UNDEF;
 
-      if (is_32bit_elf)
-       {
-         tep->start.offset = byte_get ((unsigned char *) tp + 0, 4);
-         tep->end.offset = byte_get ((unsigned char *) tp + 4, 4);
-         tmp1 = byte_get ((unsigned char *) tp + 8, 4);
-         tmp2 = byte_get ((unsigned char *) tp + 12, 4);
-       }
-      else
-       {
-         tep->start.offset = BYTE_GET ((unsigned char *) tp + 0);
-         tep->end.offset = BYTE_GET ((unsigned char *) tp + 8);
-         tmp1 = byte_get ((unsigned char *) tp + 16, 4);
-         tmp2 = byte_get ((unsigned char *) tp + 20, 4);
-       }
+      tep->start.offset = byte_get ((unsigned char *) tp + 0, 4);
+      tep->end.offset = byte_get ((unsigned char *) tp + 4, 4);
+      tmp1 = byte_get ((unsigned char *) tp + 8, 4);
+      tmp2 = byte_get ((unsigned char *) tp + 12, 4);
+
+      tep->start.offset += aux->seg_base;
+      tep->end.offset   += aux->seg_base;
 
       tep->Cannot_unwind = (tmp1 >> 31) & 0x1;
       tep->Millicode = (tmp1 >> 30) & 0x1;
@@ -4918,9 +5290,6 @@ slurp_hppa_unwind_table (FILE *file,
       tep->Pseudo_SP_Set = (tmp2 >> 28) & 0x1;
       tep->reserved4 = (tmp2 >> 27) & 0x1;
       tep->Total_frame_size = tmp2 & 0x7ffffff;
-
-      tep->start.offset += aux->seg_base;
-      tep->end.offset   += aux->seg_base;
     }
   free (table);
 
@@ -4931,6 +5300,7 @@ slurp_hppa_unwind_table (FILE *file,
        ++relsec)
     {
       if (relsec->sh_type != SHT_RELA
+         || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
          || SECTION_HEADER (relsec->sh_info) != sec)
        continue;
 
@@ -4978,7 +5348,7 @@ slurp_hppa_unwind_table (FILE *file,
       free (rela);
     }
 
-  aux->table_len = size / unw_ent_size;
+  aux->table_len = nentries;
 
   return 1;
 }
@@ -4994,19 +5364,21 @@ hppa_process_unwind (FILE *file)
 
   memset (& aux, 0, sizeof (aux));
 
-  assert (string_table != NULL);
+  if (string_table == NULL)
+    return 1;
 
   for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
     {
-      if (sec->sh_type == SHT_SYMTAB)
+      if (sec->sh_type == SHT_SYMTAB
+         && SECTION_HEADER_INDEX (sec->sh_link) < elf_header.e_shnum)
        {
          aux.nsyms = sec->sh_size / sec->sh_entsize;
          aux.symtab = GET_ELF_SYMBOLS (file, sec);
 
          strsec = SECTION_HEADER (sec->sh_link);
-         aux.strtab_size = strsec->sh_size;
          aux.strtab = get_data (NULL, file, strsec->sh_offset,
-                                aux.strtab_size, _("string table"));
+                                1, strsec->sh_size, _("string table"));
+         aux.strtab_size = aux.strtab != NULL ? strsec->sh_size : 0;
        }
       else if (streq (SECTION_NAME (sec), ".PARISC.unwind"))
        unwsec = sec;
@@ -5112,9 +5484,9 @@ dynamic_section_mips_val (Elf_Internal_Dyn *entry)
 
        time_t time = entry->d_un.d_val;
        tmp = gmtime (&time);
-       sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u",
-                tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
-                tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+       snprintf (timebuf, sizeof (timebuf), "%04u-%02u-%02uT%02u:%02u:%02u",
+                 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
+                 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
        printf ("Time Stamp: %s\n", timebuf);
       }
       break;
@@ -5165,7 +5537,13 @@ dynamic_section_parisc_val (Elf_Internal_Dyn *entry)
          { DT_HP_BIND_RESTRICTED, "HP_BIND_RESTRICTED" },
          { DT_HP_BIND_SYMBOLIC, "HP_BIND_SYMBOLIC" },
          { DT_HP_RPATH_FIRST, "HP_RPATH_FIRST" },
-         { DT_HP_BIND_DEPTH_FIRST, "HP_BIND_DEPTH_FIRST" }
+         { DT_HP_BIND_DEPTH_FIRST, "HP_BIND_DEPTH_FIRST" },
+         { DT_HP_GST, "HP_GST" },
+         { DT_HP_SHLIB_FIXED, "HP_SHLIB_FIXED" },
+         { DT_HP_MERGE_SHLIB_SEG, "HP_MERGE_SHLIB_SEG" },
+         { DT_HP_NODELETE, "HP_NODELETE" },
+         { DT_HP_GROUP, "HP_GROUP" },
+         { DT_HP_PROTECT_LINKAGE_TABLE, "HP_PROTECT_LINKAGE_TABLE" }
        };
        int first = 1;
        size_t cnt;
@@ -5222,7 +5600,7 @@ get_32bit_dynamic_section (FILE *file)
   Elf32_External_Dyn *edyn, *ext;
   Elf_Internal_Dyn *entry;
 
-  edyn = get_data (NULL, file, dynamic_addr, dynamic_size,
+  edyn = get_data (NULL, file, dynamic_addr, 1, dynamic_size,
                   _("dynamic section"));
   if (!edyn)
     return 0;
@@ -5239,7 +5617,7 @@ get_32bit_dynamic_section (FILE *file)
        break;
     }
 
-  dynamic_section = malloc (dynamic_nent * sizeof (*entry));
+  dynamic_section = cmalloc (dynamic_nent, sizeof (*entry));
   if (dynamic_section == NULL)
     {
       error (_("Out of memory\n"));
@@ -5266,7 +5644,7 @@ get_64bit_dynamic_section (FILE *file)
   Elf64_External_Dyn *edyn, *ext;
   Elf_Internal_Dyn *entry;
 
-  edyn = get_data (NULL, file, dynamic_addr, dynamic_size,
+  edyn = get_data (NULL, file, dynamic_addr, 1, dynamic_size,
                   _("dynamic section"));
   if (!edyn)
     return 0;
@@ -5283,7 +5661,7 @@ get_64bit_dynamic_section (FILE *file)
        break;
     }
 
-  dynamic_section = malloc (dynamic_nent * sizeof (*entry));
+  dynamic_section = cmalloc (dynamic_nent, sizeof (*entry));
   if (dynamic_section == NULL)
     {
       error (_("Out of memory\n"));
@@ -5304,13 +5682,11 @@ get_64bit_dynamic_section (FILE *file)
   return 1;
 }
 
-static const char *
-get_dynamic_flags (bfd_vma flags)
+static void
+print_dynamic_flags (bfd_vma flags)
 {
-  static char buff[128];
-  char *p = buff;
+  int first = 1;
 
-  *p = '\0';
   while (flags)
     {
       bfd_vma flag;
@@ -5318,22 +5694,22 @@ get_dynamic_flags (bfd_vma flags)
       flag = flags & - flags;
       flags &= ~ flag;
 
-      if (p != buff)
-       *p++ = ' ';
+      if (first)
+       first = 0;
+      else
+       putc (' ', stdout);
 
       switch (flag)
        {
-       case DF_ORIGIN:         strcpy (p, "ORIGIN"); break;
-       case DF_SYMBOLIC:       strcpy (p, "SYMBOLIC"); break;
-       case DF_TEXTREL:        strcpy (p, "TEXTREL"); break;
-       case DF_BIND_NOW:       strcpy (p, "BIND_NOW"); break;
-       case DF_STATIC_TLS:     strcpy (p, "STATIC_TLS"); break;
-       default:                strcpy (p, "unknown"); break;
+       case DF_ORIGIN:         fputs ("ORIGIN", stdout); break;
+       case DF_SYMBOLIC:       fputs ("SYMBOLIC", stdout); break;
+       case DF_TEXTREL:        fputs ("TEXTREL", stdout); break;
+       case DF_BIND_NOW:       fputs ("BIND_NOW", stdout); break;
+       case DF_STATIC_TLS:     fputs ("STATIC_TLS", stdout); break;
+       default:                fputs ("unknown", stdout); break;
        }
-
-      p = strchr (p, '\0');
     }
-  return buff;
+  puts ("");
 }
 
 /* Parse and display the contents of the dynamic section.  */
@@ -5443,7 +5819,7 @@ process_dynamic_section (FILE *file)
              continue;
            }
 
-         dynamic_strings = get_data (NULL, file, offset, str_tab_len,
+         dynamic_strings = get_data (NULL, file, offset, 1, str_tab_len,
                                      _("dynamic string table"));
          dynamic_strings_length = str_tab_len;
          break;
@@ -5478,8 +5854,8 @@ process_dynamic_section (FILE *file)
          Elf_Internal_Syminfo *syminfo;
 
          /* There is a syminfo section.  Read the data.  */
-         extsyminfo = get_data (NULL, file, dynamic_syminfo_offset, syminsz,
-                                _("symbol information"));
+         extsyminfo = get_data (NULL, file, dynamic_syminfo_offset, 1,
+                                syminsz, _("symbol information"));
          if (!extsyminfo)
            return 0;
 
@@ -5530,7 +5906,7 @@ process_dynamic_section (FILE *file)
        {
        case DT_FLAGS:
          if (do_dynamic)
-           puts (get_dynamic_flags (entry->d_un.d_val));
+           print_dynamic_flags (entry->d_un.d_val);
          break;
 
        case DT_AUXILIARY:
@@ -5955,9 +6331,13 @@ process_version_sections (FILE *file)
            printf_vma (section->sh_addr);
            printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
                    (unsigned long) section->sh_offset, section->sh_link,
-                   SECTION_NAME (SECTION_HEADER (section->sh_link)));
+                   SECTION_HEADER_INDEX (section->sh_link)
+                   < elf_header.e_shnum
+                   ? SECTION_NAME (SECTION_HEADER (section->sh_link))
+                   : "<corrupt>");
 
-           edefs = get_data (NULL, file, section->sh_offset, section->sh_size,
+           edefs = get_data (NULL, file, section->sh_offset, 1,
+                             section->sh_size,
                              _("version definition section"));
            if (!edefs)
              break;
@@ -6044,9 +6424,13 @@ process_version_sections (FILE *file)
            printf_vma (section->sh_addr);
            printf (_("  Offset: %#08lx  Link to section: %ld (%s)\n"),
                    (unsigned long) section->sh_offset, section->sh_link,
-                   SECTION_NAME (SECTION_HEADER (section->sh_link)));
+                   SECTION_HEADER_INDEX (section->sh_link)
+                   < elf_header.e_shnum
+                   ? SECTION_NAME (SECTION_HEADER (section->sh_link))
+                   : "<corrupt>");
 
-           eneed = get_data (NULL, file, section->sh_offset, section->sh_size,
+           eneed = get_data (NULL, file, section->sh_offset, 1,
+                             section->sh_size,
                              _("version need section"));
            if (!eneed)
              break;
@@ -6126,8 +6510,15 @@ process_version_sections (FILE *file)
            Elf_Internal_Shdr *string_sec;
            long off;
 
+           if (SECTION_HEADER_INDEX (section->sh_link) >= elf_header.e_shnum)
+             break;
+
            link_section = SECTION_HEADER (section->sh_link);
-           total = section->sh_size / section->sh_entsize;
+           total = section->sh_size / sizeof (Elf_External_Versym);
+
+           if (SECTION_HEADER_INDEX (link_section->sh_link)
+               >= elf_header.e_shnum)
+             break;
 
            found = 1;
 
@@ -6135,7 +6526,7 @@ process_version_sections (FILE *file)
 
            string_sec = SECTION_HEADER (link_section->sh_link);
 
-           strtab = get_data (NULL, file, string_sec->sh_offset,
+           strtab = get_data (NULL, file, string_sec->sh_offset, 1,
                               string_sec->sh_size, _("version string table"));
            if (!strtab)
              break;
@@ -6152,7 +6543,7 @@ process_version_sections (FILE *file)
            off = offset_from_vma (file,
                                   version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
                                   total * sizeof (short));
-           edata = get_data (NULL, file, off, total * sizeof (short),
+           edata = get_data (NULL, file, off, total, sizeof (short),
                              _("version symbol data"));
            if (!edata)
              {
@@ -6160,7 +6551,7 @@ process_version_sections (FILE *file)
                break;
              }
 
-           data = malloc (total * sizeof (short));
+           data = cmalloc (total, sizeof (short));
 
            for (cnt = total; cnt --;)
              data[cnt] = byte_get (edata + cnt * sizeof (short),
@@ -6193,8 +6584,10 @@ process_version_sections (FILE *file)
 
                      check_def = 1;
                      check_need = 1;
-                     if (SECTION_HEADER (symbols[cnt + j].st_shndx)->sh_type
-                         != SHT_NOBITS)
+                     if (SECTION_HEADER_INDEX (symbols[cnt + j].st_shndx)
+                         >= elf_header.e_shnum
+                         || SECTION_HEADER (symbols[cnt + j].st_shndx)->sh_type
+                            != SHT_NOBITS)
                        {
                          if (symbols[cnt + j].st_shndx == SHN_UNDEF)
                            check_def = 0;
@@ -6219,7 +6612,7 @@ process_version_sections (FILE *file)
                              Elf_External_Vernaux evna;
                              unsigned long a_off;
 
-                             get_data (&evn, file, offset, sizeof (evn),
+                             get_data (&evn, file, offset, sizeof (evn), 1,
                                        _("version need"));
 
                              ivn.vn_aux  = BYTE_GET (evn.vn_aux);
@@ -6230,7 +6623,7 @@ process_version_sections (FILE *file)
                              do
                                {
                                  get_data (&evna, file, a_off, sizeof (evna),
-                                           _("version need aux (2)"));
+                                           1, _("version need aux (2)"));
 
                                  ivna.vna_next  = BYTE_GET (evna.vna_next);
                                  ivna.vna_other = BYTE_GET (evna.vna_other);
@@ -6271,7 +6664,7 @@ process_version_sections (FILE *file)
 
                          do
                            {
-                             get_data (&evd, file, offset, sizeof (evd),
+                             get_data (&evd, file, offset, sizeof (evd), 1,
                                        _("version def"));
 
                              ivd.vd_next = BYTE_GET (evd.vd_next);
@@ -6291,7 +6684,8 @@ process_version_sections (FILE *file)
 
                              get_data (&evda, file,
                                        offset - ivd.vd_next + ivd.vd_aux,
-                                       sizeof (evda), _("version def aux"));
+                                       sizeof (evda), 1,
+                                       _("version def aux"));
 
                              ivda.vda_name = BYTE_GET (evda.vda_name);
 
@@ -6339,11 +6733,12 @@ get_symbol_binding (unsigned int binding)
     case STB_WEAK:     return "WEAK";
     default:
       if (binding >= STB_LOPROC && binding <= STB_HIPROC)
-       sprintf (buff, _("<processor specific>: %d"), binding);
+       snprintf (buff, sizeof (buff), _("<processor specific>: %d"),
+                 binding);
       else if (binding >= STB_LOOS && binding <= STB_HIOS)
-       sprintf (buff, _("<OS specific>: %d"), binding);
+       snprintf (buff, sizeof (buff), _("<OS specific>: %d"), binding);
       else
-       sprintf (buff, _("<unknown>: %d"), binding);
+       snprintf (buff, sizeof (buff), _("<unknown>: %d"), binding);
       return buff;
     }
 }
@@ -6374,7 +6769,7 @@ get_symbol_type (unsigned int type)
          if (elf_header.e_machine == EM_PARISC && type == STT_PARISC_MILLI)
            return "PARISC_MILLI";
 
-         sprintf (buff, _("<processor specific>: %d"), type);
+         snprintf (buff, sizeof (buff), _("<processor specific>: %d"), type);
        }
       else if (type >= STT_LOOS && type <= STT_HIOS)
        {
@@ -6386,10 +6781,10 @@ get_symbol_type (unsigned int type)
                return "HP_STUB";
            }
 
-         sprintf (buff, _("<OS specific>: %d"), type);
+         snprintf (buff, sizeof (buff), _("<OS specific>: %d"), type);
        }
       else
-       sprintf (buff, _("<unknown>: %d"), type);
+       snprintf (buff, sizeof (buff), _("<unknown>: %d"), type);
       return buff;
     }
 }
@@ -6422,6 +6817,9 @@ get_symbol_index_type (unsigned int type)
          && elf_header.e_machine == EM_IA_64
          && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX)
        return "ANSI_COM";
+      else if (elf_header.e_machine == EM_X86_64
+              && type == SHN_X86_64_LCOMMON)
+       return "LARGE_COM";
       else if (type >= SHN_LOPROC && type <= SHN_HIPROC)
        sprintf (buff, "PRC[0x%04x]", type);
       else if (type >= SHN_LOOS && type <= SHN_HIOS)
@@ -6442,7 +6840,7 @@ get_dynamic_data (FILE *file, unsigned int number, unsigned int ent_size)
   unsigned char *e_data;
   bfd_vma *i_data;
 
-  e_data = malloc (number * ent_size);
+  e_data = cmalloc (number, ent_size);
 
   if (e_data == NULL)
     {
@@ -6456,7 +6854,7 @@ get_dynamic_data (FILE *file, unsigned int number, unsigned int ent_size)
       return NULL;
     }
 
-  i_data = malloc (number * sizeof (*i_data));
+  i_data = cmalloc (number, sizeof (*i_data));
 
   if (i_data == NULL)
     {
@@ -6584,7 +6982,8 @@ process_symbol_table (FILE *file)
           i++, section++)
        {
          unsigned int si;
-         char *strtab;
+         char *strtab = NULL;
+         unsigned long int strtab_size = 0;
          Elf_Internal_Sym *symtab;
          Elf_Internal_Sym *psym;
 
@@ -6606,15 +7005,19 @@ process_symbol_table (FILE *file)
            continue;
 
          if (section->sh_link == elf_header.e_shstrndx)
-           strtab = string_table;
-         else
+           {
+             strtab = string_table;
+             strtab_size = string_table_length;
+           }
+         else if (SECTION_HEADER_INDEX (section->sh_link) < elf_header.e_shnum)
            {
              Elf_Internal_Shdr *string_sec;
 
              string_sec = SECTION_HEADER (section->sh_link);
 
              strtab = get_data (NULL, file, string_sec->sh_offset,
-                                string_sec->sh_size, _("string table"));
+                                1, string_sec->sh_size, _("string table"));
+             strtab_size = strtab != NULL ? string_sec->sh_size : 0;
            }
 
          for (si = 0, psym = symtab;
@@ -6629,7 +7032,8 @@ process_symbol_table (FILE *file)
              printf (" %-6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));
              printf (" %-3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
              printf (" %4s ", get_symbol_index_type (psym->st_shndx));
-             print_symbol (25, strtab + psym->st_name);
+             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)
@@ -6645,12 +7049,14 @@ process_symbol_table (FILE *file)
                     sizeof data + si * sizeof (vers_data));
 
                  get_data (&data, file, offset + si * sizeof (vers_data),
-                           sizeof (data), _("version data"));
+                           sizeof (data), 1, _("version data"));
 
                  vers_data = byte_get (data, 2);
 
-                 is_nobits = (SECTION_HEADER (psym->st_shndx)->sh_type
-                              == SHT_NOBITS);
+                 is_nobits = (SECTION_HEADER_INDEX (psym->st_shndx)
+                              < elf_header.e_shnum
+                              && SECTION_HEADER (psym->st_shndx)->sh_type
+                                 == SHT_NOBITS);
 
                  check_def = (psym->st_shndx != SHN_UNDEF);
 
@@ -6672,7 +7078,7 @@ process_symbol_table (FILE *file)
                            {
                              unsigned long vna_off;
 
-                             get_data (&evn, file, offset, sizeof (evn),
+                             get_data (&evn, file, offset, sizeof (evn), 1,
                                        _("version need"));
 
                              ivn.vn_aux  = BYTE_GET (evn.vn_aux);
@@ -6685,7 +7091,7 @@ process_symbol_table (FILE *file)
                                  Elf_External_Vernaux evna;
 
                                  get_data (&evna, file, vna_off,
-                                           sizeof (evna),
+                                           sizeof (evna), 1,
                                            _("version need aux (3)"));
 
                                  ivna.vna_other = BYTE_GET (evna.vna_other);
@@ -6707,7 +7113,9 @@ process_symbol_table (FILE *file)
                          if (ivna.vna_other == vers_data)
                            {
                              printf ("@%s (%d)",
-                                     strtab + ivna.vna_name, ivna.vna_other);
+                                     ivna.vna_name < strtab_size
+                                     ? strtab + ivna.vna_name : "<corrupt>",
+                                     ivna.vna_other);
                              check_def = 0;
                            }
                          else if (! is_nobits)
@@ -6736,7 +7144,7 @@ process_symbol_table (FILE *file)
                                  Elf_External_Verdef evd;
 
                                  get_data (&evd, file, offset, sizeof (evd),
-                                           _("version def"));
+                                           1, _("version def"));
 
                                  ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
                                  ivd.vd_aux = BYTE_GET (evd.vd_aux);
@@ -6751,14 +7159,15 @@ process_symbol_table (FILE *file)
                              offset += ivd.vd_aux;
 
                              get_data (&evda, file, offset, sizeof (evda),
-                                       _("version def aux"));
+                                       1, _("version def aux"));
 
                              ivda.vda_name = BYTE_GET (evda.vda_name);
 
                              if (psym->st_name != ivda.vda_name)
                                printf ((vers_data & 0x8000)
                                        ? "@%s" : "@@%s",
-                                       strtab + ivda.vda_name);
+                                       ivda.vda_name < strtab_size
+                                       ? strtab + ivda.vda_name : "<corrupt>");
                            }
                        }
                    }
@@ -6943,7 +7352,8 @@ dump_section (Elf_Internal_Shdr *section, FILE *file)
 
   addr = section->sh_addr;
 
-  start = get_data (NULL, file, section->sh_offset, bytes, _("section data"));
+  start = get_data (NULL, file, section->sh_offset, 1, bytes,
+                   _("section data"));
   if (!start)
     return 0;
 
@@ -7069,8 +7479,8 @@ reset_state_machine (int is_stmt)
   state_machine_regs.last_file_entry = 0;
 }
 
-/* Handled an extend line op.  Returns true if this is the end
-   of sequence.  */
+/* Handled an extend line op.
+   Returns the number of bytes read.  */
 
 static int
 process_extended_line_op (unsigned char *data, int is_stmt, int pointer_size)
@@ -7150,7 +7560,7 @@ load_debug_str (FILE *file)
 
   debug_str_size = sec->sh_size;
 
-  debug_str_contents = get_data (NULL, file, sec->sh_offset, sec->sh_size,
+  debug_str_contents = get_data (NULL, file, sec->sh_offset, 1, sec->sh_size,
                                 _("debug_str section data"));
 }
 
@@ -7172,7 +7582,10 @@ fetch_indirect_string (unsigned long offset)
     return _("<no .debug_str section>");
 
   if (offset > debug_str_size)
-    return _("<offset is too big>");
+    {
+      warn (_("DW_FORM_strp offset too big: %lx\n"), offset);
+      return _("<offset is too big>");
+    }
 
   return debug_str_contents + offset;
 }
@@ -7196,7 +7609,7 @@ load_debug_loc (FILE *file)
 
   debug_loc_size = sec->sh_size;
 
-  debug_loc_contents = get_data (NULL, file, sec->sh_offset, sec->sh_size,
+  debug_loc_contents = get_data (NULL, file, sec->sh_offset, 1, sec->sh_size,
                                 _("debug_loc section data"));
 }
 
@@ -7223,14 +7636,14 @@ load_debug_range (FILE *file)
   if (debug_range_contents != NULL)
     return;
 
-  /* Locate the .debug_str section.  */
+  /* Locate the .debug_ranges section.  */
   sec = find_section (".debug_ranges");
   if (sec == NULL)
     return;
 
   debug_range_size = sec->sh_size;
 
-  debug_range_contents = get_data (NULL, file, sec->sh_offset, sec->sh_size,
+  debug_range_contents = get_data (NULL, file, sec->sh_offset, 1, sec->sh_size,
                                   _("debug_range section data"));
 }
 
@@ -7271,8 +7684,10 @@ debug_apply_rela_addends (FILE *file,
       Elf_Internal_Sym *sym;
 
       if (relsec->sh_type != SHT_RELA
+         || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
          || SECTION_HEADER (relsec->sh_info) != section
-         || relsec->sh_size == 0)
+         || relsec->sh_size == 0
+         || SECTION_HEADER_INDEX (relsec->sh_link) >= elf_header.e_shnum)
        continue;
 
       if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
@@ -7303,7 +7718,7 @@ debug_apply_rela_addends (FILE *file,
                     example of this see the _clz.o binary in libgcc.a.  */
                  && ELF32_ST_TYPE (sym->st_info) != STT_OBJECT)
                {
-                 warn (_("%s: skipping unexpected symbol type %s in relocation in section .rela%s\n"),
+                 warn (_("skipping unexpected symbol type %s in relocation in section .rela%s\n"),
                        get_symbol_type (ELF32_ST_TYPE (sym->st_info)),
                        SECTION_NAME (section));
                  continue;
@@ -7311,6 +7726,18 @@ debug_apply_rela_addends (FILE *file,
            }
          else
            {
+             /* In MIPS little-endian objects, r_info isn't really a
+                64-bit little-endian value: it has a 32-bit little-endian
+                symbol index followed by four individual byte fields.
+                Reorder INFO accordingly.  */
+             if (elf_header.e_machine == EM_MIPS
+                 && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
+               rp->r_info = (((rp->r_info & 0xffffffff) << 32)
+                             | ((rp->r_info >> 56) & 0xff)
+                             | ((rp->r_info >> 40) & 0xff00)
+                             | ((rp->r_info >> 24) & 0xff0000)
+                             | ((rp->r_info >> 8) & 0xff000000));
+
              sym = symtab + ELF64_R_SYM (rp->r_info);
 
              if (ELF64_R_SYM (rp->r_info) != 0
@@ -7561,7 +7988,7 @@ get_TAG_name (unsigned long tag)
       {
        static char buffer[100];
 
-       sprintf (buffer, _("Unknown TAG value: %lx"), tag);
+       snprintf (buffer, sizeof (buffer), _("Unknown TAG value: %lx"), tag);
        return buffer;
       }
     }
@@ -7597,7 +8024,7 @@ get_FORM_name (unsigned long form)
       {
        static char buffer[100];
 
-       sprintf (buffer, _("Unknown FORM value: %lx"), form);
+       snprintf (buffer, sizeof (buffer), _("Unknown FORM value: %lx"), form);
        return buffer;
       }
     }
@@ -8167,7 +8594,7 @@ read_and_display_attr_value (unsigned long attribute,
       break;
 
     default:
-      warn (_("Unrecognized form: %d\n"), form);
+      warn (_("Unrecognized form: %lu\n"), form);
       break;
     }
 
@@ -8198,11 +8625,11 @@ read_and_display_attr_value (unsigned long attribute,
                {
                  max += 1024;
                  debug_info_p->loc_offsets
-                   = xrealloc (debug_info_p->loc_offsets,
-                               max * sizeof (*debug_info_p->loc_offsets));
+                   = xcrealloc (debug_info_p->loc_offsets,
+                                max, sizeof (*debug_info_p->loc_offsets));
                  debug_info_p->have_frame_base
-                   = xrealloc (debug_info_p->have_frame_base,
-                               max * sizeof (*debug_info_p->have_frame_base));
+                   = xcrealloc (debug_info_p->have_frame_base,
+                                max, sizeof (*debug_info_p->have_frame_base));
                  debug_info_p->max_loc_offsets = max;
                }
              debug_info_p->loc_offsets [num] = uvalue;
@@ -8227,8 +8654,8 @@ read_and_display_attr_value (unsigned long attribute,
                {
                  max += 1024;
                  debug_info_p->range_lists
-                   = xrealloc (debug_info_p->range_lists,
-                               max * sizeof (*debug_info_p->range_lists));
+                   = xcrealloc (debug_info_p->range_lists,
+                                max, sizeof (*debug_info_p->range_lists));
                  debug_info_p->max_range_lists = max;
                }
              debug_info_p->range_lists [num] = uvalue;
@@ -8310,6 +8737,7 @@ read_and_display_attr_value (unsigned long attribute,
        case DW_ATE_unsigned_char:      printf ("(unsigned char)"); break;
          /* DWARF 2.1 value.  */
        case DW_ATE_imaginary_float:    printf ("(imaginary float)"); break;
+       case DW_ATE_decimal_float:      printf ("(decimal float)"); break;
        default:
          if (uvalue >= DW_ATE_lo_user
              && uvalue <= DW_ATE_hi_user)
@@ -8530,7 +8958,8 @@ get_AT_name (unsigned long attribute)
       {
        static char buffer[100];
 
-       sprintf (buffer, _("Unknown AT value: %lx"), attribute);
+       snprintf (buffer, sizeof (buffer), _("Unknown AT value: %lx"),
+                 attribute);
        return buffer;
       }
     }
@@ -8602,8 +9031,8 @@ process_debug_info (Elf_Internal_Shdr *section, unsigned char *start,
        }
 
       /* Then allocate an array to hold the information.  */
-      debug_information = malloc (num_units *
-                                 sizeof (* debug_information));
+      debug_information = cmalloc (num_units,
+                                  sizeof (* debug_information));
       if (debug_information == NULL)
        {
          error (_("Not enough memory for a debug info array of %u entries"),
@@ -8688,7 +9117,7 @@ process_debug_info (Elf_Internal_Shdr *section, unsigned char *start,
 
       if (!do_loc)
        {
-         printf (_("  Compilation Unit @ %lx:\n"), cu_offset);
+         printf (_("  Compilation Unit @ offset 0x%lx:\n"), cu_offset);
          printf (_("   Length:        %ld\n"), compunit.cu_length);
          printf (_("   Version:       %d\n"), compunit.cu_version);
          printf (_("   Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset);
@@ -8716,7 +9145,7 @@ process_debug_info (Elf_Internal_Shdr *section, unsigned char *start,
            return 0;
          }
 
-       begin = get_data (NULL, file, sec->sh_offset, sec->sh_size,
+       begin = get_data (NULL, file, sec->sh_offset, 1, sec->sh_size,
                          _("debug_abbrev section data"));
        if (!begin)
          return 0;
@@ -8800,7 +9229,7 @@ process_debug_info (Elf_Internal_Shdr *section, unsigned char *start,
     }
  
   /* Set num_debug_info_entries here so that it can be used to check if
-     we need to proecess .debug_loc and .debug_ranges sections.  */
+     we need to process .debug_loc and .debug_ranges sections.  */
   if ((do_loc || do_debug_loc || do_debug_ranges)
       && num_debug_info_entries == 0)
     num_debug_info_entries = num_units;
@@ -8885,7 +9314,7 @@ get_debug_info (FILE * file)
   if (section == NULL)
     return 0;
 
-  start = get_data (NULL, file, section->sh_offset, section->sh_size,
+  start = get_data (NULL, file, section->sh_offset, 1, section->sh_size,
                    _("extracting information from .debug_info section"));
   if (start == NULL)
     return 0;
@@ -8976,7 +9405,7 @@ display_debug_lines (Elf_Internal_Shdr *section,
       /* Get the pointer size from the comp unit associated
         with this block of line number information.  */
       pointer_size = get_pointer_size_and_offset_of_comp_unit
-       (comp_unit, ".debug_lines", NULL);
+       (comp_unit, ".debug_line", NULL);
       comp_unit ++;
 
       printf (_("  Length:                      %ld\n"), info.li_length);
@@ -8987,7 +9416,9 @@ display_debug_lines (Elf_Internal_Shdr *section,
       printf (_("  Line Base:                   %d\n"), info.li_line_base);
       printf (_("  Line Range:                  %d\n"), info.li_line_range);
       printf (_("  Opcode Base:                 %d\n"), info.li_opcode_base);
-      printf (_("  (Pointer size:               %u)\n"), pointer_size);
+      printf (_("  (Pointer size:               %u)%s\n"),
+             pointer_size,
+             warned_about_missing_comp_units ? " [assumed]" : "" );
 
       end_of_sequence = data + info.li_length + initial_length_size;
 
@@ -9078,6 +9509,12 @@ display_debug_lines (Elf_Internal_Shdr *section,
          else switch (op_code)
            {
            case DW_LNS_extended_op:
+             if (pointer_size == 0)
+               {
+                 warn (_("Extend line ops need a valid pointer size, guessing at 4\n"));
+                 pointer_size = 4;
+               }
+
              data += process_extended_line_op (data, info.li_default_is_stmt,
                                                pointer_size);
              break;
@@ -9491,15 +9928,29 @@ display_debug_loc (Elf_Internal_Shdr *section,
            {
              if (start < next)
                warn (_("There is a hole [0x%lx - 0x%lx] in .debug_loc section.\n"),
-                     start - section_begin, next - section_begin);
+                     (long)(start - section_begin), (long)(next - section_begin));
              else if (start > next)
                warn (_("There is an overlap [0x%lx - 0x%lx] in .debug_loc section.\n"),
-                     start - section_begin, next - section_begin);
+                     (long)(start - section_begin), (long)(next - section_begin));
            }
          start = next;
 
+         if (offset >= bytes)
+           {
+             warn (_("Offset 0x%lx is bigger than .debug_loc section size.\n"),
+                   offset);
+             continue;
+           }
+
          while (1)
            {
+             if (start + 2 * pointer_size > section_end)
+               {
+                 warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
+                       offset);
+                 break;
+               }
+
              begin = byte_get (start, pointer_size);
              start += pointer_size;
              end = byte_get (start, pointer_size);
@@ -9515,14 +9966,28 @@ display_debug_loc (Elf_Internal_Shdr *section,
              if (begin == -1UL && end != -1UL)
                {
                  base_address = end;
-                 printf ("    %8.8lx %8.8lx %8.8lx (base address)\n",
+                 printf (_("    %8.8lx %8.8lx %8.8lx (base address)\n"),
                          offset, begin, end);
                  continue;
                }
 
+             if (start + 2 > section_end)
+               {
+                 warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
+                       offset);
+                 break;
+               }
+
              length = byte_get (start, 2);
              start += 2;
 
+             if (start + length > section_end)
+               {
+                 warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
+                       offset);
+                 break;
+               }
+
              printf ("    %8.8lx %8.8lx %8.8lx (",
                      offset, begin + base_address, end + base_address);
              need_frame_base = decode_location_expression (start,
@@ -9816,10 +10281,10 @@ display_debug_ranges (Elf_Internal_Shdr *section,
            {
              if (start < next)
                warn (_("There is a hole [0x%lx - 0x%lx] in .debug_ranges section.\n"),
-                     start - section_begin, next - section_begin);
+                     (long)(start - section_begin), (long)(next - section_begin));
              else if (start > next)
                warn (_("There is an overlap [0x%lx - 0x%lx] in .debug_ranges section.\n"),
-                     start - section_begin, next - section_begin);
+                     (long)(start - section_begin), (long)(next - section_begin));
            }
          start = next;
 
@@ -9831,7 +10296,10 @@ display_debug_ranges (Elf_Internal_Shdr *section,
              start += pointer_size;
 
              if (begin == 0 && end == 0)
-               break;
+               {
+                 printf (_("    %8.8lx <End of list>\n"), offset);
+                 break;
+               }
 
              /* Check base address specifiers.  */
              if (begin == -1UL && end != -1UL)
@@ -9852,7 +10320,6 @@ display_debug_ranges (Elf_Internal_Shdr *section,
 
              putchar ('\n');
            }
-         fputs (_("  <End of list>\n"), stdout);
        }
     }
   putchar ('\n');
@@ -9893,8 +10360,8 @@ frame_need_space (Frame_Chunk *fc, int reg)
     return;
 
   fc->ncols = reg + 1;
-  fc->col_type = xrealloc (fc->col_type, fc->ncols * sizeof (short int));
-  fc->col_offset = xrealloc (fc->col_offset, fc->ncols * sizeof (int));
+  fc->col_type = xcrealloc (fc->col_type, fc->ncols, sizeof (short int));
+  fc->col_offset = xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
 
   while (prev < fc->ncols)
     {
@@ -10190,7 +10657,7 @@ display_debug_frames (Elf_Internal_Shdr *section,
 
          if (!cie)
            {
-             warn ("Invalid CIE pointer %08lx in FDE at %08lx\n",
+             warn ("Invalid CIE pointer %08lx in FDE at %p\n",
                    cie_id, saved_start);
              start = block_end;
              fc->ncols = 0;
@@ -10204,8 +10671,8 @@ display_debug_frames (Elf_Internal_Shdr *section,
          else
            {
              fc->ncols = cie->ncols;
-             fc->col_type = xmalloc (fc->ncols * sizeof (short int));
-             fc->col_offset = xmalloc (fc->ncols * sizeof (int));
+             fc->col_type = xcmalloc (fc->ncols, sizeof (short int));
+             fc->col_offset = xcmalloc (fc->ncols, sizeof (int));
              memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int));
              memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int));
              fc->augmentation = cie->augmentation;
@@ -10517,8 +10984,8 @@ display_debug_frames (Elf_Internal_Shdr *section,
                printf ("  DW_CFA_remember_state\n");
              rs = xmalloc (sizeof (Frame_Chunk));
              rs->ncols = fc->ncols;
-             rs->col_type = xmalloc (rs->ncols * sizeof (short int));
-             rs->col_offset = xmalloc (rs->ncols * sizeof (int));
+             rs->col_type = xcmalloc (rs->ncols, sizeof (short int));
+             rs->col_offset = xcmalloc (rs->ncols, sizeof (int));
              memcpy (rs->col_type, fc->col_type, rs->ncols);
              memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (int));
              rs->next = remembered_state;
@@ -10610,6 +11077,7 @@ display_debug_frames (Elf_Internal_Shdr *section,
            case DW_CFA_def_cfa_sf:
              fc->cfa_reg = LEB ();
              fc->cfa_offset = SLEB ();
+             fc->cfa_offset = fc->cfa_offset * fc->data_factor;
              fc->cfa_exp = 0;
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_def_cfa_sf: r%d ofs %d\n",
@@ -10618,6 +11086,7 @@ display_debug_frames (Elf_Internal_Shdr *section,
 
            case DW_CFA_def_cfa_offset_sf:
              fc->cfa_offset = SLEB ();
+             fc->cfa_offset = fc->cfa_offset * fc->data_factor;
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_def_cfa_offset_sf: %d\n", fc->cfa_offset);
              break;
@@ -10689,7 +11158,7 @@ display_debug_not_supported (Elf_Internal_Shdr *section,
 
 /* A structure containing the name of a debug section
    and a pointer to a function that can decode it.  */
-struct
+static struct
 {
   const char *const name;
   int (*display) (Elf_Internal_Shdr *, unsigned char *, FILE *);
@@ -10738,7 +11207,7 @@ display_debug_section (Elf_Internal_Shdr *section, FILE *file)
       {
        unsigned char *start;
 
-       start = get_data (NULL, file, section->sh_offset, length,
+       start = get_data (NULL, file, section->sh_offset, 1, length,
                          _("debug section data"));
        if (start == NULL)
          {
@@ -10864,7 +11333,7 @@ process_mips_specific (FILE *file)
       size_t cnt;
 
       elib = get_data (NULL, file, liblist_offset,
-                      liblistno * sizeof (Elf32_External_Lib),
+                      liblistno, sizeof (Elf32_External_Lib),
                       _("liblist"));
       if (elib)
        {
@@ -10887,9 +11356,10 @@ process_mips_specific (FILE *file)
              liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
 
              tmp = gmtime (&time);
-             sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u",
-                      tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
-                      tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+             snprintf (timebuf, sizeof (timebuf),
+                       "%04u-%02u-%02uT%02u:%02u:%02u",
+                       tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
+                       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
 
              printf ("%3lu: ", (unsigned long) cnt);
              if (VALID_DYNAMIC_NAME (liblist.l_name))
@@ -10952,11 +11422,11 @@ process_mips_specific (FILE *file)
       while (sect->sh_type != SHT_MIPS_OPTIONS)
        ++sect;
 
-      eopt = get_data (NULL, file, options_offset, sect->sh_size,
+      eopt = get_data (NULL, file, options_offset, 1, sect->sh_size,
                       _("options"));
       if (eopt)
        {
-         iopt = malloc ((sect->sh_size / sizeof (eopt)) * sizeof (*iopt));
+         iopt = cmalloc ((sect->sh_size / sizeof (eopt)), sizeof (*iopt));
          if (iopt == NULL)
            {
              error (_("Out of memory"));
@@ -11148,7 +11618,7 @@ process_mips_specific (FILE *file)
          return 0;
        }
 
-      iconf = malloc (conflictsno * sizeof (*iconf));
+      iconf = cmalloc (conflictsno, sizeof (*iconf));
       if (iconf == NULL)
        {
          error (_("Out of memory"));
@@ -11160,7 +11630,7 @@ process_mips_specific (FILE *file)
          Elf32_External_Conflict *econf32;
 
          econf32 = get_data (NULL, file, conflicts_offset,
-                             conflictsno * sizeof (*econf32), _("conflict"));
+                             conflictsno, sizeof (*econf32), _("conflict"));
          if (!econf32)
            return 0;
 
@@ -11174,7 +11644,7 @@ process_mips_specific (FILE *file)
          Elf64_External_Conflict *econf64;
 
          econf64 = get_data (NULL, file, conflicts_offset,
-                             conflictsno * sizeof (*econf64), _("conflict"));
+                             conflictsno, sizeof (*econf64), _("conflict"));
          if (!econf64)
            return 0;
 
@@ -11214,6 +11684,7 @@ process_gnu_liblist (FILE *file)
   Elf_Internal_Shdr *section, *string_sec;
   Elf32_External_Lib *elib;
   char *strtab;
+  size_t strtab_size;
   size_t cnt;
   unsigned i;
 
@@ -11227,15 +11698,19 @@ process_gnu_liblist (FILE *file)
       switch (section->sh_type)
        {
        case SHT_GNU_LIBLIST:
-         elib = get_data (NULL, file, section->sh_offset, section->sh_size,
+         if (SECTION_HEADER_INDEX (section->sh_link) >= elf_header.e_shnum)
+           break;
+
+         elib = get_data (NULL, file, section->sh_offset, 1, section->sh_size,
                           _("liblist"));
 
          if (elib == NULL)
            break;
          string_sec = SECTION_HEADER (section->sh_link);
 
-         strtab = get_data (NULL, file, string_sec->sh_offset,
+         strtab = 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))
@@ -11265,15 +11740,18 @@ process_gnu_liblist (FILE *file)
              liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
 
              tmp = gmtime (&time);
-             sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u",
-                      tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
-                      tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+             snprintf (timebuf, sizeof (timebuf),
+                       "%04u-%02u-%02uT%02u:%02u:%02u",
+                       tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
+                       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
 
              printf ("%3lu: ", (unsigned long) cnt);
              if (do_wide)
-               printf ("%-20s", strtab + liblist.l_name);
+               printf ("%-20s", liblist.l_name < strtab_size
+                                ? strtab + liblist.l_name : "<corrupt>");
              else
-               printf ("%-20.20s", strtab + liblist.l_name);
+               printf ("%-20.20s", liblist.l_name < strtab_size
+                                   ? strtab + liblist.l_name : "<corrupt>");
              printf (" %s %#010lx %-7ld %-7ld\n", timebuf, liblist.l_checksum,
                      liblist.l_version, liblist.l_flags);
            }
@@ -11331,7 +11809,7 @@ get_note_type (unsigned e_type)
        break;
       }
 
-  sprintf (buff, _("Unknown note type: (0x%08x)"), e_type);
+  snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
   return buff;
 }
 
@@ -11353,7 +11831,7 @@ get_netbsd_elfcore_note_type (unsigned e_type)
 
   if (e_type < NT_NETBSDCORE_FIRSTMACH)
     {
-      sprintf (buff, _("Unknown note type: (0x%08x)"), e_type);
+      snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
       return buff;
     }
 
@@ -11392,7 +11870,8 @@ get_netbsd_elfcore_note_type (unsigned e_type)
        }
     }
 
-  sprintf (buff, _("PT_FIRSTMACH+%d"), e_type - NT_NETBSDCORE_FIRSTMACH);
+  snprintf (buff, sizeof (buff), _("PT_FIRSTMACH+%d"),
+           e_type - NT_NETBSDCORE_FIRSTMACH);
   return buff;
 }
 
@@ -11437,7 +11916,7 @@ process_corefile_note_segment (FILE *file, bfd_vma offset, bfd_vma length)
   if (length <= 0)
     return 0;
 
-  pnotes = get_data (NULL, file, offset, length, _("notes"));
+  pnotes = get_data (NULL, file, offset, 1, length, _("notes"));
   if (!pnotes)
     return 0;
 
@@ -11464,9 +11943,9 @@ process_corefile_note_segment (FILE *file, bfd_vma offset, bfd_vma length)
 
       if (((char *) next) > (((char *) pnotes) + length))
        {
-         warn (_("corrupt note found at offset %x into core notes\n"),
-               ((char *) external) - ((char *) pnotes));
-         warn (_(" type: %x, namesize: %08lx, descsize: %08lx\n"),
+         warn (_("corrupt note found at offset %lx into core notes\n"),
+               (long)((char *)external - (char *)pnotes));
+         warn (_(" type: %lx, namesize: %08lx, descsize: %08lx\n"),
                inote.type, inote.namesz, inote.descsz);
          break;
        }
@@ -11945,7 +12424,7 @@ process_archive (char *file_name, FILE *file)
          off = strtoul (arhdr.ar_name + 1, NULL, 10);
          if (off >= longnames_size)
            {
-             error (_("%s: invalid archive string table offset %lu\n"), off);
+             error (_("%s: invalid archive string table offset %lu\n"), file_name, off);
              ret = 1;
              break;
            }
@@ -11961,7 +12440,7 @@ process_archive (char *file_name, FILE *file)
 
       if (nameend == NULL)
        {
-         error (_("%s: bad archive file name\n"));
+         error (_("%s: bad archive file name\n"), file_name);
          ret = 1;
          break;
        }
This page took 0.060514 seconds and 4 git commands to generate.