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:
H.J. Lu 2010-11-21 21:27:15 +00:00
parent f84854b643
commit 3284fe0c5e
10 changed files with 902 additions and 1212 deletions

View File

@ -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

View File

@ -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

View File

@ -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@

View File

@ -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)
{

View File

@ -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
View 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
View 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 */

View File

@ -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;
}

View File

@ -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"

View File

@ -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. */