summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2006-11-30 23:52:50 +0000
committerIan Lance Taylor <iant@google.com>2006-11-30 23:52:50 +0000
commit5a6f7e2db556f93765b75baf2d1ee1509225410d (patch)
tree6db53a1cd843958dc18135430dbf37bd7b92b17e
parent2621033b5dbe773f00cb90d24604b70a1cead2f1 (diff)
downloadbinutils-gdb-5a6f7e2db556f93765b75baf2d1ee1509225410d.tar.gz
Added a testsuite. More support for COPY relocations.
-rw-r--r--gold/Makefile.am24
-rw-r--r--gold/Makefile.in91
-rwxr-xr-xgold/configure87
-rw-r--r--gold/configure.ac3
-rw-r--r--gold/fileread.cc81
-rw-r--r--gold/fileread.h32
-rw-r--r--gold/gold.cc49
-rw-r--r--gold/gold.h3
-rw-r--r--gold/i386.cc119
-rw-r--r--gold/layout.cc4
-rw-r--r--gold/main.cc57
-rw-r--r--gold/object.h56
-rw-r--r--gold/output.cc24
-rw-r--r--gold/output.h177
-rw-r--r--gold/po/gold.pot56
-rw-r--r--gold/readsyms.cc2
-rw-r--r--gold/reloc.cc175
-rw-r--r--gold/reloc.h95
-rw-r--r--gold/target.h11
-rw-r--r--gold/testsuite/Makefile.am22
-rw-r--r--gold/testsuite/Makefile.in521
-rw-r--r--gold/testsuite/object_unittest.cc41
-rw-r--r--gold/testsuite/test.cc78
-rw-r--r--gold/testsuite/test.h121
-rw-r--r--gold/testsuite/testfile.cc261
-rw-r--r--gold/testsuite/testfile.h20
-rw-r--r--gold/testsuite/testmain.cc18
27 files changed, 1988 insertions, 240 deletions
diff --git a/gold/Makefile.am b/gold/Makefile.am
index f76ee5b00c5..02a6da11f63 100644
--- a/gold/Makefile.am
+++ b/gold/Makefile.am
@@ -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
diff --git a/gold/Makefile.in b/gold/Makefile.in
index 560f481932b..36994c3dad9 100644
--- a/gold/Makefile.in
+++ b/gold/Makefile.in
@@ -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:
diff --git a/gold/configure b/gold/configure
index 8be7e913a5d..5d69594d33f 100755
--- a/gold/configure
+++ b/gold/configure
@@ -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
diff --git a/gold/configure.ac b/gold/configure.ac
index 10e0db98b27..5cbaf2c455d 100644
--- a/gold/configure.ac
+++ b/gold/configure.ac
@@ -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)
diff --git a/gold/fileread.cc b/gold/fileread.cc
index e96476c34ff..1a142022569 100644
--- a/gold/fileread.cc
+++ b/gold/fileread.cc
@@ -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);
}
}
diff --git a/gold/fileread.h b/gold/fileread.h
index 6e49324ab86..178e7f355e4 100644
--- a/gold/fileread.h
+++ b/gold/fileread.h
@@ -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_;
};
diff --git a/gold/gold.cc b/gold/gold.cc
index 7c8ed8fc5be..5051a13a6aa 100644
--- a/gold/gold.cc
+++ b/gold/gold.cc
@@ -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);
-}
diff --git a/gold/gold.h b/gold/gold.h
index 78c106f4dd0..e4cd7869422 100644
--- a/gold/gold.h
+++ b/gold/gold.h
@@ -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*,
diff --git a/gold/i386.cc b/gold/i386.cc
index 488da799f80..4cf90e99f9e 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -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
diff --git a/gold/layout.cc b/gold/layout.cc
index 97917b0b758..0de42c2f758 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -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
index 00000000000..ea65c2da27e
--- /dev/null
+++ b/gold/main.cc
@@ -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);
+}
diff --git a/gold/object.h b/gold/object.h
index cd2bc8d8e48..b823599cbcf 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -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;
}
diff --git a/gold/output.cc b/gold/output.cc
index e4720dff0d1..2dbf576fc16 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -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_));
diff --git a/gold/output.h b/gold/output.h
index c7d835d78bf..6e575ba404c 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -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
diff --git a/gold/po/gold.pot b/gold/po/gold.pot
index 5663031576a..4a852a1e720 100644
--- a/gold/po/gold.pot
+++ b/gold/po/gold.pot
@@ -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 ""
diff --git a/gold/readsyms.cc b/gold/readsyms.cc
index 2b200ba5484..ba3e85e70a4 100644
--- a/gold/readsyms.cc
+++ b/gold/readsyms.cc
@@ -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.
diff --git a/gold/reloc.cc b/gold/reloc.cc
index 35f262e8b8b..915656c374e 100644
--- a/gold/reloc.cc
+++ b/gold/reloc.cc
@@ -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.
diff --git a/gold/reloc.h b/gold/reloc.h
index 7829440bf49..1edaa579cee 100644
--- a/gold/reloc.h
+++ b/gold/reloc.h
@@ -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.
diff --git a/gold/target.h b/gold/target.h
index 039b97dc7f4..a031c403302 100644
--- a/gold/target.h
+++ b/gold/target.h
@@ -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
index 00000000000..122be70592b
--- /dev/null
+++ b/gold/testsuite/Makefile.am
@@ -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
index 00000000000..4967af6c862
--- /dev/null
+++ b/gold/testsuite/Makefile.in
@@ -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
index 00000000000..c15237d822b
--- /dev/null
+++ b/gold/testsuite/object_unittest.cc
@@ -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
index 00000000000..37a4ada9ab0
--- /dev/null
+++ b/gold/testsuite/test.cc
@@ -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
index 00000000000..e0556e26731
--- /dev/null
+++ b/gold/testsuite/test.h
@@ -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
index 00000000000..bfe3c9d7a18
--- /dev/null
+++ b/gold/testsuite/testfile.cc
@@ -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
index 00000000000..c123107e496
--- /dev/null
+++ b/gold/testsuite/testfile.h
@@ -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
index 00000000000..eb46b72d84f
--- /dev/null
+++ b/gold/testsuite/testmain.cc
@@ -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());
+}