]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - binutils/readelf.c
Oops, changelog for last patch.
[thirdparty/binutils-gdb.git] / binutils / readelf.c
index 9fea0771e2cb717e0c652d213dca72ccc82ad816..73a98b5c44b2576f7f7cc8234ca80a49d7dfc74e 100644 (file)
@@ -2,7 +2,7 @@
    Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
    Originally developed by Eric Youngdale <eric@andante.jic.com>
-   Modifications by Nick Clifton <nickc@cygnus.com>
+   Modifications by Nick Clifton <nickc@redhat.com>
 
    This file is part of GNU Binutils.
 
 #include "elf/mn10200.h"
 #include "elf/mn10300.h"
 #include "elf/hppa.h"
+#include "elf/h8.h"
 #include "elf/arc.h"
 #include "elf/fr30.h"
 #include "elf/mcore.h"
+#include "elf/mmix.h"
 #include "elf/i960.h"
 #include "elf/pj.h"
 #include "elf/avr.h"
@@ -75,6 +77,7 @@
 #include "elf/i860.h"
 #include "elf/x86-64.h"
 #include "elf/s390.h"
+#include "elf/xstormy16.h"
 
 #include "bucomm.h"
 #include "getopt.h"
@@ -110,6 +113,7 @@ 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;
@@ -119,6 +123,8 @@ int                     do_debug_pubnames;
 int                     do_debug_aranges;
 int                     do_debug_frames;
 int                     do_debug_frames_interp;
+int                    do_debug_macinfo;
+int                    do_debug_str;
 int                     do_arch;
 int                     do_notes;
 int                    is_32bit_elf;
@@ -183,13 +189,16 @@ static void               dynamic_segment_mips_val    PARAMS ((Elf_Internal_Dyn
 static void               dynamic_segment_parisc_val  PARAMS ((Elf_Internal_Dyn *));
 static int                process_dynamic_segment     PARAMS ((FILE *));
 static int                process_symbol_table        PARAMS ((FILE *));
+static int                process_syminfo             PARAMS ((FILE *));
 static int                process_section_contents    PARAMS ((FILE *));
-static void               process_file                PARAMS ((char *));
+static void               process_mips_fpe_exception  PARAMS ((int));
+static int                process_mips_specific       PARAMS ((FILE *));
+static int                process_file                PARAMS ((char *));
 static int                process_relocs              PARAMS ((FILE *));
 static int                process_version_sections    PARAMS ((FILE *));
 static char *             get_ver_flags               PARAMS ((unsigned int));
-static int                get_32bit_section_headers   PARAMS ((FILE *));
-static int                get_64bit_section_headers   PARAMS ((FILE *));
+static int                get_32bit_section_headers   PARAMS ((FILE *, unsigned int));
+static int                get_64bit_section_headers   PARAMS ((FILE *, unsigned int));
 static int               get_32bit_program_headers   PARAMS ((FILE *, Elf_Internal_Phdr *));
 static int               get_64bit_program_headers   PARAMS ((FILE *, Elf_Internal_Phdr *));
 static int                get_file_header             PARAMS ((FILE *));
@@ -206,11 +215,18 @@ static int                  dump_section                PARAMS ((Elf32_Internal_Shdr *,
 static int               display_debug_section       PARAMS ((Elf32_Internal_Shdr *, FILE *));
 static int                display_debug_info          PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 static int                display_debug_not_supported PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+static int                prescan_debug_info          PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 static int                display_debug_lines         PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_pubnames      PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 static int                display_debug_abbrev        PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 static int                display_debug_aranges       PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 static int                display_debug_frames        PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_macinfo       PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_str           PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 static unsigned char *    process_abbrev_section      PARAMS ((unsigned char *, unsigned char *));
+static void               load_debug_str              PARAMS ((FILE *));
+static void               free_debug_str              PARAMS ((void));
+static const char *       fetch_indirect_string       PARAMS ((unsigned long));
 static unsigned long      read_leb128                 PARAMS ((unsigned char *, int *, int));
 static int                process_extended_line_op    PARAMS ((unsigned char *, int, int));
 static void               reset_state_machine         PARAMS ((int));
@@ -221,18 +237,20 @@ static void               free_abbrevs                PARAMS ((void));
 static void               add_abbrev                  PARAMS ((unsigned long, unsigned long, int));
 static void               add_abbrev_attr             PARAMS ((unsigned long, unsigned long));
 static unsigned char *    read_and_display_attr       PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long, unsigned long));
+static unsigned char *    read_and_display_attr_value PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long, unsigned long));
 static unsigned char *    display_block               PARAMS ((unsigned char *, unsigned long));
 static void               decode_location_expression  PARAMS ((unsigned char *, unsigned int, unsigned long));
-static void              request_dump                PARAMS ((unsigned int, char));
-static const char *       get_elf_class               PARAMS ((unsigned char));
-static const char *       get_data_encoding           PARAMS ((unsigned char));
-static const char *       get_osabi_name              PARAMS ((unsigned char));
+static void              request_dump                PARAMS ((unsigned int, int));
+static const char *       get_elf_class               PARAMS ((unsigned int));
+static const char *       get_data_encoding           PARAMS ((unsigned int));
+static const char *       get_osabi_name              PARAMS ((unsigned int));
 static int               guess_is_rela               PARAMS ((unsigned long));
 static char *            get_note_type                  PARAMS ((unsigned int));
 static int               process_note                   PARAMS ((Elf32_Internal_Note *));
 static int               process_corefile_note_segment  PARAMS ((FILE *, bfd_vma, bfd_vma));
 static int               process_corefile_note_segments PARAMS ((FILE *));
 static int               process_corefile_contents      PARAMS ((FILE *));
+static int               process_arch_specific          PARAMS ((FILE *));
 
 typedef int Elf32_Word;
 
@@ -264,68 +282,34 @@ typedef int Elf32_Word;
 #define BYTE_GET8(field)       byte_get (field, 8)
 #endif
 
-#define NUM_ELEM(array)        (sizeof (array) / sizeof ((array)[0]))
+#define NUM_ELEM(array)        (sizeof (array) / sizeof ((array)[0]))
 
 #define GET_ELF_SYMBOLS(file, offset, size)                    \
   (is_32bit_elf ? get_32bit_elf_symbols (file, offset, size)   \
    : get_64bit_elf_symbols (file, offset, size))
 
 
-#ifdef ANSI_PROTOTYPES
 static void
-error (const char * message, ...)
+error VPARAMS ((const char *message, ...))
 {
-  va_list args;
+  VA_OPEN (args, message);
+  VA_FIXEDARG (args, const char *, message);
 
   fprintf (stderr, _("%s: Error: "), program_name);
-  va_start (args, message);
   vfprintf (stderr, message, args);
-  va_end (args);
-  return;
-}
-
-static void
-warn (const char * message, ...)
-{
-  va_list args;
-
-  fprintf (stderr, _("%s: Warning: "), program_name);
-  va_start (args, message);
-  vfprintf (stderr, message, args);
-  va_end (args);
-  return;
-}
-#else
-static void
-error (va_alist)
-     va_dcl
-{
-  char * message;
-  va_list args;
-
-  fprintf (stderr, _("%s: Error: "), program_name);
-  va_start (args);
-  message = va_arg (args, char *);
-  vfprintf (stderr, message, args);
-  va_end (args);
-  return;
+  VA_CLOSE (args);
 }
 
 static void
-warn (va_alist)
-     va_dcl
+warn VPARAMS ((const char *message, ...))
 {
-  char * message;
-  va_list args;
+  VA_OPEN (args, message);
+  VA_FIXEDARG (args, const char *, message);
 
   fprintf (stderr, _("%s: Warning: "), program_name);
-  va_start (args);
-  message = va_arg (args, char *);
   vfprintf (stderr, message, args);
-  va_end (args);
-  return;
+  VA_CLOSE (args);
 }
-#endif
 
 static PTR get_data PARAMS ((PTR, FILE *, long, size_t, const char *));
 
@@ -464,7 +448,7 @@ print_vma (vma, mode)
          printf ("%lx", vma);
 #else
          if (_bfd_int64_high (vma))
-           printf ("%lx%lx", _bfd_int64_high (vma), _bfd_int64_low (vma));
+           printf ("%lx%8.8lx", _bfd_int64_high (vma), _bfd_int64_low (vma));
          else
            printf ("%lx", _bfd_int64_low (vma));
 #endif
@@ -573,7 +557,9 @@ guess_is_rela (e_machine)
     case EM_386:
     case EM_486:
     case EM_960:
+    case EM_M32R:
     case EM_CYGNUS_M32R:
+    case EM_D10V:
     case EM_CYGNUS_D10V:
     case EM_MIPS:
     case EM_MIPS_RS3_LE:
@@ -581,25 +567,36 @@ guess_is_rela (e_machine)
 
       /* 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_V850:
     case EM_CYGNUS_V850:
+    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_SH:
     case EM_ALPHA:
     case EM_MCORE:
     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_MMIX:
+    case EM_XSTORMY16:
       return TRUE;
 
     case EM_MMA:
@@ -802,12 +799,24 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
        return 0;
     }
 
-  if (is_rela)
-    printf
-      (_("  Offset    Info  Type            Symbol's Value  Symbol's Name          Addend\n"));
+  if (is_32bit_elf)
+    {
+      if (is_rela)
+       printf
+         (_(" Offset     Info    Type            Symbol's Value  Symbol's Name          Addend\n"));
+      else
+       printf
+         (_(" Offset     Info    Type            Symbol's Value  Symbol's Name\n"));
+    }
   else
-    printf
-      (_("  Offset    Info  Type            Symbol's Value  Symbol's Name\n"));
+    {
+      if (is_rela)
+       printf
+         (_("    Offset             Info            Type               Symbol's Value   Symbol's Name           Addend\n"));
+      else
+       printf
+         (_("    Offset             Info            Type               Symbol's Value   Symbol's Name\n"));
+    }
 
   for (i = 0; i < rel_size; i++)
     {
@@ -847,11 +856,26 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
 #endif
        }
 
+      if (is_32bit_elf)
+       {
 #ifdef _bfd_int64_low
-      printf ("  %8.8lx  %5.5lx ", _bfd_int64_low (offset), _bfd_int64_low (info));
+         printf ("%8.8lx  %8.8lx ", _bfd_int64_low (offset), _bfd_int64_low (info));
 #else
-      printf ("  %8.8lx  %5.5lx ", offset, info);
+         printf ("%8.8lx  %8.8lx ", offset, info);
 #endif
+       }
+      else
+       {
+#ifdef _bfd_int64_low
+         printf ("%8.8lx%8.8lx  %8.8lx%8.8lx ",
+                 _bfd_int64_high (offset),
+                 _bfd_int64_low (offset),
+                 _bfd_int64_high (info),
+                 _bfd_int64_low (info));
+#else
+         printf ("%16.16lx  %16.16lx ", offset, info);
+#endif
+       }
 
       switch (elf_header.e_machine)
        {
@@ -859,6 +883,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = NULL;
          break;
 
+       case EM_M32R:
        case EM_CYGNUS_M32R:
          rtype = elf_m32r_reloc_type (type);
          break;
@@ -877,6 +902,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          break;
 
        case EM_AVR:
+       case EM_AVR_OLD:
          rtype = elf_avr_reloc_type (type);
          break;
 
@@ -887,14 +913,17 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = elf_sparc_reloc_type (type);
          break;
 
+       case EM_V850:
        case EM_CYGNUS_V850:
          rtype = v850_reloc_type (type);
          break;
 
+       case EM_D10V:
        case EM_CYGNUS_D10V:
          rtype = elf_d10v_reloc_type (type);
          break;
 
+       case EM_D30V:
        case EM_CYGNUS_D30V:
          rtype = elf_d30v_reloc_type (type);
          break;
@@ -903,14 +932,17 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = elf_sh_reloc_type (type);
          break;
 
+       case EM_MN10300:
        case EM_CYGNUS_MN10300:
          rtype = elf_mn10300_reloc_type (type);
          break;
 
+       case EM_MN10200:
        case EM_CYGNUS_MN10200:
          rtype = elf_mn10200_reloc_type (type);
          break;
 
+       case EM_FR30:
        case EM_CYGNUS_FR30:
          rtype = elf_fr30_reloc_type (type);
          break;
@@ -919,7 +951,12 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = elf_mcore_reloc_type (type);
          break;
 
+       case EM_MMIX:
+         rtype = elf_mmix_reloc_type (type);
+         break;
+
        case EM_PPC:
+       case EM_PPC64:
          rtype = elf_ppc_reloc_type (type);
          break;
 
@@ -936,7 +973,6 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = elf_arm_reloc_type (type);
          break;
 
-       case EM_CYGNUS_ARC:
        case EM_ARC:
          rtype = elf_arc_reloc_type (type);
          break;
@@ -945,7 +981,14 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = elf_hppa_reloc_type (type);
          break;
 
+       case EM_H8_300:
+       case EM_H8_300H:
+       case EM_H8S:
+         rtype = elf_h8_reloc_type (type);
+         break;
+
        case EM_PJ:
+       case EM_PJ_OLD:
          rtype = elf_pj_reloc_type (type);
          break;
        case EM_IA_64:
@@ -968,6 +1011,10 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
         case EM_S390:
           rtype = elf_s390_reloc_type (type);
           break;
+
+       case EM_XSTORMY16:
+         rtype = elf_xstormy16_reloc_type (type);
+         break;
        }
 
       if (rtype == NULL)
@@ -1309,14 +1356,21 @@ get_machine_name (e_machine)
     case EM_COLDFIRE:          return "Motorola Coldfire";
     case EM_68HC12:            return "Motorola M68HC12";
     case EM_ALPHA:             return "Alpha";
-    case EM_CYGNUS_D10V:        return "d10v";
-    case EM_CYGNUS_D30V:        return "d30v";
-    case EM_CYGNUS_ARC:                return "ARC";
-    case EM_CYGNUS_M32R:       return "Mitsubishi M32r";
-    case EM_CYGNUS_V850:       return "NEC v850";
-    case EM_CYGNUS_MN10300:    return "mn10300";
-    case EM_CYGNUS_MN10200:    return "mn10200";
-    case EM_CYGNUS_FR30:       return "Fujitsu FR30";
+    case EM_CYGNUS_D10V:
+    case EM_D10V:              return "d10v";
+    case EM_CYGNUS_D30V:
+    case EM_D30V:              return "d30v";
+    case EM_CYGNUS_M32R:
+    case EM_M32R:              return "Mitsubishi M32r";
+    case EM_CYGNUS_V850:
+    case EM_V850:              return "NEC v850";
+    case EM_CYGNUS_MN10300:
+    case EM_MN10300:           return "mn10300";
+    case EM_CYGNUS_MN10200:
+    case EM_MN10200:           return "mn10200";
+    case EM_CYGNUS_FR30:
+    case EM_FR30:              return "Fujitsu FR30";
+    case EM_PJ_OLD:
     case EM_PJ:                 return "picoJava";
     case EM_MMA:               return "Fujitsu Multimedia Accelerator";
     case EM_PCP:               return "Siemens PCP";
@@ -1336,6 +1390,7 @@ get_machine_name (e_machine)
     case EM_SVX:               return "Silicon Graphics SVx";
     case EM_ST19:              return "STMicroelectronics ST19 8-bit microcontroller";
     case EM_VAX:               return "Digital VAX";
+    case EM_AVR_OLD:
     case EM_AVR:                return "Atmel AVR 8-bit microcontroller";
     case EM_CRIS:              return "Axis Communications 32-bit embedded processor";
     case EM_JAVELIN:           return "Infineon Technologies 32-bit embedded cpu";
@@ -1347,6 +1402,7 @@ get_machine_name (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_XSTORMY16:         return "Sanyo Xstormy16 CPU core";
     default:
       sprintf (buff, _("<unknown>: %x"), e_machine);
       return buff;
@@ -1531,6 +1587,7 @@ get_machine_flags (e_flags, e_machine)
            strcat (buf, ", relocatable-lib");
          break;
 
+       case EM_V850:
        case EM_CYGNUS_V850:
          switch (e_flags & EF_V850_ARCH)
            {
@@ -1549,6 +1606,7 @@ get_machine_flags (e_flags, e_machine)
            }
          break;
 
+       case EM_M32R:
        case EM_CYGNUS_M32R:
          if ((e_flags & EF_M32R_ARCH) == E_M32R_ARCH)
            strcat (buf, ", m32r");
@@ -1566,9 +1624,15 @@ get_machine_flags (e_flags, e_machine)
          if (e_flags & EF_MIPS_CPIC)
            strcat (buf, ", cpic");
 
+         if (e_flags & EF_MIPS_UCODE)
+           strcat (buf, ", ugen_reserved");
+
          if (e_flags & EF_MIPS_ABI2)
            strcat (buf, ", abi2");
 
+         if (e_flags & EF_MIPS_32BITMODE)
+           strcat (buf, ", 32bitmode");
+
          if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1)
            strcat (buf, ", mips1");
 
@@ -1597,7 +1661,6 @@ get_machine_flags (e_flags, e_machine)
            case E_MIPS_MACH_4100: strcat (buf, ", 4100"); break;
            case E_MIPS_MACH_4650: strcat (buf, ", 4650"); break;
            case E_MIPS_MACH_4111: strcat (buf, ", 4111"); break;
-           case E_MIPS_MACH_MIPS32_4K: strcat (buf, ", mips32-4k"); break;
            case E_MIPS_MACH_SB1:  strcat (buf, ", sb1");  break;
            default: strcat (buf, " UNKNOWN"); break;
            }
@@ -1659,6 +1722,7 @@ get_machine_flags (e_flags, e_machine)
          break;
 
        case EM_PJ:
+       case EM_PJ_OLD:
          if ((e_flags & EF_PICOJAVA_NEWCALLS) == EF_PICOJAVA_NEWCALLS)
            strcat (buf, ", new calling convention");
 
@@ -1763,6 +1827,9 @@ get_segment_type (p_type)
     case PT_SHLIB:      return "SHLIB";
     case PT_PHDR:       return "PHDR";
 
+    case PT_GNU_EH_FRAME:
+                       return "GNU_EH_FRAME";
+
     default:
       if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
        {
@@ -1954,12 +2021,12 @@ get_section_type_name (sh_type)
          if (result != NULL)
            return result;
 
-         sprintf (buff, "SHT_LOPROC+%x", sh_type - SHT_LOPROC);
+         sprintf (buff, "LOPROC+%x", sh_type - SHT_LOPROC);
        }
       else if ((sh_type >= SHT_LOOS) && (sh_type <= SHT_HIOS))
-       sprintf (buff, "SHT_LOOS+%x", sh_type - SHT_LOOS);
+       sprintf (buff, "LOOS+%x", sh_type - SHT_LOOS);
       else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
-       sprintf (buff, "SHT_LOUSER+%x", sh_type - SHT_LOUSER);
+       sprintf (buff, "LOUSER+%x", sh_type - SHT_LOUSER);
       else
        sprintf (buff, _("<unknown>: %x"), sh_type);
 
@@ -1993,6 +2060,7 @@ struct option options [] =
 #endif
 
   {"version",          no_argument, 0, 'v'},
+  {"wide",             no_argument, 0, 'W'},
   {"help",             no_argument, 0, 'H'},
   {0,                  no_argument, 0, 0}
 };
@@ -2019,7 +2087,7 @@ usage ()
   fprintf (stdout, _("  -D or --use-dynamic       Use the dynamic section info when displaying symbols\n"));
   fprintf (stdout, _("  -x <number> or --hex-dump=<number>\n"));
   fprintf (stdout, _("                            Dump the contents of section <number>\n"));
-  fprintf (stdout, _("  -w[liaprf] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=frames]\n"));
+  fprintf (stdout, _("  -w[liaprmfs] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str]\n"));
   fprintf (stdout, _("                            Display the contents of DWARF2 debug sections\n"));
 #ifdef SUPPORT_DISASSEMBLY
   fprintf (stdout, _("  -i <number> or --instruction-dump=<number>\n"));
@@ -2027,6 +2095,7 @@ usage ()
 #endif
   fprintf (stdout, _("  -I or --histogram         Display histogram of bucket list lengths\n"));
   fprintf (stdout, _("  -v or --version           Display the version number of readelf\n"));
+  fprintf (stdout, _("  -W or --wide              Don't split lines to fit into 80 columns\n"));
   fprintf (stdout, _("  -H or --help              Display this information\n"));
   fprintf (stdout, _("Report bugs to %s\n"), REPORT_BUGS_TO);
 
@@ -2036,7 +2105,7 @@ usage ()
 static void
 request_dump (section, type)
      unsigned int section;
-     char         type;
+     int         type;
 {
   if (section >= num_dump_sects)
     {
@@ -2075,7 +2144,7 @@ parse_args (argc, argv)
     usage ();
 
   while ((c = getopt_long
-         (argc, argv, "ersuahnldSDAIw::x:i:vV", options, NULL)) != EOF)
+         (argc, argv, "ersuahnldSDAIw::x:i:vVW", options, NULL)) != EOF)
     {
       char *    cp;
       int      section;
@@ -2155,44 +2224,58 @@ parse_args (argc, argv)
            do_debugging = 1;
          else
            {
+             unsigned int index = 0;
+             
              do_debugging = 0;
-             switch (optarg[0])
-               {
-               case 'i':
-               case 'I':
-                 do_debug_info = 1;
-                 break;
 
-               case 'a':
-               case 'A':
-                 do_debug_abbrevs = 1;
-                 break;
+             while (optarg[index])
+               switch (optarg[index++])
+                 {
+                 case 'i':
+                 case 'I':
+                   do_debug_info = 1;
+                   break;
 
-               case 'l':
-               case 'L':
-                 do_debug_lines = 1;
-                 break;
+                 case 'a':
+                 case 'A':
+                   do_debug_abbrevs = 1;
+                   break;
 
-               case 'p':
-               case 'P':
-                 do_debug_pubnames = 1;
-                 break;
+                 case 'l':
+                 case 'L':
+                   do_debug_lines = 1;
+                   break;
 
-               case 'r':
-               case 'R':
-                 do_debug_aranges = 1;
-                 break;
+                 case 'p':
+                 case 'P':
+                   do_debug_pubnames = 1;
+                   break;
 
-               case 'F':
-                 do_debug_frames_interp = 1;
-               case 'f':
-                 do_debug_frames = 1;
-                 break;
+                 case 'r':
+                 case 'R':
+                   do_debug_aranges = 1;
+                   break;
 
-               default:
-                 warn (_("Unrecognised debug option '%s'\n"), optarg);
-                 break;
-               }
+                 case 'F':
+                   do_debug_frames_interp = 1;
+                 case 'f':
+                   do_debug_frames = 1;
+                   break;
+
+                 case 'm':
+                 case 'M':
+                   do_debug_macinfo = 1;
+                   break;
+
+                 case 's':
+                 case 'S':
+                   do_debug_str = 1;
+                   break;
+
+                 default:
+                   warn (_("Unrecognised debug option '%s'\n"), optarg);
+                   break;
+                 }
            }
          break;
 #ifdef SUPPORT_DISASSEMBLY
@@ -2212,6 +2295,9 @@ parse_args (argc, argv)
        case 'V':
          do_version ++;
          break;
+       case 'W':
+         do_wide ++;
+         break;
        default:
        oops:
          /* xgettext:c-format */
@@ -2235,15 +2321,15 @@ parse_args (argc, argv)
 
 static const char *
 get_elf_class (elf_class)
-     unsigned char elf_class;
+     unsigned int elf_class;
 {
   static char buff [32];
 
   switch (elf_class)
     {
     case ELFCLASSNONE: return _("none");
-    case ELFCLASS32:   return _("ELF32");
-    case ELFCLASS64:   return _("ELF64");
+    case ELFCLASS32:   return "ELF32";
+    case ELFCLASS64:   return "ELF64";
     default:
       sprintf (buff, _("<unknown: %x>"), elf_class);
       return buff;
@@ -2252,7 +2338,7 @@ get_elf_class (elf_class)
 
 static const char *
 get_data_encoding (encoding)
-     unsigned char encoding;
+     unsigned int encoding;
 {
   static char buff [32];
 
@@ -2269,26 +2355,26 @@ get_data_encoding (encoding)
 
 static const char *
 get_osabi_name (osabi)
-     unsigned char osabi;
+     unsigned int osabi;
 {
   static char buff [32];
 
   switch (osabi)
     {
-    case ELFOSABI_NONE:       return _("UNIX - System V");
-    case ELFOSABI_HPUX:       return _("UNIX - HP-UX");
-    case ELFOSABI_NETBSD:     return _("UNIX - NetBSD");
-    case ELFOSABI_LINUX:      return _("UNIX - Linux");
-    case ELFOSABI_HURD:       return _("GNU/Hurd");
-    case ELFOSABI_SOLARIS:    return _("UNIX - Solaris");
-    case ELFOSABI_AIX:        return _("UNIX - AIX");
-    case ELFOSABI_IRIX:       return _("UNIX - IRIX");
-    case ELFOSABI_FREEBSD:    return _("UNIX - FreeBSD");
-    case ELFOSABI_TRU64:      return _("UNIX - TRU64");
-    case ELFOSABI_MODESTO:    return _("Novell - Modesto");
-    case ELFOSABI_OPENBSD:    return _("UNIX - OpenBSD");
+    case ELFOSABI_NONE:       return "UNIX - System V";
+    case ELFOSABI_HPUX:       return "UNIX - HP-UX";
+    case ELFOSABI_NETBSD:     return "UNIX - NetBSD";
+    case ELFOSABI_LINUX:      return "UNIX - Linux";
+    case ELFOSABI_HURD:       return "GNU/Hurd";
+    case ELFOSABI_SOLARIS:    return "UNIX - Solaris";
+    case ELFOSABI_AIX:        return "UNIX - AIX";
+    case ELFOSABI_IRIX:       return "UNIX - IRIX";
+    case ELFOSABI_FREEBSD:    return "UNIX - FreeBSD";
+    case ELFOSABI_TRU64:      return "UNIX - TRU64";
+    case ELFOSABI_MODESTO:    return "Novell - Modesto";
+    case ELFOSABI_OPENBSD:    return "UNIX - OpenBSD";
     case ELFOSABI_STANDALONE: return _("Standalone App");
-    case ELFOSABI_ARM:        return _("ARM");
+    case ELFOSABI_ARM:        return "ARM";
     default:
       sprintf (buff, _("<unknown: %x>"), osabi);
       return buff;
@@ -2359,10 +2445,26 @@ process_file_header ()
              (long) elf_header.e_phnum);
       printf (_("  Size of section headers:           %ld (bytes)\n"),
              (long) elf_header.e_shentsize);
-      printf (_("  Number of section headers:         %ld\n"),
+      printf (_("  Number of section headers:         %ld"),
              (long) elf_header.e_shnum);
-      printf (_("  Section header string table index: %ld\n"),
+      if (section_headers != NULL && elf_header.e_shnum == 0)
+       printf (" (%ld)", (long) section_headers[0].sh_size);
+      putc ('\n', stdout);
+      printf (_("  Section header string table index: %ld"),
              (long) elf_header.e_shstrndx);
+      if (section_headers != NULL && elf_header.e_shstrndx == SHN_XINDEX)
+       printf (" (%ld)", (long) section_headers[0].sh_link);
+      putc ('\n', stdout);
+    }
+
+  if (section_headers != NULL)
+    {
+      if (elf_header.e_shnum == 0)
+       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;
+      free (section_headers);
+      section_headers = NULL;
     }
 
   return 1;
@@ -2495,6 +2597,9 @@ process_program_headers (file)
       if (is_32bit_elf)
        printf
          (_("  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align\n"));
+      else if (do_wide)
+       printf
+         (_("  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align\n"));
       else
        {
          printf
@@ -2529,6 +2634,48 @@ process_program_headers (file)
                      (segment->p_flags & PF_X ? 'E' : ' '));
              printf ("%#lx", (unsigned long) segment->p_align);
            }
+         else if (do_wide)
+           {
+             if ((unsigned long) segment->p_offset == segment->p_offset)
+               printf ("0x%6.6lx ", (unsigned long) segment->p_offset);
+             else
+               {
+                 print_vma (segment->p_offset, FULL_HEX);
+                 putchar (' ');
+               }
+
+             print_vma (segment->p_vaddr, FULL_HEX);
+             putchar (' ');
+             print_vma (segment->p_paddr, FULL_HEX);
+             putchar (' ');
+
+             if ((unsigned long) segment->p_filesz == segment->p_filesz)
+               printf ("0x%6.6lx ", (unsigned long) segment->p_filesz);
+             else
+               {
+                 print_vma (segment->p_filesz, FULL_HEX);
+                 putchar (' ');
+               }
+
+             if ((unsigned long) segment->p_memsz == segment->p_memsz)
+               printf ("0x%6.6lx", (unsigned long) segment->p_memsz);
+             else
+               {
+                 print_vma (segment->p_offset, FULL_HEX);
+               }
+
+             printf (" %c%c%c ",
+                     (segment->p_flags & PF_R ? 'R' : ' '),
+                     (segment->p_flags & PF_W ? 'W' : ' '),
+                     (segment->p_flags & PF_X ? 'E' : ' '));
+
+             if ((unsigned long) segment->p_align == segment->p_align)
+               printf ("%#lx", (unsigned long) segment->p_align);
+             else
+               {
+                 print_vma (segment->p_align, PREFIX_HEX);
+               }
+           }
          else
            {
              print_vma (segment->p_offset, FULL_HEX);
@@ -2585,7 +2732,7 @@ process_program_headers (file)
 
   if (loadaddr == -1)
     {
-      /* Very strange. */
+      /* Very strange.  */
       loadaddr = 0;
     }
 
@@ -2632,8 +2779,9 @@ process_program_headers (file)
 
 
 static int
-get_32bit_section_headers (file)
+get_32bit_section_headers (file, num)
      FILE * file;
+     unsigned int num;
 {
   Elf32_External_Shdr * shdrs;
   Elf32_Internal_Shdr * internal;
@@ -2641,13 +2789,13 @@ get_32bit_section_headers (file)
 
   shdrs = ((Elf32_External_Shdr *)
           get_data (NULL, file, elf_header.e_shoff,
-                    elf_header.e_shentsize * elf_header.e_shnum,
+                    elf_header.e_shentsize * num,
                     _("section headers")));
   if (!shdrs)
     return 0;
 
-  section_headers = (Elf_Internal_Shdr *) malloc
-    (elf_header.e_shnum * sizeof (Elf_Internal_Shdr));
+  section_headers = ((Elf_Internal_Shdr *)
+                    malloc (num * sizeof (Elf_Internal_Shdr)));
 
   if (section_headers == NULL)
     {
@@ -2656,7 +2804,7 @@ get_32bit_section_headers (file)
     }
 
   for (i = 0, internal = section_headers;
-       i < elf_header.e_shnum;
+       i < num;
        i ++, internal ++)
     {
       internal->sh_name      = BYTE_GET (shdrs[i].sh_name);
@@ -2677,8 +2825,9 @@ get_32bit_section_headers (file)
 }
 
 static int
-get_64bit_section_headers (file)
+get_64bit_section_headers (file, num)
      FILE * file;
+     unsigned int num;
 {
   Elf64_External_Shdr * shdrs;
   Elf64_Internal_Shdr * internal;
@@ -2686,13 +2835,13 @@ get_64bit_section_headers (file)
 
   shdrs = ((Elf64_External_Shdr *)
           get_data (NULL, file, elf_header.e_shoff,
-                    elf_header.e_shentsize * elf_header.e_shnum,
+                    elf_header.e_shentsize * num,
                     _("section headers")));
   if (!shdrs)
     return 0;
 
-  section_headers = (Elf_Internal_Shdr *) malloc
-    (elf_header.e_shnum * sizeof (Elf_Internal_Shdr));
+  section_headers = ((Elf_Internal_Shdr *)
+                    malloc (num * sizeof (Elf_Internal_Shdr)));
 
   if (section_headers == NULL)
     {
@@ -2701,7 +2850,7 @@ get_64bit_section_headers (file)
     }
 
   for (i = 0, internal = section_headers;
-       i < elf_header.e_shnum;
+       i < num;
        i ++, internal ++)
     {
       internal->sh_name      = BYTE_GET (shdrs[i].sh_name);
@@ -2879,10 +3028,10 @@ process_section_headers (file)
 
   if (is_32bit_elf)
     {
-      if (! get_32bit_section_headers (file))
+      if (! get_32bit_section_headers (file, elf_header.e_shnum))
        return 0;
     }
-  else if (! get_64bit_section_headers (file))
+  else if (! get_64bit_section_headers (file, elf_header.e_shnum))
     return 0;
 
   /* Read in the string table, so that we have names to display.  */
@@ -2897,7 +3046,7 @@ process_section_headers (file)
     }
 
   /* Scan the sections for the dynamic symbol table
-     and dynamic string table and debug sections. */
+     and dynamic string table and debug sections.  */
   dynamic_symbols = NULL;
   dynamic_strings = NULL;
   dynamic_syminfo = NULL;
@@ -2935,7 +3084,7 @@ process_section_headers (file)
        }
       else if ((do_debugging || do_debug_info || do_debug_abbrevs
                || do_debug_lines || do_debug_pubnames || do_debug_aranges
-               || do_debug_frames)
+               || do_debug_frames || do_debug_macinfo || do_debug_str)
               && strncmp (name, ".debug_", 7) == 0)
        {
          name += 7;
@@ -2947,6 +3096,8 @@ process_section_headers (file)
              || (do_debug_pubnames && (strcmp (name, "pubnames") == 0))
              || (do_debug_aranges  && (strcmp (name, "aranges") == 0))
              || (do_debug_frames   && (strcmp (name, "frame") == 0))
+             || (do_debug_macinfo  && (strcmp (name, "macinfo") == 0))
+             || (do_debug_str      && (strcmp (name, "str") == 0))
              )
            request_dump (i, DEBUG_DUMP);
        }
@@ -2966,6 +3117,9 @@ process_section_headers (file)
   if (is_32bit_elf)
     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"));
   else
     {
       printf (_("  [Nr] Name              Type             Address           Offset\n"));
@@ -2997,11 +3151,59 @@ process_section_headers (file)
                  (unsigned long) section->sh_info,
                  (unsigned long) section->sh_addralign);
        }
+      else if (do_wide)
+       {
+         print_vma (section->sh_addr, LONG_HEX);
+
+         if ((long) section->sh_offset == section->sh_offset)
+           printf (" %6.6lx", (unsigned long) section->sh_offset);
+         else
+           {
+             putchar (' ');
+             print_vma (section->sh_offset, LONG_HEX);
+           }
+
+         if ((unsigned long) section->sh_size == section->sh_size)
+           printf (" %6.6lx", (unsigned long) section->sh_size);
+         else
+           {
+             putchar (' ');
+             print_vma (section->sh_size, LONG_HEX);
+           }
+
+         if ((unsigned long) section->sh_entsize == section->sh_entsize)
+           printf (" %2.2lx", (unsigned long) section->sh_entsize);
+         else
+           {
+             putchar (' ');
+             print_vma (section->sh_entsize, LONG_HEX);
+           }
+
+         printf (" %3s ", get_elf_section_flags (section->sh_flags));
+
+         printf ("%2ld %3lx ",
+                 (unsigned long) section->sh_link,
+                 (unsigned long) section->sh_info);
+
+         if ((unsigned long) section->sh_addralign == section->sh_addralign)
+           printf ("%2ld\n", (unsigned long) section->sh_addralign);
+         else
+           {
+             print_vma (section->sh_addralign, DEC);
+             putchar ('\n');
+           }
+       }
       else
        {
          putchar (' ');
          print_vma (section->sh_addr, LONG_HEX);
-         printf ("  %8.8lx", section->sh_offset);
+         if ((long) section->sh_offset == section->sh_offset)
+           printf ("  %8.8lx", (unsigned long) section->sh_offset);
+         else
+           {
+             printf ("  ");
+             print_vma (section->sh_offset, LONG_HEX);
+           }
          printf ("\n       ");
          print_vma (section->sh_size, LONG_HEX);
          printf ("  ");
@@ -3016,10 +3218,10 @@ process_section_headers (file)
        }
     }
 
-  printf (_("Key to Flags:\n"));
-  printf (_("  W (write), A (alloc), X (execute), M (merge), S (strings)\n"));
-  printf (_("  I (info), L (link order), G (group), x (unknown)\n"));
-  printf (_("  O (extra OS processing required) o (OS specific), p (processor specific)\n"));
+  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"));
 
   return 1;
 }
@@ -3403,7 +3605,7 @@ slurp_ia64_unwind_table (file, aux, sec)
 
              if (ELF32_ST_TYPE (sym->st_info) != STT_SECTION)
                {
-                 warn (_("Skipping unexpected symbol type %u"),
+                 warn (_("Skipping unexpected symbol type %u\n"),
                        ELF32_ST_TYPE (sym->st_info));
                  continue;
                }
@@ -3415,7 +3617,7 @@ slurp_ia64_unwind_table (file, aux, sec)
 
              if (ELF64_ST_TYPE (sym->st_info) != STT_SECTION)
                {
-                 warn (_("Skipping unexpected symbol type %u"),
+                 warn (_("Skipping unexpected symbol type %u\n"),
                        ELF64_ST_TYPE (sym->st_info));
                  continue;
                }
@@ -3423,7 +3625,7 @@ slurp_ia64_unwind_table (file, aux, sec)
 
          if (strncmp (relname, "R_IA64_SEGREL", 13) != 0)
            {
-             warn (_("Skipping unexpected relocation type %s"), relname);
+             warn (_("Skipping unexpected relocation type %s\n"), relname);
              continue;
            }
 
@@ -3566,7 +3768,7 @@ process_unwind (file)
            printf ("'%s'", SECTION_NAME (unwsec));
 
          printf (_(" at offset 0x%lx contains %lu entries:\n"),
-                 unwsec->sh_offset,
+                 (unsigned long) unwsec->sh_offset,
                  (unsigned long) (unwsec->sh_size / (3 * addr_size)));
 
          (void) slurp_ia64_unwind_table (file, & aux, unwsec);
@@ -3873,7 +4075,7 @@ process_dynamic_segment (file)
          /* Since we do not know how big the symbol table is,
             we default to reading in the entire file (!) and
             processing that.  This is overkill, I know, but it
-            should work. */
+            should work.  */
          offset = entry->d_un.d_val - loadaddr;
 
          if (fseek (file, 0, SEEK_END))
@@ -3912,7 +4114,7 @@ process_dynamic_segment (file)
          /* Since we do not know how big the string table is,
             we default to reading in the entire file (!) and
             processing that.  This is overkill, I know, but it
-            should work. */
+            should work.  */
 
          offset = entry->d_un.d_val - loadaddr;
          if (fseek (file, 0, SEEK_END))
@@ -3928,7 +4130,6 @@ process_dynamic_segment (file)
 
          dynamic_strings = (char *) get_data (NULL, file, offset, str_tab_len,
                                               _("dynamic string table"));
-
          break;
        }
     }
@@ -4577,12 +4778,12 @@ process_version_sections (file)
        case SHT_GNU_versym:
          {
            Elf32_Internal_Shdr *       link_section;
-           int         total;
-           int         cnt;
-           unsigned char *             edata;
-           unsigned short *            data;
-           char *              strtab;
-           Elf_Internal_Sym *          symbols;
+           int                         total;
+           int                         cnt;
+           unsigned char *             edata;
+           unsigned short *            data;
+           char *                      strtab;
+           Elf_Internal_Sym *          symbols;
            Elf32_Internal_Shdr *       string_sec;
 
            link_section = section_headers + section->sh_link;
@@ -4934,7 +5135,7 @@ get_dynamic_data (file, number)
   return i_data;
 }
 
-/* Dump the symbol table */
+/* Dump the symbol table */
 static int
 process_symbol_table (file)
      FILE * file;
@@ -5536,7 +5737,7 @@ process_extended_line_op (data, is_stmt, pointer_size)
 
   if (len == 0)
     {
-      warn (_("badly formed extended line op encountered!"));
+      warn (_("badly formed extended line op encountered!\n"));
       return bytes_read;
     }
 
@@ -5609,6 +5810,13 @@ display_debug_lines (section, start, file)
 
       /* Check the length of the block.  */
       info.li_length = BYTE_GET (external->li_length);
+
+      if (info.li_length == 0xffffffff)
+       {
+         warn (_("64-bit DWARF line info is not supported yet.\n"));
+         break;
+       }
+
       if (info.li_length + sizeof (external->li_length) > section->sh_size)
        {
          warn
@@ -5719,7 +5927,19 @@ display_debug_lines (section, start, file)
 
          op_code = * data ++;
 
-         switch (op_code)
+         if (op_code >= info.li_opcode_base)
+           {
+             op_code -= info.li_opcode_base;
+             adv      = (op_code / info.li_line_range) * info.li_min_insn_length;
+             state_machine_regs.address += adv;
+             printf (_("  Special opcode %d: advance Address by %d to 0x%lx"),
+                     op_code, adv, state_machine_regs.address);
+             adv = (op_code % info.li_line_range) + info.li_line_base;
+             state_machine_regs.line += adv;
+             printf (_(" and Line by %d to %d\n"),
+                     adv, state_machine_regs.line);
+           } 
+         else switch (op_code) 
            {
            case DW_LNS_extended_op:
              data += process_extended_line_op (data, info.li_default_is_stmt,
@@ -5789,20 +6009,36 @@ display_debug_lines (section, start, file)
                      adv, state_machine_regs.address);
              break;
 
+           case DW_LNS_set_prologue_end:
+             printf (_("  Set prologue_end to true\n"));
+             break;
+             
+           case DW_LNS_set_epilogue_begin:
+             printf (_("  Set epilogue_begin to true\n"));
+             break;
+             
+           case DW_LNS_set_isa:
+             adv = read_leb128 (data, & bytes_read, 0);
+             data += bytes_read;
+             printf (_("  Set ISA to %d\n"), adv);
+             break;
+             
            default:
-             op_code -= info.li_opcode_base;
-             adv      = (op_code / info.li_line_range) * info.li_min_insn_length;
-             state_machine_regs.address += adv;
-             printf (_("  Special opcode %d: advance Address by %d to 0x%lx"),
-                     op_code, adv, state_machine_regs.address);
-             adv = (op_code % info.li_line_range) + info.li_line_base;
-             state_machine_regs.line += adv;
-             printf (_(" and Line by %d to %d\n"),
-                     adv, state_machine_regs.line);
+             printf (_("  Unknown opcode %d with operands: "), op_code);
+             {
+               int i;
+               for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
+                 {
+                   printf ("0x%lx%s", read_leb128 (data, &bytes_read, 0),
+                           i == 1 ? "" : ", ");
+                   data += bytes_read;
+                 }
+               putchar ('\n');
+             }
              break;
            }
        }
-      printf ("\n");
+      putchar ('\n');
     }
 
   return 1;
@@ -5837,6 +6073,12 @@ display_debug_pubnames (section, start, file)
       data   = start + sizeof (* external);
       start += pubnames.pn_length + sizeof (external->pn_length);
 
+      if (pubnames.pn_length == 0xffffffff)
+       {
+         warn (_("64-bit DWARF pubnames are not supported yet.\n"));
+         break;
+       }
+
       if (pubnames.pn_version != 2)
        {
          static int warned = 0;
@@ -5885,58 +6127,67 @@ get_TAG_name (tag)
 {
   switch (tag)
     {
-    case DW_TAG_padding: return "DW_TAG_padding";
-    case DW_TAG_array_type: return "DW_TAG_array_type";
-    case DW_TAG_class_type: return "DW_TAG_class_type";
-    case DW_TAG_entry_point: return "DW_TAG_entry_point";
-    case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type";
-    case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter";
-    case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration";
-    case DW_TAG_label: return "DW_TAG_label";
-    case DW_TAG_lexical_block: return "DW_TAG_lexical_block";
-    case DW_TAG_member: return "DW_TAG_member";
-    case DW_TAG_pointer_type: return "DW_TAG_pointer_type";
-    case DW_TAG_reference_type: return "DW_TAG_reference_type";
-    case DW_TAG_compile_unit: return "DW_TAG_compile_unit";
-    case DW_TAG_string_type: return "DW_TAG_string_type";
-    case DW_TAG_structure_type: return "DW_TAG_structure_type";
-    case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type";
-    case DW_TAG_typedef: return "DW_TAG_typedef";
-    case DW_TAG_union_type: return "DW_TAG_union_type";
+    case DW_TAG_padding:                return "DW_TAG_padding";
+    case DW_TAG_array_type:             return "DW_TAG_array_type";
+    case DW_TAG_class_type:             return "DW_TAG_class_type";
+    case DW_TAG_entry_point:            return "DW_TAG_entry_point";
+    case DW_TAG_enumeration_type:       return "DW_TAG_enumeration_type";
+    case DW_TAG_formal_parameter:       return "DW_TAG_formal_parameter";
+    case DW_TAG_imported_declaration:   return "DW_TAG_imported_declaration";
+    case DW_TAG_label:                  return "DW_TAG_label";
+    case DW_TAG_lexical_block:          return "DW_TAG_lexical_block";
+    case DW_TAG_member:                 return "DW_TAG_member";
+    case DW_TAG_pointer_type:           return "DW_TAG_pointer_type";
+    case DW_TAG_reference_type:         return "DW_TAG_reference_type";
+    case DW_TAG_compile_unit:           return "DW_TAG_compile_unit";
+    case DW_TAG_string_type:            return "DW_TAG_string_type";
+    case DW_TAG_structure_type:         return "DW_TAG_structure_type";
+    case DW_TAG_subroutine_type:        return "DW_TAG_subroutine_type";
+    case DW_TAG_typedef:                return "DW_TAG_typedef";
+    case DW_TAG_union_type:             return "DW_TAG_union_type";
     case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters";
-    case DW_TAG_variant: return "DW_TAG_variant";
-    case DW_TAG_common_block: return "DW_TAG_common_block";
-    case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion";
-    case DW_TAG_inheritance: return "DW_TAG_inheritance";
-    case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine";
-    case DW_TAG_module: return "DW_TAG_module";
-    case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type";
-    case DW_TAG_set_type: return "DW_TAG_set_type";
-    case DW_TAG_subrange_type: return "DW_TAG_subrange_type";
-    case DW_TAG_with_stmt: return "DW_TAG_with_stmt";
-    case DW_TAG_access_declaration: return "DW_TAG_access_declaration";
-    case DW_TAG_base_type: return "DW_TAG_base_type";
-    case DW_TAG_catch_block: return "DW_TAG_catch_block";
-    case DW_TAG_const_type: return "DW_TAG_const_type";
-    case DW_TAG_constant: return "DW_TAG_constant";
-    case DW_TAG_enumerator: return "DW_TAG_enumerator";
-    case DW_TAG_file_type: return "DW_TAG_file_type";
-    case DW_TAG_friend: return "DW_TAG_friend";
-    case DW_TAG_namelist: return "DW_TAG_namelist";
-    case DW_TAG_namelist_item: return "DW_TAG_namelist_item";
-    case DW_TAG_packed_type: return "DW_TAG_packed_type";
-    case DW_TAG_subprogram: return "DW_TAG_subprogram";
-    case DW_TAG_template_type_param: return "DW_TAG_template_type_param";
-    case DW_TAG_template_value_param: return "DW_TAG_template_value_param";
-    case DW_TAG_thrown_type: return "DW_TAG_thrown_type";
-    case DW_TAG_try_block: return "DW_TAG_try_block";
-    case DW_TAG_variant_part: return "DW_TAG_variant_part";
-    case DW_TAG_variable: return "DW_TAG_variable";
-    case DW_TAG_volatile_type: return "DW_TAG_volatile_type";
-    case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop";
-    case DW_TAG_format_label: return "DW_TAG_format_label";
-    case DW_TAG_function_template: return "DW_TAG_function_template";
-    case DW_TAG_class_template: return "DW_TAG_class_template";
+    case DW_TAG_variant:                return "DW_TAG_variant";
+    case DW_TAG_common_block:           return "DW_TAG_common_block";
+    case DW_TAG_common_inclusion:       return "DW_TAG_common_inclusion";
+    case DW_TAG_inheritance:            return "DW_TAG_inheritance";
+    case DW_TAG_inlined_subroutine:     return "DW_TAG_inlined_subroutine";
+    case DW_TAG_module:                 return "DW_TAG_module";
+    case DW_TAG_ptr_to_member_type:     return "DW_TAG_ptr_to_member_type";
+    case DW_TAG_set_type:               return "DW_TAG_set_type";
+    case DW_TAG_subrange_type:          return "DW_TAG_subrange_type";
+    case DW_TAG_with_stmt:              return "DW_TAG_with_stmt";
+    case DW_TAG_access_declaration:     return "DW_TAG_access_declaration";
+    case DW_TAG_base_type:              return "DW_TAG_base_type";
+    case DW_TAG_catch_block:            return "DW_TAG_catch_block";
+    case DW_TAG_const_type:             return "DW_TAG_const_type";
+    case DW_TAG_constant:               return "DW_TAG_constant";
+    case DW_TAG_enumerator:             return "DW_TAG_enumerator";
+    case DW_TAG_file_type:              return "DW_TAG_file_type";
+    case DW_TAG_friend:                 return "DW_TAG_friend";
+    case DW_TAG_namelist:               return "DW_TAG_namelist";
+    case DW_TAG_namelist_item:          return "DW_TAG_namelist_item";
+    case DW_TAG_packed_type:            return "DW_TAG_packed_type";
+    case DW_TAG_subprogram:             return "DW_TAG_subprogram";
+    case DW_TAG_template_type_param:    return "DW_TAG_template_type_param";
+    case DW_TAG_template_value_param:   return "DW_TAG_template_value_param";
+    case DW_TAG_thrown_type:            return "DW_TAG_thrown_type";
+    case DW_TAG_try_block:              return "DW_TAG_try_block";
+    case DW_TAG_variant_part:           return "DW_TAG_variant_part";
+    case DW_TAG_variable:               return "DW_TAG_variable";
+    case DW_TAG_volatile_type:          return "DW_TAG_volatile_type";
+    case DW_TAG_MIPS_loop:              return "DW_TAG_MIPS_loop";
+    case DW_TAG_format_label:           return "DW_TAG_format_label";
+    case DW_TAG_function_template:      return "DW_TAG_function_template";
+    case DW_TAG_class_template:         return "DW_TAG_class_template";
+      /* DWARF 2.1 values.  */
+    case DW_TAG_dwarf_procedure:        return "DW_TAG_dwarf_procedure";
+    case DW_TAG_restrict_type:          return "DW_TAG_restrict_type";
+    case DW_TAG_interface_type:         return "DW_TAG_interface_type";
+    case DW_TAG_namespace:              return "DW_TAG_namespace";
+    case DW_TAG_imported_module:        return "DW_TAG_imported_module";
+    case DW_TAG_unspecified_type:       return "DW_TAG_unspecified_type";
+    case DW_TAG_partial_unit:           return "DW_TAG_partial_unit";
+    case DW_TAG_imported_unit:          return "DW_TAG_imported_unit";
     default:
       {
        static char buffer [100];
@@ -5953,85 +6204,100 @@ get_AT_name (attribute)
 {
   switch (attribute)
     {
-    case DW_AT_sibling: return "DW_AT_sibling";
-    case DW_AT_location: return "DW_AT_location";
-    case DW_AT_name: return "DW_AT_name";
-    case DW_AT_ordering: return "DW_AT_ordering";
-    case DW_AT_subscr_data: return "DW_AT_subscr_data";
-    case DW_AT_byte_size: return "DW_AT_byte_size";
-    case DW_AT_bit_offset: return "DW_AT_bit_offset";
-    case DW_AT_bit_size: return "DW_AT_bit_size";
-    case DW_AT_element_list: return "DW_AT_element_list";
-    case DW_AT_stmt_list: return "DW_AT_stmt_list";
-    case DW_AT_low_pc: return "DW_AT_low_pc";
-    case DW_AT_high_pc: return "DW_AT_high_pc";
-    case DW_AT_language: return "DW_AT_language";
-    case DW_AT_member: return "DW_AT_member";
-    case DW_AT_discr: return "DW_AT_discr";
-    case DW_AT_discr_value: return "DW_AT_discr_value";
-    case DW_AT_visibility: return "DW_AT_visibility";
-    case DW_AT_import: return "DW_AT_import";
-    case DW_AT_string_length: return "DW_AT_string_length";
-    case DW_AT_common_reference: return "DW_AT_common_reference";
-    case DW_AT_comp_dir: return "DW_AT_comp_dir";
-    case DW_AT_const_value: return "DW_AT_const_value";
-    case DW_AT_containing_type: return "DW_AT_containing_type";
-    case DW_AT_default_value: return "DW_AT_default_value";
-    case DW_AT_inline: return "DW_AT_inline";
-    case DW_AT_is_optional: return "DW_AT_is_optional";
-    case DW_AT_lower_bound: return "DW_AT_lower_bound";
-    case DW_AT_producer: return "DW_AT_producer";
-    case DW_AT_prototyped: return "DW_AT_prototyped";
-    case DW_AT_return_addr: return "DW_AT_return_addr";
-    case DW_AT_start_scope: return "DW_AT_start_scope";
-    case DW_AT_stride_size: return "DW_AT_stride_size";
-    case DW_AT_upper_bound: return "DW_AT_upper_bound";
-    case DW_AT_abstract_origin: return "DW_AT_abstract_origin";
-    case DW_AT_accessibility: return "DW_AT_accessibility";
-    case DW_AT_address_class: return "DW_AT_address_class";
-    case DW_AT_artificial: return "DW_AT_artificial";
-    case DW_AT_base_types: return "DW_AT_base_types";
-    case DW_AT_calling_convention: return "DW_AT_calling_convention";
-    case DW_AT_count: return "DW_AT_count";
+    case DW_AT_sibling:              return "DW_AT_sibling";
+    case DW_AT_location:             return "DW_AT_location";
+    case DW_AT_name:                 return "DW_AT_name";
+    case DW_AT_ordering:             return "DW_AT_ordering";
+    case DW_AT_subscr_data:          return "DW_AT_subscr_data";
+    case DW_AT_byte_size:            return "DW_AT_byte_size";
+    case DW_AT_bit_offset:           return "DW_AT_bit_offset";
+    case DW_AT_bit_size:             return "DW_AT_bit_size";
+    case DW_AT_element_list:         return "DW_AT_element_list";
+    case DW_AT_stmt_list:            return "DW_AT_stmt_list";
+    case DW_AT_low_pc:               return "DW_AT_low_pc";
+    case DW_AT_high_pc:              return "DW_AT_high_pc";
+    case DW_AT_language:             return "DW_AT_language";
+    case DW_AT_member:               return "DW_AT_member";
+    case DW_AT_discr:                return "DW_AT_discr";
+    case DW_AT_discr_value:          return "DW_AT_discr_value";
+    case DW_AT_visibility:           return "DW_AT_visibility";
+    case DW_AT_import:               return "DW_AT_import";
+    case DW_AT_string_length:        return "DW_AT_string_length";
+    case DW_AT_common_reference:     return "DW_AT_common_reference";
+    case DW_AT_comp_dir:             return "DW_AT_comp_dir";
+    case DW_AT_const_value:          return "DW_AT_const_value";
+    case DW_AT_containing_type:      return "DW_AT_containing_type";
+    case DW_AT_default_value:        return "DW_AT_default_value";
+    case DW_AT_inline:               return "DW_AT_inline";
+    case DW_AT_is_optional:          return "DW_AT_is_optional";
+    case DW_AT_lower_bound:          return "DW_AT_lower_bound";
+    case DW_AT_producer:             return "DW_AT_producer";
+    case DW_AT_prototyped:           return "DW_AT_prototyped";
+    case DW_AT_return_addr:          return "DW_AT_return_addr";
+    case DW_AT_start_scope:          return "DW_AT_start_scope";
+    case DW_AT_stride_size:          return "DW_AT_stride_size";
+    case DW_AT_upper_bound:          return "DW_AT_upper_bound";
+    case DW_AT_abstract_origin:      return "DW_AT_abstract_origin";
+    case DW_AT_accessibility:        return "DW_AT_accessibility";
+    case DW_AT_address_class:        return "DW_AT_address_class";
+    case DW_AT_artificial:           return "DW_AT_artificial";
+    case DW_AT_base_types:           return "DW_AT_base_types";
+    case DW_AT_calling_convention:   return "DW_AT_calling_convention";
+    case DW_AT_count:                return "DW_AT_count";
     case DW_AT_data_member_location: return "DW_AT_data_member_location";
-    case DW_AT_decl_column: return "DW_AT_decl_column";
-    case DW_AT_decl_file: return "DW_AT_decl_file";
-    case DW_AT_decl_line: return "DW_AT_decl_line";
-    case DW_AT_declaration: return "DW_AT_declaration";
-    case DW_AT_discr_list: return "DW_AT_discr_list";
-    case DW_AT_encoding: return "DW_AT_encoding";
-    case DW_AT_external: return "DW_AT_external";
-    case DW_AT_frame_base: return "DW_AT_frame_base";
-    case DW_AT_friend: return "DW_AT_friend";
-    case DW_AT_identifier_case: return "DW_AT_identifier_case";
-    case DW_AT_macro_info: return "DW_AT_macro_info";
-    case DW_AT_namelist_items: return "DW_AT_namelist_items";
-    case DW_AT_priority: return "DW_AT_priority";
-    case DW_AT_segment: return "DW_AT_segment";
-    case DW_AT_specification: return "DW_AT_specification";
-    case DW_AT_static_link: return "DW_AT_static_link";
-    case DW_AT_type: return "DW_AT_type";
-    case DW_AT_use_location: return "DW_AT_use_location";
-    case DW_AT_variable_parameter: return "DW_AT_variable_parameter";
-    case DW_AT_virtuality: return "DW_AT_virtuality";
+    case DW_AT_decl_column:          return "DW_AT_decl_column";
+    case DW_AT_decl_file:            return "DW_AT_decl_file";
+    case DW_AT_decl_line:            return "DW_AT_decl_line";
+    case DW_AT_declaration:          return "DW_AT_declaration";
+    case DW_AT_discr_list:           return "DW_AT_discr_list";
+    case DW_AT_encoding:             return "DW_AT_encoding";
+    case DW_AT_external:             return "DW_AT_external";
+    case DW_AT_frame_base:           return "DW_AT_frame_base";
+    case DW_AT_friend:               return "DW_AT_friend";
+    case DW_AT_identifier_case:      return "DW_AT_identifier_case";
+    case DW_AT_macro_info:           return "DW_AT_macro_info";
+    case DW_AT_namelist_items:       return "DW_AT_namelist_items";
+    case DW_AT_priority:             return "DW_AT_priority";
+    case DW_AT_segment:              return "DW_AT_segment";
+    case DW_AT_specification:        return "DW_AT_specification";
+    case DW_AT_static_link:          return "DW_AT_static_link";
+    case DW_AT_type:                 return "DW_AT_type";
+    case DW_AT_use_location:         return "DW_AT_use_location";
+    case DW_AT_variable_parameter:   return "DW_AT_variable_parameter";
+    case DW_AT_virtuality:           return "DW_AT_virtuality";
     case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location";
-    case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde";
-    case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin";
+      /* DWARF 2.1 values.  */
+    case DW_AT_allocated:            return "DW_AT_allocated";
+    case DW_AT_associated:           return "DW_AT_associated";
+    case DW_AT_data_location:        return "DW_AT_data_location";
+    case DW_AT_stride:               return "DW_AT_stride";
+    case DW_AT_entry_pc:             return "DW_AT_entry_pc";
+    case DW_AT_use_UTF8:             return "DW_AT_use_UTF8";
+    case DW_AT_extension:            return "DW_AT_extension";
+    case DW_AT_ranges:               return "DW_AT_ranges";
+    case DW_AT_trampoline:           return "DW_AT_trampoline";
+    case DW_AT_call_column:          return "DW_AT_call_column";
+    case DW_AT_call_file:            return "DW_AT_call_file";
+    case DW_AT_call_line:            return "DW_AT_call_line";
+      /* SGI/MIPS extensions.  */
+    case DW_AT_MIPS_fde:             return "DW_AT_MIPS_fde";
+    case DW_AT_MIPS_loop_begin:      return "DW_AT_MIPS_loop_begin";
     case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin";
-    case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin";
+    case DW_AT_MIPS_epilog_begin:    return "DW_AT_MIPS_epilog_begin";
     case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor";
     case DW_AT_MIPS_software_pipeline_depth: return "DW_AT_MIPS_software_pipeline_depth";
-    case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name";
-    case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride";
-    case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name";
-    case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin";
-    case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines";
-    case DW_AT_sf_names: return "DW_AT_sf_names";
-    case DW_AT_src_info: return "DW_AT_src_info";
-    case DW_AT_mac_info: return "DW_AT_mac_info";
-    case DW_AT_src_coords: return "DW_AT_src_coords";
-    case DW_AT_body_begin: return "DW_AT_body_begin";
-    case DW_AT_body_end: return "DW_AT_body_end";
+    case DW_AT_MIPS_linkage_name:    return "DW_AT_MIPS_linkage_name";
+    case DW_AT_MIPS_stride:          return "DW_AT_MIPS_stride";
+    case DW_AT_MIPS_abstract_name:   return "DW_AT_MIPS_abstract_name";
+    case DW_AT_MIPS_clone_origin:    return "DW_AT_MIPS_clone_origin";
+    case DW_AT_MIPS_has_inlines:     return "DW_AT_MIPS_has_inlines";
+      /* GNU extensions.  */
+    case DW_AT_sf_names:             return "DW_AT_sf_names";
+    case DW_AT_src_info:             return "DW_AT_src_info";
+    case DW_AT_mac_info:             return "DW_AT_mac_info";
+    case DW_AT_src_coords:           return "DW_AT_src_coords";
+    case DW_AT_body_begin:           return "DW_AT_body_begin";
+    case DW_AT_body_end:             return "DW_AT_body_end";
     default:
       {
        static char buffer [100];
@@ -6048,27 +6314,27 @@ get_FORM_name (form)
 {
   switch (form)
     {
-    case DW_FORM_addr: return "DW_FORM_addr";
-    case DW_FORM_block2: return "DW_FORM_block2";
-    case DW_FORM_block4: return "DW_FORM_block4";
-    case DW_FORM_data2: return "DW_FORM_data2";
-    case DW_FORM_data4: return "DW_FORM_data4";
-    case DW_FORM_data8: return "DW_FORM_data8";
-    case DW_FORM_string: return "DW_FORM_string";
-    case DW_FORM_block: return "DW_FORM_block";
-    case DW_FORM_block1: return "DW_FORM_block1";
-    case DW_FORM_data1: return "DW_FORM_data1";
-    case DW_FORM_flag: return "DW_FORM_flag";
-    case DW_FORM_sdata: return "DW_FORM_sdata";
-    case DW_FORM_strp: return "DW_FORM_strp";
-    case DW_FORM_udata: return "DW_FORM_udata";
-    case DW_FORM_ref_addr: return "DW_FORM_ref_addr";
-    case DW_FORM_ref1: return "DW_FORM_ref1";
-    case DW_FORM_ref2: return "DW_FORM_ref2";
-    case DW_FORM_ref4: return "DW_FORM_ref4";
-    case DW_FORM_ref8: return "DW_FORM_ref8";
+    case DW_FORM_addr:      return "DW_FORM_addr";
+    case DW_FORM_block2:    return "DW_FORM_block2";
+    case DW_FORM_block4:    return "DW_FORM_block4";
+    case DW_FORM_data2:     return "DW_FORM_data2";
+    case DW_FORM_data4:     return "DW_FORM_data4";
+    case DW_FORM_data8:     return "DW_FORM_data8";
+    case DW_FORM_string:    return "DW_FORM_string";
+    case DW_FORM_block:     return "DW_FORM_block";
+    case DW_FORM_block1:    return "DW_FORM_block1";
+    case DW_FORM_data1:     return "DW_FORM_data1";
+    case DW_FORM_flag:      return "DW_FORM_flag";
+    case DW_FORM_sdata:     return "DW_FORM_sdata";
+    case DW_FORM_strp:      return "DW_FORM_strp";
+    case DW_FORM_udata:     return "DW_FORM_udata";
+    case DW_FORM_ref_addr:  return "DW_FORM_ref_addr";
+    case DW_FORM_ref1:      return "DW_FORM_ref1";
+    case DW_FORM_ref2:      return "DW_FORM_ref2";
+    case DW_FORM_ref4:      return "DW_FORM_ref4";
+    case DW_FORM_ref8:      return "DW_FORM_ref8";
     case DW_FORM_ref_udata: return "DW_FORM_ref_udata";
-    case DW_FORM_indirect: return "DW_FORM_indirect";
+    case DW_FORM_indirect:  return "DW_FORM_indirect";
     default:
       {
        static char buffer [100];
@@ -6240,6 +6506,80 @@ process_abbrev_section (start, end)
 }
 
 
+static int
+display_debug_macinfo (section, start, file)
+     Elf32_Internal_Shdr * section;
+     unsigned char *       start;
+     FILE *                file ATTRIBUTE_UNUSED;
+{
+  unsigned char * end = start + section->sh_size;
+  unsigned char * curr = start;
+  unsigned int bytes_read;
+  enum dwarf_macinfo_record_type op;
+
+  printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section));
+
+  while (curr < end)
+    {
+      unsigned int lineno;
+      const char * string;
+
+      op = * curr;
+      curr ++;
+
+      switch (op)
+       {
+       case DW_MACINFO_start_file:
+         {
+           unsigned int filenum;
+
+           lineno = read_leb128 (curr, & bytes_read, 0);
+           curr += bytes_read;
+           filenum = read_leb128 (curr, & bytes_read, 0);
+           curr += bytes_read;
+
+           printf (_(" DW_MACINFO_start_file - lineno: %d filenum: %d\n"), lineno, filenum);
+         }
+         break;
+
+       case DW_MACINFO_end_file:
+         printf (_(" DW_MACINFO_end_file\n"));
+         break;
+
+       case DW_MACINFO_define:
+         lineno = read_leb128 (curr, & bytes_read, 0);
+         curr += bytes_read;
+         string = curr;
+         curr += strlen (string) + 1;
+         printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"), lineno, string);
+         break;
+
+       case DW_MACINFO_undef:
+         lineno = read_leb128 (curr, & bytes_read, 0);
+         curr += bytes_read;
+         string = curr;
+         curr += strlen (string) + 1;
+         printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"), lineno, string);
+         break;
+
+       case DW_MACINFO_vendor_ext:
+         {
+           unsigned int constant;
+
+           constant = read_leb128 (curr, & bytes_read, 0);
+           curr += bytes_read;
+           string = curr;
+           curr += strlen (string) + 1;
+           printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"), constant, string);
+         }
+         break;
+       }
+    }
+
+  return 1;
+}
+
+
 static int
 display_debug_abbrev (section, start, file)
      Elf32_Internal_Shdr * section;
@@ -6255,6 +6595,9 @@ display_debug_abbrev (section, start, file)
     {
       start = process_abbrev_section (start, end);
 
+      if (first_abbrev == NULL)
+       continue;
+
       printf (_("  Number TAG\n"));
 
       for (entry = first_abbrev; entry; entry = entry->next)
@@ -6273,6 +6616,8 @@ display_debug_abbrev (section, start, file)
                      get_FORM_name (attr->form));
            }
        }
+
+      free_abbrevs ();
     }
   while (start);
 
@@ -6591,6 +6936,22 @@ decode_location_expression (data, pointer_size, length)
          printf ("DW_OP_nop");
          break;
 
+         /* DWARF 2.1 extensions.  */
+       case DW_OP_push_object_address:
+         printf ("DW_OP_push_object_address");
+         break;
+       case DW_OP_call2:
+         printf ("DW_OP_call2: <%lx>", (long) byte_get (data, 2));
+         data += 2;
+         break;
+       case DW_OP_call4:
+         printf ("DW_OP_call4: <%lx>", (long) byte_get (data, 4));
+         data += 4;
+         break;
+       case DW_OP_calli:
+         printf ("DW_OP_calli");
+         break;
+
        default:
          if (op >= DW_OP_lo_user
              && op <= DW_OP_hi_user)
@@ -6600,12 +6961,132 @@ decode_location_expression (data, pointer_size, length)
          /* No way to tell where the next op is, so just bail.  */
          return;
        }
+
+      /* Separate the ops.  */
+      printf ("; ");
+    }
+}
+
+
+static const char * debug_str_contents;
+static bfd_vma      debug_str_size;
+
+static void
+load_debug_str (file)
+     FILE * file;
+{
+  Elf32_Internal_Shdr * sec;
+  int                   i;
+
+  /* If it is already loaded, do nothing.  */
+  if (debug_str_contents != NULL)
+    return;
+
+  /* Locate the .debug_str section.  */
+  for (i = 0, sec = section_headers;
+       i < elf_header.e_shnum;
+       i ++, sec ++)
+    if (strcmp (SECTION_NAME (sec), ".debug_str") == 0)
+      break;
+
+  if (i == elf_header.e_shnum || sec->sh_size == 0)
+    return;
+
+  debug_str_size = sec->sh_size;
+
+  debug_str_contents = ((char *)
+                       get_data (NULL, file, sec->sh_offset, sec->sh_size,
+                                 _("debug_str section data")));
+}
+
+static void
+free_debug_str ()
+{
+  if (debug_str_contents == NULL)
+    return;
+
+  free ((char *) debug_str_contents);
+  debug_str_contents = NULL;
+  debug_str_size = 0;
+}
+
+static const char *
+fetch_indirect_string (offset)
+     unsigned long offset;
+{
+  if (debug_str_contents == NULL)
+    return _("<no .debug_str section>");
+
+  if (offset > debug_str_size)
+    return _("<offset is too big>");
+
+  return debug_str_contents + offset;
+}
+
+
+static int
+display_debug_str (section, start, file)
+     Elf32_Internal_Shdr * section;
+     unsigned char *       start;
+     FILE *                file ATTRIBUTE_UNUSED;
+{
+  unsigned long   bytes;
+  bfd_vma         addr;
+
+  addr  = section->sh_addr;
+  bytes = section->sh_size;
+
+  if (bytes == 0)
+    {
+      printf (_("\nThe .debug_str section is empty.\n"));
+      return 0;
+    }
+
+  printf (_("Contents of the .debug_str section:\n\n"));
+
+  while (bytes)
+    {
+      int j;
+      int k;
+      int lbytes;
+
+      lbytes = (bytes > 16 ? 16 : bytes);
+
+      printf ("  0x%8.8lx ", (unsigned long) addr);
+
+      for (j = 0; j < 16; j++)
+       {
+         if (j < lbytes)
+           printf ("%2.2x", start [j]);
+         else
+           printf ("  ");
+
+         if ((j & 3) == 3)
+           printf (" ");
+       }
+
+      for (j = 0; j < lbytes; j++)
+       {
+         k = start [j];
+         if (k >= ' ' && k < 0x80)
+           printf ("%c", k);
+         else
+           printf (".");
+       }
+
+      putchar ('\n');
+
+      start += lbytes;
+      addr  += lbytes;
+      bytes -= lbytes;
     }
+
+  return 1;
 }
 
 
 static unsigned char *
-read_and_display_attr (attribute, form, data, cu_offset, pointer_size)
+read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
      unsigned long   attribute;
      unsigned long   form;
      unsigned char * data;
@@ -6616,8 +7097,6 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size)
   unsigned char * block_start = NULL;
   int             bytes_read;
 
-  printf ("     %-18s:", get_AT_name (attribute));
-
   switch (form)
     {
     default:
@@ -6629,6 +7108,11 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size)
       data += pointer_size;
       break;
 
+    case DW_FORM_strp:
+      uvalue = byte_get (data, /* offset_size */ 4);
+      data += /* offset_size */ 4;
+      break;
+
     case DW_FORM_ref1:
     case DW_FORM_flag:
     case DW_FORM_data1:
@@ -6657,6 +7141,13 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size)
       uvalue = read_leb128 (data, & bytes_read, 0);
       data += bytes_read;
       break;
+
+    case DW_FORM_indirect:
+      form = read_leb128 (data, & bytes_read, 0);
+      data += bytes_read;
+      printf (" %s", get_FORM_name (form));
+      return read_and_display_attr_value (attribute, form, data, cu_offset,
+                                          pointer_size);
     }
 
   switch (form)
@@ -6722,12 +7213,16 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size)
       break;
 
     case DW_FORM_strp:
+      printf (_(" (indirect string, offset: 0x%lx): "), uvalue);
+      printf (fetch_indirect_string (uvalue));
+      break;
+
     case DW_FORM_indirect:
-      warn (_("Unable to handle FORM: %d"), form);
+      /* Handled above.  */
       break;
 
     default:
-      warn (_("Unrecognised form: %d"), form);
+      warn (_("Unrecognised form: %d\n"), form);
       break;
     }
 
@@ -6761,6 +7256,11 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size)
        case DW_LANG_Ada83:          printf ("(Ada)"); break;
        case DW_LANG_Cobol74:        printf ("(Cobol 74)"); break;
        case DW_LANG_Cobol85:        printf ("(Cobol 85)"); break;
+         /* DWARF 2.1 values.  */
+       case DW_LANG_C99:            printf ("(ANSI C99)"); break;
+       case DW_LANG_Ada95:          printf ("(ADA 95)"); break;
+       case DW_LANG_Fortran95:      printf ("(Fortran 95)"); break;
+         /* MIPS extension.  */
        case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break;
        default:                     printf ("(Unknown: %lx)", uvalue); break;
        }
@@ -6778,6 +7278,8 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size)
        case DW_ATE_signed_char:     printf ("(signed char)"); break;
        case DW_ATE_unsigned:        printf ("(unsigned)"); break;
        case DW_ATE_unsigned_char:   printf ("(unsigned char)"); break;
+         /* DWARF 2.1 value.  */
+       case DW_ATE_imaginary_float: printf ("(imaginary float)"); break;
        default:
          if (uvalue >= DW_ATE_lo_user
              && uvalue <= DW_ATE_hi_user)
@@ -6844,10 +7346,25 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size)
        }
       break;
 
+    case DW_AT_ordering:
+      switch (uvalue)
+       {
+       case -1: printf ("(undefined)"); break;
+       case 0:  printf ("(row major)"); break;
+       case 1:  printf ("(column major)"); break;
+       }
+      break;
+
     case DW_AT_frame_base:
     case DW_AT_location:
     case DW_AT_data_member_location:
     case DW_AT_vtable_elem_location:
+    case DW_AT_allocated:
+    case DW_AT_associated:
+    case DW_AT_data_location:
+    case DW_AT_stride:
+    case DW_AT_upper_bound:
+    case DW_AT_lower_bound:
       if (block_start)
        {
          printf ("(");
@@ -6860,6 +7377,20 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size)
       break;
     }
 
+  return data;
+}
+
+static unsigned char *
+read_and_display_attr (attribute, form, data, cu_offset, pointer_size)
+     unsigned long   attribute;
+     unsigned long   form;
+     unsigned char * data;
+     unsigned long   cu_offset;
+     unsigned long   pointer_size;
+{
+  printf ("     %-18s:", get_AT_name (attribute));
+  data = read_and_display_attr_value (attribute, form, data, cu_offset,
+                                      pointer_size);
   printf ("\n");
   return data;
 }
@@ -6875,10 +7406,13 @@ display_debug_info (section, start, file)
 
   printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
 
+  load_debug_str (file);
+
   while (start < end)
     {
       DWARF2_External_CompUnit * external;
       DWARF2_Internal_CompUnit   compunit;
+      Elf32_Internal_Shdr *      relsec;
       unsigned char *            tags;
       int                        i;
       int                       level;
@@ -6891,6 +7425,74 @@ display_debug_info (section, start, file)
       compunit.cu_abbrev_offset = BYTE_GET (external->cu_abbrev_offset);
       compunit.cu_pointer_size  = BYTE_GET (external->cu_pointer_size);
 
+      if (compunit.cu_length == 0xffffffff)
+       {
+         warn (_("64-bit DWARF debug info is not supported yet.\n"));
+         break;
+       }
+
+      /* Check for RELA relocations in the abbrev_offset address, and
+         apply them.  */
+      for (relsec = section_headers;
+          relsec < section_headers + elf_header.e_shnum;
+          ++relsec)
+       {
+         unsigned long nrelas, nsyms;
+         Elf_Internal_Rela *rela, *rp;
+         Elf32_Internal_Shdr *symsec;
+         Elf_Internal_Sym *symtab;
+         Elf_Internal_Sym *sym;
+
+         if (relsec->sh_type != SHT_RELA
+             || section_headers + relsec->sh_info != section)
+           continue;
+
+         if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
+                                 & rela, & nrelas))
+           return 0;
+
+         symsec = section_headers + relsec->sh_link;
+         nsyms = symsec->sh_size / symsec->sh_entsize;
+         symtab = GET_ELF_SYMBOLS (file, symsec->sh_offset, nsyms);
+
+         for (rp = rela; rp < rela + nrelas; ++rp)
+           {
+             if (rp->r_offset
+                 != (bfd_vma) ((unsigned char *) &external->cu_abbrev_offset
+                               - section_begin))
+               continue;
+
+             if (is_32bit_elf)
+               {
+                 sym = symtab + ELF32_R_SYM (rp->r_info);
+
+                 if (ELF32_ST_TYPE (sym->st_info) != STT_SECTION)
+                   {
+                     warn (_("Skipping unexpected symbol type %u\n"),
+                           ELF32_ST_TYPE (sym->st_info));
+                     continue;
+                   }
+               }
+             else
+               {
+                 sym = symtab + ELF64_R_SYM (rp->r_info);
+
+                 if (ELF64_ST_TYPE (sym->st_info) != STT_SECTION)
+                   {
+                     warn (_("Skipping unexpected symbol type %u\n"),
+                           ELF64_ST_TYPE (sym->st_info));
+                     continue;
+                   }
+               }
+
+             compunit.cu_abbrev_offset += rp->r_addend;
+             break;
+           }
+
+         free (rela);
+         break;
+       }
+
       tags = start + sizeof (* external);
       cu_offset = start - section_begin;
       start += compunit.cu_length + sizeof (external->cu_length);
@@ -6907,8 +7509,7 @@ display_debug_info (section, start, file)
          continue;
        }
 
-      if (first_abbrev != NULL)
-       free_abbrevs ();
+      free_abbrevs ();
 
       /* Read in the abbrevs used by this compilation unit.  */
 
@@ -6923,14 +7524,14 @@ display_debug_info (section, start, file)
          if (strcmp (SECTION_NAME (sec), ".debug_abbrev") == 0)
            break;
 
-       if (i == -1 || sec->sh_size == 0)
+       if (i == elf_header.e_shnum || sec->sh_size == 0)
          {
            warn (_("Unable to locate .debug_abbrev section!\n"));
            return 0;
          }
 
        begin = ((unsigned char *)
-                get_data (NULL, file, sec->sh_offset, sec->sh_size, 
+                get_data (NULL, file, sec->sh_offset, sec->sh_size,
                           _("debug_abbrev section data")));
        if (!begin)
          return 0;
@@ -6973,8 +7574,9 @@ display_debug_info (section, start, file)
              return 0;
            }
 
-         printf (_(" <%d><%x>: Abbrev Number: %lu (%s)\n"),
-                 level, tags - section_begin - bytes_read,
+         printf (_(" <%d><%lx>: Abbrev Number: %lu (%s)\n"),
+                 level,
+                 (unsigned long) (tags - section_begin - bytes_read),
                  abbrev_number,
                  get_TAG_name (entry->tag));
 
@@ -6989,6 +7591,8 @@ display_debug_info (section, start, file)
        }
     }
 
+  free_debug_str ();
+
   printf ("\n");
 
   return 1;
@@ -7021,6 +7625,12 @@ display_debug_aranges (section, start, file)
       arange.ar_pointer_size = BYTE_GET (external->ar_pointer_size);
       arange.ar_segment_size = BYTE_GET (external->ar_segment_size);
 
+      if (arange.ar_length == 0xffffffff)
+       {
+         warn (_("64-bit DWARF aranges are not supported yet.\n"));
+         break;
+       }
+
       if (arange.ar_version != 2)
        {
          warn (_("Only DWARF 2 aranges are currently supported.\n"));
@@ -7091,6 +7701,10 @@ Frame_Chunk;
    in the frame info.  */
 #define DW_CFA_unreferenced (-1)
 
+static void frame_need_space PARAMS ((Frame_Chunk *, int));
+static void frame_display_row PARAMS ((Frame_Chunk *, int *, int *));
+static int size_of_encoded_value PARAMS ((int));
+
 static void
 frame_need_space (fc, reg)
      Frame_Chunk * fc;
@@ -7232,6 +7846,12 @@ display_debug_frames (section, start, file)
       if (length == 0)
        return 1;
 
+      if (length == 0xffffffff)
+       {
+         warn (_("64-bit DWARF format frames are not supported yet.\n"));
+         break;
+       }
+
       block_end = saved_start + length + 4;
       cie_id = byte_get (start, 4); start += 4;
 
@@ -7340,7 +7960,7 @@ display_debug_frames (section, start, file)
 
          look_for = is_eh ? start - 4 - cie_id : section_start + cie_id;
 
-         for (cie=chunks; cie ; cie = cie->next)
+         for (cie = chunks; cie ; cie = cie->next)
            if (cie->chunk_start == look_for)
              break;
 
@@ -7389,10 +8009,10 @@ display_debug_frames (section, start, file)
              start += augmentation_data_len;
            }
 
-         printf ("\n%08lx %08lx %08lx FDE cie=%08x pc=%08lx..%08lx\n",
+         printf ("\n%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n",
                  (unsigned long)(saved_start - section_start), length, cie_id,
-                 cie->chunk_start - section_start, fc->pc_begin,
-                 fc->pc_begin + fc->pc_range);
+                 (unsigned long)(cie->chunk_start - section_start),
+                 fc->pc_begin, fc->pc_begin + fc->pc_range);
          if (! do_debug_frames_interp && augmentation_data_len)
            {
              unsigned long i;
@@ -7768,21 +8388,24 @@ prescan_debug_info (section, start, file)
      sections.  */
 struct
 {
-  char * name;
+  const char * const name;
   int (* display) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
   int (* prescan) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 }
 debug_displays[] =
 {
-  { ".debug_info",        display_debug_info, prescan_debug_info },
   { ".debug_abbrev",      display_debug_abbrev, NULL },
-  { ".debug_line",        display_debug_lines, NULL },
   { ".debug_aranges",     display_debug_aranges, NULL },
-  { ".debug_pubnames",    display_debug_pubnames, NULL },
   { ".debug_frame",       display_debug_frames, NULL },
+  { ".debug_info",        display_debug_info, prescan_debug_info },
+  { ".debug_line",        display_debug_lines, NULL },
+  { ".debug_pubnames",    display_debug_pubnames, NULL },
   { ".eh_frame",          display_debug_frames, NULL },
-  { ".debug_macinfo",     display_debug_not_supported, NULL },
-  { ".debug_str",         display_debug_not_supported, NULL },
+  { ".debug_macinfo",     display_debug_macinfo, NULL },
+  { ".debug_str",         display_debug_str, NULL },
+  
+  { ".debug_pubtypes",    display_debug_not_supported, NULL },
+  { ".debug_ranges",      display_debug_not_supported, NULL },
   { ".debug_static_func", display_debug_not_supported, NULL },
   { ".debug_static_vars", display_debug_not_supported, NULL },
   { ".debug_types",       display_debug_not_supported, NULL },
@@ -7806,7 +8429,7 @@ display_debug_section (section, file)
       return 0;
     }
 
-  start = (unsigned char *) get_data (NULL, file, section->sh_offset, length, 
+  start = (unsigned char *) get_data (NULL, file, section->sh_offset, length,
                                      _("debug section data"));
   if (!start)
     return 0;
@@ -7829,8 +8452,7 @@ display_debug_section (section, file)
 
   /* If we loaded in the abbrev section at some point,
      we must release it here.  */
-  if (first_abbrev != NULL)
-    free_abbrevs ();
+  free_abbrevs ();
 
   return 1;
 }
@@ -7869,7 +8491,7 @@ process_section_contents (file)
 
                length = section->sh_size;
                start = ((unsigned char *)
-                        get_data (NULL, file, section->sh_offset, length, 
+                        get_data (NULL, file, section->sh_offset, length,
                                   _("debug section data")));
                if (!start)
                  return 0;
@@ -8291,7 +8913,8 @@ process_mips_specific (file)
          free (econf64);
        }
 
-      printf (_("\nSection '.conflict' contains %d entries:\n"), conflictsno);
+      printf (_("\nSection '.conflict' contains %ld entries:\n"),
+             (long) conflictsno);
       puts (_("  Num:    Index       Value  Name"));
 
       for (cnt = 0; cnt < conflictsno; ++cnt)
@@ -8338,7 +8961,7 @@ get_note_type (e_type)
    terminated, and namesz includes the terminating null byte.
    I.E. the value of namesz for the name "FSF" is 4.
 
-   If the value of namesz is zero, there is no name present. */
+   If the value of namesz is zero, there is no name present.  */
 static int
 process_note (pnote)
   Elf32_Internal_Note * pnote;
@@ -8561,8 +9184,8 @@ get_file_header (file)
         overwritting things.  */
       if (sizeof (bfd_vma) < 8)
        {
-         error (_("This instance of readelf has been built without support for a\n"));
-         error (_("64 bit data type and so it cannot read 64 bit ELF files.\n"));
+         error (_("This instance of readelf has been built without support for a\n\
+64 bit data type and so it cannot read 64 bit ELF files.\n"));
          return 0;
        }
 
@@ -8584,10 +9207,17 @@ get_file_header (file)
       elf_header.e_shstrndx  = BYTE_GET (ehdr64.e_shstrndx);
     }
 
+  /* There may be some extensions in the first section header.  Don't
+     bomb if we can't read it.  */
+  if (is_32bit_elf)
+    get_32bit_section_headers (file, 1);
+  else
+    get_64bit_section_headers (file, 1);
+
   return 1;
 }
 
-static void
+static int
 process_file (file_name)
      char * file_name;
 {
@@ -8598,21 +9228,21 @@ process_file (file_name)
   if (stat (file_name, & statbuf) < 0)
     {
       error (_("Cannot stat input file %s.\n"), file_name);
-      return;
+      return 1;
     }
 
   file = fopen (file_name, "rb");
   if (file == NULL)
     {
       error (_("Input file %s not found.\n"), file_name);
-      return;
+      return 1;
     }
 
   if (! get_file_header (file))
     {
       error (_("%s: Failed to read file header\n"), file_name);
       fclose (file);
-      return;
+      return 1;
     }
 
   /* Initialise per file variables.  */
@@ -8629,7 +9259,7 @@ process_file (file_name)
   if (! process_file_header ())
     {
       fclose (file);
-      return;
+      return 1;
     }
 
   process_section_headers (file);
@@ -8687,12 +9317,14 @@ process_file (file_name)
       free (dynamic_syminfo);
       dynamic_syminfo = NULL;
     }
+
+  return 0;
 }
 
 #ifdef SUPPORT_DISASSEMBLY
 /* Needed by the i386 disassembler.  For extra credit, someone could
    fix this so that we insert symbolic addresses here, esp for GOT/PLT
-   symbols */
+   symbols */
 
 void
 print_address (unsigned int addr, FILE * outfile)
@@ -8700,7 +9332,7 @@ print_address (unsigned int addr, FILE * outfile)
   fprintf (outfile,"0x%8.8x", addr);
 }
 
-/* Needed by the i386 disassembler. */
+/* Needed by the i386 disassembler.  */
 void
 db_task_printsym (unsigned int addr)
 {
@@ -8708,13 +9340,20 @@ db_task_printsym (unsigned int addr)
 }
 #endif
 
+int main PARAMS ((int, char **));
+
 int
 main (argc, argv)
      int     argc;
      char ** argv;
 {
+  int err;
+
 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
   setlocale (LC_MESSAGES, "");
+#endif
+#if defined (HAVE_SETLOCALE)
+  setlocale (LC_CTYPE, "");
 #endif
   bindtextdomain (PACKAGE, LOCALEDIR);
   textdomain (PACKAGE);
@@ -8724,11 +9363,12 @@ main (argc, argv)
   if (optind < (argc - 1))
     show_name = 1;
 
+  err = 0;
   while (optind < argc)
-    process_file (argv [optind ++]);
+    err |= process_file (argv [optind ++]);
 
   if (dump_sects != NULL)
     free (dump_sects);
 
-  return 0;
+  return err;
 }