Add 'readelf' to binutils.
authorNick Clifton <nickc@redhat.com>
Thu, 11 Jun 1998 21:51:56 +0000 (21:51 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 11 Jun 1998 21:51:56 +0000 (21:51 +0000)
binutils/.Sanitize
binutils/Makefile.am
binutils/Makefile.in
binutils/binutils.texi
binutils/readelf.c [new file with mode: 0644]
binutils/readelf.h [new file with mode: 0644]

index be27465062ef9ad7fc364bae26965a633650d708..f3166dac9502cb5c6b5b73de0013070bfd7a88d0 100644 (file)
@@ -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
index b06b6f5264329c0b08b9dd9b19bc701d6780dc53..c4529b2fe437f2f1f8f7ef15cb3ecd7b559f7ae2 100644 (file)
@@ -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
index bd282033991fc2aa6a1468fdf1299ad906a19159..ee1463e1ae567f61e3ea1c292b953a74a55cef83 100644 (file)
@@ -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
index 70f68b384ff5ee049c8bd9cd4ff626c53590ff8c..8f20e52819d933beef54435de10eed4dafd34245 100644 (file)
@@ -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 (file)
index 0000000..ee2f079
--- /dev/null
@@ -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.  */
+\f
+
+#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 (file)
index 0000000..371716e
--- /dev/null
@@ -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.  */
+\f
+#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 */