]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - binutils/readelf.c
top level:
[thirdparty/binutils-gdb.git] / binutils / readelf.c
index debde024b11e2bf81dc3c5d11f4178fee1817be1..6d8f07fab3975307aa2ad19db64594dad60fb5c9 100644 (file)
@@ -1,5 +1,5 @@
 /* readelf.c -- display contents of an ELF format file
-   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    Originally developed by Eric Youngdale <eric@andante.jic.com>
 #include <stdio.h>
 #include <time.h>
 
+/* for PATH_MAX */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef PATH_MAX
+/* for MAXPATHLEN */
+# ifdef HAVE_SYS_PARAM_H
+#  include <sys/param.h>
+# endif
+# ifndef PATH_MAX
+#  ifdef MAXPATHLEN
+#   define PATH_MAX MAXPATHLEN
+#  else
+#   define PATH_MAX 1024
+#  endif
+# endif
+#endif
+
 #if __GNUC__ >= 2
 /* Define BFD64 here, even if our default architecture is 32 bit ELF
    as this will allow us to read in and parse 64bit and 32bit ELF files.
 #include "elf/external.h"
 #include "elf/internal.h"
 
+
+/* Included here, before RELOC_MACROS_GEN_FUNC is defined, so that
+   we can obtain the H8 reloc numbers.  We need these for the
+   get_reloc_size() function.  We include h8.h again after defining
+   RELOC_MACROS_GEN_FUNC so that we get the naming function as well.  */
+
+#include "elf/h8.h"
+#undef _ELF_H8_H
+
+/* Undo the effects of #including reloc-macros.h.  */
+
+#undef START_RELOC_NUMBERS
+#undef RELOC_NUMBER
+#undef FAKE_RELOC
+#undef EMPTY_RELOC
+#undef END_RELOC_NUMBERS
+#undef _RELOC_MACROS_H
+
 /* The following headers use the elf/reloc-macros.h file to
    automatically generate relocation recognition functions
    such as elf_mips_reloc_type()  */
 #include "elf/avr.h"
 #include "elf/bfin.h"
 #include "elf/cris.h"
+#include "elf/crx.h"
 #include "elf/d10v.h"
 #include "elf/d30v.h"
 #include "elf/dlx.h"
 #include "elf/i960.h"
 #include "elf/ia64.h"
 #include "elf/ip2k.h"
+#include "elf/iq2000.h"
 #include "elf/m32c.h"
 #include "elf/m32r.h"
 #include "elf/m68k.h"
 #include "elf/m68hc11.h"
 #include "elf/mcore.h"
+#include "elf/mep.h"
 #include "elf/mips.h"
 #include "elf/mmix.h"
 #include "elf/mn10200.h"
 #include "elf/mn10300.h"
-#include "elf/ms1.h"
+#include "elf/mt.h"
 #include "elf/msp430.h"
 #include "elf/or32.h"
 #include "elf/pj.h"
 #include "elf/ppc.h"
 #include "elf/ppc64.h"
 #include "elf/s390.h"
+#include "elf/score.h"
 #include "elf/sh.h"
 #include "elf/sparc.h"
+#include "elf/spu.h"
 #include "elf/v850.h"
 #include "elf/vax.h"
 #include "elf/x86-64.h"
 #include "elf/xstormy16.h"
-#include "elf/crx.h"
-#include "elf/iq2000.h"
 #include "elf/xtensa.h"
 
 #include "aout/ar.h"
@@ -133,8 +173,9 @@ 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 char program_interpreter[PATH_MAX];
 static bfd_vma dynamic_info[DT_JMPREL + 1];
+static bfd_vma dynamic_info_DT_GNU_HASH;
 static bfd_vma version_info[16];
 static Elf_Internal_Ehdr elf_header;
 static Elf_Internal_Shdr *section_headers;
@@ -177,6 +218,16 @@ static size_t group_count;
 static struct group *section_groups;
 static struct group **section_headers_groups;
 
+/* A linked list of the section names for which dumps were requested
+   by name.  */
+struct dump_list_entry
+{
+  char *name;
+  int type;
+  struct dump_list_entry *next;
+};
+static struct dump_list_entry *dump_sects_byname;
+
 /* A dynamic array of flags indicating for which sections a hex dump
    has been requested (via the -x switch) and/or a disassembly dump
    (via the -i switch).  */
@@ -185,8 +236,9 @@ unsigned num_cmdline_dump_sects = 0;
 
 /* A dynamic array of flags indicating for which sections a dump of
    some kind has been requested.  It is reset on a per-object file
-   basis and then initialised from the cmdline_dump_sects array and
-   the results of interpreting the -w switch.  */
+   basis and then initialised from the cmdline_dump_sects array,
+   the results of interpreting the -w switch, and the
+   dump_sects_byname list.  */
 char *dump_sects = NULL;
 unsigned int num_dump_sects = 0;
 
@@ -211,9 +263,11 @@ static void (*byte_put) (unsigned char *, bfd_vma, int);
 
 #define UNKNOWN -1
 
-#define SECTION_NAME(X)        ((X) == NULL ? "<none>" : \
-                        ((X)->sh_name >= string_table_length \
-                         ? "<corrupt>" : string_table + (X)->sh_name))
+#define SECTION_NAME(X)        \
+  ((X) == NULL ? "<none>" \
+  : string_table == NULL ? "<no-name>" \
+  : ((X)->sh_name >= string_table_length ? "<corrupt>" \
+  : string_table + (X)->sh_name))
 
 /* Given st_shndx I, map to section_headers index.  */
 #define SECTION_HEADER_INDEX(I)                                \
@@ -249,6 +303,7 @@ static void (*byte_put) (unsigned char *, bfd_vma, int);
 /* This is just a bit of syntatic sugar.  */
 #define streq(a,b)     (strcmp ((a), (b)) == 0)
 #define strneq(a,b,n)  (strncmp ((a), (b), (n)) == 0)
+#define const_strneq(a,b) (strncmp ((a), (b), sizeof (b) - 1) == 0)
 \f
 static void *
 get_data (void *var, FILE *file, long offset, size_t size, size_t nmemb,
@@ -539,86 +594,91 @@ guess_is_rela (unsigned long e_machine)
   switch (e_machine)
     {
       /* Targets that use REL relocations.  */
-    case EM_ARM:
     case EM_386:
     case EM_486:
     case EM_960:
-    case EM_DLX:
-    case EM_OPENRISC:
-    case EM_OR32:
-    case EM_CYGNUS_M32R:
+    case EM_ARM:
     case EM_D10V:
     case EM_CYGNUS_D10V:
+    case EM_DLX:
     case EM_MIPS:
     case EM_MIPS_RS3_LE:
+    case EM_CYGNUS_M32R:
+    case EM_OPENRISC:
+    case EM_OR32:
+    case EM_SCORE:
       return FALSE;
 
       /* Targets that use RELA relocations.  */
     case EM_68K:
-    case EM_H8_300:
-    case EM_H8_300H:
-    case EM_H8S:
-    case EM_SPARC32PLUS:
-    case EM_SPARCV9:
-    case EM_SPARC:
-    case EM_PPC:
-    case EM_PPC64:
-    case EM_V850:
-    case EM_CYGNUS_V850:
+    case EM_860:
+    case EM_ALPHA:
+    case EM_ALTERA_NIOS2:
+    case EM_AVR:
+    case EM_AVR_OLD:
+    case EM_BLACKFIN:
+    case EM_CRIS:
+    case EM_CRX:
     case EM_D30V:
     case EM_CYGNUS_D30V:
-    case EM_MN10200:
-    case EM_CYGNUS_MN10200:
-    case EM_MN10300:
-    case EM_CYGNUS_MN10300:
     case EM_FR30:
     case EM_CYGNUS_FR30:
     case EM_CYGNUS_FRV:
-    case EM_SH:
-    case EM_ALPHA:
-    case EM_MCORE:
+    case EM_H8S:
+    case EM_H8_300:
+    case EM_H8_300H:
     case EM_IA_64:
-    case EM_AVR:
-    case EM_AVR_OLD:
-    case EM_CRIS:
-    case EM_860:
-    case EM_X86_64:
-    case EM_S390:
-    case EM_S390_OLD:
+    case EM_IP2K:
+    case EM_IP2K_OLD:
+    case EM_IQ2000:
+    case EM_M32C:
+    case EM_M32R:
+    case EM_MCORE:
+    case EM_CYGNUS_MEP:
     case EM_MMIX:
+    case EM_MN10200:
+    case EM_CYGNUS_MN10200:
+    case EM_MN10300:
+    case EM_CYGNUS_MN10300:
     case EM_MSP430:
     case EM_MSP430_OLD:
-    case EM_XSTORMY16:
-    case EM_CRX:
+    case EM_MT:
+    case EM_NIOS32:
+    case EM_PPC64:
+    case EM_PPC:
+    case EM_S390:
+    case EM_S390_OLD:
+    case EM_SH:
+    case EM_SPARC:
+    case EM_SPARC32PLUS:
+    case EM_SPARCV9:
+    case EM_SPU:
+    case EM_V850:
+    case EM_CYGNUS_V850:
     case EM_VAX:
-    case EM_IP2K:
-    case EM_IP2K_OLD:
-    case EM_IQ2000:
+    case EM_X86_64:
+    case EM_XSTORMY16:
     case EM_XTENSA:
     case EM_XTENSA_OLD:
-    case EM_M32R:
-    case EM_M32C:
-    case EM_MS1:
-    case EM_BLACKFIN:
       return TRUE;
 
+    case EM_68HC05:
+    case EM_68HC08:
+    case EM_68HC11:
+    case EM_68HC16:
+    case EM_FX66:
+    case EM_ME16:
     case EM_MMA:
-    case EM_PCP:
     case EM_NCPU:
     case EM_NDR1:
-    case EM_STARCORE:
-    case EM_ME16:
+    case EM_PCP:
     case EM_ST100:
-    case EM_TINYJ:
-    case EM_FX66:
-    case EM_ST9PLUS:
+    case EM_ST19:
     case EM_ST7:
-    case EM_68HC16:
-    case EM_68HC11:
-    case EM_68HC08:
-    case EM_68HC05:
+    case EM_ST9PLUS:
+    case EM_STARCORE:
     case EM_SVX:
-    case EM_ST19:
+    case EM_TINYJ:
     default:
       warn (_("Don't know about relocations on this machine architecture\n"));
       return FALSE;
@@ -953,6 +1013,10 @@ dump_relocations (FILE *file,
          rtype = elf_sparc_reloc_type (type);
          break;
 
+       case EM_SPU:
+         rtype = elf_spu_reloc_type (type);
+         break;
+
        case EM_V850:
        case EM_CYGNUS_V850:
          rtype = v850_reloc_type (type);
@@ -1082,6 +1146,10 @@ dump_relocations (FILE *file,
          rtype = elf_s390_reloc_type (type);
          break;
 
+       case EM_SCORE:
+         rtype = elf_score_reloc_type (type);
+         break;
+
        case EM_XSTORMY16:
          rtype = elf_xstormy16_reloc_type (type);
          break;
@@ -1112,14 +1180,17 @@ dump_relocations (FILE *file,
          rtype = elf_m32c_reloc_type (type);
          break;
 
-       case EM_MS1:
-         rtype = elf_ms1_reloc_type (type);
+       case EM_MT:
+         rtype = elf_mt_reloc_type (type);
          break;
 
        case EM_BLACKFIN:
          rtype = elf_bfin_reloc_type (type);
          break;
 
+       case EM_CYGNUS_MEP:
+         rtype = elf_mep_reloc_type (type);
+         break;
        }
 
       if (rtype == NULL)
@@ -1132,6 +1203,7 @@ dump_relocations (FILE *file,
        printf (do_wide ? "%-22.22s" : "%-17.17s", rtype);
 
       if (elf_header.e_machine == EM_ALPHA
+         && rtype != NULL
          && streq (rtype, "R_ALPHA_LITUSE")
          && is_rela)
        {
@@ -1190,6 +1262,12 @@ dump_relocations (FILE *file,
                        sec_name = "ABS";
                      else if (psym->st_shndx == SHN_COMMON)
                        sec_name = "COMMON";
+                     else if (elf_header.e_machine == EM_MIPS
+                              && psym->st_shndx == SHN_MIPS_SCOMMON)
+                       sec_name = "SCOMMON";
+                     else if (elf_header.e_machine == EM_MIPS
+                              && psym->st_shndx == SHN_MIPS_SUNDEFINED)
+                       sec_name = "SUNDEF";
                      else if (elf_header.e_machine == EM_X86_64
                               && psym->st_shndx == SHN_X86_64_LCOMMON)
                        sec_name = "LARGE_COMMON";
@@ -1224,7 +1302,9 @@ 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
+         && rtype != NULL
+         && streq (rtype, "R_SPARC_OLO10"))
        printf (" + %lx", (unsigned long) ELF64_R_TYPE_DATA (info));
 
       putchar ('\n');
@@ -1406,6 +1486,23 @@ get_alpha_dynamic_type (unsigned long type)
     }
 }
 
+static const char *
+get_score_dynamic_type (unsigned long type)
+{
+  switch (type)
+    {
+    case DT_SCORE_BASE_ADDRESS: return "SCORE_BASE_ADDRESS";
+    case DT_SCORE_LOCAL_GOTNO:  return "SCORE_LOCAL_GOTNO";
+    case DT_SCORE_SYMTABNO:     return "SCORE_SYMTABNO";
+    case DT_SCORE_GOTSYM:       return "SCORE_GOTSYM";
+    case DT_SCORE_UNREFEXTNO:   return "SCORE_UNREFEXTNO";
+    case DT_SCORE_HIPAGENO:     return "SCORE_HIPAGENO";
+    default:
+      return NULL;
+    }
+}
+
+
 static const char *
 get_dynamic_type (unsigned long type)
 {
@@ -1467,6 +1564,8 @@ get_dynamic_type (unsigned long type)
 
     case DT_VERSYM:    return "VERSYM";
 
+    case DT_TLSDESC_GOT: return "TLSDESC_GOT";
+    case DT_TLSDESC_PLT: return "TLSDESC_PLT";
     case DT_RELACOUNT: return "RELACOUNT";
     case DT_RELCOUNT:  return "RELCOUNT";
     case DT_FLAGS_1:   return "FLAGS_1";
@@ -1484,6 +1583,7 @@ get_dynamic_type (unsigned long type)
     case DT_GNU_CONFLICTSZ: return "GNU_CONFLICTSZ";
     case DT_GNU_LIBLIST: return "GNU_LIBLIST";
     case DT_GNU_LIBLISTSZ: return "GNU_LIBLISTSZ";
+    case DT_GNU_HASH:  return "GNU_HASH";
 
     default:
       if ((type >= DT_LOPROC) && (type <= DT_HIPROC))
@@ -1511,6 +1611,9 @@ get_dynamic_type (unsigned long type)
            case EM_ALPHA:
              result = get_alpha_dynamic_type (type);
              break;
+           case EM_SCORE:
+             result = get_score_dynamic_type (type);
+             break;
            default:
              result = NULL;
              break;
@@ -1584,6 +1687,7 @@ get_machine_name (unsigned e_machine)
     case EM_NONE:              return _("None");
     case EM_M32:               return "WE32100";
     case EM_SPARC:             return "Sparc";
+    case EM_SPU:               return "SPU";
     case EM_386:               return "Intel 80386";
     case EM_68K:               return "MC68000";
     case EM_88K:               return "MC88000";
@@ -1665,6 +1769,7 @@ get_machine_name (unsigned e_machine)
     case EM_X86_64:            return "Advanced Micro Devices X86-64";
     case EM_S390_OLD:
     case EM_S390:              return "IBM S/390";
+    case EM_SCORE:             return "SUNPLUS S+Core";
     case EM_XSTORMY16:         return "Sanyo Xstormy16 CPU core";
     case EM_OPENRISC:
     case EM_OR32:              return "OpenRISC";
@@ -1676,7 +1781,12 @@ get_machine_name (unsigned e_machine)
     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";
+    case EM_MT:                 return "Morpho Techologies MT processor";
+    case EM_BLACKFIN:          return "Analog Devices Blackfin";
+    case EM_NIOS32:            return "Altera Nios";
+    case EM_ALTERA_NIOS2:      return "Altera Nios II";
+    case EM_XC16X:             return "Infineon Technologies xc16x";
+    case EM_CYGNUS_MEP:         return "Toshiba MeP Media Engine";
     default:
       snprintf (buff, sizeof (buff), _("<unknown>: %x"), e_machine);
       return buff;
@@ -1774,6 +1884,11 @@ decode_ARM_machine_flags (unsigned e_flags, char buf[])
 
     case EF_ARM_EABI_VER4:
       strcat (buf, ", Version4 EABI");
+      goto eabi;
+
+    case EF_ARM_EABI_VER5:
+      strcat (buf, ", Version5 EABI");
+    eabi:
       while (e_flags)
        {
          unsigned flag;
@@ -1922,10 +2037,62 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
          break;
 
        case EM_68K:
-         if (e_flags & EF_CPU32)
-           strcat (buf, ", cpu32");
-         if (e_flags & EF_M68000)
+         if ((e_flags & EF_M68K_ARCH_MASK) == EF_M68K_M68000)
            strcat (buf, ", m68000");
+         else if ((e_flags & EF_M68K_ARCH_MASK) == EF_M68K_CPU32)
+           strcat (buf, ", cpu32");
+         else if ((e_flags & EF_M68K_ARCH_MASK) == EF_M68K_FIDO)
+           strcat (buf, ", fido_a");
+         else
+           {
+             char const *isa = _("unknown");
+             char const *mac = _("unknown mac");
+             char const *additional = NULL;
+
+             switch (e_flags & EF_M68K_CF_ISA_MASK)
+               {
+               case EF_M68K_CF_ISA_A_NODIV:
+                 isa = "A";
+                 additional = ", nodiv";
+                 break;
+               case EF_M68K_CF_ISA_A:
+                 isa = "A";
+                 break;
+               case EF_M68K_CF_ISA_A_PLUS:
+                 isa = "A+";
+                 break;
+               case EF_M68K_CF_ISA_B_NOUSP:
+                 isa = "B";
+                 additional = ", nousp";
+                 break;
+               case EF_M68K_CF_ISA_B:
+                 isa = "B";
+                 break;
+               }
+             strcat (buf, ", cf, isa ");
+             strcat (buf, isa);
+             if (additional)
+               strcat (buf, additional);
+             if (e_flags & EF_M68K_CF_FLOAT)
+               strcat (buf, ", float");
+             switch (e_flags & EF_M68K_CF_MAC_MASK)
+               {
+               case 0:
+                 mac = NULL;
+                 break;
+               case EF_M68K_CF_MAC:
+                 mac = "mac";
+                 break;
+               case EF_M68K_CF_EMAC:
+                 mac = "emac";
+                 break;
+               }
+             if (mac)
+               {
+                 strcat (buf, ", ");
+                 strcat (buf, mac);
+               }
+           }
          break;
 
        case EM_PPC:
@@ -1962,7 +2129,6 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
        case EM_CYGNUS_M32R:
          if ((e_flags & EF_M32R_ARCH) == E_M32R_ARCH)
            strcat (buf, ", m32r");
-
          break;
 
        case EM_MIPS:
@@ -2063,6 +2229,12 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
            case EF_SH4_NOFPU: strcat (buf, ", sh4-nofpu"); break;
            case EF_SH4A_NOFPU: strcat (buf, ", sh4a-nofpu"); break;
            case EF_SH2A_NOFPU: strcat (buf, ", sh2a-nofpu"); break;
+           case EF_SH3_NOMMU: strcat (buf, ", sh3-nommu"); break;
+           case EF_SH4_NOMMU_NOFPU: strcat (buf, ", sh4-nommu-nofpu"); break;
+           case EF_SH2A_SH4_NOFPU: strcat (buf, ", sh2a-nofpu-or-sh4-nommu-nofpu"); break;
+           case EF_SH2A_SH3_NOFPU: strcat (buf, ", sh2a-nofpu-or-sh3-nommu"); break;
+           case EF_SH2A_SH4: strcat (buf, ", sh2a-or-sh4"); break;
+           case EF_SH2A_SH3E: strcat (buf, ", sh2a-or-sh3e"); break;
            default: strcat (buf, ", unknown ISA"); break;
            }
 
@@ -2489,6 +2661,7 @@ get_section_type_name (unsigned int sh_type)
     case SHT_INIT_ARRAY:       return "INIT_ARRAY";
     case SHT_FINI_ARRAY:       return "FINI_ARRAY";
     case SHT_PREINIT_ARRAY:    return "PREINIT_ARRAY";
+    case SHT_GNU_HASH:         return "GNU_HASH";
     case SHT_GROUP:            return "GROUP";
     case SHT_SYMTAB_SHNDX:     return "SYMTAB SECTION INDICIES";
     case SHT_GNU_verdef:       return "VERDEF";
@@ -2581,11 +2754,11 @@ static struct option options[] =
 };
 
 static void
-usage (void)
+usage (FILE *stream)
 {
-  fprintf (stdout, _("Usage: readelf <option(s)> elf-file(s)\n"));
-  fprintf (stdout, _(" Display information about the contents of ELF format files\n"));
-  fprintf (stdout, _(" Options are:\n\
+  fprintf (stream, _("Usage: readelf <option(s)> elf-file(s)\n"));
+  fprintf (stream, _(" Display information about the contents of ELF format files\n"));
+  fprintf (stream, _(" Options are:\n\
   -a --all               Equivalent to: -h -l -S -s -r -d -V -A -I\n\
   -h --file-header       Display the ELF file header\n\
   -l --program-headers   Display the program headers\n\
@@ -2609,18 +2782,21 @@ usage (void)
   --debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
                          Display the contents of DWARF2 debug sections\n"));
 #ifdef SUPPORT_DISASSEMBLY
-  fprintf (stdout, _("\
+  fprintf (stream, _("\
   -i --instruction-dump=<number>\n\
                          Disassemble the contents of section <number>\n"));
 #endif
-  fprintf (stdout, _("\
+  fprintf (stream, _("\
   -I --histogram         Display histogram of bucket list lengths\n\
   -W --wide              Allow output width to exceed 80 characters\n\
+  @<file>                Read options from <file>\n\
   -H --help              Display this information\n\
   -v --version           Display the version number of readelf\n"));
-  fprintf (stdout, _("Report bugs to %s\n"), REPORT_BUGS_TO);
+  
+  if (REPORT_BUGS_TO[0] && stream == stdout)
+    fprintf (stdout, _("Report bugs to %s\n"), REPORT_BUGS_TO);
 
-  exit (0);
+  exit (stream == stdout ? 0 : 1);
 }
 
 /* Record the fact that the user wants the contents of section number
@@ -2657,13 +2833,34 @@ request_dump (unsigned int section, int type)
   return;
 }
 
+/* Request a dump by section name.  */
+
+static void
+request_dump_byname (const char *section, int type)
+{
+  struct dump_list_entry *new_request;
+
+  new_request = malloc (sizeof (struct dump_list_entry));
+  if (!new_request)
+    error (_("Out of memory allocating dump request table."));
+
+  new_request->name = strdup (section);
+  if (!new_request->name)
+    error (_("Out of memory allocating dump request table."));
+
+  new_request->type = type;
+
+  new_request->next = dump_sects_byname;
+  dump_sects_byname = new_request;
+}
+
 static void
 parse_args (int argc, char **argv)
 {
   int c;
 
   if (argc < 2)
-    usage ();
+    usage (stderr);
 
   while ((c = getopt_long
          (argc, argv, "ersuahnldSDAINtgw::x:i:vVWH", options, NULL)) != EOF)
@@ -2677,7 +2874,7 @@ parse_args (int argc, char **argv)
          /* Long options.  */
          break;
        case 'H':
-         usage ();
+         usage (stdout);
          break;
 
        case 'a':
@@ -2744,11 +2941,10 @@ parse_args (int argc, char **argv)
          do_dump++;
          section = strtoul (optarg, & cp, 0);
          if (! *cp && section >= 0)
-           {
-             request_dump (section, HEX_DUMP);
-             break;
-           }
-         goto oops;
+           request_dump (section, HEX_DUMP);
+         else
+           request_dump_byname (optarg, HEX_DUMP);
+         break;
        case 'w':
          do_dump++;
          if (optarg == 0)
@@ -2912,12 +3108,14 @@ parse_args (int argc, char **argv)
          do_wide++;
          break;
        default:
+#ifdef SUPPORT_DISASSEMBLY
        oops:
+#endif
          /* xgettext:c-format */
          error (_("Invalid option '-%c'\n"), c);
          /* Drop through.  */
        case '?':
-         usage ();
+         usage (stderr);
        }
     }
 
@@ -2925,11 +3123,11 @@ parse_args (int argc, char **argv)
       && !do_segments && !do_header && !do_dump && !do_version
       && !do_histogram && !do_debugging && !do_arch && !do_notes
       && !do_section_groups)
-    usage ();
+    usage (stderr);
   else if (argc < 3)
     {
       warn (_("Nothing to do.\n"));
-      usage ();
+      usage (stderr);
     }
 }
 
@@ -3039,6 +3237,11 @@ process_file_header (void)
              (long) elf_header.e_shstrndx);
       if (section_headers != NULL && elf_header.e_shstrndx == SHN_XINDEX)
        printf (" (%ld)", (long) section_headers[0].sh_link);
+      else if (elf_header.e_shstrndx != SHN_UNDEF
+              && (elf_header.e_shstrndx >= elf_header.e_shnum
+                  || (elf_header.e_shstrndx >= SHN_LORESERVE
+                      && elf_header.e_shstrndx <= SHN_HIRESERVE)))
+       printf (" <corrupt: out of range>");
       putc ('\n', stdout);
     }
 
@@ -3048,6 +3251,11 @@ process_file_header (void)
        elf_header.e_shnum = section_headers[0].sh_size;
       if (elf_header.e_shstrndx == SHN_XINDEX)
        elf_header.e_shstrndx = section_headers[0].sh_link;
+      else if (elf_header.e_shstrndx != SHN_UNDEF
+              && (elf_header.e_shstrndx >= elf_header.e_shnum
+                  || (elf_header.e_shstrndx >= SHN_LORESERVE
+                      && elf_header.e_shstrndx <= SHN_HIRESERVE)))
+       elf_header.e_shstrndx = SHN_UNDEF;
       free (section_headers);
       section_headers = NULL;
     }
@@ -3332,8 +3540,15 @@ process_program_headers (FILE *file)
            error (_("Unable to find program interpreter name\n"));
          else
            {
+             char fmt [32];
+             int ret = snprintf (fmt, sizeof (fmt), "%%%ds", PATH_MAX);
+
+             if (ret >= (int) sizeof (fmt) || ret < 0)
+               error (_("Internal error: failed to create format string to display program interpreter"));
+
              program_interpreter[0] = 0;
-             fscanf (file, "%63s", program_interpreter);
+             if (fscanf (file, fmt, program_interpreter) <= 0)
+               error (_("Unable to read program interpreter name\n"));
 
              if (do_segments)
                printf (_("\n      [Requesting program interpreter: %s]"),
@@ -3363,21 +3578,7 @@ process_program_headers (FILE *file)
 
          for (j = 1; j < elf_header.e_shnum; j++, section++)
            {
-             if (section->sh_size > 0
-                 /* Compare allocated sections by VMA, unallocated
-                    sections by file offset.  */
-                 && (section->sh_flags & SHF_ALLOC
-                     ? (section->sh_addr >= segment->p_vaddr
-                        && section->sh_addr + section->sh_size
-                        <= segment->p_vaddr + segment->p_memsz)
-                     : ((bfd_vma) section->sh_offset >= segment->p_offset
-                        && (section->sh_offset + section->sh_size
-                            <= segment->p_offset + segment->p_filesz)))
-                 /* .tbss is special.  It doesn't contribute memory space
-                    to normal segments.  */
-                 && (!((section->sh_flags & SHF_TLS) != 0
-                       && section->sh_type == SHT_NOBITS)
-                     || segment->p_type == PT_TLS))
+             if (ELF_IS_SECTION_IN_SEGMENT_MEMORY(section, segment))
                printf ("%s ", SECTION_NAME (section));
            }
 
@@ -3831,7 +4032,8 @@ process_section_headers (FILE *file)
     return 0;
 
   /* Read in the string table, so that we have names to display.  */
-  if (SECTION_HEADER_INDEX (elf_header.e_shstrndx) < elf_header.e_shnum)
+  if (elf_header.e_shstrndx != SHN_UNDEF
+       && SECTION_HEADER_INDEX (elf_header.e_shstrndx) < elf_header.e_shnum)
     {
       section = SECTION_HEADER (elf_header.e_shstrndx);
 
@@ -3869,6 +4071,23 @@ process_section_headers (FILE *file)
          && find_section (".gcc_compiled_long32") == NULL)
        eh_addr_size = 8;
       break;
+
+    case EM_H8_300:
+    case EM_H8_300H:
+      switch (elf_header.e_flags & EF_H8_MACH)
+       {
+       case E_H8_MACH_H8300:
+       case E_H8_MACH_H8300HN:
+       case E_H8_MACH_H8300SN:
+       case E_H8_MACH_H8300SXN:
+         eh_addr_size = 2;
+         break;
+       case E_H8_MACH_H8300H:
+       case E_H8_MACH_H8300S:
+       case E_H8_MACH_H8300SX:
+         eh_addr_size = 4;
+         break;
+       }
     }
 
 #define CHECK_ENTSIZE_VALUES(section, i, size32, size64) \
@@ -3939,7 +4158,7 @@ process_section_headers (FILE *file)
                || do_debug_lines || do_debug_pubnames || do_debug_aranges
                || do_debug_frames || do_debug_macinfo || do_debug_str
                || do_debug_loc || do_debug_ranges)
-              && strneq (name, ".debug_", 7))
+              && const_strneq (name, ".debug_"))
        {
          name += 7;
 
@@ -3959,7 +4178,7 @@ process_section_headers (FILE *file)
        }
       /* linkonce section to be combined with .debug_info at link time.  */
       else if ((do_debugging || do_debug_info)
-              && strneq (name, ".gnu.linkonce.wi.", 17))
+              && const_strneq (name, ".gnu.linkonce.wi."))
        request_dump (i, DEBUG_DUMP);
       else if (do_debug_frames && streq (name, ".eh_frame"))
        request_dump (i, DEBUG_DUMP);
@@ -4579,6 +4798,11 @@ struct absaddr
     bfd_vma offset;
   };
 
+#define ABSADDR(a) \
+  ((a).section \
+   ? section_headers [(a).section].sh_addr + (a).offset \
+   : (a).offset)
+
 struct ia64_unw_aux_info
   {
     struct ia64_unw_table_entry
@@ -4671,7 +4895,7 @@ dump_ia64_unwind (struct ia64_unw_aux_info *aux)
       printf ("], info at +0x%lx\n",
              (unsigned long) (tp->info.offset - aux->seg_base));
 
-      head = aux->info + (tp->info.offset - aux->info_addr);
+      head = aux->info + (ABSADDR (tp->info) - aux->info_addr);
       stamp = byte_get ((unsigned char *) head, sizeof (stamp));
 
       printf ("  v%u, flags=0x%lx (%s%s), len=%lu bytes\n",
@@ -4790,7 +5014,7 @@ slurp_ia64_unwind_table (FILE *file,
              sym = aux->symtab + ELF64_R_SYM (rp->r_info);
            }
 
-         if (! strneq (relname, "R_IA64_SEGREL", 13))
+         if (! const_strneq (relname, "R_IA64_SEGREL"))
            {
              warn (_("Skipping unexpected relocation type %s\n"), relname);
              continue;
@@ -5203,7 +5427,7 @@ slurp_hppa_unwind_table (FILE *file,
            }
 
          /* R_PARISC_SEGREL32 or R_PARISC_SEGREL64.  */
-         if (strncmp (relname, "R_PARISC_SEGREL", 15) != 0)
+         if (! const_strneq (relname, "R_PARISC_SEGREL"))
            {
              warn (_("Skipping unexpected relocation type %s\n"), relname);
              continue;
@@ -6121,6 +6345,15 @@ process_dynamic_section (FILE *file)
            }
          break;
 
+       case DT_GNU_HASH:
+         dynamic_info_DT_GNU_HASH = entry->d_un.d_val;
+         if (do_dynamic)
+           {
+             print_vma (entry->d_un.d_val, PREFIX_HEX);
+             putchar ('\n');
+           }
+         break;
+
        default:
          if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM))
            version_info[DT_VERSIONTAGIDX (entry->d_tag)] =
@@ -6638,6 +6871,8 @@ get_symbol_type (unsigned int type)
     case STT_FILE:     return "FILE";
     case STT_COMMON:   return "COMMON";
     case STT_TLS:      return "TLS";
+    case STT_RELC:      return "RELC";
+    case STT_SRELC:     return "SRELC";
     default:
       if (type >= STT_LOPROC && type <= STT_HIPROC)
        {
@@ -6683,6 +6918,41 @@ get_symbol_visibility (unsigned int visibility)
     }
 }
 
+static const char *
+get_mips_symbol_other (unsigned int other)
+{
+  switch (other)
+    {
+    case STO_OPTIONAL:  return "OPTIONAL";
+    case STO_MIPS16:    return "MIPS16";
+    default:           return NULL;
+    }
+}
+
+static const char *
+get_symbol_other (unsigned int other)
+{
+  const char * result = NULL;
+  static char buff [32];
+
+  if (other == 0)
+    return "";
+
+  switch (elf_header.e_machine)
+    {
+    case EM_MIPS:
+      result = get_mips_symbol_other (other);
+    default:
+      break;
+    }
+
+  if (result)
+    return result;
+
+  snprintf (buff, sizeof buff, _("<other>: %x"), other);
+  return buff;
+}
+
 static const char *
 get_symbol_index_type (unsigned int type)
 {
@@ -6701,6 +6971,12 @@ get_symbol_index_type (unsigned int type)
       else if (elf_header.e_machine == EM_X86_64
               && type == SHN_X86_64_LCOMMON)
        return "LARGE_COM";
+      else if (type == SHN_MIPS_SCOMMON
+              && elf_header.e_machine == EM_MIPS)
+       return "SCOM";
+      else if (type == SHN_MIPS_SUNDEFINED
+              && elf_header.e_machine == EM_MIPS)
+       return "SUND";
       else if (type >= SHN_LOPROC && type <= SHN_HIPROC)
        sprintf (buff, "PRC[0x%04x]", type);
       else if (type >= SHN_LOOS && type <= SHN_HIOS)
@@ -6761,6 +7037,9 @@ process_symbol_table (FILE *file)
   bfd_vma nchains = 0;
   bfd_vma *buckets = NULL;
   bfd_vma *chains = NULL;
+  bfd_vma ngnubuckets = 0;
+  bfd_vma *gnubuckets = NULL;
+  bfd_vma *gnuchains = NULL;
 
   if (! do_syms && !do_histogram)
     return 1;
@@ -6845,6 +7124,11 @@ process_symbol_table (FILE *file)
              printf ("  %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
              printf (" %6s",  get_symbol_binding (ELF_ST_BIND (psym->st_info)));
              printf (" %3s",  get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
+             /* Check to see if any other bits in the st_other field are set.
+                Note - displaying this information disrupts the layout of the
+                table being generated, but for the moment this case is very rare.  */
+             if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))
+               printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)));
              printf (" %3.3s ", get_symbol_index_type (psym->st_shndx));
              if (VALID_DYNAMIC_NAME (psym->st_name))
                print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
@@ -6912,6 +7196,11 @@ process_symbol_table (FILE *file)
              printf (" %-7s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
              printf (" %-6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));
              printf (" %-3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
+             /* Check to see if any other bits in the st_other field are set.
+                Note - displaying this information disrupts the layout of the
+                table being generated, but for the moment this case is very rare.  */
+             if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))
+               printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)));
              printf (" %4s ", get_symbol_index_type (psym->st_shndx));
              print_symbol (25, psym->st_name < strtab_size
                            ? strtab + psym->st_name : "<corrupt>");
@@ -7130,6 +7419,166 @@ process_symbol_table (FILE *file)
       free (chains);
     }
 
+  if (do_histogram && dynamic_info_DT_GNU_HASH)
+    {
+      unsigned char nb[16];
+      bfd_vma i, maxchain = 0xffffffff, symidx, bitmaskwords;
+      unsigned long *lengths;
+      unsigned long *counts;
+      unsigned long hn;
+      unsigned long maxlength = 0;
+      unsigned long nzero_counts = 0;
+      unsigned long nsyms = 0;
+      bfd_vma buckets_vma;
+
+      if (fseek (file,
+                (archive_file_offset
+                 + offset_from_vma (file, dynamic_info_DT_GNU_HASH,
+                                    sizeof nb)),
+                SEEK_SET))
+       {
+         error (_("Unable to seek to start of dynamic information"));
+         return 0;
+       }
+
+      if (fread (nb, 16, 1, file) != 1)
+       {
+         error (_("Failed to read in number of buckets\n"));
+         return 0;
+       }
+
+      ngnubuckets = byte_get (nb, 4);
+      symidx = byte_get (nb + 4, 4);
+      bitmaskwords = byte_get (nb + 8, 4);
+      buckets_vma = dynamic_info_DT_GNU_HASH + 16;
+      if (is_32bit_elf)
+       buckets_vma += bitmaskwords * 4;
+      else
+       buckets_vma += bitmaskwords * 8;
+
+      if (fseek (file,
+                (archive_file_offset
+                 + offset_from_vma (file, buckets_vma, 4)),
+                SEEK_SET))
+       {
+         error (_("Unable to seek to start of dynamic information"));
+         return 0;
+       }
+
+      gnubuckets = get_dynamic_data (file, ngnubuckets, 4);
+
+      if (gnubuckets == NULL)
+       return 0;
+
+      for (i = 0; i < ngnubuckets; i++)
+       if (gnubuckets[i] != 0)
+         {
+           if (gnubuckets[i] < symidx)
+             return 0;
+
+           if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
+             maxchain = gnubuckets[i];
+         }
+
+      if (maxchain == 0xffffffff)
+       return 0;
+
+      maxchain -= symidx;
+
+      if (fseek (file,
+                (archive_file_offset
+                 + offset_from_vma (file, buckets_vma
+                                          + 4 * (ngnubuckets + maxchain), 4)),
+                SEEK_SET))
+       {
+         error (_("Unable to seek to start of dynamic information"));
+         return 0;
+       }
+
+      do
+       {
+         if (fread (nb, 4, 1, file) != 1)
+           {
+             error (_("Failed to determine last chain length\n"));
+             return 0;
+           }
+
+         if (maxchain + 1 == 0)
+           return 0;
+
+         ++maxchain;
+       }
+      while ((byte_get (nb, 4) & 1) == 0);
+
+      if (fseek (file,
+                (archive_file_offset
+                 + offset_from_vma (file, buckets_vma + 4 * ngnubuckets, 4)),
+                SEEK_SET))
+       {
+         error (_("Unable to seek to start of dynamic information"));
+         return 0;
+       }
+
+      gnuchains = get_dynamic_data (file, maxchain, 4);
+
+      if (gnuchains == NULL)
+       return 0;
+
+      lengths = calloc (ngnubuckets, sizeof (*lengths));
+      if (lengths == NULL)
+       {
+         error (_("Out of memory"));
+         return 0;
+       }
+
+      printf (_("\nHistogram for `.gnu.hash' bucket list length (total of %lu buckets):\n"),
+             (unsigned long) ngnubuckets);
+      printf (_(" Length  Number     %% of total  Coverage\n"));
+
+      for (hn = 0; hn < ngnubuckets; ++hn)
+       if (gnubuckets[hn] != 0)
+         {
+           bfd_vma off, length = 1;
+
+           for (off = gnubuckets[hn] - symidx;
+                (gnuchains[off] & 1) == 0; ++off)
+             ++length;
+           lengths[hn] = length;
+           if (length > maxlength)
+             maxlength = length;
+           nsyms += length;
+         }
+
+      counts = calloc (maxlength + 1, sizeof (*counts));
+      if (counts == NULL)
+       {
+         error (_("Out of memory"));
+         return 0;
+       }
+
+      for (hn = 0; hn < ngnubuckets; ++hn)
+       ++counts[lengths[hn]];
+
+      if (ngnubuckets > 0)
+       {
+         unsigned long j;
+         printf ("      0  %-10lu (%5.1f%%)\n",
+                 counts[0], (counts[0] * 100.0) / ngnubuckets);
+         for (j = 1; j <= maxlength; ++j)
+           {
+             nzero_counts += counts[j] * j;
+             printf ("%7lu  %-10lu (%5.1f%%)    %5.1f%%\n",
+                     j, counts[j], (counts[j] * 100.0) / ngnubuckets,
+                     (nzero_counts * 100.0) / nsyms);
+           }
+       }
+
+      free (counts);
+      free (lengths);
+      free (gnubuckets);
+      free (gnuchains);
+    }
+
   return 1;
 }
 
@@ -7215,6 +7664,7 @@ disassemble_section (Elf_Internal_Shdr *section, FILE *file)
 static int
 dump_section (Elf_Internal_Shdr *section, FILE *file)
 {
+  Elf_Internal_Shdr *relsec;
   bfd_size_type bytes;
   bfd_vma addr;
   unsigned char *data;
@@ -7238,6 +7688,26 @@ dump_section (Elf_Internal_Shdr *section, FILE *file)
   if (!start)
     return 0;
 
+  /* If the section being dumped has relocations against it the user might
+     be expecting these relocations to have been applied.  Check for this
+     case and issue a warning message in order to avoid confusion.
+     FIXME: Maybe we ought to have an option that dumps a section with
+     relocs applied ?  */
+  for (relsec = section_headers;
+       relsec < section_headers + elf_header.e_shnum;
+       ++relsec)
+    {
+      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
+         || SECTION_HEADER_INDEX (relsec->sh_link) >= elf_header.e_shnum)
+       continue;
+
+      printf (_(" NOTE: This section has relocations against it, but these have NOT been applied to this dump.\n"));
+      break;
+    }
+  
   data = start;
 
   while (bytes)
@@ -7250,34 +7720,15 @@ dump_section (Elf_Internal_Shdr *section, FILE *file)
 
       printf ("  0x%8.8lx ", (unsigned long) addr);
 
-      switch (elf_header.e_ident[EI_DATA])
+      for (j = 0; j < 16; j++)
        {
-       default:
-       case ELFDATA2LSB:
-         for (j = 15; j >= 0; j --)
-           {
-             if (j < lbytes)
-               printf ("%2.2x", data[j]);
-             else
-               printf ("  ");
-
-             if (!(j & 0x3))
-               printf (" ");
-           }
-         break;
-
-       case ELFDATA2MSB:
-         for (j = 0; j < 16; j++)
-           {
-             if (j < lbytes)
-               printf ("%2.2x", data[j]);
-             else
-               printf ("  ");
+         if (j < lbytes)
+           printf ("%2.2x", data[j]);
+         else
+           printf ("  ");
 
-             if ((j & 3) == 3)
-               printf (" ");
-           }
-         break;
+         if ((j & 3) == 3)
+           printf (" ");
        }
 
       for (j = 0; j < lbytes; j++)
@@ -7298,9 +7749,47 @@ dump_section (Elf_Internal_Shdr *section, FILE *file)
 
   free (start);
 
+  putchar ('\n');
   return 1;
 }
 
+/* Return the number of bytes affected by a given reloc.
+   This information is architecture and reloc dependent.
+   Returns 4 by default, although this is not always correct.
+   It should return 0 if a decision cannot be made.
+   FIXME: This is not the correct way to solve this problem.
+   The proper way is to have target specific reloc sizing functions
+   created by the reloc-macros.h header, in the same way that it
+   already creates the reloc naming functions.  */
+
+static unsigned int
+get_reloc_size (Elf_Internal_Rela * reloc)
+{
+  switch (elf_header.e_machine)
+    {
+    case EM_H8S:
+    case EM_H8_300:
+    case EM_H8_300H:
+    case EM_H8_500:
+      switch (ELF32_R_TYPE (reloc->r_info))
+       {
+         /* PR gas/3800 - without this information we do not correctly
+            decode the debug information generated by the h8300 assembler.  */
+       case R_H8_DIR16:
+         return 2;
+       default:
+         return 4;
+       }
+    default:
+      /* FIXME: We need to extend this switch statement to cope with other
+        architecture's relocs.  (When those relocs are used against debug
+        sections, and when their size is not 4).  But see the multiple
+        inclusions of <elf/h8.h> for an example of the hoops that we need
+        to jump through in order to obtain the reloc numbers.  */
+      return 4;
+    }
+}
+
 /* Apply addends of RELA relocations.  */
 
 static int
@@ -7310,15 +7799,10 @@ debug_apply_rela_addends (void *file,
 {
   Elf_Internal_Shdr *relsec;
   unsigned char *end = start + section->sh_size;
-  /* FIXME: The relocation field size is relocation type dependent.  */
-  unsigned int reloc_size = 4;
 
   if (!is_relocatable)
     return 1;
 
-  if (section->sh_size < reloc_size)
-    return 1;
-
   for (relsec = section_headers;
        relsec < section_headers + elf_header.e_shnum;
        ++relsec)
@@ -7346,6 +7830,16 @@ debug_apply_rela_addends (void *file,
       for (rp = rela; rp < rela + nrelas; ++rp)
        {
          unsigned char *loc;
+         unsigned int reloc_size;
+
+         reloc_size = get_reloc_size (rp);
+         if (reloc_size == 0)
+           {
+             warn (_("skipping relocation of unknown size against offset 0x%lx in section %s\n"),
+                   (unsigned long) rp->r_offset,
+                   SECTION_NAME (section));
+             continue;
+           }
 
          loc = start + rp->r_offset;
          if ((loc + reloc_size) > end)
@@ -7362,6 +7856,10 @@ debug_apply_rela_addends (void *file,
 
              if (ELF32_R_SYM (rp->r_info) != 0
                  && ELF32_ST_TYPE (sym->st_info) != STT_SECTION
+                 /* Relocations against symbols without type can happen.
+                    Gcc -feliminate-dwarf2-dups may generate symbols
+                    without type for debug info.  */
+                 && ELF32_ST_TYPE (sym->st_info) != STT_NOTYPE
                  /* Relocations against object symbols can happen,
                     eg when referencing a global array.  For an
                     example of this see the _clz.o binary in libgcc.a.  */
@@ -7391,6 +7889,7 @@ debug_apply_rela_addends (void *file,
 
              if (ELF64_R_SYM (rp->r_info) != 0
                  && ELF64_ST_TYPE (sym->st_info) != STT_SECTION
+                 && ELF64_ST_TYPE (sym->st_info) != STT_NOTYPE
                  && ELF64_ST_TYPE (sym->st_info) != STT_OBJECT)
                {
                  warn (_("skipping unexpected symbol type %s in relocation in section .rela.%s\n"),
@@ -7467,7 +7966,7 @@ display_debug_section (Elf_Internal_Shdr *section, FILE *file)
       return 0;
     }
 
-  if (strneq (name, ".gnu.linkonce.wi.", 17))
+  if (const_strneq (name, ".gnu.linkonce.wi."))
     name = ".debug_info";
 
   /* See if we know how to display the contents of this section.  */
@@ -7496,6 +7995,32 @@ display_debug_section (Elf_Internal_Shdr *section, FILE *file)
   return result;
 }
 
+/* Set DUMP_SECTS for all sections where dumps were requested
+   based on section name.  */
+
+static void
+initialise_dumps_byname (void)
+{
+  struct dump_list_entry *cur;
+
+  for (cur = dump_sects_byname; cur; cur = cur->next)
+    {
+      unsigned int i;
+      int any;
+
+      for (i = 0, any = 0; i < elf_header.e_shnum; i++)
+       if (streq (SECTION_NAME (section_headers + i), cur->name))
+         {
+           request_dump (i, cur->type);
+           any = 1;
+         }
+
+      if (!any)
+       warn (_("Section '%s' was not dumped because it does not exist!\n"),
+             cur->name);
+    }
+}
+
 static void
 process_section_contents (FILE *file)
 {
@@ -7505,6 +8030,8 @@ process_section_contents (FILE *file)
   if (! do_dump)
     return;
 
+  initialise_dumps_byname ();
+
   for (i = 0, section = section_headers;
        i < elf_header.e_shnum && i < num_dump_sects;
        i++, section++)
@@ -7564,7 +8091,8 @@ static const char *arm_attr_tag_CPU_arch[] =
 static const char *arm_attr_tag_ARM_ISA_use[] = {"No", "Yes"};
 static const char *arm_attr_tag_THUMB_ISA_use[] =
   {"No", "Thumb-1", "Thumb-2"};
-static const char *arm_attr_tag_VFP_arch[] = {"No", "VFPv1", "VFPv2"};
+/* FIXME: VFPv3 encoding was extrapolated!  */
+static const char *arm_attr_tag_VFP_arch[] = {"No", "VFPv1", "VFPv2", "VFPv3"};
 static const char *arm_attr_tag_WMMX_arch[] = {"No", "WMMXv1"};
 static const char *arm_attr_tag_NEON_arch[] = {"No", "NEONv1"};
 static const char *arm_attr_tag_ABI_PCS_config[] =
@@ -7606,7 +8134,7 @@ static const char *arm_attr_tag_ABI_FP_optimization_goals[] =
 
 #define LOOKUP(id, name) \
   {id, #name, 0x80 | ARRAY_SIZE(arm_attr_tag_##name), arm_attr_tag_##name}
-static arm_attr_public_tag arm_attr_public_tags[] = 
+static arm_attr_public_tag arm_attr_public_tags[] =
 {
   {4, "CPU_raw_name", 1, NULL},
   {5, "CPU_name", 1, NULL},
@@ -7783,7 +8311,7 @@ process_arm_specific (FILE *file)
 
       contents = get_data (NULL, file, sect->sh_offset, 1, sect->sh_size,
                           _("attributes"));
-      
+
       if (!contents)
        continue;
       p = contents;
@@ -7873,7 +8401,7 @@ process_arm_specific (FILE *file)
        {
          printf (_("Unknown format '%c'\n"), *p);
        }
-       
+
       free(contents);
     }
   return 1;
@@ -8483,7 +9011,7 @@ process_note (Elf_Internal_Note *pnote)
        note type strings.  */
     nt = get_note_type (pnote->type);
 
-  else if (strneq (pnote->namedata, "NetBSD-CORE", 11))
+  else if (const_strneq (pnote->namedata, "NetBSD-CORE"))
     /* NetBSD-specific core file notes.  */
     nt = get_netbsd_elfcore_note_type (pnote->type);
 
@@ -8797,7 +9325,7 @@ process_object (char *file_name, FILE *file)
       assert (num_dump_sects >= num_cmdline_dump_sects);
       memcpy (dump_sects, cmdline_dump_sects, num_cmdline_dump_sects);
     }
-  
+
   if (! process_file_header ())
     return 1;
 
@@ -8931,7 +9459,7 @@ process_archive (char *file_name, FILE *file)
       return 1;
     }
 
-  if (memcmp (arhdr.ar_name, "/               ", 16) == 0)
+  if (const_strneq (arhdr.ar_name, "/               "))
     {
       /* This is the archive symbol table.  Skip it.
         FIXME: We should have an option to dump it.  */
@@ -8953,7 +9481,7 @@ process_archive (char *file_name, FILE *file)
        }
     }
 
-  if (memcmp (arhdr.ar_name, "//              ", 16) == 0)
+  if (const_strneq (arhdr.ar_name, "//              "))
     {
       /* This is the archive string table holding long member
         names.  */
@@ -9043,7 +9571,7 @@ process_archive (char *file_name, FILE *file)
 
       archive_file_offset = ftell (file);
       archive_file_size = strtoul (arhdr.ar_size, NULL, 10);
-      
+
       ret |= process_object (namealc, file);
 
       free (namealc);