Only decode 64bit ELF files if the host compiler supports a 64bit data type.

This commit is contained in:
Nick Clifton 1999-07-09 03:14:15 +00:00
parent 99f8f232c6
commit a952a37550
2 changed files with 64 additions and 7 deletions

View file

@ -1,3 +1,10 @@
1999-07-09 Nick Clifton <nickc@cygnus.com>
* readelf.c: Only support decoding 64bit ELF files if the compiler
supports a 64 bit data type.
Add -I equivalent for --histogram.
Add -A command-line option to display architecture specific information.
1999-07-08 Jakub Jelinek <jj@ultra.linux.cz> 1999-07-08 Jakub Jelinek <jj@ultra.linux.cz>
* readelf.c (guess_is_rela): Sparcv9 and v8plus use rela. * readelf.c (guess_is_rela): Sparcv9 and v8plus use rela.

View file

@ -27,9 +27,14 @@
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#if __GNUC__ >= 2
/* Define BFD64 here, even if our default architecture is 32 bit ELF /* 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 #define BFD64
#endif
#include "bfd.h" #include "bfd.h"
#include "elf/common.h" #include "elf/common.h"
@ -108,6 +113,7 @@ int do_debug_abbrevs;
int do_debug_lines; int do_debug_lines;
int do_debug_pubnames; int do_debug_pubnames;
int do_debug_aranges; int do_debug_aranges;
int do_arch;
int is_32bit_elf; int is_32bit_elf;
/* A dynamic array of flags indicating which sections require dumping. */ /* 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 DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
#define BYTE_GET(field) byte_get (field, sizeof (field)) #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) #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])) #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 [2])) << 16)
| (((unsigned long) (field [3])) << 24); | (((unsigned long) (field [3])) << 24);
#ifdef BFD64
case -8: case -8:
/* This is a special case, generated by the BYTE_GET8 macro. /* This is a special case, generated by the BYTE_GET8 macro.
It means that we are loading an 8 byte value from a field 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 [5])) << 40)
| (((bfd_vma) (field [6])) << 48) | (((bfd_vma) (field [6])) << 48)
| (((bfd_vma) (field [7])) << 56); | (((bfd_vma) (field [7])) << 56);
#endif
default: default:
error (_("Unhandled data length: %d\n"), size); error (_("Unhandled data length: %d\n"), size);
abort (); abort ();
@ -373,6 +393,7 @@ byte_get_big_endian (field, size)
| (((unsigned long) (field [5])) << 16) | (((unsigned long) (field [5])) << 16)
| (((unsigned long) (field [4])) << 24); | (((unsigned long) (field [4])) << 24);
#ifdef BFD64
case -8: case -8:
/* This is a special case, generated by the BYTE_GET8 macro. /* This is a special case, generated by the BYTE_GET8 macro.
It means that we are loading an 8 byte value from a field 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 [2])) << 40)
| (((bfd_vma) (field [1])) << 48) | (((bfd_vma) (field [1])) << 48)
| (((bfd_vma) (field [0])) << 56); | (((bfd_vma) (field [0])) << 56);
#endif
default: default:
error (_("Unhandled data length: %d\n"), size); 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); type = ELF64_R_TYPE_ID (info);
else else
type = ELF64_R_TYPE (info); type = ELF64_R_TYPE (info);
/* The #ifdef BFD64 below is to prevent a compile time warning.
We know that if we do not have a 64 bit data type that we
will never execute this code anyway. */
#ifdef BFD64
symtab_index = ELF64_R_SYM (info); symtab_index = ELF64_R_SYM (info);
#endif
} }
#ifdef _bfd_int64_low #ifdef _bfd_int64_low
@ -1282,7 +1309,7 @@ struct option options [] =
{"file-header", no_argument, 0, 'h'}, {"file-header", no_argument, 0, 'h'},
{"program-headers", no_argument, 0, 'l'}, {"program-headers", no_argument, 0, 'l'},
{"headers", no_argument, 0, 'e'}, {"headers", no_argument, 0, 'e'},
{"histogram", no_argument, & do_histogram, 1}, {"histogram", no_argument, 0, 'I'},
{"segments", no_argument, 0, 'l'}, {"segments", no_argument, 0, 'l'},
{"sections", no_argument, 0, 'S'}, {"sections", no_argument, 0, 'S'},
{"section-headers", no_argument, 0, 'S'}, {"section-headers", no_argument, 0, 'S'},
@ -1290,6 +1317,7 @@ struct option options [] =
{"syms", no_argument, 0, 's'}, {"syms", no_argument, 0, 's'},
{"relocs", no_argument, 0, 'r'}, {"relocs", no_argument, 0, 'r'},
{"dynamic", no_argument, 0, 'd'}, {"dynamic", no_argument, 0, 'd'},
{"arch-specific", no_argument, 0, 'A'},
{"version-info", no_argument, 0, 'V'}, {"version-info", no_argument, 0, 'V'},
{"use-dynamic", no_argument, 0, 'D'}, {"use-dynamic", no_argument, 0, 'D'},
{"hex-dump", required_argument, 0, 'x'}, {"hex-dump", required_argument, 0, 'x'},
@ -1308,7 +1336,7 @@ usage ()
{ {
fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n")); fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n"));
fprintf (stdout, _(" Options are:\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, _(" -h or --file-header Display the ELF file header\n"));
fprintf (stdout, _(" -l or --program-headers or --segments\n")); fprintf (stdout, _(" -l or --program-headers or --segments\n"));
fprintf (stdout, _(" Display the program headers\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, _(" -r or --relocs Display the relocations (if present)\n"));
fprintf (stdout, _(" -d or --dynamic Display the dynamic segment (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, _(" -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, _(" -D or --use-dynamic Use the dynamic section info when displaying symbols\n"));
fprintf (stdout, _(" -x <number> or --hex-dump=<number>\n")); fprintf (stdout, _(" -x <number> or --hex-dump=<number>\n"));
fprintf (stdout, _(" Dump the contents of section <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, _(" -i <number> or --instruction-dump=<number>\n"));
fprintf (stdout, _(" Disassemble the contents of section <number>\n")); fprintf (stdout, _(" Disassemble the contents of section <number>\n"));
#endif #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, _(" -v or --version Display the version number of readelf\n"));
fprintf (stdout, _(" -H or --help Display this information\n")); fprintf (stdout, _(" -H or --help Display this information\n"));
fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n")); fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n"));
@ -1378,7 +1407,7 @@ parse_args (argc, argv)
usage (); usage ();
while ((c = getopt_long while ((c = getopt_long
(argc, argv, "ersahldSDw::x:i:vV", options, NULL)) != EOF) (argc, argv, "ersahldSDAIw::x:i:vV", options, NULL)) != EOF)
{ {
char * cp; char * cp;
int section; int section;
@ -1401,12 +1430,16 @@ parse_args (argc, argv)
do_segments ++; do_segments ++;
do_version ++; do_version ++;
do_histogram ++; do_histogram ++;
do_arch ++;
break; break;
case 'e': case 'e':
do_header ++; do_header ++;
do_sections ++; do_sections ++;
do_segments ++; do_segments ++;
break; break;
case 'A':
do_arch ++;
break;
case 'D': case 'D':
do_using_dynamic ++; do_using_dynamic ++;
break; break;
@ -1428,6 +1461,9 @@ parse_args (argc, argv)
case 'd': case 'd':
do_dynamic ++; do_dynamic ++;
break; break;
case 'I':
do_histogram ++;
break;
case 'x': case 'x':
do_dump ++; do_dump ++;
section = strtoul (optarg, & cp, 0); section = strtoul (optarg, & cp, 0);
@ -1506,7 +1542,7 @@ parse_args (argc, argv)
if (!do_dynamic && !do_syms && !do_reloc && !do_sections if (!do_dynamic && !do_syms && !do_reloc && !do_sections
&& !do_segments && !do_header && !do_dump && !do_version && !do_segments && !do_header && !do_dump && !do_version
&& !do_histogram && !do_debugging) && !do_histogram && !do_debugging && !do_arch)
usage (); usage ();
else if (argc < 3) else if (argc < 3)
{ {
@ -6229,6 +6265,9 @@ static int
process_arch_specific (file) process_arch_specific (file)
FILE * file; FILE * file;
{ {
if (! do_arch)
return 1;
switch (elf_header.e_machine) switch (elf_header.e_machine)
{ {
case EM_MIPS: case EM_MIPS:
@ -6286,6 +6325,17 @@ get_file_header (file)
else else
{ {
Elf64_External_Ehdr ehdr64; 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) if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT, 1, file) != 1)
return 0; return 0;