Added a testsuite. More support for COPY relocations.
authorIan Lance Taylor <iant@google.com>
Thu, 30 Nov 2006 23:52:50 +0000 (23:52 +0000)
committerIan Lance Taylor <iant@google.com>
Thu, 30 Nov 2006 23:52:50 +0000 (23:52 +0000)
27 files changed:
gold/Makefile.am
gold/Makefile.in
gold/configure
gold/configure.ac
gold/fileread.cc
gold/fileread.h
gold/gold.cc
gold/gold.h
gold/i386.cc
gold/layout.cc
gold/main.cc [new file with mode: 0644]
gold/object.h
gold/output.cc
gold/output.h
gold/po/gold.pot
gold/readsyms.cc
gold/reloc.cc
gold/reloc.h
gold/target.h
gold/testsuite/Makefile.am [new file with mode: 0644]
gold/testsuite/Makefile.in [new file with mode: 0644]
gold/testsuite/object_unittest.cc [new file with mode: 0644]
gold/testsuite/test.cc [new file with mode: 0644]
gold/testsuite/test.h [new file with mode: 0644]
gold/testsuite/testfile.cc [new file with mode: 0644]
gold/testsuite/testfile.h [new file with mode: 0644]
gold/testsuite/testmain.cc [new file with mode: 0644]

index f76ee5b00c5852c6fda7ac0181a8bdc65c569e44..02a6da11f63722186e88ec9ea9294866f31a2c9d 100644 (file)
@@ -2,7 +2,7 @@
 
 AUTOMAKE_OPTIONS =
 
-SUBDIRS = po
+SUBDIRS = po testsuite
 
 tooldir = $(exec_prefix)/$(target_alias)
 
@@ -18,6 +18,7 @@ INCLUDES = -D_GNU_SOURCE \
 YFLAGS = -d
 
 noinst_PROGRAMS = ld-new
+noinst_LIBRARIES = libgold.a
 
 CCFILES = \
        archive.cc \
@@ -74,19 +75,18 @@ YFILES = \
 
 EXTRA_DIST = yyscript.c yyscript.h
 
-POTFILES= $(CCFILES) $(HFILES) $(TARGETFILES)
-
-po/POTFILES.in: @MAINT@ Makefile
-       for f in $(POTFILES); do echo $$f; done | LC_COLLATE= sort > tmp \
-         && mv tmp $(srcdir)/po/POTFILES.in
+libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES)
 
-ld_new_SOURCES = $(CCFILES) $(HFILES) $(TARGETFILES) $(YFILES)
-ld_new_DEPENDENCIES = $(LIBINTL_DEP)
-ld_new_LDADD = $(LIBINTL)
+ld_new_SOURCES = main.cc $(TARGETFILES)
+ld_new_DEPENDENCIES = libgold.a $(LIBINTL_DEP)
+ld_new_LDADD = libgold.a $(LIBINTL)
 
 # Use an explicit dependency for the bison generated header file.
 script.$(OBJEXT): yyscript.h
 
+# We have to build libgold.a before we run the tests.
+check: libgold.a
+
 .PHONY: install-exec-local
 
 install-exec-local: ld-new$(EXEEXT)
@@ -102,3 +102,9 @@ install-exec-local: ld-new$(EXEEXT)
 # We want install to imply install-info as per GNU standards, despite
 # the cygnus option.
 install-data-local: install-info
+
+POTFILES= $(CCFILES) $(HFILES) $(TARGETFILES)
+
+po/POTFILES.in: @MAINT@ Makefile
+       for f in $(POTFILES); do echo $$f; done | LC_COLLATE= sort > tmp \
+         && mv tmp $(srcdir)/po/POTFILES.in
index 560f481932b6f2e00604ab92e5333d2120dfbe23..36994c3dad984450f7fc9cb3edc9105314792044 100644 (file)
@@ -16,6 +16,7 @@
 
 # Process this file with automake to generate Makefile.in
 
+
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
 VPATH = @srcdir@
@@ -62,7 +63,11 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
 mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
 CONFIG_HEADER = config.h
 CONFIG_CLEAN_FILES = po/Makefile.in
-PROGRAMS = $(noinst_PROGRAMS)
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libgold_a_AR = $(AR) $(ARFLAGS)
+libgold_a_LIBADD =
 am__objects_1 = archive.$(OBJEXT) common.$(OBJEXT) defstd.$(OBJEXT) \
        dirsearch.$(OBJEXT) dynobj.$(OBJEXT) fileread.$(OBJEXT) \
        gold.$(OBJEXT) gold-threads.$(OBJEXT) layout.$(OBJEXT) \
@@ -71,10 +76,13 @@ am__objects_1 = archive.$(OBJEXT) common.$(OBJEXT) defstd.$(OBJEXT) \
        script.$(OBJEXT) symtab.$(OBJEXT) stringpool.$(OBJEXT) \
        target-select.$(OBJEXT) workqueue.$(OBJEXT)
 am__objects_2 =
-am__objects_3 = i386.$(OBJEXT)
-am__objects_4 = yyscript.$(OBJEXT)
-am_ld_new_OBJECTS = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
-       $(am__objects_4)
+am__objects_3 = yyscript.$(OBJEXT)
+am_libgold_a_OBJECTS = $(am__objects_1) $(am__objects_2) \
+       $(am__objects_3)
+libgold_a_OBJECTS = $(am_libgold_a_OBJECTS)
+PROGRAMS = $(noinst_PROGRAMS)
+am__objects_4 = i386.$(OBJEXT)
+am_ld_new_OBJECTS = main.$(OBJEXT) $(am__objects_4)
 ld_new_OBJECTS = $(am_ld_new_OBJECTS)
 am__DEPENDENCIES_1 =
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I.
@@ -90,8 +98,8 @@ CXXLD = $(CXX)
 CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
        -o $@
 YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
-SOURCES = $(ld_new_SOURCES)
-DIST_SOURCES = $(ld_new_SOURCES)
+SOURCES = $(libgold_a_SOURCES) $(ld_new_SOURCES)
+DIST_SOURCES = $(libgold_a_SOURCES) $(ld_new_SOURCES)
 RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
        html-recursive info-recursive install-data-recursive \
        install-exec-recursive install-info-recursive \
@@ -171,6 +179,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
 POSUB = @POSUB@
+RANLIB = @RANLIB@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
@@ -182,6 +191,7 @@ XGETTEXT = @XGETTEXT@
 YACC = @YACC@
 ac_ct_CC = @ac_ct_CC@
 ac_ct_CXX = @ac_ct_CXX@
+ac_ct_RANLIB = @ac_ct_RANLIB@
 ac_ct_STRIP = @ac_ct_STRIP@
 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
@@ -225,7 +235,7 @@ target_cpu = @target_cpu@
 target_os = @target_os@
 target_vendor = @target_vendor@
 AUTOMAKE_OPTIONS = 
-SUBDIRS = po
+SUBDIRS = po testsuite
 tooldir = $(exec_prefix)/$(target_alias)
 ACLOCAL_AMFLAGS = -I ../bfd -I ../config
 AM_CXXFLAGS = $(WARN_CXXFLAGS) $(LFS_CXXFLAGS)
@@ -235,6 +245,7 @@ INCLUDES = -D_GNU_SOURCE \
        @INCINTL@
 
 YFLAGS = -d
+noinst_LIBRARIES = libgold.a
 CCFILES = \
        archive.cc \
        common.cc \
@@ -289,10 +300,11 @@ YFILES = \
        yyscript.y
 
 EXTRA_DIST = yyscript.c yyscript.h
+libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES)
+ld_new_SOURCES = main.cc $(TARGETFILES)
+ld_new_DEPENDENCIES = libgold.a $(LIBINTL_DEP)
+ld_new_LDADD = libgold.a $(LIBINTL)
 POTFILES = $(CCFILES) $(HFILES) $(TARGETFILES)
-ld_new_SOURCES = $(CCFILES) $(HFILES) $(TARGETFILES) $(YFILES)
-ld_new_DEPENDENCIES = $(LIBINTL_DEP)
-ld_new_LDADD = $(LIBINTL)
 all: config.h
        $(MAKE) $(AM_MAKEFLAGS) all-recursive
 
@@ -351,13 +363,20 @@ distclean-hdr:
 po/Makefile.in: $(top_builddir)/config.status $(top_srcdir)/po/Make-in
        cd $(top_builddir) && $(SHELL) ./config.status $@
 
-clean-noinstPROGRAMS:
-       -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+clean-noinstLIBRARIES:
+       -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
 yyscript.h: yyscript.c
        @if test ! -f $@; then \
          rm -f yyscript.c; \
          $(MAKE) yyscript.c; \
        else :; fi
+libgold.a: $(libgold_a_OBJECTS) $(libgold_a_DEPENDENCIES) 
+       -rm -f libgold.a
+       $(libgold_a_AR) libgold.a $(libgold_a_OBJECTS) $(libgold_a_LIBADD)
+       $(RANLIB) libgold.a
+
+clean-noinstPROGRAMS:
+       -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
 ld-new$(EXEEXT): $(ld_new_OBJECTS) $(ld_new_DEPENDENCIES) 
        @rm -f ld-new$(EXEEXT)
        $(CXXLINK) $(ld_new_LDFLAGS) $(ld_new_OBJECTS) $(ld_new_LDADD) $(LIBS)
@@ -378,6 +397,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gold.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i386.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layout.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Po@am__quote@
@@ -717,7 +737,7 @@ distcleancheck: distclean
               exit 1; } >&2
 check-am: all-am
 check: check-recursive
-all-am: Makefile $(PROGRAMS) config.h
+all-am: Makefile $(LIBRARIES) $(PROGRAMS) config.h
 installdirs: installdirs-recursive
 installdirs-am:
 install: install-recursive
@@ -748,7 +768,8 @@ maintainer-clean-generic:
        -rm -f yyscript.h
 clean: clean-recursive
 
-clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am
+clean-am: clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS \
+       mostlyclean-am
 
 distclean: distclean-recursive
        -rm -f $(am__CONFIG_DISTCLEAN_FILES)
@@ -801,29 +822,29 @@ uninstall-am: uninstall-info-am
 uninstall-info: uninstall-info-recursive
 
 .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \
-       check-am clean clean-generic clean-noinstPROGRAMS \
-       clean-recursive ctags ctags-recursive dist dist-all dist-bzip2 \
-       dist-gzip dist-shar dist-tarZ dist-zip distcheck distclean \
-       distclean-compile distclean-generic distclean-hdr \
-       distclean-recursive distclean-tags distcleancheck distdir \
-       distuninstallcheck dvi dvi-am html html-am info info-am \
-       install install-am install-data install-data-am \
-       install-data-local install-exec install-exec-am \
-       install-exec-local install-info install-info-am install-man \
-       install-strip installcheck installcheck-am installdirs \
-       installdirs-am maintainer-clean maintainer-clean-generic \
-       maintainer-clean-recursive mostlyclean mostlyclean-compile \
-       mostlyclean-generic mostlyclean-recursive pdf pdf-am ps ps-am \
-       tags tags-recursive uninstall uninstall-am uninstall-info-am
+       check-am clean clean-generic clean-noinstLIBRARIES \
+       clean-noinstPROGRAMS clean-recursive ctags ctags-recursive \
+       dist dist-all dist-bzip2 dist-gzip dist-shar dist-tarZ \
+       dist-zip distcheck distclean distclean-compile \
+       distclean-generic distclean-hdr distclean-recursive \
+       distclean-tags distcleancheck distdir distuninstallcheck dvi \
+       dvi-am html html-am info info-am install install-am \
+       install-data install-data-am install-data-local install-exec \
+       install-exec-am install-exec-local install-info \
+       install-info-am install-man install-strip installcheck \
+       installcheck-am installdirs installdirs-am maintainer-clean \
+       maintainer-clean-generic maintainer-clean-recursive \
+       mostlyclean mostlyclean-compile mostlyclean-generic \
+       mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \
+       uninstall uninstall-am uninstall-info-am
 
 
-po/POTFILES.in: @MAINT@ Makefile
-       for f in $(POTFILES); do echo $$f; done | LC_COLLATE= sort > tmp \
-         && mv tmp $(srcdir)/po/POTFILES.in
-
 # Use an explicit dependency for the bison generated header file.
 script.$(OBJEXT): yyscript.h
 
+# We have to build libgold.a before we run the tests.
+check: libgold.a
+
 .PHONY: install-exec-local
 
 install-exec-local: ld-new$(EXEEXT)
@@ -839,6 +860,10 @@ install-exec-local: ld-new$(EXEEXT)
 # We want install to imply install-info as per GNU standards, despite
 # the cygnus option.
 install-data-local: install-info
+
+po/POTFILES.in: @MAINT@ Makefile
+       for f in $(POTFILES); do echo $$f; done | LC_COLLATE= sort > tmp \
+         && mv tmp $(srcdir)/po/POTFILES.in
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
index 8be7e913a5dc5e385c56ea19a36f0a869bb8bb1c..5d69594d33fb7fa2589f9ff67fa2e5e30a2387d6 100755 (executable)
@@ -309,7 +309,7 @@ ac_includes_default="\
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE YACC USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CXXFLAGS CXXCPP EGREP MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE YACC RANLIB ac_ct_RANLIB USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CXXFLAGS CXXCPP EGREP MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LIBOBJS LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -3450,6 +3450,86 @@ fi
 done
 test -n "$YACC" || YACC="yacc"
 
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  RANLIB=$ac_ct_RANLIB
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
 # Find a good install program.  We prefer a C program (faster),
 # so one script is as good as another.  But avoid the broken or
 # incompatible versions:
@@ -5070,7 +5150,7 @@ fi
 
 
 
-                    ac_config_files="$ac_config_files Makefile po/Makefile.in:po/Make-in"
+                              ac_config_files="$ac_config_files Makefile testsuite/Makefile po/Makefile.in:po/Make-in"
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
 # tests run on this system so they can be shared between configure
@@ -5642,6 +5722,7 @@ do
   case "$ac_config_target" in
   # Handling of arguments.
   "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  "testsuite/Makefile" ) CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;;
   "po/Makefile.in" ) CONFIG_FILES="$CONFIG_FILES po/Makefile.in:po/Make-in" ;;
   "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
   "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
@@ -5788,6 +5869,8 @@ s,@CXXDEPMODE@,$CXXDEPMODE,;t t
 s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t
 s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t
 s,@YACC@,$YACC,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
 s,@USE_NLS@,$USE_NLS,;t t
 s,@LIBINTL@,$LIBINTL,;t t
 s,@LIBINTL_DEP@,$LIBINTL_DEP,;t t
index 10e0db98b27b86f0c156b8986229c9b38bb730a6..5cbaf2c455d9cd011b4324110bb8f3d249452b37 100644 (file)
@@ -13,6 +13,7 @@ AM_CONFIG_HEADER(config.h:config.in)
 AC_PROG_CC
 AC_PROG_CXX
 AC_PROG_YACC
+AC_PROG_RANLIB
 AC_PROG_INSTALL
 ZW_GNU_GETTEXT_SISTER_DIR
 AM_PO_SUBDIRS
@@ -48,4 +49,4 @@ AC_LANG_POP(C++)
 
 AM_MAINTAINER_MODE
 
-AC_OUTPUT(Makefile po/Makefile.in:po/Make-in)
+AC_OUTPUT(Makefile testsuite/Makefile po/Makefile.in:po/Make-in)
index e96476c34ff297794dca6626304eced86fc831e6..1a142022569a624bdfd8e7148404374e96a1d104 100644 (file)
@@ -60,6 +60,8 @@ File_read::~File_read()
   this->clear_views(true);
 }
 
+// Open the file.
+
 bool
 File_read::open(const std::string& name)
 {
@@ -72,11 +74,20 @@ File_read::open(const std::string& name)
   return this->descriptor_ >= 0;
 }
 
-int
-File_read::get_descriptor()
+// Open the file for testing purposes.
+
+bool
+File_read::open(const std::string& name, const unsigned char* contents,
+               off_t contents_size)
 {
-  gold_assert(this->lock_count_ > 0);
-  return this->descriptor_;
+  gold_assert(this->lock_count_ == 0
+             && this->descriptor_ < 0
+             && this->name_.empty());
+  this->name_ = name;
+  this->contents_ = contents;
+  this->contents_size_ = contents_size;
+  ++this->lock_count_;
+  return true;
 }
 
 void
@@ -121,23 +132,37 @@ off_t
 File_read::do_read(off_t start, off_t size, void* p, off_t* pbytes)
 {
   gold_assert(this->lock_count_ > 0);
-  int o = this->descriptor_;
 
-  if (lseek(o, start, SEEK_SET) < 0)
+  off_t bytes;
+  if (this->contents_ == NULL)
     {
-      fprintf(stderr, _("%s: %s: lseek to %lld failed: %s"),
-             program_name, this->filename().c_str(),
-             static_cast<long long>(start),
-             strerror(errno));
-      gold_exit(false);
-    }
+      int o = this->descriptor_;
 
-  off_t bytes = ::read(o, p, size);
-  if (bytes < 0)
+      if (lseek(o, start, SEEK_SET) < 0)
+       {
+         fprintf(stderr, _("%s: %s: lseek to %lld failed: %s"),
+                 program_name, this->filename().c_str(),
+                 static_cast<long long>(start),
+                 strerror(errno));
+         gold_exit(false);
+       }
+
+      bytes = ::read(o, p, size);
+      if (bytes < 0)
+       {
+         fprintf(stderr, _("%s: %s: read failed: %s\n"),
+                 program_name, this->filename().c_str(), strerror(errno));
+         gold_exit(false);
+       }
+    }
+  else
     {
-      fprintf(stderr, _("%s: %s: read failed: %s\n"),
-             program_name, this->filename().c_str(), strerror(errno));
-      gold_exit(false);
+      bytes = this->contents_size_ - start;
+      if (bytes < 0)
+       bytes = 0;
+      else if (bytes > size)
+       bytes = size;
+      memcpy(p, this->contents_ + start, bytes);
     }
 
   if (pbytes != NULL)
@@ -302,16 +327,30 @@ File_view::~File_view()
 
 // Class Input_file.
 
+// Create a file for testing.
+
+Input_file::Input_file(const char* name, const unsigned char* contents,
+                      off_t size)
+  : file_()
+{
+  this->input_argument_ =
+    new Input_file_argument(name, false, Position_dependent_options());
+  bool ok = file_.open(name, contents, size);
+  gold_assert(ok);
+}
+
+// Open the file.
+
 void
 Input_file::open(const General_options& options, const Dirsearch& dirpath)
 {
   std::string name;
-  if (!this->input_argument_.is_lib())
-    name = this->input_argument_.name();
+  if (!this->input_argument_->is_lib())
+    name = this->input_argument_->name();
   else
     {
       std::string n1("lib");
-      n1 += this->input_argument_.name();
+      n1 += this->input_argument_->name();
       std::string n2;
       if (options.is_static())
        n1 += ".a";
@@ -324,7 +363,7 @@ Input_file::open(const General_options& options, const Dirsearch& dirpath)
       if (name.empty())
        {
          fprintf(stderr, _("%s: cannot find %s\n"), program_name,
-                 this->input_argument_.name());
+                 this->input_argument_->name());
          gold_exit(false);
        }
     }
index 6e49324ab86b98e32686c130a3d6596f9dbf0303..178e7f355e446f2afb8678f8bfb679596aa27234 100644 (file)
@@ -25,23 +25,27 @@ class File_read
 {
  public:
   File_read()
-    : name_(), descriptor_(-1), lock_count_(0)
+    : name_(), descriptor_(-1), lock_count_(0), views_(),
+      saved_views_(), contents_(NULL), contents_size_(0)
   { }
+
   ~File_read();
 
   // Open a file.
   bool
   open(const std::string& name);
 
+  // Pretend to open the file, but provide the file contents.  No
+  // actual file system activity will occur.  This is used for
+  // testing.
+  bool
+  open(const std::string& name, const unsigned char* contents, off_t size);
+
   // Return the file name.
   const std::string&
   filename() const
   { return this->name_; }
 
-  // Return the file descriptor.
-  int
-  get_descriptor();
-
   // Lock the file for access within a particular Task::run execution.
   // This means that the descriptor can not be closed.  This routine
   // may only be called from the main thread.
@@ -169,6 +173,10 @@ class File_read
   // List of views which were locked but had to be removed from views_
   // because they were not large enough.
   Saved_views saved_views_;
+  // Specified file contents.  Used only for testing purposes.
+  const unsigned char* contents_;
+  // Specified file size.  Used only for testing purposes.
+  off_t contents_size_;
 };
 
 // A view of file data that persists even when the file is unlocked.
@@ -209,17 +217,23 @@ class File_view
 class Input_file
 {
  public:
-  Input_file(const Input_file_argument& input_argument)
-    : input_argument_(input_argument)
+  Input_file(const Input_file_argument* input_argument)
+    : input_argument_(input_argument), file_()
   { }
 
+  // Create an input file with the contents already provided.  This is
+  // only used for testing.  With this path, don't call the open
+  // method.
+  Input_file(const char* name, const unsigned char* contents, off_t size);
+
+  // Open the file.
   void
   open(const General_options&, const Dirsearch&);
 
   // Return the name given by the user.
   const char*
   name() const
-  { return this->input_argument_.name(); }
+  { return this->input_argument_->name(); }
 
   // Return the file name.
   const std::string&
@@ -234,7 +248,7 @@ class Input_file
   Input_file(const Input_file&);
   Input_file& operator=(const Input_file&);
 
-  const Input_file_argument& input_argument_;
+  const Input_file_argument* input_argument_;
   File_read file_;
 };
 
index 7c8ed8fc5bef8b9039929ecc2e56de1975e370bd..5051a13a6aaeaa31429592bca5050fcd781fee13 100644 (file)
@@ -1,4 +1,4 @@
-// ld.c -- linker main function
+// gold.cc -- main linker functions
 
 #include "gold.h"
 
@@ -234,50 +234,3 @@ queue_final_tasks(const General_options& options,
 }
 
 } // End namespace gold.
-
-using namespace gold;
-
-int
-main(int argc, char** argv)
-{
-#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
-  setlocale (LC_MESSAGES, "");
-#endif
-#if defined (HAVE_SETLOCALE)
-  setlocale (LC_CTYPE, "");
-#endif
-  bindtextdomain (PACKAGE, LOCALEDIR);
-  textdomain (PACKAGE);
-
-  gold::program_name = argv[0];
-
-  // Handle the command line options.
-  gold::Command_line command_line;
-  command_line.process(argc - 1, argv + 1);
-
-  // The work queue.
-  gold::Workqueue workqueue(command_line.options());
-
-  // The list of input objects.
-  Input_objects input_objects;
-
-  // The symbol table.
-  Symbol_table symtab;
-
-  // The layout object.
-  Layout layout(command_line.options());
-
-  // Get the search path from the -L options.
-  Dirsearch search_path;
-  search_path.add(&workqueue, command_line.options().search_path());
-
-  // Queue up the first set of tasks.
-  queue_initial_tasks(command_line.options(), search_path,
-                     command_line, &workqueue, &input_objects,
-                     &symtab, &layout);
-
-  // Run the main task processing loop.
-  workqueue.process();
-
-  gold::gold_exit(true);
-}
index 78c106f4dd0fe4e560e0dca1cb042c62b43d28e2..e4cd78694229cd9aefc134b7508645596ab7bb9e 100644 (file)
@@ -137,6 +137,7 @@ namespace gold
 {
 
 class General_options;
+class Command_line;
 class Input_argument_list;
 class Dirsearch;
 class Input_objects;
@@ -180,7 +181,7 @@ extern void do_gold_unreachable(const char*, int, const char*)
 extern void
 queue_initial_tasks(const General_options&,
                    const Dirsearch&,
-                   const Input_argument_list&,
+                   const Command_line&,
                    Workqueue*,
                    Input_objects*,
                    Symbol_table*,
index 488da799f8054c0e05071bc9c6c2d31ec8d002cb..4cf90e99f9eaf54a368f84b7b58e82439551490a 100644 (file)
@@ -27,9 +27,12 @@ class Output_data_plt_i386;
 class Target_i386 : public Sized_target<32, false>
 {
  public:
+  typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, false> Reloc_section;
+
   Target_i386()
     : Sized_target<32, false>(&i386_info),
-      got_(NULL), plt_(NULL), got_plt_(NULL)
+      got_(NULL), plt_(NULL), got_plt_(NULL), rel_dyn_(NULL),
+      copy_relocs_(NULL), dynbss_(NULL)
   { }
 
   // Scan the relocations to look for symbol adjustments.
@@ -46,6 +49,10 @@ class Target_i386 : public Sized_target<32, false>
              const unsigned char* plocal_symbols,
              Symbol** global_symbols);
 
+  // Finalize the sections.
+  void
+  do_finalize_sections(Layout*);
+
   // Relocate a section.
   void
   relocate_section(const Relocate_info<32, false>*,
@@ -170,9 +177,14 @@ class Target_i386 : public Sized_target<32, false>
     return this->plt_;
   }
 
+  // Get the dynamic reloc section, creating it if necessary.
+  Reloc_section*
+  rel_dyn_section(Layout*);
+
   // Copy a relocation against a global symbol.
   void
-  copy_reloc(const General_options*, Sized_relobj<32, false>*, unsigned int,
+  copy_reloc(const General_options*, Symbol_table*, Layout*,
+            Sized_relobj<32, false>*, unsigned int,
             Symbol*, const elfcpp::Rel<32, false>&);
 
   // Information about this specific target which we pass to the
@@ -185,6 +197,12 @@ class Target_i386 : public Sized_target<32, false>
   Output_data_plt_i386* plt_;
   // The GOT PLT section.
   Output_data_space* got_plt_;
+  // The dynamic reloc section.
+  Reloc_section* rel_dyn_;
+  // Relocs saved to avoid a COPY reloc.
+  Copy_relocs<32, false>* copy_relocs_;
+  // Space for variables copied with a COPY reloc.
+  Output_data_space* dynbss_;
 };
 
 const Target::Target_info Target_i386::i386_info =
@@ -238,6 +256,21 @@ Target_i386::got_section(const General_options* options, Symbol_table* symtab,
   return this->got_;
 }
 
+// Get the dynamic reloc section, creating it if necessary.
+
+Target_i386::Reloc_section*
+Target_i386::rel_dyn_section(Layout* layout)
+{
+  if (this->rel_dyn_ == NULL)
+    {
+      gold_assert(layout != NULL);
+      this->rel_dyn_ = new Reloc_section();
+      layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
+                                     elfcpp::SHF_ALLOC, this->rel_dyn_);
+    }
+  return this->rel_dyn_;
+}
+
 // A class to handle the PLT data.
 
 class Output_data_plt_i386 : public Output_section_data
@@ -493,18 +526,70 @@ Target_i386::make_plt_entry(const General_options* options,
 
 void
 Target_i386::copy_reloc(const General_options* options,
+                       Symbol_table* symtab,
+                       Layout* layout,
                        Sized_relobj<32, false>* object,
                        unsigned int data_shndx, Symbol* gsym,
-                       const elfcpp::Rel<32, false>&)
+                       const elfcpp::Rel<32, false>& rel)
 {
-  if (!Relocate_functions<32, false>::need_copy_reloc(options, object,
-                                                     data_shndx, gsym))
+  Sized_symbol<32>* ssym;
+  ssym = symtab->get_sized_symbol SELECT_SIZE_NAME(32) (gsym
+                                                       SELECT_SIZE(32));
+
+  if (!Copy_relocs<32, false>::need_copy_reloc(options, object,
+                                              data_shndx, ssym))
     {
       // So far we do not need a COPY reloc.  Save this relocation.
-      // If it turns out that we never a COPY reloc for this symbol,
-      // then we emit the relocation.
+      // If it turns out that we never need a COPY reloc for this
+      // symbol, then we will emit the relocation.
+      if (this->copy_relocs_ == NULL)
+       this->copy_relocs_ = new Copy_relocs<32, false>();
+      this->copy_relocs_->save(ssym, object, data_shndx, rel);
     }
+  else
+    {
+      // Allocate space for this symbol in the .bss section.
+
+      elfcpp::Elf_types<32>::Elf_WXword symsize = ssym->symsize();
+
+      // There is no defined way to determine the required alignment
+      // of the symbol.  We pick the alignment based on the size.  We
+      // set an arbitrary maximum of 256.
+      unsigned int align;
+      for (align = 1; align < 512; align <<= 1)
+       if ((symsize & align) != 0)
+         break;
 
+      if (this->dynbss_ == NULL)
+       {
+         this->dynbss_ = new Output_data_space(align);
+         layout->add_output_section_data(".bss",
+                                         elfcpp::SHT_NOBITS,
+                                         (elfcpp::SHF_ALLOC
+                                          | elfcpp::SHF_WRITE),
+                                         this->dynbss_);
+       }
+
+      Output_data_space* dynbss = this->dynbss_;
+
+      if (align > dynbss->addralign())
+       dynbss->set_space_alignment(align);
+
+      off_t dynbss_size = dynbss->data_size();
+      dynbss_size = align_address(dynbss_size, align);
+      off_t offset = dynbss_size;
+      dynbss->set_space_size(dynbss_size + symsize);
+
+      // Define the symbol in the .dynbss section.
+      symtab->define_in_output_data(this, ssym->name(), dynbss, offset,
+                                   symsize, ssym->type(), ssym->binding(),
+                                   ssym->visibility(), ssym->nonvis(),
+                                   false, false);
+
+      // Add the COPY reloc.
+      Reloc_section* rel_dyn = this->rel_dyn_section(layout);
+      rel_dyn->add_global(ssym, elfcpp::R_386_COPY, dynbss, offset);
+    }
 }
 
 // Optimize the TLS relocation type based on what we know about the
@@ -715,7 +800,8 @@ Target_i386::Scan::global(const General_options& options,
          if (gsym->type() == elfcpp::STT_FUNC)
            target->make_plt_entry(&options, symtab, layout, gsym);
          else
-           target->copy_reloc(&options, object, data_shndx, gsym, reloc);
+           target->copy_reloc(&options, symtab, layout, object, data_shndx,
+                              gsym, reloc);
        }
 
       break;
@@ -854,6 +940,23 @@ Target_i386::scan_relocs(const General_options& options,
     global_symbols);
 }
 
+// Finalize the sections.  This is where we emit any relocs we saved
+// in an attempt to avoid generating extra COPY relocs.
+
+void
+Target_i386::do_finalize_sections(Layout* layout)
+{
+  if (this->copy_relocs_ == NULL)
+    return;
+  if (this->copy_relocs_->any_to_emit())
+    {
+      Reloc_section* rel_dyn = this->rel_dyn_section(layout);
+      this->copy_relocs_->emit(rel_dyn);
+    }
+  delete this->copy_relocs_;
+  this->copy_relocs_ = NULL;
+}
+
 // Perform a relocation.
 
 inline bool
index 97917b0b7586008f1868cd4fdea46a50ca919029..0de42c2f758ab34d5f35e0b73f99ef1718de76aa 100644 (file)
@@ -383,9 +383,11 @@ Layout::find_first_load_seg()
 off_t
 Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
 {
-  const Target* const target = input_objects->target();
+  Target* const target = input_objects->target();
   const int size = target->get_size();
 
+  target->finalize_sections(this);
+
   Output_segment* phdr_seg = NULL;
   if (input_objects->any_dynamic())
     {
diff --git a/gold/main.cc b/gold/main.cc
new file mode 100644 (file)
index 0000000..ea65c2d
--- /dev/null
@@ -0,0 +1,57 @@
+// main.cc -- gold main function.
+
+#include "gold.h"
+
+#include "options.h"
+#include "dirsearch.h"
+#include "workqueue.h"
+#include "object.h"
+#include "symtab.h"
+#include "layout.h"
+
+using namespace gold;
+
+int
+main(int argc, char** argv)
+{
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+#if defined (HAVE_SETLOCALE)
+  setlocale (LC_CTYPE, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  program_name = argv[0];
+
+  // Handle the command line options.
+  Command_line command_line;
+  command_line.process(argc - 1, argv + 1);
+
+  // The work queue.
+  Workqueue workqueue(command_line.options());
+
+  // The list of input objects.
+  Input_objects input_objects;
+
+  // The symbol table.
+  Symbol_table symtab;
+
+  // The layout object.
+  Layout layout(command_line.options());
+
+  // Get the search path from the -L options.
+  Dirsearch search_path;
+  search_path.add(&workqueue, command_line.options().search_path());
+
+  // Queue up the first set of tasks.
+  queue_initial_tasks(command_line.options(), search_path,
+                     command_line, &workqueue, &input_objects,
+                     &symtab, &layout);
+
+  // Run the main task processing loop.
+  workqueue.process();
+
+  gold_exit(true);
+}
index cd2bc8d8e483bb930854aa4d8a6587ef3843b643..b823599cbcfc4b71d93d9c8c8bd96cb8ebbc8b13 100644 (file)
@@ -140,22 +140,10 @@ class Object
   Sized_target<size, big_endian>*
   sized_target(ACCEPT_SIZE_ENDIAN_ONLY);
 
-  // Read the symbol information.
-  void
-  read_symbols(Read_symbols_data* sd)
-  { return this->do_read_symbols(sd); }
-
-  // Pass sections which should be included in the link to the Layout
-  // object, and record where the sections go in the output file.
-  void
-  layout(const General_options& options, Symbol_table* symtab,
-        Layout* layout, Read_symbols_data* sd)
-  { this->do_layout(options, symtab, layout, sd); }
-
-  // Add symbol information to the global symbol table.
-  void
-  add_symbols(Symbol_table* symtab, Read_symbols_data* sd)
-  { this->do_add_symbols(symtab, sd); }
+  // Get the number of sections.
+  unsigned int
+  shnum() const
+  { return this->shnum_; }
 
   // Return a view of the contents of a section.  Set *PLEN to the
   // size.
@@ -173,6 +161,23 @@ class Object
   section_flags(unsigned int shndx)
   { return this->do_section_flags(shndx); }
 
+  // Read the symbol information.
+  void
+  read_symbols(Read_symbols_data* sd)
+  { return this->do_read_symbols(sd); }
+
+  // Pass sections which should be included in the link to the Layout
+  // object, and record where the sections go in the output file.
+  void
+  layout(const General_options& options, Symbol_table* symtab,
+        Layout* layout, Read_symbols_data* sd)
+  { this->do_layout(options, symtab, layout, sd); }
+
+  // Add symbol information to the global symbol table.
+  void
+  add_symbols(Symbol_table* symtab, Read_symbols_data* sd)
+  { this->do_add_symbols(symtab, sd); }
+
   // Functions and types for the elfcpp::Elf_file interface.  This
   // permit us to use Object as the File template parameter for
   // elfcpp::Elf_file.
@@ -280,11 +285,6 @@ class Object
   set_target(int machine, int size, bool big_endian, int osabi,
             int abiversion);
 
-  // Get the number of sections.
-  unsigned int
-  shnum() const
-  { return this->shnum_; }
-
   // Set the number of sections.
   void
   set_shnum(int shnum)
@@ -373,17 +373,17 @@ class Relobj : public Object
 
   // Return whether an input section is being included in the link.
   bool
-  is_section_included(unsigned int shnum) const
+  is_section_included(unsigned int shndx) const
   {
-    gold_assert(shnum < this->map_to_output_.size());
-    return this->map_to_output_[shnum].output_section != NULL;
+    gold_assert(shndx < this->map_to_output_.size());
+    return this->map_to_output_[shndx].output_section != NULL;
   }
 
   // Given a section index, return the corresponding Output_section
   // (which will be NULL if the section is not included in the link)
   // and set *POFF to the offset within that section.
   inline Output_section*
-  output_section(unsigned int shnum, off_t* poff);
+  output_section(unsigned int shndx, off_t* poff);
 
   // Set the offset of an input section within its output section.
   void
@@ -437,10 +437,10 @@ class Relobj : public Object
 
 // Implement Object::output_section inline for efficiency.
 inline Output_section*
-Relobj::output_section(unsigned int shnum, off_t* poff)
+Relobj::output_section(unsigned int shndx, off_t* poff)
 {
-  gold_assert(shnum < this->map_to_output_.size());
-  const Map_to_output& mo(this->map_to_output_[shnum]);
+  gold_assert(shndx < this->map_to_output_.size());
+  const Map_to_output& mo(this->map_to_output_[shndx]);
   *poff = mo.offset;
   return mo.output_section;
 }
index e4720dff0d1ecf14ed96ae0b547b00e48904ff41..2dbf576fc1647d65b8b1537db9f32599f34f3e7d 100644 (file)
@@ -415,19 +415,19 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_symbol_index()
       gold_unreachable();
 
     case GSYM_CODE:
-      if (this->u_.gsym == NULL)
+      if (this->u1_.gsym == NULL)
        index = 0;
       else if (dynamic)
-       index = this->u_.gsym->dynsym_index();
+       index = this->u1_.gsym->dynsym_index();
       else
-       index = this->u_.gsym->symtab_index();
+       index = this->u1_.gsym->symtab_index();
       break;
 
     case SECTION_CODE:
       if (dynamic)
-       index = this->u_.os->dynsym_index();
+       index = this->u1_.os->dynsym_index();
       else
-       index = this->u_.os->symtab_index();
+       index = this->u1_.os->symtab_index();
       break;
 
     default:
@@ -439,7 +439,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_symbol_index()
          gold_unreachable();
        }
       else
-       index = this->u_.object->symtab_index(this->local_sym_index_);
+       index = this->u1_.relobj->symtab_index(this->local_sym_index_);
       break;
     }
   gold_assert(index != -1U);
@@ -456,8 +456,16 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::write_rel(
     Write_rel* wr) const
 {
   Address address = this->address_;
-  if (this->od_ != NULL)
-    address += this->od_->address();
+  if (this->shndx_ != INVALID_CODE)
+    {
+      off_t off;
+      Output_section* os = this->u2_.relobj->output_section(this->shndx_,
+                                                           &off);
+      gold_assert(os != NULL);
+      address += os->address() + off;
+    }
+  else if (this->u2_.od != NULL)
+    address += this->u2_.od->address();
   wr->put_r_offset(address);
   wr->put_r_info(elfcpp::elf_r_info<size>(this->get_symbol_index(),
                                          this->type_));
index c7d835d78bf66502e4e4b9108cb8b6f70c87cc17..6e575ba404c2d1017edf8f4f2912943b5e6729b0 100644 (file)
@@ -323,6 +323,11 @@ class Output_section_data : public Output_data
   unsigned int
   do_out_shndx() const;
 
+  // Set the alignment.
+  void
+  set_addralign(uint64_t addralign)
+  { this->addralign_ = addralign; }
+
  private:
   // The output section for this section.
   const Output_section* output_section_;
@@ -402,6 +407,11 @@ class Output_data_space : public Output_section_data
   set_space_size(off_t space_size)
   { this->set_data_size(space_size); }
 
+  // Set the alignment.
+  void
+  set_space_alignment(uint64_t align)
+  { this->set_addralign(align); }
+
   // Write out the data--this must be handled elsewhere.
   void
   do_write(Output_file*)
@@ -457,30 +467,77 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   { }
 
   // A reloc against a global symbol.
+
   Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
               Address address)
-    : local_sym_index_(GSYM_CODE), type_(type), od_(od), address_(address)
-  { this->u_.gsym = gsym; }
+    : address_(address), local_sym_index_(GSYM_CODE), type_(type),
+      shndx_(INVALID_CODE)
+  {
+    this->u1_.gsym = gsym;
+    this->u2_.od = od;
+  }
+
+  Output_reloc(Symbol* gsym, unsigned int type, Relobj* relobj,
+              unsigned int shndx, Address address)
+    : address_(address), local_sym_index_(GSYM_CODE), type_(type),
+      shndx_(shndx)
+  {
+    gold_assert(shndx != INVALID_CODE);
+    this->u1_.gsym = gsym;
+    this->u2_.relobj = relobj;
+  }
 
   // A reloc against a local symbol.
-  Output_reloc(Sized_relobj<size, big_endian>* object,
+
+  Output_reloc(Sized_relobj<size, big_endian>* relobj,
               unsigned int local_sym_index,
               unsigned int type,
               Output_data* od,
               Address address)
-    : local_sym_index_(local_sym_index), type_(type), od_(od),
-      address_(address)
+    : address_(address), local_sym_index_(local_sym_index), type_(type),
+      shndx_(INVALID_CODE)
   {
     gold_assert(local_sym_index != GSYM_CODE
                && local_sym_index != INVALID_CODE);
-    this->u_.object = object;
+    this->u1_.relobj = relobj;
+    this->u2_.od = od;
+  }
+
+  Output_reloc(Sized_relobj<size, big_endian>* relobj,
+              unsigned int local_sym_index,
+              unsigned int type,
+              unsigned int shndx,
+              Address address)
+    : address_(address), local_sym_index_(local_sym_index), type_(type),
+      shndx_(shndx)
+  {
+    gold_assert(local_sym_index != GSYM_CODE
+               && local_sym_index != INVALID_CODE);
+    gold_assert(shndx != INVALID_CODE);
+    this->u1_.relobj = relobj;
+    this->u2_.relobj = relobj;
   }
 
   // A reloc against the STT_SECTION symbol of an output section.
+
   Output_reloc(Output_section* os, unsigned int type, Output_data* od,
               Address address)
-    : local_sym_index_(SECTION_CODE), type_(type), od_(od), address_(address)
-  { this->u_.os = os; }
+    : address_(address), local_sym_index_(SECTION_CODE), type_(type),
+      shndx_(INVALID_CODE)
+  {
+    this->u1_.os = os;
+    this->u2_.od = od;
+  }
+
+  Output_reloc(Output_section* os, unsigned int type, Relobj* relobj,
+              unsigned int shndx, Address address)
+    : address_(address), local_sym_index_(SECTION_CODE), type_(type),
+      shndx_(shndx)
+  {
+    gold_assert(shndx != INVALID_CODE);
+    this->u1_.os = os;
+    this->u2_.relobj = relobj;
+  }
 
   // Write the reloc entry to an output view.
   void
@@ -513,24 +570,34 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
     // relocation against a local symbol in a dynamic object; that
     // doesn't make sense.  And our callers will always be
     // templatized, so we use Sized_relobj here.
-    Sized_relobj<size, big_endian>* object;
+    Sized_relobj<size, big_endian>* relobj;
     // For a global symbol, the symbol.  If this is NULL, it indicates
     // a relocation against the undefined 0 symbol.
     Symbol* gsym;
     // For a relocation against an output section, the output section.
     Output_section* os;
-  } u_;
+  } u1_;
+  union
+  {
+    // If shndx_ is not INVALID CODE, the object which holds the input
+    // section being used to specify the reloc address.
+    Relobj* relobj;
+    // If shndx_ is INVALID_CODE, the output data being used to
+    // specify the reloc address.  This may be NULL if the reloc
+    // address is absolute.
+    Output_data* od;
+  } u2_;
+  // The address offset within the input section or the Output_data.
+  Address address_;
   // For a local symbol, the local symbol index.  This is GSYM_CODE
   // for a global symbol, or INVALID_CODE for an uninitialized value.
   unsigned int local_sym_index_;
   // The reloc type--a processor specific code.
   unsigned int type_;
-  // If this is not NULL, then the relocation is against the contents
-  // of this output data.
-  Output_data* od_;
-  // The reloc address--if od_ is not NULL, this is the offset from
-  // the start of od_.
-  Address address_;
+  // If the reloc address is an input section in an object, the
+  // section index.  This is INVALID_CODE if the reloc address is
+  // specified in some other way.
+  unsigned int shndx_;
 };
 
 // The SHT_RELA version of Output_reloc<>.  This is just derived from
@@ -549,25 +616,48 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   { }
 
   // A reloc against a global symbol.
+
   Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
               Address address, Addend addend)
     : rel_(gsym, type, od, address), addend_(addend)
   { }
 
+  Output_reloc(Symbol* gsym, unsigned int type, Relobj* relobj,
+              unsigned int shndx, Address address, Addend addend)
+    : rel_(gsym, type, relobj, shndx, address), addend_(addend)
+  { }
+
   // A reloc against a local symbol.
-  Output_reloc(Sized_relobj<size, big_endian>* object,
+
+  Output_reloc(Sized_relobj<size, big_endian>* relobj,
               unsigned int local_sym_index,
               unsigned int type, Output_data* od, Address address,
               Addend addend)
-    : rel_(object, local_sym_index, type, od, address), addend_(addend)
+    : rel_(relobj, local_sym_index, type, od, address), addend_(addend)
+  { }
+
+  Output_reloc(Sized_relobj<size, big_endian>* relobj,
+              unsigned int local_sym_index,
+              unsigned int type,
+              unsigned int shndx,
+              Address address,
+              Addend addend)
+    : rel_(relobj, local_sym_index, type, shndx, address),
+      addend_(addend)
   { }
 
   // A reloc against the STT_SECTION symbol of an output section.
+
   Output_reloc(Output_section* os, unsigned int type, Output_data* od,
               Address address, Addend addend)
     : rel_(os, type, od, address), addend_(addend)
   { }
 
+  Output_reloc(Output_section* os, unsigned int type, Relobj* relobj,
+              unsigned int shndx, Address address, Addend addend)
+    : rel_(os, type, relobj, shndx, address), addend_(addend)
+  { }
+
   // Write the reloc entry to an output view.
   void
   write(unsigned char* pov) const;
@@ -643,22 +733,43 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   { }
 
   // Add a reloc against a global symbol.
+
   void
   add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address)
   { this->add(Output_reloc_type(gsym, type, od, address)); }
 
+  void
+  add_global(Symbol* gsym, unsigned int type, Relobj* relobj,
+            unsigned int shndx, Address address)
+  { this->add(Output_reloc_type(gsym, type, relobj, shndx, address)); }
+
   // Add a reloc against a local symbol.
+
   void
-  add_local(Sized_relobj<size, big_endian>* object,
+  add_local(Sized_relobj<size, big_endian>* relobj,
            unsigned int local_sym_index, unsigned int type,
            Output_data* od, Address address)
-  { this->add(Output_reloc_type(object, local_sym_index, type, od, address)); }
+  { this->add(Output_reloc_type(relobj, local_sym_index, type, od, address)); }
+
+  void
+  add_local(Sized_relobj<size, big_endian>* relobj,
+           unsigned int local_sym_index, unsigned int type,
+           unsigned int shndx, Address address)
+  { this->add(Output_reloc_type(relobj, local_sym_index, type, shndx,
+                               address)); }
+
 
   // A reloc against the STT_SECTION symbol of an output section.
+
   void
   add_output_section(Output_section* os, unsigned int type,
                     Output_data* od, Address address)
   { this->add(Output_reloc_type(os, type, od, address)); }
+
+  void
+  add_output_section(Output_section* os, unsigned int type,
+                    Relobj* relobj, unsigned int shndx, Address address)
+  { this->add(Output_reloc_type(os, type, relobj, shndx, address)); }
 };
 
 // The SHT_RELA version of Output_data_reloc.
@@ -681,26 +792,48 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   { }
 
   // Add a reloc against a global symbol.
+
   void
   add_global(Symbol* gsym, unsigned int type, Output_data* od,
             Address address, Addend addend)
   { this->add(Output_reloc_type(gsym, type, od, address, addend)); }
 
+  void
+  add_global(Symbol* gsym, unsigned int type, Relobj* relobj,
+            unsigned int shndx, Address address, Addend addend)
+  { this->add(Output_reloc_type(gsym, type, relobj, shndx, address, addend)); }
+
   // Add a reloc against a local symbol.
+
   void
-  add_local(Sized_relobj<size, big_endian>* object,
+  add_local(Sized_relobj<size, big_endian>* relobj,
            unsigned int local_sym_index, unsigned int type,
            Output_data* od, Address address, Addend addend)
   {
-    this->add(Output_reloc_type(object, local_sym_index, type, od, address,
+    this->add(Output_reloc_type(relobj, local_sym_index, type, od, address,
+                               addend));
+  }
+
+  void
+  add_local(Sized_relobj<size, big_endian>* relobj,
+           unsigned int local_sym_index, unsigned int type,
+           unsigned int shndx, Address address, Addend addend)
+  {
+    this->add(Output_reloc_type(relobj, local_sym_index, type, shndx, address,
                                addend));
   }
 
   // A reloc against the STT_SECTION symbol of an output section.
+
   void
   add_output_section(Output_section* os, unsigned int type, Output_data* od,
                     Address address, Addend addend)
   { this->add(Output_reloc_type(os, type, od, address, addend)); }
+
+  void
+  add_output_section(Output_section* os, unsigned int type, Relobj* relobj,
+                    unsigned int shndx, Address address, Addend addend)
+  { this->add(Output_reloc_type(os, type, relobj, shndx, address, addend)); }
 };
 
 // Output_data_got is used to manage a GOT.  Each entry in the GOT is
index 5663031576a2f32d47af0955183bf60edfa6528c..4a852a1e720e731b9b8ec12e1fb8605ed8b4f673 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-11-29 09:53-0800\n"
+"POT-Creation-Date: 2006-11-30 15:37-0800\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -161,27 +161,27 @@ msgstr ""
 msgid "%s: warning: close(%s) failed: %s"
 msgstr ""
 
-#: fileread.cc:128
+#: fileread.cc:143
 #, c-format
 msgid "%s: %s: lseek to %lld failed: %s"
 msgstr ""
 
-#: fileread.cc:138
+#: fileread.cc:153
 #, c-format
 msgid "%s: %s: read failed: %s\n"
 msgstr ""
 
-#: fileread.cc:148 fileread.cc:231
+#: fileread.cc:173 fileread.cc:256
 #, c-format
 msgid "%s: %s: file too short: read only %lld of %lld bytes at %lld\n"
 msgstr ""
 
-#: fileread.cc:326
+#: fileread.cc:365
 #, c-format
 msgid "%s: cannot find %s\n"
 msgstr ""
 
-#: fileread.cc:334
+#: fileread.cc:373
 #, c-format
 msgid "%s: cannot open %s: %s\n"
 msgstr ""
@@ -235,57 +235,57 @@ msgid "pthread_cond_signal failed"
 msgstr ""
 
 #. FIXME: This needs to specify the location somehow.
-#: i386.cc:93
+#: i386.cc:100
 #, c-format
 msgid "%s: missing expected TLS relocation\n"
 msgstr ""
 
-#: i386.cc:617 i386.cc:757 i386.cc:961
+#: i386.cc:702 i386.cc:843 i386.cc:1064
 #, c-format
 msgid "%s: %s: unexpected reloc %u in object file\n"
 msgstr ""
 
-#: i386.cc:653 i386.cc:672
+#: i386.cc:738 i386.cc:757
 #, c-format
 msgid "%s: %s: unsupported reloc %u against local symbol\n"
 msgstr ""
 
-#: i386.cc:793 i386.cc:814
+#: i386.cc:879 i386.cc:900
 #, c-format
 msgid "%s: %s: unsupported reloc %u against global symbol %s\n"
 msgstr ""
 
-#: i386.cc:837
+#: i386.cc:923
 #, c-format
 msgid "%s: %s: unsupported RELA reloc section\n"
 msgstr ""
 
-#: i386.cc:877
+#: i386.cc:980
 #, c-format
 msgid "%s: %s: missing expected TLS relocation\n"
 msgstr ""
 
-#: i386.cc:993 i386.cc:1068 i386.cc:1079
+#: i386.cc:1096 i386.cc:1171 i386.cc:1182
 #, c-format
 msgid "%s: %s: unsupported reloc %u\n"
 msgstr ""
 
-#: i386.cc:1020
+#: i386.cc:1123
 #, c-format
 msgid "%s: %s: TLS reloc but no TLS segment\n"
 msgstr ""
 
-#: i386.cc:1053
+#: i386.cc:1156
 #, c-format
 msgid "%s: %s: unsupported reloc type %u\n"
 msgstr ""
 
-#: i386.cc:1262
+#: i386.cc:1365
 #, c-format
 msgid "%s: %s: TLS relocation out of range\n"
 msgstr ""
 
-#: i386.cc:1280
+#: i386.cc:1383
 #, c-format
 msgid "%s: %s: TLS relocation against invalid instruction\n"
 msgstr ""
@@ -496,37 +496,37 @@ msgstr ""
 msgid "%s: -%c: %s\n"
 msgstr ""
 
-#: output.cc:809
+#: output.cc:817
 #, c-format
 msgid "%s: %s: invalid alignment %lu for section \"%s\"\n"
 msgstr ""
 
-#: output.cc:1308
+#: output.cc:1316
 #, c-format
 msgid "%s: %s: open: %s\n"
 msgstr ""
 
-#: output.cc:1317
+#: output.cc:1325
 #, c-format
 msgid "%s: %s: lseek: %s\n"
 msgstr ""
 
-#: output.cc:1324
+#: output.cc:1332
 #, c-format
 msgid "%s: %s: write: %s\n"
 msgstr ""
 
-#: output.cc:1334
+#: output.cc:1342
 #, c-format
 msgid "%s: %s: mmap: %s\n"
 msgstr ""
 
-#: output.cc:1348
+#: output.cc:1356
 #, c-format
 msgid "%s: %s: munmap: %s\n"
 msgstr ""
 
-#: output.cc:1356
+#: output.cc:1364
 #, c-format
 msgid "%s: %s: close: %s\n"
 msgstr ""
@@ -547,22 +547,22 @@ msgstr ""
 msgid "%s: %s: not an object or archive\n"
 msgstr ""
 
-#: reloc.cc:168 reloc.cc:409
+#: reloc.cc:169 reloc.cc:410
 #, c-format
 msgid "%s: %s: relocation section %u has bad info %u\n"
 msgstr ""
 
-#: reloc.cc:187 reloc.cc:426
+#: reloc.cc:188 reloc.cc:427
 #, c-format
 msgid "%s: %s: relocation section %u uses unexpected symbol table %u\n"
 msgstr ""
 
-#: reloc.cc:203 reloc.cc:445
+#: reloc.cc:204 reloc.cc:446
 #, c-format
 msgid "%s: %s: unexpected entsize for reloc section %u: %lu != %u"
 msgstr ""
 
-#: reloc.cc:214 reloc.cc:456
+#: reloc.cc:215 reloc.cc:457
 #, c-format
 msgid "%s: %s: reloc section %u size %lu uneven"
 msgstr ""
index 2b200ba54849764e8143bce102391520253e6f6a..ba3e85e70a4c5ab74390d65e8a2fbe0c472058eb 100644 (file)
@@ -61,7 +61,7 @@ Read_symbols::run(Workqueue* workqueue)
       return;
     }
 
-  Input_file* input_file = new Input_file(this->input_argument_->file());
+  Input_file* input_file = new Input_file(&this->input_argument_->file());
   input_file->open(this->options_, this->dirpath_);
 
   // Read enough of the file to pick up the entire ELF header.
index 35f262e8b8b775da9af34f0b668869c2c782ba0c..915656c374e56f4f28cc3f9554375b31b2cac7a1 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "workqueue.h"
 #include "object.h"
+#include "symtab.h"
 #include "output.h"
 #include "reloc.h"
 
@@ -471,21 +472,64 @@ Sized_relobj<size, big_endian>::relocate_sections(
     }
 }
 
-// Relocate_functions functions.
+// Copy_relocs::Copy_reloc_entry methods.
+
+// Return whether we should emit this reloc.  We should emit it if the
+// symbol is still defined in a dynamic object.  If we should not emit
+// it, we clear it, to save ourselves the test next time.
+
+template<int size, bool big_endian>
+bool
+Copy_relocs<size, big_endian>::Copy_reloc_entry::should_emit()
+{
+  if (this->sym_ == NULL)
+    return false;
+  if (this->sym_->is_defined_in_dynobj())
+    return true;
+  this->sym_ = NULL;
+  return false;
+}
+
+// Emit a reloc into a SHT_REL section.
+
+template<int size, bool big_endian>
+void
+Copy_relocs<size, big_endian>::Copy_reloc_entry::emit(
+    Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian>* reloc_data)
+{
+  reloc_data->add_global(this->sym_, this->reloc_type_, this->relobj_,
+                        this->shndx_, this->address_);
+}
+
+// Emit a reloc into a SHT_RELA section.
+
+template<int size, bool big_endian>
+void
+Copy_relocs<size, big_endian>::Copy_reloc_entry::emit(
+    Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>* reloc_data)
+{
+  reloc_data->add_global(this->sym_, this->reloc_type_, this->relobj_,
+                        this->shndx_, this->address_, this->addend_);
+}
+
+// Copy_relocs methods.
 
 // Return whether we need a COPY reloc for a relocation against GSYM.
 // The relocation is being applied to section SHNDX in OBJECT.
 
 template<int size, bool big_endian>
 bool
-Relocate_functions<size, big_endian>::need_copy_reloc(
+Copy_relocs<size, big_endian>::need_copy_reloc(
     const General_options*,
     Relobj* object,
     unsigned int shndx,
-    Symbol*)
+    Sized_symbol<size>* sym)
 {
   // FIXME: Handle -z nocopyrelocs.
 
+  if (sym->symsize() == 0)
+    return false;
+
   // If this is a readonly section, then we need a COPY reloc.
   // Otherwise we can use a dynamic reloc.
   if ((object->section_flags(shndx) & elfcpp::SHF_WRITE) == 0)
@@ -494,6 +538,71 @@ Relocate_functions<size, big_endian>::need_copy_reloc(
   return false;
 }
 
+// Save a Rel reloc.
+
+template<int size, bool big_endian>
+void
+Copy_relocs<size, big_endian>::save(
+    Symbol* sym,
+    Relobj* relobj,
+    unsigned int shndx,
+    const elfcpp::Rel<size, big_endian>& rel)
+{
+  unsigned int reloc_type = elfcpp::elf_r_type<size>(rel.get_r_info());
+  this->entries_.push_back(Copy_reloc_entry(sym, reloc_type, relobj, shndx,
+                                           rel.get_r_offset(), 0));
+}
+
+// Save a Rela reloc.
+
+template<int size, bool big_endian>
+void
+Copy_relocs<size, big_endian>::save(
+    Symbol* sym,
+    Relobj* relobj,
+    unsigned int shndx,
+    const elfcpp::Rela<size, big_endian>& rela)
+{
+  unsigned int reloc_type = elfcpp::elf_r_type<size>(rela.get_r_info());
+  this->entries_.push_back(Copy_reloc_entry(sym, reloc_type, relobj, shndx,
+                                           rela.get_r_offset(),
+                                           rela.get_r_addend()));
+}
+
+// Return whether there are any relocs to emit.  We don't want to emit
+// a reloc if the symbol is no longer defined in a dynamic object.
+
+template<int size, bool big_endian>
+bool
+Copy_relocs<size, big_endian>::any_to_emit()
+{
+  for (typename Copy_reloc_entries::iterator p = this->entries_.begin();
+       p != this->entries_.end();
+       ++p)
+    {
+      if (p->should_emit())
+       return true;
+    }
+  return false;
+}
+
+// Emit relocs.
+
+template<int size, bool big_endian>
+template<int sh_type>
+void
+Copy_relocs<size, big_endian>::emit(
+    Output_data_reloc<sh_type, true, size, big_endian>* reloc_data)
+{
+  for (typename Copy_reloc_entries::iterator p = this->entries_.begin();
+       p != this->entries_.end();
+       ++p)
+    {
+      if (p->should_emit())
+       p->emit(reloc_data);
+    }
+}
+
 // Instantiate the templates we need.  We could use the configure
 // script to restrict this to only the ones for implemented targets.
 
@@ -570,27 +679,55 @@ Sized_relobj<64, true>::do_relocate(const General_options& options,
                                    Output_file* of);
 
 template
-bool
-Relocate_functions<32, false>::need_copy_reloc(const General_options*,
-                                              Relobj*, unsigned int,
-                                              Symbol*);
+class Copy_relocs<32, false>;
 
 template
-bool
-Relocate_functions<32, true>::need_copy_reloc(const General_options*,
-                                             Relobj*, unsigned int,
-                                             Symbol*);
+class Copy_relocs<32, true>;
 
 template
-bool
-Relocate_functions<64, false>::need_copy_reloc(const General_options*,
-                                              Relobj*, unsigned int,
-                                              Symbol*);
+class Copy_relocs<64, false>;
 
 template
-bool
-Relocate_functions<64, true>::need_copy_reloc(const General_options*,
-                                             Relobj*, unsigned int,
-                                             Symbol*);
+class Copy_relocs<64, true>;
+
+template
+void
+Copy_relocs<32, false>::emit<elfcpp::SHT_REL>(
+    Output_data_reloc<elfcpp::SHT_REL, true, 32, false>*);
+
+template
+void
+Copy_relocs<32, true>::emit<elfcpp::SHT_REL>(
+    Output_data_reloc<elfcpp::SHT_REL, true, 32, true>*);
+
+template
+void
+Copy_relocs<64, false>::emit<elfcpp::SHT_REL>(
+    Output_data_reloc<elfcpp::SHT_REL, true, 64, false>*);
+
+template
+void
+Copy_relocs<64, true>::emit<elfcpp::SHT_REL>(
+    Output_data_reloc<elfcpp::SHT_REL, true, 64, true>*);
+
+template
+void
+Copy_relocs<32, false>::emit<elfcpp::SHT_RELA>(
+    Output_data_reloc<elfcpp::SHT_RELA , true, 32, false>*);
+
+template
+void
+Copy_relocs<32, true>::emit<elfcpp::SHT_RELA>(
+    Output_data_reloc<elfcpp::SHT_RELA, true, 32, true>*);
+
+template
+void
+Copy_relocs<64, false>::emit<elfcpp::SHT_RELA>(
+    Output_data_reloc<elfcpp::SHT_RELA, true, 64, false>*);
+
+template
+void
+Copy_relocs<64, true>::emit<elfcpp::SHT_RELA>(
+    Output_data_reloc<elfcpp::SHT_RELA, true, 64, true>*);
 
 } // End namespace gold.
index 7829440bf49ecb21f2d8529919a67843e45df371..1edaa579ceed403c0adfc4894aa00bcc07ce1420 100644 (file)
@@ -17,6 +17,12 @@ class Stringpool;
 class Symbol;
 class Layout;
 
+template<int size>
+class Sized_symbol;
+
+template<int sh_type, bool dynamic, int size, bool big_endian>
+class Output_data_reloc;
+
 // A class to read the relocations for an object file, and then queue
 // up a task to see if they require any GOT/PLT/COPY relocations in
 // the symbol table.
@@ -229,12 +235,99 @@ public:
   {
     This::template pcrel<64>(view, value, address);
   }
+};
+
+// We try to avoid COPY relocations when possible.  A COPY relocation
+// may be required when an executable refers to a variable defined in
+// a shared library.  COPY relocations are problematic because they
+// tie the executable to the exact size of the variable in the shared
+// library.  We can avoid them if all the references to the variable
+// are in a writeable section.  In that case we can simply use dynamic
+// relocations.  However, when scanning relocs, we don't know when we
+// see the relocation whether we will be forced to use a COPY
+// relocation or not.  So we have to save the relocation during the
+// reloc scanning, and then emit it as a dynamic relocation if
+// necessary.  This class implements that.  It is used by the target
+// specific code.
+
+template<int size, bool big_endian>
+class Copy_relocs
+{
+ public:
+  Copy_relocs()
+    : entries_()
+  { }
 
   // Return whether we need a COPY reloc for a reloc against GSYM,
   // which is being applied to section SHNDX in OBJECT.
   static bool
   need_copy_reloc(const General_options*, Relobj* object, unsigned int shndx,
-                 Symbol* gsym);
+                 Sized_symbol<size>* gsym);
+
+  // Save a Rel against SYM for possible emission later.  SHNDX is the
+  // index of the section to which the reloc is being applied.
+  void
+  save(Symbol* sym, Relobj*, unsigned int shndx,
+       const elfcpp::Rel<size, big_endian>&);
+
+  // Save a Rela against SYM for possible emission later.
+  void
+  save(Symbol* sym, Relobj*, unsigned int shndx,
+       const elfcpp::Rela<size, big_endian>&);
+
+  // Return whether there are any relocs to emit.  This also discards
+  // entries which need not be emitted.
+  bool
+  any_to_emit();
+
+  // Emit relocs for each symbol which did not get a COPY reloc (i.e.,
+  // is still defined in the dynamic object).
+  template<int sh_type>
+  void
+  emit(Output_data_reloc<sh_type, true, size, big_endian>*);
+
+ private:
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Addend;
+
+  // This POD class holds the entries we are saving.
+  class Copy_reloc_entry
+  {
+   public:
+    Copy_reloc_entry(Symbol* sym, unsigned int reloc_type,
+                    Relobj* relobj, unsigned int shndx,
+                    Address address, Addend addend)
+      : sym_(sym), reloc_type_(reloc_type), relobj_(relobj),
+       shndx_(shndx), address_(address), addend_(addend)
+    { }
+
+    // Return whether we should emit this reloc.  If we should not
+    // emit, we clear it.
+    bool
+    should_emit();
+
+    // Emit this reloc.
+
+    void
+    emit(Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian>*);
+
+    void
+    emit(Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>*);
+
+   private:
+    Symbol* sym_;
+    unsigned int reloc_type_;
+    Relobj* relobj_;
+    unsigned int shndx_;
+    Address address_;
+    Addend addend_;
+  };
+
+  // A list of relocs to be saved.
+  typedef std::vector<Copy_reloc_entry> Copy_reloc_entries;
+
+  // The list of relocs we are saving.
+  Copy_reloc_entries entries_;
 };
 
 } // End namespace gold.
index 039b97dc7f40f20c62408f591b577071aac6ecc8..a031c403302197dd8e7f340767ab6026557491c3 100644 (file)
@@ -83,6 +83,12 @@ class Target
   common_pagesize() const
   { return this->pti_->common_pagesize; }
 
+  // This is called to tell the target to complete any sections it is
+  // handling.  After this all sections must have their final size.
+  void
+  finalize_sections(Layout* layout)
+  { return this->do_finalize_sections(layout); }
+
  protected:
   // This struct holds the constant information for a child class.  We
   // use a struct to avoid the overhead of virtual function calls for
@@ -113,6 +119,11 @@ class Target
     : pti_(pti)
   { }
 
+  // Virtual function which may be implemented by the child class.
+  virtual void
+  do_finalize_sections(Layout*)
+  { }
+
  private:
   Target(const Target&);
   Target& operator=(const Target&);
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
new file mode 100644 (file)
index 0000000..122be70
--- /dev/null
@@ -0,0 +1,22 @@
+# Process this file with automake to generate Makefile.in
+
+AUTOMAKE_OPTIONS =
+
+AM_CXXFLAGS = $(WARN_CXXFLAGS) $(LFS_CXXFLAGS)
+
+INCLUDES = -D_GNU_SOURCE \
+       -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../include \
+       -I$(srcdir)/../../elfcpp \
+       -DLOCALEDIR="\"$(datadir)/locale\"" \
+       @INCINTL@
+
+TESTS = object_unittest
+
+check_LIBRARIES = libgoldtest.a
+libgoldtest_a_SOURCES = test.cc testmain.cc testfile.cc
+
+LDADD = libgoldtest.a ../libgold.a
+
+check_PROGRAMS = object_unittest
+
+object_unittest_SOURCES = object_unittest.cc
diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in
new file mode 100644 (file)
index 0000000..4967af6
--- /dev/null
@@ -0,0 +1,521 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Process this file with automake to generate Makefile.in
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+check_PROGRAMS = object_unittest$(EXEEXT)
+subdir = testsuite
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
+       $(top_srcdir)/../config/lead-dot.m4 \
+       $(top_srcdir)/../config/progtest.m4 \
+       $(top_srcdir)/../config/po.m4 $(top_srcdir)/../config/nls.m4 \
+       $(top_srcdir)/../config/gettext-sister.m4 \
+       $(top_srcdir)/../bfd/warning.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+AR = ar
+ARFLAGS = cru
+libgoldtest_a_AR = $(AR) $(ARFLAGS)
+libgoldtest_a_LIBADD =
+am_libgoldtest_a_OBJECTS = test.$(OBJEXT) testmain.$(OBJEXT) \
+       testfile.$(OBJEXT)
+libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS)
+am_object_unittest_OBJECTS = object_unittest.$(OBJEXT)
+object_unittest_OBJECTS = $(am_object_unittest_OBJECTS)
+object_unittest_LDADD = $(LDADD)
+object_unittest_DEPENDENCIES = libgoldtest.a ../libgold.a
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/../depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+       -o $@
+SOURCES = $(libgoldtest_a_SOURCES) $(object_unittest_SOURCES)
+DIST_SOURCES = $(libgoldtest_a_SOURCES) $(object_unittest_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GENCAT = @GENCAT@
+GMSGFMT = @GMSGFMT@
+INCINTL = @INCINTL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+LDFLAGS = @LDFLAGS@
+LFS_CXXFLAGS = @LFS_CXXFLAGS@
+LIBINTL = @LIBINTL@
+LIBINTL_DEP = @LIBINTL_DEP@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGMERGE = @MSGMERGE@
+NO_WERROR = @NO_WERROR@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_CXXFLAGS = @WARN_CXXFLAGS@
+XGETTEXT = @XGETTEXT@
+YACC = @YACC@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+AUTOMAKE_OPTIONS = 
+AM_CXXFLAGS = $(WARN_CXXFLAGS) $(LFS_CXXFLAGS)
+INCLUDES = -D_GNU_SOURCE \
+       -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../include \
+       -I$(srcdir)/../../elfcpp \
+       -DLOCALEDIR="\"$(datadir)/locale\"" \
+       @INCINTL@
+
+TESTS = object_unittest
+check_LIBRARIES = libgoldtest.a
+libgoldtest_a_SOURCES = test.cc testmain.cc testfile.cc
+LDADD = libgoldtest.a ../libgold.a
+object_unittest_SOURCES = object_unittest.cc
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  testsuite/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  testsuite/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-checkLIBRARIES:
+       -test -z "$(check_LIBRARIES)" || rm -f $(check_LIBRARIES)
+libgoldtest.a: $(libgoldtest_a_OBJECTS) $(libgoldtest_a_DEPENDENCIES) 
+       -rm -f libgoldtest.a
+       $(libgoldtest_a_AR) libgoldtest.a $(libgoldtest_a_OBJECTS) $(libgoldtest_a_LIBADD)
+       $(RANLIB) libgoldtest.a
+
+clean-checkPROGRAMS:
+       -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS)
+object_unittest$(EXEEXT): $(object_unittest_OBJECTS) $(object_unittest_DEPENDENCIES) 
+       @rm -f object_unittest$(EXEEXT)
+       $(CXXLINK) $(object_unittest_LDFLAGS) $(object_unittest_OBJECTS) $(object_unittest_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testfile.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testmain.Po@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@  if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@  if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+       @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+       srcdir=$(srcdir); export srcdir; \
+       list='$(TESTS)'; \
+       if test -n "$$list"; then \
+         for tst in $$list; do \
+           if test -f ./$$tst; then dir=./; \
+           elif test -f $$tst; then dir=; \
+           else dir="$(srcdir)/"; fi; \
+           if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+             all=`expr $$all + 1`; \
+             case " $(XFAIL_TESTS) " in \
+             *" $$tst "*) \
+               xpass=`expr $$xpass + 1`; \
+               failed=`expr $$failed + 1`; \
+               echo "XPASS: $$tst"; \
+             ;; \
+             *) \
+               echo "PASS: $$tst"; \
+             ;; \
+             esac; \
+           elif test $$? -ne 77; then \
+             all=`expr $$all + 1`; \
+             case " $(XFAIL_TESTS) " in \
+             *" $$tst "*) \
+               xfail=`expr $$xfail + 1`; \
+               echo "XFAIL: $$tst"; \
+             ;; \
+             *) \
+               failed=`expr $$failed + 1`; \
+               echo "FAIL: $$tst"; \
+             ;; \
+             esac; \
+           else \
+             skip=`expr $$skip + 1`; \
+             echo "SKIP: $$tst"; \
+           fi; \
+         done; \
+         if test "$$failed" -eq 0; then \
+           if test "$$xfail" -eq 0; then \
+             banner="All $$all tests passed"; \
+           else \
+             banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+           fi; \
+         else \
+           if test "$$xpass" -eq 0; then \
+             banner="$$failed of $$all tests failed"; \
+           else \
+             banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+           fi; \
+         fi; \
+         dashes="$$banner"; \
+         skipped=""; \
+         if test "$$skip" -ne 0; then \
+           skipped="($$skip tests were not run)"; \
+           test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+             dashes="$$skipped"; \
+         fi; \
+         report=""; \
+         if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+           report="Please report to $(PACKAGE_BUGREPORT)"; \
+           test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+             dashes="$$report"; \
+         fi; \
+         dashes=`echo "$$dashes" | sed s/./=/g`; \
+         echo "$$dashes"; \
+         echo "$$banner"; \
+         test -z "$$skipped" || echo "$$skipped"; \
+         test -z "$$report" || echo "$$report"; \
+         echo "$$dashes"; \
+         test "$$failed" -eq 0; \
+       else :; fi
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+       list='$(DISTFILES)'; for file in $$list; do \
+         case $$file in \
+           $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+           $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+         esac; \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           dir="/$$dir"; \
+           $(mkdir_p) "$(distdir)$$dir"; \
+         else \
+           dir=''; \
+         fi; \
+         if test -d $$d/$$file; then \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+       $(MAKE) $(AM_MAKEFLAGS) $(check_LIBRARIES) $(check_PROGRAMS)
+       $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkLIBRARIES clean-checkPROGRAMS clean-generic \
+       mostlyclean-am
+
+distclean: distclean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
+       clean-checkLIBRARIES clean-checkPROGRAMS clean-generic ctags \
+       distclean distclean-compile distclean-generic distclean-tags \
+       distdir dvi dvi-am html html-am info info-am install \
+       install-am install-data install-data-am install-exec \
+       install-exec-am install-info install-info-am install-man \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+       tags uninstall uninstall-am uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/gold/testsuite/object_unittest.cc b/gold/testsuite/object_unittest.cc
new file mode 100644 (file)
index 0000000..c15237d
--- /dev/null
@@ -0,0 +1,41 @@
+// object_unittest.cc -- test Object, Relobj, etc.
+
+#include "gold.h"
+
+#include "object.h"
+
+#include "test.h"
+#include "testfile.h"
+
+namespace gold_testsuite
+{
+
+using namespace gold;
+
+// Test basic Object functionality.
+
+bool
+Object_test(Test_report*)
+{
+  Input_file input_file("test.o", test_file_1, test_file_1_size);
+  Object* object = make_elf_object("test.o", &input_file, 0,
+                                  test_file_1, test_file_1_size);
+  CHECK(object->name() == "test.o");
+  CHECK(!object->is_dynamic());
+  CHECK(object->target() == target_test_pointer);
+  CHECK(object->is_locked());
+  object->unlock();
+  CHECK(!object->is_locked());
+  object->lock();
+  CHECK(object->shnum() == 5);
+  CHECK(object->section_name(0).empty());
+  CHECK(object->section_name(1) == ".test");
+  CHECK(object->section_flags(0) == 0);
+  CHECK(object->section_flags(1) == elfcpp::SHF_ALLOC);
+  object->unlock();
+  return true;
+}
+
+Register_test object_register("Object", Object_test);
+
+} // End namespace gold_testsuite.
diff --git a/gold/testsuite/test.cc b/gold/testsuite/test.cc
new file mode 100644 (file)
index 0000000..37a4ada
--- /dev/null
@@ -0,0 +1,78 @@
+// test.cc -- simplistic test framework for gold.
+
+#include "gold.h"
+
+#include <cstdio>
+
+#include "test.h"
+
+namespace gold_testsuite
+{
+
+// Test_framework methods.
+
+// The current test being run.
+
+Test_report* Test_framework::current_report;
+
+// Run a test.
+
+void
+Test_framework::run(const char *name, bool (*pfn)(Test_report*))
+{
+  this->testname_ = name;
+  this->current_fail_ = false;
+
+  Test_report tr(this);
+  Test_framework::current_report = &tr;
+
+  if ((*pfn)(&tr) && !this->current_fail_)
+    {
+      printf("PASS: %s\n", name);
+      ++this->passes_;
+    }
+  else
+    {
+      printf("FAIL: %s\n", name);
+      ++this->failures_;
+    }
+
+  Test_framework::current_report = NULL;
+  this->testname_ = NULL;
+}
+
+// Let a test report an error.
+
+void
+Test_framework::error(const char* message)
+{
+  printf("ERROR: %s: %s\n", this->testname_, message);
+  this->fail();
+}
+
+// Register_test methods.
+
+// Linked list of all registered tests.
+
+Register_test* Register_test::all_tests;
+
+// Register a test.
+
+Register_test::Register_test(const char* name, bool (*pfn)(Test_report*))
+  : name_(name), pfn_(pfn), next_(Register_test::all_tests)
+{
+  Register_test::all_tests = this;
+}
+
+// Run all registered tests.
+
+void
+Register_test::run_tests(Test_framework* tf)
+{
+  for (Register_test* p = Register_test::all_tests;
+       p != NULL;
+       p = p->next_)
+    tf->run(p->name_, p->pfn_);
+}
+
+} // End namespace gold_testsuite.
diff --git a/gold/testsuite/test.h b/gold/testsuite/test.h
new file mode 100644 (file)
index 0000000..e0556e2
--- /dev/null
@@ -0,0 +1,121 @@
+// test.h -- simplistic test framework for gold unittests -*- C++ -*-
+
+#ifndef GOLD_TESTSUITE_TEST_H
+#define GOLD_TESTSUITE_TEST_H
+
+namespace gold_testsuite
+{
+
+class Test_report;
+
+// This class handles basic test framework functionality.
+
+class Test_framework
+{
+ public:
+  Test_framework()
+    : testname_(NULL), current_fail_(0), passes_(0), failures_(0)
+  { }
+
+  // Return number of failures.
+  unsigned int
+  failures() const
+  { return this->failures_; }
+
+  // Run a test.
+  void
+  run(const char* name, bool (*pfn)(Test_report*));
+
+  // Get the current Test_report.  This is used by the test support
+  // macros.
+  static Test_report*
+  report()
+  { return Test_framework::current_report; }
+
+ private:
+  friend class Test_report;
+
+  // Cause the current test to fail.
+  void
+  fail()
+  { ++this->current_fail_ = true; }
+
+  // Report an error from the current test.
+  void
+  error(const char* message);
+
+  // Current Test_report.  This is a static variable valid while a
+  // test is being run.
+  static Test_report* current_report;
+
+  // Current test being run.
+  const char* testname_;
+  // Whether the current test is failing.
+  bool current_fail_;
+  // Total number of passeed tests.
+  unsigned int passes_;
+  // Total number of failed tests.
+  unsigned int failures_;
+};
+
+// An instance of this class is passed to each test function.
+
+class Test_report
+{
+public:
+  Test_report(Test_framework* tf)
+    : tf_(tf)
+  { }
+
+  // Mark the test as failing.
+  void
+  fail()
+  { this->tf_->fail(); }
+
+  // Report an error.
+  void
+  error(const char* message)
+  { this->tf_->error(message); }
+
+private:
+  Test_framework* tf_;
+};
+
+// This class registers a test function so that the testsuite runs it.
+
+class Register_test
+{
+ public: 
+  Register_test(const char* name, bool (*pfn)(Test_report*));
+
+  // Run all registered tests.
+  static void
+  run_tests(Test_framework*);
+
+ private:
+  // Linked list of all tests.
+  static Register_test* all_tests;
+
+  // Test name.
+  const char* name_;
+  // Function to call.  It should return true if the test passes,
+  // false if it fails.
+  bool (*pfn_)(Test_report*);
+  // Next test in linked list.
+  Register_test* next_;
+};
+
+} // End namespace gold_testsuite.
+
+// These macros are for convenient use in tests.
+
+// Check that a condition is true.  If it is false, report a failure.
+
+#define CHECK(cond) \
+  ((cond) ? 0 : (::gold_testsuite::Test_framework::report()->fail(), 0))
+
+// Report an error during a test.
+
+#define ERROR(msg) (::gold_testsuite::Test_framework::report()->error(msg))
+
+#endif // !defined(GOLD_TESTSUITE_TEST_H)
diff --git a/gold/testsuite/testfile.cc b/gold/testsuite/testfile.cc
new file mode 100644 (file)
index 0000000..bfe3c9d
--- /dev/null
@@ -0,0 +1,261 @@
+// testfile.cc -- Dummy ELF objects for testing purposes.
+
+#include "gold.h"
+
+#include "target.h"
+#include "target-select.h"
+
+#include "test.h"
+#include "testfile.h"
+
+namespace gold_testsuite
+{
+
+using namespace gold;
+
+// A Target used for testing purposes.
+
+class Target_test : public Sized_target<32, false>
+{
+ public:
+  Target_test()
+    : Sized_target<32, false>(&test_target_info)
+  { }
+
+  void
+  scan_relocs(const General_options&, Symbol_table*, Layout*,
+             Sized_relobj<32, false>*, unsigned int, unsigned int,
+             const unsigned char*, size_t, size_t, const unsigned char*,
+             Symbol**)
+  { ERROR("call to Target_test::scan_relocs"); }
+
+  void
+  relocate_section(const Relocate_info<32, false>*, unsigned int,
+                  const unsigned char*, size_t, unsigned char*,
+                  elfcpp::Elf_types<32>::Elf_Addr, off_t)
+  { ERROR("call to Target_test::relocate_section"); }
+
+  static const Target::Target_info test_target_info;
+};
+
+const Target::Target_info Target_test::test_target_info =
+{
+  32,                                  // size
+  false,                               // is_big_endian
+  static_cast<elfcpp::EM>(0xffff),     // machine_code
+  false,                               // has_make_symbol
+  false,                               // has_resolve
+  "/dummy",                            // dynamic_linker
+  0x08000000,                          // text_segment_address
+  0x1000,                              // abi_pagesize
+  0x1000                               // common_pagesize
+};
+
+// The single test target.
+
+Target_test target_test;
+
+// A pointer to the test target.  This is used in CHECKs.
+
+Target* target_test_pointer = &target_test;
+
+// Select the test target.
+
+class Target_selector_test : public Target_selector
+{
+ public:
+  Target_selector_test()
+    : Target_selector(0xffff, 32, false)
+  { }
+
+  Target*
+  recognize(int, int, int)
+  { return &target_test; }
+};
+
+// Register the test target selector.
+
+Target_selector_test target_selector_test;
+
+// A simple ELF object with one empty section, named ".test" and one
+// globally visible symbol named "test".
+
+const unsigned char test_file_1[] =
+{
+  // Ehdr
+  // EI_MAG[0-3]
+  0x7f, 'E', 'L', 'F',
+  // EI_CLASS: 32 bit.
+  1,
+  // EI_DATA: little endian
+  1,
+  // EI_VERSION
+  1,
+  // EI_OSABI
+  0,
+  // EI_ABIVERSION
+  0,
+  // EI_PAD
+  0, 0, 0, 0, 0, 0, 0,
+  // e_type: ET_REL
+  1, 0,
+  // e_machine: a magic value used for testing.
+  0xff, 0xff,
+  // e_version
+  1, 0, 0, 0,
+  // e_entry
+  0, 0, 0, 0,
+  // e_phoff
+  0, 0, 0, 0,
+  // e_shoff: starts right after file header
+  52, 0, 0, 0,
+  // e_flags
+  0, 0, 0, 0,
+  // e_ehsize
+  52, 0,
+  // e_phentsize
+  32, 0,
+  // e_phnum
+  0, 0,
+  // e_shentsize
+  40, 0,
+  // e_shnum: dummy, .test, .symtab, .strtab, .shstrtab
+  5, 0,
+  // e_shstrndx
+  4, 0,
+
+  // Offset 52
+  // Shdr 0: dummy entry
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,
+
+  // Offset 92
+  // Shdr 1: .test
+  // sh_name: after initial null
+  1, 0, 0, 0,
+  // sh_type: SHT_PROGBITS
+  1, 0, 0, 0,
+  // sh_flags: SHF_ALLOC
+  2, 0, 0, 0,
+  // sh_addr
+  0, 0, 0, 0,
+  // sh_offset: after file header + 5 section headers
+  252, 0, 0, 0,
+  // sh_size
+  0, 0, 0, 0,
+  // sh_link
+  0, 0, 0, 0,
+  // sh_info
+  0, 0, 0, 0,
+  // sh_addralign
+  1, 0, 0, 0,
+  // sh_entsize
+  0, 0, 0, 0,
+
+  // Offset 132
+  // Shdr 2: .symtab
+  // sh_name: 1 null byte + ".test\0"
+  7, 0, 0, 0,
+  // sh_type: SHT_SYMTAB
+  2, 0, 0, 0,
+  // sh_flags
+  0, 0, 0, 0,
+  // sh_addr
+  0, 0, 0, 0,
+  // sh_offset: after file header + 5 section headers + empty section
+  252, 0, 0, 0,
+  // sh_size: two symbols: dummy symbol + test symbol
+  32, 0, 0, 0,
+  // sh_link: to .strtab
+  3, 0, 0, 0,
+  // sh_info: one local symbol, the dummy symbol
+  1, 0, 0, 0,
+  // sh_addralign
+  4, 0, 0, 0,
+  // sh_entsize: size of symbol
+  16, 0, 0, 0,
+
+  // Offset 172
+  // Shdr 3: .strtab
+  // sh_name: 1 null byte + ".test\0" + ".symtab\0"
+  15, 0, 0, 0,
+  // sh_type: SHT_STRTAB
+  3, 0, 0, 0,
+  // sh_flags
+  0, 0, 0, 0,
+  // sh_addr
+  0, 0, 0, 0,
+  // sh_offset: after .symtab section.  284 == 0x11c
+  0x1c, 0x1, 0, 0,
+  // sh_size: 1 null byte + "test\0"
+  6, 0, 0, 0,
+  // sh_link
+  0, 0, 0, 0,
+  // sh_info
+  0, 0, 0, 0,
+  // sh_addralign
+  1, 0, 0, 0,
+  // sh_entsize
+  0, 0, 0, 0,
+
+  // Offset 212
+  // Shdr 4: .shstrtab
+  // sh_name: 1 null byte + ".test\0" + ".symtab\0" + ".strtab\0"
+  23, 0, 0, 0,
+  // sh_type: SHT_STRTAB
+  3, 0, 0, 0,
+  // sh_flags
+  0, 0, 0, 0,
+  // sh_addr
+  0, 0, 0, 0,
+  // sh_offset: after .strtab section.  290 == 0x122
+  0x22, 0x1, 0, 0,
+  // sh_size: all section names
+  33, 0, 0, 0,
+  // sh_link
+  0, 0, 0, 0,
+  // sh_info
+  0, 0, 0, 0,
+  // sh_addralign
+  1, 0, 0, 0,
+  // sh_entsize
+  0, 0, 0, 0,
+
+  // Offset 252
+  // Contents of .symtab section
+  // Symbol 0
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+  // Offset 268
+  // Symbol 1
+  // st_name
+  1, 0, 0, 0,
+  // st_value
+  0, 0, 0, 0,
+  // st_size
+  0, 0, 0, 0,
+  // st_info: STT_NOTYPE, STB_GLOBAL
+  0x10,
+  // st_other
+  0,
+  // st_shndx: In .test
+  1, 0,
+
+  // Offset 284
+  // Contents of .strtab section
+  '\0',
+  't', 'e', 's', 't', '\0',
+
+  // Offset 290
+  // Contents of .shstrtab section
+  '\0',
+  '.', 't', 'e', 's', 't', '\0',
+  '.', 's', 'y', 'm', 't', 'a', 'b', '\0',
+  '.', 's', 't', 'r', 't', 'a', 'b', '\0',
+  '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', '\0'
+};
+
+const unsigned int test_file_1_size = sizeof test_file_1;
+
+} // End namespace gold_testsuite.
diff --git a/gold/testsuite/testfile.h b/gold/testsuite/testfile.h
new file mode 100644 (file)
index 0000000..c123107
--- /dev/null
@@ -0,0 +1,20 @@
+// testfile.h -- test input files   -*- C++ -*-
+
+#ifndef GOLD_TESTSUITE_TESTFILE_H
+#define GOLD_TESTSUITE_TESTFILE_H
+
+namespace gold
+{
+class Target;
+}
+
+namespace gold_testsuite
+{
+
+extern gold::Target* target_test_pointer;
+extern const unsigned char test_file_1[];
+extern const unsigned int test_file_1_size;
+
+}; // End namespace gold_testsuite.
+
+#endif // !defined(GOLD_TESTSUITE_TESTFILE_H)
diff --git a/gold/testsuite/testmain.cc b/gold/testsuite/testmain.cc
new file mode 100644 (file)
index 0000000..eb46b72
--- /dev/null
@@ -0,0 +1,18 @@
+// testmain.cc -- main function for simplisitic gold test framework.
+
+#include "gold.h"
+
+#include "test.h"
+
+using namespace gold_testsuite;
+
+int
+main(int, char** argv)
+{
+  gold::program_name = argv[0];
+
+  Test_framework tf;
+  Register_test::run_tests(&tf);
+
+  exit(tf.failures());
+}
This page took 0.064356 seconds and 4 git commands to generate.