]> 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 eced501409e7dd94a5ddf7856e4c4b0a3d93adca..73a98b5c44b2576f7f7cc8234ca80a49d7dfc74e 100644 (file)
@@ -68,6 +68,7 @@
 #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"
@@ -76,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"
@@ -111,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;
@@ -121,6 +124,7 @@ 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;
@@ -193,8 +197,8 @@ 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 *));
@@ -218,7 +222,11 @@ static int                display_debug_abbrev        PARAMS ((Elf32_Internal_Sh
 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));
@@ -229,12 +237,13 @@ 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 *));
@@ -273,69 +282,35 @@ 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;
+  VA_CLOSE (args);
 }
 
 static void
-warn (const char * message, ...)
+warn VPARAMS ((const 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);
-  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
-{
-  char * message;
-  va_list args;
-
-  fprintf (stderr, _("%s: Warning: "), program_name);
-  va_start (args);
-  message = va_arg (args, char *);
-  vfprintf (stderr, message, args);
-  va_end (args);
-  return;
-}
-#endif
-
 static PTR get_data PARAMS ((PTR, FILE *, long, size_t, const char *));
 
 static PTR
@@ -473,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
@@ -620,6 +595,8 @@ guess_is_rela (e_machine)
     case EM_X86_64:
     case EM_S390:
     case EM_S390_OLD:
+    case EM_MMIX:
+    case EM_XSTORMY16:
       return TRUE;
 
     case EM_MMA:
@@ -974,6 +951,10 @@ 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);
@@ -1030,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)
@@ -1417,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;
@@ -1841,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))
        {
@@ -2032,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);
 
@@ -2071,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}
 };
@@ -2097,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[liaprmf] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=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"));
@@ -2105,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);
 
@@ -2114,7 +2105,7 @@ usage ()
 static void
 request_dump (section, type)
      unsigned int section;
-     char         type;
+     int         type;
 {
   if (section >= num_dump_sects)
     {
@@ -2153,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;
@@ -2233,49 +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;
 
-               case 'm':
-               case 'M':
-                 do_debug_macinfo = 1;
-                 break;
+                 case 'F':
+                   do_debug_frames_interp = 1;
+                 case 'f':
+                   do_debug_frames = 1;
+                   break;
 
-               default:
-                 warn (_("Unrecognised debug option '%s'\n"), optarg);
-                 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
@@ -2295,6 +2295,9 @@ parse_args (argc, argv)
        case 'V':
          do_version ++;
          break;
+       case 'W':
+         do_wide ++;
+         break;
        default:
        oops:
          /* xgettext:c-format */
@@ -2318,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;
@@ -2335,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];
 
@@ -2352,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;
@@ -2442,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;
@@ -2578,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
@@ -2612,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);
@@ -2668,7 +2732,7 @@ process_program_headers (file)
 
   if (loadaddr == -1)
     {
-      /* Very strange. */
+      /* Very strange.  */
       loadaddr = 0;
     }
 
@@ -2715,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;
@@ -2724,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)
     {
@@ -2739,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);
@@ -2760,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;
@@ -2769,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)
     {
@@ -2784,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);
@@ -2962,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.  */
@@ -2980,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;
@@ -3018,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_macinfo)
+               || do_debug_frames || do_debug_macinfo || do_debug_str)
               && strncmp (name, ".debug_", 7) == 0)
        {
          name += 7;
@@ -3031,6 +3097,7 @@ process_section_headers (file)
              || (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);
        }
@@ -3050,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"));
@@ -3081,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", (unsigned long) 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 ("  ");
@@ -3100,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;
 }
@@ -3487,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;
                }
@@ -3499,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;
                }
@@ -3507,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;
            }
 
@@ -3957,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))
@@ -3996,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))
@@ -4012,7 +4130,6 @@ process_dynamic_segment (file)
 
          dynamic_strings = (char *) get_data (NULL, file, offset, str_tab_len,
                                               _("dynamic string table"));
-
          break;
        }
     }
@@ -4661,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;
@@ -5018,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;
@@ -5620,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;
     }
 
@@ -5693,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
@@ -5803,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,
@@ -5873,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;
@@ -5921,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;
@@ -6437,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)
@@ -6455,6 +6616,8 @@ display_debug_abbrev (section, start, file)
                      get_FORM_name (attr->form));
            }
        }
+
+      free_abbrevs ();
     }
   while (start);
 
@@ -6805,8 +6968,125 @@ decode_location_expression (data, pointer_size, length)
 }
 
 
+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;
@@ -6817,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:
@@ -6830,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:
@@ -6858,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)
@@ -6923,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;
     }
 
@@ -6965,7 +7259,7 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size)
          /* 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;
+       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;
@@ -7083,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;
 }
@@ -7098,6 +7406,8 @@ 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;
@@ -7115,6 +7425,12 @@ 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;
@@ -7152,7 +7468,7 @@ display_debug_info (section, start, file)
 
                  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;
                    }
@@ -7163,7 +7479,7 @@ display_debug_info (section, start, file)
 
                  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;
                    }
@@ -7193,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.  */
 
@@ -7209,7 +7524,7 @@ 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;
@@ -7276,6 +7591,8 @@ display_debug_info (section, start, file)
        }
     }
 
+  free_debug_str ();
+
   printf ("\n");
 
   return 1;
@@ -7308,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"));
@@ -7523,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;
 
@@ -7631,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;
 
@@ -8059,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_macinfo, NULL },
-  { ".debug_str",         display_debug_not_supported, 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 },
@@ -8120,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;
 }
@@ -8630,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;
@@ -8853,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;
        }
 
@@ -8876,6 +9207,13 @@ 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;
 }
 
@@ -8986,7 +9324,7 @@ process_file (file_name)
 #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)
@@ -8994,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)
 {
@@ -9002,6 +9340,8 @@ db_task_printsym (unsigned int addr)
 }
 #endif
 
+int main PARAMS ((int, char **));
+
 int
 main (argc, argv)
      int     argc;