Add and use elfcomm.c/elfcomm.h.
authorH.J. Lu <hjl.tools@gmail.com>
Sun, 21 Nov 2010 21:27:15 +0000 (21:27 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Sun, 21 Nov 2010 21:27:15 +0000 (21:27 +0000)
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.

binutils/ChangeLog
binutils/Makefile.am
binutils/Makefile.in
binutils/dwarf.c
binutils/dwarf.h
binutils/elfcomm.c [new file with mode: 0644]
binutils/elfcomm.h [new file with mode: 0644]
binutils/elfedit.c
binutils/objdump.c
binutils/readelf.c

index d1300fc..a4f391e 100644 (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
index 0978538..6546087 100644 (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
index fddc931..8e3d7f2 100644 (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@
index 369304b..c986ca7 100644 (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)
 {
@@ -5020,28 +4902,6 @@ xcrealloc (void *ptr, size_t nmemb, size_t size)
 }
 
 void
-error (const char *message, ...)
-{
-  va_list args;
-
-  va_start (args, message);
-  fprintf (stderr, _("%s: Error: "), program_name);
-  vfprintf (stderr, message, args);
-  va_end (args);
-}
-
-void
-warn (const char *message, ...)
-{
-  va_list args;
-
-  va_start (args, message);
-  fprintf (stderr, _("%s: Warning: "), program_name);
-  vfprintf (stderr, message, args);
-  va_end (args);
-}
-
-void
 free_debug_memory (void)
 {
   unsigned int i;
index 1c47c5e..e9de463 100644 (file)
    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
    MA 02110-1301, USA.  */
 
-#if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
-/* We can't use any bfd types here since readelf may define BFD64 and
-   objdump may not.  */
-typedef unsigned long long dwarf_vma;
-typedef unsigned long long dwarf_size_type;
-#else
-typedef unsigned long dwarf_vma;
-typedef unsigned long dwarf_size_type;
-#endif
+typedef unsigned HOST_WIDEST_INT dwarf_vma;
+typedef unsigned HOST_WIDEST_INT dwarf_size_type;
 
 struct dwarf_section
 {
@@ -100,11 +93,6 @@ typedef struct
 }
 debug_info;
 
-extern dwarf_vma (*byte_get) (unsigned char *, int);
-extern dwarf_vma byte_get_signed (unsigned char *, int);
-extern dwarf_vma byte_get_little_endian (unsigned char *, int);
-extern dwarf_vma byte_get_big_endian (unsigned char *, int);
-
 extern int eh_addr_size;
 
 extern int do_debug_info;
@@ -142,8 +130,5 @@ void *cmalloc (size_t, size_t);
 void *xcmalloc (size_t, size_t);
 void *xcrealloc (void *, size_t, size_t);
 
-void error (const char *, ...) ATTRIBUTE_PRINTF_1;
-void warn (const char *, ...) ATTRIBUTE_PRINTF_1;
-
 unsigned long int read_leb128 (unsigned char *data,
                               unsigned int *length_return, int sign);
diff --git a/binutils/elfcomm.c b/binutils/elfcomm.c
new file mode 100644 (file)
index 0000000..e44dee8
--- /dev/null
@@ -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;
+}
diff --git a/binutils/elfcomm.h b/binutils/elfcomm.h
new file mode 100644 (file)
index 0000000..3f9727e
--- /dev/null
@@ -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.  */
+\f
+#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 */
index c9a4b5a..1805ec1 100644 (file)
 #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;
 }
index 11a11ae..da68eeb 100644 (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"
index 8c20888..3f4167b 100644 (file)
@@ -61,6 +61,7 @@
 
 #include "bfd.h"
 #include "bucomm.h"
+#include "elfcomm.h"
 #include "dwarf.h"
 
 #include "elf/common.h"
 #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.  */