aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binutils/.Sanitize30
-rw-r--r--binutils/Makefile.am16
-rw-r--r--binutils/Makefile.in29
-rw-r--r--binutils/binutils.texi108
-rw-r--r--binutils/readelf.c2254
-rw-r--r--binutils/readelf.h173
6 files changed, 2597 insertions, 13 deletions
diff --git a/binutils/.Sanitize b/binutils/.Sanitize
index be27465..f3166da 100644
--- a/binutils/.Sanitize
+++ b/binutils/.Sanitize
@@ -90,6 +90,8 @@ rclex.l
rcparse.y
rdcoff.c
rddbg.c
+readelf.c
+readelf.h
resbin.c
rescoff.c
resrc.c
@@ -122,6 +124,34 @@ Things-to-lose:
Do-last:
+v850e_files="readelf.c"
+if ( echo $* | grep keep\-v850e > /dev/null ) ; then
+ for i in $v850e_files ; do
+ if test ! -d $i && (grep sanitize-v850e $i > /dev/null) ; then
+ if [ -n "${verbose}" ] ; then
+ echo Keeping v850e stuff in $i
+ fi
+ fi
+ done
+else
+ for i in $v850e_files ; do
+ if test -r $i && (grep sanitize-v850e $i > /dev/null) ; then
+ if [ -n "${verbose}" ] ; then
+ echo Removing traces of \"v850e\" from $i...
+ fi
+ cp $i new
+ sed '/start\-sanitize\-v850e/,/end\-sanitize\-v850e/d' < $i > new
+ if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
+ if [ -n "${verbose}" ] ; then
+ echo Caching $i in .Recover...
+ fi
+ mv $i .Recover
+ fi
+ mv new $i
+ fi
+ done
+fi
+
# This must come after all other sanitizations. Re-sanitize the .pot
# file.
if [ -n "${verbose}" ]; then
diff --git a/binutils/Makefile.am b/binutils/Makefile.am
index b06b6f5..c4529b2 100644
--- a/binutils/Makefile.am
+++ b/binutils/Makefile.am
@@ -29,6 +29,8 @@ STRIP_PROG=strip-new
STRINGS_PROG=strings
+READELF_PROG=readelf
+
# These should all be the same program too.
SIZE_PROG=size
NM_PROG=nm-new
@@ -49,9 +51,9 @@ SRCONV_PROG=srconv$(EXEEXT) sysdump$(EXEEXT) coffdump$(EXEEXT)
man_MANS = ar.1 nm.1 objdump.1 ranlib.1 size.1 strings.1 strip.1 objcopy.1 \
addr2line.1 nlmconv.1 $(DEMANGLER_PROG).1
-PROGS = $(SIZE_PROG) $(OBJDUMP_PROG) $(NM_PROG) $(AR_PROG) $(STRINGS_PROG) $(STRIP_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG)
+PROGS = $(SIZE_PROG) $(OBJDUMP_PROG) $(NM_PROG) $(AR_PROG) $(STRINGS_PROG) $(STRIP_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG)
-bin_PROGRAMS = $(SIZE_PROG) $(OBJDUMP_PROG) $(AR_PROG) $(STRINGS_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG)
+bin_PROGRAMS = $(SIZE_PROG) $(OBJDUMP_PROG) $(AR_PROG) $(STRINGS_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG)
## We need a special rule to install the programs which are built with -new
noinst_PROGRAMS = $(NM_PROG) $(STRIP_PROG)
@@ -71,7 +73,7 @@ DEP = mkdep
INCLUDES = -D_GNU_SOURCE -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) @HDEFINES@ -I$(srcdir)/../intl -I../intl -DLOCALEDIR="\"$(prefix)/share/locale\""
HFILES = arsup.h bucomm.h budbg.h coffgrok.h debug.h nlmconv.h dlltool.h \
- windres.h
+ windres.h readelf.h
GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h
@@ -80,7 +82,7 @@ CFILES = addr2line.c ar.c arsup.c bucomm.c coffdump.c coffgrok.c debug.c \
maybe-strip.c nlmconv.c nm.c not-ranlib.c not-strip.c \
objcopy.c objdump.c prdbg.c rdcoff.c rddbg.c size.c srconv.c \
stabs.c strings.c sysdump.c version.c wrstabs.c \
- windres.c resrc.c rescoff.c resbin.c
+ windres.c resrc.c rescoff.c resbin.c readelf.c
GENERATED_CFILES = \
underscore.c arparse.c arlex.c sysroff.c sysinfo.c syslex.c \
@@ -154,6 +156,9 @@ objcopy_SOURCES = objcopy.c not-strip.c $(WRITE_DEBUG_SRCS) $(BULIBS)
strings_SOURCES = strings.c $(BULIBS)
+readelf_SOURCES = readelf.c version.c
+readelf_LDADD = $(INTLLIBS)
+
strip_new_SOURCES = objcopy.c is-strip.c $(WRITE_DEBUG_SRCS) $(BULIBS)
nm_new_SOURCES = nm.c $(BULIBS)
@@ -393,6 +398,9 @@ objdump.o: objdump.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
$(INCDIR)/getopt.h $(INCDIR)/progress.h bucomm.h config.h \
$(INCDIR)/fopen-same.h $(INCDIR)/dis-asm.h $(INCDIR)/libiberty.h \
$(INCDIR)/demangle.h debug.h budbg.h $(INCDIR)/aout/aout64.h
+readelf.o: readelf.c $(INCDIR)/ansidecl.h ./readelf.h \
+ $(INCDIR)/progress.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \
+ $(INCDIR)/getopt.h $(INCDIR)/libiberty.h $(INCDIR)/elf/common.h
prdbg.o: prdbg.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
debug.h budbg.h
diff --git a/binutils/Makefile.in b/binutils/Makefile.in
index bd28203..ee1463e 100644
--- a/binutils/Makefile.in
+++ b/binutils/Makefile.in
@@ -102,6 +102,8 @@ STRIP_PROG=strip-new
STRINGS_PROG=strings
+READELF_PROG=readelf
+
# These should all be the same program too.
SIZE_PROG=size
NM_PROG=nm-new
@@ -122,9 +124,9 @@ SRCONV_PROG=srconv$(EXEEXT) sysdump$(EXEEXT) coffdump$(EXEEXT)
man_MANS = ar.1 nm.1 objdump.1 ranlib.1 size.1 strings.1 strip.1 objcopy.1 \
addr2line.1 nlmconv.1 $(DEMANGLER_PROG).1
-PROGS = $(SIZE_PROG) $(OBJDUMP_PROG) $(NM_PROG) $(AR_PROG) $(STRINGS_PROG) $(STRIP_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG)
+PROGS = $(SIZE_PROG) $(OBJDUMP_PROG) $(NM_PROG) $(AR_PROG) $(STRINGS_PROG) $(STRIP_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG)
-bin_PROGRAMS = $(SIZE_PROG) $(OBJDUMP_PROG) $(AR_PROG) $(STRINGS_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG)
+bin_PROGRAMS = $(SIZE_PROG) $(OBJDUMP_PROG) $(AR_PROG) $(STRINGS_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG)
noinst_PROGRAMS = $(NM_PROG) $(STRIP_PROG)
@@ -143,7 +145,7 @@ DEP = mkdep
INCLUDES = -D_GNU_SOURCE -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) @HDEFINES@ -I$(srcdir)/../intl -I../intl -DLOCALEDIR="\"$(prefix)/share/locale\""
HFILES = arsup.h bucomm.h budbg.h coffgrok.h debug.h nlmconv.h dlltool.h \
- windres.h
+ windres.h readelf.h
GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h
@@ -152,7 +154,7 @@ CFILES = addr2line.c ar.c arsup.c bucomm.c coffdump.c coffgrok.c debug.c \
maybe-strip.c nlmconv.c nm.c not-ranlib.c not-strip.c \
objcopy.c objdump.c prdbg.c rdcoff.c rddbg.c size.c srconv.c \
stabs.c strings.c sysdump.c version.c wrstabs.c \
- windres.c resrc.c rescoff.c resbin.c
+ windres.c resrc.c rescoff.c resbin.c readelf.c
GENERATED_CFILES = \
underscore.c arparse.c arlex.c sysroff.c sysinfo.c syslex.c \
@@ -204,6 +206,9 @@ objcopy_SOURCES = objcopy.c not-strip.c $(WRITE_DEBUG_SRCS) $(BULIBS)
strings_SOURCES = strings.c $(BULIBS)
+readelf_SOURCES = readelf.c version.c
+readelf_LDADD = $(INTLLIBS)
+
strip_new_SOURCES = objcopy.c is-strip.c $(WRITE_DEBUG_SRCS) $(BULIBS)
nm_new_SOURCES = nm.c $(BULIBS)
@@ -254,7 +259,7 @@ CONFIG_CLEAN_FILES =
bin_PROGRAMS = size$(EXEEXT) objdump$(EXEEXT) ar$(EXEEXT) \
strings$(EXEEXT) ranlib$(EXEEXT) c++filt$(EXEEXT) objcopy$(EXEEXT) \
@BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ \
-addr2line$(EXEEXT)
+addr2line$(EXEEXT) readelf$(EXEEXT)
noinst_PROGRAMS = nm-new$(EXEEXT) strip-new$(EXEEXT)
PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
@@ -321,6 +326,9 @@ addr2line_OBJECTS = addr2line.o bucomm.o version.o filemode.o
addr2line_LDADD = $(LDADD)
addr2line_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a
addr2line_LDFLAGS =
+readelf_OBJECTS = readelf.o version.o
+readelf_DEPENDENCIES =
+readelf_LDFLAGS =
nm_new_OBJECTS = nm.o bucomm.o version.o filemode.o
nm_new_LDADD = $(LDADD)
nm_new_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a
@@ -360,8 +368,8 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP = --best
-SOURCES = $(nlmconv_SOURCES) $(srconv_SOURCES) $(sysdump_SOURCES) $(coffdump_SOURCES) $(dlltool_SOURCES) $(windres_SOURCES) $(size_SOURCES) $(objdump_SOURCES) $(ar_SOURCES) $(strings_SOURCES) $(ranlib_SOURCES) $(c__filt_SOURCES) $(objcopy_SOURCES) $(addr2line_SOURCES) $(nm_new_SOURCES) $(strip_new_SOURCES)
-OBJECTS = $(nlmconv_OBJECTS) $(srconv_OBJECTS) $(sysdump_OBJECTS) $(coffdump_OBJECTS) $(dlltool_OBJECTS) $(windres_OBJECTS) $(size_OBJECTS) $(objdump_OBJECTS) $(ar_OBJECTS) $(strings_OBJECTS) $(ranlib_OBJECTS) $(c__filt_OBJECTS) $(objcopy_OBJECTS) $(addr2line_OBJECTS) $(nm_new_OBJECTS) $(strip_new_OBJECTS)
+SOURCES = $(nlmconv_SOURCES) $(srconv_SOURCES) $(sysdump_SOURCES) $(coffdump_SOURCES) $(dlltool_SOURCES) $(windres_SOURCES) $(size_SOURCES) $(objdump_SOURCES) $(ar_SOURCES) $(strings_SOURCES) $(ranlib_SOURCES) $(c__filt_SOURCES) $(objcopy_SOURCES) $(addr2line_SOURCES) $(readelf_SOURCES) $(nm_new_SOURCES) $(strip_new_SOURCES)
+OBJECTS = $(nlmconv_OBJECTS) $(srconv_OBJECTS) $(sysdump_OBJECTS) $(coffdump_OBJECTS) $(dlltool_OBJECTS) $(windres_OBJECTS) $(size_OBJECTS) $(objdump_OBJECTS) $(ar_OBJECTS) $(strings_OBJECTS) $(ranlib_OBJECTS) $(c__filt_OBJECTS) $(objcopy_OBJECTS) $(addr2line_OBJECTS) $(readelf_OBJECTS) $(nm_new_OBJECTS) $(strip_new_OBJECTS)
all: all-recursive-am all-am
@@ -531,6 +539,10 @@ addr2line$(EXEEXT): $(addr2line_OBJECTS) $(addr2line_DEPENDENCIES)
@rm -f addr2line$(EXEEXT)
$(LINK) $(addr2line_LDFLAGS) $(addr2line_OBJECTS) $(addr2line_LDADD) $(LIBS)
+readelf$(EXEEXT): $(readelf_OBJECTS) $(readelf_DEPENDENCIES)
+ @rm -f readelf$(EXEEXT)
+ $(LINK) $(readelf_LDFLAGS) $(readelf_OBJECTS) $(readelf_LDADD) $(LIBS)
+
nm-new$(EXEEXT): $(nm_new_OBJECTS) $(nm_new_DEPENDENCIES)
@rm -f nm-new$(EXEEXT)
$(LINK) $(nm_new_LDFLAGS) $(nm_new_OBJECTS) $(nm_new_LDADD) $(LIBS)
@@ -1158,6 +1170,9 @@ objdump.o: objdump.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
$(INCDIR)/getopt.h $(INCDIR)/progress.h bucomm.h config.h \
$(INCDIR)/fopen-same.h $(INCDIR)/dis-asm.h $(INCDIR)/libiberty.h \
$(INCDIR)/demangle.h debug.h budbg.h $(INCDIR)/aout/aout64.h
+readelf.o: readelf.c $(INCDIR)/ansidecl.h ./readelf.h \
+ $(INCDIR)/progress.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \
+ $(INCDIR)/getopt.h $(INCDIR)/libiberty.h $(INCDIR)/elf/common.h
prdbg.o: prdbg.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
debug.h budbg.h
diff --git a/binutils/binutils.texi b/binutils/binutils.texi
index 70f68b3..8f20e52 100644
--- a/binutils/binutils.texi
+++ b/binutils/binutils.texi
@@ -6,7 +6,7 @@
@format
START-INFO-DIR-ENTRY
* Binutils: (binutils). The GNU binary utilities "ar", "objcopy",
- "objdump", "nm", "nlmconv", "size",
+ "objdump", "nm", "nlmconv", "size", "readelf"
"strings", "strip", "ranlib" and "dlltool".
END-INFO-DIR-ENTRY
@end format
@@ -39,7 +39,7 @@ into another language, under the above conditions for modified versions.
@synindex ky cp
@c
@c This file documents the GNU binary utilities "ar", "ld", "objcopy",
-@c "objdump", "nm", "size", "strings", "strip", and "ranlib".
+@c "objdump", "nm", "size", "strings", "strip", "readelf" and "ranlib".
@c
@c Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
@c
@@ -105,6 +105,9 @@ Display information from object files
@item ranlib
Generate index to archive contents
+@item readelf
+Display the contents of ELF format files.
+
@item size
List file section sizes and total size
@@ -137,6 +140,7 @@ Create the files needed to build and use Dynamic Link Libraries
* objcopy:: Copy and translate object files
* objdump:: Display information from object files
* ranlib:: Generate index to archive contents
+* readelf:: Display the contents of ELF format files.
* size:: List section sizes and total size
* strings:: List printable strings from files
* strip:: Discard symbols
@@ -2262,6 +2266,106 @@ Displays dlltool's version number and then exits.
@end table
+@node readelf
+@chapter readelf
+
+@cindex ELF file information
+@kindex readelf
+
+@smallexample
+readelf [ -a | --all ]
+ [ -h | --file-header]
+ [ -l | --program-headers | --segments]
+ [ -S | --sections]
+ [ -s | --symbols]
+ [ -r | --relocs]
+ [ -d | --dynamic]
+ [ -V | --version-info]
+ [ -D | --use-dynamic]
+ [ -x <number> | --hex-dump=<number>]
+ [ -v | --version]
+ [ -H | --help]
+ @var{elffile}@dots{}
+@end smallexample
+
+@code{readelf} displays information about one or more ELF format object
+files. The options control what particular information to display.
+
+@var{elffile}@dots{} are the object files to be examined. At the
+moment, @code{readelf} does not support examining archives, nor does it
+support examing 64 bit ELF files.
+
+The long and short forms of options, shown here as alternatives, are
+equivalent. At least one option besides @samp{-v} or @samp{-H} must be
+given.
+
+@table @code
+@item -a
+@itemx --all
+Equivalent to specifiying @samp{--file-header},
+@samp{--program-headers}, @samp{--sections}, @samp{--symbols},
+@samp{--relocs}, @samp{--dynamic} and @samp{--version-info}.
+
+@item -h
+@itemx --file-header
+@cindex ELF file header information
+Displays the information contained in the ELF header at the start of the
+file.
+
+@item -l
+@itemx --program-headers
+@itemx --segments
+@cindex ELF program header information
+@cindex ELF segment information
+Displays the information contained in the file's segment headers, if it
+has any.
+
+@item -S
+@itemx --sections
+@cindex ELF section information
+Displays the information contained in the file's section headers, if it
+has any.
+
+@item -s
+@itemx --symbols
+@cindex ELF symbol table information
+Displays the entries in symbol table section of the file, if it has one.
+
+@item -r
+@itemx --relocs
+@cindex ELF reloc information
+Displays the contents of the file's relocation section, if it ha one.
+
+@item -d
+@itemx --dynamic
+@cindex ELF dynamic section information
+Displays the contents of the file's dynamic section, if it has one.
+
+@item -V
+@itemx --version-info
+@cindex ELF version sections informations
+Displays the contents of the version sections in the file, it they
+exist.
+
+@item -D
+@itemx --use-dynamic
+When displaying symbols, this option makes @code{readelf} use the
+symblol table in the file's dynamic section, rather than the one in the
+symbols section.
+
+@item -x <number>
+@itemx --hex-dump=<number>
+Displays the contents of the indicated section as a hexadecimal dump.
+
+@item -v
+@itemx --version
+Display the version number of readelf.
+
+@item -H
+@itemx --help
+Display the command line options understood by @code{readelf}.
+
+@end table
@node Selecting The Target System
diff --git a/binutils/readelf.c b/binutils/readelf.c
new file mode 100644
index 0000000..ee2f079
--- /dev/null
+++ b/binutils/readelf.c
@@ -0,0 +1,2254 @@
+/* readelf.c -- display contents of an ELF format file
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+ Originally developed by Eric Youngdale <eric@andante.jic.com>
+ Modifications by Nick Clifton <nickc@cygnus.com>
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+
+#include <assert.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+#include "readelf.h"
+#include "getopt.h"
+#include "bucomm.h"
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+unsigned int dynamic_addr;
+unsigned int dynamic_size;
+char * pint = "";
+char * program_name = "readelf";
+
+int dynamic_info [DT_JMPREL + 1];
+int version_info [16];
+
+int must_swap = 0;
+
+unsigned int rel_size;
+int loadaddr = -1;
+
+unsigned int rela_addr;
+unsigned int rela_size;
+char * strtab;
+int symtab_index;
+int lastmapped;
+char * header;
+
+Elf_Dyn * dpnt;
+Elf_Rel * rpnt;
+Elf_Shdr * elf_sections;
+Elf_Ehdr * epnt;
+Elf_Sym * symtab;
+
+int show_name;
+int do_dynamic;
+int do_syms;
+int do_reloc;
+int do_section;
+int do_load;
+int do_using_dynamic;
+int do_header;
+int do_dump;
+int do_version;
+long int expected_endian;
+
+char * dyntype[] =
+{
+ "NULL", "NEEDED","PLTRELSZ","PLTGOT","HASH","STRTAB","SYMTAB","RELA",
+ "RELASZ","RELAENT","STRSZ","SYMENT","INIT","FINI","SONAME","RPATH",
+ "SYMBOLIC","REL","RELSZ","RELENT","PLTREL","DEBUG","TEXTREL","JMPREL"
+};
+
+char * vertype[] =
+{
+ "VERNEEDNUM", "VERNEED", "VERDEFNUM", "VERDEF",
+ "", "", "", "", "", "", "", "", "", "", "", "VERSYM"
+};
+
+char * filtertype[] =
+{
+ "FILTER", "USED", "AUXILIARY"
+};
+
+
+char * sttinfo[] = {"NOTYPE","OBJECT","FUNC","SECTION","FILE"};
+char * stbinfo[] = {"LOCAL","GLOBAL","WEAK"};
+
+#define SECTION_NAME(X) (& header [lastmapped + (X)->sh_name])
+
+#define NUM_DUMP_SECTS 100
+char dump_sects [NUM_DUMP_SECTS];
+#define HEX_DUMP 1
+#define DISASS_DUMP 2
+
+/* Forward declarations for dumb compilers. */
+static char * get_i386_rel_type PARAMS ((bfd_vma rtype));
+static char * get_m68k_rel_type PARAMS ((bfd_vma rtype));
+static char * get_sparc_rel_type PARAMS ((bfd_vma rtype));
+static char * get_m32r_rel_type PARAMS ((bfd_vma rtype));
+static char * get_v850_rel_type PARAMS ((bfd_vma rtype));
+static char * get_d10v_rel_type PARAMS ((bfd_vma rtype));
+static char * get_d30v_rel_type PARAMS ((bfd_vma rtype));
+static char * get_sh_rel_type PARAMS ((bfd_vma rtype));
+static char * get_mn10300_rel_type PARAMS ((bfd_vma rtype));
+static char * get_mn10200_rel_type PARAMS ((bfd_vma rtype));
+static void dump_relocations PARAMS ((Elf_Rel * rpnt, int rel_size));
+static char * get_file_type PARAMS ((unsigned short e_type));
+static char * get_machine_name PARAMS ((unsigned short e_machine));
+static char * get_segment_type PARAMS ((unsigned long p_type));
+static char * get_section_type_name PARAMS ((unsigned int sh_type));
+static void usage PARAMS ((void));
+static void parse_args PARAMS ((int argc, char ** argv));
+static int process_elf_header PARAMS ((void));
+static void process_program_headers PARAMS ((void));
+static void process_section_headers PARAMS ((void));
+static void process_dynamic_segment PARAMS ((void));
+static void process_symbol_table PARAMS ((void));
+static void process_section_contents PARAMS ((void));
+static void process_file PARAMS ((char * file_name));
+
+
+#define SWAP2(val) ( (((val) << 8) & (0xff << 8)) \
+ | (((val) >> 8) & (0xff << 0)))
+
+#define SWAP4(val) ( (((val) << 24) & (0xff << 24)) \
+ | (((val) << 8) & (0xff << 16)) \
+ | (((val) >> 8) & (0xff << 8)) \
+ | (((val) >> 24) & (0xff << 0)))
+
+/* Warning: This macro assumes 8 bits in a char. */
+#define BYTE_SWAP(pointer, field) \
+ if (sizeof ((pointer)->field) == 2) \
+ { \
+ unsigned short val = (pointer)->field ; \
+ new_header->field = SWAP2 (val); \
+ } \
+ else if (sizeof ((pointer)->field) != 4) \
+ abort (); \
+ else \
+ { \
+ unsigned long val = (pointer)->field ; \
+ new_header->field = SWAP4 (val); \
+ }
+
+
+#ifdef ANSI_PROTOTYPES
+static void
+error (const char * message, ...)
+{
+ va_list args;
+
+ fprintf (stderr, _("%s: Error: "), program_name);
+ va_start (args, message);
+ vfprintf (stderr, message, args);
+ va_end (args);
+ return;
+}
+
+static void
+warn (const char * message, ...)
+{
+ va_list args;
+
+ fprintf (stderr, _("%s: Warning: "), program_name);
+ va_start (args, message);
+ vfprintf (stderr, message, args);
+ va_end (args);
+ return;
+}
+#else
+static void
+error (va_alist)
+{
+ char * message;
+ va_list args;
+
+ fprintf (stderr, _("%s: Error: "), program_name);
+ va_start (args);
+ message = va_arg (args, char *);
+ vfprintf (stderr, message, args);
+ va_end (args);
+ return;
+}
+
+static void
+warn (va_alist)
+ va_dcl;
+{
+ char * message;
+ va_list args;
+
+ fprintf (stderr, _("%s: Warning: "), program_name);
+ va_start (args);
+ message = va_arg (args, char *);
+ vfprintf (stderr, message, args);
+ va_end (args);
+ return;
+}
+#endif
+
+
+static char *
+get_i386_rel_type (rtype)
+ bfd_vma rtype;
+{
+ switch (rtype)
+ {
+ case 0: return "R_386_NONE";
+ case 1: return "R_386_32";
+ case 2: return "R_386_PC32";
+ case 3: return "R_386_GOT32";
+ case 4: return "R_386_PLT32";
+ case 5: return "R_386_COPY";
+ case 6: return "R_386_GLOB_DAT";
+ case 7: return "R_386_JMP_SLOT";
+ case 8: return "R_386_RELATIVE";
+ case 9: return "R_386_GOTOFF";
+ case 10: return "R_386_GOTPC";
+ case 20: return "R_386_16";
+ case 21: return "R_386_PC16";
+ case 22: return "R_386_PC8";
+ case 23: return "R_386_max";
+ default: return _("*INVALID*");
+ }
+}
+
+static char *
+get_m68k_rel_type (rtype)
+ bfd_vma rtype;
+{
+ switch (rtype)
+ {
+ case 0: return "R_68K_NONE";
+ case 1: return "R_68K_32";
+ case 2: return "R_68K_16";
+ case 3: return "R_68K_8";
+ case 4: return "R_68K_PC32";
+ case 5: return "R_68K_PC16";
+ case 6: return "R_68K_PC8";
+ case 7: return "R_68K_GOT32";
+ case 8: return "R_68K_GOT16";
+ case 9: return "R_68K_GOT8";
+ case 10: return "R_68K_GOT32O";
+ case 11: return "R_68K_GOT16O";
+ case 12: return "R_68K_GOT8O";
+ case 13: return "R_68K_PLT32";
+ case 14: return "R_68K_PLT16";
+ case 15: return "R_68K_PLT8";
+ case 16: return "R_68K_PLT32O";
+ case 17: return "R_68K_PLT16O";
+ case 18: return "R_68K_PLT8O";
+ case 19: return "R_68K_COPY";
+ case 20: return "R_68K_GLOB_DAT";
+ case 21: return "R_68K_JMP_SLOT";
+ case 22: return "R_68K_RELATIVE";
+ default: return _("*INVALID*");
+ }
+}
+
+
+static char *
+get_sparc_rel_type (rtype)
+ bfd_vma rtype;
+{
+ switch (rtype)
+ {
+ case 0: return "R_SPARC_NONE";
+ case 1: return "R_SPARC_8";
+ case 2: return "R_SPARC_16";
+ case 3: return "R_SPARC_32";
+ case 4: return "R_SPARC_DISP8";
+ case 5: return "R_SPARC_DISP16";
+ case 6: return "R_SPARC_DISP32";
+ case 7: return "R_SPARC_WDISP30";
+ case 8: return "R_SPARC_WDISP22";
+ case 9: return "R_SPARC_HI22";
+ case 10: return "R_SPARC_22";
+ case 11: return "R_SPARC_13";
+ case 12: return "R_SPARC_LO10";
+ case 13: return "R_SPARC_GOT10";
+ case 14: return "R_SPARC_GOT13";
+ case 15: return "R_SPARC_GOT22";
+ case 16: return "R_SPARC_PC10";
+ case 17: return "R_SPARC_PC22";
+ case 18: return "R_SPARC_WPLT30";
+ case 19: return "R_SPARC_COPY";
+ case 20: return "R_SPARC_GLOB_DAT";
+ case 21: return "R_SPARC_JMP_SLOT";
+ case 22: return "R_SPARC_RELATIVE";
+ case 23: return "R_SPARC_UA32";
+ case 24: return "R_SPARC_10";
+ case 25: return "R_SPARC_11";
+ case 26: return "R_SPARC_64";
+ case 27: return "R_SPARC_OLO10";
+ case 28: return "R_SPARC_HH22";
+ case 29: return "R_SPARC_HM10";
+ case 30: return "R_SPARC_LM22";
+ case 31: return "R_SPARC_PC_HH22";
+ case 32: return "R_SPARC_PC_HM10";
+ case 33: return "R_SPARC_PC_LM22";
+ case 34: return "R_SPARC_WDISP16";
+ case 35: return "R_SPARC_WDISP19";
+ case 36: return "R_SPARC_UNUSED_42";
+ case 37: return "R_SPARC_7";
+ case 38: return "R_SPARC_5";
+ case 39: return "R_SPARC_6";
+ case 40: return "R_SPARC_DISP64";
+ case 41: return "R_SPARC_PLT64";
+ case 42: return "R_SPARC_HIX22";
+ case 43: return "R_SPARC_LOX10";
+ case 44: return "R_SPARC_H44";
+ case 45: return "R_SPARC_M44";
+ case 46: return "R_SPARC_L44";
+ case 47: return "R_SPARC_REGISTER";
+ case 48: return "R_SPARC_UA64";
+ case 49: return "R_SPARC_UA16";
+ case 50: return "R_SPARC_32LE";
+ default: return _("*INVALID*");
+ }
+}
+
+
+static char *
+get_m32r_rel_type (rtype)
+ bfd_vma rtype;
+{
+ switch (rtype)
+ {
+ case 0: return "R_M32R_NONE";
+ case 1: return "R_M32R_16";
+ case 2: return "R_M32R_32";
+ case 3: return "R_M32R_24";
+ case 4: return "R_M32R_10_PCREL";
+ case 5: return "R_M32R_18_PCREL";
+ case 6: return "R_M32R_26_PCREL";
+ case 7: return "R_M32R_HI16_ULO";
+ case 8: return "R_M32R_HI16_SLO";
+ case 9: return "R_M32R_LO16";
+ case 10: return "R_M32R_SDA16";
+ default: return _("*INVALID*");
+ }
+}
+
+
+static char *
+get_v850_rel_type (rtype)
+ bfd_vma rtype;
+{
+ switch (rtype)
+ {
+ case 0: return "R_V850_NONE";
+ case 1: return "R_V850_9_PCREL";
+ case 2: return "R_V850_22_PCREL";
+ case 3: return "R_V850_HI16_S";
+ case 4: return "R_V850_HI16";
+ case 5: return "R_V850_LO16";
+ case 6: return "R_V850_32";
+ case 7: return "R_V850_16";
+ case 8: return "R_V850_8";
+ case 9: return "R_V850_SDA_16_16_OFFSET";
+ case 10: return "R_V850_SDA_15_16_OFFSET";
+ case 11: return "R_V850_ZDA_16_16_OFFSET";
+ case 12: return "R_V850_ZDA_15_16_OFFSET";
+ case 13: return "R_V850_TDA_6_8_OFFSET";
+ case 14: return "R_V850_TDA_7_8_OFFSET";
+ case 15: return "R_V850_TDA_7_7_OFFSET";
+ case 16: return "R_V850_TDA_16_16_OFFSET";
+/* start-sanitize-v850e */
+ case 17: return "R_V850_TDA_4_5_OFFSET";
+ case 18: return "R_V850_TDA_4_4_OFFSET";
+ case 19: return "R_V850_SDA_16_16_SPLIT_OFFSET";
+ case 20: return "R_V850_ZDA_16_16_SPLIT_OFFSET";
+ case 21: return "R_V850_CALLT_6_7_OFFSET";
+ case 22: return "R_V850_CALLT_16_16_OFFSET";
+/* end-sanitize-v850e */
+ default: return _("*INVALID*");
+ }
+}
+
+
+static char *
+get_d10v_rel_type (rtype)
+ bfd_vma rtype;
+{
+ switch (rtype)
+ {
+ case 0: return "R_D10V_NONE";
+ case 1: return "R_D10V_10_PCREL_R";
+ case 2: return "R_D10V_10_PCREL_L";
+ case 3: return "R_D10V_16";
+ case 4: return "R_D10V_18";
+ case 5: return "R_D10V_18_PCREL";
+ case 6: return "R_D10V_32";
+ default: return _("*INVALID*");
+ }
+}
+
+
+static char *
+get_d30v_rel_type (rtype)
+ bfd_vma rtype;
+{
+ switch (rtype)
+ {
+ case 0: return "R_D30V_NONE";
+ case 1: return "R_D30V_6";
+ case 2: return "R_D30V_9_PCREL";
+ case 3: return "R_D30V_9_PCREL_R";
+ case 4: return "R_D30V_15";
+ case 5: return "R_D30V_15_PCREL";
+ case 6: return "R_D30V_15_PCREL_R";
+ case 7: return "R_D30V_21";
+ case 8: return "R_D30V_21_PCREL";
+ case 9: return "R_D30V_21_PCREL_R";
+ case 10: return "R_D30V_32";
+ case 11: return "R_D30V_32_PCREL";
+ case 12: return "R_D30V_32_NORMAL";
+ default: return _("*INVALID*");
+ }
+}
+
+
+static char *
+get_sh_rel_type (rtype)
+ bfd_vma rtype;
+{
+ switch (rtype)
+ {
+ case 0: return "R_SH_NONE";
+ case 1: return "R_SH_DIR32";
+ case 2: return "R_SH_REL32";
+ case 3: return "R_SH_DIR8WPN";
+ case 4: return "R_SH_IND12W";
+ case 5: return "R_SH_DIR8WPL";
+ case 6: return "R_SH_DIR8WPZ";
+ case 7: return "R_SH_DIR8BP";
+ case 8: return "R_SH_DIR8W";
+ case 9: return "R_SH_DIR8L";
+ case 25: return "R_SH_SWITCH16";
+ case 26: return "R_SH_SWITCH32";
+ case 27: return "R_SH_USES";
+ case 28: return "R_SH_COUNT";
+ case 29: return "R_SH_ALIGN";
+ case 30: return "R_SH_CODE";
+ case 31: return "R_SH_DATA";
+ case 32: return "R_SH_LABEL";
+ default: return _("*INVALID*");
+ }
+}
+
+
+static char *
+get_mn10300_rel_type (rtype)
+ bfd_vma rtype;
+{
+ switch (rtype)
+ {
+ case 0: return "R_MN10300_NONE";
+ case 1: return "R_MN10300_32";
+ case 2: return "R_MN10300_16";
+ case 3: return "R_MN10300_8";
+ case 4: return "R_MN10300_PCREL32";
+ case 5: return "R_MN10300_PCREL16";
+ case 6: return "R_MN10300_PCREL8";
+ default: return _("*INVALID*");
+ }
+}
+
+
+static char *
+get_mn10200_rel_type (rtype)
+ bfd_vma rtype;
+{
+ switch (rtype)
+ {
+ case 0: return "R_MN10200_NONE";
+ case 1: return "R_MN10200_32";
+ case 2: return "R_MN10200_16";
+ case 3: return "R_MN10200_8";
+ case 4: return "R_MN10200_24";
+ case 5: return "R_MN10200_PCREL8";
+ case 6: return "R_MN10200_PCREL16";
+ case 7: return "R_MN10200_PCREL24";
+ default: return _("*INVALID*");
+ }
+}
+
+
+static void
+dump_relocations (rpnt, rel_size)
+ Elf_Rel * rpnt;
+ int rel_size;
+{
+ int i;
+ int is_rela;
+ Elf_Rela * rapnt;
+ Elf_Rela * relocs = NULL;
+
+
+ rapnt = (Elf_Rela *) rpnt;
+
+ /* Compute number of relocations. */
+ switch (epnt->e_machine)
+ {
+ case EM_386:
+ case EM_486:
+ case EM_CYGNUS_M32R:
+ case EM_CYGNUS_D10V:
+ rel_size = rel_size / sizeof (Elf_Rel);
+
+ if (must_swap)
+ {
+ Elf_Rel * new_header = malloc (sizeof (* new_header) * rel_size);
+
+ if (new_header == NULL)
+ {
+ error (_("out of memory\n"));
+ return;
+ }
+
+ memcpy (new_header, rpnt, sizeof (* new_header) * rel_size);
+
+ rpnt = new_header;
+ relocs = (Elf_Rela *) new_header;
+
+ for (i = 0; i < rel_size; i++)
+ {
+ BYTE_SWAP (rpnt + i, r_offset);
+ BYTE_SWAP (rpnt + i, r_info);
+
+ new_header ++;
+ }
+ }
+
+ is_rela = 0;
+ break;
+
+ case EM_68K:
+ case EM_SPARC:
+ case EM_CYGNUS_V850:
+ case EM_CYGNUS_D30V:
+ case EM_CYGNUS_MN10200:
+ case EM_CYGNUS_MN10300:
+ case EM_SH:
+ rel_size = rel_size / sizeof (Elf_Rela);
+
+ if (must_swap)
+ {
+ Elf_Rela * new_header = malloc (sizeof (* new_header) * rel_size);
+
+ if (new_header == NULL)
+ {
+ error (_("out of memory\n"));
+ return;
+ }
+
+ memcpy (new_header, rpnt, sizeof (* new_header) * rel_size);
+
+ relocs = rapnt = new_header;
+
+ for (i = rel_size; i--;)
+ {
+ BYTE_SWAP (new_header, r_offset);
+ BYTE_SWAP (new_header, r_info);
+ BYTE_SWAP (new_header, r_addend);
+
+ new_header ++;
+ }
+ }
+
+ is_rela = 1;
+ break;
+
+ default:
+ warn (_("Don't know about relocations on this machine architecture\n"));
+ return;
+ }
+
+ if (is_rela)
+ printf (_(" Offset Value Type Symbol's Value Symbol Name Addend\n"));
+ else
+ printf (_(" Offset Value Type Symbol's Value Symbol Name\n"));
+
+ for (i = 0; i < rel_size; i++)
+ {
+ char * rtype;
+
+ if (is_rela)
+ rpnt = (Elf_Rel *) rapnt;
+
+ printf (" %5.5x %5.5x ", rpnt->r_offset, rpnt->r_info);
+
+ switch (epnt->e_machine)
+ {
+ case EM_CYGNUS_M32R:
+ rtype = get_m32r_rel_type (ELF32_R_TYPE (rpnt->r_info));
+ break;
+
+ case EM_386:
+ case EM_486:
+ rtype = get_i386_rel_type (ELF32_R_TYPE (rpnt->r_info));
+ break;
+
+ case EM_68K:
+ rtype = get_m68k_rel_type (ELF32_R_TYPE (rpnt->r_info));
+ break;
+
+ case EM_SPARC:
+ rtype = get_sparc_rel_type (ELF32_R_TYPE (rapnt->r_info));
+ break;
+
+ case EM_CYGNUS_V850:
+ rtype = get_v850_rel_type (ELF32_R_TYPE (rpnt->r_info));
+ break;
+
+ case EM_CYGNUS_D10V:
+ rtype = get_d10v_rel_type (ELF32_R_TYPE (rpnt->r_info));
+ break;
+
+ case EM_CYGNUS_D30V:
+ rtype = get_d30v_rel_type (ELF32_R_TYPE (rpnt->r_info));
+ break;
+
+ case EM_SH:
+ rtype = get_sh_rel_type (ELF32_R_TYPE (rpnt->r_info));
+ break;
+
+ case EM_CYGNUS_MN10300:
+ rtype = get_mn10300_rel_type (ELF32_R_TYPE (rpnt->r_info));
+ break;
+
+ case EM_CYGNUS_MN10200:
+ rtype = get_mn10200_rel_type (ELF32_R_TYPE (rpnt->r_info));
+ break;
+ }
+
+ printf ("%-18s", rtype);
+
+ symtab_index = ELF32_R_SYM (rpnt->r_info);
+
+ if (symtab_index)
+ {
+ Elf_Sym ssym;
+ Elf_Sym * psym;
+
+ psym = symtab + symtab_index;
+
+ if (must_swap)
+ {
+ Elf_Sym * new_header = & ssym;
+
+ ssym = * psym;
+
+ BYTE_SWAP (psym, st_name);
+ BYTE_SWAP (psym, st_value);
+ /* BYTE_SWAP (psym, st_size); */
+ BYTE_SWAP (psym, st_shndx);
+
+ psym = new_header;
+ }
+
+ if (psym->st_name == 0)
+ printf (" %08x %-15s", psym->st_value,
+ SECTION_NAME (elf_sections + psym->st_shndx));
+ else
+ printf (" %08x %-15s", psym->st_value, strtab + psym->st_name);
+
+ if (is_rela)
+ printf (" + %x", rapnt->r_addend);
+ }
+
+ putchar ('\n');
+ rapnt ++;
+ rpnt ++;
+ }
+
+ if (relocs != NULL)
+ free (relocs);
+}
+
+static char *
+get_file_type (e_type)
+ unsigned short e_type;
+{
+ static char buff [32];
+
+ switch (e_type)
+ {
+ case ET_NONE: return _("None");
+ case ET_REL: return _("Relocatable file");
+ case ET_EXEC: return _("Executable file");
+ case ET_DYN: return _("Shared object file");
+ case ET_CORE: return _("Core file");
+
+ default:
+ if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC))
+ sprintf (buff, _("Processor Specific: (%x)"), e_type);
+ else
+ sprintf (buff, _("<unknown>: %x"), e_type);
+ return buff;
+ }
+}
+
+static char *
+get_machine_name (e_machine)
+ unsigned short e_machine;
+{
+ static char buff [32];
+
+ switch (e_machine)
+ {
+ case EM_NONE: return _("None");
+ case EM_M32: return "WE32100";
+ case EM_SPARC: return "Sparc";
+ case EM_386: return "80386";
+ case EM_68K: return "MC68000";
+ case EM_88K: return "MC88000";
+ case EM_486: return "Intel 80486";
+ case EM_860: return "Intel 80860";
+ case EM_MIPS: return "MIPS R3000 big-endian";
+ case EM_S370: return "Amdahl";
+ case EM_MIPS_RS4_BE: return "MIPS R400 big-endian";
+ case EM_PARISC: return "HPPA";
+ case EM_SPARC32PLUS: return "Sparc v8+" ;
+ case EM_PPC: return "Power PCC";
+ case EM_SPARCV9: return "Sparc v9";
+ case EM_ARM: return "ARM";
+ case EM_SH: return "Hitachi SH";
+ case EM_ALPHA: return "Alpha";
+ case EM_CYGNUS_D10V: return "d10v";
+ case EM_CYGNUS_D30V: return "d30v";
+ case EM_CYGNUS_M32R: return "M32r";
+ case EM_CYGNUS_V850: return "v850";
+ case EM_CYGNUS_MN10300: return "mn10300";
+ case EM_CYGNUS_MN10200: return "mn10200";
+
+ default:
+ sprintf (buff, _("<unknown>: %x"), e_machine);
+ return buff;
+ }
+}
+
+static char *
+get_segment_type (p_type)
+ unsigned long p_type;
+{
+ static char buff [32];
+
+ switch (p_type)
+ {
+ case PT_NULL: return _("Unused");
+ case PT_LOAD: return _("Loadable");
+ case PT_DYNAMIC: return _("Dynamic link info");
+ case PT_INTERP: return _("Interpreter");
+ case PT_NOTE: return _("Auxillary Info");
+ case PT_SHLIB: return _("Shared Library");
+ case PT_PHDR: return _("Program Headers");
+
+ default:
+ if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
+ return _("processor specific");
+ else
+ {
+ sprintf (buff, _("<unknown>: %x"), p_type);
+ return buff;
+ }
+ }
+}
+
+static char *
+get_section_type_name (sh_type)
+ unsigned int sh_type;
+{
+ static char buff [32];
+
+ switch (sh_type)
+ {
+ case SHT_NULL: return _("Unused");
+ case SHT_PROGBITS: return _("Program data");
+ case SHT_SYMTAB: return _("Symbol table");
+ case SHT_STRTAB: return _("String table");
+ case SHT_RELA: return _("Relocs, addends");
+ case SHT_HASH: return _("Symbol hash table");
+ case SHT_DYNAMIC: return _("Dynamic linking info");
+ case SHT_NOTE: return _("Notes");
+ case SHT_NOBITS: return _("Space, no data");
+ case SHT_REL: return _("Relocs, no addends");
+ case SHT_SHLIB: return _("Shared Library info");
+ case SHT_DYNSYM: return _("Dynamic linker symbols");
+ case SHT_GNU_verdef: return _("Version definition");
+ case SHT_GNU_verneed: return _("Version needs");
+ case SHT_GNU_versym: return _("Version symbols");
+ case 0x6ffffff0: return "VERSYM";
+ case 0x6ffffffc: return "VERDEF";
+ case 0x7ffffffd: return "AUXILIARY";
+ case 0x7fffffff: return "FILTER";
+
+ default:
+ if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC))
+ return _("processor specific");
+ else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
+ return _("application specific");
+ else
+ {
+ sprintf (buff, _("<unknown>: %x"), sh_type);
+ return buff;
+ }
+ }
+}
+
+struct option options [] =
+{
+ {"all", no_argument, 0, 'a'},
+ {"file-header", no_argument, 0, 'h'},
+ {"program-headers", no_argument, 0, 'l'},
+ {"segments", no_argument, 0, 'l'},
+ {"sections", no_argument, 0, 'S'},
+ {"symbols", no_argument, 0, 's'},
+ {"relocs", no_argument, 0, 'r'},
+ {"dynamic", no_argument, 0, 'd'},
+ {"version-info", no_argument, 0, 'V'},
+ {"use-dynamic", no_argument, 0, 'D'},
+
+ {"hex-dump", required_argument, 0, 'x'},
+#ifdef SUPPORT_DISASSEMBLY
+ {"instruction-dump", required_argument, 0, 'i'},
+#endif
+
+ {"version", no_argument, 0, 'v'},
+ {"help", no_argument, 0, 'H'},
+
+ {0, no_argument, 0, 0}
+};
+
+static void
+usage ()
+{
+ fprintf (stderr, _("Usage: readelf {options} elf-file(s)\n"));
+ fprintf (stderr, _(" Options are:\n"));
+ fprintf (stderr, _(" -a or --all Display all the information\n"));
+ fprintf (stderr, _(" -h or --file-header Display the ELF file header\n"));
+ fprintf (stderr, _(" -l or --program-headers or --segments\n"));
+ fprintf (stderr, _(" Display the program headers\n"));
+ fprintf (stderr, _(" -S or --sections Display the sections' headers\n"));
+ fprintf (stderr, _(" -s or --symbols Display the symbol table\n"));
+ fprintf (stderr, _(" -r or --relocs Display the relocations (if present)\n"));
+ fprintf (stderr, _(" -d or --dynamic Display the dynamic section (if present)\n"));
+ fprintf (stderr, _(" -V or --version-info Display the version sections (if present)\n"));
+ fprintf (stderr, _(" -D or --use-dynamic Use the dynamic section info when displaying symbols\n"));
+ fprintf (stderr, _(" -x <number> or --hex-dump=<number>\n"));
+ fprintf (stderr, _(" Dump the contents of section <number>\n"));
+#ifdef SUPPORT_DISASSEMBLY
+ fprintf (stderr, _(" -i <number> or --instruction-dump=<number>\n"));
+ fprintf (stderr, _(" Disassemble the contents of section <number>\n"));
+#endif
+ fprintf (stderr, _(" -v or --version Display the version number of readelf\n"));
+ fprintf (stderr, _(" -H or --help Display this information\n"));
+
+ exit (0);
+}
+
+static void
+parse_args (argc, argv)
+ int argc;
+ char ** argv;
+{
+ char c;
+
+ if (argc < 2)
+ usage ();
+
+ while ((c = getopt_long
+ (argc, argv, "rsahldSDx:i:vV", options, NULL)) != EOF)
+ {
+ char * cp;
+ int section;
+
+ switch (c)
+ {
+ case 'H':
+ usage ();
+ break;
+
+ case 'a':
+ do_syms++;
+ do_reloc++;
+ do_dynamic++;
+ do_header++;
+ do_section++;
+ do_load++;
+ do_version++;
+ break;
+ case 'D':
+ do_using_dynamic++;
+ break;
+ case 'r':
+ do_reloc++;
+ break;
+ case 'h':
+ do_header++;
+ break;
+ case 'l':
+ do_load++;
+ break;
+ case 's':
+ do_syms++;
+ break;
+ case 'S':
+ do_section++;
+ break;
+ case 'd':
+ do_dynamic++;
+ break;
+ case 'x':
+ do_dump ++;
+ section = strtoul (optarg, & cp, 0);
+ if (! * cp && section >= 0 && section < NUM_DUMP_SECTS)
+ {
+ dump_sects [section] |= HEX_DUMP;
+ break;
+ }
+ goto oops;
+#ifdef SUPPORT_DISASSEMBLY
+ case 'i':
+ do_dump ++;
+ section = strtoul (optarg, & cp, 0);
+ if (! * cp && section >= 0 && section < NUM_DUMP_SECTS)
+ {
+ dump_sects [section] |= DISASS_DUMP;
+ break;
+ }
+ goto oops;
+#endif
+ case 'v':
+ print_version (program_name);
+ break;
+ case 'V':
+ do_version ++;
+ break;
+ default:
+ oops:
+ /* xgettext:c-format */
+ error (_("Invalid option '-%c'\n"), c);
+ /* Drop through. */
+ case '?':
+ usage ();
+ }
+ }
+
+ if (!do_dynamic && !do_syms && !do_reloc && !do_section
+ && !do_load && !do_header && !do_dump && !do_version)
+ usage ();
+ else if (argc < 3)
+ warn (_("Nothing to do.\n"));
+}
+
+static int
+process_elf_header ()
+{
+ if ( epnt->e_ident [EI_MAG0] != ELFMAG0
+ || epnt->e_ident [EI_MAG1] != ELFMAG1
+ || epnt->e_ident [EI_MAG2] != ELFMAG2
+ || epnt->e_ident [EI_MAG3] != ELFMAG3)
+ {
+ error (_("Not an ELF file - it has the wrong magic bytes at the start\n"));
+ return 0;
+ }
+
+ if (epnt->e_ident [EI_CLASS] != ELFCLASS32)
+ {
+ error (_("Not a 32 bit ELF file\n"));
+ return 0;
+ }
+
+ if (epnt->e_ident [EI_DATA] != expected_endian)
+ must_swap = 1;
+
+ if (must_swap)
+ {
+ Elf_Ehdr * new_header = malloc (sizeof (* new_header));
+
+ if (new_header == NULL)
+ {
+ error (_("out of memory\n"));
+ return 0;
+ }
+
+ memcpy (new_header, epnt, sizeof (* new_header));
+
+ BYTE_SWAP (epnt, e_type);
+ BYTE_SWAP (epnt, e_machine);
+ BYTE_SWAP (epnt, e_version);
+ BYTE_SWAP (epnt, e_entry);
+ BYTE_SWAP (epnt, e_phoff);
+ BYTE_SWAP (epnt, e_shoff);
+ BYTE_SWAP (epnt, e_flags);
+ BYTE_SWAP (epnt, e_ehsize);
+ BYTE_SWAP (epnt, e_phentsize);
+ BYTE_SWAP (epnt, e_phnum);
+ BYTE_SWAP (epnt, e_shentsize);
+ BYTE_SWAP (epnt, e_shnum);
+ BYTE_SWAP (epnt, e_shstrndx);
+
+ epnt = new_header;
+ }
+
+ if (do_header)
+ {
+ int i;
+
+ printf (_("ELF Header....\n"));
+ printf (_(" Magic: "));
+ for (i = 0; i < EI_NIDENT; i ++)
+ printf ("%2.2x ", epnt->e_ident [i]);
+ printf ("\n");
+ printf (_(" Type: %s\n"), get_file_type (epnt->e_type));
+ printf (_(" Machine: %s\n"), get_machine_name (epnt->e_machine));
+ printf (_(" Version: %x\n"), epnt->e_version);
+ printf (_(" Entry point address: %x\n"), epnt->e_entry);
+ printf (_(" Start of program headers: %d (bytes into file)\n"), epnt->e_phoff);
+ printf (_(" Start of section headers: %d (bytes into file)\n"), epnt->e_shoff);
+ printf (_(" Flags: %x\n"), epnt->e_flags);
+ printf (_(" Size of this header: %d (bytes)\n"), epnt->e_ehsize);
+ printf (_(" Size of program headers: %d (bytes)\n"), epnt->e_phentsize);
+ printf (_(" Number of program headers: %d\n"), epnt->e_phnum);
+ printf (_(" Size of section headers: %d (bytes)\n"), epnt->e_shentsize);
+ printf (_(" Number of section headers: %d\n"), epnt->e_shnum);
+ printf (_(" Section header string table index: %d\n"), epnt->e_shstrndx);
+ }
+
+ return 1;
+}
+
+
+static void
+process_program_headers ()
+{
+ Elf_Phdr * elf_segments;
+ Elf_Phdr * ppnt;
+ int i;
+
+ if (epnt->e_phnum == 0)
+ {
+ if (do_load)
+ printf (_("\nThere are no program headers in this file\n"));
+ return;
+ }
+
+ if (do_load && !do_header)
+ {
+ printf (_("\nElf file is %s\n"), get_file_type (epnt->e_type));
+ printf (_("Entry point 0x%x\n"), epnt->e_entry);
+ printf (_("There are %d program headers, starting at offset %x:\n"),
+ epnt->e_phnum, epnt->e_phoff);
+ }
+
+ if (must_swap)
+ {
+ Elf_Phdr * new_header = malloc (sizeof (* new_header) * epnt->e_phnum);
+
+ if (new_header == NULL)
+ {
+ error (_("out of memory\n"));
+ return;
+ }
+
+ memcpy (new_header, & header [epnt->e_phoff],
+ sizeof (* new_header) * epnt->e_phnum);
+
+ elf_segments = ppnt = new_header;
+
+ for (i = 0; i < epnt->e_phnum; i++)
+ {
+ BYTE_SWAP (ppnt + i, p_type);
+ BYTE_SWAP (ppnt + i, p_flags);
+ BYTE_SWAP (ppnt + i, p_offset);
+ BYTE_SWAP (ppnt + i, p_vaddr);
+ BYTE_SWAP (ppnt + i, p_paddr);
+ BYTE_SWAP (ppnt + i, p_filesz);
+ BYTE_SWAP (ppnt + i, p_memsz);
+ BYTE_SWAP (ppnt + i, p_align);
+
+ new_header ++;
+ }
+ }
+ else
+ {
+ ppnt = (Elf_Phdr *) & header [epnt->e_phoff];
+ elf_segments = NULL;
+ }
+
+ if (do_load)
+ {
+ printf (_("\nProgram Header%s....\n"), epnt->e_phnum > 1 ? "s" : "");
+ printf (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n"));
+ }
+
+ loadaddr = -1;
+ dynamic_addr = 0;
+
+ for (i = 0; i < epnt->e_phnum; i++)
+ {
+ if (loadaddr == -1 && ppnt->p_type == PT_LOAD)
+ loadaddr = (ppnt->p_vaddr & 0xfffff000)
+ - (ppnt->p_offset & 0xfffff000);
+
+ if (do_load)
+ {
+ printf (" %-10s ", get_segment_type (ppnt->p_type));
+ printf ("0x%5.5x ",ppnt->p_offset);
+ printf ("0x%8.8x ",ppnt->p_vaddr);
+ printf ("0x%8.8x ",ppnt->p_paddr);
+ printf ("0x%5.5x 0x%5.5x ",ppnt->p_filesz, ppnt->p_memsz);
+ printf ("%c%c%c ",
+ (ppnt->p_flags & 4 ? 'R' : ' '),
+ (ppnt->p_flags & 2 ? 'W' : ' '),
+ (ppnt->p_flags & 1 ? 'E' : ' '));
+ printf ("%#x", ppnt->p_align);
+ }
+
+ if (ppnt->p_type == PT_DYNAMIC)
+ {
+ if (dynamic_addr)
+ error (_("more than one dynamic section\n"));
+
+ dynamic_addr = ppnt->p_offset;
+ dynamic_size = ppnt->p_filesz;
+ }
+
+ if (ppnt->p_type == PT_INTERP)
+ {
+ if (do_load)
+ printf (_("\nRequesting program interpreter [%s]"),
+ & header [ppnt->p_offset]);
+ pint = strdup (& header [ppnt->p_offset]);
+ }
+
+ if (do_load)
+ putc ('\n', stdout);
+
+ ppnt ++;
+ }
+
+ if (do_load)
+ {
+ printf (_("\n Section to Segment mapping:\n"));
+ printf (_(" Segment Sections...\n"));
+
+ if (elf_segments)
+ ppnt = elf_segments;
+ else
+ ppnt = (Elf_Phdr *) & header [epnt->e_phoff];
+
+ for (i = 0; i < epnt->e_phnum; i++, ppnt++)
+ {
+ int j;
+ Elf_Shdr * spnt;
+
+ printf (" %2.2d ", i);
+
+ spnt = (Elf_Shdr *) & header [epnt->e_shoff];
+
+ if (must_swap)
+ {
+ lastmapped = SWAP4 (spnt[epnt->e_shstrndx].sh_offset);
+
+ for (j = 0; j < epnt->e_shnum; j++)
+ {
+ bfd_vma addr;
+ bfd_size_type size;
+ unsigned int name;
+
+ addr = SWAP4 (spnt[j].sh_addr);
+ size = SWAP4 (spnt[j].sh_size);
+ name = SWAP4 (spnt[j].sh_name);
+
+ if (size > 0
+ && (addr >= ppnt->p_vaddr)
+ && (addr + size) <= (ppnt->p_vaddr + ppnt->p_memsz))
+ printf ("%s ", header + lastmapped + name);
+ }
+ }
+ else
+ {
+ lastmapped = spnt[epnt->e_shstrndx].sh_offset;
+
+ for (j = 0; j < epnt->e_shnum; j++, spnt++)
+ {
+ if (spnt->sh_size > 0
+ && (spnt->sh_addr >= ppnt->p_vaddr)
+ && (spnt->sh_addr + spnt->sh_size)
+ <= (ppnt->p_vaddr + ppnt->p_memsz))
+ printf ("%s ", SECTION_NAME (spnt));
+ }
+ }
+
+ putc ('\n',stdout);
+ }
+ }
+
+ if (elf_segments)
+ free (elf_segments);
+}
+
+
+static void
+process_section_headers ()
+{
+ Elf_Shdr * spnt;
+ int i;
+
+ if (must_swap)
+ {
+ Elf_Shdr * new_header = malloc (sizeof (* new_header) * epnt->e_shnum);
+
+ if (new_header == NULL)
+ {
+ error (_("out of memory\n"));
+ return;
+ }
+
+ memcpy (new_header, & header [epnt->e_shoff],
+ sizeof (* new_header) * epnt->e_shnum);
+
+ elf_sections = spnt = new_header;
+
+ for (i = 0; i < epnt->e_shnum; i++)
+ {
+ BYTE_SWAP (spnt + i, sh_name);
+ BYTE_SWAP (spnt + i, sh_type);
+ BYTE_SWAP (spnt + i, sh_flags);
+ BYTE_SWAP (spnt + i, sh_addr);
+ BYTE_SWAP (spnt + i, sh_offset);
+ BYTE_SWAP (spnt + i, sh_size);
+ BYTE_SWAP (spnt + i, sh_link);
+ BYTE_SWAP (spnt + i, sh_info);
+ BYTE_SWAP (spnt + i, sh_addralign);
+ BYTE_SWAP (spnt + i, sh_entsize);
+
+ new_header ++;
+ }
+ }
+ else
+ {
+ elf_sections = spnt = (Elf_Shdr *) & header [epnt->e_shoff];
+ }
+
+ spnt += epnt->e_shstrndx;
+ lastmapped = spnt->sh_offset;
+ spnt = elf_sections;
+
+ if (! do_section || (epnt->e_shnum == 0))
+ return;
+
+ if (! do_header)
+ printf (_("There are %d section headers, starting at offset %x:\n"),
+ epnt->e_shnum, epnt->e_shoff);
+
+ printf (_("\nSection Header%s....\n"), epnt->e_shnum > 1 ? "s" : "");
+ printf (_(" [Nr] Name Type Addr Off Size ES Flg Lk In Al\n"));
+
+ for (i = 0; i < epnt->e_shnum; i++)
+ {
+ printf (" [%2d] %-14s", i, SECTION_NAME (spnt));
+
+ printf (" %-18s ",get_section_type_name (spnt->sh_type));
+ printf ( "%8.8x %6.6x %6.6x %2.2x",
+ spnt->sh_addr,
+ spnt->sh_offset,
+ spnt->sh_size,
+ spnt->sh_entsize);
+
+ printf (" %c%c%c %2d %2x %d \n",
+ (spnt->sh_flags & 1 ? 'W' : ' '),
+ (spnt->sh_flags & 2 ? 'A' : ' '),
+ (spnt->sh_flags & 4 ? 'X' : ' '),
+ spnt->sh_link,
+ spnt->sh_info,
+ spnt->sh_addralign);
+ spnt ++;
+ }
+}
+
+/* Parse the dynamic segment */
+static void
+process_dynamic_segment ()
+{
+ Elf_Dyn * elf_dynamic;
+ unsigned int i;
+
+ dynamic_size = dynamic_size / sizeof (Elf_Dyn);
+
+ if (must_swap)
+ {
+ Elf_Dyn * new_header = malloc (sizeof (* new_header) * dynamic_size);
+
+ if (new_header == NULL)
+ {
+ error (_("out of memory\n"));
+ return;
+ }
+
+ memcpy (new_header, & header [dynamic_addr],
+ sizeof (* new_header) * dynamic_size);
+
+ elf_dynamic = dpnt = new_header;
+
+ for (i = 0; i < dynamic_size; i++)
+ {
+ BYTE_SWAP (dpnt + i, d_tag);
+ BYTE_SWAP (dpnt + i, d_un.d_ptr);
+
+ new_header ++;
+ }
+ }
+ else
+ {
+ dpnt = (Elf_Dyn *) & header [dynamic_addr];
+ elf_dynamic = NULL;
+ }
+
+ /* Find symtab. */
+ for (i = 0; i < dynamic_size; ++i, ++dpnt)
+ if (dpnt->d_tag == DT_SYMTAB)
+ {
+ dynamic_info [DT_SYMTAB] = dpnt->d_un.d_val;
+ symtab = (Elf_Sym *) (header - loadaddr
+ + dynamic_info[DT_SYMTAB]);
+ }
+ else if (dpnt->d_tag == DT_STRTAB)
+ {
+ dynamic_info [DT_STRTAB] = dpnt->d_un.d_val;
+ strtab = (char *) (header - loadaddr + dynamic_info[DT_STRTAB]);
+ }
+
+ if (do_dynamic && dynamic_addr)
+ {
+ printf (_("\n Dynamic section data: %x, %d entries\n"),
+ dynamic_addr, dynamic_size );
+ }
+
+ for (i = 0; i < dynamic_size; i++)
+ {
+ if (do_dynamic)
+ printf (_(" Tag: %#10x: "), dpnt->d_tag);
+
+ switch (dpnt->d_tag)
+ {
+ case DT_AUXILIARY:
+ case DT_FILTER:
+ if (do_dynamic)
+ {
+ printf ("(%-11s)", filtertype [DT_FILTER - dpnt->d_tag]);
+
+ if (dynamic_info [DT_STRTAB])
+ {
+ if (dpnt->d_tag == DT_AUXILIARY)
+ printf (_("Auxiliary library"));
+ else
+ printf (_("Filter library"));
+
+ printf (": [%s]\n", (dpnt->d_un.d_val + strtab));
+ }
+ else
+ printf (_("Value %x\n"), dpnt->d_un.d_val);
+ }
+ break;
+
+ case DT_NULL :
+ case DT_NEEDED :
+ case DT_PLTRELSZ:
+ case DT_PLTGOT :
+ case DT_HASH :
+ case DT_STRTAB :
+ case DT_SYMTAB :
+ case DT_RELA :
+ case DT_RELASZ :
+ case DT_RELAENT :
+ case DT_STRSZ :
+ case DT_SYMENT :
+ case DT_INIT :
+ case DT_FINI :
+ case DT_SONAME :
+ case DT_RPATH :
+ case DT_SYMBOLIC:
+ case DT_REL :
+ case DT_RELSZ :
+ case DT_RELENT :
+ case DT_PLTREL :
+ case DT_DEBUG :
+ case DT_TEXTREL :
+ case DT_JMPREL :
+ dynamic_info [dpnt->d_tag] = dpnt->d_un.d_val;
+
+ if (do_dynamic)
+ {
+ printf ("(%-11s)", dyntype [dpnt->d_tag]);
+
+ if (dynamic_info [DT_STRTAB])
+ {
+ switch (dpnt->d_tag)
+ {
+ case DT_NEEDED:
+ printf (_("Shared library: [%s]\n"),
+ (dpnt->d_un.d_val + strtab));
+
+ if (strcmp (dpnt->d_un.d_val + strtab, pint))
+ printf ("\n");
+ else
+ printf (_(" program interpreter\n"));
+ break;
+
+ case DT_SONAME:
+ printf (_("Library soname: [%s]\n"),
+ (dpnt->d_un.d_val + strtab));
+ break;
+
+ case DT_RPATH:
+ printf (_("Library rpath: [%s]\n"),
+ (dpnt->d_un.d_val + strtab));
+ break;
+
+ default:
+ printf (_("Value %x\n"), dpnt->d_un.d_val);
+ }
+ }
+ else
+ printf (_("Value %x\n"), dpnt->d_un.d_val);
+ }
+ break;
+
+ default:
+ if ((dpnt->d_tag >= DT_VERSYM) && (dpnt->d_tag <= DT_VERNEEDNUM))
+ {
+ version_info [DT_VERSIONTAGIDX (dpnt->d_tag)] = dpnt->d_un.d_val;
+
+ if (do_dynamic)
+ printf (_("(%-11s) Value %#x\n"),
+ vertype [DT_VERSIONTAGIDX (dpnt->d_tag)],
+ dpnt->d_un.d_ptr);
+ }
+ else
+ warn (_("<Invalid> Value %#x\n"), dpnt->d_un.d_ptr);
+ break;
+ }
+
+ dpnt ++;
+ }
+
+ if (do_reloc)
+ {
+ if (do_using_dynamic)
+ {
+ if (dynamic_info [DT_REL])
+ {
+ rpnt = (Elf_Rel *) (header + dynamic_info [DT_REL] - loadaddr);
+ rel_size = dynamic_info [DT_RELSZ];
+ if (rel_size)
+ {
+ printf (_("\nRelocation section data: %x %x\n"),
+ dynamic_info[DT_REL], rel_size);
+ dump_relocations (rpnt, rel_size);
+ }
+ else
+ printf (_("\nNo Relocations in this file\n"));
+ }
+
+ if (dynamic_info[DT_RELA])
+ {
+ rpnt = (Elf_Rel *) (header + dynamic_info[DT_RELA] - loadaddr);
+ rel_size = dynamic_info[DT_RELASZ];
+ if (rel_size)
+ {
+ printf (_("\nRelocation section data: %x %x\n"),
+ dynamic_info[DT_RELA], rel_size);
+ dump_relocations (rpnt, rel_size);
+ }
+ else
+ printf (_("\nNo Relocations in this file\n"));
+ }
+
+ if (dynamic_info[DT_JMPREL])
+ {
+ rpnt = (Elf_Rel *) (header + dynamic_info[DT_JMPREL]
+ - loadaddr);
+ rel_size = dynamic_info[DT_PLTRELSZ];
+ if (rel_size)
+ {
+ printf (_("\nJumptable Relocation section data: %x %x\n"),
+ dynamic_info[DT_JMPREL], rel_size);
+ dump_relocations (rpnt, rel_size);
+ }
+ else
+ printf (_("\nNo Relocations in this file\n"));
+ }
+ }
+ else
+ {
+ Elf_Shdr * spnt;
+
+ spnt = elf_sections;
+
+ for (i = 0; i < epnt->e_shnum; i++, spnt++)
+ {
+ Elf_Shdr * symsec;
+
+
+ if (spnt->sh_type != SHT_RELA && spnt->sh_type != SHT_REL)
+ continue;
+
+ rpnt = (Elf_Rel *) (header + spnt->sh_offset);
+
+ rel_size = spnt->sh_size;
+
+ if (rel_size)
+ {
+ printf (_("\nRelocation section data: %s (%#x entries)\n"),
+ SECTION_NAME (spnt), rel_size / spnt->sh_entsize);
+
+ symsec = & elf_sections [spnt->sh_link];
+ symtab = (Elf_Sym *) (header + symsec->sh_offset);
+ strtab = (char *) (header
+ + elf_sections [symsec->sh_link].sh_offset);
+
+ dump_relocations (rpnt, rel_size);
+ }
+ else
+ printf (_("\nNo Relocations in this file\n"));
+ }
+ }
+ }
+
+ if (elf_dynamic)
+ free (elf_dynamic);
+}
+
+/* Dump the symbol table */
+static void
+process_symbol_table ()
+{
+ char * pnt;
+ int i;
+ Elf_Shdr * spnt;
+
+ if (! do_syms)
+ return;
+
+ if (dynamic_info [DT_HASH] && do_using_dynamic)
+ {
+ int nbucket;
+ int nchain;
+ int * elf_buckets;
+ int * chains;
+ int hn;
+ int si;
+ int * hash_addr;
+
+ hash_addr = (int *) (dynamic_info [DT_HASH] + header - loadaddr);
+
+ nbucket = *hash_addr++;
+ nchain = *hash_addr++;
+ elf_buckets = hash_addr;
+ hash_addr += nbucket;
+ chains = hash_addr;
+
+ printf (_("\n Symbol table for image\n"));
+ printf (_(" Num Buc: Value Size Type Bind Ot Ndx Name\n"));
+
+ for (hn = 0; hn < nbucket; hn++)
+ {
+ if (! elf_buckets [hn])
+ continue;
+
+ for (si = elf_buckets[hn]; si; si = chains[si])
+ {
+ pnt = strtab + symtab[si].st_name;
+
+ printf ("%3d %3d: %8x %5d %6s %6s %2d ", si, hn,
+ symtab[si].st_value,
+ symtab[si].st_size,
+ sttinfo [ELF_ST_TYPE (symtab[si].st_info)],
+ stbinfo [ELF_ST_BIND (symtab[si].st_info)],
+ symtab[si].st_other);
+
+ if (symtab[si].st_shndx == 0)
+ printf ("UND");
+ else if ((symtab[si].st_shndx & 0xffff) == 0xfff1)
+ printf ("ABS");
+ else if ((symtab[si].st_shndx & 0xffff) == 0xfff2)
+ printf ("COM");
+ else
+ printf ("%3d", symtab[si].st_shndx);
+ printf (" %s\n", pnt);
+ }
+ }
+ }
+ else if (!do_using_dynamic)
+ {
+ int i;
+ unsigned short * vers_addr;
+
+ spnt = elf_sections;
+ vers_addr = (short *) (version_info [DT_VERNEEDNUM - DT_VERSYM]
+ + header - loadaddr);
+
+ for (i = 0; i < epnt->e_shnum; i++, spnt++)
+ {
+ unsigned int si;
+
+ if (spnt->sh_type != SHT_SYMTAB && spnt->sh_type != SHT_DYNSYM)
+ continue;
+
+ printf (_("\nSymbol data for: %s\n"), SECTION_NAME (spnt));
+ printf (_(" Num: Value Size Type Bind Ot Ndx Name\n"));
+
+ symtab = (Elf_Sym *) (header + spnt->sh_offset);
+ strtab = (char *) (header + elf_sections [spnt->sh_link].sh_offset);
+
+ for (si = 0; si < spnt->sh_size / spnt->sh_entsize; si++)
+ {
+ Elf_Sym ssym;
+ Elf_Sym * psym;
+ Elf_Sym * new_header;
+
+ psym = symtab + si;
+
+ if (must_swap)
+ {
+ ssym = * psym;
+
+ new_header = & ssym;
+
+ BYTE_SWAP (psym, st_name);
+ BYTE_SWAP (psym, st_value);
+ BYTE_SWAP (psym, st_size);
+ BYTE_SWAP (psym, st_shndx);
+
+ psym = new_header;
+ }
+
+ pnt = strtab + psym->st_name;
+
+ printf (" %3d: %8x %5d %-7s %-6s %2d ", si,
+ psym->st_value,
+ psym->st_size,
+ sttinfo [ELF_ST_TYPE (psym->st_info)],
+ stbinfo [ELF_ST_BIND (psym->st_info)],
+ psym->st_other);
+
+ if (psym->st_shndx == 0)
+ printf ("UND");
+ else if ((psym->st_shndx & 0xffff) == 0xfff1)
+ printf ("ABS");
+ else if ((psym->st_shndx & 0xffff) == 0xfff2)
+ printf ("COM");
+ else
+ printf ("%3d", psym->st_shndx);
+ printf (" %s", pnt);
+
+ if (spnt->sh_type == SHT_DYNSYM &&
+ version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0 &&
+ ((vers_addr[si] & 0x8000) || vers_addr[si] > 1))
+ {
+ Elf_Vernaux * a;
+
+ if (elf_sections [psym->st_shndx].sh_type == SHT_NOBITS
+ || psym->st_shndx == SHN_UNDEF)
+ {
+ Elf_Verneed * v;
+
+ /* We must test both. */
+ v = (Elf_Verneed *)
+ (version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
+ + header - loadaddr);
+
+ for (;;)
+ {
+ a = (Elf_Vernaux *)((char *)v + v->vn_aux);
+
+ while (a->vna_other != vers_addr[si]
+ && a->vna_next != 0)
+ a = (Elf_Vernaux *)((char *)a + a->vna_next);
+
+ if (a->vna_other == vers_addr[si])
+ break;
+
+ if (v->vn_next == 0)
+ {
+ if (elf_sections [psym->st_shndx].sh_type
+ != SHT_NOBITS)
+ error (_("bad dynamic symbol"));
+
+ a = NULL;
+ break;
+ }
+
+ v = (Elf_Verneed *)((char *)v + v->vn_next);
+ }
+
+ if (a != NULL)
+ printf ("@%s (%d)", strtab + a->vna_name, a->vna_other);
+ }
+ else if ((elf_sections [psym->st_shndx].sh_type
+ == SHT_NOBITS && a == NULL)
+ || psym->st_shndx != SHN_UNDEF)
+ {
+ Elf_Verdef * v;
+ Elf_Verdaux * b;
+
+ v = (Elf_Verdef *)
+ (version_info [DT_VERSIONTAGIDX (DT_VERDEF)]
+ + header - loadaddr);
+
+ if (vers_addr[si] == 0x8001)
+ pnt = "";
+ else
+ {
+ while (v->vd_ndx != (vers_addr [si] & 0x7fff))
+ v = (Elf_Verdef *)((char *)v + v->vd_next);
+
+ b = (Elf_Verdaux *) ((char *)v + v->vd_aux);
+
+ if (psym->st_name != b->vda_name)
+ pnt = strtab + b->vda_name;
+ else
+ pnt = NULL;
+ }
+
+ if (pnt)
+ printf ((vers_addr [si] & 0x8000)
+ ? "@%s" : "@@%s", pnt);
+ }
+ }
+
+ puts ("");
+ }
+ }
+ }
+
+ if (! do_version)
+ return;
+
+ spnt = elf_sections;
+
+ for (i = 0; i < epnt->e_shnum; i++, spnt++)
+ {
+ if (spnt->sh_type == SHT_GNU_verdef)
+ {
+ Elf_Shdr * dspnt = &elf_sections[spnt->sh_link];
+ unsigned int idx;
+ unsigned int cnt;
+
+ strtab = (char *) (header - loadaddr + dynamic_info[DT_STRTAB]);
+
+ printf (_("\n Version definitions:%s (%#0x entries)\n"),
+ SECTION_NAME(spnt), spnt->sh_info);
+ printf (_("Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
+ spnt->sh_addr, spnt->sh_offset, spnt->sh_link,
+ SECTION_NAME(dspnt));
+
+ for (idx = cnt = 0; cnt < spnt->sh_info; ++cnt)
+ {
+ Elf_Verdef * ent = (Elf_Verdef *)
+ ((char *) header + spnt->sh_offset + idx);
+ Elf_Verdaux * aux = (Elf_Verdaux *)
+ ((char *) ent + ent->vd_aux);
+ int j, isum;
+
+ printf (_("%#06x: Rev: %d Flags: "), idx, ent->vd_version);
+
+ if (ent->vd_flags == 0)
+ printf (_("none"));
+ else
+ {
+ int f = 1;
+ if (ent->vd_flags & 0x1)
+ {
+ printf (_("BASE"));
+ f = 0;
+ }
+ if (ent->vd_flags & 0x2)
+ {
+ printf (_("%sWEAK"), f ? "" : "|");
+ f = 0;
+ }
+ }
+ printf (_(" Index: %d Cnt: %d Name: %s\n"),
+ ent->vd_ndx, ent->vd_cnt, strtab + aux->vda_name);
+ j = 1;
+ isum = idx + ent->vd_aux;
+ while (j < ent->vd_cnt)
+ {
+ isum += aux->vda_next;
+ aux = (Elf_Verdaux *)((char *)aux + aux->vda_next);
+ printf (_(" %#06x: Parent %d: %s\n"), isum, j,
+ strtab + aux->vda_name);
+ ++j;
+ }
+
+ idx += ent->vd_next;
+ }
+ }
+
+ if (spnt->sh_type == SHT_GNU_verneed)
+ {
+ Elf_Shdr * dspnt = &elf_sections[spnt->sh_link];
+ unsigned int idx;
+ unsigned int cnt;
+
+ strtab = (char *) (header - loadaddr + dynamic_info[DT_STRTAB]);
+ printf (_("\n Needed versions:%s (%#0x entries)\n"),
+ SECTION_NAME (spnt), spnt->sh_info);
+ printf (_("Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
+ spnt->sh_addr, spnt->sh_offset, spnt->sh_link,
+ SECTION_NAME (dspnt));
+
+ for (idx = cnt = 0; cnt < spnt->sh_info; ++cnt)
+ {
+ Elf_Verneed * ent = (Elf_Verneed *)
+ ((char *) header + spnt->sh_offset + idx);
+ Elf_Vernaux * aux = (Elf_Vernaux *)
+ ((char *) ent + ent->vn_aux);
+ int j, isum;
+
+ printf (_("%#06x: Version: %d File: %s Cnt: %d\n"),
+ idx, ent->vn_version, strtab + ent->vn_file,ent->vn_cnt);
+
+ for (j = 0, isum = idx + ent->vn_aux; j < ent->vn_cnt; ++j)
+ {
+ printf (_(" %#06x: Name: %s Flags: %s Version: %d\n"),
+ isum, strtab+aux->vna_name,
+ aux->vna_flags & 0x2 ? "WEAK" : "none",
+ aux->vna_other);
+ isum += aux->vna_next;
+ aux = (Elf_Vernaux *)((char *) aux + aux->vna_next);
+ }
+
+ idx += ent->vn_next;
+ }
+ }
+
+ if (spnt->sh_type == SHT_GNU_versym)
+ {
+ Elf_Shdr * dspnt = &elf_sections[spnt->sh_link];
+ int total = spnt->sh_size / spnt->sh_entsize;
+ int cnt;
+ unsigned short * p = (short *)
+ (version_info[DT_VERNEEDNUM - DT_VERSYM] + header - loadaddr);
+
+ symtab = (Elf_Sym *) (header + dspnt->sh_offset);
+ strtab = (char *) (header + elf_sections[dspnt->sh_link].sh_offset);
+
+ printf (_("\n Version symbols:%s (%#0x entries)\n"),
+ SECTION_NAME (spnt), total);
+ printf (_("Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
+ spnt->sh_addr, spnt->sh_offset, spnt->sh_link,
+ SECTION_NAME (dspnt));
+
+ for (cnt = 0; cnt < total; cnt += 4)
+ {
+ int j, nn;
+
+ printf ("%#08x:", cnt);
+
+ for (j = 0; (j < 4) && (cnt + j) < total; ++j)
+ switch (p[cnt + j])
+ {
+ case 0:
+ printf (" 0 (*local*) ");
+ break;
+ case 1:
+ printf (" 1 (*global*) ");
+ break;
+ default:
+ nn = printf ("%4x%c", p[cnt + j] & 0x7fff,
+ p[cnt + j] & 0x8000 ? 'h' : ' ');
+ if (elf_sections[symtab[cnt + j].st_shndx].sh_type
+ == SHT_NOBITS)
+ {
+ /* We must test both. */
+ Elf_Verneed * v = (Elf_Verneed *)
+ (version_info [DT_VERNEEDNUM - DT_VERNEED]
+ + header - loadaddr);
+ Elf_Vernaux * a = NULL;
+
+ for (;;)
+ {
+ a = (Elf_Vernaux *)((char *) v + v->vn_aux);
+
+ while (a->vna_other != p[cnt + j]
+ && a->vna_next != 0)
+ a = (Elf_Vernaux *)((char *) a + a->vna_next);
+
+ if (a->vna_other == p[cnt + j])
+ break;
+
+ if (v->vn_next == 0)
+ {
+ a = NULL;
+ break;
+ }
+
+ v = (Elf_Verneed *)((char *)v + v->vn_next);
+ }
+
+ if (a != NULL)
+ nn += printf ("(%s)", strtab + a->vna_name);
+ else
+ {
+ Elf_Verdef * v = (Elf_Verdef *)
+ (version_info [DT_VERNEEDNUM - DT_VERDEF]
+ + header - loadaddr);
+ Elf_Verdaux * a;
+
+ if (p[cnt + j] == 0x8001)
+ pnt = "";
+ else
+ {
+ while (v->vd_ndx != (p[cnt + j]&0x7fff))
+ v = (Elf_Verdef *)((char *)v + v->vd_next);
+
+ a = (Elf_Verdaux *) ((char *) v + v->vd_aux);
+ pnt = strtab + a->vda_name;
+ }
+
+ if (pnt)
+ nn += printf ("(%s)", pnt);
+ }
+
+ if (nn <16)
+ printf ("%*c", 16 - nn, ' ');
+ }
+ else if (symtab[cnt + j].st_shndx ==SHN_UNDEF)
+ {
+ Elf_Verneed * v = (Elf_Verneed *)
+ (version_info [DT_VERNEEDNUM - DT_VERNEED]
+ + header - loadaddr);
+ Elf_Vernaux * a;
+
+ for (;;)
+ {
+ a = (Elf_Vernaux *)((char *) v + v->vn_aux);
+
+ while (a->vna_other != p[cnt + j]
+ && a->vna_next != 0)
+ a = (Elf_Vernaux *)((char *)a + a->vna_next);
+
+ if (a->vna_other == p[cnt + j])
+ break;
+
+ v = (Elf_Verneed *)((char *) v + v->vn_next);
+ }
+
+ nn += printf ("(%s)", strtab + a->vna_name);
+
+ if (nn <16)
+ printf ("%*c", 16 - nn, ' ');
+ }
+ else
+ {
+ Elf_Verdef * v = (Elf_Verdef *)
+ (version_info [DT_VERNEEDNUM - DT_VERDEF]
+ + header - loadaddr);
+ Elf_Verdaux * a;
+
+ if (p[cnt + j] == 0x8001)
+ pnt = "";
+ else
+ {
+ while (v->vd_ndx != (p[cnt + j] & 0x7fff))
+ v = (Elf_Verdef *)((char *) v + v->vd_next);
+
+ a = (Elf_Verdaux *) ((char *) v + v->vd_aux);
+ pnt = strtab + a->vda_name;
+ }
+
+ if (pnt)
+ nn += printf ("(%s)", pnt);
+
+ if (nn <16)
+ printf ("%*c", 16 - nn, ' ');
+ }
+ }
+
+ printf ("\n");
+ }
+ }
+ }
+}
+
+static void
+process_section_contents ()
+{
+ Elf_Shdr * spnt;
+ int i;
+
+ if (! do_dump)
+ return;
+
+ spnt = elf_sections;
+
+ for (i = 0; i < epnt->e_shnum; i++, spnt++)
+ {
+ int bytes;
+ int addr;
+ int lbytes;
+ unsigned char * my_addr;
+
+#ifdef SUPPORT_DISASSEMBLY
+ /* See if we need an assembly dump of this section */
+
+ if ((i < NUM_DUMP_SECTS) && (dump_sects[i] & DISASS_DUMP))
+ {
+ printf (_("\nAssembly dump of section %s\n"), SECTION_NAME (spnt));
+
+ bytes = spnt->sh_size;
+ addr = spnt->sh_addr;
+ my_addr = (unsigned char *) (header + spnt->sh_offset);
+
+ while (bytes > 0)
+ {
+ printf ("0x%8.8x ", addr);
+
+ switch (epnt->e_machine)
+ {
+ case EM_386:
+ case EM_486:
+ lbytes = db_disasm ((unsigned int) my_addr, 0, 0) -
+ ((unsigned int) my_addr);
+ break;
+ case EM_68K:
+ lbytes = (m68k_disass ((unsigned int) my_addr, addr)
+ - (unsigned int) my_addr);
+ break;
+ default:
+ warn (_("Unable to disassemble code for this platform\n"));
+ return;
+ }
+
+ addr += lbytes;
+ my_addr += lbytes;
+ bytes -= lbytes;
+
+ printf ("\n");
+ }
+ }
+#endif
+
+ /* OK, see if we need a hex dump of this section. */
+ if ((i < NUM_DUMP_SECTS) && (dump_sects[i] & HEX_DUMP))
+ {
+ int j;
+ int k;
+
+ printf (_("\nHex dump of section %s\n"), SECTION_NAME (spnt));
+
+ bytes = spnt->sh_size;
+ addr = spnt->sh_addr;
+ my_addr = (unsigned char *) (header + spnt->sh_offset);
+
+ while (bytes)
+ {
+ lbytes = (bytes > 16 ? 16 : bytes);
+
+ printf ("0x%8.8x ",addr);
+
+ switch (epnt->e_ident [EI_DATA])
+ {
+ case ELFDATA2LSB:
+ for (j = 15; j >= 0; j --)
+ {
+ if (j < lbytes)
+ printf ("%2.2x", my_addr[j]);
+ else
+ printf (" ");
+
+ if (!(j & 0x3))
+ printf (" ");
+ }
+ break;
+
+ case ELFDATA2MSB:
+ for (j = 0; j < 16; j++)
+ {
+ if (j < lbytes)
+ printf ("%2.2x", my_addr[j]);
+ else
+ printf (" ");
+
+ if ((j & 3) == 3)
+ printf (" ");
+ }
+ break;
+ }
+
+ for (j = 0; j < lbytes; j++)
+ {
+ k = my_addr [j];
+ if (k >= ' ' && k < 0x80)
+ printf ("%c", k);
+ else
+ printf (".");
+ }
+
+ printf ("\n");
+
+ my_addr += lbytes;
+ addr += lbytes;
+ bytes -= lbytes;
+ }
+ }
+ }
+}
+
+static void
+process_file (file_name)
+ char * file_name;
+{
+ int fd;
+ struct stat statbuf;
+
+ must_swap = 0;
+
+ fd = open (file_name, O_RDONLY);
+ if (fd == -1)
+ {
+ error (_("Input file %s not found.\n"), file_name);
+ return;
+ }
+
+ if (fstat (fd, & statbuf) < 0)
+ {
+ error (_("Cannot stat input file %s.\n"), file_name);
+ close (fd);
+ return;
+ }
+
+ header = mmap (0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+
+ if ((header == (char *) -1) || (header == NULL))
+ {
+ error (_("Cannot mmap %s: %s\n"), file_name, strerror (errno));
+ close (fd);
+ return;
+ }
+
+ close (fd);
+
+ epnt = (Elf_Ehdr *) header;
+
+ if (show_name)
+ printf (_("\nFile: %s\n"), file_name);
+
+ if (! process_elf_header ())
+ {
+ munmap (header, statbuf.st_size);
+ return;
+ }
+
+ process_program_headers ();
+
+ if (loadaddr == -1)
+ {
+ /* Very strange. */
+ loadaddr = 0;
+ }
+
+ process_section_headers ();
+
+ process_dynamic_segment ();
+
+ process_symbol_table ();
+
+ process_section_contents ();
+
+ munmap (header, statbuf.st_size);
+
+ if (must_swap)
+ {
+ if (epnt)
+ {
+ free (epnt);
+ epnt = NULL;
+ }
+
+ if (elf_sections)
+ {
+ free (elf_sections);
+ elf_sections = NULL;
+ }
+ }
+}
+
+#ifdef SUPPORT_DISASSEMBLY
+/* Needed by the i386 disassembler. For extra credit, someone could
+fix this so that we insert symbolic addresses here, esp for GOT/PLT
+symbols */
+
+void
+print_address (unsigned int addr, FILE * outfile)
+{
+ fprintf (outfile,"0x%8.8x", addr);
+}
+
+/* Needed by the i386 disassembler. */
+void
+db_task_printsym (unsigned int addr)
+{
+ print_address (addr, stderr);
+}
+#endif
+
+int
+main (argc, argv)
+ int argc;
+ char ** argv;
+{
+ parse_args (argc, argv);
+
+ expected_endian = 0x12345678;
+
+ if (* ((char *) & expected_endian) == 0x12)
+ expected_endian = ELFDATA2MSB;
+ else
+ expected_endian = ELFDATA2LSB;
+
+ if (optind < (argc - 1))
+ show_name = 1;
+
+ while (optind < argc)
+ process_file (argv [optind ++]);
+
+ return 0;
+}
diff --git a/binutils/readelf.h b/binutils/readelf.h
new file mode 100644
index 0000000..371716e
--- /dev/null
+++ b/binutils/readelf.h
@@ -0,0 +1,173 @@
+/* readelf.h -- This file contains structures similar to those found in
+ include/elf/internal.h. These structures however, match the layout of
+ the information in the file, rather than being optimised for internal
+ storage.
+
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _READELF_H
+#define _READELF_H
+
+#include "bfd.h"
+#include "elf/common.h"
+
+/* The type 'bfd_vma' is used in places where the 64 bit version of the
+ structure has a 64 bit wide field, and the 32 bit version has a 32 bit wide
+ field. It does not necessarily imply that the field contains an address. */
+
+#define EI_NIDENT 16
+
+/* The ELF file header. This appears at the start of every ELF file. */
+typedef struct
+{
+ unsigned char e_ident [EI_NIDENT]; /* Magic number and other info */
+ unsigned short e_type; /* Object file type */
+ unsigned short e_machine; /* Architecture */
+ unsigned long e_version; /* Object file version */
+ bfd_vma e_entry; /* Entry point virtual address */
+ bfd_vma e_phoff; /* Program header table file offset */
+ bfd_vma e_shoff; /* Section header table file offset */
+ unsigned long e_flags; /* Processor-specific flags */
+ unsigned short e_ehsize; /* ELF header size in bytes */
+ unsigned short e_phentsize; /* Program header table entry size */
+ unsigned short e_phnum; /* Program header table entry count */
+ unsigned short e_shentsize; /* Section header table entry size */
+ unsigned short e_shnum; /* Section header table entry count */
+ unsigned short e_shstrndx; /* Section header string table index */
+}
+Elf_Ehdr;
+
+/* Program Segment Header. (Might be wrong for 64 bit ELF formats). */
+typedef struct
+{
+ unsigned long p_type; /* Segment type */
+ bfd_vma p_offset; /* Segment file offset */
+ bfd_vma p_vaddr; /* Segment virtual address */
+ bfd_vma p_paddr; /* Segment physical address */
+ unsigned long p_filesz; /* Segment size in file */
+ unsigned long p_memsz; /* Segment size in memory */
+ unsigned long p_flags; /* Segment flags */
+ unsigned long p_align; /* Segment alignment */
+}
+Elf_Phdr;
+
+/* Section header. */
+typedef struct
+{
+ unsigned long sh_name; /* Section name (string tbl index) */
+ unsigned long sh_type; /* Section type */
+ bfd_vma sh_flags; /* Section flags */
+ bfd_vma sh_addr; /* Section virtual addr at execution */
+ bfd_vma sh_offset; /* Section file offset */
+ unsigned long sh_size; /* Section size in bytes */
+ unsigned long sh_link; /* Link to another section */
+ unsigned long sh_info; /* Additional section information */
+ bfd_vma sh_addralign; /* Section alignment */
+ bfd_vma sh_entsize; /* Entry size if section holds table */
+}
+Elf_Shdr;
+
+/* Symbol table entry. (Might be incorrect for 64 bit ELF formats) */
+typedef struct
+{
+ unsigned long st_name; /* Symbol name (string tbl index) */
+ bfd_vma st_value; /* Symbol value */
+ bfd_vma st_size; /* Symbol size */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* No defined meaning, 0 */
+ unsigned short st_shndx; /* Section index */
+}
+Elf_Sym;
+
+/* Version definition sections. */
+typedef struct
+{
+ unsigned short vd_version; /* Version number of structure. */
+ unsigned short vd_flags; /* Flags (VER_FLG_*). */
+ unsigned short vd_ndx; /* Version index. */
+ unsigned short vd_cnt; /* Number of verdaux entries. */
+ unsigned long vd_hash; /* Hash of name. */
+ unsigned long vd_aux; /* Offset to verdaux entries. */
+ unsigned long vd_next; /* Offset to next verdef. */
+}
+Elf_Verdef;
+
+/* Auxialiary version information. */
+typedef struct
+{
+ unsigned long vda_name; /* String table offset of name. */
+ unsigned long vda_next; /* Offset to next verdaux. */
+}
+Elf_Verdaux;
+
+/* Version dependency section. */
+typedef struct
+{
+ unsigned short vn_version; /* Version number of structure. */
+ unsigned short vn_cnt; /* Number of vernaux entries. */
+ unsigned long vn_file; /* String table offset of library name. */
+ unsigned long vn_aux; /* Offset to vernaux entries. */
+ unsigned long vn_next; /* Offset to next verneed. */
+}
+Elf_Verneed;
+
+/* Auxiliary needed version information. */
+typedef struct
+{
+ unsigned long vna_hash; /* Hash of dependency name. */
+ unsigned short vna_flags; /* Flags (VER_FLG_*). */
+ unsigned short vna_other; /* Unused. */
+ unsigned long vna_name; /* String table offset to version name. */
+ unsigned long vna_next; /* Offset to next vernaux. */
+}
+Elf_Vernaux;
+
+/* Relocation table entry without addend. */
+typedef struct
+{
+ bfd_vma r_offset; /* Location at which to apply the action */
+ bfd_vma r_info; /* index and type of relocation */
+}
+Elf_Rel;
+
+/* Relocation table entry with addend. */
+typedef struct
+{
+ bfd_vma r_offset; /* Location at which to apply the action */
+ bfd_vma r_info; /* Index and Type of relocation */
+ bfd_signed_vma r_addend; /* Constant addend used to compute value */
+}
+Elf_Rela;
+
+/* Dynamic section entry. */
+typedef struct
+{
+ signed long d_tag; /* Dynamic entry type */
+ union
+ {
+ bfd_vma d_val; /* Integer value */
+ bfd_vma d_ptr; /* Address value */
+ } d_un;
+}
+Elf_Dyn;
+
+
+#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
+
+#endif /* _READELF_H */