* readelf.c Replace occurrences of Elf32_Internal_* and
[binutils-gdb.git] / binutils / readelf.c
index 3bd67ba9baaaa5123f9c6d5cdc7b0de404ebc633..ba9529a4899edf09c51dad034bd281221616b79f 100644 (file)
 #include "elf/cris.h"
 #include "elf/d10v.h"
 #include "elf/d30v.h"
+#include "elf/dlx.h"
 #include "elf/fr30.h"
+#include "elf/frv.h"
 #include "elf/h8.h"
 #include "elf/hppa.h"
 #include "elf/i386.h"
+#include "elf/i370.h"
 #include "elf/i860.h"
 #include "elf/i960.h"
 #include "elf/ia64.h"
+#include "elf/ip2k.h"
 #include "elf/m32r.h"
 #include "elf/m68k.h"
+#include "elf/m68hc11.h"
 #include "elf/mcore.h"
 #include "elf/mips.h"
 #include "elf/mmix.h"
@@ -77,6 +82,7 @@
 #include "elf/sh.h"
 #include "elf/sparc.h"
 #include "elf/v850.h"
+#include "elf/vax.h"
 #include "elf/x86-64.h"
 #include "elf/xstormy16.h"
 
@@ -127,6 +133,7 @@ int                     do_debug_frames;
 int                     do_debug_frames_interp;
 int                    do_debug_macinfo;
 int                    do_debug_str;
+int                     do_debug_loc;
 int                     do_arch;
 int                     do_notes;
 int                    is_32bit_elf;
@@ -154,7 +161,7 @@ print_mode;
 
 /* Forward declarations for dumb compilers.  */
 static void              print_vma                   PARAMS ((bfd_vma, print_mode));
-static void              print_symbol                PARAMS ((int, char *));
+static void              print_symbol                PARAMS ((int, const char *));
 static bfd_vma (*         byte_get)                   PARAMS ((unsigned char *, int));
 static bfd_vma            byte_get_little_endian      PARAMS ((unsigned char *, int));
 static bfd_vma            byte_get_big_endian         PARAMS ((unsigned char *, int));
@@ -164,7 +171,7 @@ static const char *       get_ppc64_dynamic_type      PARAMS ((unsigned long));
 static const char *       get_parisc_dynamic_type     PARAMS ((unsigned long));
 static const char *       get_dynamic_type            PARAMS ((unsigned long));
 static int               slurp_rela_relocs           PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rela **, unsigned long *));
-static int               slurp_rel_relocs            PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rel **, unsigned long *));
+static int               slurp_rel_relocs            PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rela **, unsigned long *));
 static int                dump_relocations            PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, unsigned long, char *, int));
 static char *             get_file_type               PARAMS ((unsigned));
 static char *             get_machine_name            PARAMS ((unsigned));
@@ -213,24 +220,27 @@ static int *              get_dynamic_data            PARAMS ((FILE *, unsigned
 static int                get_32bit_dynamic_segment   PARAMS ((FILE *));
 static int                get_64bit_dynamic_segment   PARAMS ((FILE *));
 #ifdef SUPPORT_DISASSEMBLY
-static int               disassemble_section         PARAMS ((Elf32_Internal_Shdr *, FILE *));
+static int               disassemble_section         PARAMS ((Elf_Internal_Shdr *, FILE *));
 #endif
-static int               dump_section                PARAMS ((Elf32_Internal_Shdr *, FILE *));
-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 int               dump_section                PARAMS ((Elf_Internal_Shdr *, FILE *));
+static int               display_debug_section       PARAMS ((Elf_Internal_Shdr *, FILE *));
+static int                display_debug_info          PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_not_supported PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
+static int                prescan_debug_info          PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_lines         PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_pubnames      PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_abbrev        PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_aranges       PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_frames        PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_macinfo       PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_str           PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_loc           PARAMS ((Elf_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 void               load_debug_loc              PARAMS ((FILE *));
+static void               free_debug_loc              PARAMS ((void));
 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));
@@ -251,11 +261,12 @@ static const char *       get_osabi_name              PARAMS ((unsigned int));
 static int               guess_is_rela               PARAMS ((unsigned long));
 static const char *      get_note_type                  PARAMS ((unsigned int));
 static const char *      get_netbsd_elfcore_note_type   PARAMS ((unsigned int));
-static int               process_note                   PARAMS ((Elf32_Internal_Note *));
+static int               process_note                   PARAMS ((Elf_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 *));
+static int               process_gnu_liblist            PARAMS ((FILE *));
 
 typedef int Elf32_Word;
 
@@ -395,7 +406,7 @@ byte_get_little_endian (field, size)
     case 8:
       /* We want to extract data from an 8 byte wide field and
         place it into a 4 byte wide field.  Since this is a little
-        endian source we can juts use the 4 byte extraction code.  */
+        endian source we can just use the 4 byte extraction code.  */
       /* Fall through.  */
 #endif
     case 4:
@@ -517,20 +528,20 @@ print_vma (vma, mode)
 
 /* Display a symbol on stdout.  If do_wide is not true then
    format the symbol to be at most WIDTH characters,
-   truhncating as necessary.  If WIDTH is negative then
+   truncating as necessary.  If WIDTH is negative then
    format the string to be exactly - WIDTH characters,
    truncating or padding as necessary.  */
 
 static void
 print_symbol (width, symbol)
      int width;
-     char * symbol;
+     const char * symbol;
 {
   if (do_wide)
-    printf (symbol);
+    printf ("%s", symbol);
   else if (width < 0)
     printf ("%-*.*s", width, width, symbol);
-  else 
+  else
     printf ("%-.*s", width, symbol);
 }
 
@@ -597,6 +608,7 @@ guess_is_rela (e_machine)
     case EM_386:
     case EM_486:
     case EM_960:
+    case EM_DLX:
     case EM_OPENRISC:
     case EM_OR32:
     case EM_M32R:
@@ -627,6 +639,7 @@ guess_is_rela (e_machine)
     case EM_CYGNUS_MN10300:
     case EM_FR30:
     case EM_CYGNUS_FR30:
+    case EM_CYGNUS_FRV:
     case EM_SH:
     case EM_ALPHA:
     case EM_MCORE:
@@ -640,6 +653,9 @@ guess_is_rela (e_machine)
     case EM_S390_OLD:
     case EM_MMIX:
     case EM_XSTORMY16:
+    case EM_VAX:
+    case EM_IP2K:
+    case EM_IP2K_OLD:
       return TRUE;
 
     case EM_MMA:
@@ -659,7 +675,6 @@ guess_is_rela (e_machine)
     case EM_68HC05:
     case EM_SVX:
     case EM_ST19:
-    case EM_VAX:
     default:
       warn (_("Don't know about relocations on this machine architecture\n"));
       return FALSE;
@@ -746,10 +761,10 @@ slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp)
      FILE *file;
      unsigned long rel_offset;
      unsigned long rel_size;
-     Elf_Internal_Rel **relsp;
+     Elf_Internal_Rela **relsp;
      unsigned long *nrelsp;
 {
-  Elf_Internal_Rel *rels;
+  Elf_Internal_Rela *rels;
   unsigned long nrels;
   unsigned int i;
 
@@ -764,7 +779,7 @@ slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp)
 
       nrels = rel_size / sizeof (Elf32_External_Rel);
 
-      rels = (Elf_Internal_Rel *) malloc (nrels * sizeof (Elf_Internal_Rel));
+      rels = (Elf_Internal_Rela *) malloc (nrels * sizeof (Elf_Internal_Rela));
 
       if (rels == NULL)
        {
@@ -776,6 +791,7 @@ slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp)
        {
          rels[i].r_offset = BYTE_GET (erels[i].r_offset);
          rels[i].r_info   = BYTE_GET (erels[i].r_info);
+         rels[i].r_addend = 0;
        }
 
       free (erels);
@@ -791,7 +807,7 @@ slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp)
 
       nrels = rel_size / sizeof (Elf64_External_Rel);
 
-      rels = (Elf_Internal_Rel *) malloc (nrels * sizeof (Elf_Internal_Rel));
+      rels = (Elf_Internal_Rela *) malloc (nrels * sizeof (Elf_Internal_Rela));
 
       if (rels == NULL)
        {
@@ -803,6 +819,7 @@ slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp)
        {
          rels[i].r_offset = BYTE_GET8 (erels[i].r_offset);
          rels[i].r_info   = BYTE_GET8 (erels[i].r_info);
+         rels[i].r_addend = 0;
        }
 
       free (erels);
@@ -824,8 +841,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
      int                is_rela;
 {
   unsigned int        i;
-  Elf_Internal_Rel *  rels;
-  Elf_Internal_Rela * relas;
+  Elf_Internal_Rela * rels;
 
 
   if (is_rela == UNKNOWN)
@@ -833,7 +849,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
 
   if (is_rela)
     {
-      if (!slurp_rela_relocs (file, rel_offset, rel_size, &relas, &rel_size))
+      if (!slurp_rela_relocs (file, rel_offset, rel_size, &rels, &rel_size))
        return 0;
     }
   else
@@ -845,40 +861,52 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
   if (is_32bit_elf)
     {
       if (is_rela)
-       printf
-         (_(" Offset     Info    Type            Symbol's Value  Symbol's Name          Addend\n"));
+       {
+         if (do_wide)
+           printf (_(" Offset     Info    Type                Sym. Value  Symbol's Name + Addend\n"));
+         else
+           printf (_(" Offset     Info    Type            Sym.Value  Sym. Name + Addend\n"));
+       }
       else
-       printf
-         (_(" Offset     Info    Type            Symbol's Value  Symbol's Name\n"));
+       {
+         if (do_wide)
+           printf (_(" Offset     Info    Type                Sym. Value  Symbol's Name\n"));
+         else
+           printf (_(" Offset     Info    Type            Sym.Value  Sym. Name\n"));
+       }
     }
   else
     {
       if (is_rela)
-       printf
-         (_("    Offset             Info            Type               Symbol's Value   Symbol's Name           Addend\n"));
+       {
+         if (do_wide)
+           printf (_("    Offset             Info            Type               Symbol's Value  Symbol's Name + Addend\n"));
+         else
+           printf (_("  Offset          Info           Type           Sym. Value    Sym. Name + Addend\n"));
+       }
       else
-       printf
-         (_("    Offset             Info            Type               Symbol's Value   Symbol's Name\n"));
+       {
+         if (do_wide)
+           printf (_("    Offset             Info            Type               Symbol's Value  Symbol's Name\n"));
+         else
+           printf (_("  Offset          Info           Type           Sym. Value    Sym. Name\n"));
+       }
     }
 
   for (i = 0; i < rel_size; i++)
     {
       const char * rtype;
+      const char * rtype2 = NULL;
+      const char * rtype3 = NULL;
       bfd_vma      offset;
       bfd_vma      info;
       bfd_vma      symtab_index;
       bfd_vma      type;
+      bfd_vma      type2 = (bfd_vma) NULL;
+      bfd_vma      type3 = (bfd_vma) NULL;
 
-      if (is_rela)
-       {
-         offset = relas [i].r_offset;
-         info   = relas [i].r_info;
-       }
-      else
-       {
-         offset = rels [i].r_offset;
-         info   = rels [i].r_info;
-       }
+      offset = rels [i].r_offset;
+      info   = rels [i].r_info;
 
       if (is_32bit_elf)
        {
@@ -887,10 +915,16 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
        }
       else
        {
-         if (elf_header.e_machine == EM_SPARCV9)
-           type       = ELF64_R_TYPE_ID (info);
+         if (elf_header.e_machine == EM_MIPS)
+           {
+             type  = ELF64_MIPS_R_TYPE (info);
+             type2 = ELF64_MIPS_R_TYPE2 (info);
+             type3 = ELF64_MIPS_R_TYPE3 (info);
+           }
+         else if (elf_header.e_machine == EM_SPARCV9)
+           type = ELF64_R_TYPE_ID (info);
          else
-           type       = ELF64_R_TYPE (info);
+           type = ELF64_R_TYPE (info);
          /* The #ifdef BFD64 below is to prevent a compile time warning.
             We know that if we do not have a 64 bit data type that we
             will never execute this code anyway.  */
@@ -910,13 +944,18 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
       else
        {
 #ifdef _bfd_int64_low
-         printf ("%8.8lx%8.8lx  %8.8lx%8.8lx ",
+         printf (do_wide
+                 ? "%8.8lx%8.8lx  %8.8lx%8.8lx "
+                 : "%4.4lx%8.8lx  %4.4lx%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);
+         printf (do_wide
+                 ? "%16.16lx  %16.16lx "
+                 : "%12.12lx  %12.12lx ",
+                 offset, info);
 #endif
        }
 
@@ -936,6 +975,11 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = elf_i386_reloc_type (type);
          break;
 
+        case EM_68HC11:
+        case EM_68HC12:
+          rtype = elf_m68hc11_reloc_type (type);
+          break;
+
        case EM_68K:
          rtype = elf_m68k_reloc_type (type);
          break;
@@ -971,6 +1015,10 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = elf_d30v_reloc_type (type);
          break;
 
+       case EM_DLX:
+         rtype = elf_dlx_reloc_type (type);
+         break;
+
        case EM_SH:
          rtype = elf_sh_reloc_type (type);
          break;
@@ -990,6 +1038,10 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = elf_fr30_reloc_type (type);
          break;
 
+        case EM_CYGNUS_FRV:
+          rtype = elf_frv_reloc_type (type);
+          break;
+
        case EM_MCORE:
          rtype = elf_mcore_reloc_type (type);
          break;
@@ -1006,6 +1058,11 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
        case EM_MIPS:
        case EM_MIPS_RS3_LE:
          rtype = elf_mips_reloc_type (type);
+         if (!is_32bit_elf)
+           {
+             rtype2 = elf_mips_reloc_type (type2);
+             rtype3 = elf_mips_reloc_type (type3);
+           }
          break;
 
        case EM_ALPHA:
@@ -1055,24 +1112,37 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          rtype = elf_x86_64_reloc_type (type);
          break;
 
-        case EM_S390_OLD:
-        case EM_S390:
-          rtype = elf_s390_reloc_type (type);
-          break;
+       case EM_S370:
+         rtype = i370_reloc_type (type);
+         break;
+
+       case EM_S390_OLD:
+       case EM_S390:
+         rtype = elf_s390_reloc_type (type);
+         break;
 
        case EM_XSTORMY16:
          rtype = elf_xstormy16_reloc_type (type);
          break;
+
+       case EM_VAX:
+         rtype = elf_vax_reloc_type (type);
+         break;
+
+       case EM_IP2K:
+       case EM_IP2K_OLD:
+         rtype = elf_ip2k_reloc_type (type);
+         break;
        }
 
       if (rtype == NULL)
 #ifdef _bfd_int64_low
-       printf (_("unrecognised: %-7lx"), _bfd_int64_low (type));
+       printf (_("unrecognized: %-7lx"), _bfd_int64_low (type));
 #else
-       printf (_("unrecognised: %-7lx"), type);
+       printf (_("unrecognized: %-7lx"), type);
 #endif
       else
-       printf ("%-21.21s", rtype);
+       printf (do_wide ? "%-21.21s" : "%-17.17s", rtype);
 
       if (symtab_index)
        {
@@ -1086,23 +1156,51 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
 
              printf (" ");
              print_vma (psym->st_value, LONG_HEX);
-             printf ( ");
+             printf (is_32bit_elf ? "   " : " ");
 
              if (psym->st_name == 0)
-               print_symbol (-25, SECTION_NAME (section_headers + psym->st_shndx));
+               {
+                 const char *sec_name = "<null>";
+                 char name_buf[40];
+
+                 if (ELF_ST_TYPE (psym->st_info) == STT_SECTION)
+                   {
+                     bfd_vma sec_index = (bfd_vma) -1;
+
+                     if (psym->st_shndx < SHN_LORESERVE)
+                       sec_index = psym->st_shndx;
+                     else if (psym->st_shndx > SHN_LORESERVE)
+                       sec_index = psym->st_shndx - (SHN_HIRESERVE + 1
+                                                     - SHN_LORESERVE);
+
+                     if (sec_index != (bfd_vma) -1)
+                       sec_name = SECTION_NAME (section_headers + sec_index);
+                     else if (psym->st_shndx == SHN_ABS)
+                       sec_name = "ABS";
+                     else if (psym->st_shndx == SHN_COMMON)
+                       sec_name = "COMMON";
+                     else
+                       {
+                         sprintf (name_buf, "<section 0x%x>",
+                                  (unsigned int) psym->st_shndx);
+                         sec_name = name_buf;
+                       }
+                   }
+                 print_symbol (22, sec_name);
+               }
              else if (strtab == NULL)
                printf (_("<string table index %3ld>"), psym->st_name);
              else
-               print_symbol (-25, strtab + psym->st_name);
+               print_symbol (22, strtab + psym->st_name);
 
              if (is_rela)
-               printf (" + %lx", (unsigned long) relas [i].r_addend);
+               printf (" + %lx", (unsigned long) rels [i].r_addend);
            }
        }
       else if (is_rela)
        {
-         printf ("%*c", is_32bit_elf ? 34 : 26, ' ');
-         print_vma (relas[i].r_addend, LONG_HEX);
+         printf ("%*c", is_32bit_elf ? (do_wide ? 34 : 28) : (do_wide ? 26 : 20), ' ');
+         print_vma (rels[i].r_addend, LONG_HEX);
        }
 
       if (elf_header.e_machine == EM_SPARCV9
@@ -1110,12 +1208,36 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
        printf (" + %lx", (unsigned long) ELF64_R_TYPE_DATA (info));
 
       putchar ('\n');
+
+      if (! is_32bit_elf && elf_header.e_machine == EM_MIPS)
+       {
+         printf ("                    Type2: ");
+
+         if (rtype2 == NULL)
+#ifdef _bfd_int64_low
+           printf (_("unrecognized: %-7lx"), _bfd_int64_low (type2));
+#else
+           printf (_("unrecognized: %-7lx"), type2);
+#endif
+         else
+           printf ("%-17.17s", rtype2);
+
+         printf("\n                    Type3: ");
+
+         if (rtype3 == NULL)
+#ifdef _bfd_int64_low
+           printf (_("unrecognized: %-7lx"), _bfd_int64_low (type3));
+#else
+           printf (_("unrecognized: %-7lx"), type3);
+#endif
+         else
+           printf ("%-17.17s", rtype3);
+
+         putchar ('\n');
+       }
     }
 
-  if (is_rela)
-    free (relas);
-  else
-    free (rels);
+  free (rels);
 
   return 1;
 }
@@ -1298,6 +1420,12 @@ get_dynamic_type (type)
     case DT_USED:      return "USED";
     case DT_FILTER:    return "FILTER";
 
+    case DT_GNU_PRELINKED: return "GNU_PRELINKED";
+    case DT_GNU_CONFLICT: return "GNU_CONFLICT";
+    case DT_GNU_CONFLICTSZ: return "GNU_CONFLICTSZ";
+    case DT_GNU_LIBLIST: return "GNU_LIBLIST";
+    case DT_GNU_LIBLISTSZ: return "GNU_LIBLISTSZ";
+
     default:
       if ((type >= DT_LOPROC) && (type <= DT_HIPROC))
        {
@@ -1435,6 +1563,7 @@ get_machine_name (e_machine)
     case EM_MN10200:           return "mn10200";
     case EM_CYGNUS_FR30:
     case EM_FR30:              return "Fujitsu FR30";
+    case EM_CYGNUS_FRV:                return "Fujitsu FR-V";
     case EM_PJ_OLD:
     case EM_PJ:                 return "picoJava";
     case EM_MMA:               return "Fujitsu Multimedia Accelerator";
@@ -1470,6 +1599,9 @@ get_machine_name (e_machine)
     case EM_XSTORMY16:         return "Sanyo Xstormy16 CPU core";
     case EM_OPENRISC:
     case EM_OR32:              return "OpenRISC";
+    case EM_DLX:               return "OpenDLX";
+    case EM_IP2K_OLD:
+    case EM_IP2K:               return "Ubicom IP2xxx 8-bit microcontrollers";
     default:
       sprintf (buff, _("<unknown>: %x"), e_machine);
       return buff;
@@ -1504,7 +1636,7 @@ decode_ARM_machine_flags (e_flags, buf)
   switch (eabi)
     {
     default:
-      strcat (buf, ", <unrecognised EABI>");
+      strcat (buf, ", <unrecognized EABI>");
       if (e_flags)
        unknown = 1;
       break;
@@ -1638,12 +1770,12 @@ get_machine_flags (e_flags, e_machine)
          decode_ARM_machine_flags (e_flags, buf);
          break;
 
-        case EM_68K:
-          if (e_flags & EF_CPU32)
-            strcat (buf, ", cpu32");
+       case EM_68K:
+         if (e_flags & EF_CPU32)
+           strcat (buf, ", cpu32");
          if (e_flags & EF_M68000)
            strcat (buf, ", m68000");
-          break;
+         break;
 
        case EM_PPC:
          if (e_flags & EF_PPC_EMB)
@@ -1663,9 +1795,6 @@ get_machine_flags (e_flags, e_machine)
            case E_V850E_ARCH:
              strcat (buf, ", v850e");
              break;
-           case E_V850EA_ARCH:
-             strcat (buf, ", v850ea");
-             break;
            case E_V850_ARCH:
              strcat (buf, ", v850");
              break;
@@ -1710,8 +1839,11 @@ get_machine_flags (e_flags, e_machine)
            case E_MIPS_MACH_3900: strcat (buf, ", 3900"); break;
            case E_MIPS_MACH_4010: strcat (buf, ", 4010"); break;
            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_4120: strcat (buf, ", 4120"); break;
+           case E_MIPS_MACH_4650: strcat (buf, ", 4650"); break;
+           case E_MIPS_MACH_5400: strcat (buf, ", 5400"); break;
+           case E_MIPS_MACH_5500: strcat (buf, ", 5500"); break;
            case E_MIPS_MACH_SB1:  strcat (buf, ", sb1");  break;
            case 0:
            /* We simply ignore the field in this case to avoid confusion:
@@ -1834,6 +1966,15 @@ get_machine_flags (e_flags, e_machine)
          if ((e_flags & EF_IA_64_ABSOLUTE))
            strcat (buf, ", absolute");
          break;
+
+       case EM_VAX:
+         if ((e_flags & EF_VAX_NONPIC))
+           strcat (buf, ", non-PIC");
+         if ((e_flags & EF_VAX_DFLOAT))
+           strcat (buf, ", D-Float");
+         if ((e_flags & EF_VAX_GFLOAT))
+           strcat (buf, ", G-Float");
+         break;
        }
     }
 
@@ -1920,6 +2061,7 @@ get_segment_type (p_type)
     case PT_NOTE:       return "NOTE";
     case PT_SHLIB:      return "SHLIB";
     case PT_PHDR:       return "PHDR";
+    case PT_TLS:       return "TLS";
 
     case PT_GNU_EH_FRAME:
                        return "GNU_EH_FRAME";
@@ -2092,6 +2234,7 @@ get_section_type_name (sh_type)
     case 0x6ffffffc:           return "VERDEF";
     case 0x7ffffffd:           return "AUXILIARY";
     case 0x7fffffff:           return "FILTER";
+    case SHT_GNU_LIBLIST:      return "GNU_LIBLIST";
 
     default:
       if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC))
@@ -2131,6 +2274,8 @@ get_section_type_name (sh_type)
     }
 }
 
+#define OPTION_DEBUG_DUMP      512
+
 struct option options [] =
 {
   {"all",              no_argument, 0, 'a'},
@@ -2150,7 +2295,7 @@ struct option options [] =
   {"version-info",     no_argument, 0, 'V'},
   {"use-dynamic",      no_argument, 0, 'D'},
   {"hex-dump",         required_argument, 0, 'x'},
-  {"debug-dump",       optional_argument, 0, 'w'},
+  {"debug-dump",       optional_argument, 0, OPTION_DEBUG_DUMP},
   {"unwind",          no_argument, 0, 'u'},
 #ifdef SUPPORT_DISASSEMBLY
   {"instruction-dump", required_argument, 0, 'i'},
@@ -2185,7 +2330,8 @@ usage ()
   -A --arch-specific     Display architecture specific information (if any).\n\
   -D --use-dynamic       Use the dynamic section info when displaying symbols\n\
   -x --hex-dump=<number> Dump the contents of section <number>\n\
-  -w --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str]\n\
+  -w[liaprmfFso] or\n\
+  --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str,=loc]\n\
                          Display the contents of DWARF2 debug sections\n"));
 #ifdef SUPPORT_DISASSEMBLY
   fprintf (stdout, _("\
@@ -2325,7 +2471,7 @@ parse_args (argc, argv)
          else
            {
              unsigned int index = 0;
-             
+
              do_debugging = 0;
 
              while (optarg[index])
@@ -2372,12 +2518,99 @@ parse_args (argc, argv)
                    do_debug_str = 1;
                    break;
 
+                 case 'o':
+                 case 'O':
+                   do_debug_loc = 1;
+                   break;
+
                  default:
-                   warn (_("Unrecognised debug option '%s'\n"), optarg);
+                   warn (_("Unrecognized debug option '%s'\n"), optarg);
                    break;
                  }
            }
          break;
+       case OPTION_DEBUG_DUMP:
+         do_dump ++;
+         if (optarg == 0)
+           do_debugging = 1;
+         else
+           {
+             static const char *debug_dump_opt[]
+               = { "line", "info", "abbrev", "pubnames", "ranges",
+                   "macro", "frames", "frames-interp", "str", "loc", NULL };
+             unsigned int index;
+             const char *p;
+
+             do_debugging = 0;
+
+             p = optarg;
+             while (*p)
+               {
+                 for (index = 0; debug_dump_opt[index]; index++)
+                   {
+                     size_t len = strlen (debug_dump_opt[index]);
+
+                     if (strncmp (p, debug_dump_opt[index], len) == 0
+                         && (p[len] == ',' || p[len] == '\0'))
+                       {
+                         switch (p[0])
+                           {
+                           case 'i':
+                             do_debug_info = 1;
+                             break;
+
+                           case 'a':
+                             do_debug_abbrevs = 1;
+                             break;
+
+                           case 'l':
+                             if (p[1] == 'i')
+                               do_debug_lines = 1;
+                             else
+                               do_debug_loc = 1;
+                             break;
+
+                           case 'p':
+                             do_debug_pubnames = 1;
+                             break;
+
+                           case 'r':
+                             do_debug_aranges = 1;
+                             break;
+
+                           case 'f':
+                             if (len > 6)
+                               do_debug_frames_interp = 1;
+                             do_debug_frames = 1;
+                             break;
+
+                           case 'm':
+                             do_debug_macinfo = 1;
+                             break;
+
+                           case 's':
+                             do_debug_str = 1;
+                             break;
+                           }
+
+                         p += len;
+                         break;
+                       }
+                   }
+
+                 if (debug_dump_opt[index] == NULL)
+                   {
+                     warn (_("Unrecognized debug option '%s'\n"), p);
+                     p = strchr (p, ',');
+                     if (p == NULL)
+                       break;
+                   }
+
+                 if (*p == ',')
+                   p++;
+               }
+           }
+         break;
 #ifdef SUPPORT_DISASSEMBLY
        case 'i':
          do_dump ++;
@@ -2578,7 +2811,7 @@ get_32bit_program_headers (file, program_headers)
 {
   Elf32_External_Phdr * phdrs;
   Elf32_External_Phdr * external;
-  Elf32_Internal_Phdr * internal;
+  Elf_Internal_Phdr *   internal;
   unsigned int          i;
 
   phdrs = ((Elf32_External_Phdr *)
@@ -2614,7 +2847,7 @@ get_64bit_program_headers (file, program_headers)
 {
   Elf64_External_Phdr * phdrs;
   Elf64_External_Phdr * external;
-  Elf64_Internal_Phdr * internal;
+  Elf_Internal_Phdr *   internal;
   unsigned int          i;
 
   phdrs = ((Elf64_External_Phdr *)
@@ -2643,6 +2876,8 @@ get_64bit_program_headers (file, program_headers)
   return 1;
 }
 
+/* Returns 1 if the program headers were loaded.  */
+
 static int
 process_program_headers (file)
      FILE * file;
@@ -2655,7 +2890,7 @@ process_program_headers (file)
     {
       if (do_segments)
        printf (_("\nThere are no program headers in this file.\n"));
-      return 1;
+      return 0;
     }
 
   if (do_segments && !do_header)
@@ -2691,8 +2926,10 @@ process_program_headers (file)
 
   if (do_segments)
     {
-      printf
-       (_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : "");
+      if (elf_header.e_phnum > 1)
+       printf (_("\nProgram Headers:\n"));
+      else
+       printf (_("\nProgram Headers:\n"));
 
       if (is_32bit_elf)
        printf
@@ -2884,7 +3121,7 @@ get_32bit_section_headers (file, num)
      unsigned int num;
 {
   Elf32_External_Shdr * shdrs;
-  Elf32_Internal_Shdr * internal;
+  Elf_Internal_Shdr *   internal;
   unsigned int          i;
 
   shdrs = ((Elf32_External_Shdr *)
@@ -2930,7 +3167,7 @@ get_64bit_section_headers (file, num)
      unsigned int num;
 {
   Elf64_External_Shdr * shdrs;
-  Elf64_Internal_Shdr * internal;
+  Elf_Internal_Shdr *   internal;
   unsigned int          i;
 
   shdrs = ((Elf64_External_Shdr *)
@@ -3130,6 +3367,7 @@ get_elf_section_flags (sh_flags)
        case SHF_LINK_ORDER:       strcat (buff, "L"); break;
        case SHF_OS_NONCONFORMING: strcat (buff, "O"); break;
        case SHF_GROUP:            strcat (buff, "G"); break;
+       case SHF_TLS:              strcat (buff, "T"); break;
 
        default:
          if (flag & SHF_MASKOS)
@@ -3196,6 +3434,7 @@ process_section_headers (file)
   dynamic_symbols = NULL;
   dynamic_strings = NULL;
   dynamic_syminfo = NULL;
+  symtab_shndx_hdr = NULL;
 
   for (i = 0, section = section_headers;
        i < elf_header.e_shnum;
@@ -3238,7 +3477,8 @@ 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_str)
+               || do_debug_frames || do_debug_macinfo || do_debug_str
+               || do_debug_loc)
               && strncmp (name, ".debug_", 7) == 0)
        {
          name += 7;
@@ -3252,6 +3492,7 @@ process_section_headers (file)
              || (do_debug_frames   && (strcmp (name, "frame") == 0))
              || (do_debug_macinfo  && (strcmp (name, "macinfo") == 0))
              || (do_debug_str      && (strcmp (name, "str") == 0))
+             || (do_debug_loc      && (strcmp (name, "loc") == 0))
              )
            request_dump (i, DEBUG_DUMP);
        }
@@ -3266,7 +3507,10 @@ process_section_headers (file)
   if (! do_sections)
     return 1;
 
-  printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : "");
+  if (elf_header.e_shnum > 1)
+    printf (_("\nSection Headers:\n"));
+  else
+    printf (_("\nSection Header:\n"));
 
   if (is_32bit_elf)
     printf
@@ -3351,13 +3595,13 @@ process_section_headers (file)
        {
          putchar (' ');
          print_vma (section->sh_addr, LONG_HEX);
-         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);
-           }
+         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 ("  ");
@@ -3444,7 +3688,7 @@ process_relocs (file)
     }
   else
     {
-      Elf32_Internal_Shdr *     section;
+      Elf_Internal_Shdr *      section;
       unsigned long            i;
       int              found = 0;
 
@@ -3461,18 +3705,18 @@ process_relocs (file)
 
          if (rel_size)
            {
-             Elf32_Internal_Shdr * strsec;
-             Elf_Internal_Sym *    symtab;
-             char *                strtab;
-             int                   is_rela;
-             unsigned long         nsyms;
+             Elf_Internal_Shdr * strsec;
+             Elf_Internal_Sym *  symtab;
+             char *              strtab;
+             int                 is_rela;
+             unsigned long       nsyms;
 
              printf (_("\nRelocation section "));
 
              if (string_table == NULL)
                printf ("%d", section->sh_name);
              else
-               printf ("'%s'", SECTION_NAME (section));
+               printf (_("'%s'"), SECTION_NAME (section));
 
              printf (_(" at offset 0x%lx contains %lu entries:\n"),
                 rel_offset, (unsigned long) (rel_size / section->sh_entsize));
@@ -3482,7 +3726,7 @@ process_relocs (file)
              nsyms = 0;
              if (section->sh_link)
                {
-                 Elf32_Internal_Shdr * symsec;
+                 Elf_Internal_Shdr * symsec;
 
                  symsec = SECTION_HEADER (section->sh_link);
                  nsyms = symsec->sh_size / symsec->sh_entsize;
@@ -3555,7 +3799,7 @@ static void find_symbol_for_address PARAMS ((struct unw_aux_info *,
                                             bfd_vma *));
 static void dump_ia64_unwind PARAMS ((struct unw_aux_info *));
 static int  slurp_ia64_unwind_table PARAMS ((FILE *, struct unw_aux_info *,
-                                           Elf32_Internal_Shdr *));
+                                           Elf_Internal_Shdr *));
 
 static void
 find_symbol_for_address (aux, addr, symname, offset)
@@ -3627,13 +3871,13 @@ dump_ia64_unwind (aux)
       print_vma (tp->start.offset, PREFIX_HEX);
       fputc ('-', stdout);
       print_vma (tp->end.offset, PREFIX_HEX);
-      printf ("), info at +0x%lx\n",
+      printf ("], info at +0x%lx\n",
              (unsigned long) (tp->info.offset - aux->seg_base));
 
       head = aux->info + (tp->info.offset - aux->info_addr);
       stamp = BYTE_GET8 ((unsigned char *) head);
 
-      printf ("  v%u, flags=0x%lx (%s%s ), len=%lu bytes\n",
+      printf ("  v%u, flags=0x%lx (%s%s), len=%lu bytes\n",
              (unsigned) UNW_VER (stamp),
              (unsigned long) ((stamp & UNW_FLAG_MASK) >> 32),
              UNW_FLAG_EHANDLER (stamp) ? " ehandler" : "",
@@ -3656,12 +3900,12 @@ static int
 slurp_ia64_unwind_table (file, aux, sec)
      FILE *file;
      struct unw_aux_info *aux;
-     Elf32_Internal_Shdr *sec;
+     Elf_Internal_Shdr *sec;
 {
   unsigned long size, addr_size, nrelas, i;
   Elf_Internal_Phdr *prog_hdrs, *seg;
   struct unw_table_entry *tep;
-  Elf32_Internal_Shdr *relsec;
+  Elf_Internal_Shdr *relsec;
   Elf_Internal_Rela *rela, *rp;
   unsigned char *table, *tp;
   Elf_Internal_Sym *sym;
@@ -3815,7 +4059,7 @@ static int
 process_unwind (file)
      FILE * file;
 {
-  Elf32_Internal_Shdr *sec, *unwsec = NULL, *strsec;
+  Elf_Internal_Shdr *sec, *unwsec = NULL, *strsec;
   unsigned long i, addr_size, unwcount = 0, unwstart = 0;
   struct unw_aux_info aux;
 
@@ -3905,7 +4149,7 @@ process_unwind (file)
          if (string_table == NULL)
            printf ("%d", unwsec->sh_name);
          else
-           printf ("'%s'", SECTION_NAME (unwsec));
+           printf (_("'%s'"), SECTION_NAME (unwsec));
        }
       else
        {
@@ -3919,7 +4163,7 @@ process_unwind (file)
          if (string_table == NULL)
            printf ("%d", unwsec->sh_name);
          else
-           printf ("'%s'", SECTION_NAME (unwsec));
+           printf (_("'%s'"), SECTION_NAME (unwsec));
 
          printf (_(" at offset 0x%lx contains %lu entries:\n"),
                  (unsigned long) unwsec->sh_offset,
@@ -4076,6 +4320,7 @@ dynamic_segment_parisc_val (entry)
       print_vma (entry->d_un.d_ptr, PREFIX_HEX);
       break;
     }
+  putchar ('\n');
 }
 
 static int
@@ -4168,7 +4413,10 @@ static const char *
 get_dynamic_flags (flags)
      bfd_vma flags;
 {
-  static char buff [64];
+  static char buff [128];
+  char *p = buff;
+
+  *p = '\0';
   while (flags)
     {
       bfd_vma flag;
@@ -4176,14 +4424,20 @@ get_dynamic_flags (flags)
       flag = flags & - flags;
       flags &= ~ flag;
 
+      if (p != buff)
+       *p++ = ' ';
+
       switch (flag)
        {
-       case DF_ORIGIN:   strcat (buff, "ORIGIN "); break;
-       case DF_SYMBOLIC: strcat (buff, "SYMBOLIC "); break;
-       case DF_TEXTREL:  strcat (buff, "TEXTREL "); break;
-       case DF_BIND_NOW: strcat (buff, "BIND_NOW "); break;
-       default:          strcat (buff, "unknown "); break;
+       case DF_ORIGIN:   strcpy (p, "ORIGIN"); break;
+       case DF_SYMBOLIC: strcpy (p, "SYMBOLIC"); break;
+       case DF_TEXTREL:  strcpy (p, "TEXTREL"); break;
+       case DF_BIND_NOW: strcpy (p, "BIND_NOW"); break;
+       case DF_STATIC_TLS: strcpy (p, "STATIC_TLS"); break;
+       default:          strcpy (p, "unknown"); break;
        }
+
+      p = strchr (p, '\0');
     }
   return buff;
 }
@@ -4219,7 +4473,7 @@ process_dynamic_segment (file)
           i < dynamic_size;
           ++i, ++ entry)
        {
-         Elf32_Internal_Shdr section;
+         Elf_Internal_Shdr section;
 
          if (entry->d_tag != DT_SYMTAB)
            continue;
@@ -4369,7 +4623,7 @@ process_dynamic_segment (file)
        {
        case DT_FLAGS:
          if (do_dynamic)
-           printf ("%s", get_dynamic_flags (entry->d_un.d_val));
+           puts (get_dynamic_flags (entry->d_un.d_val));
          break;
 
        case DT_AUXILIARY:
@@ -4417,11 +4671,13 @@ process_dynamic_segment (file)
          if (do_dynamic)
            {
              printf (_("Flags:"));
+
              if (entry->d_un.d_val == 0)
                printf (_(" None\n"));
              else
                {
                  unsigned long int val = entry->d_un.d_val;
+
                  if (val & DTF_1_PARINIT)
                    {
                      printf (" PARINIT");
@@ -4443,11 +4699,13 @@ process_dynamic_segment (file)
          if (do_dynamic)
            {
              printf (_("Flags:"));
+
              if (entry->d_un.d_val == 0)
                printf (_(" None\n"));
              else
                {
                  unsigned long int val = entry->d_un.d_val;
+
                  if (val & DF_P1_LAZYLOAD)
                    {
                      printf (" LAZYLOAD");
@@ -4474,6 +4732,7 @@ process_dynamic_segment (file)
              else
                {
                  unsigned long int val = entry->d_un.d_val;
+
                  if (val & DF_1_NOW)
                    {
                      printf (" NOW");
@@ -4631,6 +4890,8 @@ process_dynamic_segment (file)
        case DT_MOVESZ  :
        case DT_INIT_ARRAYSZ:
        case DT_FINI_ARRAYSZ:
+       case DT_GNU_CONFLICTSZ:
+       case DT_GNU_LIBLISTSZ:
          if (do_dynamic)
            {
              print_vma (entry->d_un.d_val, UNSIGNED);
@@ -4677,6 +4938,22 @@ process_dynamic_segment (file)
 
        case DT_BIND_NOW:
          /* The value of this entry is ignored.  */
+         if (do_dynamic)
+           putchar ('\n');
+         break;
+
+       case DT_GNU_PRELINKED:
+         if (do_dynamic)
+           {
+             struct tm * tmp;
+             time_t time = entry->d_un.d_val;
+
+             tmp = gmtime (&time);
+             printf ("%04u-%02u-%02uT%02u:%02u:%02u\n",
+                     tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
+                     tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+
+           }
          break;
 
        default:
@@ -4740,7 +5017,7 @@ static int
 process_version_sections (file)
      FILE * file;
 {
-  Elf32_Internal_Shdr * section;
+  Elf_Internal_Shdr * section;
   unsigned   i;
   int        found = 0;
 
@@ -4933,14 +5210,14 @@ process_version_sections (file)
 
        case SHT_GNU_versym:
          {
-           Elf32_Internal_Shdr *       link_section;
+           Elf_Internal_Shdr *         link_section;
            int                         total;
            int                         cnt;
            unsigned char *             edata;
            unsigned short *            data;
            char *                      strtab;
            Elf_Internal_Sym *          symbols;
-           Elf32_Internal_Shdr *       string_sec;
+           Elf_Internal_Shdr *         string_sec;
 
            link_section = SECTION_HEADER (section->sh_link);
            total = section->sh_size / section->sh_entsize;
@@ -5178,6 +5455,7 @@ get_symbol_type (type)
     case STT_SECTION:  return "SECTION";
     case STT_FILE:     return "FILE";
     case STT_COMMON:   return "COMMON";
+    case STT_TLS:      return "TLS";
     default:
       if (type >= STT_LOPROC && type <= STT_HIPROC)
        {
@@ -5228,6 +5506,8 @@ static const char *
 get_symbol_index_type (type)
      unsigned int type;
 {
+  static char buff [32];
+
   switch (type)
     {
     case SHN_UNDEF:  return "UND";
@@ -5235,19 +5515,17 @@ get_symbol_index_type (type)
     case SHN_COMMON: return "COM";
     default:
       if (type >= SHN_LOPROC && type <= SHN_HIPROC)
-       return "PRC";
+       sprintf (buff, "PRC[0x%04x]", type);
       else if (type >= SHN_LOOS && type <= SHN_HIOS)
-       return "OS ";
+       sprintf (buff, "OS [0x%04x]", type);
       else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
-       return "RSV";
+       sprintf (buff, "RSV[0x%04x]", type);
       else
-       {
-         static char buff [32];
-
-         sprintf (buff, "%3d", type);
-         return buff;
-       }
+       sprintf (buff, "%3d", type);
+      break;
     }
+
+  return buff;
 }
 
 static int *
@@ -5294,7 +5572,7 @@ static int
 process_symbol_table (file)
      FILE * file;
 {
-  Elf32_Internal_Shdr *   section;
+  Elf_Internal_Shdr * section;
   unsigned char   nb [4];
   unsigned char   nc [4];
   int    nbuckets = 0;
@@ -5407,7 +5685,7 @@ process_symbol_table (file)
            strtab = string_table;
          else
            {
-             Elf32_Internal_Shdr * string_sec;
+             Elf_Internal_Shdr * string_sec;
 
              string_sec = SECTION_HEADER (section->sh_link);
 
@@ -5709,7 +5987,7 @@ process_syminfo (file)
 #ifdef SUPPORT_DISASSEMBLY
 static void
 disassemble_section (section, file)
-     Elf32_Internal_Shdr * section;
+     Elf_Internal_Shdr * section;
      FILE * file;
 {
   printf (_("\nAssembly dump of section %s\n"),
@@ -5723,7 +6001,7 @@ disassemble_section (section, file)
 
 static int
 dump_section (section, file)
-     Elf32_Internal_Shdr * section;
+     Elf_Internal_Shdr * section;
      FILE * file;
 {
   bfd_size_type   bytes;
@@ -5946,7 +6224,7 @@ static int debug_line_pointer_size = 4;
 
 static int
 display_debug_lines (section, start, file)
-     Elf32_Internal_Shdr * section;
+     Elf_Internal_Shdr *   section;
      unsigned char *       start;
      FILE *                file ATTRIBUTE_UNUSED;
 {
@@ -6095,12 +6373,12 @@ display_debug_lines (section, start, file)
              state_machine_regs.line += adv;
              printf (_(" and Line by %d to %d\n"),
                      adv, state_machine_regs.line);
-           } 
-         else switch (op_code) 
+           }
+         else switch (op_code)
            {
            case DW_LNS_extended_op:
              data += process_extended_line_op (data, info.li_default_is_stmt,
-                                                debug_line_pointer_size);
+                                               debug_line_pointer_size);
              break;
 
            case DW_LNS_copy:
@@ -6169,17 +6447,17 @@ display_debug_lines (section, start, file)
            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:
              printf (_("  Unknown opcode %d with operands: "), op_code);
              {
@@ -6203,7 +6481,7 @@ display_debug_lines (section, start, file)
 
 static int
 display_debug_pubnames (section, start, file)
-     Elf32_Internal_Shdr * section;
+     Elf_Internal_Shdr *   section;
      unsigned char *       start;
      FILE *                file ATTRIBUTE_UNUSED;
 {
@@ -6455,6 +6733,7 @@ get_AT_name (attribute)
     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_GNU_vector:           return "DW_AT_GNU_vector";
     default:
       {
        static char buffer [100];
@@ -6665,7 +6944,7 @@ process_abbrev_section (start, end)
 
 static int
 display_debug_macinfo (section, start, file)
-     Elf32_Internal_Shdr * section;
+     Elf_Internal_Shdr *   section;
      unsigned char *       start;
      FILE *                file ATTRIBUTE_UNUSED;
 {
@@ -6739,7 +7018,7 @@ display_debug_macinfo (section, start, file)
 
 static int
 display_debug_abbrev (section, start, file)
-     Elf32_Internal_Shdr * section;
+     Elf_Internal_Shdr *   section;
      unsigned char *       start;
      FILE *                file ATTRIBUTE_UNUSED;
 {
@@ -7093,7 +7372,7 @@ decode_location_expression (data, pointer_size, length)
          printf ("DW_OP_nop");
          break;
 
-         /* DWARF 2.1 extensions.  */
+         /* DWARF 3 extensions.  */
        case DW_OP_push_object_address:
          printf ("DW_OP_push_object_address");
          break;
@@ -7105,8 +7384,13 @@ decode_location_expression (data, pointer_size, length)
          printf ("DW_OP_call4: <%lx>", (long) byte_get (data, 4));
          data += 4;
          break;
-       case DW_OP_calli:
-         printf ("DW_OP_calli");
+       case DW_OP_call_ref:
+         printf ("DW_OP_call_ref");
+         break;
+
+         /* GNU extensions.  */
+       case DW_OP_GNU_push_tls_address:
+         printf ("DW_OP_GNU_push_tls_address");
          break;
 
        default:
@@ -7124,6 +7408,115 @@ decode_location_expression (data, pointer_size, length)
     }
 }
 
+static const char * debug_loc_contents;
+static bfd_vma      debug_loc_size;
+
+static void
+load_debug_loc (file)
+     FILE * file;
+{
+  Elf_Internal_Shdr * sec;
+  unsigned int        i;
+
+  /* If it is already loaded, do nothing.  */
+  if (debug_loc_contents != NULL)
+    return;
+
+  /* Locate the .debug_loc section.  */
+  for (i = 0, sec = section_headers;
+       i < elf_header.e_shnum;
+       i ++, sec ++)
+    if (strcmp (SECTION_NAME (sec), ".debug_loc") == 0)
+      break;
+
+  if (i == elf_header.e_shnum || sec->sh_size == 0)
+    return;
+
+  debug_loc_size = sec->sh_size;
+
+  debug_loc_contents = ((char *)
+                       get_data (NULL, file, sec->sh_offset, sec->sh_size,
+                                 _("debug_loc section data")));
+}
+
+static void
+free_debug_loc ()
+{
+  if (debug_loc_contents == NULL)
+    return;
+
+  free ((char *) debug_loc_contents);
+  debug_loc_contents = NULL;
+  debug_loc_size = 0;
+}
+
+
+static int
+display_debug_loc (section, start, file)
+     Elf_Internal_Shdr * section;
+     unsigned char * start;
+     FILE * file ATTRIBUTE_UNUSED;
+{
+  unsigned char *section_end;
+  unsigned long bytes;
+  unsigned char *section_begin = start;
+  bfd_vma addr;
+
+  addr = section->sh_addr;
+  bytes = section->sh_size;
+  section_end = start + bytes;
+
+  if (bytes == 0)
+    {
+      printf (_("\nThe .debug_loc section is empty.\n"));
+      return 0;
+    }
+
+  printf (_("Contents of the .debug_loc section:\n\n"));
+  printf (_("\n    Offset   Begin    End      Expression\n"));
+
+  while (start < section_end)
+    {
+      unsigned long begin;
+      unsigned long end;
+      unsigned short length;
+      unsigned long offset;
+
+      offset = start - section_begin;
+
+      while (1)
+       {
+         /* Normally, the lists in  the debug_loc section are related to a
+            given compilation unit, and thus, we would use the
+            pointer size of that compilation unit.  However, since we are
+            displaying it seperately here, we either have to store
+            pointer sizes of all compilation units, or assume they don't
+            change.   We assume, like the debug_line display, that
+            it doesn't change.  */
+         begin = byte_get (start, debug_line_pointer_size);
+         start += debug_line_pointer_size;
+         end = byte_get (start, debug_line_pointer_size);
+         start += debug_line_pointer_size;
+
+         if (begin == 0 && end == 0)
+           break;
+
+         begin += addr;
+         end += addr;
+
+         length = byte_get (start, 2);
+         start += 2;
+
+         printf ("    %8.8lx %8.8lx %8.8lx (", offset, begin, end);
+         decode_location_expression (start, debug_line_pointer_size, length);
+         printf (")\n");
+
+         start += length;
+       }
+      printf ("\n");
+    }
+  return 1;
+}
 
 static const char * debug_str_contents;
 static bfd_vma      debug_str_size;
@@ -7132,8 +7525,8 @@ static void
 load_debug_str (file)
      FILE * file;
 {
-  Elf32_Internal_Shdr * sec;
-  unsigned int          i;
+  Elf_Internal_Shdr * sec;
+  unsigned int        i;
 
   /* If it is already loaded, do nothing.  */
   if (debug_str_contents != NULL)
@@ -7180,10 +7573,9 @@ fetch_indirect_string (offset)
   return debug_str_contents + offset;
 }
 
-
 static int
 display_debug_str (section, start, file)
-     Elf32_Internal_Shdr * section;
+     Elf_Internal_Shdr * section;
      unsigned char *       start;
      FILE *                file ATTRIBUTE_UNUSED;
 {
@@ -7241,7 +7633,6 @@ display_debug_str (section, start, file)
   return 1;
 }
 
-
 static unsigned char *
 read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
      unsigned long   attribute;
@@ -7304,7 +7695,7 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
       data += bytes_read;
       printf (" %s", get_FORM_name (form));
       return read_and_display_attr_value (attribute, form, data, cu_offset,
-                                          pointer_size);
+                                         pointer_size);
     }
 
   switch (form)
@@ -7370,8 +7761,8 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
       break;
 
     case DW_FORM_strp:
-      printf (_(" (indirect string, offset: 0x%lx): "), uvalue);
-      printf (fetch_indirect_string (uvalue));
+      printf (_(" (indirect string, offset: 0x%lx): %s"),
+             uvalue, fetch_indirect_string (uvalue));
       break;
 
     case DW_FORM_indirect:
@@ -7379,7 +7770,7 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
       break;
 
     default:
-      warn (_("Unrecognised form: %d\n"), form);
+      warn (_("Unrecognized form: %d\n"), form);
       break;
     }
 
@@ -7528,6 +7919,12 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
          decode_location_expression (block_start, pointer_size, uvalue);
          printf (")");
        }
+      else if (form == DW_FORM_data4)
+       {
+         printf ("(");
+         printf ("location list");
+         printf (")");
+       }
       break;
 
     default:
@@ -7547,14 +7944,14 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size)
 {
   printf ("     %-18s:", get_AT_name (attribute));
   data = read_and_display_attr_value (attribute, form, data, cu_offset,
-                                      pointer_size);
+                                     pointer_size);
   printf ("\n");
   return data;
 }
 
 static int
 display_debug_info (section, start, file)
-     Elf32_Internal_Shdr * section;
+     Elf_Internal_Shdr *   section;
      unsigned char *       start;
      FILE *                file;
 {
@@ -7564,12 +7961,13 @@ display_debug_info (section, start, file)
   printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
 
   load_debug_str (file);
+  load_debug_loc (file);
 
   while (start < end)
     {
       DWARF2_External_CompUnit * external;
       DWARF2_Internal_CompUnit   compunit;
-      Elf32_Internal_Shdr *      relsec;
+      Elf_Internal_Shdr *        relsec;
       unsigned char *            tags;
       unsigned int               i;
       int                       level;
@@ -7588,20 +7986,21 @@ display_debug_info (section, start, file)
          break;
        }
 
-      /* Check for RELA relocations in the abbrev_offset address, and
-         apply them.  */
+      /* 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;
          Elf_Internal_Rela *rela, *rp;
-         Elf32_Internal_Shdr *symsec;
+         Elf_Internal_Shdr *symsec;
          Elf_Internal_Sym *symtab;
          Elf_Internal_Sym *sym;
 
          if (relsec->sh_type != SHT_RELA
-             || SECTION_HEADER (relsec->sh_info) != section)
+             || SECTION_HEADER (relsec->sh_info) != section
+             || relsec->sh_size == 0)
            continue;
 
          if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
@@ -7622,7 +8021,8 @@ display_debug_info (section, start, file)
                {
                  sym = symtab + ELF32_R_SYM (rp->r_info);
 
-                 if (ELF32_ST_TYPE (sym->st_info) != STT_SECTION)
+                 if (ELF32_R_SYM (rp->r_info) != 0
+                     && ELF32_ST_TYPE (sym->st_info) != STT_SECTION)
                    {
                      warn (_("Skipping unexpected symbol type %u\n"),
                            ELF32_ST_TYPE (sym->st_info));
@@ -7633,7 +8033,8 @@ display_debug_info (section, start, file)
                {
                  sym = symtab + ELF64_R_SYM (rp->r_info);
 
-                 if (ELF64_ST_TYPE (sym->st_info) != STT_SECTION)
+                 if (ELF64_R_SYM (rp->r_info) != 0
+                     && ELF64_ST_TYPE (sym->st_info) != STT_SECTION)
                    {
                      warn (_("Skipping unexpected symbol type %u\n"),
                            ELF64_ST_TYPE (sym->st_info));
@@ -7641,7 +8042,7 @@ display_debug_info (section, start, file)
                    }
                }
 
-             compunit.cu_abbrev_offset += rp->r_addend;
+             compunit.cu_abbrev_offset = rp->r_addend;
              break;
            }
 
@@ -7668,10 +8069,9 @@ display_debug_info (section, start, file)
       free_abbrevs ();
 
       /* Read in the abbrevs used by this compilation unit.  */
-
       {
-       Elf32_Internal_Shdr * sec;
-       unsigned char *       begin;
+       Elf_Internal_Shdr * sec;
+       unsigned char *     begin;
 
        /* Locate the .debug_abbrev section and process it.  */
        for (i = 0, sec = section_headers;
@@ -7748,6 +8148,7 @@ display_debug_info (section, start, file)
     }
 
   free_debug_str ();
+  free_debug_loc ();
 
   printf ("\n");
 
@@ -7756,7 +8157,7 @@ display_debug_info (section, start, file)
 
 static int
 display_debug_aranges (section, start, file)
-     Elf32_Internal_Shdr * section;
+     Elf_Internal_Shdr *   section;
      unsigned char *       start;
      FILE *                file ATTRIBUTE_UNUSED;
 {
@@ -7967,7 +8368,7 @@ size_of_encoded_value (encoding)
 
 static int
 display_debug_frames (section, start, file)
-     Elf32_Internal_Shdr * section;
+     Elf_Internal_Shdr * section;
      unsigned char *       start;
      FILE *                file ATTRIBUTE_UNUSED;
 {
@@ -8000,7 +8401,11 @@ display_debug_frames (section, start, file)
       length = byte_get (start, 4); start += 4;
 
       if (length == 0)
-       return 1;
+       {
+         printf ("\n%08lx ZERO terminator\n\n",
+                   (unsigned long)(saved_start - section_start));
+         return 1;
+       }
 
       if (length == 0xffffffff)
        {
@@ -8154,6 +8559,8 @@ display_debug_frames (section, start, file)
            encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
 
          fc->pc_begin = byte_get (start, encoded_ptr_size);
+         if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
+           fc->pc_begin += section->sh_addr + (start - section_start);
          start += encoded_ptr_size;
          fc->pc_range = byte_get (start, encoded_ptr_size);
          start += encoded_ptr_size;
@@ -8184,102 +8591,107 @@ display_debug_frames (section, start, file)
         about to interpret instructions for the chunk.  */
 
       if (do_debug_frames_interp)
-      {
-       /* Start by making a pass over the chunk, allocating storage
-           and taking note of what registers are used.  */
-       unsigned char * tmp = start;
+       {
+         /* Start by making a pass over the chunk, allocating storage
+            and taking note of what registers are used.  */
+         unsigned char * tmp = start;
 
-       while (start < block_end)
-         {
-           unsigned op, opa;
-           unsigned long reg;
+         while (start < block_end)
+           {
+             unsigned op, opa;
+             unsigned long reg;
 
-           op = * start ++;
-           opa = op & 0x3f;
-           if (op & 0xc0)
-             op &= 0xc0;
+             op = * start ++;
+             opa = op & 0x3f;
+             if (op & 0xc0)
+               op &= 0xc0;
 
-           /* Warning: if you add any more cases to this switch, be
-              sure to add them to the corresponding switch below.  */
-           switch (op)
-             {
-             case DW_CFA_advance_loc:
-               break;
-             case DW_CFA_offset:
-               LEB ();
-               frame_need_space (fc, opa);
-               fc->col_type[opa] = DW_CFA_undefined;
-               break;
-             case DW_CFA_restore:
-               frame_need_space (fc, opa);
-               fc->col_type[opa] = DW_CFA_undefined;
-               break;
-             case DW_CFA_set_loc:
-               start += encoded_ptr_size;
-               break;
-             case DW_CFA_advance_loc1:
-               start += 1;
-               break;
-             case DW_CFA_advance_loc2:
-               start += 2;
-               break;
-             case DW_CFA_advance_loc4:
-               start += 4;
-               break;
-             case DW_CFA_offset_extended:
-               reg = LEB (); LEB ();
-               frame_need_space (fc, reg);
-               fc->col_type[reg] = DW_CFA_undefined;
-               break;
-             case DW_CFA_restore_extended:
-               reg = LEB ();
-               frame_need_space (fc, reg);
-               fc->col_type[reg] = DW_CFA_undefined;
-               break;
-             case DW_CFA_undefined:
-               reg = LEB ();
-               frame_need_space (fc, reg);
-               fc->col_type[reg] = DW_CFA_undefined;
-               break;
-             case DW_CFA_same_value:
-               reg = LEB ();
-               frame_need_space (fc, reg);
-               fc->col_type[reg] = DW_CFA_undefined;
-               break;
-             case DW_CFA_register:
-               reg = LEB (); LEB ();
-               frame_need_space (fc, reg);
-               fc->col_type[reg] = DW_CFA_undefined;
-               break;
-             case DW_CFA_def_cfa:
-               LEB (); LEB ();
-               break;
-             case DW_CFA_def_cfa_register:
-               LEB ();
-               break;
-             case DW_CFA_def_cfa_offset:
-               LEB ();
-               break;
-#ifndef DW_CFA_GNU_args_size
-#define DW_CFA_GNU_args_size 0x2e
-#endif
-             case DW_CFA_GNU_args_size:
-               LEB ();
-               break;
-#ifndef DW_CFA_GNU_negative_offset_extended
-#define DW_CFA_GNU_negative_offset_extended 0x2f
-#endif
-             case DW_CFA_GNU_negative_offset_extended:
-               reg = LEB (); LEB ();
-               frame_need_space (fc, reg);
-               fc->col_type[reg] = DW_CFA_undefined;
+             /* Warning: if you add any more cases to this switch, be
+                sure to add them to the corresponding switch below.  */
+             switch (op)
+               {
+               case DW_CFA_advance_loc:
+                 break;
+               case DW_CFA_offset:
+                 LEB ();
+                 frame_need_space (fc, opa);
+                 fc->col_type[opa] = DW_CFA_undefined;
+                 break;
+               case DW_CFA_restore:
+                 frame_need_space (fc, opa);
+                 fc->col_type[opa] = DW_CFA_undefined;
+                 break;
+               case DW_CFA_set_loc:
+                 start += encoded_ptr_size;
+                 break;
+               case DW_CFA_advance_loc1:
+                 start += 1;
+                 break;
+               case DW_CFA_advance_loc2:
+                 start += 2;
+                 break;
+               case DW_CFA_advance_loc4:
+                 start += 4;
+                 break;
+               case DW_CFA_offset_extended:
+                 reg = LEB (); LEB ();
+                 frame_need_space (fc, reg);
+                 fc->col_type[reg] = DW_CFA_undefined;
+                 break;
+               case DW_CFA_restore_extended:
+                 reg = LEB ();
+                 frame_need_space (fc, reg);
+                 fc->col_type[reg] = DW_CFA_undefined;
+                 break;
+               case DW_CFA_undefined:
+                 reg = LEB ();
+                 frame_need_space (fc, reg);
+                 fc->col_type[reg] = DW_CFA_undefined;
+                 break;
+               case DW_CFA_same_value:
+                 reg = LEB ();
+                 frame_need_space (fc, reg);
+                 fc->col_type[reg] = DW_CFA_undefined;
+                 break;
+               case DW_CFA_register:
+                 reg = LEB (); LEB ();
+                 frame_need_space (fc, reg);
+                 fc->col_type[reg] = DW_CFA_undefined;
+                 break;
+               case DW_CFA_def_cfa:
+                 LEB (); LEB ();
+                 break;
+               case DW_CFA_def_cfa_register:
+                 LEB ();
+                 break;
+               case DW_CFA_def_cfa_offset:
+                 LEB ();
+                 break;
+               case DW_CFA_offset_extended_sf:
+                 reg = LEB (); SLEB ();
+                 frame_need_space (fc, reg);
+                 fc->col_type[reg] = DW_CFA_undefined;
+                 break;
+               case DW_CFA_def_cfa_sf:
+                 LEB (); SLEB ();
+                 break;
+               case DW_CFA_def_cfa_offset_sf:
+                 SLEB ();
+                 break;
+               case DW_CFA_GNU_args_size:
+                 LEB ();
+                 break;
+               case DW_CFA_GNU_negative_offset_extended:
+                 reg = LEB (); LEB ();
+                 frame_need_space (fc, reg);
+                 fc->col_type[reg] = DW_CFA_undefined;
 
-             default:
-               break;
-             }
-         }
-       start = tmp;
-      }
+               default:
+                 break;
+               }
+           }
+         start = tmp;
+       }
 
       /* Now we know what registers are used, make a second pass over
          the chunk, this time actually printing out the info.  */
@@ -8296,16 +8708,16 @@ display_debug_frames (section, start, file)
          if (op & 0xc0)
            op &= 0xc0;
 
-           /* Warning: if you add any more cases to this switch, be
-              sure to add them to the corresponding switch above.  */
+         /* Warning: if you add any more cases to this switch, be
+            sure to add them to the corresponding switch above.  */
          switch (op)
            {
            case DW_CFA_advance_loc:
              if (do_debug_frames_interp)
-               frame_display_row (fc, &need_col_headers, &max_regs);
+               frame_display_row (fc, &need_col_headers, &max_regs);
              else
-               printf ("  DW_CFA_advance_loc: %d to %08lx\n",
-                       opa * fc->code_factor,
+               printf ("  DW_CFA_advance_loc: %d to %08lx\n",
+                       opa * fc->code_factor,
                        fc->pc_begin + opa * fc->code_factor);
              fc->pc_begin += opa * fc->code_factor;
              break;
@@ -8313,7 +8725,7 @@ display_debug_frames (section, start, file)
            case DW_CFA_offset:
              roffs = LEB ();
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_offset: r%d at cfa%+ld\n",
+               printf ("  DW_CFA_offset: r%d at cfa%+ld\n",
                        opa, roffs * fc->data_factor);
              fc->col_type[opa] = DW_CFA_offset;
              fc->col_offset[opa] = roffs * fc->data_factor;
@@ -8321,28 +8733,30 @@ display_debug_frames (section, start, file)
 
            case DW_CFA_restore:
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_restore: r%d\n", opa);
+               printf ("  DW_CFA_restore: r%d\n", opa);
              fc->col_type[opa] = cie->col_type[opa];
              fc->col_offset[opa] = cie->col_offset[opa];
              break;
 
            case DW_CFA_set_loc:
              vma = byte_get (start, encoded_ptr_size);
+             if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
+               vma += section->sh_addr + (start - section_start);
              start += encoded_ptr_size;
              if (do_debug_frames_interp)
-               frame_display_row (fc, &need_col_headers, &max_regs);
+               frame_display_row (fc, &need_col_headers, &max_regs);
              else
-               printf ("  DW_CFA_set_loc: %08lx\n", (unsigned long)vma);
+               printf ("  DW_CFA_set_loc: %08lx\n", (unsigned long)vma);
              fc->pc_begin = vma;
              break;
 
            case DW_CFA_advance_loc1:
              ofs = byte_get (start, 1); start += 1;
              if (do_debug_frames_interp)
-               frame_display_row (fc, &need_col_headers, &max_regs);
+               frame_display_row (fc, &need_col_headers, &max_regs);
              else
-               printf ("  DW_CFA_advance_loc1: %ld to %08lx\n",
-                       ofs * fc->code_factor,
+               printf ("  DW_CFA_advance_loc1: %ld to %08lx\n",
+                       ofs * fc->code_factor,
                        fc->pc_begin + ofs * fc->code_factor);
              fc->pc_begin += ofs * fc->code_factor;
              break;
@@ -8350,10 +8764,10 @@ display_debug_frames (section, start, file)
            case DW_CFA_advance_loc2:
              ofs = byte_get (start, 2); start += 2;
              if (do_debug_frames_interp)
-               frame_display_row (fc, &need_col_headers, &max_regs);
+               frame_display_row (fc, &need_col_headers, &max_regs);
              else
-               printf ("  DW_CFA_advance_loc2: %ld to %08lx\n",
-                       ofs * fc->code_factor,
+               printf ("  DW_CFA_advance_loc2: %ld to %08lx\n",
+                       ofs * fc->code_factor,
                        fc->pc_begin + ofs * fc->code_factor);
              fc->pc_begin += ofs * fc->code_factor;
              break;
@@ -8361,10 +8775,10 @@ display_debug_frames (section, start, file)
            case DW_CFA_advance_loc4:
              ofs = byte_get (start, 4); start += 4;
              if (do_debug_frames_interp)
-               frame_display_row (fc, &need_col_headers, &max_regs);
+               frame_display_row (fc, &need_col_headers, &max_regs);
              else
-               printf ("  DW_CFA_advance_loc4: %ld to %08lx\n",
-                       ofs * fc->code_factor,
+               printf ("  DW_CFA_advance_loc4: %ld to %08lx\n",
+                       ofs * fc->code_factor,
                        fc->pc_begin + ofs * fc->code_factor);
              fc->pc_begin += ofs * fc->code_factor;
              break;
@@ -8382,7 +8796,7 @@ display_debug_frames (section, start, file)
            case DW_CFA_restore_extended:
              reg = LEB ();
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_restore_extended: r%ld\n", reg);
+               printf ("  DW_CFA_restore_extended: r%ld\n", reg);
              fc->col_type[reg] = cie->col_type[reg];
              fc->col_offset[reg] = cie->col_offset[reg];
              break;
@@ -8390,7 +8804,7 @@ display_debug_frames (section, start, file)
            case DW_CFA_undefined:
              reg = LEB ();
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_undefined: r%ld\n", reg);
+               printf ("  DW_CFA_undefined: r%ld\n", reg);
              fc->col_type[reg] = DW_CFA_undefined;
              fc->col_offset[reg] = 0;
              break;
@@ -8398,7 +8812,7 @@ display_debug_frames (section, start, file)
            case DW_CFA_same_value:
              reg = LEB ();
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_same_value: r%ld\n", reg);
+               printf ("  DW_CFA_same_value: r%ld\n", reg);
              fc->col_type[reg] = DW_CFA_same_value;
              fc->col_offset[reg] = 0;
              break;
@@ -8407,14 +8821,14 @@ display_debug_frames (section, start, file)
              reg = LEB ();
              roffs = LEB ();
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_register: r%ld\n", reg);
+               printf ("  DW_CFA_register: r%ld\n", reg);
              fc->col_type[reg] = DW_CFA_register;
              fc->col_offset[reg] = roffs;
              break;
 
            case DW_CFA_remember_state:
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_remember_state\n");
+               printf ("  DW_CFA_remember_state\n");
              rs = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
              rs->ncols = fc->ncols;
              rs->col_type = (short int *) xmalloc (rs->ncols * sizeof (short int));
@@ -8427,7 +8841,7 @@ display_debug_frames (section, start, file)
 
            case DW_CFA_restore_state:
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_restore_state\n");
+               printf ("  DW_CFA_restore_state\n");
              rs = remembered_state;
              remembered_state = rs->next;
              frame_need_space (fc, rs->ncols-1);
@@ -8442,39 +8856,61 @@ display_debug_frames (section, start, file)
              fc->cfa_reg = LEB ();
              fc->cfa_offset = LEB ();
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_def_cfa: r%d ofs %d\n",
+               printf ("  DW_CFA_def_cfa: r%d ofs %d\n",
                        fc->cfa_reg, fc->cfa_offset);
              break;
 
            case DW_CFA_def_cfa_register:
              fc->cfa_reg = LEB ();
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_def_cfa_reg: r%d\n", fc->cfa_reg);
+               printf ("  DW_CFA_def_cfa_reg: r%d\n", fc->cfa_reg);
              break;
 
            case DW_CFA_def_cfa_offset:
              fc->cfa_offset = LEB ();
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_def_cfa_offset: %d\n", fc->cfa_offset);
+               printf ("  DW_CFA_def_cfa_offset: %d\n", fc->cfa_offset);
              break;
 
            case DW_CFA_nop:
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_nop\n");
+               printf ("  DW_CFA_nop\n");
+             break;
+
+           case DW_CFA_offset_extended_sf:
+             reg = LEB ();
+             l = SLEB ();
+             frame_need_space (fc, reg);
+             if (! do_debug_frames_interp)
+               printf ("  DW_CFA_offset_extended_sf: r%ld at cfa%+ld\n",
+                       reg, l * fc->data_factor);
+             fc->col_type[reg] = DW_CFA_offset;
+             fc->col_offset[reg] = l * fc->data_factor;
+             break;
+
+           case DW_CFA_def_cfa_sf:
+             fc->cfa_reg = LEB ();
+             fc->cfa_offset = SLEB ();
+             if (! do_debug_frames_interp)
+               printf ("  DW_CFA_def_cfa_sf: r%d ofs %d\n",
+                       fc->cfa_reg, fc->cfa_offset);
+             break;
+
+           case DW_CFA_def_cfa_offset_sf:
+             fc->cfa_offset = SLEB ();
+             if (! do_debug_frames_interp)
+               printf ("  DW_CFA_def_cfa_offset_sf: %d\n", fc->cfa_offset);
              break;
 
-#ifndef DW_CFA_GNU_window_save
-#define DW_CFA_GNU_window_save 0x2d
-#endif
            case DW_CFA_GNU_window_save:
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_GNU_window_save\n");
+               printf ("  DW_CFA_GNU_window_save\n");
              break;
 
            case DW_CFA_GNU_args_size:
              ul = LEB ();
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_GNU_args_size: %ld\n", ul);
+               printf ("  DW_CFA_GNU_args_size: %ld\n", ul);
              break;
 
            case DW_CFA_GNU_negative_offset_extended:
@@ -8482,12 +8918,23 @@ display_debug_frames (section, start, file)
              l = - LEB ();
              frame_need_space (fc, reg);
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_GNU_negative_offset_extended: r%ld at cfa%+ld\n",
+               printf ("  DW_CFA_GNU_negative_offset_extended: r%ld at cfa%+ld\n",
                        reg, l * fc->data_factor);
              fc->col_type[reg] = DW_CFA_offset;
              fc->col_offset[reg] = l * fc->data_factor;
              break;
 
+           /* FIXME: How do we handle these? */
+           case DW_CFA_def_cfa_expression:
+             fprintf (stderr, "unsupported DW_CFA_def_cfa_expression\n");
+             start = block_end;
+             break;
+
+           case DW_CFA_expression:
+             fprintf (stderr, "unsupported DW_CFA_expression\n");
+             start = block_end;
+             break;
+
            default:
              fprintf (stderr, "unsupported or unknown DW_CFA_%d\n", op);
              start = block_end;
@@ -8495,7 +8942,7 @@ display_debug_frames (section, start, file)
        }
 
       if (do_debug_frames_interp)
-        frame_display_row (fc, &need_col_headers, &max_regs);
+       frame_display_row (fc, &need_col_headers, &max_regs);
 
       start = block_end;
     }
@@ -8511,9 +8958,9 @@ display_debug_frames (section, start, file)
 
 static int
 display_debug_not_supported (section, start, file)
-     Elf32_Internal_Shdr * section;
-     unsigned char *       start ATTRIBUTE_UNUSED;
-     FILE *                file ATTRIBUTE_UNUSED;
+     Elf_Internal_Shdr * section;
+     unsigned char *     start ATTRIBUTE_UNUSED;
+     FILE *              file ATTRIBUTE_UNUSED;
 {
   printf (_("Displaying the debug contents of section %s is not yet supported.\n"),
            SECTION_NAME (section));
@@ -8526,9 +8973,9 @@ display_debug_not_supported (section, start, file)
    that all compilation units have the same address size.  */
 static int
 prescan_debug_info (section, start, file)
-     Elf32_Internal_Shdr * section ATTRIBUTE_UNUSED;
-     unsigned char *       start;
-     FILE *                file ATTRIBUTE_UNUSED;
+     Elf_Internal_Shdr * section ATTRIBUTE_UNUSED;
+     unsigned char *     start;
+     FILE *              file ATTRIBUTE_UNUSED;
 {
   DWARF2_External_CompUnit * external;
 
@@ -8545,8 +8992,8 @@ prescan_debug_info (section, start, file)
 struct
 {
   const char * const name;
-  int (* display) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
-  int (* prescan) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+  int (* display) PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
+  int (* prescan) PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
 }
 debug_displays[] =
 {
@@ -8559,7 +9006,7 @@ debug_displays[] =
   { ".eh_frame",          display_debug_frames, NULL },
   { ".debug_macinfo",     display_debug_macinfo, NULL },
   { ".debug_str",         display_debug_str, NULL },
-  
+  { ".debug_loc",         display_debug_loc, NULL },
   { ".debug_pubtypes",    display_debug_not_supported, NULL },
   { ".debug_ranges",      display_debug_not_supported, NULL },
   { ".debug_static_func", display_debug_not_supported, NULL },
@@ -8570,7 +9017,7 @@ debug_displays[] =
 
 static int
 display_debug_section (section, file)
-     Elf32_Internal_Shdr * section;
+     Elf_Internal_Shdr * section;
      FILE * file;
 {
   char *          name = SECTION_NAME (section);
@@ -8602,7 +9049,7 @@ display_debug_section (section, file)
       }
 
   if (i == -1)
-    printf (_("Unrecognised debug section: %s\n"), name);
+    printf (_("Unrecognized debug section: %s\n"), name);
 
   free (start);
 
@@ -8617,7 +9064,7 @@ static int
 process_section_contents (file)
      FILE * file;
 {
-  Elf32_Internal_Shdr * section;
+  Elf_Internal_Shdr * section;
   unsigned int i;
 
   if (! do_dump)
@@ -8634,11 +9081,11 @@ process_section_contents (file)
       int       j;
 
       if (section->sh_size == 0)
-        continue;
+       continue;
 
       /* See if there is some pre-scan operation for this section.  */
       for (j = NUM_ELEM (debug_displays); j--;)
-        if (strcmp (debug_displays[j].name, name) == 0)
+       if (strcmp (debug_displays[j].name, name) == 0)
          {
            if (debug_displays[j].prescan != NULL)
              {
@@ -8656,8 +9103,8 @@ process_section_contents (file)
                free (start);
              }
 
-            break;
-          }
+           break;
+         }
     }
 
   for (i = 0, section = section_headers;
@@ -9026,7 +9473,7 @@ process_mips_specific (file)
 
       if (dynamic_symbols == NULL)
        {
-         error (_("conflict list with without table"));
+         error (_("conflict list found without a dynamic symbol table"));
          return 0;
        }
 
@@ -9091,6 +9538,86 @@ process_mips_specific (file)
   return 1;
 }
 
+static int
+process_gnu_liblist (file)
+     FILE * file;
+{
+  Elf_Internal_Shdr * section, * string_sec;
+  Elf32_External_Lib * elib;
+  char * strtab;
+  size_t cnt;
+  unsigned i;
+
+  if (! do_arch)
+    return 0;
+
+  for (i = 0, section = section_headers;
+       i < elf_header.e_shnum;
+       i++, section ++)
+    {
+      switch (section->sh_type)
+       {
+       case SHT_GNU_LIBLIST:
+         elib = ((Elf32_External_Lib *)
+                get_data (NULL, file, section->sh_offset, section->sh_size,
+                          _("liblist")));
+
+         if (elib == NULL)
+           break;
+         string_sec = SECTION_HEADER (section->sh_link);
+
+         strtab = (char *) get_data (NULL, file, string_sec->sh_offset,
+                                     string_sec->sh_size,
+                                     _("liblist string table"));
+
+         if (strtab == NULL
+             || section->sh_entsize != sizeof (Elf32_External_Lib))
+           {
+             free (elib);
+             break;
+           }
+
+         printf (_("\nLibrary list section '%s' contains %lu entries:\n"),
+                 SECTION_NAME (section),
+                 (long) (section->sh_size / sizeof (Elf32_External_Lib)));
+
+         puts ("     Library              Time Stamp          Checksum   Version Flags");
+
+         for (cnt = 0; cnt < section->sh_size / sizeof (Elf32_External_Lib);
+              ++cnt)
+           {
+             Elf32_Lib liblist;
+             time_t time;
+             char timebuf[20];
+             struct tm * tmp;
+
+             liblist.l_name = BYTE_GET (elib[cnt].l_name);
+             time = BYTE_GET (elib[cnt].l_time_stamp);
+             liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum);
+             liblist.l_version = BYTE_GET (elib[cnt].l_version);
+             liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
+
+             tmp = gmtime (&time);
+             sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u",
+                      tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
+                      tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+
+             printf ("%3lu: ", (unsigned long) cnt);
+             if (do_wide)
+               printf ("%-20s", strtab + liblist.l_name);
+             else
+               printf ("%-20.20s", strtab + liblist.l_name);
+             printf (" %s %#010lx %-7ld %-7ld\n", timebuf, liblist.l_checksum,
+                     liblist.l_version, liblist.l_flags);
+           }
+
+         free (elib);
+       }
+    }
+
+  return 1;
+}
+
 static const char *
 get_note_type (e_type)
      unsigned e_type;
@@ -9109,7 +9636,7 @@ get_note_type (e_type)
     case NT_PSINFO:    return _("NT_PSINFO (psinfo structure)");
     case NT_LWPSTATUS: return _("NT_LWPSTATUS (lwpstatus_t structure)");
     case NT_LWPSINFO:  return _("NT_LWPSINFO (lwpsinfo_t structure)");
-    case NT_WIN32PSTATUS: return _("NT_WIN32PSTATUS (win32_pstatus strcuture)");
+    case NT_WIN32PSTATUS: return _("NT_WIN32PSTATUS (win32_pstatus structure)");
     default:
       sprintf (buff, _("Unknown note type: (0x%08x)"), e_type);
       return buff;
@@ -9185,7 +9712,7 @@ get_netbsd_elfcore_note_type (e_type)
    If the value of namesz is zero, there is no name present.  */
 static int
 process_note (pnote)
-  Elf32_Internal_Note * pnote;
+     Elf_Internal_Note * pnote;
 {
   const char *nt;
 
@@ -9240,7 +9767,8 @@ process_corefile_note_segment (file, offset, length)
 
   while (external < (Elf_External_Note *)((char *) pnotes + length))
     {
-      Elf32_Internal_Note inote;
+      Elf_External_Note * next;
+      Elf_Internal_Note   inote;
       char * temp = NULL;
 
       inote.type     = BYTE_GET (external->type);
@@ -9250,7 +9778,18 @@ process_corefile_note_segment (file, offset, length)
       inote.descdata = inote.namedata + align_power (inote.namesz, 2);
       inote.descpos  = offset + (inote.descdata - (char *) pnotes);
 
-      external = (Elf_External_Note *)(inote.descdata + align_power (inote.descsz, 2));
+      next = (Elf_External_Note *)(inote.descdata + align_power (inote.descsz, 2));
+
+      if (((char *) next) > (((char *) pnotes) + length))
+       {
+         warn (_("corrupt note found at offset %x into core notes\n"),
+               ((char *) external) - ((char *) pnotes));
+         warn (_(" type: %x, namesize: %08lx, descsize: %08lx\n"),
+               inote.type, inote.namesz, inote.descsz);
+         break;
+       }
+
+      external = next;
 
       /* Verify that name is null terminated.  It appears that at least
         one version of Linux (RedHat 6.0) generates corefiles that don't
@@ -9448,12 +9987,15 @@ 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);
+  if (elf_header.e_shoff)
+    {
+      /* 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;
 }
@@ -9503,11 +10045,18 @@ process_file (file_name)
       return 1;
     }
 
-  process_section_headers (file);
+  if (! process_section_headers (file))
+    {
+      /* Without loaded section headers we
+        cannot process lots of things.  */
+      do_unwind = do_version = do_dump = do_arch = 0;
 
-  process_program_headers (file);
+      if (! do_using_dynamic)
+       do_syms = do_reloc = 0;
+    }
 
-  process_dynamic_segment (file);
+  if (process_program_headers (file))
+    process_dynamic_segment (file);
 
   process_relocs (file);
 
@@ -9523,6 +10072,8 @@ process_file (file_name)
 
   process_corefile_contents (file);
 
+  process_gnu_liblist (file);
+
   process_arch_specific (file);
 
   fclose (file);