summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--binutils-2.19/Makefile.def1
-rw-r--r--binutils-2.19/Makefile.in1
-rw-r--r--binutils-2.19/README.android51
-rwxr-xr-xbinutils-2.19/configure76
-rw-r--r--binutils-2.19/configure.ac78
-rw-r--r--binutils-2.19/gold/Makefile.am17
-rw-r--r--binutils-2.19/gold/Makefile.in19
-rw-r--r--binutils-2.19/gold/arm.cc491
-rw-r--r--binutils-2.19/gold/configure31
-rw-r--r--binutils-2.19/gold/configure.ac27
-rw-r--r--binutils-2.19/gold/gold.cc10
-rw-r--r--binutils-2.19/gold/merge.cc28
-rw-r--r--binutils-2.19/gold/merge.h84
-rw-r--r--binutils-2.19/gold/object.cc16
-rw-r--r--binutils-2.19/gold/output.cc251
-rw-r--r--binutils-2.19/gold/output.h789
-rw-r--r--binutils-2.19/gold/script-sections.cc55
-rw-r--r--binutils-2.19/gold/target-reloc.h15
-rw-r--r--binutils-2.19/gold/target.h30
-rw-r--r--binutils-2.19/ld/Makefile.am37
-rw-r--r--binutils-2.19/ld/Makefile.in112
-rwxr-xr-xbinutils-2.19/ld/configure58
-rw-r--r--binutils-2.19/ld/configure.in23
23 files changed, 1635 insertions, 665 deletions
diff --git a/binutils-2.19/Makefile.def b/binutils-2.19/Makefile.def
index 832fc423..382ce099 100644
--- a/binutils-2.19/Makefile.def
+++ b/binutils-2.19/Makefile.def
@@ -378,6 +378,7 @@ dependencies = { module=all-ld; on=all-build-bison; };
dependencies = { module=all-ld; on=all-build-byacc; };
dependencies = { module=all-ld; on=all-build-flex; };
dependencies = { module=all-ld; on=all-intl; };
+dependencies = { module=install-ld; on=install-gold; };
dependencies = { module=configure-gold; on=configure-intl; };
dependencies = { module=all-gold; on=all-libiberty; };
dependencies = { module=all-gold; on=all-intl; };
diff --git a/binutils-2.19/Makefile.in b/binutils-2.19/Makefile.in
index 0305d28c..013809d5 100644
--- a/binutils-2.19/Makefile.in
+++ b/binutils-2.19/Makefile.in
@@ -53314,6 +53314,7 @@ all-stageb3g2-ld: maybe-all-stageb3g2-intl
all-stage4-ld: maybe-all-stage4-intl
all-stageprofile-ld: maybe-all-stageprofile-intl
all-stagefeedback-ld: maybe-all-stagefeedback-intl
+install-ld: maybe-install-gold
configure-gold: maybe-configure-intl
configure-stage1-gold: maybe-configure-stage1-intl
diff --git a/binutils-2.19/README.android b/binutils-2.19/README.android
index 64473577..1231282c 100644
--- a/binutils-2.19/README.android
+++ b/binutils-2.19/README.android
@@ -1,3 +1,54 @@
+2010-06-02 Doug Kwan <dougkwan@google.com>
+
+ Backport upstream patches to support dual-linker configuration.
+
+ gcc change for rev 158786.
+ http://sourceware.org/ml/binutils-cvs/2010-04/msg00138.html
+ http://sourceware.org/ml/binutils-cvs/2010-04/msg00142.html
+
+2010-05-27 Doug Kwan <dougkwan@google.com>
+
+ Backport upstream patches to make gold build ARM Linux kernel
+ correctly.
+
+ http://sourceware.org/ml/binutils-cvs/2010-05/msg00068.html
+ http://sourceware.org/ml/binutils-cvs/2010-05/msg00082.html
+ http://sourceware.org/ml/binutils-cvs/2010-05/msg00104.html
+ http://sourceware.org/ml/binutils-cvs/2010-05/msg00113.html
+
+ Changed files:
+
+ arm.cc
+ merge.cc
+ merge.h
+ object.cc
+ output.cc
+ output.h
+ script-sections.cc
+ target-reloc.h
+ target.h
+
+2010-04-15 Doug Kwan <dougkwan@google.com>
+
+ Backport upstream patch to fix linker crash.
+
+ http://sourceware.org/ml/binutils-cvs/2010-04/msg00078.html
+
+ Changed files:
+
+ gold/arm.cc
+ gold/gold.cc
+
+2010-04-13 Doug Kwan <dougkwan@google.com>
+
+ Backport upstream patch to fix crash during ARM kernel build.
+
+ http://sourceware.org/ml/binutils-cvs/2010-04/msg00067.html
+
+ Changed files:
+
+ gold/arm.cc
+
2010-04-09 Doug Kwan <dougkwan@google.com>
Backport upstream patch to add support for NOLOAD section type in
diff --git a/binutils-2.19/configure b/binutils-2.19/configure
index 2c7815fb..49e76945 100755
--- a/binutils-2.19/configure
+++ b/binutils-2.19/configure
@@ -932,7 +932,7 @@ if test -n "$ac_init_help"; then
Optional Features:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --enable-gold use gold instead of ld
+ --enable-gold[=ARG] build gold [ARG={both}[/{gold,ld}]]
--enable-libada build libada directory
--enable-libssp build libssp directory
--enable-stage1-languages[=all] choose additional languages to build during
@@ -1880,8 +1880,8 @@ host_libs="intl mmalloc libiberty opcodes bfd readline tcl tk itcl libgui zlib l
# know that we are building the simulator.
# binutils, gas and ld appear in that order because it makes sense to run
# "make check" in that particular order.
-# If --enable-gold is used, "gold" will replace "ld".
-host_tools="texinfo byacc flex bison binutils gas ld fixincludes gcc sid sim gdb make patch prms send-pr gprof etc expect dejagnu ash bash bzip2 m4 autoconf automake libtool diff rcs fileutils shellutils time textutils wdiff find uudecode hello tar gzip indent recode release sed utils guile perl gawk findutils gettext zip fastjar gnattools"
+# If --enable-gold is used, "gold" may replace "ld".
+host_tools="byacc flex bison binutils gas ld fixincludes gcc sid sim gdb make patch prms send-pr gprof etc expect dejagnu ash bash bzip2 m4 autoconf automake libtool diff rcs fileutils shellutils time textutils wdiff find uudecode hello tar gzip indent recode release sed utils guile perl gawk findutils gettext zip fastjar gnattools"
# libgcj represents the runtime libraries only used by gcj.
libgcj="target-libffi \
@@ -2036,39 +2036,61 @@ case ${with_newlib} in
esac
# Handle --enable-gold.
+# --enable-gold Build only gold
+# --disable-gold [default] Build only ld
+# --enable-gold=both Build both gold and ld, ld is default
+# --enable-gold=both/ld Same
+# --enable-gold=both/gold Build both gold and ld, gold is default, ld is renamed ld.bfd
-# Check whether --enable-gold or --disable-gold was given.
+ # Check whether --enable-gold or --disable-gold was given.
if test "${enable_gold+set}" = set; then
enableval="$enable_gold"
ENABLE_GOLD=$enableval
else
ENABLE_GOLD=no
fi;
-if test "${ENABLE_GOLD}" = "yes"; then
- # Check for ELF target.
- is_elf=no
- case "${target}" in
- *-*-elf* | *-*-sysv4* | *-*-unixware* | *-*-eabi* | hppa*64*-*-hpux* \
- | *-*-linux* | frv-*-uclinux* | *-*-irix5* | *-*-irix6* \
- | *-*-netbsd* | *-*-openbsd* | *-*-freebsd* | *-*-solaris2*)
- case "${target}" in
- *-*-linux*aout* | *-*-linux*oldld*)
- ;;
- *)
- is_elf=yes
- ;;
- esac
- esac
-
- if test "$is_elf" = "yes"; then
- # Check for target supported by gold.
+ case "${ENABLE_GOLD}" in
+ yes|both|both/gold|both/ld)
+ # Check for ELF target.
+ is_elf=no
case "${target}" in
- i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-*)
- configdirs="`echo " ${configdirs} " | sed -e 's/ ld / gold /'`"
- ;;
+ *-*-elf* | *-*-sysv4* | *-*-unixware* | *-*-eabi* | hppa*64*-*-hpux* \
+ | *-*-linux* | frv-*-uclinux* | *-*-irix5* | *-*-irix6* \
+ | *-*-netbsd* | *-*-openbsd* | *-*-freebsd* | *-*-solaris2* | *-*-nto*)
+ case "${target}" in
+ *-*-linux*aout* | *-*-linux*oldld*)
+ ;;
+ *)
+ is_elf=yes
+ ;;
+ esac
+ esac
+
+ if test "$is_elf" = "yes"; then
+ # Check for target supported by gold.
+ case "${target}" in
+ i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-*)
+ case "${ENABLE_GOLD}" in
+ both*)
+ configdirs="$configdirs gold"
+ ;;
+ *)
+ configdirs="`echo " ${configdirs} " | sed -e 's/ ld / gold /'`"
+ ;;
+ esac
+ ENABLE_GOLD=yes
+ ;;
+ esac
+ fi
+ ;;
+ no)
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: invalid --enable-gold argument" >&5
+echo "$as_me: error: invalid --enable-gold argument" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
esac
- fi
-fi
# Configure extra directories which are host specific
diff --git a/binutils-2.19/configure.ac b/binutils-2.19/configure.ac
index c31e2558..a5b844aa 100644
--- a/binutils-2.19/configure.ac
+++ b/binutils-2.19/configure.ac
@@ -165,7 +165,7 @@ host_libs="intl mmalloc libiberty opcodes bfd readline tcl tk itcl libgui zlib l
# know that we are building the simulator.
# binutils, gas and ld appear in that order because it makes sense to run
# "make check" in that particular order.
-# If --enable-gold is used, "gold" will replace "ld".
+# If --enable-gold is used, "gold" may replace "ld".
host_tools="byacc flex bison binutils gas ld fixincludes gcc sid sim gdb make patch prms send-pr gprof etc expect dejagnu ash bash bzip2 m4 autoconf automake libtool diff rcs fileutils shellutils time textutils wdiff find uudecode hello tar gzip indent recode release sed utils guile perl gawk findutils gettext zip fastjar gnattools"
# libgcj represents the runtime libraries only used by gcj.
@@ -294,37 +294,57 @@ case ${with_newlib} in
esac
# Handle --enable-gold.
-
-AC_ARG_ENABLE(gold,
-[ --enable-gold use gold instead of ld],
-ENABLE_GOLD=$enableval,
-ENABLE_GOLD=no)
-if test "${ENABLE_GOLD}" = "yes"; then
- # Check for ELF target.
- is_elf=no
- case "${target}" in
- *-*-elf* | *-*-sysv4* | *-*-unixware* | *-*-eabi* | hppa*64*-*-hpux* \
- | *-*-linux* | frv-*-uclinux* | *-*-irix5* | *-*-irix6* \
- | *-*-netbsd* | *-*-openbsd* | *-*-freebsd* | *-*-solaris2*)
- case "${target}" in
- *-*-linux*aout* | *-*-linux*oldld*)
- ;;
- *)
- is_elf=yes
- ;;
- esac
- esac
-
- if test "$is_elf" = "yes"; then
- # Check for target supported by gold.
+# --enable-gold Build only gold
+# --disable-gold [default] Build only ld
+# --enable-gold=both Build both gold and ld, ld is default
+# --enable-gold=both/ld Same
+# --enable-gold=both/gold Build both gold and ld, gold is default, ld is renamed ld.bfd
+
+ AC_ARG_ENABLE(gold,
+[[ --enable-gold[=ARG] build gold [ARG={both}[/{gold,ld}]]]],
+ ENABLE_GOLD=$enableval,
+ ENABLE_GOLD=no)
+ case "${ENABLE_GOLD}" in
+ yes|both|both/gold|both/ld)
+ # Check for ELF target.
+ is_elf=no
case "${target}" in
- i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-*)
- configdirs="`echo " ${configdirs} " | sed -e 's/ ld / gold /'`"
- ;;
+ *-*-elf* | *-*-sysv4* | *-*-unixware* | *-*-eabi* | hppa*64*-*-hpux* \
+ | *-*-linux* | frv-*-uclinux* | *-*-irix5* | *-*-irix6* \
+ | *-*-netbsd* | *-*-openbsd* | *-*-freebsd* | *-*-solaris2* | *-*-nto*)
+ case "${target}" in
+ *-*-linux*aout* | *-*-linux*oldld*)
+ ;;
+ *)
+ is_elf=yes
+ ;;
+ esac
esac
- fi
-fi
+ if test "$is_elf" = "yes"; then
+ # Check for target supported by gold.
+ case "${target}" in
+ i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-*)
+ case "${ENABLE_GOLD}" in
+ both*)
+ configdirs="$configdirs gold"
+ ;;
+ *)
+ configdirs="`echo " ${configdirs} " | sed -e 's/ ld / gold /'`"
+ ;;
+ esac
+ ENABLE_GOLD=yes
+ ;;
+ esac
+ fi
+ ;;
+ no)
+ ;;
+ *)
+ AC_MSG_ERROR([invalid --enable-gold argument])
+ ;;
+ esac
+
# Configure extra directories which are host specific
case "${host}" in
diff --git a/binutils-2.19/gold/Makefile.am b/binutils-2.19/gold/Makefile.am
index e0665e04..df5e66c6 100644
--- a/binutils-2.19/gold/Makefile.am
+++ b/binutils-2.19/gold/Makefile.am
@@ -178,12 +178,23 @@ check: libgold.a
install-exec-local: ld-new$(EXEEXT)
$(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(tooldir)/bin
- n=`echo ld | sed '$(transform)'`; \
+ n=`echo $(installed_linker) | sed '$(transform)'`; \
$(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(bindir)/$${n}$(EXEEXT); \
if test "$(bindir)" != "$(tooldir)/bin"; then \
- rm -f $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
- ln $(DESTDIR)$(bindir)/$${n}$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT) >/dev/null 2>/dev/null \
+ rm -f $(DESTDIR)$(tooldir)/bin/$(installed_linker)$(EXEEXT); \
+ ln $(DESTDIR)$(bindir)/$${n}$(EXEEXT) $(DESTDIR)$(tooldir)/bin/$(installed_linker)$(EXEEXT) >/dev/null 2>/dev/null \
+ || $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(tooldir)/bin/$(installed_linker)$(EXEEXT); \
+ fi; \
+ if test "x$(install_as_default)" = "xyes"; then \
+ ld=`echo ld | sed '$(transform)'`; \
+ rm -f $(DESTDIR)$(bindir)/$${ld}$(EXEEXT); \
+ ln $(DESTDIR)$(bindir)/$${n}$(EXEEXT) $(DESTDIR)$(bindir)/$${ld}$(EXEEXT) >/dev/null 2>/dev/null \
+ || $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(bindir)/$${ld}$(EXEEXT); \
+ if test "$(bindir)" != "$(tooldir)/bin"; then \
+ rm -f $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
+ ln $(DESTDIR)$(bindir)/$${n}$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT) >/dev/null 2>/dev/null \
|| $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
+ fi; \
fi
# We want install to imply install-info as per GNU standards, despite
diff --git a/binutils-2.19/gold/Makefile.in b/binutils-2.19/gold/Makefile.in
index 29e1d1a9..e9b28bc5 100644
--- a/binutils-2.19/gold/Makefile.in
+++ b/binutils-2.19/gold/Makefile.in
@@ -305,7 +305,9 @@ host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
+install_as_default = @install_as_default@
install_sh = @install_sh@
+installed_linker = @installed_linker@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
@@ -1226,12 +1228,23 @@ check: libgold.a
install-exec-local: ld-new$(EXEEXT)
$(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(tooldir)/bin
- n=`echo ld | sed '$(transform)'`; \
+ n=`echo $(installed_linker) | sed '$(transform)'`; \
$(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(bindir)/$${n}$(EXEEXT); \
if test "$(bindir)" != "$(tooldir)/bin"; then \
- rm -f $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
- ln $(DESTDIR)$(bindir)/$${n}$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT) >/dev/null 2>/dev/null \
+ rm -f $(DESTDIR)$(tooldir)/bin/$(installed_linker)$(EXEEXT); \
+ ln $(DESTDIR)$(bindir)/$${n}$(EXEEXT) $(DESTDIR)$(tooldir)/bin/$(installed_linker)$(EXEEXT) >/dev/null 2>/dev/null \
+ || $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(tooldir)/bin/$(installed_linker)$(EXEEXT); \
+ fi; \
+ if test "x$(install_as_default)" = "xyes"; then \
+ ld=`echo ld | sed '$(transform)'`; \
+ rm -f $(DESTDIR)$(bindir)/$${ld}$(EXEEXT); \
+ ln $(DESTDIR)$(bindir)/$${n}$(EXEEXT) $(DESTDIR)$(bindir)/$${ld}$(EXEEXT) >/dev/null 2>/dev/null \
+ || $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(bindir)/$${ld}$(EXEEXT); \
+ if test "$(bindir)" != "$(tooldir)/bin"; then \
+ rm -f $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
+ ln $(DESTDIR)$(bindir)/$${n}$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT) >/dev/null 2>/dev/null \
|| $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
+ fi; \
fi
# We want install to imply install-info as per GNU standards, despite
diff --git a/binutils-2.19/gold/arm.cc b/binutils-2.19/gold/arm.cc
index 8943fea8..76f28bec 100644
--- a/binutils-2.19/gold/arm.cc
+++ b/binutils-2.19/gold/arm.cc
@@ -1164,6 +1164,11 @@ class Arm_input_section : public Output_relaxed_input_section
as_arm_input_section(Output_relaxed_input_section* poris)
{ return static_cast<Arm_input_section<big_endian>*>(poris); }
+ // Return the original size of the section.
+ uint32_t
+ original_size() const
+ { return this->original_size_; }
+
protected:
// Write data to output file.
void
@@ -1175,7 +1180,7 @@ class Arm_input_section : public Output_relaxed_input_section
{
if (this->is_stub_table_owner())
return std::max(this->stub_table_->addralign(),
- this->original_addralign_);
+ static_cast<uint64_t>(this->original_addralign_));
else
return this->original_addralign_;
}
@@ -1197,8 +1202,8 @@ class Arm_input_section : public Output_relaxed_input_section
if ((object == this->relobj())
&& (shndx == this->shndx())
&& (offset >= 0)
- && (convert_types<uint64_t, section_offset_type>(offset)
- <= this->original_size_))
+ && (offset <=
+ convert_types<section_offset_type, uint32_t>(this->original_size_)))
{
*poutput = offset;
return true;
@@ -1213,9 +1218,9 @@ class Arm_input_section : public Output_relaxed_input_section
Arm_input_section& operator=(const Arm_input_section&);
// Address alignment of the original input section.
- uint64_t original_addralign_;
+ uint32_t original_addralign_;
// Section size of the original input section.
- uint64_t original_size_;
+ uint32_t original_size_;
// Stub table.
Stub_table<big_endian>* stub_table_;
};
@@ -1946,6 +1951,79 @@ class Arm_output_data_got : public Output_data_got<32, big_endian>
std::vector<Static_reloc> static_relocs_;
};
+// The ARM target has many relocation types with odd-sizes or incontigious
+// bits. The default handling of relocatable relocation cannot process these
+// relocations. So we have to extend the default code.
+
+template<bool big_endian, int sh_type, typename Classify_reloc>
+class Arm_scan_relocatable_relocs :
+ public Default_scan_relocatable_relocs<sh_type, Classify_reloc>
+{
+ public:
+ // Return the strategy to use for a local symbol which is a section
+ // symbol, given the relocation type.
+ inline Relocatable_relocs::Reloc_strategy
+ local_section_strategy(unsigned int r_type, Relobj*)
+ {
+ if (sh_type == elfcpp::SHT_RELA)
+ return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA;
+ else
+ {
+ if (r_type == elfcpp::R_ARM_TARGET1
+ || r_type == elfcpp::R_ARM_TARGET2)
+ {
+ const Target_arm<big_endian>* arm_target =
+ Target_arm<big_endian>::default_target();
+ r_type = arm_target->get_real_reloc_type(r_type);
+ }
+
+ switch(r_type)
+ {
+ // Relocations that write nothing. These exclude R_ARM_TARGET1
+ // and R_ARM_TARGET2.
+ case elfcpp::R_ARM_NONE:
+ case elfcpp::R_ARM_V4BX:
+ case elfcpp::R_ARM_TLS_GOTDESC:
+ case elfcpp::R_ARM_TLS_CALL:
+ case elfcpp::R_ARM_TLS_DESCSEQ:
+ case elfcpp::R_ARM_THM_TLS_CALL:
+ case elfcpp::R_ARM_GOTRELAX:
+ case elfcpp::R_ARM_GNU_VTENTRY:
+ case elfcpp::R_ARM_GNU_VTINHERIT:
+ case elfcpp::R_ARM_THM_TLS_DESCSEQ16:
+ case elfcpp::R_ARM_THM_TLS_DESCSEQ32:
+ return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0;
+ // These should have been converted to something else above.
+ case elfcpp::R_ARM_TARGET1:
+ case elfcpp::R_ARM_TARGET2:
+ gold_unreachable();
+ // Relocations that write full 32 bits.
+ case elfcpp::R_ARM_ABS32:
+ case elfcpp::R_ARM_REL32:
+ case elfcpp::R_ARM_SBREL32:
+ case elfcpp::R_ARM_GOTOFF32:
+ case elfcpp::R_ARM_BASE_PREL:
+ case elfcpp::R_ARM_GOT_BREL:
+ case elfcpp::R_ARM_BASE_ABS:
+ case elfcpp::R_ARM_ABS32_NOI:
+ case elfcpp::R_ARM_REL32_NOI:
+ case elfcpp::R_ARM_PLT32_ABS:
+ case elfcpp::R_ARM_GOT_ABS:
+ case elfcpp::R_ARM_GOT_PREL:
+ case elfcpp::R_ARM_TLS_GD32:
+ case elfcpp::R_ARM_TLS_LDM32:
+ case elfcpp::R_ARM_TLS_LDO32:
+ case elfcpp::R_ARM_TLS_IE32:
+ case elfcpp::R_ARM_TLS_LE32:
+ return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_4;
+ default:
+ // For all other static relocations, return RELOC_SPECIAL.
+ return Relocatable_relocs::RELOC_SPECIAL;
+ }
+ }
+ }
+};
+
// Utilities for manipulating integers of up to 32-bits
namespace utils
@@ -2175,6 +2253,21 @@ class Target_arm : public Sized_target<32, big_endian>
unsigned char* reloc_view,
section_size_type reloc_view_size);
+ // Perform target-specific processing in a relocatable link. This is
+ // only used if we use the relocation strategy RELOC_SPECIAL.
+ void
+ relocate_special_relocatable(const Relocate_info<32, big_endian>* relinfo,
+ unsigned int sh_type,
+ const unsigned char* preloc_in,
+ size_t relnum,
+ Output_section* output_section,
+ off_t offset_in_output_section,
+ unsigned char* view,
+ typename elfcpp::Elf_types<32>::Elf_Addr
+ view_address,
+ section_size_type view_size,
+ unsigned char* preloc_out);
+
// Return whether SYM is defined by the ABI.
bool
do_is_defined_by_abi(Symbol* sym) const
@@ -3706,6 +3799,7 @@ Arm_relocate_functions<big_endian>::arm_branch_common(
Target_arm<big_endian>::default_target();
if (is_weakly_undefined_without_plt)
{
+ gold_assert(!parameters->options().relocatable());
Valtype cond = val & 0xf0000000U;
if (arm_target->may_use_arm_nop())
val = cond | 0x0320f000;
@@ -3723,8 +3817,11 @@ Arm_relocate_functions<big_endian>::arm_branch_common(
// to switch mode.
bool may_use_blx = arm_target->may_use_blx();
Reloc_stub* stub = NULL;
- if (utils::has_overflow<26>(branch_offset)
- || ((thumb_bit != 0) && !(may_use_blx && r_type == elfcpp::R_ARM_CALL)))
+
+ if (!parameters->options().relocatable()
+ && (utils::has_overflow<26>(branch_offset)
+ || ((thumb_bit != 0)
+ && !(may_use_blx && r_type == elfcpp::R_ARM_CALL))))
{
Valtype unadjusted_branch_target = psymval->value(object, 0);
@@ -3831,6 +3928,7 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
Target_arm<big_endian>::default_target();
if (is_weakly_undefined_without_plt)
{
+ gold_assert(!parameters->options().relocatable());
if (arm_target->may_use_thumb2_nop())
{
elfcpp::Swap<16, big_endian>::writeval(wv, 0xf3af);
@@ -3857,11 +3955,12 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
// We need a stub if the branch offset is too large or if we need
// to switch mode.
bool thumb2 = arm_target->using_thumb2();
- if ((!thumb2 && utils::has_overflow<23>(branch_offset))
- || (thumb2 && utils::has_overflow<25>(branch_offset))
- || ((thumb_bit == 0)
- && (((r_type == elfcpp::R_ARM_THM_CALL) && !may_use_blx)
- || r_type == elfcpp::R_ARM_THM_JUMP24)))
+ if (!parameters->options().relocatable()
+ && ((!thumb2 && utils::has_overflow<23>(branch_offset))
+ || (thumb2 && utils::has_overflow<25>(branch_offset))
+ || ((thumb_bit == 0)
+ && (((r_type == elfcpp::R_ARM_THM_CALL) && !may_use_blx)
+ || r_type == elfcpp::R_ARM_THM_JUMP24))))
{
Arm_address unadjusted_branch_target = psymval->value(object, 0);
@@ -4895,8 +4994,10 @@ Arm_input_section<big_endian>::init()
// Cache these to speed up size and alignment queries. It is too slow
// to call section_addraglin and section_size every time.
- this->original_addralign_ = relobj->section_addralign(shndx);
- this->original_size_ = relobj->section_size(shndx);
+ this->original_addralign_ =
+ convert_types<uint32_t, uint64_t>(relobj->section_addralign(shndx));
+ this->original_size_ =
+ convert_types<uint32_t, uint64_t>(relobj->section_size(shndx));
// We want to make this look like the original input section after
// output sections are finalized.
@@ -4931,21 +5032,15 @@ template<bool big_endian>
void
Arm_input_section<big_endian>::set_final_data_size()
{
- // If this owns a stub table, finalize its data size as well.
+ off_t off = convert_types<off_t, uint64_t>(this->original_size_);
+
if (this->is_stub_table_owner())
{
- uint64_t address = this->address();
-
- // The stub table comes after the original section contents.
- address += this->original_size_;
- address = align_address(address, this->stub_table_->addralign());
- off_t offset = this->offset() + (address - this->address());
- this->stub_table_->set_address_and_file_offset(address, offset);
- address += this->stub_table_->data_size();
- gold_assert(address == this->address() + this->current_data_size());
+ this->stub_table_->finalize_data_size();
+ off = align_address(off, this->stub_table_->addralign());
+ off += this->stub_table_->data_size();
}
-
- this->set_data_size(this->current_data_size());
+ this->set_data_size(off);
}
// Reset address and file offset.
@@ -5564,8 +5659,8 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
// Remove all input sections.
uint64_t address = this->address();
- typedef std::list<Simple_input_section> Simple_input_section_list;
- Simple_input_section_list input_sections;
+ typedef std::list<Output_section::Input_section> Input_section_list;
+ Input_section_list input_sections;
this->reset_address_and_file_offset();
this->get_input_sections(address, std::string(""), &input_sections);
@@ -5574,20 +5669,23 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
// Go through all the known input sections and record them.
typedef Unordered_set<Section_id, Section_id_hash> Section_id_set;
- Section_id_set known_input_sections;
- for (Simple_input_section_list::const_iterator p = input_sections.begin();
+ typedef Unordered_map<Section_id, const Output_section::Input_section*,
+ Section_id_hash> Text_to_exidx_map;
+ Text_to_exidx_map text_to_exidx_map;
+ for (Input_section_list::const_iterator p = input_sections.begin();
p != input_sections.end();
++p)
{
// This should never happen. At this point, we should only see
// plain EXIDX input sections.
gold_assert(!p->is_relaxed_input_section());
- known_input_sections.insert(Section_id(p->relobj(), p->shndx()));
+ text_to_exidx_map[Section_id(p->relobj(), p->shndx())] = &(*p);
}
Arm_exidx_fixup exidx_fixup(this);
// Go over the sorted text sections.
+ typedef Unordered_set<Section_id, Section_id_hash> Section_id_set;
Section_id_set processed_input_sections;
for (Text_section_list::const_iterator p = sorted_text_sections.begin();
p != sorted_text_sections.end();
@@ -5612,7 +5710,8 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
Relobj* exidx_relobj = exidx_input_section->relobj();
unsigned int exidx_shndx = exidx_input_section->shndx();
Section_id sid(exidx_relobj, exidx_shndx);
- if (known_input_sections.find(sid) == known_input_sections.end())
+ Text_to_exidx_map::const_iterator iter = text_to_exidx_map.find(sid);
+ if (iter == text_to_exidx_map.end())
{
// This is odd. We have not seen this EXIDX input section before.
// We cannot do fix-up. If we saw a SECTIONS clause in a script,
@@ -5667,9 +5766,9 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
{
// Just add back the EXIDX input section.
gold_assert(section_offset_map == NULL);
- Output_section::Simple_input_section sis(exidx_relobj, exidx_shndx);
- this->add_simple_input_section(sis, exidx_input_section->size(),
- exidx_input_section->addralign());
+ const Output_section::Input_section* pis = iter->second;
+ gold_assert(pis->is_input_section());
+ this->add_script_input_section(*pis);
}
processed_input_sections.insert(Section_id(exidx_relobj, exidx_shndx));
@@ -5679,7 +5778,7 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
exidx_fixup.add_exidx_cantunwind_as_needed();
// Remove any known EXIDX input sections that are not processed.
- for (Simple_input_section_list::const_iterator p = input_sections.begin();
+ for (Input_section_list::const_iterator p = input_sections.begin();
p != input_sections.end();
++p)
{
@@ -5696,8 +5795,10 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
unsigned int text_shndx = exidx_input_section->link();
gold_assert(symtab->is_section_folded(p->relobj(), text_shndx));
- // Remove this from link.
+ // Remove this from link. We also need to recount the
+ // local symbols.
p->relobj()->set_output_section(p->shndx(), NULL);
+ arm_relobj->set_output_local_symbol_count_needs_update();
}
}
@@ -8895,7 +8996,7 @@ Target_arm<big_endian>::scan_relocatable_relocs(
{
gold_assert(sh_type == elfcpp::SHT_REL);
- typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_REL,
+ typedef Arm_scan_relocatable_relocs<big_endian, elfcpp::SHT_REL,
Relocatable_size_for_reloc> Scan_relocatable_relocs;
gold::scan_relocatable_relocs<32, big_endian, elfcpp::SHT_REL,
@@ -8947,6 +9048,291 @@ Target_arm<big_endian>::relocate_for_relocatable(
reloc_view_size);
}
+// Perform target-specific processing in a relocatable link. This is
+// only used if we use the relocation strategy RELOC_SPECIAL.
+
+template<bool big_endian>
+void
+Target_arm<big_endian>::relocate_special_relocatable(
+ const Relocate_info<32, big_endian>* relinfo,
+ unsigned int sh_type,
+ const unsigned char* preloc_in,
+ size_t relnum,
+ Output_section* output_section,
+ off_t offset_in_output_section,
+ unsigned char* view,
+ elfcpp::Elf_types<32>::Elf_Addr view_address,
+ section_size_type,
+ unsigned char* preloc_out)
+{
+ // We can only handle REL type relocation sections.
+ gold_assert(sh_type == elfcpp::SHT_REL);
+
+ typedef typename Reloc_types<elfcpp::SHT_REL, 32, big_endian>::Reloc Reltype;
+ typedef typename Reloc_types<elfcpp::SHT_REL, 32, big_endian>::Reloc_write
+ Reltype_write;
+ const Arm_address invalid_address = static_cast<Arm_address>(0) - 1;
+
+ const Arm_relobj<big_endian>* object =
+ Arm_relobj<big_endian>::as_arm_relobj(relinfo->object);
+ const unsigned int local_count = object->local_symbol_count();
+
+ Reltype reloc(preloc_in);
+ Reltype_write reloc_write(preloc_out);
+
+ elfcpp::Elf_types<32>::Elf_WXword r_info = reloc.get_r_info();
+ const unsigned int r_sym = elfcpp::elf_r_sym<32>(r_info);
+ const unsigned int r_type = elfcpp::elf_r_type<32>(r_info);
+
+ const Arm_reloc_property* arp =
+ arm_reloc_property_table->get_implemented_static_reloc_property(r_type);
+ gold_assert(arp != NULL);
+
+ // Get the new symbol index.
+ // We only use RELOC_SPECIAL strategy in local relocations.
+ gold_assert(r_sym < local_count);
+
+ // We are adjusting a section symbol. We need to find
+ // the symbol table index of the section symbol for
+ // the output section corresponding to input section
+ // in which this symbol is defined.
+ bool is_ordinary;
+ unsigned int shndx = object->local_symbol_input_shndx(r_sym, &is_ordinary);
+ gold_assert(is_ordinary);
+ Output_section* os = object->output_section(shndx);
+ gold_assert(os != NULL);
+ gold_assert(os->needs_symtab_index());
+ unsigned int new_symndx = os->symtab_index();
+
+ // Get the new offset--the location in the output section where
+ // this relocation should be applied.
+
+ Arm_address offset = reloc.get_r_offset();
+ Arm_address new_offset;
+ if (offset_in_output_section != invalid_address)
+ new_offset = offset + offset_in_output_section;
+ else
+ {
+ section_offset_type sot_offset =
+ convert_types<section_offset_type, Arm_address>(offset);
+ section_offset_type new_sot_offset =
+ output_section->output_offset(object, relinfo->data_shndx,
+ sot_offset);
+ gold_assert(new_sot_offset != -1);
+ new_offset = new_sot_offset;
+ }
+
+ // In an object file, r_offset is an offset within the section.
+ // In an executable or dynamic object, generated by
+ // --emit-relocs, r_offset is an absolute address.
+ if (!parameters->options().relocatable())
+ {
+ new_offset += view_address;
+ if (offset_in_output_section != invalid_address)
+ new_offset -= offset_in_output_section;
+ }
+
+ reloc_write.put_r_offset(new_offset);
+ reloc_write.put_r_info(elfcpp::elf_r_info<32>(new_symndx, r_type));
+
+ // Handle the reloc addend.
+ // The relocation uses a section symbol in the input file.
+ // We are adjusting it to use a section symbol in the output
+ // file. The input section symbol refers to some address in
+ // the input section. We need the relocation in the output
+ // file to refer to that same address. This adjustment to
+ // the addend is the same calculation we use for a simple
+ // absolute relocation for the input section symbol.
+
+ const Symbol_value<32>* psymval = object->local_symbol(r_sym);
+
+ // Handle THUMB bit.
+ Symbol_value<32> symval;
+ Arm_address thumb_bit =
+ object->local_symbol_is_thumb_function(r_sym) ? 1 : 0;
+ if (thumb_bit != 0
+ && arp->uses_thumb_bit()
+ && ((psymval->value(object, 0) & 1) != 0))
+ {
+ Arm_address stripped_value =
+ psymval->value(object, 0) & ~static_cast<Arm_address>(1);
+ symval.set_output_value(stripped_value);
+ psymval = &symval;
+ }
+
+ unsigned char* paddend = view + offset;
+ typename Arm_relocate_functions<big_endian>::Status reloc_status =
+ Arm_relocate_functions<big_endian>::STATUS_OKAY;
+ switch (r_type)
+ {
+ case elfcpp::R_ARM_ABS8:
+ reloc_status = Arm_relocate_functions<big_endian>::abs8(paddend, object,
+ psymval);
+ break;
+
+ case elfcpp::R_ARM_ABS12:
+ reloc_status = Arm_relocate_functions<big_endian>::abs12(paddend, object,
+ psymval);
+ break;
+
+ case elfcpp::R_ARM_ABS16:
+ reloc_status = Arm_relocate_functions<big_endian>::abs16(paddend, object,
+ psymval);
+ break;
+
+ case elfcpp::R_ARM_THM_ABS5:
+ reloc_status = Arm_relocate_functions<big_endian>::thm_abs5(paddend,
+ object,
+ psymval);
+ break;
+
+ case elfcpp::R_ARM_MOVW_ABS_NC:
+ case elfcpp::R_ARM_MOVW_PREL_NC:
+ case elfcpp::R_ARM_MOVW_BREL_NC:
+ case elfcpp::R_ARM_MOVW_BREL:
+ reloc_status = Arm_relocate_functions<big_endian>::movw(
+ paddend, object, psymval, 0, thumb_bit, arp->checks_overflow());
+ break;
+
+ case elfcpp::R_ARM_THM_MOVW_ABS_NC:
+ case elfcpp::R_ARM_THM_MOVW_PREL_NC:
+ case elfcpp::R_ARM_THM_MOVW_BREL_NC:
+ case elfcpp::R_ARM_THM_MOVW_BREL:
+ reloc_status = Arm_relocate_functions<big_endian>::thm_movw(
+ paddend, object, psymval, 0, thumb_bit, arp->checks_overflow());
+ break;
+
+ case elfcpp::R_ARM_THM_CALL:
+ case elfcpp::R_ARM_THM_XPC22:
+ case elfcpp::R_ARM_THM_JUMP24:
+ reloc_status =
+ Arm_relocate_functions<big_endian>::thumb_branch_common(
+ r_type, relinfo, paddend, NULL, object, 0, psymval, 0, thumb_bit,
+ false);
+ break;
+
+ case elfcpp::R_ARM_PLT32:
+ case elfcpp::R_ARM_CALL:
+ case elfcpp::R_ARM_JUMP24:
+ case elfcpp::R_ARM_XPC25:
+ reloc_status =
+ Arm_relocate_functions<big_endian>::arm_branch_common(
+ r_type, relinfo, paddend, NULL, object, 0, psymval, 0, thumb_bit,
+ false);
+ break;
+
+ case elfcpp::R_ARM_THM_JUMP19:
+ reloc_status =
+ Arm_relocate_functions<big_endian>::thm_jump19(paddend, object,
+ psymval, 0, thumb_bit);
+ break;
+
+ case elfcpp::R_ARM_THM_JUMP6:
+ reloc_status =
+ Arm_relocate_functions<big_endian>::thm_jump6(paddend, object, psymval,
+ 0);
+ break;
+
+ case elfcpp::R_ARM_THM_JUMP8:
+ reloc_status =
+ Arm_relocate_functions<big_endian>::thm_jump8(paddend, object, psymval,
+ 0);
+ break;
+
+ case elfcpp::R_ARM_THM_JUMP11:
+ reloc_status =
+ Arm_relocate_functions<big_endian>::thm_jump11(paddend, object, psymval,
+ 0);
+ break;
+
+ case elfcpp::R_ARM_PREL31:
+ reloc_status =
+ Arm_relocate_functions<big_endian>::prel31(paddend, object, psymval, 0,
+ thumb_bit);
+ break;
+
+ case elfcpp::R_ARM_THM_PC8:
+ reloc_status =
+ Arm_relocate_functions<big_endian>::thm_pc8(paddend, object, psymval,
+ 0);
+ break;
+
+ case elfcpp::R_ARM_THM_PC12:
+ reloc_status =
+ Arm_relocate_functions<big_endian>::thm_pc12(paddend, object, psymval,
+ 0);
+ break;
+
+ case elfcpp::R_ARM_THM_ALU_PREL_11_0:
+ reloc_status =
+ Arm_relocate_functions<big_endian>::thm_alu11(paddend, object, psymval,
+ 0, thumb_bit);
+ break;
+
+ // These relocation truncate relocation results so we cannot handle them
+ // in a relocatable link.
+ case elfcpp::R_ARM_MOVT_ABS:
+ case elfcpp::R_ARM_THM_MOVT_ABS:
+ case elfcpp::R_ARM_MOVT_PREL:
+ case elfcpp::R_ARM_MOVT_BREL:
+ case elfcpp::R_ARM_THM_MOVT_PREL:
+ case elfcpp::R_ARM_THM_MOVT_BREL:
+ case elfcpp::R_ARM_ALU_PC_G0_NC:
+ case elfcpp::R_ARM_ALU_PC_G0:
+ case elfcpp::R_ARM_ALU_PC_G1_NC:
+ case elfcpp::R_ARM_ALU_PC_G1:
+ case elfcpp::R_ARM_ALU_PC_G2:
+ case elfcpp::R_ARM_ALU_SB_G0_NC:
+ case elfcpp::R_ARM_ALU_SB_G0:
+ case elfcpp::R_ARM_ALU_SB_G1_NC:
+ case elfcpp::R_ARM_ALU_SB_G1:
+ case elfcpp::R_ARM_ALU_SB_G2:
+ case elfcpp::R_ARM_LDR_PC_G0:
+ case elfcpp::R_ARM_LDR_PC_G1:
+ case elfcpp::R_ARM_LDR_PC_G2:
+ case elfcpp::R_ARM_LDR_SB_G0:
+ case elfcpp::R_ARM_LDR_SB_G1:
+ case elfcpp::R_ARM_LDR_SB_G2:
+ case elfcpp::R_ARM_LDRS_PC_G0:
+ case elfcpp::R_ARM_LDRS_PC_G1:
+ case elfcpp::R_ARM_LDRS_PC_G2:
+ case elfcpp::R_ARM_LDRS_SB_G0:
+ case elfcpp::R_ARM_LDRS_SB_G1:
+ case elfcpp::R_ARM_LDRS_SB_G2:
+ case elfcpp::R_ARM_LDC_PC_G0:
+ case elfcpp::R_ARM_LDC_PC_G1:
+ case elfcpp::R_ARM_LDC_PC_G2:
+ case elfcpp::R_ARM_LDC_SB_G0:
+ case elfcpp::R_ARM_LDC_SB_G1:
+ case elfcpp::R_ARM_LDC_SB_G2:
+ gold_error(_("cannot handle %s in a relocatable link"),
+ arp->name().c_str());
+ break;
+
+ default:
+ gold_unreachable();
+ }
+
+ // Report any errors.
+ switch (reloc_status)
+ {
+ case Arm_relocate_functions<big_endian>::STATUS_OKAY:
+ break;
+ case Arm_relocate_functions<big_endian>::STATUS_OVERFLOW:
+ gold_error_at_location(relinfo, relnum, reloc.get_r_offset(),
+ _("relocation overflow in %s"),
+ arp->name().c_str());
+ break;
+ case Arm_relocate_functions<big_endian>::STATUS_BAD_RELOC:
+ gold_error_at_location(relinfo, relnum, reloc.get_r_offset(),
+ _("unexpected opcode while processing relocation %s"),
+ arp->name().c_str());
+ break;
+ default:
+ gold_unreachable();
+ }
+}
+
// Return the value to use for a dynamic symbol which requires special
// treatment. This is how we support equality comparisons of function
// pointers across shared library boundaries, as described in the
@@ -10362,6 +10748,7 @@ Target_arm<big_endian>::do_relax(
// If this is the first pass, we need to group input sections into
// stub groups.
bool done_exidx_fixup = false;
+ typedef typename Stub_table_list::iterator Stub_table_iterator;
if (pass == 1)
{
// Determine the stub group size. The group size is the absolute
@@ -10410,13 +10797,27 @@ Target_arm<big_endian>::do_relax(
done_exidx_fixup = true;
}
}
+ else
+ {
+ // If this is not the first pass, addresses and file offsets have
+ // been reset at this point, set them here.
+ for (Stub_table_iterator sp = this->stub_tables_.begin();
+ sp != this->stub_tables_.end();
+ ++sp)
+ {
+ Arm_input_section<big_endian>* owner = (*sp)->owner();
+ off_t off = align_address(owner->original_size(),
+ (*sp)->addralign());
+ (*sp)->set_address_and_file_offset(owner->address() + off,
+ owner->offset() + off);
+ }
+ }
// The Cortex-A8 stubs are sensitive to layout of code sections. At the
// beginning of each relaxation pass, just blow away all the stubs.
// Alternatively, we could selectively remove only the stubs and reloc
// information for code sections that have moved since the last pass.
// That would require more book-keeping.
- typedef typename Stub_table_list::iterator Stub_table_iterator;
if (this->fix_cortex_a8_)
{
// Clear all Cortex-A8 reloc information.
@@ -10793,13 +11194,11 @@ Target_arm<big_endian>::apply_cortex_a8_workaround(
switch (stub->stub_template()->type())
{
case arm_stub_a8_veneer_b_cond:
- gold_assert(!utils::has_overflow<21>(branch_offset));
- upper_insn = RelocFuncs::thumb32_cond_branch_upper(upper_insn,
- branch_offset);
- lower_insn = RelocFuncs::thumb32_cond_branch_lower(lower_insn,
- branch_offset);
- break;
-
+ // For a conditional branch, we re-write it to be a uncondition
+ // branch to the stub. We use the THUMB-2 encoding here.
+ upper_insn = 0xf000U;
+ lower_insn = 0xb800U;
+ // Fall through
case arm_stub_a8_veneer_b:
case arm_stub_a8_veneer_bl:
case arm_stub_a8_veneer_blx:
diff --git a/binutils-2.19/gold/configure b/binutils-2.19/gold/configure
index 9fd198f2..1a869783 100644
--- a/binutils-2.19/gold/configure
+++ b/binutils-2.19/gold/configure
@@ -682,6 +682,8 @@ PLUGINS_FALSE
PLUGINS_TRUE
THREADS_FALSE
THREADS_TRUE
+installed_linker
+install_as_default
am__untar
am__tar
AMTAR
@@ -759,6 +761,7 @@ ac_subst_files=''
ac_user_opts='
enable_option_checking
with_sysroot
+enable_gold
enable_threads
enable_plugins
enable_targets
@@ -1403,6 +1406,7 @@ Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-gold[=ARG] build gold [ARG={both}[/{gold,ld}]]
--enable-threads multi-threaded linking
--enable-plugins linker plugins
--enable-targets alternative target configurations
@@ -3227,6 +3231,33 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+# Check whether --enable-gold was given.
+if test "${enable_gold+set}" = set; then :
+ enableval=$enable_gold; case "${enableval}" in
+ yes)
+ install_as_default=gold
+ installed_linker=ld
+ ;;
+ both/gold)
+ install_as_default=yes
+ installed_linker=ld.gold
+ ;;
+ both|both/ld)
+ install_as_default=no
+ installed_linker=ld.gold
+ ;;
+ *)
+ as_fn_error "invalid --enable-gold argument" "$LINENO" 5
+ ;;
+ esac
+else
+ install_as_default=gold
+ installed_linker=ld
+fi
+
+
+
+
# Check whether --enable-threads was given.
if test "${enable_threads+set}" = set; then :
enableval=$enable_threads; case "${enableval}" in
diff --git a/binutils-2.19/gold/configure.ac b/binutils-2.19/gold/configure.ac
index f184d4b2..e5601177 100644
--- a/binutils-2.19/gold/configure.ac
+++ b/binutils-2.19/gold/configure.ac
@@ -38,6 +38,33 @@ AC_DEFINE_UNQUOTED(TARGET_SYSTEM_ROOT, "$sysroot",
AC_DEFINE_UNQUOTED(TARGET_SYSTEM_ROOT_RELOCATABLE, $sysroot_relocatable,
[Whether the system root can be relocated])
+dnl "install_as_default" is true if the linker to be installed as the
+dnl default linker, ld.
+dnl "installed_linker" is the installed gold linker name.
+AC_ARG_ENABLE(gold,
+[[ --enable-gold[=ARG] build gold [ARG={both}[/{gold,ld}]]]],
+[case "${enableval}" in
+ yes)
+ install_as_default=gold
+ installed_linker=ld
+ ;;
+ both/gold)
+ install_as_default=yes
+ installed_linker=ld.gold
+ ;;
+ both|both/ld)
+ install_as_default=no
+ installed_linker=ld.gold
+ ;;
+ *)
+ AC_MSG_ERROR([invalid --enable-gold argument])
+ ;;
+ esac],
+[install_as_default=gold
+ installed_linker=ld])
+AC_SUBST(install_as_default)
+AC_SUBST(installed_linker)
+
dnl For now threads are a configure time option.
AC_ARG_ENABLE([threads],
[ --enable-threads multi-threaded linking],
diff --git a/binutils-2.19/gold/gold.cc b/binutils-2.19/gold/gold.cc
index 39c2ce7b..bf81321e 100644
--- a/binutils-2.19/gold/gold.cc
+++ b/binutils-2.19/gold/gold.cc
@@ -276,6 +276,16 @@ queue_middle_gc_tasks(const General_options& options,
next_blocker));
this_blocker = next_blocker;
}
+
+ // If we are given only archives in input, we have no regular
+ // objects and THIS_BLOCKER is NULL here. Create a dummy
+ // blocker here so that we can run the middle tasks immediately.
+ if (this_blocker == NULL)
+ {
+ gold_assert(input_objects->number_of_relobjs() == 0);
+ this_blocker = new Task_token(true);
+ }
+
workqueue->queue(new Task_function(new Middle_runner(options,
input_objects,
symtab,
diff --git a/binutils-2.19/gold/merge.cc b/binutils-2.19/gold/merge.cc
index e2b6eef2..6e44ddd4 100644
--- a/binutils-2.19/gold/merge.cc
+++ b/binutils-2.19/gold/merge.cc
@@ -304,6 +304,26 @@ Output_merge_base::do_is_merge_section_for(const Relobj* object,
return this->merge_map_.is_merge_section_for(object, shndx);
}
+// Record a merged input section for script processing.
+
+void
+Output_merge_base::record_input_section(Relobj* relobj, unsigned int shndx)
+{
+ gold_assert(this->keeps_input_sections_ && relobj != NULL);
+ // If this is the first input section, record it. We need do this because
+ // this->input_sections_ is unordered.
+ if (this->first_relobj_ == NULL)
+ {
+ this->first_relobj_ = relobj;
+ this->first_shndx_ = shndx;
+ }
+
+ std::pair<Input_sections::iterator, bool> result =
+ this->input_sections_.insert(Section_id(relobj, shndx));
+ // We should insert a merge section once only.
+ gold_assert(result.second);
+}
+
// Class Output_merge_data.
// Compute the hash code for a fixed-size constant.
@@ -414,6 +434,10 @@ Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
this->add_mapping(object, shndx, i, entsize, k);
}
+ // For script processing, we keep the input sections.
+ if (this->keeps_input_sections())
+ record_input_section(object, shndx);
+
return true;
}
@@ -517,6 +541,10 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
this->input_count_ += count;
+ // For script processing, we keep the input sections.
+ if (this->keeps_input_sections())
+ record_input_section(object, shndx);
+
return true;
}
diff --git a/binutils-2.19/gold/merge.h b/binutils-2.19/gold/merge.h
index 345b1154..c2d305be 100644
--- a/binutils-2.19/gold/merge.h
+++ b/binutils-2.19/gold/merge.h
@@ -216,7 +216,9 @@ class Output_merge_base : public Output_section_data
{
public:
Output_merge_base(uint64_t entsize, uint64_t addralign)
- : Output_section_data(addralign), merge_map_(), entsize_(entsize)
+ : Output_section_data(addralign), merge_map_(), entsize_(entsize),
+ keeps_input_sections_(false), first_relobj_(NULL), first_shndx_(-1),
+ input_sections_()
{ }
// Return the entry size.
@@ -230,6 +232,52 @@ class Output_merge_base : public Output_section_data
is_string()
{ return this->do_is_string(); }
+ // Whether this keeps input sections.
+ bool
+ keeps_input_sections() const
+ { return this->keeps_input_sections_; }
+
+ // Set the keeps-input-sections flag. This is virtual so that sub-classes
+ // can perform additional checks.
+ void
+ set_keeps_input_sections()
+ { this->do_set_keeps_input_sections(); }
+
+ // Return the object of the first merged input section. This used
+ // for script processing. This is NULL if merge section is empty.
+ Relobj*
+ first_relobj() const
+ { return this->first_relobj_; }
+
+ // Return the section index of the first merged input section. This
+ // is used for script processing. This is valid only if merge section
+ // is not valid.
+ unsigned int
+ first_shndx() const
+ {
+ gold_assert(this->first_relobj_ != NULL);
+ return this->first_shndx_;
+ }
+
+ // Set of merged input sections.
+ typedef Unordered_set<Section_id, Section_id_hash> Input_sections;
+
+ // Beginning of merged input sections.
+ Input_sections::const_iterator
+ input_sections_begin() const
+ {
+ gold_assert(this->keeps_input_sections_);
+ return this->input_sections_.begin();
+ }
+
+ // Beginning of merged input sections.
+ Input_sections::const_iterator
+ input_sections_end() const
+ {
+ gold_assert(this->keeps_input_sections_);
+ return this->input_sections_.end();
+ }
+
protected:
// Return the output offset for an input offset.
bool
@@ -257,6 +305,15 @@ class Output_merge_base : public Output_section_data
do_is_string()
{ return false; }
+ // This may be overridden by the child class.
+ virtual void
+ do_set_keeps_input_sections()
+ { this->keeps_input_sections_ = true; }
+
+ // Record the merged input section for script processing.
+ void
+ record_input_section(Relobj* relobj, unsigned int shndx);
+
private:
// A mapping from input object/section/offset to offset in output
// section.
@@ -264,6 +321,15 @@ class Output_merge_base : public Output_section_data
// The entry size. For fixed-size constants, this is the size of
// the constants. For strings, this is the size of a character.
uint64_t entsize_;
+ // Whether we keep input sections.
+ bool keeps_input_sections_;
+ // Object of the first merged input section. We use this for script
+ // processing.
+ Relobj* first_relobj_;
+ // Section index of the first merged input section.
+ unsigned int first_shndx_;
+ // Input sections. We only keep them is keeps_input_sections_ is true.
+ Input_sections input_sections_;
};
// Handle SHF_MERGE sections with fixed-size constant data.
@@ -303,6 +369,14 @@ class Output_merge_data : public Output_merge_base
void
do_print_merge_stats(const char* section_name);
+ // Set keeps-input-sections flag.
+ void
+ do_set_keeps_input_sections()
+ {
+ gold_assert(this->input_count_ == 0);
+ Output_merge_base::do_set_keeps_input_sections();
+ }
+
private:
// We build a hash table of the fixed-size constants. Each constant
// is stored as a pointer into the section data we are accumulating.
@@ -440,6 +514,14 @@ class Output_merge_string : public Output_merge_base
do_is_string()
{ return true; }
+ // Set keeps-input-sections flag.
+ void
+ do_set_keeps_input_sections()
+ {
+ gold_assert(this->input_count_ == 0);
+ Output_merge_base::do_set_keeps_input_sections();
+ }
+
private:
// The name of the string type, for stats.
const char*
diff --git a/binutils-2.19/gold/object.cc b/binutils-2.19/gold/object.cc
index 73bf3702..02366c02 100644
--- a/binutils-2.19/gold/object.cc
+++ b/binutils-2.19/gold/object.cc
@@ -1751,7 +1751,12 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
const Output_section_data* posd =
os->find_relaxed_input_section(this, shndx);
if (posd != NULL)
- lv.set_output_value(posd->address());
+ {
+ Address relocatable_link_adjustment =
+ relocatable ? os->address() : 0;
+ lv.set_output_value(posd->address()
+ - relocatable_link_adjustment);
+ }
else
lv.set_output_value(os->address());
}
@@ -1759,9 +1764,14 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
{
// We have to consider the addend to determine the
// value to use in a relocation. START is the start
- // of this input section.
+ // of this input section. If we are doing a relocatable
+ // link, use offset from start output section instead of
+ // address.
+ Address adjusted_start =
+ relocatable ? start - os->address() : start;
Merged_symbol_value<size>* msv =
- new Merged_symbol_value<size>(lv.input_value(), start);
+ new Merged_symbol_value<size>(lv.input_value(),
+ adjusted_start);
lv.set_merged_symbol_value(msv);
}
}
diff --git a/binutils-2.19/gold/output.cc b/binutils-2.19/gold/output.cc
index ff43d537..dbdad781 100644
--- a/binutils-2.19/gold/output.cc
+++ b/binutils-2.19/gold/output.cc
@@ -1745,6 +1745,42 @@ Output_section::Input_section::data_size() const
return this->u2_.posd->data_size();
}
+// Return the object for an input section.
+
+Relobj*
+Output_section::Input_section::relobj() const
+{
+ if (this->is_input_section())
+ return this->u2_.object;
+ else if (this->is_merge_section())
+ {
+ gold_assert(this->u2_.pomb->first_relobj() != NULL);
+ return this->u2_.pomb->first_relobj();
+ }
+ else if (this->is_relaxed_input_section())
+ return this->u2_.poris->relobj();
+ else
+ gold_unreachable();
+}
+
+// Return the input section index for an input section.
+
+unsigned int
+Output_section::Input_section::shndx() const
+{
+ if (this->is_input_section())
+ return this->shndx_;
+ else if (this->is_merge_section())
+ {
+ gold_assert(this->u2_.pomb->first_relobj() != NULL);
+ return this->u2_.pomb->first_shndx();
+ }
+ else if (this->is_relaxed_input_section())
+ return this->u2_.poris->shndx();
+ else
+ gold_unreachable();
+}
+
// Set the address and file offset.
void
@@ -1910,10 +1946,7 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
is_noload_(false),
tls_offset_(0),
checkpoint_(NULL),
- merge_section_map_(),
- merge_section_by_properties_map_(),
- relaxed_input_section_map_(),
- is_relaxed_input_section_map_valid_(true)
+ lookup_maps_(new Output_section_lookup_maps)
{
// An unallocated section has no address. Forcing this means that
// we don't need special treatment for symbols defined in debug
@@ -1997,8 +2030,12 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
&& reloc_shndx == 0
&& shdr.get_sh_size() > 0)
{
- if (this->add_merge_input_section(object, shndx, sh_flags,
- entsize, addralign))
+ // Keep information about merged input sections for rebuilding fast
+ // lookup maps if we have sections-script or we do relaxation.
+ bool keeps_input_sections =
+ have_sections_script || parameters->target().may_relax();
+ if (this->add_merge_input_section(object, shndx, sh_flags, entsize,
+ addralign, keeps_input_sections))
{
// Tell the relocation routines that they need to call the
// output_offset method to determine the final address.
@@ -2088,11 +2125,9 @@ Output_section::add_relaxed_input_section(Output_relaxed_input_section* poris)
{
Input_section inp(poris);
this->add_output_section_data(&inp);
- if (this->is_relaxed_input_section_map_valid_)
- {
- Const_section_id csid(poris->relobj(), poris->shndx());
- this->relaxed_input_section_map_[csid] = poris;
- }
+ if (this->lookup_maps_->is_valid())
+ this->lookup_maps_->add_relaxed_input_section(poris->relobj(),
+ poris->shndx(), poris);
// For a relaxed section, we use the current data size. Linker scripts
// get all the input sections, including relaxed one from an output
@@ -2138,7 +2173,8 @@ Output_section::add_output_merge_section(Output_section_data* posd,
bool
Output_section::add_merge_input_section(Relobj* object, unsigned int shndx,
uint64_t flags, uint64_t entsize,
- uint64_t addralign)
+ uint64_t addralign,
+ bool keeps_input_sections)
{
bool is_string = (flags & elfcpp::SHF_STRINGS) != 0;
@@ -2151,13 +2187,15 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx,
gold_assert(this->checkpoint_ == NULL);
// Look up merge sections by required properties.
- Output_merge_base* pomb;
+ // Currently, we only invalidate the lookup maps in script processing
+ // and relaxation. We should not have done either when we reach here.
+ // So we assume that the lookup maps are valid to simply code.
+ gold_assert(this->lookup_maps_->is_valid());
Merge_section_properties msp(is_string, entsize, addralign);
- Merge_section_by_properties_map::const_iterator p =
- this->merge_section_by_properties_map_.find(msp);
- if (p != this->merge_section_by_properties_map_.end())
+ Output_merge_base* pomb = this->lookup_maps_->find_merge_section(msp);
+ bool is_new = false;
+ if (pomb != NULL)
{
- pomb = p->second;
gold_assert(pomb->is_string() == is_string
&& pomb->entsize() == entsize
&& pomb->addralign() == addralign);
@@ -2184,22 +2222,36 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx,
return false;
}
}
- // Add new merge section to this output section and link merge
- // section properties to new merge section in map.
- this->add_output_merge_section(pomb, is_string, entsize);
- this->merge_section_by_properties_map_[msp] = pomb;
+ // If we need to do script processing or relaxation, we need to keep
+ // the original input sections to rebuild the fast lookup maps.
+ if (keeps_input_sections)
+ pomb->set_keeps_input_sections();
+ is_new = true;
}
if (pomb->add_input_section(object, shndx))
{
+ // Add new merge section to this output section and link merge
+ // section properties to new merge section in map.
+ if (is_new)
+ {
+ this->add_output_merge_section(pomb, is_string, entsize);
+ this->lookup_maps_->add_merge_section(msp, pomb);
+ }
+
// Add input section to new merge section and link input section to new
// merge section in map.
- Const_section_id csid(object, shndx);
- this->merge_section_map_[csid] = pomb;
+ this->lookup_maps_->add_merge_input_section(object, shndx, pomb);
return true;
}
else
- return false;
+ {
+ // If add_input_section failed, delete new merge section to avoid
+ // exporting empty merge sections in Output_section::get_input_section.
+ if (is_new)
+ delete pomb;
+ return false;
+ }
}
// Build a relaxation map to speed up relaxation of existing input sections.
@@ -2294,12 +2346,12 @@ Output_section::convert_input_sections_to_relaxed_sections(
&this->input_sections_);
// Update fast look-up map.
- if (this->is_relaxed_input_section_map_valid_)
+ if (this->lookup_maps_->is_valid())
for (size_t i = 0; i < relaxed_sections.size(); ++i)
{
Output_relaxed_input_section* poris = relaxed_sections[i];
- Const_section_id csid(poris->relobj(), poris->shndx());
- this->relaxed_input_section_map_[csid] = poris;
+ this->lookup_maps_->add_relaxed_input_section(poris->relobj(),
+ poris->shndx(), poris);
}
}
@@ -2344,17 +2396,47 @@ Output_section_data*
Output_section::find_merge_section(const Relobj* object,
unsigned int shndx) const
{
- Const_section_id csid(object, shndx);
- Output_section_data_by_input_section_map::const_iterator p =
- this->merge_section_map_.find(csid);
- if (p != this->merge_section_map_.end())
+ if (!this->lookup_maps_->is_valid())
+ this->build_lookup_maps();
+ return this->lookup_maps_->find_merge_section(object, shndx);
+}
+
+// Build the lookup maps for merge and relaxed sections. This is needs
+// to be declared as a const methods so that it is callable with a const
+// Output_section pointer. The method only updates states of the maps.
+
+void
+Output_section::build_lookup_maps() const
+{
+ this->lookup_maps_->clear();
+ for (Input_section_list::const_iterator p = this->input_sections_.begin();
+ p != this->input_sections_.end();
+ ++p)
{
- Output_section_data* posd = p->second;
- gold_assert(posd->is_merge_section_for(object, shndx));
- return posd;
+ if (p->is_merge_section())
+ {
+ Output_merge_base* pomb = p->output_merge_base();
+ Merge_section_properties msp(pomb->is_string(), pomb->entsize(),
+ pomb->addralign());
+ this->lookup_maps_->add_merge_section(msp, pomb);
+ for (Output_merge_base::Input_sections::const_iterator is =
+ pomb->input_sections_begin();
+ is != pomb->input_sections_end();
+ ++is)
+ {
+ const Const_section_id& csid = *is;
+ this->lookup_maps_->add_merge_input_section(csid.first,
+ csid.second, pomb);
+ }
+
+ }
+ else if (p->is_relaxed_input_section())
+ {
+ Output_relaxed_input_section* poris = p->relaxed_input_section();
+ this->lookup_maps_->add_relaxed_input_section(poris->relobj(),
+ poris->shndx(), poris);
+ }
}
- else
- return NULL;
}
// Find an relaxed input section corresponding to an input section
@@ -2364,31 +2446,9 @@ const Output_relaxed_input_section*
Output_section::find_relaxed_input_section(const Relobj* object,
unsigned int shndx) const
{
- // Be careful that the map may not be valid due to input section export
- // to scripts or a check-point restore.
- if (!this->is_relaxed_input_section_map_valid_)
- {
- // Rebuild the map as needed.
- this->relaxed_input_section_map_.clear();
- for (Input_section_list::const_iterator p = this->input_sections_.begin();
- p != this->input_sections_.end();
- ++p)
- if (p->is_relaxed_input_section())
- {
- Const_section_id csid(p->relobj(), p->shndx());
- this->relaxed_input_section_map_[csid] =
- p->relaxed_input_section();
- }
- this->is_relaxed_input_section_map_valid_ = true;
- }
-
- Const_section_id csid(object, shndx);
- Output_relaxed_input_section_by_input_section_map::const_iterator p =
- this->relaxed_input_section_map_.find(csid);
- if (p != this->relaxed_input_section_map_.end())
- return p->second;
- else
- return NULL;
+ if (!this->lookup_maps_->is_valid())
+ this->build_lookup_maps();
+ return this->lookup_maps_->find_relaxed_input_section(object, shndx);
}
// Given an address OFFSET relative to the start of input section
@@ -3042,14 +3102,14 @@ uint64_t
Output_section::get_input_sections(
uint64_t address,
const std::string& fill,
- std::list<Simple_input_section>* input_sections)
+ std::list<Input_section>* input_sections)
{
if (this->checkpoint_ != NULL
&& !this->checkpoint_->input_sections_saved())
this->checkpoint_->save_input_sections();
- // Invalidate the relaxed input section map.
- this->is_relaxed_input_section_map_valid_ = false;
+ // Invalidate fast look-up maps.
+ this->lookup_maps_->invalidate();
uint64_t orig_address = address;
@@ -3060,12 +3120,10 @@ Output_section::get_input_sections(
p != this->input_sections_.end();
++p)
{
- if (p->is_input_section())
- input_sections->push_back(Simple_input_section(p->relobj(),
- p->shndx()));
- else if (p->is_relaxed_input_section())
- input_sections->push_back(
- Simple_input_section(p->relaxed_input_section()));
+ if (p->is_input_section()
+ || p->is_relaxed_input_section()
+ || p->is_merge_section())
+ input_sections->push_back(*p);
else
{
uint64_t aligned_address = align_address(address, p->addralign());
@@ -3100,13 +3158,16 @@ Output_section::get_input_sections(
return data_size;
}
-// Add an simple input section.
+// Add a script input section. SIS is an Output_section::Input_section,
+// which can be either a plain input section or a special input section like
+// a relaxed input section. For a special input section, its size must be
+// finalized.
void
-Output_section::add_simple_input_section(const Simple_input_section& sis,
- off_t data_size,
- uint64_t addralign)
+Output_section::add_script_input_section(const Input_section& sis)
{
+ uint64_t data_size = sis.data_size();
+ uint64_t addralign = sis.addralign();
if (addralign > this->addralign_)
this->addralign_ = addralign;
@@ -3117,11 +3178,31 @@ Output_section::add_simple_input_section(const Simple_input_section& sis,
this->set_current_data_size_for_child(aligned_offset_in_section
+ data_size);
- Input_section is =
- (sis.is_relaxed_input_section()
- ? Input_section(sis.relaxed_input_section())
- : Input_section(sis.relobj(), sis.shndx(), data_size, addralign));
- this->input_sections_.push_back(is);
+ this->input_sections_.push_back(sis);
+
+ // Update fast lookup maps if necessary.
+ if (this->lookup_maps_->is_valid())
+ {
+ if (sis.is_merge_section())
+ {
+ Output_merge_base* pomb = sis.output_merge_base();
+ Merge_section_properties msp(pomb->is_string(), pomb->entsize(),
+ pomb->addralign());
+ this->lookup_maps_->add_merge_section(msp, pomb);
+ for (Output_merge_base::Input_sections::const_iterator p =
+ pomb->input_sections_begin();
+ p != pomb->input_sections_end();
+ ++p)
+ this->lookup_maps_->add_merge_input_section(p->first, p->second,
+ pomb);
+ }
+ else if (sis.is_relaxed_input_section())
+ {
+ Output_relaxed_input_section* poris = sis.relaxed_input_section();
+ this->lookup_maps_->add_relaxed_input_section(poris->relobj(),
+ poris->shndx(), poris);
+ }
+ }
}
// Save states for relaxation.
@@ -3147,9 +3228,9 @@ Output_section::discard_states()
this->checkpoint_ = NULL;
gold_assert(this->fills_.empty());
- // Simply invalidate the relaxed input section map since we do not keep
- // track of it.
- this->is_relaxed_input_section_map_valid_ = false;
+ // Simply invalidate the fast lookup maps since we do not keep
+ // track of them.
+ this->lookup_maps_->invalidate();
}
void
@@ -3181,9 +3262,9 @@ Output_section::restore_states()
this->attached_input_sections_are_sorted_ =
checkpoint->attached_input_sections_are_sorted();
- // Simply invalidate the relaxed input section map since we do not keep
- // track of it.
- this->is_relaxed_input_section_map_valid_ = false;
+ // Simply invalidate the fast lookup maps since we do not keep
+ // track of them.
+ this->lookup_maps_->invalidate();
}
// Update the section offsets of input sections in this. This is required if
diff --git a/binutils-2.19/gold/output.h b/binutils-2.19/gold/output.h
index 80885653..da321b60 100644
--- a/binutils-2.19/gold/output.h
+++ b/binutils-2.19/gold/output.h
@@ -2314,6 +2314,188 @@ class Output_relaxed_input_section : public Output_section_data_build
unsigned int shndx_;
};
+// This class describes properties of merge data sections. It is used
+// as a key type for maps.
+class Merge_section_properties
+{
+ public:
+ Merge_section_properties(bool is_string, uint64_t entsize,
+ uint64_t addralign)
+ : is_string_(is_string), entsize_(entsize), addralign_(addralign)
+ { }
+
+ // Whether this equals to another Merge_section_properties MSP.
+ bool
+ eq(const Merge_section_properties& msp) const
+ {
+ return ((this->is_string_ == msp.is_string_)
+ && (this->entsize_ == msp.entsize_)
+ && (this->addralign_ == msp.addralign_));
+ }
+
+ // Compute a hash value for this using 64-bit FNV-1a hash.
+ size_t
+ hash_value() const
+ {
+ uint64_t h = 14695981039346656037ULL; // FNV offset basis.
+ uint64_t prime = 1099511628211ULL;
+ h = (h ^ static_cast<uint64_t>(this->is_string_)) * prime;
+ h = (h ^ static_cast<uint64_t>(this->entsize_)) * prime;
+ h = (h ^ static_cast<uint64_t>(this->addralign_)) * prime;
+ return h;
+ }
+
+ // Functors for associative containers.
+ struct equal_to
+ {
+ bool
+ operator()(const Merge_section_properties& msp1,
+ const Merge_section_properties& msp2) const
+ { return msp1.eq(msp2); }
+ };
+
+ struct hash
+ {
+ size_t
+ operator()(const Merge_section_properties& msp) const
+ { return msp.hash_value(); }
+ };
+
+ private:
+ // Whether this merge data section is for strings.
+ bool is_string_;
+ // Entsize of this merge data section.
+ uint64_t entsize_;
+ // Address alignment.
+ uint64_t addralign_;
+};
+
+// This class is used to speed up look up of special input sections in an
+// Output_section.
+
+class Output_section_lookup_maps
+{
+ public:
+ Output_section_lookup_maps()
+ : is_valid_(true), merge_sections_by_properties_(),
+ merge_sections_by_id_(), relaxed_input_sections_by_id_()
+ { }
+
+ // Whether the maps are valid.
+ bool
+ is_valid() const
+ { return this->is_valid_; }
+
+ // Invalidate the maps.
+ void
+ invalidate()
+ { this->is_valid_ = false; }
+
+ // Clear the maps.
+ void
+ clear()
+ {
+ this->merge_sections_by_properties_.clear();
+ this->merge_sections_by_id_.clear();
+ this->relaxed_input_sections_by_id_.clear();
+ // A cleared map is valid.
+ this->is_valid_ = true;
+ }
+
+ // Find a merge section by merge section properties. Return NULL if none
+ // is found.
+ Output_merge_base*
+ find_merge_section(const Merge_section_properties& msp) const
+ {
+ gold_assert(this->is_valid_);
+ Merge_sections_by_properties::const_iterator p =
+ this->merge_sections_by_properties_.find(msp);
+ return p != this->merge_sections_by_properties_.end() ? p->second : NULL;
+ }
+
+ // Find a merge section by section ID of a merge input section. Return NULL
+ // if none is found.
+ Output_merge_base*
+ find_merge_section(const Object* object, unsigned int shndx) const
+ {
+ gold_assert(this->is_valid_);
+ Merge_sections_by_id::const_iterator p =
+ this->merge_sections_by_id_.find(Const_section_id(object, shndx));
+ return p != this->merge_sections_by_id_.end() ? p->second : NULL;
+ }
+
+ // Add a merge section pointed by POMB with properties MSP.
+ void
+ add_merge_section(const Merge_section_properties& msp,
+ Output_merge_base* pomb)
+ {
+ std::pair<Merge_section_properties, Output_merge_base*> value(msp, pomb);
+ std::pair<Merge_sections_by_properties::iterator, bool> result =
+ this->merge_sections_by_properties_.insert(value);
+ gold_assert(value.second);
+ }
+
+ // Add a mapping from a merged input section in OBJECT with index SHNDX
+ // to a merge output section pointed by POMB.
+ void
+ add_merge_input_section(const Object* object, unsigned int shndx,
+ Output_merge_base* pomb)
+ {
+ Const_section_id csid(object, shndx);
+ std::pair<Const_section_id, Output_merge_base*> value(csid, pomb);
+ std::pair<Merge_sections_by_id::iterator, bool> result =
+ this->merge_sections_by_id_.insert(value);
+ gold_assert(value.second);
+ }
+
+ // Find a relaxed input section of OBJECT with index SHNDX.
+ Output_relaxed_input_section*
+ find_relaxed_input_section(const Object* object, unsigned int shndx) const
+ {
+ gold_assert(this->is_valid_);
+ Relaxed_input_sections_by_id::const_iterator p =
+ this->relaxed_input_sections_by_id_.find(Const_section_id(object, shndx));
+ return p != this->relaxed_input_sections_by_id_.end() ? p->second : NULL;
+ }
+
+ // Add a relaxed input section pointed by POMB and whose original input
+ // section is in OBJECT with index SHNDX.
+ void
+ add_relaxed_input_section(const Relobj* relobj, unsigned int shndx,
+ Output_relaxed_input_section* poris)
+ {
+ Const_section_id csid(relobj, shndx);
+ std::pair<Const_section_id, Output_relaxed_input_section*>
+ value(csid, poris);
+ std::pair<Relaxed_input_sections_by_id::iterator, bool> result =
+ this->relaxed_input_sections_by_id_.insert(value);
+ gold_assert(value.second);
+ }
+
+ private:
+ typedef Unordered_map<Const_section_id, Output_merge_base*,
+ Const_section_id_hash>
+ Merge_sections_by_id;
+
+ typedef Unordered_map<Merge_section_properties, Output_merge_base*,
+ Merge_section_properties::hash,
+ Merge_section_properties::equal_to>
+ Merge_sections_by_properties;
+
+ typedef Unordered_map<Const_section_id, Output_relaxed_input_section*,
+ Const_section_id_hash>
+ Relaxed_input_sections_by_id;
+
+ // Whether this is valid
+ bool is_valid_;
+ // Merge sections by merge section properties.
+ Merge_sections_by_properties merge_sections_by_properties_;
+ // Merge sections by section IDs.
+ Merge_sections_by_id merge_sections_by_id_;
+ // Relaxed sections by section IDs.
+ Relaxed_input_sections_by_id relaxed_input_sections_by_id_;
+};
+
// An output section. We don't expect to have too many output
// sections, so we don't bother to do a template on the size.
@@ -2766,263 +2948,6 @@ class Output_section : public Output_data
// The next few calls are for linker script support.
- // We need to export the input sections to linker scripts. Previously
- // we export a pair of Relobj pointer and section index. We now need to
- // handle relaxed input sections as well. So we use this class.
- class Simple_input_section
- {
- private:
- static const unsigned int invalid_shndx = static_cast<unsigned int>(-1);
-
- public:
- Simple_input_section(Relobj *relobj, unsigned int shndx)
- : shndx_(shndx)
- {
- gold_assert(shndx != invalid_shndx);
- this->u_.relobj = relobj;
- }
-
- Simple_input_section(Output_relaxed_input_section* section)
- : shndx_(invalid_shndx)
- { this->u_.relaxed_input_section = section; }
-
- // Whether this is a relaxed section.
- bool
- is_relaxed_input_section() const
- { return this->shndx_ == invalid_shndx; }
-
- // Return object of an input section.
- Relobj*
- relobj() const
- {
- return ((this->shndx_ != invalid_shndx)
- ? this->u_.relobj
- : this->u_.relaxed_input_section->relobj());
- }
-
- // Return index of an input section.
- unsigned int
- shndx() const
- {
- return ((this->shndx_ != invalid_shndx)
- ? this->shndx_
- : this->u_.relaxed_input_section->shndx());
- }
-
- // Return the Output_relaxed_input_section object of a relaxed section.
- Output_relaxed_input_section*
- relaxed_input_section() const
- {
- gold_assert(this->shndx_ == invalid_shndx);
- return this->u_.relaxed_input_section;
- }
-
- private:
- // Pointer to either an Relobj or an Output_relaxed_input_section.
- union
- {
- Relobj* relobj;
- Output_relaxed_input_section* relaxed_input_section;
- } u_;
- // Section index for an non-relaxed section or invalid_shndx for
- // a relaxed section.
- unsigned int shndx_;
- };
-
- // Store the list of input sections for this Output_section into the
- // list passed in. This removes the input sections, leaving only
- // any Output_section_data elements. This returns the size of those
- // Output_section_data elements. ADDRESS is the address of this
- // output section. FILL is the fill value to use, in case there are
- // any spaces between the remaining Output_section_data elements.
- uint64_t
- get_input_sections(uint64_t address, const std::string& fill,
- std::list<Simple_input_section>*);
-
- // Add a simple input section.
- void
- add_simple_input_section(const Simple_input_section& input_section,
- off_t data_size, uint64_t addralign);
-
- // Set the current size of the output section.
- void
- set_current_data_size(off_t size)
- { this->set_current_data_size_for_child(size); }
-
- // Get the current size of the output section.
- off_t
- current_data_size() const
- { return this->current_data_size_for_child(); }
-
- // End of linker script support.
-
- // Save states before doing section layout.
- // This is used for relaxation.
- void
- save_states();
-
- // Restore states prior to section layout.
- void
- restore_states();
-
- // Discard states.
- void
- discard_states();
-
- // Convert existing input sections to relaxed input sections.
- void
- convert_input_sections_to_relaxed_sections(
- const std::vector<Output_relaxed_input_section*>& sections);
-
- // Find a relaxed input section to an input section in OBJECT
- // with index SHNDX. Return NULL if none is found.
- const Output_relaxed_input_section*
- find_relaxed_input_section(const Relobj* object, unsigned int shndx) const;
-
- // Whether section offsets need adjustment due to relaxation.
- bool
- section_offsets_need_adjustment() const
- { return this->section_offsets_need_adjustment_; }
-
- // Set section_offsets_need_adjustment to be true.
- void
- set_section_offsets_need_adjustment()
- { this->section_offsets_need_adjustment_ = true; }
-
- // Adjust section offsets of input sections in this. This is
- // requires if relaxation caused some input sections to change sizes.
- void
- adjust_section_offsets();
-
- // Whether this is a NOLOAD section.
- bool
- is_noload() const
- { return this->is_noload_; }
-
- // Set NOLOAD flag.
- void
- set_is_noload()
- { this->is_noload_ = true; }
-
- // Print merge statistics to stderr.
- void
- print_merge_stats();
-
- protected:
- // Return the output section--i.e., the object itself.
- Output_section*
- do_output_section()
- { return this; }
-
- const Output_section*
- do_output_section() const
- { return this; }
-
- // Return the section index in the output file.
- unsigned int
- do_out_shndx() const
- {
- gold_assert(this->out_shndx_ != -1U);
- return this->out_shndx_;
- }
-
- // Set the output section index.
- void
- do_set_out_shndx(unsigned int shndx)
- {
- gold_assert(this->out_shndx_ == -1U || this->out_shndx_ == shndx);
- this->out_shndx_ = shndx;
- }
-
- // Set the final data size of the Output_section. For a typical
- // Output_section, there is nothing to do, but if there are any
- // Output_section_data objects we need to set their final addresses
- // here.
- virtual void
- set_final_data_size();
-
- // Reset the address and file offset.
- void
- do_reset_address_and_file_offset();
-
- // Return true if address and file offset already have reset values. In
- // other words, calling reset_address_and_file_offset will not change them.
- bool
- do_address_and_file_offset_have_reset_values() const;
-
- // Write the data to the file. For a typical Output_section, this
- // does nothing: the data is written out by calling Object::Relocate
- // on each input object. But if there are any Output_section_data
- // objects we do need to write them out here.
- virtual void
- do_write(Output_file*);
-
- // Return the address alignment--function required by parent class.
- uint64_t
- do_addralign() const
- { return this->addralign_; }
-
- // Return whether there is a load address.
- bool
- do_has_load_address() const
- { return this->has_load_address_; }
-
- // Return the load address.
- uint64_t
- do_load_address() const
- {
- gold_assert(this->has_load_address_);
- return this->load_address_;
- }
-
- // Return whether this is an Output_section.
- bool
- do_is_section() const
- { return true; }
-
- // Return whether this is a section of the specified type.
- bool
- do_is_section_type(elfcpp::Elf_Word type) const
- { return this->type_ == type; }
-
- // Return whether the specified section flag is set.
- bool
- do_is_section_flag_set(elfcpp::Elf_Xword flag) const
- { return (this->flags_ & flag) != 0; }
-
- // Set the TLS offset. Called only for SHT_TLS sections.
- void
- do_set_tls_offset(uint64_t tls_base);
-
- // Return the TLS offset, relative to the base of the TLS segment.
- // Valid only for SHT_TLS sections.
- uint64_t
- do_tls_offset() const
- { return this->tls_offset_; }
-
- // This may be implemented by a child class.
- virtual void
- do_finalize_name(Layout*)
- { }
-
- // Print to the map file.
- virtual void
- do_print_to_mapfile(Mapfile*) const;
-
- // Record that this section requires postprocessing after all
- // relocations have been applied. This is called by a child class.
- void
- set_requires_postprocessing()
- {
- this->requires_postprocessing_ = true;
- this->after_input_sections_ = true;
- }
-
- // Write all the data of an Output_section into the postprocessing
- // buffer.
- void
- write_to_postprocessing_buffer();
-
// In some cases we need to keep a list of the input sections
// associated with this output section. We only need the list if we
// might have to change the offsets of the input section within the
@@ -3088,13 +3013,29 @@ class Output_section : public Output_data
uint64_t
addralign() const
{
- if (!this->is_input_section())
+ if (this->p2align_ != 0)
+ return static_cast<uint64_t>(1) << (this->p2align_ - 1);
+ else if (!this->is_input_section())
return this->u2_.posd->addralign();
- return (this->p2align_ == 0
- ? 0
- : static_cast<uint64_t>(1) << (this->p2align_ - 1));
+ else
+ return 0;
}
+ // Set the required alignment, which must be either 0 or a power of 2.
+ // For input sections that are sub-classes of Output_section_data, a
+ // alignment of zero means asking the underlying object for alignment.
+ void
+ set_addralign(uint64_t addralign)
+ {
+ if (addralign == 0)
+ this->p2align_ = 0;
+ else
+ {
+ gold_assert((addralign & (addralign - 1)) == 0);
+ this->p2align_ = ffsll(static_cast<long long>(addralign));
+ }
+ }
+
// Return the required size.
off_t
data_size() const;
@@ -3122,6 +3063,14 @@ class Output_section : public Output_data
&& this->addralign() == addralign);
}
+ // Return whether this is a merge section for some input section.
+ bool
+ is_merge_section() const
+ {
+ return (this->shndx_ == MERGE_DATA_SECTION_CODE
+ || this->shndx_ == MERGE_STRING_SECTION_CODE);
+ }
+
// Return whether this is a relaxed input section.
bool
is_relaxed_input_section() const
@@ -3136,27 +3085,11 @@ class Output_section : public Output_data
// Return the object for an input section.
Relobj*
- relobj() const
- {
- if (this->is_input_section())
- return this->u2_.object;
- else if (this->is_relaxed_input_section())
- return this->u2_.poris->relobj();
- else
- gold_unreachable();
- }
+ relobj() const;
// Return the input section index for an input section.
unsigned int
- shndx() const
- {
- if (this->is_input_section())
- return this->shndx_;
- else if (this->is_relaxed_input_section())
- return this->u2_.poris->shndx();
- else
- gold_unreachable();
- }
+ shndx() const;
// For non-input-sections, return the associated Output_section_data
// object.
@@ -3167,6 +3100,14 @@ class Output_section : public Output_data
return this->u2_.posd;
}
+ // For a merge section, return the Output_merge_base pointer.
+ Output_merge_base*
+ output_merge_base() const
+ {
+ gold_assert(this->is_merge_section());
+ return this->u2_.pomb;
+ }
+
// Return the Output_relaxed_input_section object.
Output_relaxed_input_section*
relaxed_input_section() const
@@ -3289,11 +3230,206 @@ class Output_section : public Output_data
// For OUTPUT_SECTION_CODE or MERGE_DATA_SECTION_CODE or
// MERGE_STRING_SECTION_CODE, the data.
Output_section_data* posd;
+ Output_merge_base* pomb;
// For RELAXED_INPUT_SECTION_CODE, the data.
Output_relaxed_input_section* poris;
} u2_;
};
+ // Store the list of input sections for this Output_section into the
+ // list passed in. This removes the input sections, leaving only
+ // any Output_section_data elements. This returns the size of those
+ // Output_section_data elements. ADDRESS is the address of this
+ // output section. FILL is the fill value to use, in case there are
+ // any spaces between the remaining Output_section_data elements.
+ uint64_t
+ get_input_sections(uint64_t address, const std::string& fill,
+ std::list<Input_section>*);
+
+ // Add a script input section. A script input section can either be
+ // a plain input section or a sub-class of Output_section_data.
+ void
+ add_script_input_section(const Input_section& input_section);
+
+ // Set the current size of the output section.
+ void
+ set_current_data_size(off_t size)
+ { this->set_current_data_size_for_child(size); }
+
+ // Get the current size of the output section.
+ off_t
+ current_data_size() const
+ { return this->current_data_size_for_child(); }
+
+ // End of linker script support.
+
+ // Save states before doing section layout.
+ // This is used for relaxation.
+ void
+ save_states();
+
+ // Restore states prior to section layout.
+ void
+ restore_states();
+
+ // Discard states.
+ void
+ discard_states();
+
+ // Convert existing input sections to relaxed input sections.
+ void
+ convert_input_sections_to_relaxed_sections(
+ const std::vector<Output_relaxed_input_section*>& sections);
+
+ // Find a relaxed input section to an input section in OBJECT
+ // with index SHNDX. Return NULL if none is found.
+ const Output_relaxed_input_section*
+ find_relaxed_input_section(const Relobj* object, unsigned int shndx) const;
+
+ // Whether section offsets need adjustment due to relaxation.
+ bool
+ section_offsets_need_adjustment() const
+ { return this->section_offsets_need_adjustment_; }
+
+ // Set section_offsets_need_adjustment to be true.
+ void
+ set_section_offsets_need_adjustment()
+ { this->section_offsets_need_adjustment_ = true; }
+
+ // Adjust section offsets of input sections in this. This is
+ // requires if relaxation caused some input sections to change sizes.
+ void
+ adjust_section_offsets();
+
+ // Whether this is a NOLOAD section.
+ bool
+ is_noload() const
+ { return this->is_noload_; }
+
+ // Set NOLOAD flag.
+ void
+ set_is_noload()
+ { this->is_noload_ = true; }
+
+ // Print merge statistics to stderr.
+ void
+ print_merge_stats();
+
+ protected:
+ // Return the output section--i.e., the object itself.
+ Output_section*
+ do_output_section()
+ { return this; }
+
+ const Output_section*
+ do_output_section() const
+ { return this; }
+
+ // Return the section index in the output file.
+ unsigned int
+ do_out_shndx() const
+ {
+ gold_assert(this->out_shndx_ != -1U);
+ return this->out_shndx_;
+ }
+
+ // Set the output section index.
+ void
+ do_set_out_shndx(unsigned int shndx)
+ {
+ gold_assert(this->out_shndx_ == -1U || this->out_shndx_ == shndx);
+ this->out_shndx_ = shndx;
+ }
+
+ // Set the final data size of the Output_section. For a typical
+ // Output_section, there is nothing to do, but if there are any
+ // Output_section_data objects we need to set their final addresses
+ // here.
+ virtual void
+ set_final_data_size();
+
+ // Reset the address and file offset.
+ void
+ do_reset_address_and_file_offset();
+
+ // Return true if address and file offset already have reset values. In
+ // other words, calling reset_address_and_file_offset will not change them.
+ bool
+ do_address_and_file_offset_have_reset_values() const;
+
+ // Write the data to the file. For a typical Output_section, this
+ // does nothing: the data is written out by calling Object::Relocate
+ // on each input object. But if there are any Output_section_data
+ // objects we do need to write them out here.
+ virtual void
+ do_write(Output_file*);
+
+ // Return the address alignment--function required by parent class.
+ uint64_t
+ do_addralign() const
+ { return this->addralign_; }
+
+ // Return whether there is a load address.
+ bool
+ do_has_load_address() const
+ { return this->has_load_address_; }
+
+ // Return the load address.
+ uint64_t
+ do_load_address() const
+ {
+ gold_assert(this->has_load_address_);
+ return this->load_address_;
+ }
+
+ // Return whether this is an Output_section.
+ bool
+ do_is_section() const
+ { return true; }
+
+ // Return whether this is a section of the specified type.
+ bool
+ do_is_section_type(elfcpp::Elf_Word type) const
+ { return this->type_ == type; }
+
+ // Return whether the specified section flag is set.
+ bool
+ do_is_section_flag_set(elfcpp::Elf_Xword flag) const
+ { return (this->flags_ & flag) != 0; }
+
+ // Set the TLS offset. Called only for SHT_TLS sections.
+ void
+ do_set_tls_offset(uint64_t tls_base);
+
+ // Return the TLS offset, relative to the base of the TLS segment.
+ // Valid only for SHT_TLS sections.
+ uint64_t
+ do_tls_offset() const
+ { return this->tls_offset_; }
+
+ // This may be implemented by a child class.
+ virtual void
+ do_finalize_name(Layout*)
+ { }
+
+ // Print to the map file.
+ virtual void
+ do_print_to_mapfile(Mapfile*) const;
+
+ // Record that this section requires postprocessing after all
+ // relocations have been applied. This is called by a child class.
+ void
+ set_requires_postprocessing()
+ {
+ this->requires_postprocessing_ = true;
+ this->after_input_sections_ = true;
+ }
+
+ // Write all the data of an Output_section into the postprocessing
+ // buffer.
+ void
+ write_to_postprocessing_buffer();
+
typedef std::vector<Input_section> Input_section_list;
// Allow a child class to access the input sections.
@@ -3436,78 +3572,6 @@ class Output_section : public Output_data
typedef std::vector<Fill> Fill_list;
- // This class describes properties of merge data sections. It is used
- // as a key type for maps.
- class Merge_section_properties
- {
- public:
- Merge_section_properties(bool is_string, uint64_t entsize,
- uint64_t addralign)
- : is_string_(is_string), entsize_(entsize), addralign_(addralign)
- { }
-
- // Whether this equals to another Merge_section_properties MSP.
- bool
- eq(const Merge_section_properties& msp) const
- {
- return ((this->is_string_ == msp.is_string_)
- && (this->entsize_ == msp.entsize_)
- && (this->addralign_ == msp.addralign_));
- }
-
- // Compute a hash value for this using 64-bit FNV-1a hash.
- size_t
- hash_value() const
- {
- uint64_t h = 14695981039346656037ULL; // FNV offset basis.
- uint64_t prime = 1099511628211ULL;
- h = (h ^ static_cast<uint64_t>(this->is_string_)) * prime;
- h = (h ^ static_cast<uint64_t>(this->entsize_)) * prime;
- h = (h ^ static_cast<uint64_t>(this->addralign_)) * prime;
- return h;
- }
-
- // Functors for associative containers.
- struct equal_to
- {
- bool
- operator()(const Merge_section_properties& msp1,
- const Merge_section_properties& msp2) const
- { return msp1.eq(msp2); }
- };
-
- struct hash
- {
- size_t
- operator()(const Merge_section_properties& msp) const
- { return msp.hash_value(); }
- };
-
- private:
- // Whether this merge data section is for strings.
- bool is_string_;
- // Entsize of this merge data section.
- uint64_t entsize_;
- // Address alignment.
- uint64_t addralign_;
- };
-
- // Map that link Merge_section_properties to Output_merge_base.
- typedef Unordered_map<Merge_section_properties, Output_merge_base*,
- Merge_section_properties::hash,
- Merge_section_properties::equal_to>
- Merge_section_by_properties_map;
-
- // Map that link Const_section_id to Output_section_data.
- typedef Unordered_map<Const_section_id, Output_section_data*,
- Const_section_id_hash>
- Output_section_data_by_input_section_map;
-
- // Map that link Const_section_id to Output_relaxed_input_section.
- typedef Unordered_map<Const_section_id, Output_relaxed_input_section*,
- Const_section_id_hash>
- Output_relaxed_input_section_by_input_section_map;
-
// Map used during relaxation of existing sections. This map
// a section id an input section list index. We assume that
// Input_section_list is a vector.
@@ -3518,10 +3582,12 @@ class Output_section : public Output_data
add_output_section_data(Input_section*);
// Add an SHF_MERGE input section. Returns true if the section was
- // handled.
+ // handled. If KEEPS_INPUT_SECTIONS is true, the output merge section
+ // stores information about the merged input sections.
bool
add_merge_input_section(Relobj* object, unsigned int shndx, uint64_t flags,
- uint64_t entsize, uint64_t addralign);
+ uint64_t entsize, uint64_t addralign,
+ bool keeps_input_sections);
// Add an output SHF_MERGE section POSD to this output section.
// IS_STRING indicates whether it is a SHF_STRINGS section, and
@@ -3554,6 +3620,10 @@ class Output_section : public Output_data
const Relaxation_map& map,
Input_section_list* input_sections);
+ // Build the lookup maps for merge and relaxed input sections.
+ void
+ build_lookup_maps() const;
+
// Most of these fields are only valid after layout.
// The name of the section. This will point into a Stringpool.
@@ -3676,17 +3746,8 @@ class Output_section : public Output_data
uint64_t tls_offset_;
// Saved checkpoint.
Checkpoint_output_section* checkpoint_;
- // Map from input sections to merge sections.
- Output_section_data_by_input_section_map merge_section_map_;
- // Map from merge section properties to merge_sections;
- Merge_section_by_properties_map merge_section_by_properties_map_;
- // Map from input sections to relaxed input sections. This is mutable
- // because it is updated lazily. We may need to update it in a
- // const qualified method.
- mutable Output_relaxed_input_section_by_input_section_map
- relaxed_input_section_map_;
- // Whether relaxed_input_section_map_ is valid.
- mutable bool is_relaxed_input_section_map_valid_;
+ // Fast lookup maps for merged and relaxed input sections.
+ Output_section_lookup_maps* lookup_maps_;
};
// An output segment. PT_LOAD segments are built from collections of
diff --git a/binutils-2.19/gold/script-sections.cc b/binutils-2.19/gold/script-sections.cc
index 99f0dbf9..5cfb07c4 100644
--- a/binutils-2.19/gold/script-sections.cc
+++ b/binutils-2.19/gold/script-sections.cc
@@ -525,7 +525,7 @@ class Output_section_element
{
public:
// A list of input sections.
- typedef std::list<Output_section::Simple_input_section> Input_section_list;
+ typedef std::list<Output_section::Input_section> Input_section_list;
Output_section_element()
{ }
@@ -1172,13 +1172,13 @@ Output_section_element_input::match_name(const char* file_name,
class Input_section_info
{
public:
- Input_section_info(const Output_section::Simple_input_section& input_section)
+ Input_section_info(const Output_section::Input_section& input_section)
: input_section_(input_section), section_name_(),
size_(0), addralign_(1)
{ }
// Return the simple input section.
- const Output_section::Simple_input_section&
+ const Output_section::Input_section&
input_section() const
{ return this->input_section_; }
@@ -1224,7 +1224,7 @@ class Input_section_info
private:
// Input section, can be a relaxed section.
- Output_section::Simple_input_section input_section_;
+ Output_section::Input_section input_section_;
// Name of the section.
std::string section_name_;
// Section size.
@@ -1394,9 +1394,20 @@ Output_section_element_input::set_section_addresses(
p != matching_sections[i].end();
++p)
{
- uint64_t this_subalign = p->addralign();
+ // Override the original address alignment if SUBALIGN is specified
+ // and is greater than the original alignment. We need to make a
+ // copy of the input section to modify the alignment.
+ Output_section::Input_section sis(p->input_section());
+
+ uint64_t this_subalign = sis.addralign();
+ if (!sis.is_input_section())
+ sis.output_section_data()->finalize_data_size();
+ uint64_t data_size = sis.data_size();
if (this_subalign < subalign)
- this_subalign = subalign;
+ {
+ this_subalign = subalign;
+ sis.set_addralign(subalign);
+ }
uint64_t address = align_address(dot, this_subalign);
@@ -1410,11 +1421,8 @@ Output_section_element_input::set_section_addresses(
layout->new_output_section_data_from_script(posd);
}
- output_section->add_simple_input_section(p->input_section(),
- p->size(),
- this_subalign);
-
- dot = address + p->size();
+ output_section->add_script_input_section(sis);
+ dot = address + data_size;
}
}
@@ -2351,7 +2359,7 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*,
uint64_t* dot_value,
uint64_t* load_address)
{
- typedef std::list<Output_section::Simple_input_section> Input_section_list;
+ typedef std::list<Output_section::Input_section> Input_section_list;
bool have_load_address = *load_address != *dot_value;
@@ -2373,25 +2381,12 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*,
p != input_sections.end();
++p)
{
- uint64_t addralign;
- uint64_t size;
-
- // We know what are single-threaded, so it is OK to lock the
- // object.
- {
- const Task* task = reinterpret_cast<const Task*>(-1);
- Task_lock_obj<Object> tl(task, p->relobj());
- addralign = p->relobj()->section_addralign(p->shndx());
- if (p->is_relaxed_input_section())
- // We use current data size because relxed section sizes may not
- // have finalized yet.
- size = p->relaxed_input_section()->current_data_size();
- else
- size = p->relobj()->section_size(p->shndx());
- }
-
+ uint64_t addralign = p->addralign();
+ if (!p->is_input_section())
+ p->output_section_data()->finalize_data_size();
+ uint64_t size = p->data_size();
address = align_address(address, addralign);
- this->os_->add_simple_input_section(*p, size, addralign);
+ this->os_->add_script_input_section(*p);
address += size;
}
diff --git a/binutils-2.19/gold/target-reloc.h b/binutils-2.19/gold/target-reloc.h
index 510eea05..0bd060b4 100644
--- a/binutils-2.19/gold/target-reloc.h
+++ b/binutils-2.19/gold/target-reloc.h
@@ -515,7 +515,7 @@ relocate_for_relocatable(
const Relocatable_relocs* rr,
unsigned char* view,
typename elfcpp::Elf_types<size>::Elf_Addr view_address,
- section_size_type,
+ section_size_type view_size,
unsigned char* reloc_view,
section_size_type reloc_view_size)
{
@@ -537,6 +537,19 @@ relocate_for_relocatable(
if (strategy == Relocatable_relocs::RELOC_DISCARD)
continue;
+ if (strategy == Relocatable_relocs::RELOC_SPECIAL)
+ {
+ // Target wants to handle this relocation.
+ Sized_target<size, big_endian>* target =
+ parameters->sized_target<size, big_endian>();
+ target->relocate_special_relocatable(relinfo, sh_type, prelocs,
+ i, output_section,
+ offset_in_output_section,
+ view, view_address,
+ view_size, pwrite);
+ pwrite += reloc_size;
+ continue;
+ }
Reltype reloc(prelocs);
Reltype_write reloc_write(pwrite);
diff --git a/binutils-2.19/gold/target.h b/binutils-2.19/gold/target.h
index 7429b638..02cbee2f 100644
--- a/binutils-2.19/gold/target.h
+++ b/binutils-2.19/gold/target.h
@@ -673,7 +673,37 @@ class Sized_target : public Target
section_size_type view_size,
unsigned char* reloc_view,
section_size_type reloc_view_size) = 0;
+
+ // Perform target-specific processing in a relocatable link. This is
+ // only used if we use the relocation strategy RELOC_SPECIAL.
+ // RELINFO points to a Relocation_info structure. SH_TYPE is the relocation
+ // section type. PRELOC_IN points to the original relocation. RELNUM is
+ // the index number of the relocation in the relocation section.
+ // OUTPUT_SECTION is the output section to which the relocation is applied.
+ // OFFSET_IN_OUTPUT_SECTION is the offset of the relocation input section
+ // within the output section. VIEW points to the output view of the
+ // output section. VIEW_ADDRESS is output address of the view. VIEW_SIZE
+ // is the size of the output view and PRELOC_OUT points to the new
+ // relocation in the output object.
+ //
+ // A target only needs to override this if the generic code in
+ // target-reloc.h cannot handle some relocation types.
+ virtual void
+ relocate_special_relocatable(const Relocate_info<size, big_endian>*
+ /*relinfo */,
+ unsigned int /* sh_type */,
+ const unsigned char* /* preloc_in */,
+ size_t /* relnum */,
+ Output_section* /* output_section */,
+ off_t /* offset_in_output_section */,
+ unsigned char* /* view */,
+ typename elfcpp::Elf_types<size>::Elf_Addr
+ /* view_address */,
+ section_size_type /* view_size */,
+ unsigned char* /* preloc_out*/)
+ { gold_unreachable(); }
+
protected:
Sized_target(const Target::Target_info* pti)
: Target(pti)
diff --git a/binutils-2.19/ld/Makefile.am b/binutils-2.19/ld/Makefile.am
index 0093c88e..3ba9d8cd 100644
--- a/binutils-2.19/ld/Makefile.am
+++ b/binutils-2.19/ld/Makefile.am
@@ -90,7 +90,8 @@ CXX_FOR_TARGET = ` \
fi; \
fi`
-noinst_PROGRAMS = ld-new
+transform = s/^ld-new$$/$(installed_linker)/;@program_transform_name@
+bin_PROGRAMS = ld-new
info_TEXINFOS = ld.texinfo
ld_TEXINFOS = configdoc.texi
noinst_TEXINFOS = ldint.texinfo
@@ -1887,21 +1888,25 @@ install-html-recursive:
.PHONY: install-exec-local install-data-local
-install-exec-local: ld-new$(EXEEXT)
- $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(tooldir)/bin
- @list='$(noinst_PROGRAMS)'; for p in $$list; do \
- if test -f $$p; then \
- echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
- $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
- else :; fi; \
- done
- n=`echo ld | sed '$(transform)'`; \
- if [ "$(bindir)/$$n$(EXEEXT)" != "$(tooldir)/bin/ld$(EXEEXT)" ]; then \
- rm -f $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
- ln $(DESTDIR)$(bindir)/$$n$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT) >/dev/null 2>/dev/null \
- || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
- fi
-
+install-exec-local: ld-new$(EXEEXT) install-binPROGRAMS
+ $(mkinstalldirs) $(DESTDIR)$(tooldir)/bin
+ n=`echo $(installed_linker) | sed '$(transform)'`; \
+ if test "$(bindir)" != "$(tooldir)/bin"; then \
+ rm -f $(DESTDIR)$(tooldir)/bin/$(installed_linker)$(EXEEXT); \
+ ln $(DESTDIR)$(bindir)/$$n$(EXEEXT) $(DESTDIR)$(tooldir)/bin/$(installed_linker)$(EXEEXT) >/dev/null 2>/dev/null \
+ || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(tooldir)/bin/$(installed_linker)$(EXEEXT); \
+ fi; \
+ if test "x$(install_as_default)" = "xyes"; then \
+ ld=`echo ld | sed '$(transform)'`; \
+ rm -f $(DESTDIR)$(bindir)/$$ld$(EXEEXT); \
+ ln $(DESTDIR)$(bindir)/$$n$(EXEEXT) $(DESTDIR)$(bindir)/$$ld$(EXEEXT) >/dev/null 2>/dev/null \
+ || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(bindir)/$$ld$(EXEEXT); \
+ if test "$(bindir)" != "$(tooldir)/bin"; then \
+ rm -f $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
+ ln $(DESTDIR)$(bindir)/$$n$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT) >/dev/null 2>/dev/null \
+ || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
+ fi; \
+ fi
install-data-local:
$(mkinstalldirs) $(DESTDIR)$(scriptdir)/ldscripts
for f in ldscripts/*; do \
diff --git a/binutils-2.19/ld/Makefile.in b/binutils-2.19/ld/Makefile.in
index 309e8e68..720c82b5 100644
--- a/binutils-2.19/ld/Makefile.in
+++ b/binutils-2.19/ld/Makefile.in
@@ -27,7 +27,6 @@ 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 = :
@@ -37,7 +36,7 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
-noinst_PROGRAMS = ld-new$(EXEEXT)
+bin_PROGRAMS = ld-new$(EXEEXT)
# Automake 1.9 will only build info files in the objdir if they are
# mentioned in DISTCLEANFILES. It doesn't have to be unconditional,
@@ -74,7 +73,9 @@ 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)
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
am_ld_new_OBJECTS = ldgram.$(OBJEXT) ldlex.$(OBJEXT) lexsup.$(OBJEXT) \
ldlang.$(OBJEXT) mri.$(OBJEXT) ldctor.$(OBJEXT) \
ldmain.$(OBJEXT) ldwrite.$(OBJEXT) ldexp.$(OBJEXT) \
@@ -121,7 +122,6 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
pdf-recursive ps-recursive uninstall-info-recursive \
uninstall-recursive
man1dir = $(mandir)/man1
-am__installdirs = "$(DESTDIR)$(man1dir)"
NROFF = nroff
MANS = $(man_MANS)
ETAGS = etags
@@ -129,6 +129,7 @@ CTAGS = ctags
DEJATOOL = $(PACKAGE)
RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir
DIST_SUBDIRS = $(SUBDIRS)
+transform = s/^ld-new$$/$(installed_linker)/;@program_transform_name@
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
@@ -262,7 +263,9 @@ host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
+install_as_default = @install_as_default@
install_sh = @install_sh@
+installed_linker = @installed_linker@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
@@ -789,9 +792,30 @@ distclean-hdr:
-rm -f config.h stamp-h1
po/Makefile.in: $(top_builddir)/config.status $(top_srcdir)/po/Make-in
cd $(top_builddir) && $(SHELL) ./config.status $@
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ || test -f $$p1 \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
-clean-noinstPROGRAMS:
- @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
echo " rm -f $$p $$f"; \
rm -f $$p $$f ; \
@@ -1144,7 +1168,7 @@ check: check-recursive
all-am: Makefile $(PROGRAMS) $(MANS) config.h
installdirs: installdirs-recursive
installdirs-am:
- for dir in "$(DESTDIR)$(man1dir)"; do \
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \
test -z "$$dir" || $(mkdir_p) "$$dir"; \
done
install: install-recursive
@@ -1182,8 +1206,7 @@ maintainer-clean-generic:
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-recursive
-clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
- mostlyclean-am
+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
distclean: distclean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
@@ -1206,7 +1229,7 @@ info-am: $(INFO_DEPS)
install-data-am: install-data-local install-man
-install-exec-am: install-exec-local
+install-exec-am: install-binPROGRAMS install-exec-local
install-info: install-info-recursive
@@ -1264,29 +1287,30 @@ ps: ps-recursive
ps-am: $(PSS)
-uninstall-am: uninstall-man
+uninstall-am: uninstall-binPROGRAMS uninstall-man
uninstall-info: uninstall-info-recursive
uninstall-man: uninstall-man1
.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \
- check-DEJAGNU check-am clean clean-generic clean-info \
- clean-libtool clean-noinstPROGRAMS clean-recursive ctags \
- ctags-recursive dist-info distclean distclean-DEJAGNU \
- distclean-compile distclean-generic distclean-hdr \
- distclean-libtool distclean-local distclean-recursive \
- distclean-tags 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-man1 install-strip \
- installcheck installcheck-am installdirs installdirs-am \
- maintainer-clean maintainer-clean-aminfo \
- maintainer-clean-generic maintainer-clean-recursive \
- mostlyclean mostlyclean-aminfo mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool mostlyclean-local \
- mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \
- uninstall uninstall-am uninstall-info-am uninstall-man \
+ check-DEJAGNU check-am clean clean-binPROGRAMS clean-generic \
+ clean-info clean-libtool clean-recursive ctags ctags-recursive \
+ dist-info distclean distclean-DEJAGNU distclean-compile \
+ distclean-generic distclean-hdr distclean-libtool \
+ distclean-local distclean-recursive distclean-tags dvi dvi-am \
+ html html-am info info-am install install-am \
+ install-binPROGRAMS install-data install-data-am \
+ install-data-local install-exec install-exec-am \
+ install-exec-local install-info install-info-am install-man \
+ install-man1 install-strip installcheck installcheck-am \
+ installdirs installdirs-am maintainer-clean \
+ maintainer-clean-aminfo maintainer-clean-generic \
+ maintainer-clean-recursive mostlyclean mostlyclean-aminfo \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ mostlyclean-local mostlyclean-recursive pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am \
+ uninstall-binPROGRAMS uninstall-info-am uninstall-man \
uninstall-man1
@@ -2693,21 +2717,25 @@ install-html-recursive:
.PHONY: install-exec-local install-data-local
-install-exec-local: ld-new$(EXEEXT)
- $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(tooldir)/bin
- @list='$(noinst_PROGRAMS)'; for p in $$list; do \
- if test -f $$p; then \
- echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
- $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
- else :; fi; \
- done
- n=`echo ld | sed '$(transform)'`; \
- if [ "$(bindir)/$$n$(EXEEXT)" != "$(tooldir)/bin/ld$(EXEEXT)" ]; then \
- rm -f $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
- ln $(DESTDIR)$(bindir)/$$n$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT) >/dev/null 2>/dev/null \
- || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
- fi
-
+install-exec-local: ld-new$(EXEEXT) install-binPROGRAMS
+ $(mkinstalldirs) $(DESTDIR)$(tooldir)/bin
+ n=`echo $(installed_linker) | sed '$(transform)'`; \
+ if test "$(bindir)" != "$(tooldir)/bin"; then \
+ rm -f $(DESTDIR)$(tooldir)/bin/$(installed_linker)$(EXEEXT); \
+ ln $(DESTDIR)$(bindir)/$$n$(EXEEXT) $(DESTDIR)$(tooldir)/bin/$(installed_linker)$(EXEEXT) >/dev/null 2>/dev/null \
+ || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(tooldir)/bin/$(installed_linker)$(EXEEXT); \
+ fi; \
+ if test "x$(install_as_default)" = "xyes"; then \
+ ld=`echo ld | sed '$(transform)'`; \
+ rm -f $(DESTDIR)$(bindir)/$$ld$(EXEEXT); \
+ ln $(DESTDIR)$(bindir)/$$n$(EXEEXT) $(DESTDIR)$(bindir)/$$ld$(EXEEXT) >/dev/null 2>/dev/null \
+ || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(bindir)/$$ld$(EXEEXT); \
+ if test "$(bindir)" != "$(tooldir)/bin"; then \
+ rm -f $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
+ ln $(DESTDIR)$(bindir)/$$n$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT) >/dev/null 2>/dev/null \
+ || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
+ fi; \
+ fi
install-data-local:
$(mkinstalldirs) $(DESTDIR)$(scriptdir)/ldscripts
for f in ldscripts/*; do \
diff --git a/binutils-2.19/ld/configure b/binutils-2.19/ld/configure
index c0ad08b5..eb7cb9c5 100755
--- a/binutils-2.19/ld/configure
+++ b/binutils-2.19/ld/configure
@@ -458,7 +458,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 CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT 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 DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE use_sysroot TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE WARN_CFLAGS NO_WERROR CPP EGREP LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN NM LN_S AR ac_ct_AR RANLIB ac_ct_RANLIB lt_ECHO USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE YACC LEX LEXLIB LEX_OUTPUT_ROOT MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT GENINSRC_NEVER_TRUE GENINSRC_NEVER_FALSE HDEFINES HOSTING_CRT0 HOSTING_LIBS NATIVE_LIB_DIRS STRINGIFY EMUL EMULATION_OFILES EMUL_EXTRA_OFILES LIB_PATH EMULATION_LIBPATH TESTBFDLIB datarootdir docdir htmldir 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 CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT 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 DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE use_sysroot TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE install_as_default installed_linker WARN_CFLAGS NO_WERROR CPP EGREP LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN NM LN_S AR ac_ct_AR RANLIB ac_ct_RANLIB lt_ECHO USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE YACC LEX LEXLIB LEX_OUTPUT_ROOT MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT GENINSRC_NEVER_TRUE GENINSRC_NEVER_FALSE HDEFINES HOSTING_CRT0 HOSTING_LIBS NATIVE_LIB_DIRS STRINGIFY EMUL EMULATION_OFILES EMUL_EXTRA_OFILES LIB_PATH EMULATION_LIBPATH TESTBFDLIB datarootdir docdir htmldir LIBOBJS LTLIBOBJS'
ac_subst_files='TDIRS'
ac_pwd=`pwd`
@@ -1004,6 +1004,7 @@ Optional Features:
--enable-dependency-tracking do not reject slow dependency extractors
--enable-targets alternative target configurations
--enable-64-bit-bfd 64-bit support (on hosts with narrower word sizes)
+ --enable-gold[=ARG] build gold [ARG={both}[/{gold,ld}]]
--enable-got=<type> GOT handling scheme (target, single, negative,
multigot)
--enable-werror treat compile warnings as errors
@@ -3340,6 +3341,31 @@ fi;
+# Check whether --enable-gold or --disable-gold was given.
+if test "${enable_gold+set}" = set; then
+ enableval="$enable_gold"
+ case "${enableval}" in
+ yes|both/gold)
+ install_as_default=no
+ installed_linker=ld.bfd
+ ;;
+ both|both/ld)
+ install_as_default=yes
+ installed_linker=ld.bfd
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: invalid --enable-gold argument" >&5
+echo "$as_me: error: invalid --enable-gold argument" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+else
+ install_as_default=ld
+ installed_linker=ld
+fi;
+
+
+
# Check whether --enable-got or --disable-got was given.
if test "${enable_got+set}" = set; then
enableval="$enable_got"
@@ -5542,13 +5568,13 @@ if test "${lt_cv_nm_interface+set}" = set; then
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:5545: $ac_compile\"" >&5)
+ (eval echo "\"\$as_me:5571: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
- (eval echo "\"\$as_me:5548: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval echo "\"\$as_me:5574: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
- (eval echo "\"\$as_me:5551: output\"" >&5)
+ (eval echo "\"\$as_me:5577: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -6603,7 +6629,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 6606 "configure"' > conftest.$ac_ext
+ echo '#line 6632 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -7230,11 +7256,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7233: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7259: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7237: \$? = $ac_status" >&5
+ echo "$as_me:7263: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7552,11 +7578,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7555: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7581: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7559: \$? = $ac_status" >&5
+ echo "$as_me:7585: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7657,11 +7683,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7660: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7686: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7664: \$? = $ac_status" >&5
+ echo "$as_me:7690: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -7712,11 +7738,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7715: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7741: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7719: \$? = $ac_status" >&5
+ echo "$as_me:7745: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -10509,7 +10535,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10512 "configure"
+#line 10538 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10609,7 +10635,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10612 "configure"
+#line 10638 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -14456,6 +14482,8 @@ s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t
s,@use_sysroot@,$use_sysroot,;t t
s,@TARGET_SYSTEM_ROOT@,$TARGET_SYSTEM_ROOT,;t t
s,@TARGET_SYSTEM_ROOT_DEFINE@,$TARGET_SYSTEM_ROOT_DEFINE,;t t
+s,@install_as_default@,$install_as_default,;t t
+s,@installed_linker@,$installed_linker,;t t
s,@WARN_CFLAGS@,$WARN_CFLAGS,;t t
s,@NO_WERROR@,$NO_WERROR,;t t
s,@CPP@,$CPP,;t t
diff --git a/binutils-2.19/ld/configure.in b/binutils-2.19/ld/configure.in
index 8ec534f3..ba5be575 100644
--- a/binutils-2.19/ld/configure.in
+++ b/binutils-2.19/ld/configure.in
@@ -68,6 +68,29 @@ AC_SUBST(use_sysroot)
AC_SUBST(TARGET_SYSTEM_ROOT)
AC_SUBST(TARGET_SYSTEM_ROOT_DEFINE)
+dnl Use --enable-gold to decide if this linker should be the default.
+dnl "install_as_default" is set to false if gold is the default linker.
+dnl "installed_linker" is the installed BFD linker name.
+AC_ARG_ENABLE(gold,
+[[ --enable-gold[=ARG] build gold [ARG={both}[/{gold,ld}]]]],
+[case "${enableval}" in
+ yes|both/gold)
+ install_as_default=no
+ installed_linker=ld.bfd
+ ;;
+ both|both/ld)
+ install_as_default=yes
+ installed_linker=ld.bfd
+ ;;
+ *)
+ AC_MSG_ERROR([invalid --enable-gold argument])
+ ;;
+ esac],
+[install_as_default=ld
+ installed_linker=ld])
+AC_SUBST(install_as_default)
+AC_SUBST(installed_linker)
+
AC_ARG_ENABLE([got],
AS_HELP_STRING([--enable-got=<type>],
[GOT handling scheme (target, single, negative, multigot)]),