mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-23 12:09:49 +00:00
Add and use elfcomm.c/elfcomm.h.
2010-11-21 H.J. Lu <hongjiu.lu@intel.com> 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.
This commit is contained in:
parent
f84854b643
commit
3284fe0c5e
@ -1,3 +1,77 @@
|
||||
2010-11-21 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
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 <amodra@gmail.com>
|
||||
|
||||
PR binutils/11742
|
||||
|
@ -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
|
||||
|
@ -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@
|
||||
|
142
binutils/dwarf.c
142
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)
|
||||
{
|
||||
@ -5019,28 +4901,6 @@ xcrealloc (void *ptr, size_t nmemb, size_t size)
|
||||
return xrealloc (ptr, nmemb * 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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
658
binutils/elfcomm.c
Normal file
658
binutils/elfcomm.c
Normal file
@ -0,0 +1,658 @@
|
||||
/* elfcomm.c -- common code for ELF format file.
|
||||
Copyright 2010
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Originally developed by Eric Youngdale <eric@andante.jic.com>
|
||||
Modifications by Nick Clifton <nickc@redhat.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 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;
|
||||
}
|
110
binutils/elfcomm.h
Normal file
110
binutils/elfcomm.h
Normal file
@ -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 <eric@andante.jic.com>
|
||||
Modifications by Nick Clifton <nickc@redhat.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 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 */
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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. */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user