]> 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 e9c380ff3a58ff70802fc1adeba0a5291cbec3f2..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;
@@ -306,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;
     }
 
@@ -368,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);
+
+    case DEC:
+      return printf ("%" BFD_VMA_FMT "d", vma);
 
-  while (bufp > buf)
-    putchar (*--bufp);
-  return nc;
+    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.  */
-
-       case LONG_HEX:
-         printf_vma (vma);
-         return nc + 16;
+         if (len > width)
+           len = width;
+         
+         printf (format_string, len, symbol);
 
-       case PREFIX_HEX:
-         nc = printf ("0x");
-         /* Drop through.  */
+         width -= len;
+       }
 
-       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
+      if (* c == 0 || width == 0)
+       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
+      /* 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_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
+         printf ("^%c", *c + 0x40);
 
-       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
@@ -637,6 +574,7 @@ guess_is_rela (unsigned int 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:
@@ -651,6 +589,7 @@ guess_is_rela (unsigned int 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:
@@ -768,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);
@@ -840,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);
@@ -956,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);
 
@@ -1214,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;
@@ -1231,6 +1195,7 @@ dump_relocations (FILE *file,
          break;
 
        case EM_CR16:
+       case EM_CR16_OLD:
          rtype = elf_cr16_reloc_type (type);
          break;
        }
@@ -1425,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;
     }
@@ -1848,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";
@@ -1855,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;
@@ -2426,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:
@@ -2880,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, _("\
@@ -3083,6 +3052,10 @@ parse_args (int argc, char **argv)
                    do_debug_lines = 1;
                    break;
 
+                 case 'L':
+                   do_debug_lines_decoded = 1;
+                   break;
+
                  case 'p':
                    do_debug_pubnames = 1;
                    break;
@@ -3141,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 },
@@ -3676,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);
 
@@ -3720,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;
 }
 
@@ -4228,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)
        {
@@ -4303,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"))
@@ -4324,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);
@@ -5731,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);
     }
 }
 
@@ -7065,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;
     }
 }
@@ -8052,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.  */
@@ -8079,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:
@@ -8171,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:
@@ -8227,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;
     }
@@ -8253,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:
@@ -8266,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
@@ -8327,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;
@@ -8389,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);
        }
@@ -8402,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
@@ -8464,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 (secondary)
+         free_debug_section (i);
 
-       if (load_debug_section (i, file))
+       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);
          }
 
@@ -8857,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;
@@ -9125,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)
 {
@@ -9134,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);
@@ -9165,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;
       }
@@ -9515,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;
 }
 
@@ -9561,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");
 
@@ -9625,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:
@@ -9668,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;
     }
@@ -9817,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;