Only decode 64bit ELF files if the host compiler supports a 64bit data type.
[deliverable/binutils-gdb.git] / binutils / readelf.c
index 84f73f13b73df8b3067bb52caee64c083d021b4b..3c613a6fa4c6ed5ef37f6b339c9328f4ce61ebe6 100644 (file)
 #include <stdio.h>
 #include <time.h>
 
+#if __GNUC__ >= 2
 /* Define BFD64 here, even if our default architecture is 32 bit ELF
-   as this will allow us to read in and parse 64bit and 32bit ELF files.  */
+   as this will allow us to read in and parse 64bit and 32bit ELF files.
+   Only do this if we belive that the compiler can support a 64 bit
+   data type.  For now we only rely on GCC being able to do this.  */
 #define BFD64
+#endif
+
 #include "bfd.h"
 
 #include "elf/common.h"
@@ -108,6 +113,7 @@ int                     do_debug_abbrevs;
 int                     do_debug_lines;
 int                     do_debug_pubnames;
 int                     do_debug_aranges;
+int                     do_arch;
 int                    is_32bit_elf;
 
 /* A dynamic array of flags indicating which sections require dumping.  */
@@ -200,7 +206,20 @@ typedef int Elf32_Word;
 #define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag)) /* Reverse order! */
 
 #define BYTE_GET(field)        byte_get (field, sizeof (field))
+
+/* If we can support a 64 bit data type then BFD64 should be defined
+   and sizeof (bfd_vma) == 8.  In this case when translating from an
+   external 8 byte field to an internal field, we can assume that the
+   internal field is also 8 bytes wide and so we can extact all the data.
+   If, however, BFD64 is not defined, then we must assume that the
+   internal data structure only has 4 byte wide fields that are the
+   equivalent of the 8 byte wide external counterparts, and so we must
+   truncate the data.  */
+#ifdef  BFD64
 #define BYTE_GET8(field)       byte_get (field, -8)
+#else
+#define BYTE_GET8(field)       byte_get (field, 8)
+#endif
 
 #define NUM_ELEM(array)        (sizeof (array) / sizeof ((array)[0]))
 
@@ -326,6 +345,7 @@ byte_get_little_endian (field, size)
        |    (((unsigned long) (field [2])) << 16)
        |    (((unsigned long) (field [3])) << 24);
 
+#ifdef BFD64
     case -8:
       /* This is a special case, generated by the BYTE_GET8 macro.
         It means that we are loading an 8 byte value from a field
@@ -339,7 +359,7 @@ byte_get_little_endian (field, size)
        |    (((bfd_vma) (field [5])) << 40)
        |    (((bfd_vma) (field [6])) << 48)
        |    (((bfd_vma) (field [7])) << 56);
-
+#endif
     default:
       error (_("Unhandled data length: %d\n"), size);
       abort ();
@@ -373,6 +393,7 @@ byte_get_big_endian (field, size)
        |   (((unsigned long) (field [5])) << 16)
        |   (((unsigned long) (field [4])) << 24);
 
+#ifdef BFD64
     case -8:
       /* This is a special case, generated by the BYTE_GET8 macro.
         It means that we are loading an 8 byte value from a field
@@ -386,6 +407,7 @@ byte_get_big_endian (field, size)
        |   (((bfd_vma) (field [2])) << 40)
        |   (((bfd_vma) (field [1])) << 48)
        |   (((bfd_vma) (field [0])) << 56);
+#endif
       
     default:
       error (_("Unhandled data length: %d\n"), size);
@@ -611,7 +633,12 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
            type       = ELF64_R_TYPE_ID (info);
          else
            type       = ELF64_R_TYPE (info);
+         /* The #ifdef BFD64 below is to prevent a compile time warning.
+            We know that if we do not have a 64 bit data type that we
+            will never execute this code anyway.  */
+#ifdef BFD64 
          symtab_index = ELF64_R_SYM  (info);
+#endif
        }
 
 #ifdef _bfd_int64_low
@@ -1282,7 +1309,7 @@ struct option options [] =
   {"file-header",      no_argument, 0, 'h'},
   {"program-headers",  no_argument, 0, 'l'},
   {"headers",          no_argument, 0, 'e'},
-  {"histogram",        no_argument, & do_histogram, 1},
+  {"histogram",        no_argument, 0, 'I'},
   {"segments",         no_argument, 0, 'l'},
   {"sections",         no_argument, 0, 'S'},
   {"section-headers",  no_argument, 0, 'S'},
@@ -1290,6 +1317,7 @@ struct option options [] =
   {"syms",             no_argument, 0, 's'},
   {"relocs",           no_argument, 0, 'r'},
   {"dynamic",          no_argument, 0, 'd'},
+  {"arch-specific",    no_argument, 0, 'A'},
   {"version-info",     no_argument, 0, 'V'},
   {"use-dynamic",      no_argument, 0, 'D'},
   {"hex-dump",         required_argument, 0, 'x'},
@@ -1308,7 +1336,7 @@ usage ()
 {
   fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n"));
   fprintf (stdout, _("  Options are:\n"));
-  fprintf (stdout, _("  -a or --all               Equivalent to: -h -l -S -s -r -d -V --histogram\n"));
+  fprintf (stdout, _("  -a or --all               Equivalent to: -h -l -S -s -r -d -V -A -I\n"));
   fprintf (stdout, _("  -h or --file-header       Display the ELF file header\n"));
   fprintf (stdout, _("  -l or --program-headers or --segments\n"));
   fprintf (stdout, _("                            Display the program headers\n"));
@@ -1319,6 +1347,7 @@ usage ()
   fprintf (stdout, _("  -r or --relocs            Display the relocations (if present)\n"));
   fprintf (stdout, _("  -d or --dynamic           Display the dynamic segment (if present)\n"));
   fprintf (stdout, _("  -V or --version-info      Display the version sections (if present)\n"));
+  fprintf (stdout, _("  -A or --arch-specific     Display architecture specific information (if any).\n"));
   fprintf (stdout, _("  -D or --use-dynamic       Use the dynamic section info when displaying symbols\n"));
   fprintf (stdout, _("  -x <number> or --hex-dump=<number>\n"));
   fprintf (stdout, _("                            Dump the contents of section <number>\n"));
@@ -1328,7 +1357,7 @@ usage ()
   fprintf (stdout, _("  -i <number> or --instruction-dump=<number>\n"));
   fprintf (stdout, _("                            Disassemble the contents of section <number>\n"));
 #endif
-  fprintf (stdout, _("        --histogram         Display histogram of bucket list lengths\n"));
+  fprintf (stdout, _("  -I or --histogram         Display histogram of bucket list lengths\n"));
   fprintf (stdout, _("  -v or --version           Display the version number of readelf\n"));
   fprintf (stdout, _("  -H or --help              Display this information\n"));
   fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n"));
@@ -1378,7 +1407,7 @@ parse_args (argc, argv)
     usage ();
 
   while ((c = getopt_long
-         (argc, argv, "ersahldSDw::x:i:vV", options, NULL)) != EOF)
+         (argc, argv, "ersahldSDAIw::x:i:vV", options, NULL)) != EOF)
     {
       char *    cp;
       int      section;
@@ -1401,12 +1430,16 @@ parse_args (argc, argv)
          do_segments ++;
          do_version ++;
          do_histogram ++;
+         do_arch ++;
          break;
        case 'e':
          do_header ++;
          do_sections ++;
          do_segments ++;
          break;
+       case 'A':
+         do_arch ++;
+         break;
        case 'D':
          do_using_dynamic ++;
          break;
@@ -1428,6 +1461,9 @@ parse_args (argc, argv)
        case 'd':
          do_dynamic ++;
          break;
+       case 'I':
+         do_histogram ++;
+         break;
        case 'x':
          do_dump ++;
          section = strtoul (optarg, & cp, 0);
@@ -1506,7 +1542,7 @@ parse_args (argc, argv)
 
   if (!do_dynamic && !do_syms && !do_reloc && !do_sections
       && !do_segments && !do_header && !do_dump && !do_version
-      && !do_histogram && !do_debugging)
+      && !do_histogram && !do_debugging && !do_arch)
     usage ();
   else if (argc < 3)
     {
@@ -6229,6 +6265,9 @@ static int
 process_arch_specific (file)
      FILE * file;
 {
+  if (! do_arch)
+    return 1;
+
   switch (elf_header.e_machine)
     {
     case EM_MIPS:
@@ -6286,6 +6325,17 @@ get_file_header (file)
   else
     {
       Elf64_External_Ehdr ehdr64;
+
+      /* If we have been compiled with sizeof (bfd_vma) == 4, then
+        we will not be able to cope with the 64bit data found in
+        64 ELF files.  Detect this now and abort before we start
+        overwritting things.  */
+      if (sizeof (bfd_vma) < 8)
+       {
+         error (_("This instance of readelf has been built without support for a\n"));
+         error (_("64 bit data type and so it cannot read 64 bit ELF files.\n"));
+         return 0;
+       }
       
       if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT, 1, file) != 1)
        return 0;
This page took 0.02602 seconds and 4 git commands to generate.