aboutsummaryrefslogtreecommitdiff
path: root/binutils/readelf.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils/readelf.c')
-rw-r--r--binutils/readelf.c64
1 files changed, 57 insertions, 7 deletions
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 84f73f1..3c613a6 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -27,9 +27,14 @@
#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;