bfd/
[deliverable/binutils-gdb.git] / binutils / readelf.c
index 3498b30ba64bb755d0b4be72d4914e484d562021..236816d72974d678d2718262f24133f1ccbf1ba8 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
@@ -368,177 +372,44 @@ 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)
-    {
-      vma = -vma;
-      putchar ('-');
-      nc = 1;
-    }
-
-  do
+  switch (mode)
     {
-      *bufp++ = '0' + vma % 10;
-      vma /= 10;
-    }
-  while (vma != 0);
-  nc += bufp - buf;
-
-  while (bufp > buf)
-    putchar (*--bufp);
-  return nc;
-}
-
-static int
-print_hex_vma (bfd_vma vma)
-{
-  char buf[32];
-  char *bufp = buf;
-  int nc;
+    case FULL_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;
-
-  while (bufp > buf)
-    putchar (*--bufp);
-  return nc;
-}
-#endif
-
-/* Print a VMA value.  */
-static int
-print_vma (bfd_vma vma, print_mode mode)
-{
+    case LONG_HEX:
 #ifdef BFD64
-  if (is_32bit_elf)
+      if (is_32bit_elf)
+       return nc + printf ("%08.8" BFD_VMA_FMT "x", vma);
 #endif
-    {
-      switch (mode)
-       {
-       case FULL_HEX:
-         return printf ("0x%8.8lx", (unsigned long) vma);
+      printf_vma (vma);
+      return nc + 16;
 
-       case LONG_HEX:
-         return printf ("%8.8lx", (unsigned long) vma);
+    case DEC_5:
+      if (vma <= 99999)
+       return printf ("%5" BFD_VMA_FMT "d", vma);
+      /* Drop through.  */
 
-       case DEC_5:
-         if (vma <= 99999)
-           return printf ("%5ld", (long) vma);
-         /* Drop through.  */
+    case PREFIX_HEX:
+      nc = printf ("0x");
+      /* Drop through.  */
 
-       case PREFIX_HEX:
-         return printf ("0x%lx", (unsigned long) vma);
+    case HEX:
+      return nc + printf ("%" BFD_VMA_FMT "x", vma);
 
-       case HEX:
-         return printf ("%lx", (unsigned long) vma);
+    case DEC:
+      return printf ("%" BFD_VMA_FMT "d", vma);
 
-       case DEC:
-         return printf ("%ld", (unsigned long) vma);
-
-       case UNSIGNED:
-         return printf ("%lu", (unsigned long) vma);
-       }
+    case UNSIGNED:
+      return printf ("%" BFD_VMA_FMT "u", vma);
     }
-#ifdef BFD64
-  else
-    {
-      int nc = 0;
-
-      switch (mode)
-       {
-       case FULL_HEX:
-         nc = printf ("0x");
-         /* Drop through.  */
-
-       case LONG_HEX:
-         printf_vma (vma);
-         return nc + 16;
-
-       case PREFIX_HEX:
-         nc = printf ("0x");
-         /* Drop through.  */
-
-       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
-
-       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
-
-       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
-       }
-    }
-#endif
   return 0;
 }
 
@@ -703,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:
@@ -717,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:
@@ -1280,6 +1153,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;
@@ -1297,6 +1171,7 @@ dump_relocations (FILE *file,
          break;
 
        case EM_CR16:
+       case EM_CR16_OLD:
          rtype = elf_cr16_reloc_type (type);
          break;
        }
@@ -1914,6 +1789,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";
@@ -1921,7 +1797,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;
@@ -4300,6 +4177,7 @@ process_section_headers (FILE *file)
        }
       break;
 
+    case EM_M32C_OLD:
     case EM_M32C:
       switch (elf_header.e_flags & EF_M32C_CPU_MASK)
        {
@@ -4378,9 +4256,13 @@ process_section_headers (FILE *file)
                || 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, ".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"))
@@ -8125,6 +8007,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.  */
@@ -8152,6 +8035,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:
@@ -8326,6 +8210,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:
@@ -8339,6 +8224,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
@@ -8481,26 +8438,42 @@ load_debug_section (enum dwarf_section_display_enum debug, 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);
+  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;
+  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;
 }
 
 void
@@ -8537,7 +8510,8 @@ 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;
 
@@ -8930,6 +8904,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;
@@ -9822,6 +9799,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:
This page took 0.032043 seconds and 4 git commands to generate.