]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - binutils/readelf.c
Fix testcases compilation failures due to unused variables.
[thirdparty/binutils-gdb.git] / binutils / readelf.c
index 20a7681f411841a0a29ebfc1829af5e3856995b2..9f1008ccf3a5df213b9600b969874fd16ef2a6a1 100644 (file)
   ELF file than is provided by objdump.  In particular it can display DWARF
   debugging information which (at the moment) objdump cannot.  */
 \f
+#include "config.h"
 #include "sysdep.h"
 #include <assert.h>
 #include <sys/stat.h>
 #include <time.h>
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
 
 /* for PATH_MAX */
 #ifdef HAVE_LIMITS_H
 #include "safe-ctype.h"
 
 char *program_name = "readelf";
+int do_wide;
 static long archive_file_offset;
 static unsigned long archive_file_size;
 static unsigned long dynamic_addr;
@@ -197,7 +202,6 @@ static int do_using_dynamic;
 static int do_header;
 static int do_dump;
 static int do_version;
-static int do_wide;
 static int do_histogram;
 static int do_debugging;
 static int do_arch;
@@ -276,22 +280,6 @@ static void (*byte_put) (unsigned char *, bfd_vma, int);
   : ((X)->sh_name >= string_table_length ? "<corrupt>" \
   : string_table + (X)->sh_name))
 
-/* Given st_shndx I, map to section_headers index.  */
-#define SECTION_HEADER_INDEX(I)                                \
-  ((I) < SHN_LORESERVE                                 \
-   ? (I)                                               \
-   : ((I) <= SHN_HIRESERVE                             \
-      ? 0                                              \
-      : (I) - (SHN_HIRESERVE + 1 - SHN_LORESERVE)))
-
-/* Reverse of the above.  */
-#define SECTION_HEADER_NUM(N)                          \
-  ((N) < SHN_LORESERVE                                 \
-   ? (N)                                               \
-   : (N) + (SHN_HIRESERVE + 1 - SHN_LORESERVE))
-
-#define SECTION_HEADER(I) (section_headers + SECTION_HEADER_INDEX (I))
-
 #define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag)) /* Reverse order!  */
 
 #define BYTE_GET(field)        byte_get (field, sizeof (field))
@@ -322,7 +310,7 @@ get_data (void *var, FILE *file, long offset, size_t size, size_t nmemb,
   if (fseek (file, archive_file_offset + offset, SEEK_SET))
     {
       error (_("Unable to seek to 0x%lx for %s\n"),
-            archive_file_offset + offset, reason);
+            (unsigned long) archive_file_offset + offset, reason);
       return NULL;
     }
 
@@ -384,195 +372,128 @@ byte_put_little_endian (unsigned char *field, bfd_vma value, int size)
     }
 }
 
-#if defined BFD64 && !BFD_HOST_64BIT_LONG && !BFD_HOST_64BIT_LONG_LONG
+/* Print a VMA value.  */
 static int
-print_dec_vma (bfd_vma vma, int is_signed)
+print_vma (bfd_vma vma, print_mode mode)
 {
-  char buf[40];
-  char *bufp = buf;
   int nc = 0;
 
-  if (is_signed && (bfd_signed_vma) vma < 0)
+  switch (mode)
     {
-      vma = -vma;
-      putchar ('-');
-      nc = 1;
-    }
+    case FULL_HEX:
+      nc = printf ("0x");
+      /* Drop through.  */
 
-  do
-    {
-      *bufp++ = '0' + vma % 10;
-      vma /= 10;
-    }
-  while (vma != 0);
-  nc += bufp - buf;
+    case LONG_HEX:
+#ifdef BFD64
+      if (is_32bit_elf)
+       return nc + printf ("%8.8" BFD_VMA_FMT "x", vma);
+#endif
+      printf_vma (vma);
+      return nc + 16;
 
-  while (bufp > buf)
-    putchar (*--bufp);
-  return nc;
-}
+    case DEC_5:
+      if (vma <= 99999)
+       return printf ("%5" BFD_VMA_FMT "d", vma);
+      /* Drop through.  */
 
-static int
-print_hex_vma (bfd_vma vma)
-{
-  char buf[32];
-  char *bufp = buf;
-  int nc;
+    case PREFIX_HEX:
+      nc = printf ("0x");
+      /* Drop through.  */
 
-  do
-    {
-      char digit = '0' + (vma & 0x0f);
-      if (digit > '9')
-       digit += 'a' - '0' - 10;
-      *bufp++ = digit;
-      vma >>= 4;
-    }
-  while (vma != 0);
-  nc = bufp - buf;
+    case HEX:
+      return nc + printf ("%" BFD_VMA_FMT "x", vma);
 
-  while (bufp > buf)
-    putchar (*--bufp);
-  return nc;
+    case DEC:
+      return printf ("%" BFD_VMA_FMT "d", vma);
+
+    case UNSIGNED:
+      return printf ("%" BFD_VMA_FMT "u", vma);
+    }
+  return 0;
 }
-#endif
 
-/* Print a VMA value.  */
-static int
-print_vma (bfd_vma vma, print_mode mode)
-{
-#ifdef BFD64
-  if (is_32bit_elf)
-#endif
-    {
-      switch (mode)
-       {
-       case FULL_HEX:
-         return printf ("0x%8.8lx", (unsigned long) vma);
+/* Display a symbol on stdout.  Handles the display of
+   non-printing characters.
+   If DO_WIDE is not true then format the symbol to be
+   at most WIDTH characters, truncating as necessary.
+   If WIDTH is negative then format the string to be
+   exactly - WIDTH characters, truncating or padding
+   as necessary.  */
 
-       case LONG_HEX:
-         return printf ("%8.8lx", (unsigned long) vma);
+static void
+print_symbol (int width, const char *symbol)
+{
+  const char * format_string;
+  const char * c;
 
-       case DEC_5:
-         if (vma <= 99999)
-           return printf ("%5ld", (long) vma);
-         /* Drop through.  */
+  if (do_wide)
+    {
+      format_string = "%.*s";
+      /* Set the width to a very large value.  This simplifies the code below.  */
+      width = INT_MAX;
+    }
+  else if (width < 0)
+    {
+      format_string = "%-*.*2s";
+      /* Keep the width positive.  This also helps.  */
+      width = - width;
+    }
+  else
+    {
+      format_string = "%-.*s";
+    }
 
-       case PREFIX_HEX:
-         return printf ("0x%lx", (unsigned long) vma);
+  while (width)
+    {
+      int len;
 
-       case HEX:
-         return printf ("%lx", (unsigned long) vma);
+      c = symbol;
 
-       case DEC:
-         return printf ("%ld", (unsigned long) vma);
+      /* Look for non-printing symbols inside the symbol's name.
+        This test is triggered in particular by the names generated
+        by the assembler for local labels.  */
+      while (ISPRINT (* c))
+       c++;
 
-       case UNSIGNED:
-         return printf ("%lu", (unsigned long) vma);
-       }
-    }
-#ifdef BFD64
-  else
-    {
-      int nc = 0;
+      len = c - symbol;
 
-      switch (mode)
+      if (len)
        {
-       case FULL_HEX:
-         nc = printf ("0x");
-         /* Drop through.  */
+         if (len > width)
+           len = width;
+         
+         printf (format_string, len, symbol);
 
-       case LONG_HEX:
-         printf_vma (vma);
-         return nc + 16;
+         width -= len;
+       }
 
-       case PREFIX_HEX:
-         nc = printf ("0x");
-         /* Drop through.  */
+      if (* c == 0 || width == 0)
+       break;
 
-       case HEX:
-#if BFD_HOST_64BIT_LONG
-         return nc + printf ("%lx", vma);
-#elif BFD_HOST_64BIT_LONG_LONG
-#ifndef __MSVCRT__
-         return nc + printf ("%llx", vma);
-#else
-         return nc + printf ("%I64x", vma);
-#endif
-#else
-         return nc + print_hex_vma (vma);
-#endif
+      /* Now display the non-printing character, if
+        there is room left in which to dipslay it.  */
+      if (*c < 32)
+       {
+         if (width < 2)
+           break;
 
-       case DEC:
-#if BFD_HOST_64BIT_LONG
-         return printf ("%ld", vma);
-#elif BFD_HOST_64BIT_LONG_LONG
-#ifndef __MSVCRT__
-         return printf ("%lld", vma);
-#else
-         return printf ("%I64d", vma);
-#endif
-#else
-         return print_dec_vma (vma, 1);
-#endif
+         printf ("^%c", *c + 0x40);
 
-       case DEC_5:
-#if BFD_HOST_64BIT_LONG
-         if (vma <= 99999)
-           return printf ("%5ld", vma);
-         else
-           return printf ("%#lx", vma);
-#elif BFD_HOST_64BIT_LONG_LONG
-#ifndef __MSVCRT__
-         if (vma <= 99999)
-           return printf ("%5lld", vma);
-         else
-           return printf ("%#llx", vma);
-#else
-         if (vma <= 99999)
-           return printf ("%5I64d", vma);
-         else
-           return printf ("%#I64x", vma);
-#endif
-#else
-         if (vma <= 99999)
-           return printf ("%5ld", _bfd_int64_low (vma));
-         else
-           return print_hex_vma (vma);
-#endif
-
-       case UNSIGNED:
-#if BFD_HOST_64BIT_LONG
-         return printf ("%lu", vma);
-#elif BFD_HOST_64BIT_LONG_LONG
-#ifndef __MSVCRT__
-         return printf ("%llu", vma);
-#else
-         return printf ("%I64u", vma);
-#endif
-#else
-         return print_dec_vma (vma, 0);
-#endif
+         width -= 2;
        }
-    }
-#endif
-  return 0;
-}
+      else
+       {
+         if (width < 6)
+           break;
+         
+         printf ("<0x%.2x>", *c);
 
-/* Display a symbol on stdout.  If do_wide is not true then
-   format the symbol to be at most WIDTH characters,
-   truncating as necessary.  If WIDTH is negative then
-   format the string to be exactly - WIDTH characters,
-   truncating or padding as necessary.  */
+         width -= 6;
+       }
 
-static void
-print_symbol (int width, const char *symbol)
-{
-  if (do_wide)
-    printf ("%s", symbol);
-  else if (width < 0)
-    printf ("%-*.*s", width, width, symbol);
-  else
-    printf ("%-.*s", width, symbol);
+      symbol = c + 1;
+    }
 }
 
 static void
@@ -624,7 +545,7 @@ find_section (const char *name)
 /* Guess the relocation size commonly used by the specific machines.  */
 
 static int
-guess_is_rela (unsigned long e_machine)
+guess_is_rela (unsigned int e_machine)
 {
   switch (e_machine)
     {
@@ -653,6 +574,7 @@ guess_is_rela (unsigned long e_machine)
     case EM_AVR_OLD:
     case EM_BLACKFIN:
     case EM_CR16:
+    case EM_CR16_OLD:
     case EM_CRIS:
     case EM_CRX:
     case EM_D30V:
@@ -667,6 +589,7 @@ guess_is_rela (unsigned long e_machine)
     case EM_IP2K:
     case EM_IP2K_OLD:
     case EM_IQ2000:
+    case EM_M32C_OLD:
     case EM_M32C:
     case EM_M32R:
     case EM_MCORE:
@@ -784,6 +707,28 @@ slurp_rela_relocs (FILE *file,
          relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
          relas[i].r_info   = BYTE_GET (erelas[i].r_info);
          relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
+
+         /* 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.  */
+#ifdef BFD64
+         if (elf_header.e_machine == EM_MIPS
+             && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
+           {
+             /* In little-endian objects, r_info isn't really a
+                64-bit little-endian value: it has a 32-bit
+                little-endian symbol index followed by four
+                individual byte fields.  Reorder INFO
+                accordingly.  */
+             bfd_vma info = relas[i].r_info;
+             info = (((info & 0xffffffff) << 32)
+                     | ((info >> 56) & 0xff)
+                     | ((info >> 40) & 0xff00)
+                     | ((info >> 24) & 0xff0000)
+                     | ((info >> 8) & 0xff000000));
+             relas[i].r_info = info;
+           }
+#endif /* BFD64 */
        }
 
       free (erelas);
@@ -856,6 +801,28 @@ slurp_rel_relocs (FILE *file,
          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;
+
+         /* 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.  */
+#ifdef BFD64
+         if (elf_header.e_machine == EM_MIPS
+             && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
+           {
+             /* In little-endian objects, r_info isn't really a
+                64-bit little-endian value: it has a 32-bit
+                little-endian symbol index followed by four
+                individual byte fields.  Reorder INFO
+                accordingly.  */
+             bfd_vma info = rels[i].r_info;
+             info = (((info & 0xffffffff) << 32)
+                     | ((info >> 56) & 0xff)
+                     | ((info >> 40) & 0xff00)
+                     | ((info >> 24) & 0xff0000)
+                     | ((info >> 8) & 0xff000000));
+             rels[i].r_info = info;
+           }
+#endif /* BFD64 */
        }
 
       free (erels);
@@ -972,26 +939,6 @@ dump_relocations (FILE *file,
       offset = rels[i].r_offset;
       info   = rels[i].r_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.  */
-#ifdef BFD64
-      if (!is_32bit_elf
-         && elf_header.e_machine == EM_MIPS
-         && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
-       {
-         /* In little-endian objects, r_info isn't really a 64-bit
-            little-endian value: it has a 32-bit little-endian
-            symbol index followed by four individual byte fields.
-            Reorder INFO accordingly.  */
-         info = (((info & 0xffffffff) << 32)
-                 | ((info >> 56) & 0xff)
-                 | ((info >> 40) & 0xff00)
-                 | ((info >> 24) & 0xff0000)
-                 | ((info >> 8) & 0xff000000));
-       }
-#endif /* BFD64 */
-
       type = get_reloc_type (info);
       symtab_index = get_reloc_symindex  (info);
 
@@ -1230,6 +1177,7 @@ dump_relocations (FILE *file,
          rtype = elf_xtensa_reloc_type (type);
          break;
 
+       case EM_M32C_OLD:
        case EM_M32C:
          rtype = elf_m32c_reloc_type (type);
          break;
@@ -1247,6 +1195,7 @@ dump_relocations (FILE *file,
          break;
 
        case EM_CR16:
+       case EM_CR16_OLD:
          rtype = elf_cr16_reloc_type (type);
          break;
        }
@@ -1302,16 +1251,9 @@ dump_relocations (FILE *file,
 
                  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_HIRESERVE)
-                       sec_index = psym->st_shndx - (SHN_HIRESERVE + 1
-                                                     - SHN_LORESERVE);
-
-                     if (sec_index != (bfd_vma) -1)
-                       sec_name = SECTION_NAME (section_headers + sec_index);
+                     if (psym->st_shndx < elf_header.e_shnum)
+                       sec_name
+                         = SECTION_NAME (section_headers + psym->st_shndx);
                      else if (psym->st_shndx == SHN_ABS)
                        sec_name = "ABS";
                      else if (psym->st_shndx == SHN_COMMON)
@@ -1329,6 +1271,11 @@ dump_relocations (FILE *file,
                               && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX
                               && psym->st_shndx == SHN_IA_64_ANSI_COMMON)
                        sec_name = "ANSI_COM";
+                     else if (elf_header.e_machine == EM_IA_64
+                              && (elf_header.e_ident[EI_OSABI] 
+                                  == ELFOSABI_OPENVMS)
+                              && psym->st_shndx == SHN_IA_64_VMS_SYMVEC)
+                       sec_name = "VMS_SYMVEC";
                      else
                        {
                          sprintf (name_buf, "<section 0x%x>",
@@ -1443,6 +1390,8 @@ get_mips_dynamic_type (unsigned long type)
     case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE";
     case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE";
     case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC";
+    case DT_MIPS_PLTGOT: return "MIPS_PLTGOT";
+    case DT_MIPS_RWPLT: return "MIPS_RWPLT";
     default:
       return NULL;
     }
@@ -1522,7 +1471,37 @@ get_ia64_dynamic_type (unsigned long type)
 {
   switch (type)
     {
-    case DT_IA_64_PLT_RESERVE: return "IA_64_PLT_RESERVE";
+    case DT_IA_64_PLT_RESERVE:         return "IA_64_PLT_RESERVE";
+    case DT_IA_64_VMS_SUBTYPE:         return "VMS_SUBTYPE";
+    case DT_IA_64_VMS_IMGIOCNT:        return "VMS_IMGIOCNT";
+    case DT_IA_64_VMS_LNKFLAGS:        return "VMS_LNKFLAGS";
+    case DT_IA_64_VMS_VIR_MEM_BLK_SIZ: return "VMS_VIR_MEM_BLK_SIZ";
+    case DT_IA_64_VMS_IDENT:           return "VMS_IDENT";
+    case DT_IA_64_VMS_NEEDED_IDENT:    return "VMS_NEEDED_IDENT";
+    case DT_IA_64_VMS_IMG_RELA_CNT:    return "VMS_IMG_RELA_CNT";
+    case DT_IA_64_VMS_SEG_RELA_CNT:    return "VMS_SEG_RELA_CNT";
+    case DT_IA_64_VMS_FIXUP_RELA_CNT:  return "VMS_FIXUP_RELA_CNT";
+    case DT_IA_64_VMS_FIXUP_NEEDED:    return "VMS_FIXUP_NEEDED";
+    case DT_IA_64_VMS_SYMVEC_CNT:      return "VMS_SYMVEC_CNT";
+    case DT_IA_64_VMS_XLATED:          return "VMS_XLATED";
+    case DT_IA_64_VMS_STACKSIZE:       return "VMS_STACKSIZE";
+    case DT_IA_64_VMS_UNWINDSZ:        return "VMS_UNWINDSZ";
+    case DT_IA_64_VMS_UNWIND_CODSEG:   return "VMS_UNWIND_CODSEG";
+    case DT_IA_64_VMS_UNWIND_INFOSEG:  return "VMS_UNWIND_INFOSEG";
+    case DT_IA_64_VMS_LINKTIME:        return "VMS_LINKTIME";
+    case DT_IA_64_VMS_SEG_NO:          return "VMS_SEG_NO";
+    case DT_IA_64_VMS_SYMVEC_OFFSET:   return "VMS_SYMVEC_OFFSET";
+    case DT_IA_64_VMS_SYMVEC_SEG:      return "VMS_SYMVEC_SEG";
+    case DT_IA_64_VMS_UNWIND_OFFSET:   return "VMS_UNWIND_OFFSET";
+    case DT_IA_64_VMS_UNWIND_SEG:      return "VMS_UNWIND_SEG";
+    case DT_IA_64_VMS_STRTAB_OFFSET:   return "VMS_STRTAB_OFFSET";
+    case DT_IA_64_VMS_SYSVER_OFFSET:   return "VMS_SYSVER_OFFSET";
+    case DT_IA_64_VMS_IMG_RELA_OFF:    return "VMS_IMG_RELA_OFF";
+    case DT_IA_64_VMS_SEG_RELA_OFF:    return "VMS_SEG_RELA_OFF";
+    case DT_IA_64_VMS_FIXUP_RELA_OFF:  return "VMS_FIXUP_RELA_OFF";
+    case DT_IA_64_VMS_PLTGOT_OFFSET:   return "VMS_PLTGOT_OFFSET";
+    case DT_IA_64_VMS_PLTGOT_SEG:      return "VMS_PLTGOT_SEG";
+    case DT_IA_64_VMS_FPMODE:          return "VMS_FPMODE";
     default:
       return NULL;
     }
@@ -1688,6 +1667,9 @@ get_dynamic_type (unsigned long type)
            case EM_PARISC:
              result = get_parisc_dynamic_type (type);
              break;
+           case EM_IA_64:
+             result = get_ia64_dynamic_type (type);
+             break;
            default:
              result = NULL;
              break;
@@ -1833,6 +1815,7 @@ get_machine_name (unsigned e_machine)
     case EM_IQ2000:            return "Vitesse IQ2000";
     case EM_XTENSA_OLD:
     case EM_XTENSA:            return "Tensilica Xtensa Processor";
+    case EM_M32C_OLD:
     case EM_M32C:              return "Renesas M32c";
     case EM_MT:                 return "Morpho Techologies MT processor";
     case EM_BLACKFIN:          return "Analog Devices Blackfin";
@@ -1840,7 +1823,8 @@ get_machine_name (unsigned e_machine)
     case EM_ALTERA_NIOS2:      return "Altera Nios II";
     case EM_XC16X:             return "Infineon Technologies xc16x";
     case EM_CYGNUS_MEP:         return "Toshiba MeP Media Engine";
-    case EM_CR16:              return "National Semiconductor's CR16";
+    case EM_CR16:              
+    case EM_CR16_OLD:          return "National Semiconductor's CR16";
     default:
       snprintf (buff, sizeof (buff), _("<unknown>: 0x%x"), e_machine);
       return buff;
@@ -2222,6 +2206,7 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
            case E_MIPS_MACH_9000: strcat (buf, ", 9000"); break;
            case E_MIPS_MACH_LS2E: strcat (buf, ", loongson-2e"); break;
            case E_MIPS_MACH_LS2F: strcat (buf, ", loongson-2f"); break;
+           case E_MIPS_MACH_OCTEON: strcat (buf, ", octeon"); break;
            case 0:
            /* We simply ignore the field in this case to avoid confusion:
               MIPS ELF does not specify EF_MIPS_MACH, it is a GNU
@@ -2410,7 +2395,7 @@ get_osabi_name (unsigned int osabi)
     case ELFOSABI_OPENBSD:     return "UNIX - OpenBSD";
     case ELFOSABI_OPENVMS:     return "VMS - OpenVMS";
     case ELFOSABI_NSK:         return "HP - Non-Stop Kernel";
-    case ELFOSABI_AROS:                return "Amiga Research OS";
+    case ELFOSABI_AROS:                return "AROS";
     case ELFOSABI_STANDALONE:  return _("Standalone App");
     case ELFOSABI_ARM:         return "ARM";
     default:
@@ -2657,9 +2642,16 @@ get_ia64_section_type_name (unsigned int sh_type)
 
   switch (sh_type)
     {
-    case SHT_IA_64_EXT:                  return "IA_64_EXT";
-    case SHT_IA_64_UNWIND:       return "IA_64_UNWIND";
-    case SHT_IA_64_PRIORITY_INIT: return "IA_64_PRIORITY_INIT";
+    case SHT_IA_64_EXT:                       return "IA_64_EXT";
+    case SHT_IA_64_UNWIND:            return "IA_64_UNWIND";
+    case SHT_IA_64_PRIORITY_INIT:      return "IA_64_PRIORITY_INIT";
+    case SHT_IA_64_VMS_TRACE:          return "VMS_TRACE";
+    case SHT_IA_64_VMS_TIE_SIGNATURES: return "VMS_TIE_SIGNATURES";
+    case SHT_IA_64_VMS_DEBUG:          return "VMS_DEBUG";
+    case SHT_IA_64_VMS_DEBUG_STR:      return "VMS_DEBUG_STR";
+    case SHT_IA_64_VMS_LINKAGES:       return "VMS_LINKAGES";
+    case SHT_IA_64_VMS_SYMBOL_VECTOR:  return "VMS_SYMBOL_VECTOR";
+    case SHT_IA_64_VMS_FIXUP:          return "VMS_FIXUP";
     default:
       break;
     }
@@ -2763,7 +2755,24 @@ get_section_type_name (unsigned int sh_type)
          sprintf (buff, "LOPROC+%x", sh_type - SHT_LOPROC);
        }
       else if ((sh_type >= SHT_LOOS) && (sh_type <= SHT_HIOS))
-       sprintf (buff, "LOOS+%x", sh_type - SHT_LOOS);
+       {
+         const char *result;
+
+         switch (elf_header.e_machine)
+           {
+           case EM_IA_64:
+             result = get_ia64_section_type_name (sh_type);
+             break;
+           default:
+             result = NULL;
+             break;
+           }
+
+         if (result != NULL)
+           return result;
+
+         sprintf (buff, "LOOS+%x", sh_type - SHT_LOOS);
+       }
       else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
        sprintf (buff, "LOUSER+%x", sh_type - SHT_LOUSER);
       else
@@ -2840,8 +2849,8 @@ usage (FILE *stream)
                          Dump the contents of section <number|name> as bytes\n\
   -p --string-dump=<number|name>\n\
                          Dump the contents of section <number|name> as strings\n\
-  -w[liaprmfFsoR] or\n\
-  --debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
+  -w[lLiaprmfFsoR] or\n\
+  --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
                          Display the contents of DWARF2 debug sections\n"));
 #ifdef SUPPORT_DISASSEMBLY
   fprintf (stream, _("\
@@ -3032,22 +3041,22 @@ parse_args (int argc, char **argv)
                switch (optarg[index++])
                  {
                  case 'i':
-                 case 'I':
                    do_debug_info = 1;
                    break;
 
                  case 'a':
-                 case 'A':
                    do_debug_abbrevs = 1;
                    break;
 
                  case 'l':
-                 case 'L':
                    do_debug_lines = 1;
                    break;
 
+                 case 'L':
+                   do_debug_lines_decoded = 1;
+                   break;
+
                  case 'p':
-                 case 'P':
                    do_debug_pubnames = 1;
                    break;
 
@@ -3066,17 +3075,14 @@ parse_args (int argc, char **argv)
                    break;
 
                  case 'm':
-                 case 'M':
                    do_debug_macinfo = 1;
                    break;
 
                  case 's':
-                 case 'S':
                    do_debug_str = 1;
                    break;
 
                  case 'o':
-                 case 'O':
                    do_debug_loc = 1;
                    break;
 
@@ -3108,7 +3114,9 @@ parse_args (int argc, char **argv)
                  { "frames", & do_debug_frames },
                  { "frames-interp", & do_debug_frames_interp },
                  { "info", & do_debug_info },
-                 { "line", & do_debug_lines },
+                 { "line", & do_debug_lines }, /* For backwards compatibility.  */
+                 { "rawline", & do_debug_lines },
+                 { "decodedline", & do_debug_lines_decoded },
                  { "loc",  & do_debug_loc },
                  { "macro", & do_debug_macinfo },
                  { "pubnames", & do_debug_pubnames },
@@ -3246,6 +3254,8 @@ process_file_header (void)
       return 0;
     }
 
+  init_dwarf_regnames (elf_header.e_machine);
+
   if (do_header)
     {
       int i;
@@ -3298,31 +3308,26 @@ process_file_header (void)
              (long) elf_header.e_shentsize);
       printf (_("  Number of section headers:         %ld"),
              (long) elf_header.e_shnum);
-      if (section_headers != NULL && elf_header.e_shnum == 0)
+      if (section_headers != NULL && elf_header.e_shnum == SHN_UNDEF)
        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);
-      else if (elf_header.e_shstrndx != SHN_UNDEF
-              && (elf_header.e_shstrndx >= elf_header.e_shnum
-                  || (elf_header.e_shstrndx >= SHN_LORESERVE
-                      && elf_header.e_shstrndx <= SHN_HIRESERVE)))
+      if (section_headers != NULL
+         && elf_header.e_shstrndx == (SHN_XINDEX & 0xffff))
+       printf (" (%u)", section_headers[0].sh_link);
+      else if (elf_header.e_shstrndx >= elf_header.e_shnum)
        printf (" <corrupt: out of range>");
       putc ('\n', stdout);
     }
 
   if (section_headers != NULL)
     {
-      if (elf_header.e_shnum == 0)
+      if (elf_header.e_shnum == SHN_UNDEF)
        elf_header.e_shnum = section_headers[0].sh_size;
-      if (elf_header.e_shstrndx == SHN_XINDEX)
+      if (elf_header.e_shstrndx == (SHN_XINDEX & 0xffff))
        elf_header.e_shstrndx = section_headers[0].sh_link;
-      else if (elf_header.e_shstrndx != SHN_UNDEF
-              && (elf_header.e_shstrndx >= elf_header.e_shnum
-                  || (elf_header.e_shstrndx >= SHN_LORESERVE
-                      && elf_header.e_shstrndx <= SHN_HIRESERVE)))
+      else if (elf_header.e_shstrndx >= elf_header.e_shnum)
        elf_header.e_shstrndx = SHN_UNDEF;
       free (section_headers);
       section_headers = NULL;
@@ -3646,7 +3651,7 @@ process_program_headers (FILE *file)
          Elf_Internal_Shdr *section;
 
          segment = program_headers + i;
-         section = section_headers;
+         section = section_headers + 1;
 
          printf ("   %2.2d     ", i);
 
@@ -3690,7 +3695,7 @@ offset_from_vma (FILE *file, bfd_vma vma, bfd_size_type size)
     }
 
   warn (_("Virtual address 0x%lx not located in any PT_LOAD segment.\n"),
-       (long) vma);
+       (unsigned long) vma);
   return (long) vma;
 }
 
@@ -3795,7 +3800,7 @@ get_32bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
   shndx = NULL;
   if (symtab_shndx_hdr != NULL
       && (symtab_shndx_hdr->sh_link
-         == (unsigned long) SECTION_HEADER_NUM (section - section_headers)))
+         == (unsigned long) (section - section_headers)))
     {
       shndx = get_data (NULL, file, symtab_shndx_hdr->sh_offset,
                        1, symtab_shndx_hdr->sh_size, _("symtab shndx"));
@@ -3826,9 +3831,11 @@ get_32bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
       psym->st_value = BYTE_GET (esyms[j].st_value);
       psym->st_size  = BYTE_GET (esyms[j].st_size);
       psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
-      if (psym->st_shndx == SHN_XINDEX && shndx != NULL)
+      if (psym->st_shndx == (SHN_XINDEX & 0xffff) && shndx != NULL)
        psym->st_shndx
          = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j]));
+      else if (psym->st_shndx >= (SHN_LORESERVE & 0xffff))
+       psym->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
       psym->st_info  = BYTE_GET (esyms[j].st_info);
       psym->st_other = BYTE_GET (esyms[j].st_other);
     }
@@ -3858,7 +3865,7 @@ get_64bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
   shndx = NULL;
   if (symtab_shndx_hdr != NULL
       && (symtab_shndx_hdr->sh_link
-         == (unsigned long) SECTION_HEADER_NUM (section - section_headers)))
+         == (unsigned long) (section - section_headers)))
     {
       shndx = get_data (NULL, file, symtab_shndx_hdr->sh_offset,
                        1, symtab_shndx_hdr->sh_size, _("symtab shndx"));
@@ -3889,9 +3896,11 @@ get_64bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
       psym->st_info  = BYTE_GET (esyms[j].st_info);
       psym->st_other = BYTE_GET (esyms[j].st_other);
       psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
-      if (psym->st_shndx == SHN_XINDEX && shndx != NULL)
+      if (psym->st_shndx == (SHN_XINDEX & 0xffff) && shndx != NULL)
        psym->st_shndx
          = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j]));
+      else if (psym->st_shndx >= (SHN_LORESERVE & 0xffff))
+       psym->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
       psym->st_value = BYTE_GET (esyms[j].st_value);
       psym->st_size  = BYTE_GET (esyms[j].st_size);
     }
@@ -3913,7 +3922,7 @@ get_elf_section_flags (bfd_vma sh_flags)
   bfd_vma os_flags = 0;
   bfd_vma proc_flags = 0;
   bfd_vma unknown_flags = 0;
-  const struct
+  static const struct
     {
       const char *str;
       int len;
@@ -3929,7 +3938,17 @@ get_elf_section_flags (bfd_vma sh_flags)
        { "LINK ORDER", 10 },
        { "OS NONCONF", 10 },
        { "GROUP", 5 },
-       { "TLS", 3 }
+       { "TLS", 3 },
+       /* IA-64 specific.  */
+       { "SHORT", 5 },
+       { "NORECOV", 7 },
+       /* IA-64 OpenVMS specific.  */
+       { "VMS_GLOBAL", 10 },
+       { "VMS_OVERLAID", 12 },
+       { "VMS_SHARED", 10 },
+       { "VMS_VECTOR", 10 },
+       { "VMS_ALLOC_64BIT", 15 },
+       { "VMS_PROTECTED", 13}
     };
 
   if (do_section_details)
@@ -3963,6 +3982,26 @@ get_elf_section_flags (bfd_vma sh_flags)
 
            default:
              index = -1;
+             if (elf_header.e_machine == EM_IA_64)
+               {
+                 if (flag == SHF_IA_64_SHORT)
+                   index = 10;
+                 else if (flag == SHF_IA_64_NORECOV)
+                   index = 11;
+#ifdef BFD64
+                 else if (elf_header.e_ident[EI_OSABI] == ELFOSABI_OPENVMS)
+                   switch (flag)
+                     {
+                     case SHF_IA_64_VMS_GLOBAL:      index = 12; break;
+                     case SHF_IA_64_VMS_OVERLAID:    index = 13; break;
+                     case SHF_IA_64_VMS_SHARED:      index = 14; break;
+                     case SHF_IA_64_VMS_VECTOR:      index = 15; break;
+                     case SHF_IA_64_VMS_ALLOC_64BIT: index = 16; break;
+                     case SHF_IA_64_VMS_PROTECTED:   index = 17; break;
+                     default:                        break;
+                     }
+#endif
+               }
              break;
            }
 
@@ -4107,9 +4146,9 @@ process_section_headers (FILE *file)
 
   /* Read in the string table, so that we have names to display.  */
   if (elf_header.e_shstrndx != SHN_UNDEF
-       && SECTION_HEADER_INDEX (elf_header.e_shstrndx) < elf_header.e_shnum)
+       && elf_header.e_shstrndx < elf_header.e_shnum)
     {
-      section = SECTION_HEADER (elf_header.e_shstrndx);
+      section = section_headers + elf_header.e_shstrndx;
 
       if (section->sh_size != 0)
        {
@@ -4164,6 +4203,7 @@ process_section_headers (FILE *file)
        }
       break;
 
+    case EM_M32C_OLD:
     case EM_M32C:
       switch (elf_header.e_flags & EF_M32C_CPU_MASK)
        {
@@ -4239,17 +4279,22 @@ process_section_headers (FILE *file)
       else if (section->sh_type == SHT_RELA)
        CHECK_ENTSIZE (section, i, Rela);
       else if ((do_debugging || do_debug_info || do_debug_abbrevs
-               || do_debug_lines || do_debug_pubnames || do_debug_aranges
-               || do_debug_frames || do_debug_macinfo || do_debug_str
-               || do_debug_loc || do_debug_ranges)
-              && const_strneq (name, ".debug_"))
+               || do_debug_lines || do_debug_lines_decoded || do_debug_pubnames 
+               || do_debug_aranges || do_debug_frames || do_debug_macinfo 
+               || do_debug_str || do_debug_loc || do_debug_ranges)
+              && (const_strneq (name, ".debug_")
+                   || const_strneq (name, ".zdebug_")))
        {
-         name += 7;
+          if (name[1] == 'z')
+            name += sizeof (".zdebug_") - 1;
+          else
+            name += sizeof (".debug_") - 1;
 
          if (do_debugging
              || (do_debug_info     && streq (name, "info"))
              || (do_debug_abbrevs  && streq (name, "abbrev"))
-             || (do_debug_lines    && streq (name, "line"))
+             || ((do_debug_lines || do_debug_lines_decoded) 
+                 && streq (name, "line"))
              || (do_debug_pubnames && streq (name, "pubnames"))
              || (do_debug_aranges  && streq (name, "aranges"))
              || (do_debug_ranges   && streq (name, "ranges"))
@@ -4260,7 +4305,7 @@ process_section_headers (FILE *file)
              )
            request_dump_bynumber (i, DEBUG_DUMP);
        }
-      /* linkonce section to be combined with .debug_info at link time.  */
+      /* Linkonce section to be combined with .debug_info at link time.  */
       else if ((do_debugging || do_debug_info)
               && const_strneq (name, ".gnu.linkonce.wi."))
        request_dump_bynumber (i, DEBUG_DUMP);
@@ -4323,7 +4368,7 @@ process_section_headers (FILE *file)
       if (do_section_details)
        {
          printf ("  [%2u] %s\n",
-                 SECTION_HEADER_NUM (i),
+                 i,
                  SECTION_NAME (section));
          if (is_32bit_elf || do_wide)
            printf ("       %-15.15s ",
@@ -4331,7 +4376,7 @@ process_section_headers (FILE *file)
        }
       else
        printf ("  [%2u] %-17.17s %-15.15s ",
-               SECTION_HEADER_NUM (i),
+               i,
                SECTION_NAME (section),
                get_section_type_name (section->sh_type));
 
@@ -4349,9 +4394,9 @@ process_section_headers (FILE *file)
          else
            printf (" %3s ", get_elf_section_flags (section->sh_flags));
 
-         printf ("%2ld %3lu %2ld\n",
-                 (unsigned long) section->sh_link,
-                 (unsigned long) section->sh_info,
+         printf ("%2u %3u %2lu\n",
+                 section->sh_link,
+                 section->sh_info,
                  (unsigned long) section->sh_addralign);
        }
       else if (do_wide)
@@ -4387,12 +4432,10 @@ process_section_headers (FILE *file)
          else
            printf (" %3s ", get_elf_section_flags (section->sh_flags));
 
-         printf ("%2ld %3lu ",
-                 (unsigned long) section->sh_link,
-                 (unsigned long) section->sh_info);
+         printf ("%2u %3u ", section->sh_link, section->sh_info);
 
          if ((unsigned long) section->sh_addralign == section->sh_addralign)
-           printf ("%2ld\n", (unsigned long) section->sh_addralign);
+           printf ("%2lu\n", (unsigned long) section->sh_addralign);
          else
            {
              print_vma (section->sh_addralign, DEC);
@@ -4411,13 +4454,13 @@ process_section_headers (FILE *file)
              printf ("  ");
              print_vma (section->sh_offset, LONG_HEX);
            }
-         printf ("  %ld\n       ", (unsigned long) section->sh_link);
+         printf ("  %u\n       ", section->sh_link);
          print_vma (section->sh_size, LONG_HEX);
          putchar (' ');
          print_vma (section->sh_entsize, LONG_HEX);
 
-         printf ("  %-16lu  %ld\n",
-                 (unsigned long) section->sh_info,
+         printf ("  %-16u  %lu\n",
+                 section->sh_info,
                  (unsigned long) section->sh_addralign);
        }
       else
@@ -4438,9 +4481,9 @@ process_section_headers (FILE *file)
 
          printf (" %3s ", get_elf_section_flags (section->sh_flags));
 
-         printf ("     %2ld   %3lu     %ld\n",
-                 (unsigned long) section->sh_link,
-                 (unsigned long) section->sh_info,
+         printf ("     %2u   %3u     %lu\n",
+                 section->sh_link,
+                 section->sh_info,
                  (unsigned long) section->sh_addralign);
        }
 
@@ -4554,8 +4597,8 @@ process_section_groups (FILE *file)
          Elf_Internal_Sym *sym;
 
          /* Get the symbol table.  */
-         if (SECTION_HEADER_INDEX (section->sh_link) >= elf_header.e_shnum
-             || ((sec = SECTION_HEADER (section->sh_link))->sh_type
+         if (section->sh_link >= elf_header.e_shnum
+             || ((sec = section_headers + section->sh_link)->sh_type
                  != SHT_SYMTAB))
            {
              error (_("Bad sh_link in group section `%s'\n"), name);
@@ -4574,14 +4617,14 @@ process_section_groups (FILE *file)
 
          if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
            {
-             bfd_vma sec_index = SECTION_HEADER_INDEX (sym->st_shndx);
-             if (sec_index == 0)
+             if (sym->st_shndx == 0
+                 || sym->st_shndx >= elf_header.e_shnum)
                {
                  error (_("Bad sh_info in group section `%s'\n"), name);
                  continue;
                }
 
-             group_name = SECTION_NAME (section_headers + sec_index);
+             group_name = SECTION_NAME (section_headers + sym->st_shndx);
              strtab_sec = NULL;
              if (strtab)
                free (strtab);
@@ -4591,8 +4634,7 @@ process_section_groups (FILE *file)
          else
            {
              /* Get the string table.  */
-             if (SECTION_HEADER_INDEX (symtab_sec->sh_link)
-                 >= elf_header.e_shnum)
+             if (symtab_sec->sh_link >= elf_header.e_shnum)
                {
                  strtab_sec = NULL;
                  if (strtab)
@@ -4601,7 +4643,7 @@ process_section_groups (FILE *file)
                  strtab_size = 0;
                }
              else if (strtab_sec
-                      != (sec = SECTION_HEADER (symtab_sec->sh_link)))
+                      != (sec = section_headers + symtab_sec->sh_link))
                {
                  strtab_sec = sec;
                  if (strtab)
@@ -4640,27 +4682,20 @@ process_section_groups (FILE *file)
              entry = byte_get (indices, 4);
              indices += 4;
 
-             if (SECTION_HEADER_INDEX (entry) >= elf_header.e_shnum)
+             if (entry >= elf_header.e_shnum)
                {
                  error (_("section [%5u] in group section [%5u] > maximum section [%5u]\n"),
                         entry, i, elf_header.e_shnum - 1);
                  continue;
                }
-             else if (entry >= SHN_LORESERVE && entry <= SHN_HIRESERVE)
-               {
-                 error (_("invalid section [%5u] in group section [%5u]\n"),
-                        entry, i);
-                 continue;
-               }
 
-             if (section_headers_groups [SECTION_HEADER_INDEX (entry)]
-                 != NULL)
+             if (section_headers_groups [entry] != NULL)
                {
                  if (entry)
                    {
                      error (_("section [%5u] in group section [%5u] already in group section [%5u]\n"),
                             entry, i,
-                            section_headers_groups [SECTION_HEADER_INDEX (entry)]->group_index);
+                            section_headers_groups [entry]->group_index);
                      continue;
                    }
                  else
@@ -4672,18 +4707,17 @@ process_section_groups (FILE *file)
                      if (!warned)
                        {
                          error (_("section 0 in group section [%5u]\n"),
-                                section_headers_groups [SECTION_HEADER_INDEX (entry)]->group_index);
+                                section_headers_groups [entry]->group_index);
                          warned++;
                        }
                    }
                }
 
-             section_headers_groups [SECTION_HEADER_INDEX (entry)]
-               = group;
+             section_headers_groups [entry] = group;
 
              if (do_section_groups)
                {
-                 sec = SECTION_HEADER (entry);
+                 sec = section_headers + entry;
                  printf ("   [%5u]   %s\n", entry, SECTION_NAME (sec));
                }
 
@@ -4815,9 +4849,8 @@ process_relocs (FILE *file)
 
              is_rela = section->sh_type == SHT_RELA;
 
-             if (section->sh_link
-                 && SECTION_HEADER_INDEX (section->sh_link)
-                    < elf_header.e_shnum)
+             if (section->sh_link != 0
+                 && section->sh_link < elf_header.e_shnum)
                {
                  Elf_Internal_Shdr *symsec;
                  Elf_Internal_Sym *symtab;
@@ -4825,7 +4858,7 @@ process_relocs (FILE *file)
                  unsigned long strtablen = 0;
                  char *strtab = NULL;
 
-                 symsec = SECTION_HEADER (section->sh_link);
+                 symsec = section_headers + section->sh_link;
                  if (symsec->sh_type != SHT_SYMTAB
                      && symsec->sh_type != SHT_DYNSYM)
                     continue;
@@ -4836,10 +4869,10 @@ process_relocs (FILE *file)
                  if (symtab == NULL)
                    continue;
 
-                 if (SECTION_HEADER_INDEX (symsec->sh_link)
-                     < elf_header.e_shnum)
+                 if (symsec->sh_link != 0
+                     && symsec->sh_link < elf_header.e_shnum)
                    {
-                     strsec = SECTION_HEADER (symsec->sh_link);
+                     strsec = section_headers + symsec->sh_link;
 
                      strtab = get_data (NULL, file, strsec->sh_offset,
                                         1, strsec->sh_size,
@@ -5076,8 +5109,8 @@ slurp_ia64_unwind_table (FILE *file,
        ++relsec)
     {
       if (relsec->sh_type != SHT_RELA
-         || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
-         || SECTION_HEADER (relsec->sh_info) != sec)
+         || relsec->sh_info >= elf_header.e_shnum
+         || section_headers + relsec->sh_info != sec)
        continue;
 
       if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
@@ -5135,12 +5168,12 @@ ia64_process_unwind (FILE *file)
   for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
     {
       if (sec->sh_type == SHT_SYMTAB
-         && SECTION_HEADER_INDEX (sec->sh_link) < elf_header.e_shnum)
+         && sec->sh_link < elf_header.e_shnum)
        {
          aux.nsyms = sec->sh_size / sec->sh_entsize;
          aux.symtab = GET_ELF_SYMBOLS (file, sec);
 
-         strsec = SECTION_HEADER (sec->sh_link);
+         strsec = section_headers + sec->sh_link;
          aux.strtab = get_data (NULL, file, strsec->sh_offset,
                                 1, strsec->sh_size, _("string table"));
          aux.strtab_size = aux.strtab != NULL ? strsec->sh_size : 0;
@@ -5175,7 +5208,7 @@ ia64_process_unwind (FILE *file)
 
          for (; g != NULL; g = g->next)
            {
-             sec = SECTION_HEADER (g->section_index);
+             sec = section_headers + g->section_index;
 
              if (streq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info))
                break;
@@ -5479,8 +5512,8 @@ slurp_hppa_unwind_table (FILE *file,
        ++relsec)
     {
       if (relsec->sh_type != SHT_RELA
-         || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
-         || SECTION_HEADER (relsec->sh_info) != sec)
+         || relsec->sh_info >= elf_header.e_shnum
+         || section_headers + relsec->sh_info != sec)
        continue;
 
       if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
@@ -5541,12 +5574,12 @@ hppa_process_unwind (FILE *file)
   for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
     {
       if (sec->sh_type == SHT_SYMTAB
-         && SECTION_HEADER_INDEX (sec->sh_link) < elf_header.e_shnum)
+         && sec->sh_link < elf_header.e_shnum)
        {
          aux.nsyms = sec->sh_size / sec->sh_entsize;
          aux.symtab = GET_ELF_SYMBOLS (file, sec);
 
-         strsec = SECTION_HEADER (sec->sh_link);
+         strsec = section_headers + sec->sh_link;
          aux.strtab = get_data (NULL, file, strsec->sh_offset,
                                 1, strsec->sh_size, _("string table"));
          aux.strtab_size = aux.strtab != NULL ? strsec->sh_size : 0;
@@ -5679,7 +5712,7 @@ dynamic_section_mips_val (Elf_Internal_Dyn *entry)
       break;
 
     default:
-      printf ("%#lx\n", (long) entry->d_un.d_ptr);
+      printf ("%#lx\n", (unsigned long) entry->d_un.d_ptr);
     }
 }
 
@@ -6505,16 +6538,15 @@ process_version_sections (FILE *file)
            found = 1;
 
            printf
-             (_("\nVersion definition section '%s' contains %ld entries:\n"),
+             (_("\nVersion definition section '%s' contains %u entries:\n"),
               SECTION_NAME (section), section->sh_info);
 
            printf (_("  Addr: 0x"));
            printf_vma (section->sh_addr);
-           printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
+           printf (_("  Offset: %#08lx  Link: %u (%s)\n"),
                    (unsigned long) section->sh_offset, section->sh_link,
-                   SECTION_HEADER_INDEX (section->sh_link)
-                   < elf_header.e_shnum
-                   ? SECTION_NAME (SECTION_HEADER (section->sh_link))
+                   section->sh_link < elf_header.e_shnum
+                   ? SECTION_NAME (section_headers + section->sh_link)
                    : "<corrupt>");
 
            edefs = get_data (NULL, file, section->sh_offset, 1,
@@ -6608,16 +6640,15 @@ process_version_sections (FILE *file)
 
            found = 1;
 
-           printf (_("\nVersion needs section '%s' contains %ld entries:\n"),
+           printf (_("\nVersion needs section '%s' contains %u entries:\n"),
                    SECTION_NAME (section), section->sh_info);
 
            printf (_(" Addr: 0x"));
            printf_vma (section->sh_addr);
-           printf (_("  Offset: %#08lx  Link to section: %ld (%s)\n"),
+           printf (_("  Offset: %#08lx  Link: %u (%s)\n"),
                    (unsigned long) section->sh_offset, section->sh_link,
-                   SECTION_HEADER_INDEX (section->sh_link)
-                   < elf_header.e_shnum
-                   ? SECTION_NAME (SECTION_HEADER (section->sh_link))
+                   section->sh_link < elf_header.e_shnum
+                   ? SECTION_NAME (section_headers + section->sh_link)
                    : "<corrupt>");
 
            eneed = get_data (NULL, file, section->sh_offset, 1,
@@ -6710,21 +6741,20 @@ process_version_sections (FILE *file)
            Elf_Internal_Shdr *string_sec;
            long off;
 
-           if (SECTION_HEADER_INDEX (section->sh_link) >= elf_header.e_shnum)
+           if (section->sh_link >= elf_header.e_shnum)
              break;
 
-           link_section = SECTION_HEADER (section->sh_link);
+           link_section = section_headers + section->sh_link;
            total = section->sh_size / sizeof (Elf_External_Versym);
 
-           if (SECTION_HEADER_INDEX (link_section->sh_link)
-               >= elf_header.e_shnum)
+           if (link_section->sh_link >= elf_header.e_shnum)
              break;
 
            found = 1;
 
            symbols = GET_ELF_SYMBOLS (file, link_section);
 
-           string_sec = SECTION_HEADER (link_section->sh_link);
+           string_sec = section_headers + link_section->sh_link;
 
            strtab = get_data (NULL, file, string_sec->sh_offset, 1,
                               string_sec->sh_size, _("version string table"));
@@ -6736,7 +6766,7 @@ process_version_sections (FILE *file)
 
            printf (_(" Addr: "));
            printf_vma (section->sh_addr);
-           printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
+           printf (_("  Offset: %#08lx  Link: %u (%s)\n"),
                    (unsigned long) section->sh_offset, section->sh_link,
                    SECTION_NAME (link_section));
 
@@ -6784,9 +6814,8 @@ process_version_sections (FILE *file)
 
                      check_def = 1;
                      check_need = 1;
-                     if (SECTION_HEADER_INDEX (symbols[cnt + j].st_shndx)
-                         >= elf_header.e_shnum
-                         || SECTION_HEADER (symbols[cnt + j].st_shndx)->sh_type
+                     if (symbols[cnt + j].st_shndx >= elf_header.e_shnum
+                         || section_headers[symbols[cnt + j].st_shndx].sh_type
                             != SHT_NOBITS)
                        {
                          if (symbols[cnt + j].st_shndx == SHN_UNDEF)
@@ -7017,6 +7046,8 @@ get_mips_symbol_other (unsigned int other)
     {
     case STO_OPTIONAL:  return "OPTIONAL";
     case STO_MIPS16:    return "MIPS16";
+    case STO_MIPS_PLT: return "MIPS PLT";
+    case STO_MIPS_PIC: return "MIPS PIC";
     default:           return NULL;
     }
 }
@@ -7070,11 +7101,11 @@ get_symbol_index_type (unsigned int type)
               && elf_header.e_machine == EM_MIPS)
        return "SUND";
       else if (type >= SHN_LOPROC && type <= SHN_HIPROC)
-       sprintf (buff, "PRC[0x%04x]", type);
+       sprintf (buff, "PRC[0x%04x]", type & 0xffff);
       else if (type >= SHN_LOOS && type <= SHN_HIOS)
-       sprintf (buff, "OS [0x%04x]", type);
-      else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
-       sprintf (buff, "RSV[0x%04x]", type);
+       sprintf (buff, "OS [0x%04x]", type & 0xffff);
+      else if (type >= SHN_LORESERVE)
+       sprintf (buff, "RSV[0x%04x]", type & 0xffff);
       else
        sprintf (buff, "%3d", type);
       break;
@@ -7404,11 +7435,11 @@ process_symbol_table (FILE *file)
              strtab = string_table;
              strtab_size = string_table_length;
            }
-         else if (SECTION_HEADER_INDEX (section->sh_link) < elf_header.e_shnum)
+         else if (section->sh_link < elf_header.e_shnum)
            {
              Elf_Internal_Shdr *string_sec;
 
-             string_sec = SECTION_HEADER (section->sh_link);
+             string_sec = section_headers + section->sh_link;
 
              strtab = get_data (NULL, file, string_sec->sh_offset,
                                 1, string_sec->sh_size, _("string table"));
@@ -7453,9 +7484,8 @@ process_symbol_table (FILE *file)
 
                  vers_data = byte_get (data, 2);
 
-                 is_nobits = (SECTION_HEADER_INDEX (psym->st_shndx)
-                              < elf_header.e_shnum
-                              && SECTION_HEADER (psym->st_shndx)->sh_type
+                 is_nobits = (psym->st_shndx < elf_header.e_shnum
+                              && section_headers[psym->st_shndx].sh_type
                                  == SHT_NOBITS);
 
                  check_def = (psym->st_shndx != SHN_UNDEF);
@@ -7834,10 +7864,10 @@ dump_section_as_strings (Elf_Internal_Shdr *section, FILE *file)
        ++relsec)
     {
       if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
-         || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
-         || SECTION_HEADER (relsec->sh_info) != section
+         || relsec->sh_info >= elf_header.e_shnum
+         || section_headers + relsec->sh_info != section
          || relsec->sh_size == 0
-         || SECTION_HEADER_INDEX (relsec->sh_link) >= elf_header.e_shnum)
+         || relsec->sh_link >= elf_header.e_shnum)
        continue;
 
       printf (_("  Note: This section has relocations against it, but these have NOT been applied to this dump.\n"));
@@ -7913,10 +7943,10 @@ dump_section_as_bytes (Elf_Internal_Shdr *section, FILE *file)
        ++relsec)
     {
       if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
-         || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
-         || SECTION_HEADER (relsec->sh_info) != section
+         || relsec->sh_info >= elf_header.e_shnum
+         || section_headers + relsec->sh_info != section
          || relsec->sh_size == 0
-         || SECTION_HEADER_INDEX (relsec->sh_link) >= elf_header.e_shnum)
+         || relsec->sh_link >= elf_header.e_shnum)
        continue;
 
       printf (_(" NOTE: This section has relocations against it, but these have NOT been applied to this dump.\n"));
@@ -8005,6 +8035,7 @@ is_32bit_abs_reloc (unsigned int reloc_type)
     case EM_CRIS:
       return reloc_type == 3; /* R_CRIS_32.  */
     case EM_CR16:
+    case EM_CR16_OLD:
       return reloc_type == 3; /* R_CR16_NUM32.  */
     case EM_CRX:
       return reloc_type == 15; /* R_CRX_NUM32.  */
@@ -8032,6 +8063,7 @@ is_32bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 2; /* R_IP2K_32.  */
     case EM_IQ2000:
       return reloc_type == 2; /* R_IQ2000_32.  */
+    case EM_M32C_OLD:
     case EM_M32C:
       return reloc_type == 3; /* R_M32C_32.  */
     case EM_M32R:
@@ -8124,7 +8156,7 @@ is_32bit_pcrel_reloc (unsigned int reloc_type)
     case EM_ARM:
       return reloc_type == 3;  /* R_ARM_REL32 */
     case EM_PARISC:
-      return reloc_type == 0;  /* R_PARISC_NONE.  *//* FIXME: This reloc is generated, but it may be a bug.  */
+      return reloc_type == 9;  /* R_PARISC_PCREL32.  */
     case EM_PPC:
       return reloc_type == 26; /* R_PPC_REL32.  */
     case EM_PPC64:
@@ -8180,6 +8212,38 @@ is_64bit_abs_reloc (unsigned int reloc_type)
     case EM_S390_OLD:
     case EM_S390:
       return reloc_type == 22; /* R_S390_64 */
+    case EM_MIPS:
+      return reloc_type == 18; /* R_MIPS_64 */
+    default:
+      return FALSE;
+    }
+}
+
+/* Like is_32bit_pcrel_reloc except that it returns TRUE iff RELOC_TYPE is
+   a 64-bit pc-relative RELA relocation used in DWARF debug sections.  */
+
+static bfd_boolean
+is_64bit_pcrel_reloc (unsigned int reloc_type)
+{
+  switch (elf_header.e_machine)
+    {
+    case EM_ALPHA:
+      return reloc_type == 11; /* R_ALPHA_SREL64 */
+    case EM_IA_64:
+      return reloc_type == 0x4f; /* R_IA64_PCREL64LSB */
+    case EM_PARISC:
+      return reloc_type == 72; /* R_PARISC_PCREL64 */
+    case EM_PPC64:
+      return reloc_type == 44; /* R_PPC64_REL64 */
+    case EM_SPARC32PLUS:
+    case EM_SPARCV9:
+    case EM_SPARC:
+      return reloc_type == 46; /* R_SPARC_DISP64 */
+    case EM_X86_64:
+      return reloc_type == 24; /* R_X86_64_PC64 */
+    case EM_S390_OLD:
+    case EM_S390:
+      return reloc_type == 23; /* R_S390_PC64 */
     default:
       return FALSE;
     }
@@ -8206,6 +8270,7 @@ is_16bit_abs_reloc (unsigned int reloc_type)
     case EM_IP2K_OLD:
     case EM_IP2K:
       return reloc_type == 1; /* R_IP2K_16.  */
+    case EM_M32C_OLD:
     case EM_M32C:
       return reloc_type == 1; /* R_M32C_16 */
     case EM_MSP430_OLD:
@@ -8219,6 +8284,78 @@ is_16bit_abs_reloc (unsigned int reloc_type)
     }
 }
 
+/* Uncompresses a section that was compressed using zlib, in place.
+ * This is a copy of bfd_uncompress_section_contents, in bfd/compress.c  */
+
+static int
+uncompress_section_contents (unsigned char **buffer, dwarf_size_type *size)
+{
+#ifndef HAVE_ZLIB_H
+  /* These are just to quiet gcc.  */
+  buffer = 0;
+  size = 0;
+  return FALSE;
+#else
+  dwarf_size_type compressed_size = *size;
+  unsigned char* compressed_buffer = *buffer;
+  dwarf_size_type uncompressed_size;
+  unsigned char* uncompressed_buffer;
+  z_stream strm;
+  int rc;
+  dwarf_size_type header_size = 12;
+
+  /* Read the zlib header.  In this case, it should be "ZLIB" followed
+     by the uncompressed section size, 8 bytes in big-endian order.  */
+  if (compressed_size < header_size
+      || ! streq ((char*) compressed_buffer, "ZLIB"))
+    return 0;
+  uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
+  uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
+  uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
+  uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
+  uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
+  uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
+  uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
+  uncompressed_size += compressed_buffer[11];
+
+  /* It is possible the section consists of several compressed
+     buffers concatenated together, so we uncompress in a loop.  */
+  strm.zalloc = NULL;
+  strm.zfree = NULL;
+  strm.opaque = NULL;
+  strm.avail_in = compressed_size - header_size;
+  strm.next_in = (Bytef*) compressed_buffer + header_size;
+  strm.avail_out = uncompressed_size;
+  uncompressed_buffer = xmalloc (uncompressed_size);
+
+  rc = inflateInit (&strm);
+  while (strm.avail_in > 0)
+    {
+      if (rc != Z_OK)
+        goto fail;
+      strm.next_out = ((Bytef*) uncompressed_buffer
+                       + (uncompressed_size - strm.avail_out));
+      rc = inflate (&strm, Z_FINISH);
+      if (rc != Z_STREAM_END)
+        goto fail;
+      rc = inflateReset (&strm);
+    }
+  rc = inflateEnd (&strm);
+  if (rc != Z_OK
+      || strm.avail_out != 0)
+    goto fail;
+
+  free (compressed_buffer);
+  *buffer = uncompressed_buffer;
+  *size = uncompressed_size;
+  return 1;
+
+ fail:
+  free (uncompressed_buffer);
+  return 0;
+#endif  /* HAVE_ZLIB_H */
+}
+
 /* Apply relocations to a debug section.  */
 
 static void
@@ -8245,10 +8382,10 @@ debug_apply_relocations (void *file,
       Elf_Internal_Sym *sym;
 
       if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
-         || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
-         || SECTION_HEADER (relsec->sh_info) != section
+         || relsec->sh_info >= elf_header.e_shnum
+         || section_headers + relsec->sh_info != section
          || relsec->sh_size == 0
-         || SECTION_HEADER_INDEX (relsec->sh_link) >= elf_header.e_shnum)
+         || relsec->sh_link >= elf_header.e_shnum)
        continue;
 
       is_rela = relsec->sh_type == SHT_RELA;
@@ -8270,7 +8407,7 @@ debug_apply_relocations (void *file,
       if (elf_header.e_machine == EM_SH)
        is_rela = FALSE;
 
-      symsec = SECTION_HEADER (relsec->sh_link);
+      symsec = section_headers + relsec->sh_link;
       symtab = GET_ELF_SYMBOLS (file, symsec);
 
       for (rp = relocs; rp < relocs + num_relocs; ++rp)
@@ -8280,25 +8417,13 @@ debug_apply_relocations (void *file,
          unsigned int    reloc_size;
          unsigned char * loc;
 
-         /* In MIPS little-endian objects, r_info isn't really a
-            64-bit little-endian value: it has a 32-bit little-endian
-            symbol index followed by four individual byte fields.
-            Reorder INFO accordingly.  */
-         if (!is_32bit_elf
-             && elf_header.e_machine == EM_MIPS
-             && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
-           rp->r_info = (((rp->r_info & 0xffffffff) << 32)
-                         | ((rp->r_info >> 56) & 0xff)
-                         | ((rp->r_info >> 40) & 0xff00)
-                         | ((rp->r_info >> 24) & 0xff0000)
-                         | ((rp->r_info >> 8) & 0xff000000));
-
          reloc_type = get_reloc_type (rp->r_info);
 
          if (is_32bit_abs_reloc (reloc_type)
              || is_32bit_pcrel_reloc (reloc_type))
            reloc_size = 4;
-         else if (is_64bit_abs_reloc (reloc_type))
+         else if (is_64bit_abs_reloc (reloc_type)
+                  || is_64bit_pcrel_reloc (reloc_type))
            reloc_size = 8;
          else if (is_16bit_abs_reloc (reloc_type))
            reloc_size = 2;
@@ -8342,9 +8467,15 @@ debug_apply_relocations (void *file,
 
          addend = is_rela ? rp->r_addend : byte_get (loc, reloc_size);
          
-         if (is_32bit_pcrel_reloc (reloc_type))
-           byte_put (loc, (addend + sym->st_value) - rp->r_offset,
-                     reloc_size);
+         if (is_32bit_pcrel_reloc (reloc_type)
+             || is_64bit_pcrel_reloc (reloc_type))
+           {
+             /* On HPPA, all pc-relative relocations are biased by 8.  */
+             if (elf_header.e_machine == EM_PARISC)
+               addend -= 8;
+             byte_put (loc, (addend + sym->st_value) - rp->r_offset,
+                       reloc_size);
+           }
          else
            byte_put (loc, addend + sym->st_value, reloc_size);
        }
@@ -8355,32 +8486,58 @@ debug_apply_relocations (void *file,
     }
 }
 
-int
-load_debug_section (enum dwarf_section_display_enum debug, void *file)
+static int
+load_specific_debug_section (enum dwarf_section_display_enum debug,
+                            Elf_Internal_Shdr *sec, void *file)
 {
   struct dwarf_section *section = &debug_displays [debug].section;
-  Elf_Internal_Shdr *sec;
   char buf [64];
+  int section_is_compressed;
 
   /* If it is already loaded, do nothing.  */
   if (section->start != NULL)
     return 1;
 
-  /* Locate the debug section.  */
-  sec = find_section (section->name);
-  if (sec == NULL)
-    return 0;
+  section_is_compressed = section->name == section->compressed_name;
 
   snprintf (buf, sizeof (buf), _("%s section data"), section->name);
   section->address = sec->sh_addr;
   section->size = sec->sh_size;
   section->start = get_data (NULL, file, sec->sh_offset, 1,
                             sec->sh_size, buf);
+  if (section->start == NULL)
+    return 0;
+
+  if (section_is_compressed)
+    if (! uncompress_section_contents (&section->start, &section->size))
+      return 0;
 
   if (debug_displays [debug].relocate)
     debug_apply_relocations (file, sec, section->start);
 
-  return section->start != NULL;
+  return 1;
+}
+
+int
+load_debug_section (enum dwarf_section_display_enum debug, void *file)
+{
+  struct dwarf_section *section = &debug_displays [debug].section;
+  Elf_Internal_Shdr *sec;
+
+  /* Locate the debug section.  */
+  sec = find_section (section->uncompressed_name);
+  if (sec != NULL)
+    section->name = section->uncompressed_name;
+  else
+    {
+      sec = find_section (section->compressed_name);
+      if (sec != NULL)
+       section->name = section->compressed_name;
+    }
+  if (sec == NULL)
+    return 0;
+
+  return load_specific_debug_section (debug, sec, file);
 }
 
 void
@@ -8417,15 +8574,24 @@ display_debug_section (Elf_Internal_Shdr *section, FILE *file)
 
   /* See if we know how to display the contents of this section.  */
   for (i = 0; i < max; i++)
-    if (streq (debug_displays[i].section.name, name))
+    if (streq (debug_displays[i].section.uncompressed_name, name)
+        || streq (debug_displays[i].section.compressed_name, name))
       {
        struct dwarf_section *sec = &debug_displays [i].section;
+       int secondary = (section != find_section (name));
 
-       if (load_debug_section (i, file))
+       if (secondary)
+         free_debug_section (i);
+
+       if (streq (debug_displays[i].section.uncompressed_name, name))
+         sec->name = sec->uncompressed_name;
+       else
+         sec->name = sec->compressed_name;
+       if (load_specific_debug_section (i, section, file))
          {
            result &= debug_displays[i].display (sec, file);
 
-           if (i != info && i != abbrev)
+           if (secondary || (i != info && i != abbrev))
              free_debug_section (i);
          }
 
@@ -8540,8 +8706,8 @@ static const char *arm_attr_tag_CPU_arch[] =
 static const char *arm_attr_tag_ARM_ISA_use[] = {"No", "Yes"};
 static const char *arm_attr_tag_THUMB_ISA_use[] =
   {"No", "Thumb-1", "Thumb-2"};
-/* FIXME: VFPv3 encoding was extrapolated!  */
-static const char *arm_attr_tag_VFP_arch[] = {"No", "VFPv1", "VFPv2", "VFPv3"};
+static const char *arm_attr_tag_VFP_arch[] =
+  {"No", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16"};
 static const char *arm_attr_tag_WMMX_arch[] = {"No", "WMMXv1"};
 static const char *arm_attr_tag_NEON_arch[] = {"No", "NEONv1"};
 static const char *arm_attr_tag_ABI_PCS_config[] =
@@ -8810,6 +8976,9 @@ display_power_gnu_attribute (unsigned char *p, int tag)
        case 2:
          printf ("Soft float\n");
          break;
+       case 3:
+         printf ("Single-precision hard float\n");
+         break;
        default:
          printf ("??? (%d)\n", val);
          break;
@@ -9078,6 +9247,55 @@ process_power_specific (FILE *file)
                             display_power_gnu_attribute);
 }
 
+/* DATA points to the contents of a MIPS GOT that starts at VMA PLTGOT.
+   Print the Address, Access and Initial fields of an entry at VMA ADDR
+   and return the VMA of the next entry.  */
+
+static bfd_vma
+print_mips_got_entry (unsigned char *data, bfd_vma pltgot, bfd_vma addr)
+{
+  printf ("  ");
+  print_vma (addr, LONG_HEX);
+  printf (" ");
+  if (addr < pltgot + 0xfff0)
+    printf ("%6d(gp)", (int) (addr - pltgot - 0x7ff0));
+  else
+    printf ("%10s", "");
+  printf (" ");
+  if (data == NULL)
+    printf ("%*s", is_32bit_elf ? 8 : 16, "<unknown>");
+  else
+    {
+      bfd_vma entry;
+
+      entry = byte_get (data + addr - pltgot, is_32bit_elf ? 4 : 8);
+      print_vma (entry, LONG_HEX);
+    }
+  return addr + (is_32bit_elf ? 4 : 8);
+}
+
+/* DATA points to the contents of a MIPS PLT GOT that starts at VMA
+   PLTGOT.  Print the Address and Initial fields of an entry at VMA
+   ADDR and return the VMA of the next entry.  */
+
+static bfd_vma
+print_mips_pltgot_entry (unsigned char *data, bfd_vma pltgot, bfd_vma addr)
+{
+  printf ("  ");
+  print_vma (addr, LONG_HEX);
+  printf (" ");
+  if (data == NULL)
+    printf ("%*s", is_32bit_elf ? 8 : 16, "<unknown>");
+  else
+    {
+      bfd_vma entry;
+
+      entry = byte_get (data + addr - pltgot, is_32bit_elf ? 4 : 8);
+      print_vma (entry, LONG_HEX);
+    }
+  return addr + (is_32bit_elf ? 4 : 8);
+}
+
 static int
 process_mips_specific (FILE *file)
 {
@@ -9087,6 +9305,14 @@ process_mips_specific (FILE *file)
   size_t conflictsno = 0;
   size_t options_offset = 0;
   size_t conflicts_offset = 0;
+  size_t pltrelsz = 0;
+  size_t pltrel = 0;
+  bfd_vma pltgot = 0;
+  bfd_vma mips_pltgot = 0;
+  bfd_vma jmprel = 0;
+  bfd_vma local_gotno = 0;
+  bfd_vma gotsym = 0;
+  bfd_vma symtabno = 0;
 
   process_attributes (file, NULL, SHT_GNU_ATTRIBUTES, NULL,
                      display_mips_gnu_attribute);
@@ -9118,6 +9344,30 @@ process_mips_specific (FILE *file)
       case DT_MIPS_CONFLICTNO:
        conflictsno = entry->d_un.d_val;
        break;
+      case DT_PLTGOT:
+       pltgot = entry->d_un.d_ptr;
+       break;
+      case DT_MIPS_LOCAL_GOTNO:
+       local_gotno = entry->d_un.d_val;
+       break;
+      case DT_MIPS_GOTSYM:
+       gotsym = entry->d_un.d_val;
+       break;
+      case DT_MIPS_SYMTABNO:
+       symtabno = entry->d_un.d_val;
+       break;
+      case DT_MIPS_PLTGOT:
+       mips_pltgot = entry->d_un.d_ptr;
+       break;
+      case DT_PLTREL:
+       pltrel = entry->d_un.d_val;
+       break;
+      case DT_PLTRELSZ:
+       pltrelsz = entry->d_un.d_val;
+       break;
+      case DT_JMPREL:
+       jmprel = entry->d_un.d_ptr;
+       break;
       default:
        break;
       }
@@ -9468,6 +9718,155 @@ process_mips_specific (FILE *file)
       free (iconf);
     }
 
+  if (pltgot != 0 && local_gotno != 0)
+    {
+      bfd_vma entry, local_end, global_end;
+      size_t i, offset;
+      unsigned char *data;
+      int addr_size;
+
+      entry = pltgot;
+      addr_size = (is_32bit_elf ? 4 : 8);
+      local_end = pltgot + local_gotno * addr_size;
+      global_end = local_end + (symtabno - gotsym) * addr_size;
+
+      offset = offset_from_vma (file, pltgot, global_end - pltgot);
+      data = get_data (NULL, file, offset, global_end - pltgot, 1, _("GOT"));
+      printf (_("\nPrimary GOT:\n"));
+      printf (_(" Canonical gp value: "));
+      print_vma (pltgot + 0x7ff0, LONG_HEX);
+      printf ("\n\n");
+
+      printf (_(" Reserved entries:\n"));
+      printf (_("  %*s %10s %*s Purpose\n"),
+             addr_size * 2, "Address", "Access",
+             addr_size * 2, "Initial");
+      entry = print_mips_got_entry (data, pltgot, entry);
+      printf (" Lazy resolver\n");
+      if (data
+         && (byte_get (data + entry - pltgot, addr_size)
+             >> (addr_size * 8 - 1)) != 0)
+       {
+         entry = print_mips_got_entry (data, pltgot, entry);
+         printf (" Module pointer (GNU extension)\n");
+       }
+      printf ("\n");
+
+      if (entry < local_end)
+       {
+         printf (_(" Local entries:\n"));
+         printf (_("  %*s %10s %*s\n"),
+                 addr_size * 2, "Address", "Access",
+                 addr_size * 2, "Initial");
+         while (entry < local_end)
+           {
+             entry = print_mips_got_entry (data, pltgot, entry);
+             printf ("\n");
+           }
+         printf ("\n");
+       }
+
+      if (gotsym < symtabno)
+       {
+         int sym_width;
+
+         printf (_(" Global entries:\n"));
+         printf (_("  %*s %10s %*s %*s %-7s %3s %s\n"),
+                 addr_size * 2, "Address", "Access",
+                 addr_size * 2, "Initial",
+                 addr_size * 2, "Sym.Val.", "Type", "Ndx", "Name");
+         sym_width = (is_32bit_elf ? 80 : 160) - 28 - addr_size * 6 - 1;
+         for (i = gotsym; i < symtabno; i++)
+           {
+             Elf_Internal_Sym *psym;
+
+             psym = dynamic_symbols + i;
+             entry = print_mips_got_entry (data, pltgot, entry);
+             printf (" ");
+             print_vma (psym->st_value, LONG_HEX);
+             printf (" %-7s %3s ",
+                     get_symbol_type (ELF_ST_TYPE (psym->st_info)),
+                     get_symbol_index_type (psym->st_shndx));
+             if (VALID_DYNAMIC_NAME (psym->st_name))
+               print_symbol (sym_width, GET_DYNAMIC_NAME (psym->st_name));
+             else
+               printf ("<corrupt: %14ld>", psym->st_name);
+             printf ("\n");
+           }
+         printf ("\n");
+       }
+
+      if (data)
+       free (data);
+    }
+
+  if (mips_pltgot != 0 && jmprel != 0 && pltrel != 0 && pltrelsz != 0)
+    {
+      bfd_vma entry, end;
+      size_t offset, rel_offset;
+      unsigned long count, i;
+      unsigned char *data;
+      int addr_size, sym_width;
+      Elf_Internal_Rela *rels;
+
+      rel_offset = offset_from_vma (file, jmprel, pltrelsz);
+      if (pltrel == DT_RELA)
+       {
+         if (!slurp_rela_relocs (file, rel_offset, pltrelsz, &rels, &count))
+           return 0;
+       }
+      else
+       {
+         if (!slurp_rel_relocs (file, rel_offset, pltrelsz, &rels, &count))
+           return 0;
+       }
+
+      entry = mips_pltgot;
+      addr_size = (is_32bit_elf ? 4 : 8);
+      end = mips_pltgot + (2 + count) * addr_size;
+
+      offset = offset_from_vma (file, mips_pltgot, end - mips_pltgot);
+      data = get_data (NULL, file, offset, end - mips_pltgot, 1, _("PLT GOT"));
+      printf (_("\nPLT GOT:\n\n"));
+      printf (_(" Reserved entries:\n"));
+      printf (_("  %*s %*s Purpose\n"),
+             addr_size * 2, "Address", addr_size * 2, "Initial");
+      entry = print_mips_pltgot_entry (data, mips_pltgot, entry);
+      printf (" PLT lazy resolver\n");
+      entry = print_mips_pltgot_entry (data, mips_pltgot, entry);
+      printf (" Module pointer\n");
+      printf ("\n");
+
+      printf (_(" Entries:\n"));
+      printf (_("  %*s %*s %*s %-7s %3s %s\n"),
+             addr_size * 2, "Address",
+             addr_size * 2, "Initial",
+             addr_size * 2, "Sym.Val.", "Type", "Ndx", "Name");
+      sym_width = (is_32bit_elf ? 80 : 160) - 17 - addr_size * 6 - 1;
+      for (i = 0; i < count; i++)
+       {
+         Elf_Internal_Sym *psym;
+
+         psym = dynamic_symbols + get_reloc_symindex (rels[i].r_info);
+         entry = print_mips_pltgot_entry (data, mips_pltgot, entry);
+         printf (" ");
+         print_vma (psym->st_value, LONG_HEX);
+         printf (" %-7s %3s ",
+                 get_symbol_type (ELF_ST_TYPE (psym->st_info)),
+                 get_symbol_index_type (psym->st_shndx));
+         if (VALID_DYNAMIC_NAME (psym->st_name))
+           print_symbol (sym_width, GET_DYNAMIC_NAME (psym->st_name));
+         else
+           printf ("<corrupt: %14ld>", psym->st_name);
+         printf ("\n");
+       }
+      printf ("\n");
+
+      if (data)
+       free (data);
+      free (rels);
+    }
+
   return 1;
 }
 
@@ -9491,7 +9890,7 @@ process_gnu_liblist (FILE *file)
       switch (section->sh_type)
        {
        case SHT_GNU_LIBLIST:
-         if (SECTION_HEADER_INDEX (section->sh_link) >= elf_header.e_shnum)
+         if (section->sh_link >= elf_header.e_shnum)
            break;
 
          elib = get_data (NULL, file, section->sh_offset, 1, section->sh_size,
@@ -9499,7 +9898,7 @@ process_gnu_liblist (FILE *file)
 
          if (elib == NULL)
            break;
-         string_sec = SECTION_HEADER (section->sh_link);
+         string_sec = section_headers + section->sh_link;
 
          strtab = get_data (NULL, file, string_sec->sh_offset, 1,
                             string_sec->sh_size, _("liblist string table"));
@@ -9514,7 +9913,7 @@ process_gnu_liblist (FILE *file)
 
          printf (_("\nLibrary list section '%s' contains %lu entries:\n"),
                  SECTION_NAME (section),
-                 (long) (section->sh_size / sizeof (Elf32_External_Lib)));
+                 (unsigned long) (section->sh_size / sizeof (Elf32_External_Lib)));
 
          puts ("     Library              Time Stamp          Checksum   Version Flags");
 
@@ -9578,6 +9977,8 @@ get_note_type (unsigned e_type)
        return _("NT_PRXFPREG (user_xfpregs structure)");
       case NT_PPC_VMX:
        return _("NT_PPC_VMX (ppc Altivec registers)");
+      case NT_PPC_VSX:
+       return _("NT_PPC_VSX (ppc VSX registers)");
       case NT_PSTATUS:
        return _("NT_PSTATUS (pstatus structure)");
       case NT_FPREGS:
@@ -9621,6 +10022,8 @@ get_gnu_elf_note_type (unsigned e_type)
       return _("NT_GNU_HWCAP (DSO-supplied software HWCAP info)");
     case NT_GNU_BUILD_ID:
       return _("NT_GNU_BUILD_ID (unique build ID bitstring)");
+    case NT_GNU_GOLD_VERSION:
+      return _("NT_GNU_GOLD_VERSION (gold version)");
     default:
       break;
     }
@@ -9770,7 +10173,7 @@ process_corefile_note_segment (FILE *file, bfd_vma offset, bfd_vma length)
       if (((char *) next) > (((char *) pnotes) + length))
        {
          warn (_("corrupt note found at offset %lx into core notes\n"),
-               (long)((char *)external - (char *)pnotes));
+               (unsigned long) ((char *) external - (char *) pnotes));
          warn (_(" type: %lx, namesize: %08lx, descsize: %08lx\n"),
                inote.type, inote.namesz, inote.descsz);
          break;