From 3284fe0c5e852fb8a3a06630c161b9633b9f6682 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Sun, 21 Nov 2010 21:27:15 +0000 Subject: Add and use elfcomm.c/elfcomm.h. 2010-11-21 H.J. Lu PR binutils/12235 * elfcomm.c: New. * elfcomm.h: Likewise. * Makefile.am (HFILES): Add elfcomm.h. (CFILES): Add elfcomm.c. (ELFLIBS): New. (readelf_SOURCES): Add $(ELFLIBS). (elfedit_SOURCES): Likewise. (objdump_SOURCES): Likewise. * Makefile.in: Regenerated. * dwarf.c: Include "elfcomm.h". (byte_get): Removed. (byte_get_little_endian): Likewise. (byte_get_big_endian): Likewise. (byte_get_signed): Likewise. (error): Likewise. (warn): Likewise. * dwarf.h (dwarf_vma): Defined with HOST_WIDEST_INT. (dwarf_size_type): Likewise. (byte_get): Removed. (byte_get_signed): Likewise. (byte_get_little_endian): Likewise. (byte_get_big_endian): Likewise. (error): Likewise. (warn): Likewise. * elfedit.c: Include "elfcomm.h". Don't include "aout/ar.h". Call error () instead of non_fatal (). (streq): Removed. (strneq): Likewise. (const_strneq): Likewise. (non_fatal): Likewise. (BYTE_GET): Likewise. (BYTE_PUT): Likewise. (byte_get): Likewise. (byte_put): Likewise. (byte_get_little_endian): Likewise. (byte_get_big_endian): Likewise. (byte_put_little_endian): Likewise. (byte_put_big_endian): Likewise. (adjust_relative_path): Likewise. (archive_info): Likewise. (setup_archive): Likewise. (release_archive): Likewise. (setup_nested_archive): Likewise. (get_archive_member_name): Likewise. (get_archive_member_name_at): Likewise. (make_qualified_name): Likewise. * objdump.c: Include "elfcomm.h". * readelf.c: Include "elfcomm.h". Don't include "aout/ar.h". (BYTE_GET): Removed. (BYTE_GET_SIGNED): Removed. (streq): Likewise. (strneq): Likewise. (const_strneq): Likewise. (byte_put): Likewise. (byte_put_little_endian): Likewise. (byte_put_big_endian): Likewise. (adjust_relative_path): Likewise. (archive_info): Likewise. (setup_archive): Likewise. (release_archive): Likewise. (setup_nested_archive): Likewise. (get_archive_member_name): Likewise. (get_archive_member_name_at): Likewise. (make_qualified_name): Likewise. --- binutils/ChangeLog | 74 ++++++ binutils/Makefile.am | 13 +- binutils/Makefile.in | 30 ++- binutils/dwarf.c | 142 +---------- binutils/dwarf.h | 19 +- binutils/elfcomm.c | 658 +++++++++++++++++++++++++++++++++++++++++++++++++++ binutils/elfcomm.h | 110 +++++++++ binutils/elfedit.c | 563 +++---------------------------------------- binutils/objdump.c | 1 + binutils/readelf.c | 504 +-------------------------------------- 10 files changed, 902 insertions(+), 1212 deletions(-) create mode 100644 binutils/elfcomm.c create mode 100644 binutils/elfcomm.h (limited to 'binutils') diff --git a/binutils/ChangeLog b/binutils/ChangeLog index d1300fc..a4f391e 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,77 @@ +2010-11-21 H.J. Lu + + PR binutils/12235 + * elfcomm.c: New. + * elfcomm.h: Likewise. + + * Makefile.am (HFILES): Add elfcomm.h. + (CFILES): Add elfcomm.c. + (ELFLIBS): New. + (readelf_SOURCES): Add $(ELFLIBS). + (elfedit_SOURCES): Likewise. + (objdump_SOURCES): Likewise. + * Makefile.in: Regenerated. + + * dwarf.c: Include "elfcomm.h". + (byte_get): Removed. + (byte_get_little_endian): Likewise. + (byte_get_big_endian): Likewise. + (byte_get_signed): Likewise. + (error): Likewise. + (warn): Likewise. + + * dwarf.h (dwarf_vma): Defined with HOST_WIDEST_INT. + (dwarf_size_type): Likewise. + (byte_get): Removed. + (byte_get_signed): Likewise. + (byte_get_little_endian): Likewise. + (byte_get_big_endian): Likewise. + (error): Likewise. + (warn): Likewise. + + * elfedit.c: Include "elfcomm.h". Don't include "aout/ar.h". + Call error () instead of non_fatal (). + (streq): Removed. + (strneq): Likewise. + (const_strneq): Likewise. + (non_fatal): Likewise. + (BYTE_GET): Likewise. + (BYTE_PUT): Likewise. + (byte_get): Likewise. + (byte_put): Likewise. + (byte_get_little_endian): Likewise. + (byte_get_big_endian): Likewise. + (byte_put_little_endian): Likewise. + (byte_put_big_endian): Likewise. + (adjust_relative_path): Likewise. + (archive_info): Likewise. + (setup_archive): Likewise. + (release_archive): Likewise. + (setup_nested_archive): Likewise. + (get_archive_member_name): Likewise. + (get_archive_member_name_at): Likewise. + (make_qualified_name): Likewise. + + * objdump.c: Include "elfcomm.h". + + * readelf.c: Include "elfcomm.h". Don't include "aout/ar.h". + (BYTE_GET): Removed. + (BYTE_GET_SIGNED): Removed. + (streq): Likewise. + (strneq): Likewise. + (const_strneq): Likewise. + (byte_put): Likewise. + (byte_put_little_endian): Likewise. + (byte_put_big_endian): Likewise. + (adjust_relative_path): Likewise. + (archive_info): Likewise. + (setup_archive): Likewise. + (release_archive): Likewise. + (setup_nested_archive): Likewise. + (get_archive_member_name): Likewise. + (get_archive_member_name_at): Likewise. + (make_qualified_name): Likewise. + 2010-11-18 Alan Modra PR binutils/11742 diff --git a/binutils/Makefile.am b/binutils/Makefile.am index 0978538..6546087 100644 --- a/binutils/Makefile.am +++ b/binutils/Makefile.am @@ -84,7 +84,7 @@ AM_CPPFLAGS = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) \ HFILES = \ arsup.h binemul.h bucomm.h budbg.h \ - coffgrok.h debug.h dlltool.h dwarf.h nlmconv.h \ + coffgrok.h debug.h dlltool.h dwarf.h elfcomm.h nlmconv.h \ sysdep.h unwind-ia64.h windres.h winduni.h windint.h \ windmc.h @@ -95,7 +95,7 @@ CFILES = \ addr2line.c ar.c arsup.c bin2c.c binemul.c bucomm.c \ coffdump.c coffgrok.c cxxfilt.c \ dwarf.c debug.c dlltool.c dllwrap.c \ - emul_aix.c emul_vanilla.c filemode.c \ + elfcomm.c emul_aix.c emul_vanilla.c filemode.c \ ieee.c is-ranlib.c is-strip.c maybe-ranlib.c maybe-strip.c \ nlmconv.c nm.c not-ranlib.c not-strip.c \ objcopy.c objdump.c prdbg.c \ @@ -116,6 +116,9 @@ WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c # Code shared by all the binutils. BULIBS = bucomm.c version.c filemode.c +# Code shared by the ELF related programs. +ELFLIBS = elfcomm.c + BFDLIB = ../bfd/libbfd.la OPCODES = ../opcodes/libopcodes.la @@ -192,17 +195,17 @@ objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) strings_SOURCES = strings.c $(BULIBS) -readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c +readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c $(ELFLIBS) readelf_LDADD = $(LIBINTL) $(LIBIBERTY) -elfedit_SOURCES = elfedit.c version.c +elfedit_SOURCES = elfedit.c version.c $(ELFLIBS) elfedit_LDADD = $(LIBINTL) $(LIBIBERTY) strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) nm_new_SOURCES = nm.c $(BULIBS) -objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS) +objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS) $(ELFLIBS) objdump_LDADD = $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL) objdump.@OBJEXT@:objdump.c diff --git a/binutils/Makefile.in b/binutils/Makefile.in index fddc931..8e3d7f2 100644 --- a/binutils/Makefile.in +++ b/binutils/Makefile.in @@ -121,7 +121,9 @@ am_dlltool_OBJECTS = dlltool.$(OBJEXT) defparse.$(OBJEXT) \ dlltool_OBJECTS = $(am_dlltool_OBJECTS) am_dllwrap_OBJECTS = dllwrap.$(OBJEXT) version.$(OBJEXT) dllwrap_OBJECTS = $(am_dllwrap_OBJECTS) -am_elfedit_OBJECTS = elfedit.$(OBJEXT) version.$(OBJEXT) +am__objects_2 = elfcomm.$(OBJEXT) +am_elfedit_OBJECTS = elfedit.$(OBJEXT) version.$(OBJEXT) \ + $(am__objects_2) elfedit_OBJECTS = $(am_elfedit_OBJECTS) am_nlmconv_OBJECTS = nlmconv.$(OBJEXT) nlmheader.$(OBJEXT) \ $(am__objects_1) @@ -130,22 +132,22 @@ nlmconv_LDADD = $(LDADD) am_nm_new_OBJECTS = nm.$(OBJEXT) $(am__objects_1) nm_new_OBJECTS = $(am_nm_new_OBJECTS) nm_new_LDADD = $(LDADD) -am__objects_2 = rddbg.$(OBJEXT) debug.$(OBJEXT) stabs.$(OBJEXT) \ +am__objects_3 = rddbg.$(OBJEXT) debug.$(OBJEXT) stabs.$(OBJEXT) \ ieee.$(OBJEXT) rdcoff.$(OBJEXT) -am__objects_3 = $(am__objects_2) wrstabs.$(OBJEXT) +am__objects_4 = $(am__objects_3) wrstabs.$(OBJEXT) am_objcopy_OBJECTS = objcopy.$(OBJEXT) not-strip.$(OBJEXT) \ - rename.$(OBJEXT) $(am__objects_3) $(am__objects_1) + rename.$(OBJEXT) $(am__objects_4) $(am__objects_1) objcopy_OBJECTS = $(am_objcopy_OBJECTS) objcopy_LDADD = $(LDADD) am_objdump_OBJECTS = objdump.$(OBJEXT) dwarf.$(OBJEXT) prdbg.$(OBJEXT) \ - $(am__objects_2) $(am__objects_1) + $(am__objects_3) $(am__objects_1) $(am__objects_2) objdump_OBJECTS = $(am_objdump_OBJECTS) am_ranlib_OBJECTS = ar.$(OBJEXT) is-ranlib.$(OBJEXT) arparse.$(OBJEXT) \ arlex.$(OBJEXT) arsup.$(OBJEXT) rename.$(OBJEXT) \ binemul.$(OBJEXT) emul_$(EMULATION).$(OBJEXT) $(am__objects_1) ranlib_OBJECTS = $(am_ranlib_OBJECTS) am_readelf_OBJECTS = readelf.$(OBJEXT) version.$(OBJEXT) \ - unwind-ia64.$(OBJEXT) dwarf.$(OBJEXT) + unwind-ia64.$(OBJEXT) dwarf.$(OBJEXT) $(am__objects_2) readelf_OBJECTS = $(am_readelf_OBJECTS) am_size_OBJECTS = size.$(OBJEXT) $(am__objects_1) size_OBJECTS = $(am_size_OBJECTS) @@ -158,7 +160,7 @@ am_strings_OBJECTS = strings.$(OBJEXT) $(am__objects_1) strings_OBJECTS = $(am_strings_OBJECTS) strings_LDADD = $(LDADD) am_strip_new_OBJECTS = objcopy.$(OBJEXT) is-strip.$(OBJEXT) \ - rename.$(OBJEXT) $(am__objects_3) $(am__objects_1) + rename.$(OBJEXT) $(am__objects_4) $(am__objects_1) strip_new_OBJECTS = $(am_strip_new_OBJECTS) strip_new_LDADD = $(LDADD) am_sysdump_OBJECTS = sysdump.$(OBJEXT) $(am__objects_1) @@ -426,7 +428,7 @@ AM_CPPFLAGS = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) \ HFILES = \ arsup.h binemul.h bucomm.h budbg.h \ - coffgrok.h debug.h dlltool.h dwarf.h nlmconv.h \ + coffgrok.h debug.h dlltool.h dwarf.h elfcomm.h nlmconv.h \ sysdep.h unwind-ia64.h windres.h winduni.h windint.h \ windmc.h @@ -436,7 +438,7 @@ CFILES = \ addr2line.c ar.c arsup.c bin2c.c binemul.c bucomm.c \ coffdump.c coffgrok.c cxxfilt.c \ dwarf.c debug.c dlltool.c dllwrap.c \ - emul_aix.c emul_vanilla.c filemode.c \ + elfcomm.c emul_aix.c emul_vanilla.c filemode.c \ ieee.c is-ranlib.c is-strip.c maybe-ranlib.c maybe-strip.c \ nlmconv.c nm.c not-ranlib.c not-strip.c \ objcopy.c objdump.c prdbg.c \ @@ -456,6 +458,9 @@ WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c # Code shared by all the binutils. BULIBS = bucomm.c version.c filemode.c + +# Code shared by the ELF related programs. +ELFLIBS = elfcomm.c BFDLIB = ../bfd/libbfd.la OPCODES = ../opcodes/libopcodes.la LIBIBERTY = ../libiberty/libiberty.a @@ -505,13 +510,13 @@ LDADD = $(BFDLIB) $(LIBIBERTY) $(LIBINTL) size_SOURCES = size.c $(BULIBS) objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) strings_SOURCES = strings.c $(BULIBS) -readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c +readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c $(ELFLIBS) readelf_LDADD = $(LIBINTL) $(LIBIBERTY) -elfedit_SOURCES = elfedit.c version.c +elfedit_SOURCES = elfedit.c version.c $(ELFLIBS) elfedit_LDADD = $(LIBINTL) $(LIBIBERTY) strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) nm_new_SOURCES = nm.c $(BULIBS) -objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS) +objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS) $(ELFLIBS) objdump_LDADD = $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL) cxxfilt_SOURCES = cxxfilt.c $(BULIBS) ar_SOURCES = arparse.y arlex.l ar.c not-ranlib.c arsup.c rename.c binemul.c \ @@ -771,6 +776,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlltool.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dllwrap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfcomm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfedit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emul_$(EMULATION).Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emul_aix.Po@am__quote@ diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 369304b..c986ca7 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -23,6 +23,7 @@ #include "libiberty.h" #include "bfd.h" #include "bucomm.h" +#include "elfcomm.h" #include "elf/common.h" #include "dwarf2.h" #include "dwarf.h" @@ -64,125 +65,6 @@ int do_wide; #define FLAG_DEBUG_LINES_RAW 1 #define FLAG_DEBUG_LINES_DECODED 2 -dwarf_vma (*byte_get) (unsigned char *, int); - -dwarf_vma -byte_get_little_endian (unsigned char *field, int size) -{ - switch (size) - { - case 1: - return *field; - - case 2: - return ((unsigned int) (field[0])) - | (((unsigned int) (field[1])) << 8); - - case 3: - return ((unsigned long) (field[0])) - | (((unsigned long) (field[1])) << 8) - | (((unsigned long) (field[2])) << 16); - - case 4: - return ((unsigned long) (field[0])) - | (((unsigned long) (field[1])) << 8) - | (((unsigned long) (field[2])) << 16) - | (((unsigned long) (field[3])) << 24); - - case 8: - if (sizeof (dwarf_vma) == 8) - return ((dwarf_vma) (field[0])) - | (((dwarf_vma) (field[1])) << 8) - | (((dwarf_vma) (field[2])) << 16) - | (((dwarf_vma) (field[3])) << 24) - | (((dwarf_vma) (field[4])) << 32) - | (((dwarf_vma) (field[5])) << 40) - | (((dwarf_vma) (field[6])) << 48) - | (((dwarf_vma) (field[7])) << 56); - else if (sizeof (dwarf_vma) == 4) - /* We want to extract data from an 8 byte wide field and - place it into a 4 byte wide field. Since this is a little - endian source we can just use the 4 byte extraction code. */ - return ((unsigned long) (field[0])) - | (((unsigned long) (field[1])) << 8) - | (((unsigned long) (field[2])) << 16) - | (((unsigned long) (field[3])) << 24); - - default: - error (_("Unhandled data length: %d\n"), size); - abort (); - } -} - -dwarf_vma -byte_get_big_endian (unsigned char *field, int size) -{ - switch (size) - { - case 1: - return *field; - - case 2: - return ((unsigned int) (field[1])) | (((int) (field[0])) << 8); - - case 3: - return ((unsigned long) (field[2])) - | (((unsigned long) (field[1])) << 8) - | (((unsigned long) (field[0])) << 16); - - case 4: - return ((unsigned long) (field[3])) - | (((unsigned long) (field[2])) << 8) - | (((unsigned long) (field[1])) << 16) - | (((unsigned long) (field[0])) << 24); - - case 8: - if (sizeof (dwarf_vma) == 8) - return ((dwarf_vma) (field[7])) - | (((dwarf_vma) (field[6])) << 8) - | (((dwarf_vma) (field[5])) << 16) - | (((dwarf_vma) (field[4])) << 24) - | (((dwarf_vma) (field[3])) << 32) - | (((dwarf_vma) (field[2])) << 40) - | (((dwarf_vma) (field[1])) << 48) - | (((dwarf_vma) (field[0])) << 56); - else if (sizeof (dwarf_vma) == 4) - { - /* Although we are extracing data from an 8 byte wide field, - we are returning only 4 bytes of data. */ - field += 4; - return ((unsigned long) (field[3])) - | (((unsigned long) (field[2])) << 8) - | (((unsigned long) (field[1])) << 16) - | (((unsigned long) (field[0])) << 24); - } - - default: - error (_("Unhandled data length: %d\n"), size); - abort (); - } -} - -dwarf_vma -byte_get_signed (unsigned char *field, int size) -{ - dwarf_vma x = byte_get (field, size); - - switch (size) - { - case 1: - return (x ^ 0x80) - 0x80; - case 2: - return (x ^ 0x8000) - 0x8000; - case 4: - return (x ^ 0x80000000) - 0x80000000; - case 8: - return x; - default: - abort (); - } -} - static int size_of_encoded_value (int encoding) { @@ -5020,28 +4902,6 @@ xcrealloc (void *ptr, size_t nmemb, size_t size) } void -error (const char *message, ...) -{ - va_list args; - - va_start (args, message); - fprintf (stderr, _("%s: Error: "), program_name); - vfprintf (stderr, message, args); - va_end (args); -} - -void -warn (const char *message, ...) -{ - va_list args; - - va_start (args, message); - fprintf (stderr, _("%s: Warning: "), program_name); - vfprintf (stderr, message, args); - va_end (args); -} - -void free_debug_memory (void) { unsigned int i; diff --git a/binutils/dwarf.h b/binutils/dwarf.h index 1c47c5e..e9de463 100644 --- a/binutils/dwarf.h +++ b/binutils/dwarf.h @@ -19,15 +19,8 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -#if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2) -/* We can't use any bfd types here since readelf may define BFD64 and - objdump may not. */ -typedef unsigned long long dwarf_vma; -typedef unsigned long long dwarf_size_type; -#else -typedef unsigned long dwarf_vma; -typedef unsigned long dwarf_size_type; -#endif +typedef unsigned HOST_WIDEST_INT dwarf_vma; +typedef unsigned HOST_WIDEST_INT dwarf_size_type; struct dwarf_section { @@ -100,11 +93,6 @@ typedef struct } debug_info; -extern dwarf_vma (*byte_get) (unsigned char *, int); -extern dwarf_vma byte_get_signed (unsigned char *, int); -extern dwarf_vma byte_get_little_endian (unsigned char *, int); -extern dwarf_vma byte_get_big_endian (unsigned char *, int); - extern int eh_addr_size; extern int do_debug_info; @@ -142,8 +130,5 @@ void *cmalloc (size_t, size_t); void *xcmalloc (size_t, size_t); void *xcrealloc (void *, size_t, size_t); -void error (const char *, ...) ATTRIBUTE_PRINTF_1; -void warn (const char *, ...) ATTRIBUTE_PRINTF_1; - unsigned long int read_leb128 (unsigned char *data, unsigned int *length_return, int sign); diff --git a/binutils/elfcomm.c b/binutils/elfcomm.c new file mode 100644 index 0000000..e44dee8 --- /dev/null +++ b/binutils/elfcomm.c @@ -0,0 +1,658 @@ +/* elfcomm.c -- common code for ELF format file. + Copyright 2010 + Free Software Foundation, Inc. + + Originally developed by Eric Youngdale + Modifications by Nick Clifton + + 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 3 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., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include "sysdep.h" +#include "libiberty.h" +#include "filenames.h" +#include "bfd.h" +#include "aout/ar.h" +#include "bucomm.h" +#include "elfcomm.h" + +void +error (const char *message, ...) +{ + va_list args; + + va_start (args, message); + fprintf (stderr, _("%s: Error: "), program_name); + vfprintf (stderr, message, args); + va_end (args); +} + +void +warn (const char *message, ...) +{ + va_list args; + + va_start (args, message); + fprintf (stderr, _("%s: Warning: "), program_name); + vfprintf (stderr, message, args); + va_end (args); +} + +void (*byte_put) (unsigned char *, elf_vma, int); + +void +byte_put_little_endian (unsigned char * field, elf_vma value, int size) +{ + switch (size) + { + case 8: + field[7] = (((value >> 24) >> 24) >> 8) & 0xff; + field[6] = ((value >> 24) >> 24) & 0xff; + field[5] = ((value >> 24) >> 16) & 0xff; + field[4] = ((value >> 24) >> 8) & 0xff; + /* Fall through. */ + case 4: + field[3] = (value >> 24) & 0xff; + /* Fall through. */ + case 3: + field[2] = (value >> 16) & 0xff; + /* Fall through. */ + case 2: + field[1] = (value >> 8) & 0xff; + /* Fall through. */ + case 1: + field[0] = value & 0xff; + break; + + default: + error (_("Unhandled data length: %d\n"), size); + abort (); + } +} + +void +byte_put_big_endian (unsigned char * field, elf_vma value, int size) +{ + switch (size) + { + case 8: + field[7] = value & 0xff; + field[6] = (value >> 8) & 0xff; + field[5] = (value >> 16) & 0xff; + field[4] = (value >> 24) & 0xff; + value >>= 16; + value >>= 16; + /* Fall through. */ + case 4: + field[3] = value & 0xff; + value >>= 8; + /* Fall through. */ + case 3: + field[2] = value & 0xff; + value >>= 8; + /* Fall through. */ + case 2: + field[1] = value & 0xff; + value >>= 8; + /* Fall through. */ + case 1: + field[0] = value & 0xff; + break; + + default: + error (_("Unhandled data length: %d\n"), size); + abort (); + } +} + +elf_vma (*byte_get) (unsigned char *, int); + +elf_vma +byte_get_little_endian (unsigned char *field, int size) +{ + switch (size) + { + case 1: + return *field; + + case 2: + return ((unsigned int) (field[0])) + | (((unsigned int) (field[1])) << 8); + + case 3: + return ((unsigned long) (field[0])) + | (((unsigned long) (field[1])) << 8) + | (((unsigned long) (field[2])) << 16); + + case 4: + return ((unsigned long) (field[0])) + | (((unsigned long) (field[1])) << 8) + | (((unsigned long) (field[2])) << 16) + | (((unsigned long) (field[3])) << 24); + + case 8: + if (sizeof (elf_vma) == 8) + return ((elf_vma) (field[0])) + | (((elf_vma) (field[1])) << 8) + | (((elf_vma) (field[2])) << 16) + | (((elf_vma) (field[3])) << 24) + | (((elf_vma) (field[4])) << 32) + | (((elf_vma) (field[5])) << 40) + | (((elf_vma) (field[6])) << 48) + | (((elf_vma) (field[7])) << 56); + else if (sizeof (elf_vma) == 4) + /* We want to extract data from an 8 byte wide field and + place it into a 4 byte wide field. Since this is a little + endian source we can just use the 4 byte extraction code. */ + return ((unsigned long) (field[0])) + | (((unsigned long) (field[1])) << 8) + | (((unsigned long) (field[2])) << 16) + | (((unsigned long) (field[3])) << 24); + + default: + error (_("Unhandled data length: %d\n"), size); + abort (); + } +} + +elf_vma +byte_get_big_endian (unsigned char *field, int size) +{ + switch (size) + { + case 1: + return *field; + + case 2: + return ((unsigned int) (field[1])) | (((int) (field[0])) << 8); + + case 3: + return ((unsigned long) (field[2])) + | (((unsigned long) (field[1])) << 8) + | (((unsigned long) (field[0])) << 16); + + case 4: + return ((unsigned long) (field[3])) + | (((unsigned long) (field[2])) << 8) + | (((unsigned long) (field[1])) << 16) + | (((unsigned long) (field[0])) << 24); + + case 8: + if (sizeof (elf_vma) == 8) + return ((elf_vma) (field[7])) + | (((elf_vma) (field[6])) << 8) + | (((elf_vma) (field[5])) << 16) + | (((elf_vma) (field[4])) << 24) + | (((elf_vma) (field[3])) << 32) + | (((elf_vma) (field[2])) << 40) + | (((elf_vma) (field[1])) << 48) + | (((elf_vma) (field[0])) << 56); + else if (sizeof (elf_vma) == 4) + { + /* Although we are extracing data from an 8 byte wide field, + we are returning only 4 bytes of data. */ + field += 4; + return ((unsigned long) (field[3])) + | (((unsigned long) (field[2])) << 8) + | (((unsigned long) (field[1])) << 16) + | (((unsigned long) (field[0])) << 24); + } + + default: + error (_("Unhandled data length: %d\n"), size); + abort (); + } +} + +elf_vma +byte_get_signed (unsigned char *field, int size) +{ + elf_vma x = byte_get (field, size); + + switch (size) + { + case 1: + return (x ^ 0x80) - 0x80; + case 2: + return (x ^ 0x8000) - 0x8000; + case 4: + return (x ^ 0x80000000) - 0x80000000; + case 8: + return x; + default: + abort (); + } +} + +/* Return the path name for a proxy entry in a thin archive, adjusted + relative to the path name of the thin archive itself if necessary. + Always returns a pointer to malloc'ed memory. */ + +char * +adjust_relative_path (const char *file_name, const char *name, + int name_len) +{ + char * member_file_name; + const char * base_name = lbasename (file_name); + + /* This is a proxy entry for a thin archive member. + If the extended name table contains an absolute path + name, or if the archive is in the current directory, + use the path name as given. Otherwise, we need to + find the member relative to the directory where the + archive is located. */ + if (IS_ABSOLUTE_PATH (name) || base_name == file_name) + { + member_file_name = (char *) malloc (name_len + 1); + if (member_file_name == NULL) + { + error (_("Out of memory\n")); + return NULL; + } + memcpy (member_file_name, name, name_len); + member_file_name[name_len] = '\0'; + } + else + { + /* Concatenate the path components of the archive file name + to the relative path name from the extended name table. */ + size_t prefix_len = base_name - file_name; + member_file_name = (char *) malloc (prefix_len + name_len + 1); + if (member_file_name == NULL) + { + error (_("Out of memory\n")); + return NULL; + } + memcpy (member_file_name, file_name, prefix_len); + memcpy (member_file_name + prefix_len, name, name_len); + member_file_name[prefix_len + name_len] = '\0'; + } + return member_file_name; +} + +/* Read the symbol table and long-name table from an archive. */ + +int +setup_archive (struct archive_info *arch, const char *file_name, + FILE *file, bfd_boolean is_thin_archive, + bfd_boolean read_symbols) +{ + size_t got; + unsigned long size; + + arch->file_name = strdup (file_name); + arch->file = file; + arch->index_num = 0; + arch->index_array = NULL; + arch->sym_table = NULL; + arch->sym_size = 0; + arch->longnames = NULL; + arch->longnames_size = 0; + arch->nested_member_origin = 0; + arch->is_thin_archive = is_thin_archive; + arch->next_arhdr_offset = SARMAG; + + /* Read the first archive member header. */ + if (fseek (file, SARMAG, SEEK_SET) != 0) + { + error (_("%s: failed to seek to first archive header\n"), file_name); + return 1; + } + got = fread (&arch->arhdr, 1, sizeof arch->arhdr, file); + if (got != sizeof arch->arhdr) + { + if (got == 0) + return 0; + + error (_("%s: failed to read archive header\n"), file_name); + return 1; + } + + /* See if this is the archive symbol table. */ + if (const_strneq (arch->arhdr.ar_name, "/ ") + || const_strneq (arch->arhdr.ar_name, "/SYM64/ ")) + { + size = strtoul (arch->arhdr.ar_size, NULL, 10); + size = size + (size & 1); + + arch->next_arhdr_offset += sizeof arch->arhdr + size; + + if (read_symbols) + { + unsigned long i; + /* A buffer used to hold numbers read in from an archive index. + These are always 4 bytes long and stored in big-endian + format. */ +#define SIZEOF_AR_INDEX_NUMBERS 4 + unsigned char integer_buffer[SIZEOF_AR_INDEX_NUMBERS]; + unsigned char * index_buffer; + + /* Check the size of the archive index. */ + if (size < SIZEOF_AR_INDEX_NUMBERS) + { + error (_("%s: the archive index is empty\n"), file_name); + return 1; + } + + /* Read the numer of entries in the archive index. */ + got = fread (integer_buffer, 1, sizeof integer_buffer, file); + if (got != sizeof (integer_buffer)) + { + error (_("%s: failed to read archive index\n"), file_name); + return 1; + } + arch->index_num = byte_get_big_endian (integer_buffer, + sizeof integer_buffer); + size -= SIZEOF_AR_INDEX_NUMBERS; + + /* Read in the archive index. */ + if (size < arch->index_num * SIZEOF_AR_INDEX_NUMBERS) + { + error (_("%s: the archive index is supposed to have %ld entries, but the size in the header is too small\n"), + file_name, arch->index_num); + return 1; + } + index_buffer = (unsigned char *) + malloc (arch->index_num * SIZEOF_AR_INDEX_NUMBERS); + if (index_buffer == NULL) + { + error (_("Out of memory whilst trying to read archive symbol index\n")); + return 1; + } + got = fread (index_buffer, SIZEOF_AR_INDEX_NUMBERS, + arch->index_num, file); + if (got != arch->index_num) + { + free (index_buffer); + error (_("%s: failed to read archive index\n"), file_name); + return 1; + } + size -= arch->index_num * SIZEOF_AR_INDEX_NUMBERS; + + /* Convert the index numbers into the host's numeric format. */ + arch->index_array = (long unsigned int *) + malloc (arch->index_num * sizeof (* arch->index_array)); + if (arch->index_array == NULL) + { + free (index_buffer); + error (_("Out of memory whilst trying to convert the archive symbol index\n")); + return 1; + } + + for (i = 0; i < arch->index_num; i++) + arch->index_array[i] = byte_get_big_endian ((unsigned char *) (index_buffer + (i * SIZEOF_AR_INDEX_NUMBERS)), + SIZEOF_AR_INDEX_NUMBERS); + free (index_buffer); + + /* The remaining space in the header is taken up by the symbol + table. */ + if (size < 1) + { + error (_("%s: the archive has an index but no symbols\n"), + file_name); + return 1; + } + arch->sym_table = (char *) malloc (size); + arch->sym_size = size; + if (arch->sym_table == NULL) + { + error (_("Out of memory whilst trying to read archive index symbol table\n")); + return 1; + } + got = fread (arch->sym_table, 1, size, file); + if (got != size) + { + error (_("%s: failed to read archive index symbol table\n"), + file_name); + return 1; + } + } + else + { + if (fseek (file, size, SEEK_CUR) != 0) + { + error (_("%s: failed to skip archive symbol table\n"), + file_name); + return 1; + } + } + + /* Read the next archive header. */ + got = fread (&arch->arhdr, 1, sizeof arch->arhdr, file); + if (got != sizeof arch->arhdr) + { + if (got == 0) + return 0; + error (_("%s: failed to read archive header following archive index\n"), + file_name); + return 1; + } + } + else if (read_symbols) + printf (_("%s has no archive index\n"), file_name); + + if (const_strneq (arch->arhdr.ar_name, "// ")) + { + /* This is the archive string table holding long member names. */ + arch->longnames_size = strtoul (arch->arhdr.ar_size, NULL, 10); + arch->next_arhdr_offset += sizeof arch->arhdr + arch->longnames_size; + + arch->longnames = (char *) malloc (arch->longnames_size); + if (arch->longnames == NULL) + { + error (_("Out of memory reading long symbol names in archive\n")); + return 1; + } + + if (fread (arch->longnames, arch->longnames_size, 1, file) != 1) + { + free (arch->longnames); + arch->longnames = NULL; + error (_("%s: failed to read long symbol name string table\n"), + file_name); + return 1; + } + + if ((arch->longnames_size & 1) != 0) + getc (file); + } + + return 0; +} + +/* Open and setup a nested archive, if not already open. */ + +int +setup_nested_archive (struct archive_info *nested_arch, + const char *member_file_name) +{ + FILE * member_file; + + /* Have we already setup this archive? */ + if (nested_arch->file_name != NULL + && streq (nested_arch->file_name, member_file_name)) + return 0; + + /* Close previous file and discard cached information. */ + if (nested_arch->file != NULL) + fclose (nested_arch->file); + release_archive (nested_arch); + + member_file = fopen (member_file_name, "rb"); + if (member_file == NULL) + return 1; + return setup_archive (nested_arch, member_file_name, member_file, + FALSE, FALSE); +} + +/* Release the memory used for the archive information. */ + +void +release_archive (struct archive_info * arch) +{ + if (arch->file_name != NULL) + free (arch->file_name); + if (arch->index_array != NULL) + free (arch->index_array); + if (arch->sym_table != NULL) + free (arch->sym_table); + if (arch->longnames != NULL) + free (arch->longnames); +} + +/* Get the name of an archive member from the current archive header. + For simple names, this will modify the ar_name field of the current + archive header. For long names, it will return a pointer to the + longnames table. For nested archives, it will open the nested archive + and get the name recursively. NESTED_ARCH is a single-entry cache so + we don't keep rereading the same information from a nested archive. */ + +char * +get_archive_member_name (struct archive_info *arch, + struct archive_info *nested_arch) +{ + unsigned long j, k; + + if (arch->arhdr.ar_name[0] == '/') + { + /* We have a long name. */ + char *endp; + char *member_file_name; + char *member_name; + + arch->nested_member_origin = 0; + k = j = strtoul (arch->arhdr.ar_name + 1, &endp, 10); + if (arch->is_thin_archive && endp != NULL && * endp == ':') + arch->nested_member_origin = strtoul (endp + 1, NULL, 10); + + while ((j < arch->longnames_size) + && (arch->longnames[j] != '\n') + && (arch->longnames[j] != '\0')) + j++; + if (arch->longnames[j-1] == '/') + j--; + arch->longnames[j] = '\0'; + + if (!arch->is_thin_archive || arch->nested_member_origin == 0) + return arch->longnames + k; + + /* This is a proxy for a member of a nested archive. + Find the name of the member in that archive. */ + member_file_name = adjust_relative_path (arch->file_name, + arch->longnames + k, j - k); + if (member_file_name != NULL + && setup_nested_archive (nested_arch, member_file_name) == 0) + { + member_name = get_archive_member_name_at (nested_arch, + arch->nested_member_origin, + NULL); + if (member_name != NULL) + { + free (member_file_name); + return member_name; + } + } + free (member_file_name); + + /* Last resort: just return the name of the nested archive. */ + return arch->longnames + k; + } + + /* We have a normal (short) name. */ + for (j = 0; j < sizeof (arch->arhdr.ar_name); j++) + if (arch->arhdr.ar_name[j] == '/') + { + arch->arhdr.ar_name[j] = '\0'; + return arch->arhdr.ar_name; + } + + /* The full ar_name field is used. Don't rely on ar_date starting + with a zero byte. */ + { + char *name = xmalloc (sizeof (arch->arhdr.ar_name) + 1); + memcpy (name, arch->arhdr.ar_name, sizeof (arch->arhdr.ar_name)); + name[sizeof (arch->arhdr.ar_name)] = '\0'; + return name; + } +} + +/* Get the name of an archive member at a given OFFSET within an archive + ARCH. */ + +char * +get_archive_member_name_at (struct archive_info *arch, + unsigned long offset, + struct archive_info *nested_arch) +{ + size_t got; + + if (fseek (arch->file, offset, SEEK_SET) != 0) + { + error (_("%s: failed to seek to next file name\n"), arch->file_name); + return NULL; + } + got = fread (&arch->arhdr, 1, sizeof arch->arhdr, arch->file); + if (got != sizeof arch->arhdr) + { + error (_("%s: failed to read archive header\n"), arch->file_name); + return NULL; + } + if (memcmp (arch->arhdr.ar_fmag, ARFMAG, 2) != 0) + { + error (_("%s: did not find a valid archive header\n"), + arch->file_name); + return NULL; + } + + return get_archive_member_name (arch, nested_arch); +} + +/* Construct a string showing the name of the archive member, qualified + with the name of the containing archive file. For thin archives, we + use square brackets to denote the indirection. For nested archives, + we show the qualified name of the external member inside the square + brackets (e.g., "thin.a[normal.a(foo.o)]"). */ + +char * +make_qualified_name (struct archive_info * arch, + struct archive_info * nested_arch, + const char *member_name) +{ + size_t len; + char * name; + + len = strlen (arch->file_name) + strlen (member_name) + 3; + if (arch->is_thin_archive && arch->nested_member_origin != 0) + len += strlen (nested_arch->file_name) + 2; + + name = (char *) malloc (len); + if (name == NULL) + { + error (_("Out of memory\n")); + return NULL; + } + + if (arch->is_thin_archive && arch->nested_member_origin != 0) + snprintf (name, len, "%s[%s(%s)]", arch->file_name, + nested_arch->file_name, member_name); + else if (arch->is_thin_archive) + snprintf (name, len, "%s[%s]", arch->file_name, member_name); + else + snprintf (name, len, "%s(%s)", arch->file_name, member_name); + + return name; +} diff --git a/binutils/elfcomm.h b/binutils/elfcomm.h new file mode 100644 index 0000000..3f9727e --- /dev/null +++ b/binutils/elfcomm.h @@ -0,0 +1,110 @@ +/* elfcomm.h -- include file of common code for ELF format file. + Copyright 2010 + Free Software Foundation, Inc. + + Originally developed by Eric Youngdale + Modifications by Nick Clifton + + 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 3 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., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifndef _ELFCOMM_H +#define _ELFCOMM_H + +#include "aout/ar.h" + +void error (const char *, ...) ATTRIBUTE_PRINTF_1; +void warn (const char *, ...) ATTRIBUTE_PRINTF_1; + +#if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2) +/* We can't use any bfd types here since readelf may define BFD64 and + objdump may not. */ +#define HOST_WIDEST_INT long long +#else +#define HOST_WIDEST_INT long +#endif +typedef unsigned HOST_WIDEST_INT elf_vma; + +extern void (*byte_put) (unsigned char *, elf_vma, int); +extern void byte_put_little_endian (unsigned char *, elf_vma, int); +extern void byte_put_big_endian (unsigned char *, elf_vma, int); + +extern elf_vma (*byte_get) (unsigned char *, int); +extern elf_vma byte_get_signed (unsigned char *, int); +extern elf_vma byte_get_little_endian (unsigned char *, int); +extern elf_vma byte_get_big_endian (unsigned char *, int); + +#define BYTE_PUT(field, val) byte_put (field, val, sizeof (field)) +#define BYTE_GET(field) byte_get (field, sizeof (field)) +#define BYTE_GET_SIGNED(field) byte_get_signed (field, sizeof (field)) + +/* This is just a bit of syntatic sugar. */ +#define streq(a,b) (strcmp ((a), (b)) == 0) +#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0) +#define const_strneq(a,b) (strncmp ((a), (b), sizeof (b) - 1) == 0) + +/* Structure to hold information about an archive file. */ + +struct archive_info +{ + char * file_name; /* Archive file name. */ + FILE * file; /* Open file descriptor. */ + unsigned long index_num; /* Number of symbols in table. */ + unsigned long * index_array; /* The array of member offsets. */ + char * sym_table; /* The symbol table. */ + unsigned long sym_size; /* Size of the symbol table. */ + char * longnames; /* The long file names table. */ + unsigned long longnames_size; /* Size of the long file names table. */ + unsigned long nested_member_origin; /* Origin in the nested archive of the current member. */ + unsigned long next_arhdr_offset; /* Offset of the next archive header. */ + bfd_boolean is_thin_archive; /* TRUE if this is a thin archive. */ + struct ar_hdr arhdr; /* Current archive header. */ +}; + +/* Return the path name for a proxy entry in a thin archive. */ +extern char *adjust_relative_path (const char *, const char *, int); + +/* Read the symbol table and long-name table from an archive. */ +extern int setup_archive (struct archive_info *, const char *, FILE *, + bfd_boolean, bfd_boolean); + +/* Open and setup a nested archive, if not already open. */ +extern int setup_nested_archive (struct archive_info *, const char *); + +/* Release the memory used for the archive information. */ +extern void release_archive (struct archive_info *); + +/* Get the name of an archive member from the current archive header. */ + +extern char *get_archive_member_name (struct archive_info *, + struct archive_info *); + +/* Get the name of an archive member at a given offset within an + archive. */ + +extern char *get_archive_member_name_at (struct archive_info *, + unsigned long, + struct archive_info *); + +/* Construct a string showing the name of the archive member, qualified + with the name of the containing archive file. */ + +extern char *make_qualified_name (struct archive_info *, + struct archive_info *, + const char *); + +#endif /* _ELFCOMM_H */ diff --git a/binutils/elfedit.c b/binutils/elfedit.c index c9a4b5a..1805ec1 100644 --- a/binutils/elfedit.c +++ b/binutils/elfedit.c @@ -33,15 +33,13 @@ #endif #include "bfd.h" +#include "elfcomm.h" #include "bucomm.h" #include "elf/common.h" #include "elf/external.h" #include "elf/internal.h" - -#include "aout/ar.h" - #include "getopt.h" #include "libiberty.h" #include "safe-ctype.h" @@ -61,174 +59,6 @@ static int input_elf_osabi = -1; static int output_elf_osabi = -1; static int input_elf_class = -1; -#define streq(a,b) (strcmp ((a), (b)) == 0) -#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0) -#define const_strneq(a,b) (strncmp ((a), (b), sizeof (b) - 1) == 0) - -void -non_fatal (const char *message, ...) -{ - va_list args; - - va_start (args, message); - fprintf (stderr, _("%s: Error: "), program_name); - vfprintf (stderr, message, args); - va_end (args); -} - -#define BYTE_GET(field) byte_get (field, sizeof (field)) -#define BYTE_PUT(field, val) byte_put (field, val, sizeof (field)) - -static bfd_vma (*byte_get) (unsigned char *, int); -static void (*byte_put) (unsigned char *, bfd_vma, int); - -static bfd_vma -byte_get_little_endian (unsigned char *field, int size) -{ - switch (size) - { - case 1: - return *field; - - case 2: - return ((unsigned int) (field[0])) - | (((unsigned int) (field[1])) << 8); - - case 4: - return ((unsigned long) (field[0])) - | (((unsigned long) (field[1])) << 8) - | (((unsigned long) (field[2])) << 16) - | (((unsigned long) (field[3])) << 24); - - case 8: - if (sizeof (bfd_vma) == 8) - return ((bfd_vma) (field[0])) - | (((bfd_vma) (field[1])) << 8) - | (((bfd_vma) (field[2])) << 16) - | (((bfd_vma) (field[3])) << 24) - | (((bfd_vma) (field[4])) << 32) - | (((bfd_vma) (field[5])) << 40) - | (((bfd_vma) (field[6])) << 48) - | (((bfd_vma) (field[7])) << 56); - else if (sizeof (bfd_vma) == 4) - /* We want to extract data from an 8 byte wide field and - place it into a 4 byte wide field. Since this is a little - endian source we can just use the 4 byte extraction code. */ - return ((unsigned long) (field[0])) - | (((unsigned long) (field[1])) << 8) - | (((unsigned long) (field[2])) << 16) - | (((unsigned long) (field[3])) << 24); - - default: - non_fatal (_("Unhandled data length: %d\n"), size); - abort (); - } -} - -static bfd_vma -byte_get_big_endian (unsigned char *field, int size) -{ - switch (size) - { - case 1: - return *field; - - case 2: - return ((unsigned int) (field[1])) | (((int) (field[0])) << 8); - - case 4: - return ((unsigned long) (field[3])) - | (((unsigned long) (field[2])) << 8) - | (((unsigned long) (field[1])) << 16) - | (((unsigned long) (field[0])) << 24); - - case 8: - if (sizeof (bfd_vma) == 8) - return ((bfd_vma) (field[7])) - | (((bfd_vma) (field[6])) << 8) - | (((bfd_vma) (field[5])) << 16) - | (((bfd_vma) (field[4])) << 24) - | (((bfd_vma) (field[3])) << 32) - | (((bfd_vma) (field[2])) << 40) - | (((bfd_vma) (field[1])) << 48) - | (((bfd_vma) (field[0])) << 56); - else if (sizeof (bfd_vma) == 4) - { - /* Although we are extracing data from an 8 byte wide field, - we are returning only 4 bytes of data. */ - field += 4; - return ((unsigned long) (field[3])) - | (((unsigned long) (field[2])) << 8) - | (((unsigned long) (field[1])) << 16) - | (((unsigned long) (field[0])) << 24); - } - - default: - non_fatal (_("Unhandled data length: %d\n"), size); - abort (); - } -} - -static void -byte_put_little_endian (unsigned char * field, bfd_vma value, int size) -{ - switch (size) - { - case 8: - field[7] = (((value >> 24) >> 24) >> 8) & 0xff; - field[6] = ((value >> 24) >> 24) & 0xff; - field[5] = ((value >> 24) >> 16) & 0xff; - field[4] = ((value >> 24) >> 8) & 0xff; - /* Fall through. */ - case 4: - field[3] = (value >> 24) & 0xff; - field[2] = (value >> 16) & 0xff; - /* Fall through. */ - case 2: - field[1] = (value >> 8) & 0xff; - /* Fall through. */ - case 1: - field[0] = value & 0xff; - break; - - default: - non_fatal (_("Unhandled data length: %d\n"), size); - abort (); - } -} - -static void -byte_put_big_endian (unsigned char * field, bfd_vma value, int size) -{ - switch (size) - { - case 8: - field[7] = value & 0xff; - field[6] = (value >> 8) & 0xff; - field[5] = (value >> 16) & 0xff; - field[4] = (value >> 24) & 0xff; - value >>= 16; - value >>= 16; - /* Fall through. */ - case 4: - field[3] = value & 0xff; - field[2] = (value >> 8) & 0xff; - value >>= 16; - /* Fall through. */ - case 2: - field[1] = value & 0xff; - value >>= 8; - /* Fall through. */ - case 1: - field[0] = value & 0xff; - break; - - default: - non_fatal (_("Unhandled data length: %d\n"), size); - abort (); - } -} - static int update_elf_header (const char *file_name, FILE *file) { @@ -239,7 +69,7 @@ update_elf_header (const char *file_name, FILE *file) || elf_header.e_ident[EI_MAG2] != ELFMAG2 || elf_header.e_ident[EI_MAG3] != ELFMAG3) { - non_fatal + error (_("%s: Not an ELF file - wrong magic bytes at the start\n"), file_name); return 0; @@ -247,7 +77,7 @@ update_elf_header (const char *file_name, FILE *file) if (elf_header.e_ident[EI_VERSION] != EV_CURRENT) { - non_fatal + error (_("%s: Unsupported EI_VERSION: %d is not %d\n"), file_name, elf_header.e_ident[EI_VERSION], EV_CURRENT); @@ -263,7 +93,7 @@ update_elf_header (const char *file_name, FILE *file) /* Skip if class doesn't match. */ if (input_elf_class != -1 && class != input_elf_class) { - non_fatal + error (_("%s: Unmatched EI_CLASS: %d is not %d\n"), file_name, class, input_elf_class); return 0; @@ -274,7 +104,7 @@ update_elf_header (const char *file_name, FILE *file) /* Skip if e_machine doesn't match. */ if (input_elf_machine != -1 && machine != input_elf_machine) { - non_fatal + error (_("%s: Unmatched e_machine: %d is not %d\n"), file_name, machine, input_elf_machine); return 0; @@ -285,7 +115,7 @@ update_elf_header (const char *file_name, FILE *file) /* Skip if e_type doesn't match. */ if (input_elf_type != -1 && type != input_elf_type) { - non_fatal + error (_("%s: Unmatched e_type: %d is not %d\n"), file_name, type, input_elf_type); return 0; @@ -296,7 +126,7 @@ update_elf_header (const char *file_name, FILE *file) /* Skip if OSABI doesn't match. */ if (input_elf_osabi != -1 && osabi != input_elf_osabi) { - non_fatal + error (_("%s: Unmatched EI_OSABI: %d is not %d\n"), file_name, osabi, input_elf_osabi); return 0; @@ -330,7 +160,7 @@ update_elf_header (const char *file_name, FILE *file) } if (status != 1) - non_fatal (_("%s: Failed to update ELF header: %s\n"), + error (_("%s: Failed to update ELF header: %s\n"), file_name, strerror (errno)); return status; @@ -363,7 +193,7 @@ get_file_header (FILE * file) switch (elf_header.e_ident[EI_CLASS]) { default: - non_fatal (_("Unsupported EI_CLASS: %d\n"), + error (_("Unsupported EI_CLASS: %d\n"), elf_header.e_ident[EI_CLASS]); return 0; @@ -396,7 +226,7 @@ get_file_header (FILE * file) overwriting things. */ if (sizeof (bfd_vma) < 8) { - non_fatal (_("This executable has been built without support for a\n\ + error (_("This executable has been built without support for a\n\ 64 bit data type and so it cannot process 64 bit ELF files.\n")); return 0; } @@ -437,14 +267,14 @@ process_object (const char *file_name, FILE *file) if (! get_file_header (file)) { - non_fatal (_("%s: Failed to read ELF header\n"), file_name); + error (_("%s: Failed to read ELF header\n"), file_name); return 1; } /* Go to the position of the ELF header. */ if (fseek (file, offset, SEEK_SET) != 0) { - non_fatal (_("%s: Failed to seek to ELF header\n"), file_name); + error (_("%s: Failed to seek to ELF header\n"), file_name); } if (! update_elf_header (file_name, file)) @@ -453,341 +283,6 @@ process_object (const char *file_name, FILE *file) return 0; } -/* Return the path name for a proxy entry in a thin archive, adjusted relative - to the path name of the thin archive itself if necessary. Always returns - a pointer to malloc'ed memory. */ - -static char * -adjust_relative_path (const char *file_name, char * name, int name_len) -{ - char * member_file_name; - const char * base_name = lbasename (file_name); - - /* This is a proxy entry for a thin archive member. - If the extended name table contains an absolute path - name, or if the archive is in the current directory, - use the path name as given. Otherwise, we need to - find the member relative to the directory where the - archive is located. */ - if (IS_ABSOLUTE_PATH (name) || base_name == file_name) - { - member_file_name = malloc (name_len + 1); - if (member_file_name == NULL) - { - non_fatal (_("Out of memory\n")); - return NULL; - } - memcpy (member_file_name, name, name_len); - member_file_name[name_len] = '\0'; - } - else - { - /* Concatenate the path components of the archive file name - to the relative path name from the extended name table. */ - size_t prefix_len = base_name - file_name; - member_file_name = malloc (prefix_len + name_len + 1); - if (member_file_name == NULL) - { - non_fatal (_("Out of memory\n")); - return NULL; - } - memcpy (member_file_name, file_name, prefix_len); - memcpy (member_file_name + prefix_len, name, name_len); - member_file_name[prefix_len + name_len] = '\0'; - } - return member_file_name; -} - -/* Structure to hold information about an archive file. */ - -struct archive_info -{ - char * file_name; /* Archive file name. */ - FILE * file; /* Open file descriptor. */ - unsigned long index_num; /* Number of symbols in table. */ - unsigned long * index_array; /* The array of member offsets. */ - char * sym_table; /* The symbol table. */ - unsigned long sym_size; /* Size of the symbol table. */ - char * longnames; /* The long file names table. */ - unsigned long longnames_size; /* Size of the long file names table. */ - unsigned long nested_member_origin; /* Origin in the nested archive of the current member. */ - unsigned long next_arhdr_offset; /* Offset of the next archive header. */ - bfd_boolean is_thin_archive; /* TRUE if this is a thin archive. */ - struct ar_hdr arhdr; /* Current archive header. */ -}; - -/* Read the symbol table and long-name table from an archive. */ - -static int -setup_archive (struct archive_info * arch, const char * file_name, - FILE * file, bfd_boolean is_thin_archive) -{ - size_t got; - unsigned long size; - - arch->file_name = strdup (file_name); - arch->file = file; - arch->index_num = 0; - arch->index_array = NULL; - arch->sym_table = NULL; - arch->sym_size = 0; - arch->longnames = NULL; - arch->longnames_size = 0; - arch->nested_member_origin = 0; - arch->is_thin_archive = is_thin_archive; - arch->next_arhdr_offset = SARMAG; - - /* Read the first archive member header. */ - if (fseek (file, SARMAG, SEEK_SET) != 0) - { - non_fatal (_("%s: failed to seek to first archive header\n"), - file_name); - return 1; - } - got = fread (&arch->arhdr, 1, sizeof arch->arhdr, file); - if (got != sizeof arch->arhdr) - { - if (got == 0) - return 0; - - non_fatal (_("%s: failed to read archive header\n"), file_name); - return 1; - } - - /* See if this is the archive symbol table. */ - if (const_strneq (arch->arhdr.ar_name, "/ ") - || const_strneq (arch->arhdr.ar_name, "/SYM64/ ")) - { - size = strtoul (arch->arhdr.ar_size, NULL, 10); - size = size + (size & 1); - - arch->next_arhdr_offset += sizeof arch->arhdr + size; - - if (fseek (file, size, SEEK_CUR) != 0) - { - non_fatal (_("%s: failed to skip archive symbol table\n"), - file_name); - return 1; - } - - /* Read the next archive header. */ - got = fread (&arch->arhdr, 1, sizeof arch->arhdr, file); - if (got != sizeof arch->arhdr) - { - if (got == 0) - return 0; - non_fatal (_("%s: failed to read archive header following archive index\n"), - file_name); - return 1; - } - } - - if (const_strneq (arch->arhdr.ar_name, "// ")) - { - /* This is the archive string table holding long member names. */ - arch->longnames_size = strtoul (arch->arhdr.ar_size, NULL, 10); - arch->next_arhdr_offset += sizeof arch->arhdr + arch->longnames_size; - - arch->longnames = malloc (arch->longnames_size); - if (arch->longnames == NULL) - { - non_fatal (_("Out of memory reading long symbol names in archive\n")); - return 1; - } - - if (fread (arch->longnames, arch->longnames_size, 1, file) != 1) - { - free (arch->longnames); - arch->longnames = NULL; - non_fatal (_("%s: failed to read long symbol name string table\n") - , file_name); - return 1; - } - - if ((arch->longnames_size & 1) != 0) - getc (file); - } - - return 0; -} - -/* Release the memory used for the archive information. */ - -static void -release_archive (struct archive_info * arch) -{ - if (arch->file_name != NULL) - free (arch->file_name); - if (arch->index_array != NULL) - free (arch->index_array); - if (arch->sym_table != NULL) - free (arch->sym_table); - if (arch->longnames != NULL) - free (arch->longnames); -} - -/* Open and setup a nested archive, if not already open. */ - -static int -setup_nested_archive (struct archive_info * nested_arch, char * member_file_name) -{ - FILE * member_file; - - /* Have we already setup this archive? */ - if (nested_arch->file_name != NULL - && streq (nested_arch->file_name, member_file_name)) - return 0; - - /* Close previous file and discard cached information. */ - if (nested_arch->file != NULL) - fclose (nested_arch->file); - release_archive (nested_arch); - - member_file = fopen (member_file_name, "r+b"); - if (member_file == NULL) - return 1; - return setup_archive (nested_arch, member_file_name, member_file, - FALSE); -} - -static char * -get_archive_member_name_at (struct archive_info * arch, - unsigned long offset, - struct archive_info * nested_arch); - -/* Get the name of an archive member from the current archive header. - For simple names, this will modify the ar_name field of the current - archive header. For long names, it will return a pointer to the - longnames table. For nested archives, it will open the nested archive - and get the name recursively. NESTED_ARCH is a single-entry cache so - we don't keep rereading the same information from a nested archive. */ - -static char * -get_archive_member_name (struct archive_info * arch, - struct archive_info * nested_arch) -{ - unsigned long j, k; - - if (arch->arhdr.ar_name[0] == '/') - { - /* We have a long name. */ - char * endp; - char * member_file_name; - char * member_name; - - arch->nested_member_origin = 0; - k = j = strtoul (arch->arhdr.ar_name + 1, &endp, 10); - if (arch->is_thin_archive && endp != NULL && * endp == ':') - arch->nested_member_origin = strtoul (endp + 1, NULL, 10); - - while ((j < arch->longnames_size) - && (arch->longnames[j] != '\n') - && (arch->longnames[j] != '\0')) - j++; - if (arch->longnames[j-1] == '/') - j--; - arch->longnames[j] = '\0'; - - if (!arch->is_thin_archive || arch->nested_member_origin == 0) - return arch->longnames + k; - - /* This is a proxy for a member of a nested archive. - Find the name of the member in that archive. */ - member_file_name = adjust_relative_path (arch->file_name, - arch->longnames + k, - j - k); - if (member_file_name != NULL - && setup_nested_archive (nested_arch, member_file_name) == 0 - && (member_name = get_archive_member_name_at (nested_arch, - arch->nested_member_origin, - NULL)) != NULL) - { - free (member_file_name); - return member_name; - } - free (member_file_name); - - /* Last resort: just return the name of the nested archive. */ - return arch->longnames + k; - } - - /* We have a normal (short) name. */ - j = 0; - while ((arch->arhdr.ar_name[j] != '/') && (j < 16)) - j++; - arch->arhdr.ar_name[j] = '\0'; - return arch->arhdr.ar_name; -} - -/* Get the name of an archive member at a given OFFSET within an - archive ARCH. */ - -static char * -get_archive_member_name_at (struct archive_info * arch, - unsigned long offset, - struct archive_info * nested_arch) -{ - size_t got; - - if (fseek (arch->file, offset, SEEK_SET) != 0) - { - non_fatal (_("%s: failed to seek to next file name\n"), - arch->file_name); - return NULL; - } - got = fread (&arch->arhdr, 1, sizeof arch->arhdr, arch->file); - if (got != sizeof arch->arhdr) - { - non_fatal (_("%s: failed to read archive header\n"), - arch->file_name); - return NULL; - } - if (memcmp (arch->arhdr.ar_fmag, ARFMAG, 2) != 0) - { - non_fatal (_("%s: did not find a valid archive header\n"), - arch->file_name); - return NULL; - } - - return get_archive_member_name (arch, nested_arch); -} - -/* Construct a string showing the name of the archive member, qualified - with the name of the containing archive file. For thin archives, we - use square brackets to denote the indirection. For nested archives, - we show the qualified name of the external member inside the square - brackets (e.g., "thin.a[normal.a(foo.o)]"). */ - -static char * -make_qualified_name (struct archive_info * arch, - struct archive_info * nested_arch, - char * member_name) -{ - size_t len; - char * name; - - len = strlen (arch->file_name) + strlen (member_name) + 3; - if (arch->is_thin_archive && arch->nested_member_origin != 0) - len += strlen (nested_arch->file_name) + 2; - - name = malloc (len); - if (name == NULL) - { - non_fatal (_("Out of memory\n")); - return NULL; - } - - if (arch->is_thin_archive && arch->nested_member_origin != 0) - snprintf (name, len, "%s[%s(%s)]", arch->file_name, - nested_arch->file_name, member_name); - else if (arch->is_thin_archive) - snprintf (name, len, "%s[%s]", arch->file_name, member_name); - else - snprintf (name, len, "%s(%s)", arch->file_name, member_name); - - return name; -} - /* Process an ELF archive. On entry the file is positioned just after the ARMAG string. */ @@ -816,7 +311,7 @@ process_archive (const char * file_name, FILE * file, nested_arch.sym_table = NULL; nested_arch.longnames = NULL; - if (setup_archive (&arch, file_name, file, is_thin_archive) != 0) + if (setup_archive (&arch, file_name, file, is_thin_archive, FALSE) != 0) { ret = 1; goto out; @@ -833,7 +328,7 @@ process_archive (const char * file_name, FILE * file, /* Read the next archive header. */ if (fseek (file, arch.next_arhdr_offset, SEEK_SET) != 0) { - non_fatal (_("%s: failed to seek to next archive header\n"), + error (_("%s: failed to seek to next archive header\n"), file_name); return 1; } @@ -842,14 +337,14 @@ process_archive (const char * file_name, FILE * file, { if (got == 0) break; - non_fatal (_("%s: failed to read archive header\n"), + error (_("%s: failed to read archive header\n"), file_name); ret = 1; break; } if (memcmp (arch.arhdr.ar_fmag, ARFMAG, 2) != 0) { - non_fatal (_("%s: did not find a valid archive header\n"), + error (_("%s: did not find a valid archive header\n"), arch.file_name); ret = 1; break; @@ -864,7 +359,7 @@ process_archive (const char * file_name, FILE * file, name = get_archive_member_name (&arch, &nested_arch); if (name == NULL) { - non_fatal (_("%s: bad archive file name\n"), file_name); + error (_("%s: bad archive file name\n"), file_name); ret = 1; break; } @@ -873,7 +368,7 @@ process_archive (const char * file_name, FILE * file, qualified_name = make_qualified_name (&arch, &nested_arch, name); if (qualified_name == NULL) { - non_fatal (_("%s: bad archive file name\n"), file_name); + error (_("%s: bad archive file name\n"), file_name); ret = 1; break; } @@ -893,7 +388,7 @@ process_archive (const char * file_name, FILE * file, member_file = fopen (member_file_name, "r+b"); if (member_file == NULL) { - non_fatal (_("Input file '%s' is not readable\n"), + error (_("Input file '%s' is not readable\n"), member_file_name); free (member_file_name); ret = 1; @@ -917,7 +412,7 @@ process_archive (const char * file_name, FILE * file, if (fseek (nested_arch.file, archive_file_offset, SEEK_SET) != 0) { - non_fatal (_("%s: failed to seek to archive member\n"), + error (_("%s: failed to seek to archive member\n"), nested_arch.file_name); ret = 1; break; @@ -956,16 +451,16 @@ check_file (const char *file_name, struct stat *statbuf_p) if (stat (file_name, statbuf_p) < 0) { if (errno == ENOENT) - non_fatal (_("'%s': No such file\n"), file_name); + error (_("'%s': No such file\n"), file_name); else - non_fatal (_("Could not locate '%s'. System error message: %s\n"), + error (_("Could not locate '%s'. System error message: %s\n"), file_name, strerror (errno)); return 1; } if (! S_ISREG (statbuf_p->st_mode)) { - non_fatal (_("'%s' is not an ordinary file\n"), file_name); + error (_("'%s' is not an ordinary file\n"), file_name); return 1; } @@ -985,13 +480,13 @@ process_file (const char *file_name) file = fopen (file_name, "r+b"); if (file == NULL) { - non_fatal (_("Input file '%s' is not readable\n"), file_name); + error (_("Input file '%s' is not readable\n"), file_name); return 1; } if (fread (armag, SARMAG, 1, file) != 1) { - non_fatal (_("%s: Failed to read file's magic number\n"), + error (_("%s: Failed to read file's magic number\n"), file_name); fclose (file); return 1; @@ -1049,7 +544,7 @@ elf_osabi (const char *osabi) if (strcasecmp (osabi, osabis[i].name) == 0) return osabis[i].osabi; - non_fatal (_("Unknown OSABI: %s\n"), osabi); + error (_("Unknown OSABI: %s\n"), osabi); return -1; } @@ -1068,7 +563,7 @@ elf_machine (const char *mach) if (strcasecmp (mach, "none") == 0) return EM_NONE; - non_fatal (_("Unknown machine type: %s\n"), mach); + error (_("Unknown machine type: %s\n"), mach); return -1; } @@ -1086,7 +581,7 @@ elf_class (int mach) case EM_NONE: return ELFCLASSNONE; default: - non_fatal (_("Unknown machine type: %d\n"), mach); + error (_("Unknown machine type: %d\n"), mach); return -1; } } @@ -1105,7 +600,7 @@ elf_type (const char *type) if (strcasecmp (type, "none") == 0) return ET_NONE; - non_fatal (_("Unknown type: %s\n"), type); + error (_("Unknown type: %s\n"), type); return -1; } diff --git a/binutils/objdump.c b/binutils/objdump.c index 11a11ae..da68eeb 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -55,6 +55,7 @@ #include "elf-bfd.h" #include "progress.h" #include "bucomm.h" +#include "elfcomm.h" #include "dwarf.h" #include "getopt.h" #include "safe-ctype.h" diff --git a/binutils/readelf.c b/binutils/readelf.c index 8c20888..3f4167b 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -61,6 +61,7 @@ #include "bfd.h" #include "bucomm.h" +#include "elfcomm.h" #include "dwarf.h" #include "elf/common.h" @@ -146,8 +147,6 @@ #include "elf/xstormy16.h" #include "elf/xtensa.h" -#include "aout/ar.h" - #include "getopt.h" #include "libiberty.h" #include "safe-ctype.h" @@ -260,8 +259,6 @@ typedef enum print_mode } print_mode; -static void (* byte_put) (unsigned char *, bfd_vma, int); - #define UNKNOWN -1 #define SECTION_NAME(X) \ @@ -272,9 +269,6 @@ static void (* byte_put) (unsigned char *, bfd_vma, int); #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ -#define BYTE_GET(field) byte_get (field, sizeof (field)) -#define BYTE_GET_SIGNED(field) byte_get_signed (field, sizeof (field)) - #define GET_ELF_SYMBOLS(file, section) \ (is_32bit_elf ? get_32bit_elf_symbols (file, section) \ : get_64bit_elf_symbols (file, section)) @@ -284,11 +278,6 @@ static void (* byte_put) (unsigned char *, bfd_vma, int); already been called and verified that the string exists. */ #define GET_DYNAMIC_NAME(offset) (dynamic_strings + offset) -/* This is just a bit of syntatic sugar. */ -#define streq(a,b) (strcmp ((a), (b)) == 0) -#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0) -#define const_strneq(a,b) (strncmp ((a), (b), sizeof (b) - 1) == 0) - #define REMOVE_ARCH_BITS(ADDR) do { \ if (elf_header.e_machine == EM_ARM) \ (ADDR) &= ~1; \ @@ -340,36 +329,6 @@ get_data (void * var, FILE * file, long offset, size_t size, size_t nmemb, return mvar; } -static void -byte_put_little_endian (unsigned char * field, bfd_vma value, int size) -{ - switch (size) - { - case 8: - field[7] = (((value >> 24) >> 24) >> 8) & 0xff; - field[6] = ((value >> 24) >> 24) & 0xff; - field[5] = ((value >> 24) >> 16) & 0xff; - field[4] = ((value >> 24) >> 8) & 0xff; - /* Fall through. */ - case 4: - field[3] = (value >> 24) & 0xff; - /* Fall through. */ - case 3: - field[2] = (value >> 16) & 0xff; - /* Fall through. */ - case 2: - field[1] = (value >> 8) & 0xff; - /* Fall through. */ - case 1: - field[0] = value & 0xff; - break; - - default: - error (_("Unhandled data length: %d\n"), size); - abort (); - } -} - /* Print a VMA value. */ static int @@ -503,41 +462,6 @@ print_symbol (int width, const char * symbol) return num_printed; } -static void -byte_put_big_endian (unsigned char * field, bfd_vma value, int size) -{ - switch (size) - { - case 8: - field[7] = value & 0xff; - field[6] = (value >> 8) & 0xff; - field[5] = (value >> 16) & 0xff; - field[4] = (value >> 24) & 0xff; - value >>= 16; - value >>= 16; - /* Fall through. */ - case 4: - field[3] = value & 0xff; - value >>= 8; - /* Fall through. */ - case 3: - field[2] = value & 0xff; - value >>= 8; - /* Fall through. */ - case 2: - field[1] = value & 0xff; - value >>= 8; - /* Fall through. */ - case 1: - field[0] = value & 0xff; - break; - - default: - error (_("Unhandled data length: %d\n"), size); - abort (); - } -} - /* Return a pointer to section NAME, or NULL if no such section exists. */ static Elf_Internal_Shdr * @@ -12507,432 +12431,6 @@ process_object (char * file_name, FILE * file) return 0; } -/* Return the path name for a proxy entry in a thin archive, adjusted relative - to the path name of the thin archive itself if necessary. Always returns - a pointer to malloc'ed memory. */ - -static char * -adjust_relative_path (char * file_name, char * name, int name_len) -{ - char * member_file_name; - const char * base_name = lbasename (file_name); - - /* This is a proxy entry for a thin archive member. - If the extended name table contains an absolute path - name, or if the archive is in the current directory, - use the path name as given. Otherwise, we need to - find the member relative to the directory where the - archive is located. */ - if (IS_ABSOLUTE_PATH (name) || base_name == file_name) - { - member_file_name = (char *) malloc (name_len + 1); - if (member_file_name == NULL) - { - error (_("Out of memory\n")); - return NULL; - } - memcpy (member_file_name, name, name_len); - member_file_name[name_len] = '\0'; - } - else - { - /* Concatenate the path components of the archive file name - to the relative path name from the extended name table. */ - size_t prefix_len = base_name - file_name; - member_file_name = (char *) malloc (prefix_len + name_len + 1); - if (member_file_name == NULL) - { - error (_("Out of memory\n")); - return NULL; - } - memcpy (member_file_name, file_name, prefix_len); - memcpy (member_file_name + prefix_len, name, name_len); - member_file_name[prefix_len + name_len] = '\0'; - } - return member_file_name; -} - -/* Structure to hold information about an archive file. */ - -struct archive_info -{ - char * file_name; /* Archive file name. */ - FILE * file; /* Open file descriptor. */ - unsigned long index_num; /* Number of symbols in table. */ - unsigned long * index_array; /* The array of member offsets. */ - char * sym_table; /* The symbol table. */ - unsigned long sym_size; /* Size of the symbol table. */ - char * longnames; /* The long file names table. */ - unsigned long longnames_size; /* Size of the long file names table. */ - unsigned long nested_member_origin; /* Origin in the nested archive of the current member. */ - unsigned long next_arhdr_offset; /* Offset of the next archive header. */ - bfd_boolean is_thin_archive; /* TRUE if this is a thin archive. */ - struct ar_hdr arhdr; /* Current archive header. */ -}; - -/* Read the symbol table and long-name table from an archive. */ - -static int -setup_archive (struct archive_info * arch, char * file_name, FILE * file, - bfd_boolean is_thin_archive, bfd_boolean read_symbols) -{ - size_t got; - unsigned long size; - - arch->file_name = strdup (file_name); - arch->file = file; - arch->index_num = 0; - arch->index_array = NULL; - arch->sym_table = NULL; - arch->sym_size = 0; - arch->longnames = NULL; - arch->longnames_size = 0; - arch->nested_member_origin = 0; - arch->is_thin_archive = is_thin_archive; - arch->next_arhdr_offset = SARMAG; - - /* Read the first archive member header. */ - if (fseek (file, SARMAG, SEEK_SET) != 0) - { - error (_("%s: failed to seek to first archive header\n"), file_name); - return 1; - } - got = fread (&arch->arhdr, 1, sizeof arch->arhdr, file); - if (got != sizeof arch->arhdr) - { - if (got == 0) - return 0; - - error (_("%s: failed to read archive header\n"), file_name); - return 1; - } - - /* See if this is the archive symbol table. */ - if (const_strneq (arch->arhdr.ar_name, "/ ") - || const_strneq (arch->arhdr.ar_name, "/SYM64/ ")) - { - size = strtoul (arch->arhdr.ar_size, NULL, 10); - size = size + (size & 1); - - arch->next_arhdr_offset += sizeof arch->arhdr + size; - - if (read_symbols) - { - unsigned long i; - /* A buffer used to hold numbers read in from an archive index. - These are always 4 bytes long and stored in big-endian format. */ -#define SIZEOF_AR_INDEX_NUMBERS 4 - unsigned char integer_buffer[SIZEOF_AR_INDEX_NUMBERS]; - unsigned char * index_buffer; - - /* Check the size of the archive index. */ - if (size < SIZEOF_AR_INDEX_NUMBERS) - { - error (_("%s: the archive index is empty\n"), file_name); - return 1; - } - - /* Read the numer of entries in the archive index. */ - got = fread (integer_buffer, 1, sizeof integer_buffer, file); - if (got != sizeof (integer_buffer)) - { - error (_("%s: failed to read archive index\n"), file_name); - return 1; - } - arch->index_num = byte_get_big_endian (integer_buffer, sizeof integer_buffer); - size -= SIZEOF_AR_INDEX_NUMBERS; - - /* Read in the archive index. */ - if (size < arch->index_num * SIZEOF_AR_INDEX_NUMBERS) - { - error (_("%s: the archive index is supposed to have %ld entries, but the size in the header is too small\n"), - file_name, arch->index_num); - return 1; - } - index_buffer = (unsigned char *) - malloc (arch->index_num * SIZEOF_AR_INDEX_NUMBERS); - if (index_buffer == NULL) - { - error (_("Out of memory whilst trying to read archive symbol index\n")); - return 1; - } - got = fread (index_buffer, SIZEOF_AR_INDEX_NUMBERS, arch->index_num, file); - if (got != arch->index_num) - { - free (index_buffer); - error (_("%s: failed to read archive index\n"), file_name); - return 1; - } - size -= arch->index_num * SIZEOF_AR_INDEX_NUMBERS; - - /* Convert the index numbers into the host's numeric format. */ - arch->index_array = (long unsigned int *) - malloc (arch->index_num * sizeof (* arch->index_array)); - if (arch->index_array == NULL) - { - free (index_buffer); - error (_("Out of memory whilst trying to convert the archive symbol index\n")); - return 1; - } - - for (i = 0; i < arch->index_num; i++) - arch->index_array[i] = byte_get_big_endian ((unsigned char *) (index_buffer + (i * SIZEOF_AR_INDEX_NUMBERS)), - SIZEOF_AR_INDEX_NUMBERS); - free (index_buffer); - - /* The remaining space in the header is taken up by the symbol table. */ - if (size < 1) - { - error (_("%s: the archive has an index but no symbols\n"), file_name); - return 1; - } - arch->sym_table = (char *) malloc (size); - arch->sym_size = size; - if (arch->sym_table == NULL) - { - error (_("Out of memory whilst trying to read archive index symbol table\n")); - return 1; - } - got = fread (arch->sym_table, 1, size, file); - if (got != size) - { - error (_("%s: failed to read archive index symbol table\n"), file_name); - return 1; - } - } - else - { - if (fseek (file, size, SEEK_CUR) != 0) - { - error (_("%s: failed to skip archive symbol table\n"), file_name); - return 1; - } - } - - /* Read the next archive header. */ - got = fread (&arch->arhdr, 1, sizeof arch->arhdr, file); - if (got != sizeof arch->arhdr) - { - if (got == 0) - return 0; - error (_("%s: failed to read archive header following archive index\n"), file_name); - return 1; - } - } - else if (read_symbols) - printf (_("%s has no archive index\n"), file_name); - - if (const_strneq (arch->arhdr.ar_name, "// ")) - { - /* This is the archive string table holding long member names. */ - arch->longnames_size = strtoul (arch->arhdr.ar_size, NULL, 10); - arch->next_arhdr_offset += sizeof arch->arhdr + arch->longnames_size; - - arch->longnames = (char *) malloc (arch->longnames_size); - if (arch->longnames == NULL) - { - error (_("Out of memory reading long symbol names in archive\n")); - return 1; - } - - if (fread (arch->longnames, arch->longnames_size, 1, file) != 1) - { - free (arch->longnames); - arch->longnames = NULL; - error (_("%s: failed to read long symbol name string table\n"), file_name); - return 1; - } - - if ((arch->longnames_size & 1) != 0) - getc (file); - } - - return 0; -} - -/* Release the memory used for the archive information. */ - -static void -release_archive (struct archive_info * arch) -{ - if (arch->file_name != NULL) - free (arch->file_name); - if (arch->index_array != NULL) - free (arch->index_array); - if (arch->sym_table != NULL) - free (arch->sym_table); - if (arch->longnames != NULL) - free (arch->longnames); -} - -/* Open and setup a nested archive, if not already open. */ - -static int -setup_nested_archive (struct archive_info * nested_arch, char * member_file_name) -{ - FILE * member_file; - - /* Have we already setup this archive? */ - if (nested_arch->file_name != NULL - && streq (nested_arch->file_name, member_file_name)) - return 0; - - /* Close previous file and discard cached information. */ - if (nested_arch->file != NULL) - fclose (nested_arch->file); - release_archive (nested_arch); - - member_file = fopen (member_file_name, "rb"); - if (member_file == NULL) - return 1; - return setup_archive (nested_arch, member_file_name, member_file, FALSE, FALSE); -} - -static char * -get_archive_member_name_at (struct archive_info * arch, - unsigned long offset, - struct archive_info * nested_arch); - -/* Get the name of an archive member from the current archive header. - For simple names, this will modify the ar_name field of the current - archive header. For long names, it will return a pointer to the - longnames table. For nested archives, it will open the nested archive - and get the name recursively. NESTED_ARCH is a single-entry cache so - we don't keep rereading the same information from a nested archive. */ - -static char * -get_archive_member_name (struct archive_info * arch, - struct archive_info * nested_arch) -{ - unsigned long j, k; - - if (arch->arhdr.ar_name[0] == '/') - { - /* We have a long name. */ - char * endp; - char * member_file_name; - char * member_name; - - arch->nested_member_origin = 0; - k = j = strtoul (arch->arhdr.ar_name + 1, &endp, 10); - if (arch->is_thin_archive && endp != NULL && * endp == ':') - arch->nested_member_origin = strtoul (endp + 1, NULL, 10); - - while ((j < arch->longnames_size) - && (arch->longnames[j] != '\n') - && (arch->longnames[j] != '\0')) - j++; - if (arch->longnames[j-1] == '/') - j--; - arch->longnames[j] = '\0'; - - if (!arch->is_thin_archive || arch->nested_member_origin == 0) - return arch->longnames + k; - - /* This is a proxy for a member of a nested archive. - Find the name of the member in that archive. */ - member_file_name = adjust_relative_path (arch->file_name, - arch->longnames + k, j - k); - if (member_file_name != NULL - && setup_nested_archive (nested_arch, member_file_name) == 0) - { - member_name = get_archive_member_name_at (nested_arch, - arch->nested_member_origin, - NULL); - if (member_name != NULL) - { - free (member_file_name); - return member_name; - } - } - free (member_file_name); - - /* Last resort: just return the name of the nested archive. */ - return arch->longnames + k; - } - - /* We have a normal (short) name. */ - for (j = 0; j < sizeof (arch->arhdr.ar_name); j++) - if (arch->arhdr.ar_name[j] == '/') - { - arch->arhdr.ar_name[j] = '\0'; - return arch->arhdr.ar_name; - } - - /* The full ar_name field is used. Don't rely on ar_date starting - with a zero byte. */ - { - char *name = xmalloc (sizeof (arch->arhdr.ar_name) + 1); - memcpy (name, arch->arhdr.ar_name, sizeof (arch->arhdr.ar_name)); - name[sizeof (arch->arhdr.ar_name)] = '\0'; - return name; - } -} - -/* Get the name of an archive member at a given OFFSET within an archive ARCH. */ - -static char * -get_archive_member_name_at (struct archive_info * arch, - unsigned long offset, - struct archive_info * nested_arch) -{ - size_t got; - - if (fseek (arch->file, offset, SEEK_SET) != 0) - { - error (_("%s: failed to seek to next file name\n"), arch->file_name); - return NULL; - } - got = fread (&arch->arhdr, 1, sizeof arch->arhdr, arch->file); - if (got != sizeof arch->arhdr) - { - error (_("%s: failed to read archive header\n"), arch->file_name); - return NULL; - } - if (memcmp (arch->arhdr.ar_fmag, ARFMAG, 2) != 0) - { - error (_("%s: did not find a valid archive header\n"), arch->file_name); - return NULL; - } - - return get_archive_member_name (arch, nested_arch); -} - -/* Construct a string showing the name of the archive member, qualified - with the name of the containing archive file. For thin archives, we - use square brackets to denote the indirection. For nested archives, - we show the qualified name of the external member inside the square - brackets (e.g., "thin.a[normal.a(foo.o)]"). */ - -static char * -make_qualified_name (struct archive_info * arch, - struct archive_info * nested_arch, - char * member_name) -{ - size_t len; - char * name; - - len = strlen (arch->file_name) + strlen (member_name) + 3; - if (arch->is_thin_archive && arch->nested_member_origin != 0) - len += strlen (nested_arch->file_name) + 2; - - name = (char *) malloc (len); - if (name == NULL) - { - error (_("Out of memory\n")); - return NULL; - } - - if (arch->is_thin_archive && arch->nested_member_origin != 0) - snprintf (name, len, "%s[%s(%s)]", arch->file_name, nested_arch->file_name, member_name); - else if (arch->is_thin_archive) - snprintf (name, len, "%s[%s]", arch->file_name, member_name); - else - snprintf (name, len, "%s(%s)", arch->file_name, member_name); - - return name; -} - /* Process an ELF archive. On entry the file is positioned just after the ARMAG string. */ -- cgit v1.1