* configure.ac (ENABLE_GOLD): Consider *-*-nacl* targets ELF.
authorRoland McGrath <roland@gnu.org>
Wed, 2 May 2012 21:37:24 +0000 (21:37 +0000)
committerRoland McGrath <roland@gnu.org>
Wed, 2 May 2012 21:37:24 +0000 (21:37 +0000)
* configure: Regenerate.

gold/
* nacl.cc: New file.
* nacl.h: New file.
* Makefile.am (CCFILES, HFILES): Add them.
* Makefile.in: Regenerate.
* i386.cc (Output_data_plt_i386_nacl): New class.
(Output_data_plt_i386_nacl_exec): New class.
(Output_data_plt_i386_nacl_dyn): New class.
(Target_i386_nacl): New class.
(Target_selector_i386_nacl): New class.
(target_selector_i386): Use it instead of Target_selector_i386.
* x86_64.cc (Output_data_plt_x86_64_nacl): New class.
(Target_x86_64_nacl): New class.
(Target_selector_x86_64_nacl): New class.
(target_selector_x86_64, target_selector_x32): Use it instead of
Target_selector_x86_64.
* arm.cc (Output_data_plt_arm_nacl): New class.
(Target_arm_nacl): New class.
(Target_selector_arm_nacl): New class.
(target_selector_arm, target_selector_armbe): Use it instead of
Target_selector_arm.

* target-select.cc (select_target): Take new Input_file* and off_t
arguments, pass them on to recognize method of selector.
* object.cc (make_elf_sized_object): Update caller.
* parameters.cc (parameters_force_valid_target): Likewise.
* incremental.cc (make_sized_incremental_binary): Likewise.
* target-select.h: Update decl.
(Target_selector::recognize): Take new Input_file* argument,
pass it on to do_recognize.
(Target_selector::do_recognize): Take new Input_file* argument.
* freebsd.h (Target_selector_freebsd::do_recognize): Likewise.
* powerpc.cc (Target_selector_powerpc::do_recognize): Likewise.
* sparc.cc (Target_selector_sparc::do_recognize): Likewise.
* testsuite/testfile.cc (Target_selector::do_recognize): Likewise.

* target.h (Target::Target_info): New members isolate_execinstr
and rosegment_gap.
(Target::isolate_execinstr, Target::rosegment_gap): New methods.
* arm.cc (Target_arm::arm_info): Update initializer.
* i386.cc (Target_i386::i386_info): Likewise.
* powerpc.cc (Target_powerpc::powerpc_info): Likewise.
* sparc.cc (Target_sparc::sparc_info): Likewise.
* x86_64.cc (Target_x86_64::x86_64_info): Likewise.
* testsuite/testfile.cc (Target_test::test_target_info): Likewise.
* layout.cc (Layout::attach_allocated_section_to_segment):
Take new const Target* argument.  If target->isolate_execinstr(), act
like --rosegment.
(Layout::find_first_load_seg): Take new const Target* argument;
if target->isolate_execinstr(), reject PF_X segments.
(Layout::relaxation_loop_body): Update caller.
(Layout::set_segment_offsets): If target->isolate_execinstr(),
reset file offset to zero when we hit LOAD_SEG, and then do a second
loop over the segments before LOAD_SEG to reassign offsets after
addresses have been determined.  Handle target->rosegment_gap().
(Layout::attach_section_to_segment): Take new const Target* argument;
pass it to attach_allocated_section_to_segment.
(Layout::make_output_section): Update caller.
(Layout::attach_sections_to_segments): Take new const Target* argument;
pass it to attach_section_to_segment.
* gold.cc (queue_middle_tasks): Update caller.
* layout.h (Layout): Update method decls with new arguments.

* arm.cc (Target_arm::Target_arm): Take optional argument for the
Target_info pointer to use.
(Target_arm::do_make_data_plt): New virtual method.
(Target_arm::make_data_plt): New method that calls it.
(Target_arm::make_plt_entry): Use it.
(Output_data_plt_arm::Output_data_plt_arm): Take additional argument
for the section alignment.
(Output_data_plt_arm::do_first_plt_entry_offset): New abstract virtual
method.
(Output_data_plt_arm::first_plt_entry_offset): Call it.
(Output_data_plt_arm::do_get_plt_entry_size): New abstract virtual
method.
(Output_data_plt_arm::get_plt_entry_size): Call it.
(Output_data_plt_arm::do_fill_plt_entry): New abstract virtual method.
(Output_data_plt_arm::fill_plt_entry): New method that calls it.
(Output_data_plt_arm::do_fill_first_plt_entry): New abstract virtual
method.
(Output_data_plt_arm::fill_first_plt_entry): New method that calls it.
(Output_data_plt_arm::set_final_data_size): Use get_plt_entry_size
method instead of sizeof(plt_entry).
(Output_data_plt_arm::add_entry): Likewise.
Use first_plt_entry_offset method instead of sizeof(first_plt_entry).
(Target_arm::first_plt_entry_offset): Call method on this->plt_ rather
than static method.
(Target_arm::plt_entry_size): Likewise.
(Output_data_plt_arm::first_plt_entry, Output_data_plt_arm::plt_entry):
Move to ...
(Output_data_plt_arm_standard): ... here, new class.
(Output_data_plt_arm::do_write): Move guts of PLT filling to...
(Output_data_plt_arm_standard::do_fill_first_plt_entry): ... here ...
(Output_data_plt_arm_standard::do_fill_plt_entry): ... and here.

* x86_64.cc (Output_data_plt_x86_64::Output_data_plt_x86_64):
Take additional argument for the PLT entry size.
(Output_data_plt_x86_64::get_tlsdesc_plt_offset):
Use get_plt_entry_size method rather than plt_entry_size variable.
(Output_data_plt_x86_64::reserve_slot): Likewise.
(Output_data_plt_x86_64::do_adjust_output_section): Likewise.
(Output_data_plt_x86_64::add_entry): Likewise.
(Output_data_plt_x86_64::add_local_ifunc_entry): Likewise.
(Output_data_plt_x86_64::address_for_global): Likewise.
(Output_data_plt_x86_64::address_for_local): Likewise.
(Output_data_plt_x86_64::set_final_data_size): Likewise.
(Output_data_plt_x86_64::first_plt_entry_offset): Likewise.
Make method non-static.
(Output_data_plt_x86_64::do_get_plt_entry_size): New abstract virtual
method.
(Output_data_plt_x86_64::get_plt_entry_size): Just call that.
(Output_data_plt_x86_64::do_add_eh_frame): New abstract virtual method.
(Output_data_plt_x86_64::add_eh_frame): New method to call it.
(Output_data_plt_x86_64::do_fill_first_plt_entry): New abstract
virtual method.
(Output_data_plt_x86_64::fill_first_plt_entry): New method to call it.
(Output_data_plt_x86_64::do_fill_plt_entry): New abstract
virtual method.
(Output_data_plt_x86_64::fill_plt_entry): New method to call it.
(Output_data_plt_x86_64::do_fill_tlsdesc_entry): New abstract
virtual method.
(Output_data_plt_x86_64::fill_tlsdesc_entry): New method to call it.
(Output_data_plt_x86_64::plt_entry_size)
(Output_data_plt_x86_64::first_plt_entry)
(Output_data_plt_x86_64::plt_entry)
(Output_data_plt_x86_64::tlsdesc_plt_entry)
(Output_data_plt_x86_64::plt_eh_frame_fde_size)
(Output_data_plt_x86_64::plt_eh_frame_fde): Move to ...
(Output_data_plt_x86_64_standard): ... here, new class.
(Target_x86_64::Target_x86_64): Take optional argument for the
Target_info pointer to use.
(Target_x86_64::do_make_data_plt): New virtual method.
(Target_x86_64::make_data_plt): New method to call it.
(Target_x86_64::init_got_plt_for_update): Use that.
Call this->plt_->add_eh_frame method here.
(Output_data_plt_x86_64::init): Don't do add_eh_frame_for_plt here.
(Target_x86_64::first_plt_entry_offset): Call method on this->plt_
rather than static method.
(Target_x86_64::plt_entry_size): Likewise.
(Output_data_plt_x86_64::do_write): Use get_plt_entry_size method
rather than plt_entry_size variable.  Move guts of PLT filling to...
(Output_data_plt_x86_64_standard::do_fill_first_plt_entry): ... here ...
(Output_data_plt_x86_64_standard::do_fill_plt_entry): ... and here ...
(Output_data_plt_x86_64_standard::do_fill_tlsdesc_entry): ... and here.

* i386.cc (Output_data_plt_i386::Output_data_plt_i386): Take
additional argument for the section alignment.
Don't do add_eh_frame_for_plt here.
(Output_data_plt_i386::first_plt_entry_offset): Make the method
non-static.  Use get_plt_entry_size method rather than plt_entry_size
variable.
(Output_data_plt_i386::do_get_plt_entry_size): New abstract virtual
method.
(Output_data_plt_i386::get_plt_entry_size): Call it.
(Output_data_plt_i386::do_add_eh_frame): New abstract virtual method.
(Output_data_plt_i386::add_eh_frame): New method to call it.
(Output_data_plt_i386::do_fill_first_plt_entry): New abstract virtual
method.
(Output_data_plt_i386::fill_first_plt_entry): New method to call it.
(Output_data_plt_i386::do_fill_plt_entry): New abstract virtual
method.
(Output_data_plt_i386::fill_plt_entry): New method to call it.
(Output_data_plt_i386::set_final_data_size): Use get_plt_entry_size
method instead of plt_entry_size.
(Output_data_plt_i386::plt_entry_size)
(Output_data_plt_i386::plt_eh_frame_fde_size)
(Output_data_plt_i386::plt_eh_frame_fde): Move to ...
(Output_data_plt_i386_standard): ... here, new class.
(Output_data_plt_i386_exec): New class.
(Output_data_plt_i386::exec_first_plt_entry): Move to ...
(Output_data_plt_i386_exec::first_plt_entry): ... here.
(Output_data_plt_i386::exec_plt_entry): Move to ...
(Output_data_plt_i386_exec::plt_entry): ... here.
(Output_data_plt_i386_dyn): New class.
(Output_data_plt_i386::first_plt_entry): Move to ...
(Output_data_plt_i386_dyn::first_plt_entry): ... here.
(Output_data_plt_i386::dyn_plt_entry): Move to ...
(Output_data_plt_i386_dyn::plt_entry): ... here.
(Target_i386::Target_i386): Take optional argument for the Target_info
pointer to use.
(Target_i386::do_make_data_plt): New virtual method.
(Target_i386::make_data_plt): New method to call it.
(Target_i386::make_plt_section): Use that.
Call this->plt_->add_eh_frame method here.
(Output_data_plt_i386::add_entry): Use get_plt_entry_size method
rather than plt_entry_size variable.
(Output_data_plt_i386::add_local_ifunc_entry): Likewise.
(Output_data_plt_i386::address_for_local): Likewise.
(Output_data_plt_i386::do_write): Likewise.
Move guts of PLT filling to...
(Output_data_plt_i386_exec::do_fill_first_plt_entry): ... here ...
(Output_data_plt_i386_exec::do_fill_plt_entry): ... and here ...
(Output_data_plt_i386_dyn::do_fill_first_plt_entry): ... and here ...
(Output_data_plt_i386_dyn::do_fill_plt_entry): ... and here.

Change-Id: Id24b95600489835ff5e860a39c147203d4380c2b

24 files changed:
ChangeLog
configure
configure.ac
gold/ChangeLog
gold/Makefile.am
gold/Makefile.in
gold/arm.cc
gold/freebsd.h
gold/gold.cc
gold/i386.cc
gold/incremental.cc
gold/layout.cc
gold/layout.h
gold/nacl.cc [new file with mode: 0644]
gold/nacl.h [new file with mode: 0644]
gold/object.cc
gold/parameters.cc
gold/powerpc.cc
gold/sparc.cc
gold/target-select.cc
gold/target-select.h
gold/target.h
gold/testsuite/testfile.cc
gold/x86_64.cc

index 4e8d13ed1b6fc3843a43e78176f322974c0ca158..0dc7a324a5b8af21854082afab729bdd1edd03f9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2012-05-02  Roland McGrath  <mcgrathr@google.com>
+
+       * configure.ac (ENABLE_GOLD): Consider *-*-nacl* targets ELF.
+       * configure: Regenerate.
+
 2012-04-25  Joel Brobecker  <brobecker@adacore.com>
 
        * config.sub: Update to 2012-04-18 version from official repo.
 
        * config.guess: Update to version 2011-02-02
        * config.sub: Update to version 2011-02-24
-       
+
 2011-03-03  Sebastian Pop  <sebastian.pop@amd.com>
 
         * configure.ac: Adjust test of with_ppl.
index 2fee66b16e7cdc91edaf2c02e65b10727e0aa27d..8554178f85da7607e61cc4dcf3312ae05b8e9036 100755 (executable)
--- a/configure
+++ b/configure
@@ -2869,7 +2869,7 @@ case "${ENABLE_GOLD}" in
       *-*-elf* | *-*-sysv4* | *-*-unixware* | *-*-eabi* | hppa*64*-*-hpux* \
       | *-*-linux* | frv-*-uclinux* | *-*-irix5* | *-*-irix6* \
       | *-*-netbsd* | *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* \
-      | *-*-solaris2* | *-*-nto*)
+      | *-*-solaris2* | *-*-nto* | *-*-nacl*)
         case "${target}" in
           *-*-linux*aout* | *-*-linux*oldld*)
             ;;
index c2795874c2b29d39e1285bcaa1c5b64787c2fb9c..396c87b95a7d11166706f18e703fe35cb5b2019a 100644 (file)
@@ -112,11 +112,11 @@ extra_host_args=
 ### or a host dependent tool.  Then put it into the appropriate list
 ### (library or tools, host or target), doing a dependency sort.
 
-# Subdirs will be configured in the order listed in build_configdirs, 
+# Subdirs will be configured in the order listed in build_configdirs,
 # configdirs, or target_configdirs; see the serialization section below.
 
-# Dependency sorting is only needed when *configuration* must be done in 
-# a particular order.  In all cases a dependency should be specified in 
+# Dependency sorting is only needed when *configuration* must be done in
+# a particular order.  In all cases a dependency should be specified in
 # the Makefile, whether or not it's implicitly specified here.
 
 # Double entries in build_configdirs, configdirs, or target_configdirs may
@@ -209,7 +209,7 @@ if test x"${host}" = x"${target}" ; then
   is_cross_compiler=no
 else
   is_cross_compiler=yes
-fi     
+fi
 
 # Find the build and target subdir names.
 GCC_TOPLEV_SUBDIRS
@@ -245,7 +245,7 @@ if test x$with_system_zlib = xyes ; then
   noconfigdirs="$noconfigdirs zlib"
 fi
 
-# some tools are so dependent upon X11 that if we're not building with X, 
+# some tools are so dependent upon X11 that if we're not building with X,
 # it's not even worth trying to configure, much less build, that tool.
 
 case ${with_x} in
@@ -253,7 +253,7 @@ case ${with_x} in
   no)
     skipdirs="${skipdirs} tk itcl libgui"
     # We won't be able to build gdbtk without X.
-    enable_gdbtk=no 
+    enable_gdbtk=no
     ;;
   *)  echo "*** bad value \"${with_x}\" for -with-x flag; ignored" 1>&2 ;;
 esac
@@ -313,7 +313,7 @@ case "${ENABLE_GOLD}" in
       *-*-elf* | *-*-sysv4* | *-*-unixware* | *-*-eabi* | hppa*64*-*-hpux* \
       | *-*-linux* | frv-*-uclinux* | *-*-irix5* | *-*-irix6* \
       | *-*-netbsd* | *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* \
-      | *-*-solaris2* | *-*-nto*)
+      | *-*-solaris2* | *-*-nto* | *-*-nacl*)
         case "${target}" in
           *-*-linux*aout* | *-*-linux*oldld*)
             ;;
@@ -379,7 +379,7 @@ esac
 # Only spaces may be used in this macro; not newlines or tabs.
 unsupported_languages=
 
-# Remove more programs from consideration, based on the host or 
+# Remove more programs from consideration, based on the host or
 # target this usually means that a port of the program doesn't
 # exist yet.
 
@@ -689,7 +689,7 @@ case "${target}" in
     ;;
   *-*-lynxos*)
     noconfigdirs="$noconfigdirs ${libgcj}"
-    ;; 
+    ;;
 esac
 
 # Default libgloss CPU subdirectory.
@@ -774,7 +774,7 @@ case "${target}" in
     ;;
   *-*-lynxos*)
     noconfigdirs="$noconfigdirs target-newlib target-libgloss"
-    ;; 
+    ;;
   *-*-mingw*)
     noconfigdirs="$noconfigdirs target-newlib target-libgloss"
     ;;
@@ -1078,7 +1078,7 @@ case "${host}" in
   hppa*-hp-hpux*)
     host_makefile_frag="config/mh-pa"
     ;;
-  hppa*-*)     
+  hppa*-*)
     host_makefile_frag="config/mh-pa"
     ;;
   *-*-darwin*)
@@ -1774,7 +1774,7 @@ if test -d ${srcdir}/gcc; then
       # an apparent bug in bash 1.12 on linux.
       ${srcdir}/gcc/[[*]]/config-lang.in) ;;
       *)
-        # From the config-lang.in, get $language, $target_libs, 
+        # From the config-lang.in, get $language, $target_libs,
         # $lang_dirs, $boot_language, and $build_by_default
         language=
         target_libs=
@@ -2019,7 +2019,7 @@ done
 build_configdirs_all="$build_configdirs"
 build_configdirs=
 for i in ${build_configdirs_all} ; do
-  j=`echo $i | sed -e s/build-//g` 
+  j=`echo $i | sed -e s/build-//g`
   if test -f ${srcdir}/$j/configure ; then
     build_configdirs="${build_configdirs} $i"
   fi
@@ -2036,7 +2036,7 @@ done
 target_configdirs_all="$target_configdirs"
 target_configdirs=
 for i in ${target_configdirs_all} ; do
-  j=`echo $i | sed -e s/target-//g` 
+  j=`echo $i | sed -e s/target-//g`
   if test -f ${srcdir}/$j/configure ; then
     target_configdirs="${target_configdirs} $i"
   fi
@@ -2087,7 +2087,7 @@ ACX_TOOL_DIRS
 
 copy_dirs=
 
-AC_ARG_WITH([build-sysroot], 
+AC_ARG_WITH([build-sysroot],
   [AS_HELP_STRING([--with-build-sysroot=SYSROOT],
                  [use sysroot as the system root during the build])],
   [if test x"$withval" != x ; then
@@ -2178,11 +2178,11 @@ fi
 # This is done by determining whether or not the appropriate directory
 # is available, and by checking whether or not specific configurations
 # have requested that this magic not happen.
-# 
-# The command line options always override the explicit settings in 
+#
+# The command line options always override the explicit settings in
 # configure.in, and the settings in configure.in override this magic.
 #
-# If the default for a toolchain is to use GNU as and ld, and you don't 
+# If the default for a toolchain is to use GNU as and ld, and you don't
 # want to do that, then you should use the --without-gnu-as and
 # --without-gnu-ld options for the configure script.  Similarly, if
 # the default is to use the included zlib and you don't want to do that,
@@ -2283,7 +2283,7 @@ case "${target}" in
     target_makefile_frag="config/mt-gnu"
     ;;
   *-*-aix4.[[3456789]]* | *-*-aix[[56789]].*)
-    # nm and ar from AIX 4.3 and above require -X32_64 flag to all ar and nm 
+    # nm and ar from AIX 4.3 and above require -X32_64 flag to all ar and nm
     # commands to handle both 32-bit and 64-bit objects.  These flags are
     # harmless if we're using GNU nm or ar.
     extra_arflags_for_target=" -X32_64"
@@ -2357,7 +2357,7 @@ if test $? = 0 ; then
   if test -s conftest || test -s conftest.exe ; then
     we_are_ok=yes
   fi
-fi 
+fi
 case $we_are_ok in
   no)
     echo 1>&2 "*** The command '${CC} -o conftest ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} conftest.c' failed."
@@ -2727,7 +2727,7 @@ baseargs=`echo "x$baseargs" | sed -e 's/^x *//' -e 's,\\$,$$,g'`
 # --program-suffix have been applied to it.  Autoconf has already
 # doubled dollar signs and backslashes in program_transform_name; we want
 # the backslashes un-doubled, and then the entire thing wrapped in single
-# quotes, because this will be expanded first by make and then by the shell. 
+# quotes, because this will be expanded first by make and then by the shell.
 # Also, because we want to override the logic in subdir configure scripts to
 # choose program_transform_name, replace any s,x,x, with s,y,y,.
 sed -e "s,\\\\\\\\,\\\\,g; s,','\\\\'',g; s/s,x,x,/s,y,y,/" <<EOF_SED > conftestsed.out
@@ -3052,7 +3052,7 @@ AC_SUBST(CFLAGS)
 AC_SUBST(CXXFLAGS)
 
 # Target tools.
-AC_ARG_WITH([build-time-tools], 
+AC_ARG_WITH([build-time-tools],
   [AS_HELP_STRING([--with-build-time-tools=PATH],
                  [use given path to find target tools during the build])],
   [case x"$withval" in
@@ -3157,7 +3157,7 @@ if test "$USE_MAINTAINER_MODE" = yes; then
 else
   MAINTAINER_MODE_TRUE='#'
   MAINTAINER_MODE_FALSE=
-fi     
+fi
 MAINT=$MAINTAINER_MODE_TRUE
 AC_SUBST(MAINT)dnl
 
index 888affd01bda9a862cf065e1ced3fc6c0e196810..a0a461f4846f6e4aabceaee8c28b39b3c5c39c3d 100644 (file)
@@ -1,3 +1,199 @@
+2012-05-02  Roland McGrath  <mcgrathr@google.com>
+
+       * nacl.cc: New file.
+       * nacl.h: New file.
+       * Makefile.am (CCFILES, HFILES): Add them.
+       * Makefile.in: Regenerate.
+       * i386.cc (Output_data_plt_i386_nacl): New class.
+       (Output_data_plt_i386_nacl_exec): New class.
+       (Output_data_plt_i386_nacl_dyn): New class.
+       (Target_i386_nacl): New class.
+       (Target_selector_i386_nacl): New class.
+       (target_selector_i386): Use it instead of Target_selector_i386.
+       * x86_64.cc (Output_data_plt_x86_64_nacl): New class.
+       (Target_x86_64_nacl): New class.
+       (Target_selector_x86_64_nacl): New class.
+       (target_selector_x86_64, target_selector_x32): Use it instead of
+       Target_selector_x86_64.
+       * arm.cc (Output_data_plt_arm_nacl): New class.
+       (Target_arm_nacl): New class.
+       (Target_selector_arm_nacl): New class.
+       (target_selector_arm, target_selector_armbe): Use it instead of
+       Target_selector_arm.
+
+       * target-select.cc (select_target): Take new Input_file* and off_t
+       arguments, pass them on to recognize method of selector.
+       * object.cc (make_elf_sized_object): Update caller.
+       * parameters.cc (parameters_force_valid_target): Likewise.
+       * incremental.cc (make_sized_incremental_binary): Likewise.
+       * target-select.h: Update decl.
+       (Target_selector::recognize): Take new Input_file* argument,
+       pass it on to do_recognize.
+       (Target_selector::do_recognize): Take new Input_file* argument.
+       * freebsd.h (Target_selector_freebsd::do_recognize): Likewise.
+       * powerpc.cc (Target_selector_powerpc::do_recognize): Likewise.
+       * sparc.cc (Target_selector_sparc::do_recognize): Likewise.
+       * testsuite/testfile.cc (Target_selector::do_recognize): Likewise.
+
+       * target.h (Target::Target_info): New members isolate_execinstr
+       and rosegment_gap.
+       (Target::isolate_execinstr, Target::rosegment_gap): New methods.
+       * arm.cc (Target_arm::arm_info): Update initializer.
+       * i386.cc (Target_i386::i386_info): Likewise.
+       * powerpc.cc (Target_powerpc::powerpc_info): Likewise.
+       * sparc.cc (Target_sparc::sparc_info): Likewise.
+       * x86_64.cc (Target_x86_64::x86_64_info): Likewise.
+       * testsuite/testfile.cc (Target_test::test_target_info): Likewise.
+       * layout.cc (Layout::attach_allocated_section_to_segment):
+       Take new const Target* argument.  If target->isolate_execinstr(), act
+       like --rosegment.
+       (Layout::find_first_load_seg): Take new const Target* argument;
+       if target->isolate_execinstr(), reject PF_X segments.
+       (Layout::relaxation_loop_body): Update caller.
+       (Layout::set_segment_offsets): If target->isolate_execinstr(),
+       reset file offset to zero when we hit LOAD_SEG, and then do a second
+       loop over the segments before LOAD_SEG to reassign offsets after
+       addresses have been determined.  Handle target->rosegment_gap().
+       (Layout::attach_section_to_segment): Take new const Target* argument;
+       pass it to attach_allocated_section_to_segment.
+       (Layout::make_output_section): Update caller.
+       (Layout::attach_sections_to_segments): Take new const Target* argument;
+       pass it to attach_section_to_segment.
+       * gold.cc (queue_middle_tasks): Update caller.
+       * layout.h (Layout): Update method decls with new arguments.
+
+       * arm.cc (Target_arm::Target_arm): Take optional argument for the
+       Target_info pointer to use.
+       (Target_arm::do_make_data_plt): New virtual method.
+       (Target_arm::make_data_plt): New method that calls it.
+       (Target_arm::make_plt_entry): Use it.
+       (Output_data_plt_arm::Output_data_plt_arm): Take additional argument
+       for the section alignment.
+       (Output_data_plt_arm::do_first_plt_entry_offset): New abstract virtual
+       method.
+       (Output_data_plt_arm::first_plt_entry_offset): Call it.
+       (Output_data_plt_arm::do_get_plt_entry_size): New abstract virtual
+       method.
+       (Output_data_plt_arm::get_plt_entry_size): Call it.
+       (Output_data_plt_arm::do_fill_plt_entry): New abstract virtual method.
+       (Output_data_plt_arm::fill_plt_entry): New method that calls it.
+       (Output_data_plt_arm::do_fill_first_plt_entry): New abstract virtual
+       method.
+       (Output_data_plt_arm::fill_first_plt_entry): New method that calls it.
+       (Output_data_plt_arm::set_final_data_size): Use get_plt_entry_size
+       method instead of sizeof(plt_entry).
+       (Output_data_plt_arm::add_entry): Likewise.
+       Use first_plt_entry_offset method instead of sizeof(first_plt_entry).
+       (Target_arm::first_plt_entry_offset): Call method on this->plt_ rather
+       than static method.
+       (Target_arm::plt_entry_size): Likewise.
+       (Output_data_plt_arm::first_plt_entry, Output_data_plt_arm::plt_entry):
+       Move to ...
+       (Output_data_plt_arm_standard): ... here, new class.
+       (Output_data_plt_arm::do_write): Move guts of PLT filling to...
+       (Output_data_plt_arm_standard::do_fill_first_plt_entry): ... here ...
+       (Output_data_plt_arm_standard::do_fill_plt_entry): ... and here.
+
+       * x86_64.cc (Output_data_plt_x86_64::Output_data_plt_x86_64):
+       Take additional argument for the PLT entry size.
+       (Output_data_plt_x86_64::get_tlsdesc_plt_offset):
+       Use get_plt_entry_size method rather than plt_entry_size variable.
+       (Output_data_plt_x86_64::reserve_slot): Likewise.
+       (Output_data_plt_x86_64::do_adjust_output_section): Likewise.
+       (Output_data_plt_x86_64::add_entry): Likewise.
+       (Output_data_plt_x86_64::add_local_ifunc_entry): Likewise.
+       (Output_data_plt_x86_64::address_for_global): Likewise.
+       (Output_data_plt_x86_64::address_for_local): Likewise.
+       (Output_data_plt_x86_64::set_final_data_size): Likewise.
+       (Output_data_plt_x86_64::first_plt_entry_offset): Likewise.
+       Make method non-static.
+       (Output_data_plt_x86_64::do_get_plt_entry_size): New abstract virtual
+       method.
+       (Output_data_plt_x86_64::get_plt_entry_size): Just call that.
+       (Output_data_plt_x86_64::do_add_eh_frame): New abstract virtual method.
+       (Output_data_plt_x86_64::add_eh_frame): New method to call it.
+       (Output_data_plt_x86_64::do_fill_first_plt_entry): New abstract
+       virtual method.
+       (Output_data_plt_x86_64::fill_first_plt_entry): New method to call it.
+       (Output_data_plt_x86_64::do_fill_plt_entry): New abstract
+       virtual method.
+       (Output_data_plt_x86_64::fill_plt_entry): New method to call it.
+       (Output_data_plt_x86_64::do_fill_tlsdesc_entry): New abstract
+       virtual method.
+       (Output_data_plt_x86_64::fill_tlsdesc_entry): New method to call it.
+       (Output_data_plt_x86_64::plt_entry_size)
+       (Output_data_plt_x86_64::first_plt_entry)
+       (Output_data_plt_x86_64::plt_entry)
+       (Output_data_plt_x86_64::tlsdesc_plt_entry)
+       (Output_data_plt_x86_64::plt_eh_frame_fde_size)
+       (Output_data_plt_x86_64::plt_eh_frame_fde): Move to ...
+       (Output_data_plt_x86_64_standard): ... here, new class.
+       (Target_x86_64::Target_x86_64): Take optional argument for the
+       Target_info pointer to use.
+       (Target_x86_64::do_make_data_plt): New virtual method.
+       (Target_x86_64::make_data_plt): New method to call it.
+       (Target_x86_64::init_got_plt_for_update): Use that.
+       Call this->plt_->add_eh_frame method here.
+       (Output_data_plt_x86_64::init): Don't do add_eh_frame_for_plt here.
+       (Target_x86_64::first_plt_entry_offset): Call method on this->plt_
+       rather than static method.
+       (Target_x86_64::plt_entry_size): Likewise.
+       (Output_data_plt_x86_64::do_write): Use get_plt_entry_size method
+       rather than plt_entry_size variable.  Move guts of PLT filling to...
+       (Output_data_plt_x86_64_standard::do_fill_first_plt_entry): ... here ...
+       (Output_data_plt_x86_64_standard::do_fill_plt_entry): ... and here ...
+       (Output_data_plt_x86_64_standard::do_fill_tlsdesc_entry): ... and here.
+
+       * i386.cc (Output_data_plt_i386::Output_data_plt_i386): Take
+       additional argument for the section alignment.
+       Don't do add_eh_frame_for_plt here.
+       (Output_data_plt_i386::first_plt_entry_offset): Make the method
+       non-static.  Use get_plt_entry_size method rather than plt_entry_size
+       variable.
+       (Output_data_plt_i386::do_get_plt_entry_size): New abstract virtual
+       method.
+       (Output_data_plt_i386::get_plt_entry_size): Call it.
+       (Output_data_plt_i386::do_add_eh_frame): New abstract virtual method.
+       (Output_data_plt_i386::add_eh_frame): New method to call it.
+       (Output_data_plt_i386::do_fill_first_plt_entry): New abstract virtual
+       method.
+       (Output_data_plt_i386::fill_first_plt_entry): New method to call it.
+       (Output_data_plt_i386::do_fill_plt_entry): New abstract virtual
+       method.
+       (Output_data_plt_i386::fill_plt_entry): New method to call it.
+       (Output_data_plt_i386::set_final_data_size): Use get_plt_entry_size
+       method instead of plt_entry_size.
+       (Output_data_plt_i386::plt_entry_size)
+       (Output_data_plt_i386::plt_eh_frame_fde_size)
+       (Output_data_plt_i386::plt_eh_frame_fde): Move to ...
+       (Output_data_plt_i386_standard): ... here, new class.
+       (Output_data_plt_i386_exec): New class.
+       (Output_data_plt_i386::exec_first_plt_entry): Move to ...
+       (Output_data_plt_i386_exec::first_plt_entry): ... here.
+       (Output_data_plt_i386::exec_plt_entry): Move to ...
+       (Output_data_plt_i386_exec::plt_entry): ... here.
+       (Output_data_plt_i386_dyn): New class.
+       (Output_data_plt_i386::first_plt_entry): Move to ...
+       (Output_data_plt_i386_dyn::first_plt_entry): ... here.
+       (Output_data_plt_i386::dyn_plt_entry): Move to ...
+       (Output_data_plt_i386_dyn::plt_entry): ... here.
+       (Target_i386::Target_i386): Take optional argument for the Target_info
+       pointer to use.
+       (Target_i386::do_make_data_plt): New virtual method.
+       (Target_i386::make_data_plt): New method to call it.
+       (Target_i386::make_plt_section): Use that.
+       Call this->plt_->add_eh_frame method here.
+       (Output_data_plt_i386::add_entry): Use get_plt_entry_size method
+       rather than plt_entry_size variable.
+       (Output_data_plt_i386::add_local_ifunc_entry): Likewise.
+       (Output_data_plt_i386::address_for_local): Likewise.
+       (Output_data_plt_i386::do_write): Likewise.
+       Move guts of PLT filling to...
+       (Output_data_plt_i386_exec::do_fill_first_plt_entry): ... here ...
+       (Output_data_plt_i386_exec::do_fill_plt_entry): ... and here ...
+       (Output_data_plt_i386_dyn::do_fill_first_plt_entry): ... and here ...
+       (Output_data_plt_i386_dyn::do_fill_plt_entry): ... and here.
+
 2012-05-01  Cary Coutant  <ccoutant@google.com>
 
        * dwarf_reader.cc (Dwarf_die::read_attributes)
 2012-03-19  Doug Kwan  <dougkwan@google.com>
 
        * arm.cc (Target_arm::do_define_standard_symbols): New method.
-       (Target_arm::do_finalize_sections): Remove code which defines
+       (Target_arm::do_finalize_sections): Remove code which defines
        __exidx_start and __exidx_end.  Make symbol table parameter
        anonymous as it is not used.
        * gold.cc (queue_middle_tasks): Call target hook to define any
        * output.cc: Likewise.
 
 2011-05-31  Doug Kwan  <dougkwan@google.com>
-            Asier Llano
+           Asier Llano
 
        PR gold/12826
        * arm.cc (Target_arm::tag_cpu_arch_combine): Fix handling of
 
        * arm.cc (Arm_output_section::Arm_output_section): Set SHF_LINK_ORDER
        flag of a SHT_ARM_EXIDX section.
-        * testsuite/Makefile.am (arm_exidx_test): New test rules.
+       * testsuite/Makefile.am (arm_exidx_test): New test rules.
        * testsuite/Makefile.in: Regenerate.
        * testsuite/arm_exidx_test.s: New file.
        * testsuite/arm_exidx_test.sh: Same.
 2011-02-02  Sriraman Tallam  <tmsriram@google.com>
 
        * icf.h (is_section_foldable_candidate): Change type of parameter
-        to std::string.
+       to std::string.
        * icf.cc (Icf::find_identical_sections): Change type of local variable
-        section_name to be std::string.
+       section_name to be std::string.
        (is_function_ctor_or_dtor): Change type of parameter to std::string.
 
 2011-01-25  Ian Lance Taylor  <iant@google.com>
        and updating local symbols.
        (Arm_input_section<big_endian>::init): Copy contents of original
        input section.
-       (Arm_input_section<big_endian>::do_write): Use saved contents of
+       (Arm_input_section<big_endian>::do_write): Use saved contents of
        original input section instead of calling Object::section_contents
        without locking.
        (Arm_exidx_cantunwind::do_fixed_endian_write): Find out text section
        (Arm_exidx_merged_section::Arm_exidx_merged_section): Add sanity check
        for size.  Allocate a buffer for merged EXIDX entries.
        (Arm_exidx_merged_section::build_contents): New method.
-       (Arm_exidx_merged_section::do_write): Move merge section contents
+       (Arm_exidx_merged_section::do_write): Move merge section contents
        building code to Arm_exidx_merged_section::build_contetns.  Write
        out contetns in buffer instead of building it on the fly.
        (Arm_relobj::make_exidx_input_section): Also pass text section size
 2010-10-29  Viktor Kutuzov  <vkutuzov@accesssoftek.com>
 
        * testsuite/Makefile.am: Move gcctestdir/ld rule to
-        NATIVE_OR_CROSS_LINKER.
+       NATIVE_OR_CROSS_LINKER.
        * testsuite/Makefile.in: Regenerate.
 
 2010-10-20  Doug Kwan  <dougkwan@google.com>
 2010-10-14  Cary Coutant  <ccoutant@google.com>
 
        * debug.h (DEBUG_INCREMENTAL): New flag.
-       (debug_string_to_enum): Add DEBUG_INCREMENTAL).
-       * gold.cc (queue_initial_tasks): Check parameters for incremental link
-       mode.
-       * incremental.cc (report_command_line): Ignore all forms of
-       --incremental.
-       * layout.cc (Layout::Layout): Check parameters for incremental link
-       mode.
-       * options.cc (General_options::parse_incremental): New function.
-       (General_options::parse_no_incremental): New function.
-       (General_options::parse_incremental_full): New function.
-       (General_options::parse_incremental_update): New function.
-       (General_options::incremental_mode_): New data member.
-       (General_options::finalize): Check incremental_mode_.
-       * options.h (General_options): Update help text for --incremental.
-       Add --no-incremental, --incremental-full, --incremental-update.
-       (General_options::Incremental_mode): New enum type.
-       (General_options::incremental_mode): New function.
-       (General_options::incremental_mode_): New data member.
-       * parameters.cc (Parameters::incremental_mode_): New data member.
-       (Parameters::set_options): Set incremental_mode_.
-       (Parameters::set_incremental_full): New function.
-       (Parameters::incremental): New function.
-       (Parameters::incremental_update): New function.
-       (set_parameters_incremental_full): New function.
-       * parameters.h (Parameters::set_incremental_full): New function.
-       (Parameters::incremental): New function.
-       (Parameters::incremental_update): New function.
-       (Parameters::incremental_mode_): New data member.
-       (set_parameters_incremental_full): New function.
-       * plugin.cc (Plugin_manager::add_input_file): Check parameters for
-       incremental link mode.
-       * reloc.cc (Sized_relobj::do_read_relocs): Likewise.
-       (Sized_relobj::do_relocate_sections): Likewise.
-       * testsuite/Makefile.am (incremental_test): Use --incremental-full
-       option.
-       * testsuite/Makefile.in: Regenerate.
-       * testsuite/incremental_test.sh: Filter all forms of --incremental.
+       (debug_string_to_enum): Add DEBUG_INCREMENTAL).
+       * gold.cc (queue_initial_tasks): Check parameters for incremental link
+       mode.
+       * incremental.cc (report_command_line): Ignore all forms of
+       --incremental.
+       * layout.cc (Layout::Layout): Check parameters for incremental link
+       mode.
+       * options.cc (General_options::parse_incremental): New function.
+       (General_options::parse_no_incremental): New function.
+       (General_options::parse_incremental_full): New function.
+       (General_options::parse_incremental_update): New function.
+       (General_options::incremental_mode_): New data member.
+       (General_options::finalize): Check incremental_mode_.
+       * options.h (General_options): Update help text for --incremental.
+       Add --no-incremental, --incremental-full, --incremental-update.
+       (General_options::Incremental_mode): New enum type.
+       (General_options::incremental_mode): New function.
+       (General_options::incremental_mode_): New data member.
+       * parameters.cc (Parameters::incremental_mode_): New data member.
+       (Parameters::set_options): Set incremental_mode_.
+       (Parameters::set_incremental_full): New function.
+       (Parameters::incremental): New function.
+       (Parameters::incremental_update): New function.
+       (set_parameters_incremental_full): New function.
+       * parameters.h (Parameters::set_incremental_full): New function.
+       (Parameters::incremental): New function.
+       (Parameters::incremental_update): New function.
+       (Parameters::incremental_mode_): New data member.
+       (set_parameters_incremental_full): New function.
+       * plugin.cc (Plugin_manager::add_input_file): Check parameters for
+       incremental link mode.
+       * reloc.cc (Sized_relobj::do_read_relocs): Likewise.
+       (Sized_relobj::do_relocate_sections): Likewise.
+       * testsuite/Makefile.am (incremental_test): Use --incremental-full
+       option.
+       * testsuite/Makefile.in: Regenerate.
+       * testsuite/incremental_test.sh: Filter all forms of --incremental.
 
 2010-10-12  Viktor Kutuzov  <vkutuzov@accesssoftek.com>
 
        section without SHF_EXECINSTR.
        (Arm_output_section::fix_exidx_coverage): Skip input sections with
        errors.
-       (Arm_relobj::make_exidx_input_section): Add new parameter for text
+       (Arm_relobj::make_exidx_input_section): Add new parameter for text
        section header.  Make error messages more verbose.  Check for
        a non-executable section linked to an EXIDX section.
        (Arm_relobj::do_read_symbols): Remove error checking, which has been
        in a relocatable link.
        (Target_arm::do_relax): Look for the EXIDX output section instead of
        assuming that it is called .ARM.exidx.
-       (Target_arm::fix_exidx_coverage): Add a new parameter for input
+       (Target_arm::fix_exidx_coverage): Add a new parameter for input
        section list.  Do not check for SHF_EXECINSTR section flags but
        skip any input section with errors.
        * output.cc (Output_section::Output_section): Initialize
        to use Output_section_lookup_maps class.
        (Output_section::add_relaxed_input_section): Adjst code for lookup
        maps code refactoring.
-       (Output_section::add_merge_input_section): Add a new parameter
+       (Output_section::add_merge_input_section): Add a new parameter
        KEEPS_INPUT_SECTION.  Adjust code to use Output_section_lookup_maps
        class.  If adding input section to a newly created merge output
        section fails, remove the new merge section.
        (Output_section::convert_input_sections_in_list_to_relaxed_input_sections):
        Adjust code for use of the Output_section_lookup_maps class.
-       (Output_section::find_merge_section): Ditto.
+       (Output_section::find_merge_section): Ditto.
        (Output_section::build_lookup_maps): New method defintion.
-       (Output_section::find_relaxed_input_section): Adjust code to use
+       (Output_section::find_relaxed_input_section): Adjust code to use
        Output_section_lookup_maps class.
        (Output_section::get_input_sections): Export merge sections.  Adjust
        code to use Output_section_lookup_maps class.
        defintion.  Declare method only.
        (Output_section::Input_section::shndx): Ditto.
        (Output_section::Input_section::output_merge_base): New method defintion.
-       (Output_section::Input_section::u2_.pomb): New union field.
+       (Output_section::Input_section::u2_.pomb): New union field.
        (Output_section::Merge_section_by_properties_map,
        Output_section::Output_section_data_by_input_section_map,
        Output_section::Ouptut_relaxed_input_section_by_input_section_map):
        Remove types.
-       (Output_section::add_merge_input_section): Add new parameter
+       (Output_section::add_merge_input_section): Add new parameter
        KEEPS_INPUT_SECTIONS.
        (Output_section::build_lookup_maps): New method declaration.
        (Output_section::merge_section_map_,
        section elements.  Handle discard sections.
        (Sort_output_sections::operator()): Handle NOLOAD sections.
        * script-sections.h (Script_sections::Section_type): New enum type.
-       (Script_sections::output_section_name): Add a new parameter for
+       (Script_sections::output_section_name): Add a new parameter for
        returning script section type.
        * script.cc (script_keyword_parsecodes): Add keywords COPY, DSECT,
        INFO and NOLOAD.
        thumb2_blx_in_range, thumb2_blx_in_range.o,
        thumb2_blx_out_of_range.stdout, thumb2_blx_out_of_range,
        thumb2_blx_out_of_range.o): New rules.
-       (MOSTLYCLEANFILES): Add thumb_blx_in_range, thumb_blx_out_of_range,
+       (MOSTLYCLEANFILES): Add thumb_blx_in_range, thumb_blx_out_of_range,
        thumb2_blx_in_range and thumb2_blx_out_of_range.
        * testsuite/Makefile.in: Regenerate.
        * arm_branch_in_range.sh: Add tests for THUMB BLX.
        Stub_table::reloc_stubs_size_ and Stub_table::reloc_stubs_addralign_.
        (Stub_table::reloc_stubs_size_, Stub_table::reloc_stubs_addralign_):
        New data members.
-       (Stub_table::update_data_size_and_addralign): Use
+       (Stub_table::update_data_size_and_addralign): Use
        Stub_table::reloc_stubs_size_ and Stub_table::reloc_stubs_addralign_
        instead of going over all reloc stubs.
-       (Stub_table::finalize_stubs): Do not assign reloc stub offsets.
+       (Stub_table::finalize_stubs): Do not assign reloc stub offsets.
        * stringpool.cc (Stringpool_template::Stringpool_template): Initialize
        Stringpool_template::offset_ to size of Stringpool_char.
-       (Stringpool_template::new_key_offset): Remove code to initialize
+       (Stringpool_template::new_key_offset): Remove code to initialize
        Stringpool_template::offset_.
        * stringpool.h (Stringpool_template::set_no_zero_null): Set
        Stringpool_template::offset_ to zero.
        when not optimizing.
        * stringpool.h (Chunked_vector::Chunked_vector): Initialize data
        member size_.
-       (Chunked_vector::clear): Clear size_.
-       (Chunked_vector::reserve): Call reserve method of all Element_vectors.
-       (Chunked_vector::size): Return size_.
-       (Chunked_vector::push_back): Use size_ to find insert position.
+       (Chunked_vector::clear): Clear size_.
+       (Chunked_vector::reserve): Call reserve method of all Element_vectors.
+       (Chunked_vector::size): Return size_.
+       (Chunked_vector::push_back): Use size_ to find insert position.
        (Chunked_vector::size_): New data member.
        (Stringpool_template::set_no_zero_null): Assert string set is empty.
        (Stringpool_template::new_key_offset): New method declaration.
        flags and attributes merging if an input file is a binary file.
        * fileread.cc (Input_file::open): Record format of original file.
        * fileread.h (Input_file::Format): New enum type.
-       (Input_file::Input_file): Initialize data member format_.
+       (Input_file::Input_file): Initialize data member format_.
        (Input_file::format): New method definition.
        (Input_file::format_):: New data member.
 
        (Arm_output_section::fix_exidx_coverage): Add a parameter for layout.
        If user uses a script with a SECTIONS clause, issue only a warning
        for a misplaced EXIDX input section.  Otherwise, issue an error.
-       (Arm_relobj::do_gc_process_relocs): Exit early if we are not doing
+       (Arm_relobj::do_gc_process_relocs): Exit early if we are not doing
        garbage collection.
        (Target_arm::got_mode_index_entry): Handle static linking.
        (Target_arm::Scan::local): Ditto.
 
        * arm.cc (Arm_relocate_functions::arm_branch_common): Fix bug in
        handling of the maximum backward branch offset.
-       (Arm_relocate_functions::thumb_branch_common): Ditto.
+       (Arm_relocate_functions::thumb_branch_common): Ditto.
        * testsuite/Makefile.am (check_SCRIPTS): Add arm_branch_in_range.sh.
        (check_DATA): Add arm_bl_in_range.stdout, arm_bl_out_of_range.stdout
        thumb_bl_in_range.stdout, thumb_bl_out_of_range.stdout,
        (Target_arm::optimize_tls_reloc, Target_arm::define_tls_base_symbol,
         Target_arm::got_mod_index_entry, Target_arm::rel_tls_desc_section):
        New methods.
-       (Target_arm::Got_type): Add GOT_TYPE_TLS_NOFFSET, GOT_TYPE_OFFSET,
+       (Target_arm::Got_type): Add GOT_TYPE_TLS_NOFFSET, GOT_TYPE_OFFSET,
        GOT_TYPE_TLS_PAIR and GOT_TYPE_TLS_DESC.
        (Target_arm::got_mod_index_offset_,
        Target_arm::tls_base_symbol_defined_): New data members.
 
        * Makefile.am (HFILES): Add arm-reloc-property.h.
        (DEFFILES): New.
-       (TARGETSOURCES): Add arm-reloc-property.cc
-       (ALL_TARGETOBJS): Add arm-reloc-property.$(OBJEXT)
+       (TARGETSOURCES): Add arm-reloc-property.cc
+       (ALL_TARGETOBJS): Add arm-reloc-property.$(OBJEXT)
        (libgold_a_SOURCES): $(DEFFILES)
        * Makefile.in: Regenerate.
        * arm-reloc-property.cc: New file.
        * arm.cc (set): Include.
        (class Arm_exidx_fixup): Change type of last_input_section_ to const
        pointer type.
-       (Arm_output_section::Text_section_list): New type.
+       (Arm_output_section::Text_section_list): New type.
        (Arm_output_section::append_text_sections_to_list): New method.
        (Arm_output_section::fix_exidx_coverage): Ditto.
        (Arm_relobj::Arm_relobj): Initialize exidx_section_map_.
-       (Arm_relobj::convert_input_section_to_relaxed_section): Use
+       (Arm_relobj::convert_input_section_to_relaxed_section): Use
        Relobj::set_section_offset() instead of
        Sized_relobj::invalidate_section_offset().
-       (Arm_relobj::section_needs_reloc_stub_scanning): Add an extra
+       (Arm_relobj::section_needs_reloc_stub_scanning): Add an extra
        parameter for section headers. Ignore relocation sections for
        unallocated sections and EXIDX sections.
        (Target_arm::fix_exidx_coverage): New method.
        (Arm_output_section::append_text_sections_to_list): New method.
        (Arm_output_section::fix_exidx_coverage): Ditto.
        (Arm_relobj::scan_sections_for_stubs): Adjust call to
-       Arm_relobj::section_needs_reloc_stub_scanning.
+       Arm_relobj::section_needs_reloc_stub_scanning.
        (Target_arm::do_relax): Fix EXIDX output section coverage in the
        first pass.
        (Target_arm::fix_exidx_coverage): New method.
        (Output_section::add_merge_input_section): Ditto.
        (Output_section::build_relaxation_map): Change to use Section_id
        instead of Input_section_specifier as key type.
-       (Output_section::convert_input_sections_in_list_to_relaxed_sections):
+       (Output_section::convert_input_sections_in_list_to_relaxed_sections):
        Ditto.
        (Output_section::convert_input_sections_to_relaxed_sections): Change
        to use Const_section_id instead of Input_section_specifier as key type.
-       (Output_section::find_merge_section): Ditto.
+       (Output_section::find_merge_section): Ditto.
        (Output_section::find_relaxed_input_section): Ditto.
        * output.h (Input_section_specifier): Remove class.
        (Output_section::Output_section_data_by_input_section_map): Change
           Stub_table::update_data_size_and_addralign,
           Stub_table::apply_cortex_a8_workaround_to_address_range): New method
          definitions.
-         (Stub_table::relocate_stubs): Handle Cortex-A8 stubs.
+         (Stub_table::relocate_stubs): Handle Cortex-A8 stubs.
          (Stub_table::do_write): Ditto.
          (Target_arm::do_relax): Adjust code for changes in Stub_table.
 
        (Arm_dynobj::attributes_section_data_): New data member declaration.
        (Target_arm::Target_arm): Initialize attributes_section_data_.  Change
        initialization value of may_use_blx_ to false.
-       (Target_arm::using_thumb2, Target_arm::using_thumb_only,
+       (Target_arm::using_thumb2, Target_arm::using_thumb_only,
        Target_arm::may_use_arm_nop, Target_arm::may_use_thumb2_nop): Use
        object attributes to compute results instead of hard-coding.
        (Target_arm::do_attribute_arg_type, Target_arm::do_attributes_order,
        base class initializer.
        (Output_section::add_relaxed_input_section): New method declaration.
        (Output_section::Input_section): Change visibility to protected.
-       (Output_section::Input_section::relobj,
+       (Output_section::Input_section::relobj,
        Output_section::Input_section::shndx): Handle relaxed input sections.
        Output_section::input_sections) Change visibility to protected.  Also
        define overload to return a non-const pointer.
        Output_section_data.
        (Output_data_dynamic::set_final_data_size): Add DT_NULL tag only once.
        (Output_symtab_xindex::do_write): Add array bound check.
-       (Output_section::Input_section::print_to_mapfile): Handle
+       (Output_section::Input_section::print_to_mapfile): Handle
        RELAXED_INPUT_SECTION_CODE.
        (Output_section::Output_section): Initialize data member checkpoint_.
        (Output_section::~Output_section): Delete checkpoint object pointed
        an elfcpp:Ehdr as parameter.
        * target.cc: Include dynobj.h.
        (Target::do_make_elf_object_implementation): New.
-       (Target::do_make_elf_object): New.
+       (Target::do_make_elf_object): New.
        * target.h (Target::make_elf_object): New template declaration.
        (Target::do_make_elf_object): New method declarations.
        (Target::do_make_elf_object_implementation): New template declaration.
 
        * Makefile.am (libgold_a_LIBADD): New.
        (ld_new_DEPENDENCIES, ld_new_LDADD): Remove LIBOBJS
-       * Makefile.in: Regenerate.
+       * Makefile.in: Regenerate.
        * config.in (HAVE_DECL_MEMMEM, HAVE_DECL_STRNDUP): New.
        * configure: Regenerate.
        * configure.ac (AC_CHECK_DECLS): Add strndup and memmem.
        dispositions.
        * options.cc (General_options::parse_incremental_changed): New
        function.
-        (General_options::parse_incremental_unchanged): New function.
-        (General_options::parse_incremental_unknown): New function.
-        (General_options::General_options): Initialize new fields
+       (General_options::parse_incremental_unchanged): New function.
+       (General_options::parse_incremental_unknown): New function.
+       (General_options::General_options): Initialize new fields
        incremental_disposition_ and implicit_incremental_.
-        (General_options::finalize): Check for uasge of --incremental-*
+       (General_options::finalize): Check for uasge of --incremental-*
        without --incremental.
 
 2009-02-06  Chris Demetriou  <cgd@google.com>
 2009-01-31  Mikolaj Zalewski  <mikolajz@google.com>
 
        * script.cc (Lazy_demangler): New class.
-        (Version_script_info::get_symbol_version_helper): Demangle a
+       (Version_script_info::get_symbol_version_helper): Demangle a
        symbol only once.
 
 2009-01-29  Cary Coutant  <ccoutant@google.com>
index 7d4b7254b26bece5be3eac8d0348601e716e9c3f..72ffdf51dab3cabcfceff3b7b3a245b5c8f3ec7b 100644 (file)
@@ -64,6 +64,7 @@ CCFILES = \
        layout.cc \
        mapfile.cc \
        merge.cc \
+       nacl.cc \
        object.cc \
        options.cc \
        output.cc \
@@ -111,6 +112,7 @@ HFILES = \
        layout.h \
        mapfile.h \
        merge.h \
+       nacl.h \
        object.h \
        options.h \
        output.h \
index 2998b7bf61c107364f633f0b0e578166790aea0d..356b1d63282a95690c0287c8194f316bc759927f 100644 (file)
@@ -52,6 +52,7 @@ DIST_COMMON = NEWS README ChangeLog $(srcdir)/Makefile.in \
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
        $(top_srcdir)/../config/gettext-sister.m4 \
+       $(top_srcdir)/../config/lcmessage.m4 \
        $(top_srcdir)/../config/lead-dot.m4 \
        $(top_srcdir)/../config/nls.m4 \
        $(top_srcdir)/../config/override.m4 \
@@ -80,13 +81,14 @@ am__objects_1 = archive.$(OBJEXT) attributes.$(OBJEXT) \
        gdb-index.$(OBJEXT) gold.$(OBJEXT) gold-threads.$(OBJEXT) \
        icf.$(OBJEXT) incremental.$(OBJEXT) int_encoding.$(OBJEXT) \
        layout.$(OBJEXT) mapfile.$(OBJEXT) merge.$(OBJEXT) \
-       object.$(OBJEXT) options.$(OBJEXT) output.$(OBJEXT) \
-       parameters.$(OBJEXT) plugin.$(OBJEXT) readsyms.$(OBJEXT) \
-       reduced_debug_output.$(OBJEXT) reloc.$(OBJEXT) \
-       resolve.$(OBJEXT) script-sections.$(OBJEXT) script.$(OBJEXT) \
-       stringpool.$(OBJEXT) symtab.$(OBJEXT) target.$(OBJEXT) \
-       target-select.$(OBJEXT) timer.$(OBJEXT) version.$(OBJEXT) \
-       workqueue.$(OBJEXT) workqueue-threads.$(OBJEXT)
+       nacl.$(OBJEXT) object.$(OBJEXT) options.$(OBJEXT) \
+       output.$(OBJEXT) parameters.$(OBJEXT) plugin.$(OBJEXT) \
+       readsyms.$(OBJEXT) reduced_debug_output.$(OBJEXT) \
+       reloc.$(OBJEXT) resolve.$(OBJEXT) script-sections.$(OBJEXT) \
+       script.$(OBJEXT) stringpool.$(OBJEXT) symtab.$(OBJEXT) \
+       target.$(OBJEXT) target-select.$(OBJEXT) timer.$(OBJEXT) \
+       version.$(OBJEXT) workqueue.$(OBJEXT) \
+       workqueue-threads.$(OBJEXT)
 am__objects_2 =
 am__objects_3 = yyscript.$(OBJEXT)
 am_libgold_a_OBJECTS = $(am__objects_1) $(am__objects_2) \
@@ -408,6 +410,7 @@ CCFILES = \
        layout.cc \
        mapfile.cc \
        merge.cc \
+       nacl.cc \
        object.cc \
        options.cc \
        output.cc \
@@ -455,6 +458,7 @@ HFILES = \
        layout.h \
        mapfile.h \
        merge.h \
+       nacl.h \
        object.h \
        options.h \
        output.h \
@@ -664,6 +668,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mapfile.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/merge.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nacl.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Po@am__quote@
index 1ddbf7f95ec8a51f7262053974a6dd32af22c456..92735ea84a2cb401945bd44322d337b1d1580711 100644 (file)
@@ -51,6 +51,7 @@
 #include "gc.h"
 #include "attributes.h"
 #include "arm-reloc-property.h"
+#include "nacl.h"
 
 namespace
 {
@@ -60,6 +61,9 @@ using namespace gold;
 template<bool big_endian>
 class Output_data_plt_arm;
 
+template<bool big_endian>
+class Output_data_plt_arm_standard;
+
 template<bool big_endian>
 class Stub_table;
 
@@ -107,7 +111,7 @@ const size_t ARM_TCB_SIZE = 8;
 //
 // This is a very simple port of gold for ARM-EABI.  It is intended for
 // supporting Android only for the time being.
-// 
+//
 // TODOs:
 // - Implement all static relocation types documented in arm-reloc.def.
 // - Make PLTs more flexible for different architecture features like
@@ -138,7 +142,7 @@ class Insn_template
   enum Type
     {
       THUMB16_TYPE = 1,
-      // THUMB16_SPECIAL_TYPE is used by sub-classes of Stub for instruction 
+      // THUMB16_SPECIAL_TYPE is used by sub-classes of Stub for instruction
       // templates with class-specific semantics.  Currently this is used
       // only by the Cortex_a8_stub class for handling condition codes in
       // conditional branches.
@@ -152,24 +156,24 @@ class Insn_template
 
   static const Insn_template
   thumb16_insn(uint32_t data)
-  { return Insn_template(data, THUMB16_TYPE, elfcpp::R_ARM_NONE, 0); } 
+  { return Insn_template(data, THUMB16_TYPE, elfcpp::R_ARM_NONE, 0); }
 
   // A Thumb conditional branch, in which the proper condition is inserted
   // when we build the stub.
   static const Insn_template
   thumb16_bcond_insn(uint32_t data)
-  { return Insn_template(data, THUMB16_SPECIAL_TYPE, elfcpp::R_ARM_NONE, 1); } 
+  { return Insn_template(data, THUMB16_SPECIAL_TYPE, elfcpp::R_ARM_NONE, 1); }
 
   static const Insn_template
   thumb32_insn(uint32_t data)
-  { return Insn_template(data, THUMB32_TYPE, elfcpp::R_ARM_NONE, 0); } 
+  { return Insn_template(data, THUMB32_TYPE, elfcpp::R_ARM_NONE, 0); }
 
   static const Insn_template
   thumb32_b_insn(uint32_t data, int reloc_addend)
   {
     return Insn_template(data, THUMB32_TYPE, elfcpp::R_ARM_THM_JUMP24,
                         reloc_addend);
-  } 
+  }
 
   static const Insn_template
   arm_insn(uint32_t data)
@@ -181,7 +185,7 @@ class Insn_template
 
   static const Insn_template
   data_word(unsigned data, unsigned int r_type, int reloc_addend)
-  { return Insn_template(data, DATA_TYPE, r_type, reloc_addend); } 
+  { return Insn_template(data, DATA_TYPE, r_type, reloc_addend); }
 
   // Accessors.  This class is used for read-only objects so no modifiers
   // are provided.
@@ -270,7 +274,7 @@ typedef enum
     arm_stub_cortex_a8_first = arm_stub_a8_veneer_b_cond,
     // Last Cortex-A8 stub type.
     arm_stub_cortex_a8_last = arm_stub_a8_veneer_blx,
-    
+
     // Last stub type.
     arm_stub_type_last = arm_stub_v4_veneer_bx
   } Stub_type;
@@ -312,7 +316,7 @@ class Stub_template
   unsigned
   alignment() const
   { return this->alignment_; }
-  
+
   // Return whether entry point is in thumb mode.
   bool
   entry_in_thumb_mode() const
@@ -349,7 +353,7 @@ class Stub_template
   // as possible.
   Stub_template(const Stub_template&);
   Stub_template& operator=(const Stub_template&);
-  
+
   // Stub type.
   Stub_type type_;
   // Points to an array of Insn_templates.
@@ -364,7 +368,7 @@ class Stub_template
   bool entry_in_thumb_mode_;
   // A table of reloc instruction indices and offsets.  We can find these by
   // looking at the instruction templates but we pre-compute and then stash
-  // them here for speed. 
+  // them here for speed.
   std::vector<Reloc> relocs_;
 };
 
@@ -405,7 +409,7 @@ class Stub
   void
   set_offset(section_offset_type offset)
   { this->offset_ = offset; }
-  
+
   // Return the relocation target address of the i-th relocation in the
   // stub.  This must be defined in a child class.
   Arm_address
@@ -437,7 +441,7 @@ class Stub
     else
       this->do_fixed_endian_write<false>(view, view_size);
   }
-  
+
   // This must be overridden if a child class uses the THUMB16_SPECIAL_TYPE
   // instruction template.
   virtual uint16_t
@@ -550,7 +554,7 @@ class Reloc_stub : public Stub
 
     // Whether this equals to another key k.
     bool
-    eq(const Key& k) const 
+    eq(const Key& k) const
     {
       return ((this->stub_type_ == k.stub_type_)
              && (this->r_sym_ == k.r_sym_)
@@ -600,7 +604,7 @@ class Reloc_stub : public Stub
     unsigned int r_sym_;
     // If r_sym_ is an invalid index, this points to a global symbol.
     // Otherwise, it points to a relobj.  We used the unsized and target
-    // independent Symbol and Relobj classes instead of Sized_symbol<32> and  
+    // independent Symbol and Relobj classes instead of Sized_symbol<32> and
     // Arm_relobj, in order to avoid making the stub class a template
     // as most of the stub machinery is endianness-neutral.  However, it
     // may require a bit of casting done by users of this class.
@@ -641,7 +645,7 @@ class Reloc_stub : public Stub
 
 // Cortex-A8 stub class.  We need a Cortex-A8 stub to redirect any 32-bit
 // THUMB branch that meets the following conditions:
-// 
+//
 // 1. The branch straddles across a page boundary. i.e. lower 12-bit of
 //    branch address is 0xffe.
 // 2. The branch target address is in the same page as the first word of the
@@ -715,15 +719,15 @@ class Cortex_a8_stub : public Stub
   {
     if (this->stub_template()->type() == arm_stub_a8_veneer_b_cond)
       {
-        // The conditional branch veneer has two relocations.
-        gold_assert(i < 2);
+       // The conditional branch veneer has two relocations.
+       gold_assert(i < 2);
        return i == 0 ? this->source_address_ + 4 : this->destination_address_;
       }
     else
       {
-        // All other Cortex-A8 stubs have only one relocation.
-        gold_assert(i == 0);
-        return this->destination_address_;
+       // All other Cortex-A8 stubs have only one relocation.
+       gold_assert(i == 0);
+       return this->destination_address_;
       }
   }
 
@@ -850,13 +854,13 @@ class Stub_factory
  private:
   // Constructor and destructor are protected since we only return a single
   // instance created in Stub_factory::get_instance().
-  
+
   Stub_factory();
 
   // A Stub_factory may not be copied since it is a singleton.
   Stub_factory(const Stub_factory&);
   Stub_factory& operator=(Stub_factory&);
-  
+
   // Stub templates.  These are initialized in the constructor.
   const Stub_template* stub_templates_[arm_stub_type_last+1];
 };
@@ -970,7 +974,7 @@ class Stub_table : public Output_data
   // needing the Cortex-A8 workaround.
   void
   finalize_stubs();
-  
+
   // Apply Cortex-A8 workaround to an address range.
   void
   apply_cortex_a8_workaround_to_address_range(Target_arm<big_endian>*,
@@ -981,7 +985,7 @@ class Stub_table : public Output_data
   // Write out section contents.
   void
   do_write(Output_file*);
+
   // Return the required alignment.
   uint64_t
   do_addralign() const
@@ -996,7 +1000,7 @@ class Stub_table : public Output_data
   void
   set_final_data_size()
   { this->set_data_size(this->current_data_size()); }
-  
+
  private:
   // Relocate one stub.
   void
@@ -1074,7 +1078,7 @@ class Arm_exidx_cantunwind : public Output_section_data
   template<bool big_endian>
   void inline
   do_fixed_endian_write(Output_file*);
-  
+
   // The object containing the section pointed by this.
   Relobj* relobj_;
   // The section index of the section pointed by this.
@@ -1083,7 +1087,7 @@ class Arm_exidx_cantunwind : public Output_section_data
 
 // During EXIDX coverage fix-up, we compact an EXIDX section.  The
 // Offset map is used to map input section offset within the EXIDX section
-// to the output offset from the start of this EXIDX section. 
+// to the output offset from the start of this EXIDX section.
 
 typedef std::map<section_offset_type, section_offset_type>
        Arm_exidx_section_offset_map;
@@ -1132,7 +1136,7 @@ class Arm_exidx_merged_section : public Output_relaxed_input_section
   const Arm_exidx_input_section& exidx_input_section_;
   // Section offset map.
   const Arm_exidx_section_offset_map& section_offset_map_;
-  // Merged section contents.  We need to keep build the merged section 
+  // Merged section contents.  We need to keep build the merged section
   // and save it here to avoid accessing the original EXIDX section when
   // we cannot lock the sections' object.
   unsigned char* section_contents_;
@@ -1156,7 +1160,7 @@ class Arm_input_section : public Output_relaxed_input_section
   // Initialize.
   void
   init();
-  
+
   // Whether this is a stub table owner.
   bool
   is_stub_table_owner() const
@@ -1211,7 +1215,7 @@ class Arm_input_section : public Output_relaxed_input_section
   bool
   do_output_offset(const Relobj* object, unsigned int shndx,
                   section_offset_type offset,
-                   section_offset_type* poutput) const
+                  section_offset_type* poutput) const
   {
     if ((object == this->relobj())
        && (shndx == this->shndx())
@@ -1272,7 +1276,7 @@ class Arm_exidx_fixup
                        const unsigned char* section_contents,
                        section_size_type section_size,
                        Arm_exidx_section_offset_map** psection_offset_map);
-  
+
   // Append an EXIDX_CANTUNWIND entry pointing at the end of the last
   // input section, if there is not one already.
   void
@@ -1356,7 +1360,7 @@ class Arm_output_section : public Output_section
 
   ~Arm_output_section()
   { }
-  
+
   // Group input sections for stub generation.
   void
   group_sections(section_size_type, bool, Target_arm<big_endian>*, const Task*);
@@ -1416,7 +1420,7 @@ class Arm_exidx_input_section
 
   ~Arm_exidx_input_section()
   { }
-       
+
   // Accessors:  This is a read-only class.
 
   // Return the object containing this EXIDX input section.
@@ -1485,7 +1489,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
   static const Arm_address invalid_address = static_cast<Arm_address>(-1);
 
   Arm_relobj(const std::string& name, Input_file* input_file, off_t offset,
-             const typename elfcpp::Ehdr<32, big_endian>& ehdr)
+            const typename elfcpp::Ehdr<32, big_endian>& ehdr)
     : Sized_relobj_file<32, big_endian>(name, input_file, offset, ehdr),
       stub_tables_(), local_symbol_is_thumb_function_(),
       attributes_section_data_(NULL), mapping_symbols_info_(),
@@ -1496,7 +1500,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
 
   ~Arm_relobj()
   { delete this->attributes_section_data_; }
+
   // Return the stub table of the SHNDX-th section if there is one.
   Stub_table<big_endian>*
   stub_table(unsigned int shndx) const
@@ -1521,7 +1525,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
     gold_assert(r_sym < this->local_symbol_is_thumb_function_.size());
     return this->local_symbol_is_thumb_function_[r_sym];
   }
-  
+
   // Scan all relocation sections for stub generation.
   void
   scan_sections_for_stubs(Target_arm<big_endian>*, const Symbol_table*,
@@ -1569,7 +1573,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
              || (p1.first == p2.first && p1.second < p2.second));
     }
   };
-  
+
   // We only care about the first character of a mapping symbol, so
   // we only store that instead of the whole symbol name.
   typedef std::map<Mapping_symbol_position, char,
@@ -1578,11 +1582,11 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
   // Whether a section contains any Cortex-A8 workaround.
   bool
   section_has_cortex_a8_workaround(unsigned int shndx) const
-  { 
+  {
     return (this->section_has_cortex_a8_workaround_ != NULL
            && (*this->section_has_cortex_a8_workaround_)[shndx]);
   }
-  
+
   // Mark a section that has Cortex-A8 workaround.
   void
   mark_section_for_cortex_a8_workaround(unsigned int shndx)
@@ -1625,7 +1629,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
   void
   set_output_local_symbol_count_needs_update()
   { this->output_local_symbol_count_needs_update_ = true; }
-  
+
   // Update output local symbol count at the end of relaxation.
   void
   update_output_local_symbol_count();
@@ -1634,7 +1638,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
   bool
   merge_flags_and_attributes() const
   { return this->merge_flags_and_attributes_; }
-  
+
   // Export list of EXIDX section indices.
   void
   get_exidx_shndx_list(std::vector<unsigned int>* list) const
@@ -1647,7 +1651,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
        if (p->second->shndx() == p->first)
          list->push_back(p->first);
       }
-    // Sort list to make result independent of implementation of map. 
+    // Sort list to make result independent of implementation of map.
     std::sort(list->begin(), list->end());
   }
 
@@ -1667,7 +1671,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
   // Count the local symbols.
   void
   do_count_local_symbols(Stringpool_template<char>*,
-                         Stringpool_template<char>*);
+                        Stringpool_template<char>*);
 
   void
   do_relocate_sections(
@@ -1769,7 +1773,7 @@ class Arm_dynobj : public Sized_dynobj<32, big_endian>
     : Sized_dynobj<32, big_endian>(name, input_file, offset, ehdr),
       processor_specific_flags_(0), attributes_section_data_(NULL)
   { }
+
   ~Arm_dynobj()
   { delete this->attributes_section_data_; }
 
@@ -1862,13 +1866,13 @@ class Cortex_a8_reloc
   { }
 
   // Accessors:  This is a read-only class.
-  
+
   // Return the relocation stub associated with this relocation if there is
   // one.
   const Reloc_stub*
   reloc_stub() const
-  { return this->reloc_stub_; } 
-  
+  { return this->reloc_stub_; }
+
   // Return the relocation type.
   unsigned int
   r_type() const
@@ -2076,7 +2080,7 @@ class Arm_scan_relocatable_relocs :
          case elfcpp::R_ARM_TARGET2:
            gold_unreachable();
          // Relocations that write full 32 bits and
-          // have alignment of 1.
+         // have alignment of 1.
          case elfcpp::R_ARM_ABS32:
          case elfcpp::R_ARM_REL32:
          case elfcpp::R_ARM_SBREL32:
@@ -2113,10 +2117,10 @@ class Target_arm : public Sized_target<32, big_endian>
   // When were are relocating a stub, we pass this as the relocation number.
   static const size_t fake_relnum_for_stubs = static_cast<size_t>(-1);
 
-  Target_arm()
-    : Sized_target<32, big_endian>(&arm_info),
+  Target_arm(const Target::Target_info* info = &arm_info)
+    : Sized_target<32, big_endian>(info),
       got_(NULL), plt_(NULL), got_plt_(NULL), rel_dyn_(NULL),
-      copy_relocs_(elfcpp::R_ARM_COPY), dynbss_(NULL), 
+      copy_relocs_(elfcpp::R_ARM_COPY), dynbss_(NULL),
       got_mod_index_offset_(-1U), tls_base_symbol_defined_(false),
       stub_tables_(), stub_factory_(Stub_factory::get_instance()),
       should_force_pic_veneer_(false),
@@ -2133,7 +2137,7 @@ class Target_arm : public Sized_target<32, big_endian>
   void
   set_should_force_pic_veneer(bool value)
   { this->should_force_pic_veneer_ = value; }
-  
+
   // Whether we use THUMB-2 instructions.
   bool
   using_thumb2() const
@@ -2196,7 +2200,7 @@ class Target_arm : public Sized_target<32, big_endian>
     return (arch != elfcpp::TAG_CPU_ARCH_PRE_V4
            && arch != elfcpp::TAG_CPU_ARCH_V4);
   }
-  
+
   // Whether we have v5T interworking instructions available.
   bool
   may_use_v5t_interworking() const
@@ -2215,8 +2219,8 @@ class Target_arm : public Sized_target<32, big_endian>
              && arch != elfcpp::TAG_CPU_ARCH_V4
              && arch != elfcpp::TAG_CPU_ARCH_V4T);
   }
-  
-  // Process the relocations to determine unreferenced sections for 
+
+  // Process the relocations to determine unreferenced sections for
   // garbage collection.
   void
   gc_process_relocs(Symbol_table* symtab,
@@ -2311,7 +2315,7 @@ class Target_arm : public Sized_target<32, big_endian>
                                 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(const Symbol* sym) const
@@ -2358,7 +2362,7 @@ class Target_arm : public Sized_target<32, big_endian>
   //
   // Methods to support stub-generations.
   //
-  
+
   // Return the stub factory
   const Stub_factory&
   stub_factory() const
@@ -2384,12 +2388,12 @@ class Target_arm : public Sized_target<32, big_endian>
                         bool, const unsigned char*, Arm_address,
                         section_size_type);
 
-  // Relocate a stub. 
+  // Relocate a stub.
   void
   relocate_stub(Stub*, const Relocate_info<32, big_endian>*,
                Output_section*, unsigned char*, Arm_address,
                section_size_type);
+
   // Get the default ARM target.
   static Target_arm<big_endian>*
   default_target()
@@ -2440,6 +2444,11 @@ class Target_arm : public Sized_target<32, big_endian>
                             unsigned char*, Arm_address);
 
  protected:
+  // Make the PLT-generator object.
+  Output_data_plt_arm<big_endian>*
+  make_data_plt(Layout* layout, Output_data_space* got_plt)
+  { return this->do_make_data_plt(layout, got_plt); }
+
   // Make an ELF object.
   Object*
   do_make_elf_object(const std::string&, Input_file*, off_t,
@@ -2514,10 +2523,16 @@ class Target_arm : public Sized_target<32, big_endian>
            && !is_prefix_of(".ARM.extab", section_name)
            && Target::do_section_may_have_icf_unsafe_pointers(section_name));
   }
-  
+
   virtual void
   do_define_standard_symbols(Symbol_table*, Layout*);
 
+  virtual Output_data_plt_arm<big_endian>*
+  do_make_data_plt(Layout* layout, Output_data_space* got_plt)
+  {
+    return new Output_data_plt_arm_standard<big_endian>(layout, got_plt);
+  }
+
  private:
   // The class which scans relocations.
   class Scan
@@ -2548,19 +2563,19 @@ class Target_arm : public Sized_target<32, big_endian>
 
     inline bool
     local_reloc_may_be_function_pointer(Symbol_table* , Layout* , Target_arm* ,
-                                       Sized_relobj_file<32, big_endian>* ,
-                                       unsigned int ,
-                                       Output_section* ,
-                                       const elfcpp::Rel<32, big_endian>& ,
+                                       Sized_relobj_file<32, big_endian>* ,
+                                       unsigned int ,
+                                       Output_section* ,
+                                       const elfcpp::Rel<32, big_endian>& ,
                                        unsigned int ,
-                                       const elfcpp::Sym<32, big_endian>&);
+                                       const elfcpp::Sym<32, big_endian>&);
 
     inline bool
     global_reloc_may_be_function_pointer(Symbol_table* , Layout* , Target_arm* ,
-                                        Sized_relobj_file<32, big_endian>* ,
-                                        unsigned int ,
-                                        Output_section* ,
-                                        const elfcpp::Rel<32, big_endian>& ,
+                                        Sized_relobj_file<32, big_endian>* ,
+                                        unsigned int ,
+                                        Output_section* ,
+                                        const elfcpp::Rel<32, big_endian>& ,
                                         unsigned int , Symbol*);
 
    private:
@@ -2667,7 +2682,7 @@ class Target_arm : public Sized_target<32, big_endian>
     // Do a TLS relocation.
     inline typename Arm_relocate_functions<big_endian>::Status
     relocate_tls(const Relocate_info<32, big_endian>*, Target_arm<big_endian>*,
-                 size_t, const elfcpp::Rel<32, big_endian>&, unsigned int,
+                size_t, const elfcpp::Rel<32, big_endian>&, unsigned int,
                 const Sized_symbol<32>*, const Symbol_value<32>*,
                 unsigned char*, elfcpp::Elf_types<32>::Elf_Addr,
                 section_size_type);
@@ -2862,7 +2877,7 @@ class Target_arm : public Sized_target<32, big_endian>
                        Arm_input_section<big_endian>*,
                        Section_id_hash>
          Arm_input_section_map;
-    
+
   // Map output addresses to relocs for Cortex-A8 erratum.
   typedef Unordered_map<Arm_address, const Cortex_a8_reloc*>
          Cortex_a8_relocs_info;
@@ -2915,6 +2930,8 @@ const Target::Target_info Target_arm<big_endian>::arm_info =
   0x8000,              // default_text_segment_address
   0x1000,              // abi_pagesize (overridable by -z max-page-size)
   0x1000,              // common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
   elfcpp::SHN_UNDEF,   // small_common_shndx
   elfcpp::SHN_UNDEF,   // large_common_shndx
   0,                   // small_common_section_flags
@@ -2943,10 +2960,10 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
 
   // Encoding of imm16 argument for movt and movw ARM instructions
   // from ARM ARM:
-  //     
+  //
   //     imm16 := imm4 | imm12
   //
-  //  f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0 
+  //  f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0
   // +-------+---------------+-------+-------+-----------------------+
   // |       |               |imm4   |       |imm12                  |
   // +-------+---------------+-------+-------+-----------------------+
@@ -2977,10 +2994,10 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
 
   // Encoding of imm16 argument for movt and movw Thumb2 instructions
   // from ARM ARM:
-  //     
+  //
   //     imm16 := imm4 | i | imm3 | imm8
   //
-  //  f e d c b a 9 8 7 6 5 4 3 2 1 0  f e d c b a 9 8 7 6 5 4 3 2 1 0 
+  //  f e d c b a 9 8 7 6 5 4 3 2 1 0  f e d c b a 9 8 7 6 5 4 3 2 1 0
   // +---------+-+-----------+-------++-+-----+-------+---------------+
   // |         |i|           |imm4   || |imm3 |       |imm8           |
   // +---------+-+-----------+-------++-+-----+-------+---------------+
@@ -3128,9 +3145,9 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
     uint32_t s = offset < 0 ? 1 : 0;
     uint32_t bits = static_cast<uint32_t>(offset);
     return ((lower_insn & ~0x2fffU)
-            | ((((bits >> 23) & 1) ^ !s) << 13)
-            | ((((bits >> 22) & 1) ^ !s) << 11)
-            | ((bits >> 1) & 0x7ffU));
+           | ((((bits >> 23) & 1) ^ !s) << 13)
+           | ((((bits >> 22) & 1) ^ !s) << 11)
+           | ((bits >> 1) & 0x7ffU));
   }
 
   // Return the branch offset of a 32-bit THUMB conditional branch.
@@ -3319,7 +3336,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
     int32_t addend = Bits<8>::sign_extend32((val & 0x00ff) << 1);
     int32_t x = (psymval->value(object, addend) - address);
     elfcpp::Swap<16, big_endian>::writeval(wv, ((val & 0xff00)
-                                                | ((x & 0x01fe) >> 1)));
+                                               | ((x & 0x01fe) >> 1)));
     // We do a 9-bit overflow check because x is right-shifted by 1 bit.
     return (Bits<9>::has_overflow32(x)
            ? This::STATUS_OVERFLOW
@@ -3339,7 +3356,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
     int32_t addend = Bits<11>::sign_extend32((val & 0x07ff) << 1);
     int32_t x = (psymval->value(object, addend) - address);
     elfcpp::Swap<16, big_endian>::writeval(wv, ((val & 0xf800)
-                                                | ((x & 0x0ffe) >> 1)));
+                                               | ((x & 0x0ffe) >> 1)));
     // We do a 12-bit overflow check because x is right-shifted by 1 bit.
     return (Bits<12>::has_overflow32(x)
            ? This::STATUS_OVERFLOW
@@ -3472,7 +3489,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
     elfcpp::Swap<16, big_endian>::writeval(wv, val >> 16);
     elfcpp::Swap<16, big_endian>::writeval(wv + 1, val & 0xffff);
     return ((check_overflow && Bits<16>::has_overflow32(x))
-           ? This::STATUS_OVERFLOW
+           ? This::STATUS_OVERFLOW
            : This::STATUS_OKAY);
   }
 
@@ -3549,7 +3566,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
     elfcpp::Swap<16, big_endian>::writeval(wv, insn >> 16);
     elfcpp::Swap<16, big_endian>::writeval(wv + 1, insn & 0xffff);
     return ((val > 0xfff) ?
-           This::STATUS_OVERFLOW : This::STATUS_OKAY);
+           This::STATUS_OVERFLOW : This::STATUS_OKAY);
   }
 
   // R_ARM_THM_PC8: S + A - Pa (Thumb)
@@ -3604,7 +3621,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
     elfcpp::Swap<16, big_endian>::writeval(wv, insn >> 16);
     elfcpp::Swap<16, big_endian>::writeval(wv + 1, insn & 0xffff);
     return ((val > 0xfff) ?
-           This::STATUS_OVERFLOW : This::STATUS_OKAY);
+           This::STATUS_OVERFLOW : This::STATUS_OKAY);
   }
 
   // R_ARM_V4BX
@@ -3849,9 +3866,9 @@ Arm_relocate_functions<big_endian>::arm_branch_common(
   typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
   Valtype* wv = reinterpret_cast<Valtype*>(view);
   Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
-     
+
   bool insn_is_b = (((val >> 28) & 0xf) <= 0xe)
-                   && ((val & 0x0f000000UL) == 0x0a000000UL);
+                   && ((val & 0x0f000000UL) == 0x0a000000UL);
   bool insn_is_uncond_bl = (val & 0xff000000UL) == 0xeb000000UL;
   bool insn_is_cond_bl = (((val >> 28) & 0xf) < 0xe)
                          && ((val & 0x0f000000UL) == 0x0b000000UL);
@@ -3902,7 +3919,7 @@ Arm_relocate_functions<big_endian>::arm_branch_common(
       elfcpp::Swap<32, big_endian>::writeval(wv, val);
       return This::STATUS_OKAY;
     }
+
   Valtype addend = Bits<26>::sign_extend32(val << 2);
   Valtype branch_target = psymval->value(object, addend);
   int32_t branch_offset = branch_target - address;
@@ -3984,7 +4001,7 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
   // into account.
   bool is_bl_insn = (lower_insn & 0x1000U) == 0x1000U;
   bool is_blx_insn = (lower_insn & 0x1000U) == 0x0000U;
-     
+
   // Check that the instruction is valid.
   if (r_type == elfcpp::R_ARM_THM_CALL)
     {
@@ -4007,7 +4024,7 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
          gold_warning(_("%s: Thumb BLX instruction targets "
                         "thumb function '%s'."),
                         object->name().c_str(),
-                        (gsym ? gsym->name() : "(local)")); 
+                        (gsym ? gsym->name() : "(local)"));
          // Convert BLX to BL.
          lower_insn |= 0x1000U;
        }
@@ -4036,7 +4053,7 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
        }
       return This::STATUS_OKAY;
     }
+
   int32_t addend = This::thumb32_branch_offset(upper_insn, lower_insn);
   Arm_address branch_target = psymval->value(object, addend);
 
@@ -4075,7 +4092,7 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
          gold_assert(stub != NULL);
          thumb_bit = stub->stub_template()->entry_in_thumb_mode() ? 1 : 0;
          branch_target = stub_table->address() + stub->offset() + addend;
-         if (thumb_bit == 0 && may_use_blx) 
+         if (thumb_bit == 0 && may_use_blx)
            branch_target = Bits<32>::bit_select32(branch_target, address, 0x2);
          branch_offset = branch_target - address;
        }
@@ -4301,11 +4318,11 @@ Stub_template::Stub_template(
          break;
 
        case Insn_template::THUMB32_TYPE:
-          if (insns[i].r_type() != elfcpp::R_ARM_NONE)
+         if (insns[i].r_type() != elfcpp::R_ARM_NONE)
            this->relocs_.push_back(Reloc(i, offset));
          if (i == 0)
            this->entry_in_thumb_mode_ = true;
-          break;
+         break;
 
        case Insn_template::ARM_TYPE:
          // Handle cases where the target is encoded within the
@@ -4323,7 +4340,7 @@ Stub_template::Stub_template(
        default:
          gold_unreachable();
        }
-      offset += insn_size; 
+      offset += insn_size;
     }
   this->size_ = offset;
 }
@@ -4360,7 +4377,7 @@ Stub::do_fixed_endian_write(unsigned char* view, section_size_type view_size)
            elfcpp::Swap<16, big_endian>::writeval(pov, hi);
            elfcpp::Swap<16, big_endian>::writeval(pov + 2, lo);
          }
-          break;
+         break;
        case Insn_template::ARM_TYPE:
        case Insn_template::DATA_TYPE:
          elfcpp::Swap<32, big_endian>::writeval(pov, insns[i].data());
@@ -4371,7 +4388,7 @@ Stub::do_fixed_endian_write(unsigned char* view, section_size_type view_size)
       pov += insns[i].size();
     }
   gold_assert(static_cast<section_size_type>(pov - view) == view_size);
-} 
+}
 
 // Reloc_stub::Key methods.
 
@@ -4460,7 +4477,7 @@ Reloc_stub::stub_type_for_reloc(
       if ((r_type == elfcpp::R_ARM_THM_CALL) && may_use_blx && !target_is_thumb)
        destination = Bits<32>::bit_select32(destination, location, 0x2);
       branch_offset = static_cast<int64_t>(destination) - location;
-       
+
       // Handle cases where:
       // - this call goes too far (different Thumb/Thumb2 max
       //   distance)
@@ -4511,7 +4528,7 @@ Reloc_stub::stub_type_for_reloc(
          else
            {
              // Thumb to arm.
-            
+
              // FIXME: We should check that the input section is from an
              // object that has interwork enabled.
 
@@ -4612,16 +4629,16 @@ Stub_factory::Stub_factory()
 {
   // The instruction template sequences are declared as static
   // objects and initialized first time the constructor runs.
+
   // Arm/Thumb -> Arm/Thumb long branch stub. On V5T and above, use blx
   // to reach the stub if necessary.
   static const Insn_template elf32_arm_stub_long_branch_any_any[] =
     {
       Insn_template::arm_insn(0xe51ff004),     // ldr   pc, [pc, #-4]
       Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0),
-                                               // dcd   R_ARM_ABS32(X)
+                                               // dcd   R_ARM_ABS32(X)
     };
-  
+
   // V4T Arm -> Thumb long branch stub. Used on V4T where blx is not
   // available.
   static const Insn_template elf32_arm_stub_long_branch_v4t_arm_thumb[] =
@@ -4629,9 +4646,9 @@ Stub_factory::Stub_factory()
       Insn_template::arm_insn(0xe59fc000),     // ldr   ip, [pc, #0]
       Insn_template::arm_insn(0xe12fff1c),     // bx    ip
       Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0),
-                                               // dcd   R_ARM_ABS32(X)
+                                               // dcd   R_ARM_ABS32(X)
     };
-  
+
   // Thumb -> Thumb long branch stub. Used on M-profile architectures.
   static const Insn_template elf32_arm_stub_long_branch_thumb_only[] =
     {
@@ -4642,9 +4659,9 @@ Stub_factory::Stub_factory()
       Insn_template::thumb16_insn(0x4760),     // bx   ip
       Insn_template::thumb16_insn(0xbf00),     // nop
       Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0),
-                                               // dcd  R_ARM_ABS32(X)
+                                               // dcd  R_ARM_ABS32(X)
     };
-  
+
   // V4T Thumb -> Thumb long branch stub. Using the stack is not
   // allowed.
   static const Insn_template elf32_arm_stub_long_branch_v4t_thumb_thumb[] =
@@ -4654,9 +4671,9 @@ Stub_factory::Stub_factory()
       Insn_template::arm_insn(0xe59fc000),     // ldr  ip, [pc, #0]
       Insn_template::arm_insn(0xe12fff1c),     // bx   ip
       Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0),
-                                               // dcd  R_ARM_ABS32(X)
+                                               // dcd  R_ARM_ABS32(X)
     };
-  
+
   // V4T Thumb -> ARM long branch stub. Used on V4T where blx is not
   // available.
   static const Insn_template elf32_arm_stub_long_branch_v4t_thumb_arm[] =
@@ -4665,9 +4682,9 @@ Stub_factory::Stub_factory()
       Insn_template::thumb16_insn(0x46c0),     // nop
       Insn_template::arm_insn(0xe51ff004),     // ldr   pc, [pc, #-4]
       Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0),
-                                               // dcd   R_ARM_ABS32(X)
+                                               // dcd   R_ARM_ABS32(X)
     };
-  
+
   // V4T Thumb -> ARM short branch stub. Shorter variant of the above
   // one, when the destination is close enough.
   static const Insn_template elf32_arm_stub_short_branch_v4t_thumb_arm[] =
@@ -4676,7 +4693,7 @@ Stub_factory::Stub_factory()
       Insn_template::thumb16_insn(0x46c0),             // nop
       Insn_template::arm_rel_insn(0xea000000, -8),     // b    (X-8)
     };
-  
+
   // ARM/Thumb -> ARM long branch stub, PIC.  On V5T and above, use
   // blx to reach the stub if necessary.
   static const Insn_template elf32_arm_stub_long_branch_any_arm_pic[] =
@@ -4684,9 +4701,9 @@ Stub_factory::Stub_factory()
       Insn_template::arm_insn(0xe59fc000),     // ldr   r12, [pc]
       Insn_template::arm_insn(0xe08ff00c),     // add   pc, pc, ip
       Insn_template::data_word(0, elfcpp::R_ARM_REL32, -4),
-                                               // dcd   R_ARM_REL32(X-4)
+                                               // dcd   R_ARM_REL32(X-4)
     };
-  
+
   // ARM/Thumb -> Thumb long branch stub, PIC.  On V5T and above, use
   // blx to reach the stub if necessary.  We can not add into pc;
   // it is not guaranteed to mode switch (different in ARMv6 and
@@ -4697,9 +4714,9 @@ Stub_factory::Stub_factory()
       Insn_template::arm_insn(0xe08fc00c),     // add   ip, pc, ip
       Insn_template::arm_insn(0xe12fff1c),     // bx    ip
       Insn_template::data_word(0, elfcpp::R_ARM_REL32, 0),
-                                               // dcd   R_ARM_REL32(X)
+                                               // dcd   R_ARM_REL32(X)
     };
-  
+
   // V4T ARM -> ARM long branch stub, PIC.
   static const Insn_template elf32_arm_stub_long_branch_v4t_arm_thumb_pic[] =
     {
@@ -4707,9 +4724,9 @@ Stub_factory::Stub_factory()
       Insn_template::arm_insn(0xe08fc00c),     // add   ip, pc, ip
       Insn_template::arm_insn(0xe12fff1c),     // bx    ip
       Insn_template::data_word(0, elfcpp::R_ARM_REL32, 0),
-                                               // dcd   R_ARM_REL32(X)
+                                               // dcd   R_ARM_REL32(X)
     };
-  
+
   // V4T Thumb -> ARM long branch stub, PIC.
   static const Insn_template elf32_arm_stub_long_branch_v4t_thumb_arm_pic[] =
     {
@@ -4718,9 +4735,9 @@ Stub_factory::Stub_factory()
       Insn_template::arm_insn(0xe59fc000),     // ldr  ip, [pc, #0]
       Insn_template::arm_insn(0xe08cf00f),     // add  pc, ip, pc
       Insn_template::data_word(0, elfcpp::R_ARM_REL32, -4),
-                                               // dcd  R_ARM_REL32(X)
+                                               // dcd  R_ARM_REL32(X)
     };
-  
+
   // Thumb -> Thumb long branch stub, PIC. Used on M-profile
   // architectures.
   static const Insn_template elf32_arm_stub_long_branch_thumb_only_pic[] =
@@ -4732,9 +4749,9 @@ Stub_factory::Stub_factory()
       Insn_template::thumb16_insn(0xbc01),     // pop  {r0}
       Insn_template::thumb16_insn(0x4760),     // bx   ip
       Insn_template::data_word(0, elfcpp::R_ARM_REL32, 4),
-                                               // dcd  R_ARM_REL32(X)
+                                               // dcd  R_ARM_REL32(X)
     };
-  
+
   // V4T Thumb -> Thumb long branch stub, PIC. Using the stack is not
   // allowed.
   static const Insn_template elf32_arm_stub_long_branch_v4t_thumb_thumb_pic[] =
@@ -4745,14 +4762,14 @@ Stub_factory::Stub_factory()
       Insn_template::arm_insn(0xe08fc00c),     // add   ip, pc, ip
       Insn_template::arm_insn(0xe12fff1c),     // bx   ip
       Insn_template::data_word(0, elfcpp::R_ARM_REL32, 0),
-                                               // dcd  R_ARM_REL32(X)
+                                               // dcd  R_ARM_REL32(X)
     };
-  
+
   // Cortex-A8 erratum-workaround stubs.
-  
+
   // Stub used for conditional branches (which may be beyond +/-1MB away,
   // so we can't use a conditional branch to reach this stub).
-  
+
   // original code:
   //
   //   b<cond> X
@@ -4763,21 +4780,21 @@ Stub_factory::Stub_factory()
       Insn_template::thumb16_bcond_insn(0xd001),       //      b<cond>.n true
       Insn_template::thumb32_b_insn(0xf000b800, -4),   //      b.w after
       Insn_template::thumb32_b_insn(0xf000b800, -4)    // true:
-                                                       //      b.w X
+                                                       //      b.w X
     };
-  
+
   // Stub used for b.w and bl.w instructions.
-  
+
   static const Insn_template elf32_arm_stub_a8_veneer_b[] =
     {
       Insn_template::thumb32_b_insn(0xf000b800, -4)    // b.w dest
     };
-  
+
   static const Insn_template elf32_arm_stub_a8_veneer_bl[] =
     {
       Insn_template::thumb32_b_insn(0xf000b800, -4)    // b.w dest
     };
-  
+
   // Stub used for Thumb-2 blx.w instructions.  We modified the original blx.w
   // instruction (which switches to ARM mode) to point to this stub.  Jump to
   // the real destination using an ARM-mode branch.
@@ -4998,7 +5015,7 @@ Stub_table<big_endian>::update_data_size_and_addralign()
   // Update prev_data_size_ and prev_addralign_.  These will be used
   // as the current data size and address alignment for the next pass.
   bool changed = size != this->prev_data_size_;
-  this->prev_data_size_ = size; 
+  this->prev_data_size_ = size;
 
   if (addralign != this->prev_addralign_)
     changed = true;
@@ -5132,7 +5149,7 @@ Arm_input_section<big_endian>::do_write(Output_file* of)
   // We have to write out the original section content.
   gold_assert(this->original_contents_ != NULL);
   of->write(this->offset(), this->original_contents_,
-           this->original_size_); 
+           this->original_size_);
 
   // If this owns a stub table and it is not empty, write it.
   if (this->is_stub_table_owner() && !this->stub_table_->empty())
@@ -5191,7 +5208,7 @@ Arm_exidx_cantunwind::do_fixed_endian_write(Output_file* of)
   off_t offset = this->offset();
   const section_size_type oview_size = 8;
   unsigned char* const oview = of->get_output_view(offset, oview_size);
-  
+
   typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
 
   Output_section* os = this->relobj_->output_section(this->shndx_);
@@ -5209,7 +5226,7 @@ Arm_exidx_cantunwind::do_fixed_endian_write(Output_file* of)
     {
       section_start = os->address() + output_offset;
       const Arm_exidx_input_section* exidx_input_section =
-        arm_relobj->exidx_input_section_by_link(this->shndx_);
+       arm_relobj->exidx_input_section_by_link(this->shndx_);
       gold_assert(exidx_input_section != NULL);
       section_size =
        convert_to_section_size_type(exidx_input_section->text_size());
@@ -5289,7 +5306,7 @@ Arm_exidx_merged_section::build_contents(
   section_offset_type out_max =
     convert_types<section_offset_type>(this->data_size());
   for (Arm_exidx_section_offset_map::const_iterator p =
-        this->section_offset_map_.begin();
+       this->section_offset_map_.begin();
       p != this->section_offset_map_.end();
       ++p)
     {
@@ -5361,7 +5378,7 @@ Arm_exidx_merged_section::do_output_offset(
        // Offset is discarded owing to EXIDX entry merging.
        *poutput = -1;
     }
-  
+
   return true;
 }
 
@@ -5373,7 +5390,7 @@ Arm_exidx_merged_section::do_write(Output_file* of)
   off_t offset = this->offset();
   const section_size_type oview_size = this->data_size();
   unsigned char* const oview = of->get_output_view(offset, oview_size);
-  
+
   Output_section* os = this->relobj()->output_section(this->shndx());
   gold_assert(os != NULL);
 
@@ -5484,7 +5501,7 @@ Arm_exidx_fixup::process_exidx_section(
       this->last_unwind_type_ = UT_NONE;
       return 0;
     }
-  
+
   uint32_t deleted_bytes = 0;
   bool prev_delete_entry = false;
   gold_assert(this->section_offset_map_ == NULL);
@@ -5517,7 +5534,7 @@ Arm_exidx_fixup::process_exidx_section(
 
       prev_delete_entry = delete_entry;
     }
-  
+
   // If section offset map is not NULL, make an entry for the end of
   // section.
   if (this->section_offset_map_ != NULL)
@@ -5526,7 +5543,7 @@ Arm_exidx_fixup::process_exidx_section(
   *psection_offset_map = this->section_offset_map_;
   this->section_offset_map_ = NULL;
   this->last_input_section_ = exidx_input_section;
-  
+
   // Set the first output text section so that we can link the EXIDX output
   // section to it.  Ignore any EXIDX input section that is completely merged.
   if (this->first_output_text_section_ == NULL
@@ -5559,14 +5576,14 @@ Arm_output_section<big_endian>::create_stub_group(
   // We use a different kind of relaxed section in an EXIDX section.
   // The static casting from Output_relaxed_input_section to
   // Arm_input_section is invalid in an EXIDX section.  We are okay
-  // because we should not be calling this for an EXIDX section. 
+  // because we should not be calling this for an EXIDX section.
   gold_assert(this->type() != elfcpp::SHT_ARM_EXIDX);
 
   // Currently we convert ordinary input sections into relaxed sections only
   // at this point but we may want to support creating relaxed input section
   // very early.  So we check here to see if owner is already a relaxed
   // section.
-  
+
   Arm_input_section<big_endian>* arm_input_section;
   if (owner->is_relaxed_input_section())
     {
@@ -5590,7 +5607,7 @@ Arm_output_section<big_endian>::create_stub_group(
     target->new_stub_table(arm_input_section);
 
   arm_input_section->set_stub_table(stub_table);
-  
+
   Input_section_list::const_iterator p = begin;
   Input_section_list::const_iterator prev_p;
 
@@ -5615,7 +5632,7 @@ Arm_output_section<big_endian>::create_stub_group(
 // size is just below GROUP_SIZE.  The last input section will be converted
 // into a stub table.  If STUB_ALWAYS_AFTER_BRANCH is false, we also add
 // input section after the stub table, effectively double the group size.
-// 
+//
 // This is similar to the group_sections() function in elf32-arm.c but is
 // implemented differently.
 
@@ -5666,8 +5683,8 @@ Arm_output_section<big_endian>::group_sections(
       section_size_type section_begin_offset =
        align_address(off, p->addralign());
       section_size_type section_end_offset =
-       section_begin_offset + p->data_size(); 
-      
+       section_begin_offset + p->data_size();
+
       // Check to see if we should group the previously seen sections.
       switch (state)
        {
@@ -5679,7 +5696,7 @@ Arm_output_section<big_endian>::group_sections(
          if (section_end_offset - group_begin_offset >= group_size)
            {
              if (stubs_always_after_branch)
-               {       
+               {
                  gold_assert(group_end != this->input_sections().end());
                  this->create_stub_group(group_begin, group_end, group_end,
                                          target, &new_relaxed_sections,
@@ -5712,7 +5729,7 @@ Arm_output_section<big_endian>::group_sections(
 
          default:
            gold_unreachable();
-       }       
+       }
 
       // If we see an input section and currently there is no group, start
       // a new one.  Skip any empty sections.  We look at the data size
@@ -5809,7 +5826,7 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
 
   if (!this->input_sections().empty())
     gold_error(_("Found non-EXIDX input sections in EXIDX output section"));
-  
+
   // Go through all the known input sections and record them.
   typedef Unordered_set<Section_id, Section_id_hash> Section_id_set;
   typedef Unordered_map<Section_id, const Output_section::Input_section*,
@@ -5879,12 +5896,12 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
       Task_lock_obj<Object> tl(task, exidx_relobj);
       section_size_type exidx_size;
       const unsigned char* exidx_contents =
-       exidx_relobj->section_contents(exidx_shndx, &exidx_size, false); 
+       exidx_relobj->section_contents(exidx_shndx, &exidx_size, false);
 
       // Fix up coverage and append input section to output data list.
       Arm_exidx_section_offset_map* section_offset_map = NULL;
       uint32_t deleted_bytes =
-        exidx_fixup.process_exidx_section<big_endian>(exidx_input_section,
+       exidx_fixup.process_exidx_section<big_endian>(exidx_input_section,
                                                      exidx_contents,
                                                      exidx_size,
                                                      &section_offset_map);
@@ -5928,7 +5945,7 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
          this->add_script_input_section(*pis);
        }
 
-      processed_input_sections.insert(Section_id(exidx_relobj, exidx_shndx)); 
+      processed_input_sections.insert(Section_id(exidx_relobj, exidx_shndx));
     }
 
   // Insert an EXIDX_CANTUNWIND entry at the end of output if necessary.
@@ -5963,7 +5980,7 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
          arm_relobj->set_output_local_symbol_count_needs_update();
        }
     }
-    
+
   // Link exidx output section to the first seen output section and
   // set correct entry size.
   this->set_link_section(exidx_fixup.first_output_text_section());
@@ -6170,7 +6187,7 @@ Arm_relobj<big_endian>::scan_section_for_cortex_a8_erratum(
   // scan.  There are two reasons.  First, we should look at THUMB code and
   // THUMB code only.  Second, we only want to look at the 4K-page boundary
   // to speed up the scanning.
-  
+
   while (p != this->mapping_symbols_info_.end()
        && p->first.first == shndx)
     {
@@ -6189,7 +6206,7 @@ Arm_relobj<big_endian>::scan_section_for_cortex_a8_erratum(
            span_end = convert_to_section_size_type(next->first.second);
          else
            span_end = convert_to_section_size_type(shdr.get_sh_size());
-         
+
          if (((span_start + output_address) & ~0xfffUL)
              != ((span_end + output_address - 1) & ~0xfffUL))
            {
@@ -6200,7 +6217,7 @@ Arm_relobj<big_endian>::scan_section_for_cortex_a8_erratum(
            }
        }
 
-      p = next; 
+      p = next;
     }
 }
 
@@ -6316,7 +6333,7 @@ Arm_relobj<big_endian>::scan_sections_for_stubs(
 // do_count_local_symbol in parent and scan local symbols to mark
 // THUMB functions.  This is not the most efficient way but I do not want to
 // slow down other ports by calling a per symbol target hook inside
-// Sized_relobj_file<size, big_endian>::do_count_local_symbols. 
+// Sized_relobj_file<size, big_endian>::do_count_local_symbols.
 
 template<bool big_endian>
 void
@@ -6326,7 +6343,7 @@ Arm_relobj<big_endian>::do_count_local_symbols(
 {
   // We need to fix-up the values of any local symbols whose type are
   // STT_ARM_TFUNC.
-  
+
   // Ask parent to count the local symbols.
   Sized_relobj_file<32, big_endian>::do_count_local_symbols(pool, dynpool);
   const unsigned int loccount = this->local_symbol_count();
@@ -6363,7 +6380,7 @@ Arm_relobj<big_endian>::do_count_local_symbols(
   if (strtabshdr.get_sh_type() != elfcpp::SHT_STRTAB)
     {
       this->error(_("symbol table name section has wrong type: %u"),
-                 static_cast<unsigned int>(strtabshdr.get_sh_type()));
+                 static_cast<unsigned int>(strtabshdr.get_sh_type()));
       return;
     }
   const char* pnames =
@@ -6423,7 +6440,7 @@ Arm_relobj<big_endian>::do_relocate_sections(
 {
   // Call parent to relocate sections.
   Sized_relobj_file<32, big_endian>::do_relocate_sections(symtab, layout,
-                                                         pshdrs, of, pviews); 
+                                                         pshdrs, of, pviews);
 
   // We do not generate stubs if doing a relocatable link.
   if (parameters->options().relocatable())
@@ -6471,7 +6488,7 @@ Arm_relobj<big_endian>::do_relocate_sections(
          unsigned char* view = (*pviews)[i].view + offset;
          Arm_address address = stub_table->address();
          section_size_type view_size = stub_table->data_size();
+
          stub_table->relocate_stubs(&relinfo, arm_target, os, view, address,
                                     view_size);
        }
@@ -6529,7 +6546,7 @@ Arm_relobj<big_endian>::find_linked_text_section(
     unsigned int* pshndx)
 {
   elfcpp::Shdr<32, big_endian> shdr(pshdr);
-  
+
   // If there is no relocation, we cannot find the linked text section.
   size_t reloc_size;
   if (shdr.get_sh_type() == elfcpp::SHT_REL)
@@ -6537,10 +6554,10 @@ Arm_relobj<big_endian>::find_linked_text_section(
   else
       reloc_size = elfcpp::Elf_sizes<32>::rela_size;
   size_t reloc_count = shdr.get_sh_size() / reloc_size;
+
   // Get the relocations.
   const unsigned char* prelocs =
-      this->get_view(shdr.get_sh_offset(), shdr.get_sh_size(), true, false); 
+      this->get_view(shdr.get_sh_offset(), shdr.get_sh_size(), true, false);
 
   // Find the REL31 relocation for the first word of the first EXIDX entry.
   for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
@@ -6616,7 +6633,7 @@ Arm_relobj<big_endian>::make_exidx_input_section(
                 this->section_name(shndx).c_str(), shndx, text_shndx,
                 this->name().c_str());
       exidx_input_section->set_has_errors();
-    } 
+    }
   else if (this->exidx_section_map_[text_shndx] != NULL)
     {
       unsigned other_exidx_shndx =
@@ -6707,7 +6724,7 @@ Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
 
       if (shdr.get_sh_type() == elfcpp::SHT_ARM_ATTRIBUTES)
        {
-         gold_assert(this->attributes_section_data_ == NULL);
+         gold_assert(this->attributes_section_data_ == NULL);
          section_offset_type section_offset = shdr.get_sh_offset();
          section_size_type section_size =
            convert_to_section_size_type(shdr.get_sh_size());
@@ -6742,7 +6759,7 @@ Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
       return;
     }
 
-  // Some tools are broken and they do not set the link of EXIDX sections. 
+  // Some tools are broken and they do not set the link of EXIDX sections.
   // We look at the first relocation to figure out the linked sections.
   if (!deferred_exidx_sections.empty())
     {
@@ -6788,7 +6805,7 @@ Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
       const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
                                                  locsize, true, true);
 
-      // Process the deferred EXIDX sections. 
+      // Process the deferred EXIDX sections.
       for (unsigned int i = 0; i < deferred_exidx_sections.size(); ++i)
        {
          unsigned int shndx = deferred_exidx_sections[i];
@@ -6806,7 +6823,7 @@ Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
 }
 
 // Process relocations for garbage collection.  The ARM target uses .ARM.exidx
-// sections for unwinding.  These sections are referenced implicitly by 
+// sections for unwinding.  These sections are referenced implicitly by
 // text sections linked in the section headers.  If we ignore these implicit
 // references, the .ARM.exidx sections and any .ARM.extab sections they use
 // will be garbage-collected incorrectly.  Hence we override the same function
@@ -6825,7 +6842,7 @@ Arm_relobj<big_endian>::do_gc_process_relocs(Symbol_table* symtab,
   // This happens when --icf is used but --gc-sections is not.
   if (!parameters->options().gc_sections())
     return;
-  
+
   unsigned int shnum = this->shnum();
   const unsigned int shdr_size = elfcpp::Elf_sizes<32>::shdr_size;
   const unsigned char* pshdrs = this->get_view(this->elf_file()->shoff(),
@@ -6930,7 +6947,7 @@ Arm_relobj<big_endian>::update_output_local_symbol_count()
                  // that is discarded due to entry merging.
                  lv.set_no_output_symtab_entry();
                  continue;
-               }       
+               }
            }
        }
 
@@ -6994,7 +7011,7 @@ Stub_addend_reader<elfcpp::SHT_REL, big_endian>::operator()(
     const typename Reloc_types<elfcpp::SHT_REL, 32, big_endian>::Reloc&) const
 {
   typedef class Arm_relocate_functions<big_endian> RelocFuncs;
-  
+
   switch (r_type)
     {
     case elfcpp::R_ARM_CALL:
@@ -7052,7 +7069,7 @@ Arm_output_data_got<big_endian>::add_tls_gd32_with_static_reloc(
   // We are doing a static link.  Just mark it as belong to module 1,
   // the executable.
   unsigned int got_offset = this->add_constant(1);
-  gsym->set_got_offset(got_type, got_offset); 
+  gsym->set_got_offset(got_type, got_offset);
   got_offset = this->add_constant(0);
   this->static_relocs_.push_back(Static_reloc(got_offset,
                                              elfcpp::R_ARM_TLS_DTPOFF32,
@@ -7076,8 +7093,8 @@ Arm_output_data_got<big_endian>::add_tls_gd32_with_static_reloc(
   unsigned int got_offset = this->add_constant(1);
   object->set_local_got_offset(index, got_type, got_offset);
   got_offset = this->add_constant(0);
-  this->static_relocs_.push_back(Static_reloc(got_offset, 
-                                             elfcpp::R_ARM_TLS_DTPOFF32, 
+  this->static_relocs_.push_back(Static_reloc(got_offset,
+                                             elfcpp::R_ARM_TLS_DTPOFF32,
                                              object, index));
 }
 
@@ -7101,7 +7118,7 @@ Arm_output_data_got<big_endian>::do_write(Output_file* of)
 
   Output_segment* tls_segment = this->layout_->tls_segment();
   gold_assert(tls_segment != NULL);
-  
+
   // The thread pointer $tp points to the TCB, which is followed by the
   // TLS.  So we need to adjust $tp relative addressing by this amount.
   Arm_address aligned_tcb_size =
@@ -7110,7 +7127,7 @@ Arm_output_data_got<big_endian>::do_write(Output_file* of)
   for (size_t i = 0; i < this->static_relocs_.size(); ++i)
     {
       Static_reloc& reloc(this->static_relocs_[i]);
-      
+
       Arm_address value;
       if (!reloc.symbol_is_global())
        {
@@ -7133,7 +7150,7 @@ Arm_output_data_got<big_endian>::do_write(Output_file* of)
                         reloc.index(), reloc.relobj()->name().c_str());
              continue;
            }
-         
+
          value = psymval->value(object, 0);
        }
       else
@@ -7189,6 +7206,9 @@ Arm_output_data_got<big_endian>::do_write(Output_file* of)
 }
 
 // A class to handle the PLT data.
+// This is an abstract base class that handles most of the linker details
+// but does not know the actual contents of PLT entries.  The derived
+// classes below fill in those details.
 
 template<bool big_endian>
 class Output_data_plt_arm : public Output_section_data
@@ -7197,7 +7217,7 @@ class Output_data_plt_arm : public Output_section_data
   typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, big_endian>
     Reloc_section;
 
-  Output_data_plt_arm(Layout*, Output_data_space*);
+  Output_data_plt_arm(Layout*, uint64_t addralign, Output_data_space*);
 
   // Add an entry to the PLT.
   void
@@ -7214,16 +7234,49 @@ class Output_data_plt_arm : public Output_section_data
   { return this->count_; }
 
   // Return the offset of the first non-reserved PLT entry.
-  static unsigned int
-  first_plt_entry_offset()
-  { return sizeof(first_plt_entry); }
+  unsigned int
+  first_plt_entry_offset() const
+  { return this->do_first_plt_entry_offset(); }
 
   // Return the size of a PLT entry.
-  static unsigned int
-  get_plt_entry_size()
-  { return sizeof(plt_entry); }
+  unsigned int
+  get_plt_entry_size() const
+  { return this->do_get_plt_entry_size(); }
 
  protected:
+  // Fill in the first PLT entry.
+  void
+  fill_first_plt_entry(unsigned char* pov,
+                      Arm_address got_address,
+                      Arm_address plt_address)
+  { this->do_fill_first_plt_entry(pov, got_address, plt_address); }
+
+  void
+  fill_plt_entry(unsigned char* pov,
+                Arm_address got_address,
+                Arm_address plt_address,
+                unsigned int got_offset,
+                unsigned int plt_offset)
+  { do_fill_plt_entry(pov, got_address, plt_address, got_offset, plt_offset); }
+
+  virtual unsigned int
+  do_first_plt_entry_offset() const = 0;
+
+  virtual unsigned int
+  do_get_plt_entry_size() const = 0;
+
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov,
+                         Arm_address got_address,
+                         Arm_address plt_address) = 0;
+
+  virtual void
+  do_fill_plt_entry(unsigned char* pov,
+                   Arm_address got_address,
+                   Arm_address plt_address,
+                   unsigned int got_offset,
+                   unsigned int plt_offset) = 0;
+
   void
   do_adjust_output_section(Output_section* os);
 
@@ -7233,18 +7286,12 @@ class Output_data_plt_arm : public Output_section_data
   { mapfile->print_output_data(this, _("** PLT")); }
 
  private:
-  // Template for the first PLT entry.
-  static const uint32_t first_plt_entry[5];
-
-  // Template for subsequent PLT entries. 
-  static const uint32_t plt_entry[3];
-
   // Set the final size.
   void
   set_final_data_size()
   {
-    this->set_data_size(sizeof(first_plt_entry)
-                       + this->count_ * sizeof(plt_entry));
+    this->set_data_size(this->first_plt_entry_offset()
+                       + this->count_ * this->get_plt_entry_size());
   }
 
   // Write out the PLT data.
@@ -7265,8 +7312,9 @@ class Output_data_plt_arm : public Output_section_data
 
 template<bool big_endian>
 Output_data_plt_arm<big_endian>::Output_data_plt_arm(Layout* layout,
+                                                    uint64_t addralign,
                                                     Output_data_space* got_plt)
-  : Output_section_data(4), got_plt_(got_plt), count_(0)
+  : Output_section_data(addralign), got_plt_(got_plt), count_(0)
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
@@ -7291,8 +7339,8 @@ Output_data_plt_arm<big_endian>::add_entry(Symbol* gsym)
 
   // Note that when setting the PLT offset we skip the initial
   // reserved PLT entry.
-  gsym->set_plt_offset((this->count_) * sizeof(plt_entry)
-                      + sizeof(first_plt_entry));
+  gsym->set_plt_offset((this->count_) * this->get_plt_entry_size()
+                      + this->first_plt_entry_offset());
 
   ++this->count_;
 
@@ -7313,6 +7361,45 @@ Output_data_plt_arm<big_endian>::add_entry(Symbol* gsym)
   // appear in the relocations.
 }
 
+template<bool big_endian>
+class Output_data_plt_arm_standard : public Output_data_plt_arm<big_endian>
+{
+ public:
+  Output_data_plt_arm_standard(Layout* layout, Output_data_space* got_plt)
+    : Output_data_plt_arm<big_endian>(layout, 4, got_plt)
+  { }
+
+ protected:
+  // Return the offset of the first non-reserved PLT entry.
+  virtual unsigned int
+  do_first_plt_entry_offset() const
+  { return sizeof(first_plt_entry); }
+
+  // Return the size of a PLT entry.
+  virtual unsigned int
+  do_get_plt_entry_size() const
+  { return sizeof(plt_entry); }
+
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov,
+                         Arm_address got_address,
+                         Arm_address plt_address);
+
+  virtual void
+  do_fill_plt_entry(unsigned char* pov,
+                   Arm_address got_address,
+                   Arm_address plt_address,
+                   unsigned int got_offset,
+                   unsigned int plt_offset);
+
+ private:
+  // Template for the first PLT entry.
+  static const uint32_t first_plt_entry[5];
+
+  // Template for subsequent PLT entries.
+  static const uint32_t plt_entry[3];
+};
+
 // ARM PLTs.
 // FIXME:  This is not very flexible.  Right now this has only been tested
 // on armv5te.  If we are to support additional architecture features like
@@ -7320,25 +7407,63 @@ Output_data_plt_arm<big_endian>::add_entry(Symbol* gsym)
 
 // The first entry in the PLT.
 template<bool big_endian>
-const uint32_t Output_data_plt_arm<big_endian>::first_plt_entry[5] =
+const uint32_t Output_data_plt_arm_standard<big_endian>::first_plt_entry[5] =
 {
   0xe52de004,  // str   lr, [sp, #-4]!
   0xe59fe004,   // ldr   lr, [pc, #4]
-  0xe08fe00e,  // add   lr, pc, lr 
+  0xe08fe00e,  // add   lr, pc, lr
   0xe5bef008,  // ldr   pc, [lr, #8]!
   0x00000000,  // &GOT[0] - .
 };
 
+template<bool big_endian>
+void
+Output_data_plt_arm_standard<big_endian>::do_fill_first_plt_entry(
+    unsigned char* pov,
+    Arm_address got_address,
+    Arm_address plt_address)
+{
+  // Write first PLT entry.  All but the last word are constants.
+  const size_t num_first_plt_words = (sizeof(first_plt_entry)
+                                     / sizeof(plt_entry[0]));
+  for (size_t i = 0; i < num_first_plt_words - 1; i++)
+    elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]);
+  // Last word in first PLT entry is &GOT[0] - .
+  elfcpp::Swap<32, big_endian>::writeval(pov + 16,
+                                        got_address - (plt_address + 16));
+}
+
 // Subsequent entries in the PLT.
 
 template<bool big_endian>
-const uint32_t Output_data_plt_arm<big_endian>::plt_entry[3] =
+const uint32_t Output_data_plt_arm_standard<big_endian>::plt_entry[3] =
 {
   0xe28fc600,  // add   ip, pc, #0xNN00000
   0xe28cca00,  // add   ip, ip, #0xNN000
   0xe5bcf000,  // ldr   pc, [ip, #0xNNN]!
 };
 
+template<bool big_endian>
+void
+Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry(
+    unsigned char* pov,
+    Arm_address got_address,
+    Arm_address plt_address,
+    unsigned int got_offset,
+    unsigned int plt_offset)
+{
+  int32_t offset = ((got_address + got_offset)
+                   - (plt_address + plt_offset + 8));
+
+  gold_assert(offset >= 0 && offset < 0x0fffffff);
+  uint32_t plt_insn0 = plt_entry[0] | ((offset >> 20) & 0xff);
+  elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0);
+  uint32_t plt_insn1 = plt_entry[1] | ((offset >> 12) & 0xff);
+  elfcpp::Swap<32, big_endian>::writeval(pov + 4, plt_insn1);
+  uint32_t plt_insn2 = plt_entry[2] | (offset & 0xfff);
+  elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2);
+}
+
 // Write out the PLT.  This uses the hand-coded instructions above,
 // and adjusts them as needed.  This is all specified by the arm ELF
 // Processor Supplement.
@@ -7362,46 +7487,29 @@ Output_data_plt_arm<big_endian>::do_write(Output_file* of)
   Arm_address plt_address = this->address();
   Arm_address got_address = this->got_plt_->address();
 
-  // Write first PLT entry.  All but the last word are constants.
-  const size_t num_first_plt_words = (sizeof(first_plt_entry)
-                                     / sizeof(plt_entry[0]));
-  for (size_t i = 0; i < num_first_plt_words - 1; i++)
-    elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]);
-  // Last word in first PLT entry is &GOT[0] - .
-  elfcpp::Swap<32, big_endian>::writeval(pov + 16,
-                                        got_address - (plt_address + 16));
-  pov += sizeof(first_plt_entry);
+  // Write first PLT entry.
+  this->fill_first_plt_entry(pov, got_address, plt_address);
+  pov += this->first_plt_entry_offset();
 
   unsigned char* got_pov = got_view;
 
   memset(got_pov, 0, 12);
   got_pov += 12;
 
-  const int rel_size = elfcpp::Elf_sizes<32>::rel_size;
-  unsigned int plt_offset = sizeof(first_plt_entry);
-  unsigned int plt_rel_offset = 0;
+  unsigned int plt_offset = this->first_plt_entry_offset();
   unsigned int got_offset = 12;
   const unsigned int count = this->count_;
   for (unsigned int i = 0;
        i < count;
        ++i,
-        pov += sizeof(plt_entry),
+        pov += this->get_plt_entry_size(),
         got_pov += 4,
-        plt_offset += sizeof(plt_entry),
-        plt_rel_offset += rel_size,
+        plt_offset += this->get_plt_entry_size(),
         got_offset += 4)
     {
       // Set and adjust the PLT entry itself.
-      int32_t offset = ((got_address + got_offset)
-                        - (plt_address + plt_offset + 8));
-
-      gold_assert(offset >= 0 && offset < 0x0fffffff);
-      uint32_t plt_insn0 = plt_entry[0] | ((offset >> 20) & 0xff);
-      elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0);
-      uint32_t plt_insn1 = plt_entry[1] | ((offset >> 12) & 0xff);
-      elfcpp::Swap<32, big_endian>::writeval(pov + 4, plt_insn1);
-      uint32_t plt_insn2 = plt_entry[2] | (offset & 0xfff);
-      elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2);
+      this->fill_plt_entry(pov, got_address, plt_address,
+                          got_offset, plt_offset);
 
       // Set the entry in the GOT.
       elfcpp::Swap<32, big_endian>::writeval(got_pov, plt_address);
@@ -7429,7 +7537,8 @@ Target_arm<big_endian>::make_plt_entry(Symbol_table* symtab, Layout* layout,
       // Create the GOT sections first.
       this->got_section(symtab, layout);
 
-      this->plt_ = new Output_data_plt_arm<big_endian>(layout, this->got_plt_);
+      this->plt_ = this->make_data_plt(layout, this->got_plt_);
+
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
                                      (elfcpp::SHF_ALLOC
                                       | elfcpp::SHF_EXECINSTR),
@@ -7455,7 +7564,7 @@ template<bool big_endian>
 unsigned int
 Target_arm<big_endian>::first_plt_entry_offset() const
 {
-  return Output_data_plt_arm<big_endian>::first_plt_entry_offset();
+  return this->plt_->first_plt_entry_offset();
 }
 
 // Return the size of each PLT entry.
@@ -7464,7 +7573,7 @@ template<bool big_endian>
 unsigned int
 Target_arm<big_endian>::plt_entry_size() const
 {
-  return Output_data_plt_arm<big_endian>::get_plt_entry_size();
+  return this->plt_->get_plt_entry_size();
 }
 
 // Get the section to use for TLS_DESC relocations.
@@ -7774,8 +7883,8 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
        {
          Reloc_section* rel_dyn = target->rel_dyn_section(layout);
          unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
-         // If we are to add more other reloc types than R_ARM_ABS32,
-         // we need to add check_non_pic(object, r_type) here.
+         // If we are to add more other reloc types than R_ARM_ABS32,
+         // we need to add check_non_pic(object, r_type) here.
          rel_dyn->add_local_relative(object, r_sym, elfcpp::R_ARM_RELATIVE,
                                      output_section, data_shndx,
                                      reloc.get_r_offset());
@@ -7797,16 +7906,16 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
       // data section, we need to be careful not to apply this
       // relocation statically.
       if (parameters->options().output_is_position_independent())
-        {
+       {
          check_non_pic(object, r_type);
-          Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+         Reloc_section* rel_dyn = target->rel_dyn_section(layout);
          unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
-          if (lsym.get_st_type() != elfcpp::STT_SECTION)
+         if (lsym.get_st_type() != elfcpp::STT_SECTION)
            rel_dyn->add_local(object, r_sym, r_type, output_section,
                               data_shndx, reloc.get_r_offset());
-          else
-            {
-              gold_assert(lsym.get_st_value() == 0);
+         else
+           {
+             gold_assert(lsym.get_st_value() == 0);
              unsigned int shndx = lsym.get_st_shndx();
              bool is_ordinary;
              shndx = object->adjust_sym_shndx(r_sym, shndx,
@@ -7818,8 +7927,8 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
                rel_dyn->add_local_section(object, shndx,
                                           r_type, output_section,
                                           data_shndx, reloc.get_r_offset());
-            }
-        }
+           }
+       }
       break;
 
     case elfcpp::R_ARM_REL32:
@@ -7936,18 +8045,18 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
       {
        bool output_is_shared = parameters->options().shared();
        const tls::Tls_optimization optimized_type
-            = Target_arm<big_endian>::optimize_tls_reloc(!output_is_shared,
+           = Target_arm<big_endian>::optimize_tls_reloc(!output_is_shared,
                                                         r_type);
        switch (r_type)
          {
          case elfcpp::R_ARM_TLS_GD32:          // Global-dynamic
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // Create a pair of GOT entries for the module index and
-               // dtv-relative offset.
-                Arm_output_data_got<big_endian>* got
-                    = target->got_section(symtab, layout);
-                unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+               // Create a pair of GOT entries for the module index and
+               // dtv-relative offset.
+               Arm_output_data_got<big_endian>* got
+                   = target->got_section(symtab, layout);
+               unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
                unsigned int shndx = lsym.get_st_shndx();
                bool is_ordinary;
                shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
@@ -7975,8 +8084,8 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
          case elfcpp::R_ARM_TLS_LDM32:         // Local-dynamic
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // Create a GOT entry for the module index.
-               target->got_mod_index_entry(symtab, layout, object);
+               // Create a GOT entry for the module index.
+               target->got_mod_index_entry(symtab, layout, object);
              }
            else
              // FIXME: TLS optimization not supported yet.
@@ -8019,9 +8128,9 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
            layout->set_has_static_tls();
            if (output_is_shared)
              {
-               // We need to create a dynamic relocation.
-                gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
-                unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+               // We need to create a dynamic relocation.
+               gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
+               unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
                Reloc_section* rel_dyn = target->rel_dyn_section(layout);
                rel_dyn->add_local(object, r_sym, elfcpp::R_ARM_TLS_TPOFF32,
                                   output_section, data_shndx,
@@ -8167,42 +8276,42 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
     case elfcpp::R_ARM_ABS32_NOI:
       // Absolute addressing relocations.
       {
-        // Make a PLT entry if necessary.
-        if (this->symbol_needs_plt_entry(gsym))
-          {
-            target->make_plt_entry(symtab, layout, gsym);
-            // Since this is not a PC-relative relocation, we may be
-            // taking the address of a function. In that case we need to
-            // set the entry in the dynamic symbol table to the address of
-            // the PLT entry.
-            if (gsym->is_from_dynobj() && !parameters->options().shared())
-              gsym->set_needs_dynsym_value();
-          }
-        // Make a dynamic relocation if necessary.
-        if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
-          {
-            if (gsym->may_need_copy_reloc())
-              {
-               target->copy_reloc(symtab, layout, object,
-                                  data_shndx, output_section, gsym, reloc);
-              }
-            else if ((r_type == elfcpp::R_ARM_ABS32
+       // Make a PLT entry if necessary.
+       if (this->symbol_needs_plt_entry(gsym))
+         {
+           target->make_plt_entry(symtab, layout, gsym);
+           // Since this is not a PC-relative relocation, we may be
+           // taking the address of a function. In that case we need to
+           // set the entry in the dynamic symbol table to the address of
+           // the PLT entry.
+           if (gsym->is_from_dynobj() && !parameters->options().shared())
+             gsym->set_needs_dynsym_value();
+         }
+       // Make a dynamic relocation if necessary.
+       if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
+         {
+           if (gsym->may_need_copy_reloc())
+             {
+               target->copy_reloc(symtab, layout, object,
+                                  data_shndx, output_section, gsym, reloc);
+             }
+           else if ((r_type == elfcpp::R_ARM_ABS32
                      || r_type == elfcpp::R_ARM_ABS32_NOI)
-                     && gsym->can_use_relative_reloc(false))
-              {
-                Reloc_section* rel_dyn = target->rel_dyn_section(layout);
-                rel_dyn->add_global_relative(gsym, elfcpp::R_ARM_RELATIVE,
-                                             output_section, object,
-                                             data_shndx, reloc.get_r_offset());
-              }
-            else
-              {
+                    && gsym->can_use_relative_reloc(false))
+             {
+               Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+               rel_dyn->add_global_relative(gsym, elfcpp::R_ARM_RELATIVE,
+                                            output_section, object,
+                                            data_shndx, reloc.get_r_offset());
+             }
+           else
+             {
                check_non_pic(object, r_type);
-                Reloc_section* rel_dyn = target->rel_dyn_section(layout);
-                rel_dyn->add_global(gsym, r_type, output_section, object,
-                                    data_shndx, reloc.get_r_offset());
-              }
-          }
+               Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+               rel_dyn->add_global(gsym, r_type, output_section, object,
+                                   data_shndx, reloc.get_r_offset());
+             }
+         }
       }
       break;
 
@@ -8211,7 +8320,7 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
       // We need a GOT section.
       target->got_section(symtab, layout);
       break;
-      
+
     case elfcpp::R_ARM_REL32:
     case elfcpp::R_ARM_LDR_PC_G0:
     case elfcpp::R_ARM_SBREL32:
@@ -8368,16 +8477,16 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
       {
        const bool is_final = gsym->final_value_is_known();
        const tls::Tls_optimization optimized_type
-            = Target_arm<big_endian>::optimize_tls_reloc(is_final, r_type);
+           = Target_arm<big_endian>::optimize_tls_reloc(is_final, r_type);
        switch (r_type)
          {
          case elfcpp::R_ARM_TLS_GD32:          // Global-dynamic
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // Create a pair of GOT entries for the module index and
-               // dtv-relative offset.
-                Arm_output_data_got<big_endian>* got
-                    = target->got_section(symtab, layout);
+               // Create a pair of GOT entries for the module index and
+               // dtv-relative offset.
+               Arm_output_data_got<big_endian>* got
+                   = target->got_section(symtab, layout);
                if (!parameters->doing_static_link())
                  got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
                                                target->rel_dyn_section(layout),
@@ -8394,8 +8503,8 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
          case elfcpp::R_ARM_TLS_LDM32:         // Local-dynamic
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // Create a GOT entry for the module index.
-               target->got_mod_index_entry(symtab, layout, object);
+               // Create a GOT entry for the module index.
+               target->got_mod_index_entry(symtab, layout, object);
              }
            else
              // FIXME: TLS optimization not supported yet.
@@ -8434,11 +8543,11 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
            layout->set_has_static_tls();
            if (parameters->options().shared())
              {
-               // We need to create a dynamic relocation.
-                Reloc_section* rel_dyn = target->rel_dyn_section(layout);
-                rel_dyn->add_global(gsym, elfcpp::R_ARM_TLS_TPOFF32,
+               // We need to create a dynamic relocation.
+               Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+               rel_dyn->add_global(gsym, elfcpp::R_ARM_TLS_TPOFF32,
                                    output_section, object,
-                                    data_shndx, reloc.get_r_offset());
+                                   data_shndx, reloc.get_r_offset());
              }
            break;
 
@@ -8557,7 +8666,7 @@ Target_arm<big_endian>::do_finalize_sections(
                                        arm_relobj->attributes_section_data());
          merged_any_attributes = true;
        }
-    } 
+    }
 
   for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin();
        p != input_objects->dynobj_end();
@@ -8588,22 +8697,22 @@ Target_arm<big_endian>::do_finalize_sections(
     {
       // If neither --fix-cortex-a8 nor --no-fix-cortex-a8 is used, turn on
       // Cortex-A8 erratum workaround for ARMv7-A or ARMv7 with unknown
-      // profile.  
+      // profile.
       const Object_attribute* cpu_arch_profile_attr =
        this->get_aeabi_object_attribute(elfcpp::Tag_CPU_arch_profile);
       this->fix_cortex_a8_ =
        (cpu_arch_attr->int_value() == elfcpp::TAG_CPU_ARCH_V7
-         && (cpu_arch_profile_attr->int_value() == 'A'
-             || cpu_arch_profile_attr->int_value() == 0));
+        && (cpu_arch_profile_attr->int_value() == 'A'
+            || cpu_arch_profile_attr->int_value() == 0));
     }
-  
+
   // Check if we can use V4BX interworking.
   // The V4BX interworking stub contains BX instruction,
   // which is not specified for some profiles.
   if (this->fix_v4bx() == General_options::FIX_V4BX_INTERWORKING
       && !this->may_use_v4t_interworking())
     gold_error(_("unable to provide V4BX reloc interworking fix up; "
-                "the target profile does not support BX instruction"));
+                "the target profile does not support BX instruction"));
 
   // Fill in some more dynamic tags.
   const Reloc_section* rel_plt = (this->plt_ == NULL
@@ -8623,21 +8732,21 @@ Target_arm<big_endian>::do_finalize_sections(
   if (!parameters->options().relocatable())
     {
       if (exidx_section != NULL
-          && exidx_section->type() == elfcpp::SHT_ARM_EXIDX)
-        {
-          // For the ARM target, we need to add a PT_ARM_EXIDX segment for
-          // the .ARM.exidx section.
-          if (!layout->script_options()->saw_phdrs_clause())
-            {
-              gold_assert(layout->find_output_segment(elfcpp::PT_ARM_EXIDX, 0,
-                                                      0)
-                          == NULL);
-              Output_segment*  exidx_segment =
-                layout->make_output_segment(elfcpp::PT_ARM_EXIDX, elfcpp::PF_R);
-              exidx_segment->add_output_section_to_nonload(exidx_section,
-                                                           elfcpp::PF_R);
-            }
-        }
+         && exidx_section->type() == elfcpp::SHT_ARM_EXIDX)
+       {
+         // For the ARM target, we need to add a PT_ARM_EXIDX segment for
+         // the .ARM.exidx section.
+         if (!layout->script_options()->saw_phdrs_clause())
+           {
+             gold_assert(layout->find_output_segment(elfcpp::PT_ARM_EXIDX, 0,
+                                                     0)
+                         == NULL);
+             Output_segment*  exidx_segment =
+               layout->make_output_segment(elfcpp::PT_ARM_EXIDX, elfcpp::PF_R);
+             exidx_segment->add_output_section_to_nonload(exidx_section,
+                                                          elfcpp::PF_R);
+           }
+       }
     }
 
   // Create an .ARM.attributes section if we have merged any attributes
@@ -8828,8 +8937,8 @@ Target_arm<big_endian>::Relocate::relocate(
        }
       else
        {
-          // This is a local symbol.  Determine if the final target is THUMB.
-          // We saved this information when all the local symbols were read.
+         // This is a local symbol.  Determine if the final target is THUMB.
+         // We saved this information when all the local symbols were read.
          elfcpp::Elf_types<32>::Elf_WXword r_info = rel.get_r_info();
          unsigned int r_sym = elfcpp::elf_r_sym<32>(r_info);
          thumb_bit = object->local_symbol_is_thumb_function(r_sym) ? 1 : 0;
@@ -8845,14 +8954,14 @@ Target_arm<big_endian>::Relocate::relocate(
 
   // Strip LSB if this points to a THUMB target.
   if (thumb_bit != 0
-      && reloc_property->uses_thumb_bit() 
+      && reloc_property->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;
-    } 
+    }
 
   // To look up relocation stubs, we need to pass the symbol table index of
   // a local symbol.
@@ -8903,9 +9012,9 @@ Target_arm<big_endian>::Relocate::relocate(
       relative_address_base = address & 0xfffffffcU;
       break;
     default:
-      gold_unreachable(); 
+      gold_unreachable();
     }
-    
+
   typename Arm_relocate_functions::Status reloc_status =
        Arm_relocate_functions::STATUS_OKAY;
   bool check_overflow = reloc_property->checks_overflow();
@@ -8957,7 +9066,7 @@ Target_arm<big_endian>::Relocate::relocate(
     case elfcpp::R_ARM_THM_MOVW_ABS_NC:
       if (should_apply_static_reloc(gsym, r_type, false, output_section))
        reloc_status = Arm_relocate_functions::thm_movw(view, object, psymval,
-                                                               0, thumb_bit, false);
+                                                       0, thumb_bit, false);
       break;
 
     case elfcpp::R_ARM_THM_MOVT_ABS:
@@ -8997,7 +9106,7 @@ Target_arm<big_endian>::Relocate::relocate(
        Arm_relocate_functions::thm_movt(view, object, psymval,
                                         relative_address_base);
       break;
-       
+
     case elfcpp::R_ARM_REL32:
       reloc_status = Arm_relocate_functions::rel32(view, object, psymval,
                                                   address, thumb_bit);
@@ -9066,7 +9175,7 @@ Target_arm<big_endian>::Relocate::relocate(
                      && !gsym->is_from_dynobj()
                      && !gsym->is_preemptible()));
       reloc_status =
-       Arm_relocate_functions::arm_branch_common(
+       Arm_relocate_functions::arm_branch_common(
            r_type, relinfo, view, gsym, object, r_sym, psymval, address,
            thumb_bit, is_weakly_undefined_without_plt);
       break;
@@ -9257,50 +9366,50 @@ Target_arm<big_endian>::Relocate::relocate_tls(
   switch (r_type)
     {
     case elfcpp::R_ARM_TLS_GD32:       // Global-dynamic
-        {
-          unsigned int got_type = GOT_TYPE_TLS_PAIR;
-          unsigned int got_offset;
-          if (gsym != NULL)
-            {
-              gold_assert(gsym->has_got_offset(got_type));
-              got_offset = gsym->got_offset(got_type) - target->got_size();
-            }
-          else
-            {
-              unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
-              gold_assert(object->local_has_got_offset(r_sym, got_type));
-              got_offset = (object->local_got_offset(r_sym, got_type)
+       {
+         unsigned int got_type = GOT_TYPE_TLS_PAIR;
+         unsigned int got_offset;
+         if (gsym != NULL)
+           {
+             gold_assert(gsym->has_got_offset(got_type));
+             got_offset = gsym->got_offset(got_type) - target->got_size();
+           }
+         else
+           {
+             unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+             gold_assert(object->local_has_got_offset(r_sym, got_type));
+             got_offset = (object->local_got_offset(r_sym, got_type)
                            - target->got_size());
-            }
-          if (optimized_type == tls::TLSOPT_NONE)
-            {
+           }
+         if (optimized_type == tls::TLSOPT_NONE)
+           {
              Arm_address got_entry =
                target->got_plt_section()->address() + got_offset;
-             
-              // Relocate the field with the PC relative offset of the pair of
-              // GOT entries.
+
+             // Relocate the field with the PC relative offset of the pair of
+             // GOT entries.
              RelocFuncs::pcrel32_unaligned(view, got_entry, address);
-              return ArmRelocFuncs::STATUS_OKAY;
-            }
-        }
+             return ArmRelocFuncs::STATUS_OKAY;
+           }
+       }
       break;
 
     case elfcpp::R_ARM_TLS_LDM32:      // Local-dynamic
       if (optimized_type == tls::TLSOPT_NONE)
-        {
-          // Relocate the field with the offset of the GOT entry for
-          // the module index.
-          unsigned int got_offset;
-          got_offset = (target->got_mod_index_entry(NULL, NULL, NULL)
+       {
+         // Relocate the field with the offset of the GOT entry for
+         // the module index.
+         unsigned int got_offset;
+         got_offset = (target->got_mod_index_entry(NULL, NULL, NULL)
                        - target->got_size());
          Arm_address got_entry =
            target->got_plt_section()->address() + got_offset;
 
-          // Relocate the field with the PC relative offset of the pair of
-          // GOT entries.
-          RelocFuncs::pcrel32_unaligned(view, got_entry, address);
+         // Relocate the field with the PC relative offset of the pair of
+         // GOT entries.
+         RelocFuncs::pcrel32_unaligned(view, got_entry, address);
          return ArmRelocFuncs::STATUS_OKAY;
-        }
+       }
       break;
 
     case elfcpp::R_ARM_TLS_LDO32:      // Alternate local-dynamic
@@ -9309,51 +9418,51 @@ Target_arm<big_endian>::Relocate::relocate_tls(
 
     case elfcpp::R_ARM_TLS_IE32:       // Initial-exec
       if (optimized_type == tls::TLSOPT_NONE)
-        {
-          // Relocate the field with the offset of the GOT entry for
-          // the tp-relative offset of the symbol.
+       {
+         // Relocate the field with the offset of the GOT entry for
+         // the tp-relative offset of the symbol.
          unsigned int got_type = GOT_TYPE_TLS_OFFSET;
-          unsigned int got_offset;
-          if (gsym != NULL)
-            {
-              gold_assert(gsym->has_got_offset(got_type));
-              got_offset = gsym->got_offset(got_type);
-            }
-          else
-            {
-              unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
-              gold_assert(object->local_has_got_offset(r_sym, got_type));
-              got_offset = object->local_got_offset(r_sym, got_type);
-            }
-
-          // All GOT offsets are relative to the end of the GOT.
-          got_offset -= target->got_size();
+         unsigned int got_offset;
+         if (gsym != NULL)
+           {
+             gold_assert(gsym->has_got_offset(got_type));
+             got_offset = gsym->got_offset(got_type);
+           }
+         else
+           {
+             unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+             gold_assert(object->local_has_got_offset(r_sym, got_type));
+             got_offset = object->local_got_offset(r_sym, got_type);
+           }
+
+         // All GOT offsets are relative to the end of the GOT.
+         got_offset -= target->got_size();
 
          Arm_address got_entry =
            target->got_plt_section()->address() + got_offset;
 
-          // Relocate the field with the PC relative offset of the GOT entry.
+         // Relocate the field with the PC relative offset of the GOT entry.
          RelocFuncs::pcrel32_unaligned(view, got_entry, address);
          return ArmRelocFuncs::STATUS_OKAY;
-        }
+       }
       break;
 
     case elfcpp::R_ARM_TLS_LE32:       // Local-exec
       // If we're creating a shared library, a dynamic relocation will
       // have been created for this location, so do not apply it now.
       if (!parameters->options().shared())
-        {
-          gold_assert(tls_segment != NULL);
+       {
+         gold_assert(tls_segment != NULL);
 
          // $tp points to the TCB, which is followed by the TLS, so we
          // need to add TCB size to the offset.
          Arm_address aligned_tcb_size =
            align_address(ARM_TCB_SIZE, tls_segment->maximum_alignment());
-          RelocFuncs::rel32_unaligned(view, value + aligned_tcb_size);
+         RelocFuncs::rel32_unaligned(view, value + aligned_tcb_size);
 
-        }
+       }
       return ArmRelocFuncs::STATUS_OKAY;
-    
+
     default:
       gold_unreachable();
     }
@@ -9582,10 +9691,10 @@ Target_arm<big_endian>::relocate_special_relocatable(
   else
     {
       section_offset_type sot_offset =
-          convert_types<section_offset_type, Arm_address>(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);
+         output_section->output_offset(object, relinfo->data_shndx,
+                                       sot_offset);
       gold_assert(new_sot_offset != -1);
       new_offset = new_sot_offset;
     }
@@ -9597,7 +9706,7 @@ Target_arm<big_endian>::relocate_special_relocatable(
     {
       new_offset += view_address;
       if (offset_in_output_section != invalid_address)
-        new_offset -= offset_in_output_section;
+       new_offset -= offset_in_output_section;
     }
 
   reloc_write.put_r_offset(new_offset);
@@ -9619,14 +9728,14 @@ Target_arm<big_endian>::relocate_special_relocatable(
   Arm_address thumb_bit =
      object->local_symbol_is_thumb_function(r_sym) ? 1 : 0;
   if (thumb_bit != 0
-      && arp->uses_thumb_bit() 
+      && 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 =
@@ -9684,7 +9793,7 @@ Target_arm<big_endian>::relocate_special_relocatable(
     case elfcpp::R_ARM_JUMP24:
     case elfcpp::R_ARM_XPC25:
       reloc_status =
-       Arm_relocate_functions<big_endian>::arm_branch_common(
+       Arm_relocate_functions<big_endian>::arm_branch_common(
            r_type, relinfo, paddend, NULL, object, 0, psymval, 0, thumb_bit,
            false);
       break;
@@ -9945,21 +10054,21 @@ Target_arm<big_endian>::do_make_elf_object(
       || (et == elfcpp::ET_EXEC && input_file->just_symbols()))
     {
       Arm_relobj<big_endian>* obj =
-        new Arm_relobj<big_endian>(name, input_file, offset, ehdr);
+       new Arm_relobj<big_endian>(name, input_file, offset, ehdr);
       obj->setup();
       return obj;
     }
   else if (et == elfcpp::ET_DYN)
     {
       Sized_dynobj<32, big_endian>* obj =
-        new Arm_dynobj<big_endian>(name, input_file, offset, ehdr);
+       new Arm_dynobj<big_endian>(name, input_file, offset, ehdr);
       obj->setup();
       return obj;
     }
   else
     {
       gold_error(_("%s: unsupported ELF file type %d"),
-                 name.c_str(), et);
+                name.c_str(), et);
       return NULL;
     }
 }
@@ -10254,7 +10363,7 @@ Target_arm<big_endian>::tag_cpu_name_value(unsigned int value)
       char buffer[100];
       sprintf(buffer, "<unknown CPU value %u>", value);
       return std::string(buffer);
-    } 
+    }
 }
 
 // Merge object attributes from input file called NAME with those of the
@@ -10284,7 +10393,7 @@ Target_arm<big_endian>::merge_object_attributes(
        {
          if (out_attr[elfcpp::Tag_MPextension_use].int_value() != 0
              && out_attr[elfcpp::Tag_MPextension_use_legacy].int_value()
-               != out_attr[elfcpp::Tag_MPextension_use].int_value())
+               != out_attr[elfcpp::Tag_MPextension_use].int_value())
            {
              gold_error(_("%s has both the current and legacy "
                           "Tag_MPextension_use attributes"),
@@ -10314,7 +10423,7 @@ Target_arm<big_endian>::merge_object_attributes(
            in_attr[elfcpp::Tag_ABI_VFP_args].int_value());
       else if (in_attr[elfcpp::Tag_ABI_FP_number_model].int_value() != 0
               && parameters->options().warn_mismatch())
-        gold_error(_("%s uses VFP register arguments, output does not"),
+       gold_error(_("%s uses VFP register arguments, output does not"),
                   name);
     }
 
@@ -10634,19 +10743,19 @@ Target_arm<big_endian>::merge_object_attributes(
          // the input attribute's value is zero or two then if the output
          // attribute's value is one the output value is set to the input
          // value, otherwise the output value must be the same as the
-         // inputs.  */ 
-         if (in_attr[i].int_value() != 1 && out_attr[i].int_value() != 1) 
-           { 
+         // inputs.  */
+         if (in_attr[i].int_value() != 1 && out_attr[i].int_value() != 1)
+           {
              if (in_attr[i].int_value() != out_attr[i].int_value())
                {
                  gold_error(_("DIV usage mismatch between %s and output"),
                             name);
                }
-           } 
+           }
 
          if (in_attr[i].int_value() != 1)
-           out_attr[i].set_int_value(in_attr[i].int_value()); 
-         
+           out_attr[i].set_int_value(in_attr[i].int_value());
+
          break;
 
        case elfcpp::Tag_MPextension_use_legacy:
@@ -10659,7 +10768,7 @@ Target_arm<big_endian>::merge_object_attributes(
                  != in_attr[i].int_value())
                {
                  gold_error(_("%s has has both the current and legacy "
-                              "Tag_MPextension_use attributes"), 
+                              "Tag_MPextension_use attributes"),
                             name);
                }
            }
@@ -10755,7 +10864,7 @@ Target_arm<big_endian>::merge_object_attributes(
          err_tag = out_iter->first;
          int saved_tag = out_iter->first;
          delete out_iter->second;
-         out_other_attributes->erase(out_iter); 
+         out_other_attributes->erase(out_iter);
          out_iter = out_other_attributes->upper_bound(saved_tag);
        }
       else if (in_iter != in_other_attributes->end()
@@ -10833,7 +10942,7 @@ Target_arm<big_endian>::new_arm_input_section(
   // for this input section already.
   gold_assert(ins.second);
 
-  return arm_input_section; 
+  return arm_input_section;
 }
 
 // Find the Arm_input_section object corresponding to the SHNDX-th input
@@ -10930,7 +11039,7 @@ Target_arm<big_endian>::scan_reloc_for_stub(
        psymval->value(arm_relobj, 0) & ~static_cast<Arm_address>(1);
       symval.set_output_value(stripped_value);
       psymval = &symval;
-    } 
+    }
 
   // Get the symbol value.
   Symbol_value<32>::Value value = psymval->value(arm_relobj, 0);
@@ -10964,10 +11073,10 @@ Target_arm<big_endian>::scan_reloc_for_stub(
   if (stub_type != arm_stub_none)
     {
       // Try looking up an existing stub from a stub table.
-      Stub_table<big_endian>* stub_table = 
+      Stub_table<big_endian>* stub_table =
        arm_relobj->stub_table(relinfo->data_shndx);
       gold_assert(stub_table != NULL);
-   
+
       // Locate stub by destination.
       Reloc_stub::Key stub_key(stub_type, gsym, arm_relobj, r_sym, addend);
 
@@ -11055,13 +11164,13 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
 
       // Only a few relocation types need stubs.
       if ((r_type != elfcpp::R_ARM_CALL)
-         && (r_type != elfcpp::R_ARM_JUMP24)
-         && (r_type != elfcpp::R_ARM_PLT32)
-         && (r_type != elfcpp::R_ARM_THM_CALL)
-         && (r_type != elfcpp::R_ARM_THM_XPC22)
-         && (r_type != elfcpp::R_ARM_THM_JUMP24)
-         && (r_type != elfcpp::R_ARM_THM_JUMP19)
-         && (r_type != elfcpp::R_ARM_V4BX))
+        && (r_type != elfcpp::R_ARM_JUMP24)
+        && (r_type != elfcpp::R_ARM_PLT32)
+        && (r_type != elfcpp::R_ARM_THM_CALL)
+        && (r_type != elfcpp::R_ARM_THM_XPC22)
+        && (r_type != elfcpp::R_ARM_THM_JUMP24)
+        && (r_type != elfcpp::R_ARM_THM_JUMP19)
+        && (r_type != elfcpp::R_ARM_V4BX))
        continue;
 
       section_offset_type offset =
@@ -11100,7 +11209,7 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
                    {
                      // create a new stub and add it to stub table.
                      Arm_v4bx_stub* stub =
-                       this->stub_factory().make_arm_v4bx_stub(reg);
+                       this->stub_factory().make_arm_v4bx_stub(reg);
                      gold_assert(stub != NULL);
                      stub_table->add_arm_v4bx_stub(stub);
                    }
@@ -11125,11 +11234,11 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
          sym = NULL;
          psymval = arm_object->local_symbol(r_sym);
 
-          // If the local symbol belongs to a section we are discarding,
-          // and that section is a debug section, try to find the
-          // corresponding kept section and map this symbol to its
-          // counterpart in the kept section.  The symbol must not 
-          // correspond to a section we are folding.
+         // If the local symbol belongs to a section we are discarding,
+         // and that section is a debug section, try to find the
+         // corresponding kept section and map this symbol to its
+         // counterpart in the kept section.  The symbol must not
+         // correspond to a section we are folding.
          bool is_ordinary;
          shndx = psymval->input_shndx(&is_ordinary);
          is_defined_in_discarded_section =
@@ -11145,7 +11254,7 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
              typedef Sized_relobj_file<32, big_endian> ObjType;
              typename ObjType::Compute_final_local_value_status status =
                arm_object->compute_final_local_value(r_sym, psymval, &symval,
-                                                     relinfo->symtab); 
+                                                     relinfo->symtab);
              if (status == ObjType::CFLV_OK)
                {
                  // Currently we cannot handle a branch to a target in
@@ -11164,7 +11273,7 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
              else
                {
                  // We cannot determine the final value.
-                 continue;  
+                 continue;
                }
            }
        }
@@ -11385,7 +11494,7 @@ Target_arm<big_endian>::do_relax(
        }
 
       group_sections(layout, stub_group_size, stubs_always_after_branch, task);
-     
+
       // Also fix .ARM.exidx section coverage.
       Arm_output_section<big_endian>* exidx_output_section = NULL;
       for (Layout::Section_list::const_iterator p =
@@ -11449,7 +11558,7 @@ Target_arm<big_endian>::do_relax(
           ++sp)
        (*sp)->remove_all_cortex_a8_stubs();
     }
-  
+
   // Scan relocs for relocation stubs
   for (Input_objects::Relobj_iterator op = input_objects->relobj_begin();
        op != input_objects->relobj_end();
@@ -11665,16 +11774,16 @@ Target_arm<big_endian>::scan_span_for_cortex_a8_erratum(
          // Encoding T4: B<c>.W.
          is_b = (insn & 0xf800d000U) == 0xf0009000U;
          // Encoding T1: BL<c>.W.
-         is_bl = (insn & 0xf800d000U) == 0xf000d000U;
-                 // Encoding T2: BLX<c>.W.
-                 is_blx = (insn & 0xf800d000U) == 0xf000c000U;
+         is_bl = (insn & 0xf800d000U) == 0xf000d000U;
+         // Encoding T2: BLX<c>.W.
+         is_blx = (insn & 0xf800d000U) == 0xf000c000U;
          // Encoding T3: B<c>.W (not permitted in IT block).
          is_bcc = ((insn & 0xf800d000U) == 0xf0008000U
                    && (insn & 0x07f00000U) != 0x03800000U);
        }
 
       bool is_32bit_branch = is_b || is_bl || is_blx || is_bcc;
-                          
+
       // If this instruction is a 32-bit THUMB branch that crosses a 4K
       // page boundary and it follows 32-bit non-branch instruction,
       // we need to work around.
@@ -11729,7 +11838,7 @@ Target_arm<big_endian>::scan_span_for_cortex_a8_erratum(
              offset = RelocFuncs::thumb32_branch_offset(upper_insn,
                                                         lower_insn);
              if (is_blx)
-               offset &= ~3;
+               offset &= ~3;
 
              stub_type = (is_blx
                           ? arm_stub_a8_veneer_blx
@@ -11766,17 +11875,17 @@ Target_arm<big_endian>::scan_span_for_cortex_a8_erratum(
              if (is_blx)
                pc_for_insn &= ~3;
 
-              // If we found a relocation, use the proper destination,
+             // If we found a relocation, use the proper destination,
              // not the offset in the (unrelocated) instruction.
              // Note this is always done if we switched the stub type above.
-              if (cortex_a8_reloc != NULL)
-                offset = (off_t) (cortex_a8_reloc->destination() - pc_for_insn);
+             if (cortex_a8_reloc != NULL)
+               offset = (off_t) (cortex_a8_reloc->destination() - pc_for_insn);
 
-              Arm_address target = (pc_for_insn + offset) | (is_blx ? 0 : 1);
+             Arm_address target = (pc_for_insn + offset) | (is_blx ? 0 : 1);
 
              // Add a new stub if destination address in in the same page.
-              if (((address + i) & ~0xfffU) == (target & ~0xfffU))
-                {
+             if (((address + i) & ~0xfffU) == (target & ~0xfffU))
+               {
                  Cortex_a8_stub* stub =
                    this->stub_factory_.make_cortex_a8_stub(stub_type,
                                                            arm_relobj, shndx,
@@ -11786,9 +11895,9 @@ Target_arm<big_endian>::scan_span_for_cortex_a8_erratum(
                    arm_relobj->stub_table(shndx);
                  gold_assert(stub_table != NULL);
                  stub_table->add_cortex_a8_stub(address + i, stub);
-                }
-            }
-        }
+               }
+           }
+       }
 
       i += insn_32bit ? 4 : 2;
       last_was_32bit = insn_32bit;
@@ -11846,6 +11955,9 @@ Target_arm<big_endian>::apply_cortex_a8_workaround(
   elfcpp::Swap<16, big_endian>::writeval(wv + 1, lower_insn);
 }
 
+// Target selector for ARM.  Note this is never instantiated directly.
+// It's only used in Target_selector_arm_nacl, below.
+
 template<bool big_endian>
 class Target_selector_arm : public Target_selector
 {
@@ -11919,7 +12031,7 @@ Target_arm<big_endian>::fix_exidx_coverage(
       Arm_output_section<big_endian>* arm_output_section =
        Arm_output_section<big_endian>::as_arm_output_section(*p);
       arm_output_section->append_text_sections_to_list(&sorted_text_sections);
-    } 
+    }
 
   exidx_section->fix_exidx_coverage(layout, sorted_text_sections, symtab,
                                    merge_exidx_entries(), task);
@@ -11954,7 +12066,7 @@ Target_arm<big_endian>::do_define_standard_symbols(
                                    NULL, // version
                                    Symbol_table::PREDEFINED,
                                    exidx_section,
-                                   0, // value
+                                   0, // value
                                    0, // symsize
                                    elfcpp::STT_NOTYPE,
                                    elfcpp::STB_GLOBAL,
@@ -11968,19 +12080,229 @@ Target_arm<big_endian>::do_define_standard_symbols(
       // Define __exidx_start and __exidx_end even when .ARM.exidx
       // section is missing to match ld's behaviour.
       symtab->define_as_constant("__exidx_start", NULL,
-                                 Symbol_table::PREDEFINED,
-                                 0, 0, elfcpp::STT_OBJECT,
-                                 elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN, 0,
-                                 true, false);
+                                Symbol_table::PREDEFINED,
+                                0, 0, elfcpp::STT_OBJECT,
+                                elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN, 0,
+                                true, false);
       symtab->define_as_constant("__exidx_end", NULL,
-                                 Symbol_table::PREDEFINED,
-                                 0, 0, elfcpp::STT_OBJECT,
-                                 elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN, 0,
-                                 true, false);
+                                Symbol_table::PREDEFINED,
+                                0, 0, elfcpp::STT_OBJECT,
+                                elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN, 0,
+                                true, false);
     }
 }
 
-Target_selector_arm<false> target_selector_arm;
-Target_selector_arm<true> target_selector_armbe;
+// NaCl variant.  It uses different PLT contents.
+
+template<bool big_endian>
+class Output_data_plt_arm_nacl;
+
+template<bool big_endian>
+class Target_arm_nacl : public Target_arm<big_endian>
+{
+ public:
+  Target_arm_nacl()
+    : Target_arm<big_endian>(&arm_nacl_info)
+  { }
+
+ protected:
+  virtual Output_data_plt_arm<big_endian>*
+  do_make_data_plt(Layout* layout, Output_data_space* got_plt)
+  { return new Output_data_plt_arm_nacl<big_endian>(layout, got_plt); }
+
+ private:
+  static const Target::Target_info arm_nacl_info;
+};
+
+template<bool big_endian>
+const Target::Target_info Target_arm_nacl<big_endian>::arm_nacl_info =
+{
+  32,                  // size
+  big_endian,          // is_big_endian
+  elfcpp::EM_ARM,      // machine_code
+  false,               // has_make_symbol
+  false,               // has_resolve
+  false,               // has_code_fill
+  true,                        // is_default_stack_executable
+  false,               // can_icf_inline_merge_sections
+  '\0',                        // wrap_char
+  "/lib/ld-nacl-arm.so.1", // dynamic_linker
+  0x20000,             // default_text_segment_address
+  0x10000,             // abi_pagesize (overridable by -z max-page-size)
+  0x10000,             // common_pagesize (overridable by -z common-page-size)
+  true,                 // isolate_execinstr
+  0x10000000,           // rosegment_gap
+  elfcpp::SHN_UNDEF,   // small_common_shndx
+  elfcpp::SHN_UNDEF,   // large_common_shndx
+  0,                   // small_common_section_flags
+  0,                   // large_common_section_flags
+  ".ARM.attributes",   // attributes_section
+  "aeabi"              // attributes_vendor
+};
+
+template<bool big_endian>
+class Output_data_plt_arm_nacl : public Output_data_plt_arm<big_endian>
+{
+ public:
+  Output_data_plt_arm_nacl(Layout* layout, Output_data_space* got_plt)
+    : Output_data_plt_arm<big_endian>(layout, 16, got_plt)
+  { }
+
+ protected:
+  // Return the offset of the first non-reserved PLT entry.
+  virtual unsigned int
+  do_first_plt_entry_offset() const
+  { return sizeof(first_plt_entry); }
+
+  // Return the size of a PLT entry.
+  virtual unsigned int
+  do_get_plt_entry_size() const
+  { return sizeof(plt_entry); }
+
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov,
+                         Arm_address got_address,
+                         Arm_address plt_address);
+
+  virtual void
+  do_fill_plt_entry(unsigned char* pov,
+                   Arm_address got_address,
+                   Arm_address plt_address,
+                   unsigned int got_offset,
+                   unsigned int plt_offset);
+
+ private:
+  inline uint32_t arm_movw_immediate(uint32_t value)
+  {
+    return (value & 0x00000fff) | ((value & 0x0000f000) << 4);
+  }
+
+  inline uint32_t arm_movt_immediate(uint32_t value)
+  {
+    return ((value & 0x0fff0000) >> 16) | ((value & 0xf0000000) >> 12);
+  }
+
+  // Template for the first PLT entry.
+  static const uint32_t first_plt_entry[16];
+
+  // Template for subsequent PLT entries.
+  static const uint32_t plt_entry[4];
+};
+
+// The first entry in the PLT.
+template<bool big_endian>
+const uint32_t Output_data_plt_arm_nacl<big_endian>::first_plt_entry[16] =
+{
+  // First bundle:
+  0xe300c000,                           // movw        ip, #:lower16:&GOT[2]-.+8
+  0xe340c000,                           // movt        ip, #:upper16:&GOT[2]-.+8
+  0xe08cc00f,                           // add ip, ip, pc
+  0xe52dc008,                           // str ip, [sp, #-8]!
+  // Second bundle:
+  0xe7dfcf1f,                           // bfc ip, #30, #2
+  0xe59cc000,                           // ldr ip, [ip]
+  0xe3ccc13f,                           // bic ip, ip, #0xc000000f
+  0xe12fff1c,                           // bx  ip
+  // Third bundle:
+  0xe320f000,                           // nop
+  0xe320f000,                           // nop
+  0xe320f000,                           // nop
+  // .Lplt_tail:
+  0xe50dc004,                           // str ip, [sp, #-4]
+  // Fourth bundle:
+  0xe7dfcf1f,                           // bfc ip, #30, #2
+  0xe59cc000,                           // ldr ip, [ip]
+  0xe3ccc13f,                           // bic ip, ip, #0xc000000f
+  0xe12fff1c,                           // bx  ip
+};
+
+template<bool big_endian>
+void
+Output_data_plt_arm_nacl<big_endian>::do_fill_first_plt_entry(
+    unsigned char* pov,
+    Arm_address got_address,
+    Arm_address plt_address)
+{
+  // Write first PLT entry.  All but first two words are constants.
+  const size_t num_first_plt_words = (sizeof(first_plt_entry)
+                                     / sizeof(first_plt_entry[0]));
+
+  int32_t got_displacement = got_address + 8 - (plt_address + 16);
+
+  elfcpp::Swap<32, big_endian>::writeval
+    (pov + 0, first_plt_entry[0] | arm_movw_immediate (got_displacement));
+  elfcpp::Swap<32, big_endian>::writeval
+    (pov + 4, first_plt_entry[1] | arm_movt_immediate (got_displacement));
+
+  for (size_t i = 2; i < num_first_plt_words; ++i)
+    elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]);
+}
+
+// Subsequent entries in the PLT.
+
+template<bool big_endian>
+const uint32_t Output_data_plt_arm_nacl<big_endian>::plt_entry[4] =
+{
+  0xe300c000,                           // movw        ip, #:lower16:&GOT[n]-.+8
+  0xe340c000,                           // movt        ip, #:upper16:&GOT[n]-.+8
+  0xe08cc00f,                           // add ip, ip, pc
+  0xea000000,                           // b   .Lplt_tail
+};
+
+template<bool big_endian>
+void
+Output_data_plt_arm_nacl<big_endian>::do_fill_plt_entry(
+    unsigned char* pov,
+    Arm_address got_address,
+    Arm_address plt_address,
+    unsigned int got_offset,
+    unsigned int plt_offset)
+{
+  // Calculate the displacement between the PLT slot and the
+  // common tail that's part of the special initial PLT slot.
+  int32_t tail_displacement = (plt_address + (11 * sizeof(uint32_t))
+                              - (plt_address + plt_offset
+                                 + sizeof(plt_entry) + sizeof(uint32_t)));
+  gold_assert((tail_displacement & 3) == 0);
+  tail_displacement >>= 2;
+
+  gold_assert ((tail_displacement & 0xff000000) == 0
+              || (-tail_displacement & 0xff000000) == 0);
+
+  // Calculate the displacement between the PLT slot and the entry
+  // in the GOT.  The offset accounts for the value produced by
+  // adding to pc in the penultimate instruction of the PLT stub.
+  const int32_t got_displacement = (got_address + got_offset
+                                   - (plt_address + sizeof(plt_entry)));
+
+  elfcpp::Swap<32, big_endian>::writeval
+    (pov + 0, plt_entry[0] | arm_movw_immediate (got_displacement));
+  elfcpp::Swap<32, big_endian>::writeval
+    (pov + 4, plt_entry[1] | arm_movt_immediate (got_displacement));
+  elfcpp::Swap<32, big_endian>::writeval
+    (pov + 8, plt_entry[2]);
+  elfcpp::Swap<32, big_endian>::writeval
+    (pov + 12, plt_entry[3] | (tail_displacement & 0x00ffffff));
+}
+
+// Target selectors.
+
+template<bool big_endian>
+class Target_selector_arm_nacl
+  : public Target_selector_nacl<Target_selector_arm<big_endian>,
+                               Target_arm_nacl<big_endian> >
+{
+ public:
+  Target_selector_arm_nacl()
+    : Target_selector_nacl<Target_selector_arm<big_endian>,
+                          Target_arm_nacl<big_endian> >(
+         "arm",
+         big_endian ? "elf32-bigarm-nacl" : "elf32-littlearm-nacl",
+         big_endian ? "armelfb_nacl" : "armelf_nacl")
+  { }
+};
+
+Target_selector_arm_nacl<false> target_selector_arm;
+Target_selector_arm_nacl<true> target_selector_armbe;
 
 } // End anonymous namespace.
index 175dd0561cc74205d3ace655273b1b172ae600bc..3bdedceb8ee078225b512028ab58d86e7fb0067f 100644 (file)
@@ -1,6 +1,6 @@
 // freebsd.h -- FreeBSD support for gold    -*- C++ -*-
 
-// Copyright 2009, 2011 Free Software Foundation, Inc.
+// Copyright 2009, 2011, 2012 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -48,14 +48,14 @@ class Target_selector_freebsd : public Target_selector
   // If we see a FreeBSD input file, mark the output file as using
   // FreeBSD.
   virtual Target*
-  do_recognize(int, int osabi, int)
+  do_recognize(Input_file*, off_t, int, int osabi, int)
   {
     Target* ret = this->instantiate_target();
     if (osabi == elfcpp::ELFOSABI_FREEBSD)
       ret->set_osabi(static_cast<elfcpp::ELFOSABI>(osabi));
     return ret;
   }
-  
+
   // Recognize two names.
   virtual Target*
   do_recognize_by_bfd_name(const char* name)
index f810bf913ba00fc7bdce210c3f00f1ac0819a2c4..013702fed878cef0e5d7c30bbb6859c84ea1cf47 100644 (file)
@@ -1,6 +1,7 @@
 // gold.cc -- main linker functions
 
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -136,7 +137,7 @@ Middle_runner::run(Workqueue* workqueue, const Task* task)
 
 // This class arranges the tasks to process the relocs for garbage collection.
 
-class Gc_runner : public Task_function_runner 
+class Gc_runner : public Task_function_runner
 {
   public:
    Gc_runner(const General_options& options,
@@ -161,9 +162,9 @@ class Gc_runner : public Task_function_runner
 void
 Gc_runner::run(Workqueue* workqueue, const Task* task)
 {
-  queue_middle_gc_tasks(this->options_, task, this->input_objects_, 
-                        this->symtab_, this->layout_, workqueue, 
-                        this->mapfile_);
+  queue_middle_gc_tasks(this->options_, task, this->input_objects_,
+                       this->symtab_, this->layout_, workqueue,
+                       this->mapfile_);
 }
 
 // Queue up the initial set of tasks for this link job.
@@ -287,21 +288,21 @@ queue_initial_tasks(const General_options& options,
     {
       workqueue->queue(new Task_function(new Gc_runner(options,
                                                       input_objects,
-                                                       symtab,
-                                                       layout,
-                                                       mapfile),
-                                         this_blocker,
-                                         "Task_function Gc_runner"));
+                                                      symtab,
+                                                      layout,
+                                                      mapfile),
+                                        this_blocker,
+                                        "Task_function Gc_runner"));
     }
   else
     {
       workqueue->queue(new Task_function(new Middle_runner(options,
-                                                           input_objects,
-                                                           symtab,
-                                                           layout,
-                                                           mapfile),
-                                         this_blocker,
-                                         "Task_function Middle_runner"));
+                                                          input_objects,
+                                                          symtab,
+                                                          layout,
+                                                          mapfile),
+                                        this_blocker,
+                                        "Task_function Middle_runner"));
     }
 }
 
@@ -467,12 +468,12 @@ queue_middle_gc_tasks(const General_options& options,
     }
 
   workqueue->queue(new Task_function(new Middle_runner(options,
-                                                       input_objects,
-                                                       symtab,
-                                                       layout,
-                                                       mapfile),
-                                     this_blocker,
-                                     "Task_function Middle_runner"));
+                                                      input_objects,
+                                                      symtab,
+                                                      layout,
+                                                      mapfile),
+                                    this_blocker,
+                                    "Task_function Middle_runner"));
 }
 
 // Queue up the middle set of tasks.  These are the tasks which run
@@ -496,22 +497,22 @@ queue_middle_tasks(const General_options& options,
   symtab->add_undefined_symbols_from_command_line(layout);
 
   // If garbage collection was chosen, relocs have been read and processed
-  // at this point by pre_middle_tasks.  Layout can then be done for all 
+  // at this point by pre_middle_tasks.  Layout can then be done for all
   // objects.
   if (parameters->options().gc_sections())
     {
       // Find the start symbol if any.
       Symbol* start_sym = symtab->lookup(parameters->entry());
       if (start_sym != NULL)
-        {
-          bool is_ordinary;
-          unsigned int shndx = start_sym->shndx(&is_ordinary);
-          if (is_ordinary) 
-            {
-              symtab->gc()->worklist().push(
-                Section_id(start_sym->object(), shndx));
-            }
-        }
+       {
+         bool is_ordinary;
+         unsigned int shndx = start_sym->shndx(&is_ordinary);
+         if (is_ordinary)
+           {
+             symtab->gc()->worklist().push(
+               Section_id(start_sym->object(), shndx));
+           }
+       }
       // Symbols named with -u should not be considered garbage.
       symtab->gc_mark_undef_symbols(layout);
       gold_assert(symtab->gc() != NULL);
@@ -519,29 +520,29 @@ queue_middle_tasks(const General_options& options,
       symtab->gc()->do_transitive_closure();
     }
 
-  // If identical code folding (--icf) is chosen it makes sense to do it 
-  // only after garbage collection (--gc-sections) as we do not want to 
+  // If identical code folding (--icf) is chosen it makes sense to do it
+  // only after garbage collection (--gc-sections) as we do not want to
   // be folding sections that will be garbage.
   if (parameters->options().icf_enabled())
     {
       symtab->icf()->find_identical_sections(input_objects, symtab);
     }
 
-  // Call Object::layout for the second time to determine the 
-  // output_sections for all referenced input sections.  When 
-  // --gc-sections or --icf is turned on, Object::layout is 
-  // called twice.  It is called the first time when the 
+  // Call Object::layout for the second time to determine the
+  // output_sections for all referenced input sections.  When
+  // --gc-sections or --icf is turned on, Object::layout is
+  // called twice.  It is called the first time when the
   // symbols are added.
   if (parameters->options().gc_sections()
       || parameters->options().icf_enabled())
     {
       for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
-           p != input_objects->relobj_end();
-           ++p)
-        {
-          Task_lock_obj<Object> tlo(task, *p);
-          (*p)->layout(symtab, layout, NULL);
-        }
+          p != input_objects->relobj_end();
+          ++p)
+       {
+         Task_lock_obj<Object> tlo(task, *p);
+         (*p)->layout(symtab, layout, NULL);
+       }
     }
 
   /* If plugins have specified a section order, re-arrange input sections
@@ -553,9 +554,9 @@ queue_middle_tasks(const General_options& options,
     {
       for (Layout::Section_list::const_iterator p
             = layout->section_list().begin();
-           p != layout->section_list().end();
-           ++p)
-        (*p)->update_section_layout(layout->get_section_order_map());
+          p != layout->section_list().end();
+          ++p)
+       (*p)->update_section_layout(layout->get_section_order_map());
     }
 
   // Layout deferred objects due to plugins.
@@ -564,26 +565,26 @@ queue_middle_tasks(const General_options& options,
       Plugin_manager* plugins = parameters->options().plugins();
       gold_assert(plugins != NULL);
       plugins->layout_deferred_objects();
-    }     
+    }
 
   if (parameters->options().gc_sections()
       || parameters->options().icf_enabled())
     {
       for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
-           p != input_objects->relobj_end();
-           ++p)
-        {
-          // Update the value of output_section stored in rd.
-          Read_relocs_data* rd = (*p)->get_relocs_data();
-          for (Read_relocs_data::Relocs_list::iterator q = rd->relocs.begin();
-               q != rd->relocs.end();
-               ++q)
-            {
-              q->output_section = (*p)->output_section(q->data_shndx);
-              q->needs_special_offset_handling = 
-                      (*p)->is_output_section_offset_invalid(q->data_shndx);
-            }
-        }
+          p != input_objects->relobj_end();
+          ++p)
+       {
+         // Update the value of output_section stored in rd.
+         Read_relocs_data* rd = (*p)->get_relocs_data();
+         for (Read_relocs_data::Relocs_list::iterator q = rd->relocs.begin();
+              q != rd->relocs.end();
+              ++q)
+           {
+             q->output_section = (*p)->output_section(q->data_shndx);
+             q->needs_special_offset_handling =
+                     (*p)->is_output_section_offset_invalid(q->data_shndx);
+           }
+       }
     }
 
   // We have to support the case of not seeing any input objects, and
@@ -676,11 +677,12 @@ queue_middle_tasks(const General_options& options,
   // Define symbols from any linker scripts.
   layout->define_script_symbols(symtab);
 
-  // Attach sections to segments.
-  layout->attach_sections_to_segments();
-
   // TODO(csilvers): figure out a more principled way to get the target
   Target* target = const_cast<Target*>(&parameters->target());
+
+  // Attach sections to segments.
+  layout->attach_sections_to_segments(target);
+
   if (!parameters->options().relocatable())
     {
       // Predefine standard symbols.
@@ -716,12 +718,12 @@ queue_middle_tasks(const General_options& options,
       || parameters->options().icf_enabled())
     {
       for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
-           p != input_objects->relobj_end();
-           ++p)
+          p != input_objects->relobj_end();
+          ++p)
        {
          Task_token* next_blocker = new Task_token(true);
          next_blocker->add_blocker();
-         workqueue->queue(new Scan_relocs(symtab, layout, *p, 
+         workqueue->queue(new Scan_relocs(symtab, layout, *p,
                                           (*p)->get_relocs_data(),
                                           this_blocker, next_blocker));
          this_blocker = next_blocker;
@@ -741,15 +743,15 @@ queue_middle_tasks(const General_options& options,
       // some of the sections, and thus change our minds about the types
       // of references made to the symbols.
       for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
-           p != input_objects->relobj_end();
-           ++p)
-        {
+          p != input_objects->relobj_end();
+          ++p)
+       {
          Task_token* next_blocker = new Task_token(true);
          next_blocker->add_blocker();
-          workqueue->queue(new Read_relocs(symtab, layout, *p, this_blocker,
+         workqueue->queue(new Read_relocs(symtab, layout, *p, this_blocker,
                                           next_blocker));
          this_blocker = next_blocker;
-        }
+       }
     }
 
   if (this_blocker == NULL)
@@ -761,7 +763,7 @@ queue_middle_tasks(const General_options& options,
          // blocker here so that we can run the layout task immediately.
          this_blocker = new Task_token(true);
        }
-      else 
+      else
        {
          // If we failed to open any input files, it's possible for
          // THIS_BLOCKER to be NULL here.  There's no real point in
@@ -776,7 +778,7 @@ queue_middle_tasks(const General_options& options,
   workqueue->queue(new Task_function(new Layout_task_runner(options,
                                                            input_objects,
                                                            symtab,
-                                                            target,
+                                                           target,
                                                            layout,
                                                            mapfile),
                                     this_blocker,
index b4174bc57f6a9066c5bdf84ca38fd500a374e385..47f33a0a4fce6a7a68babf4452ca8245daabfd95 100644 (file)
@@ -40,6 +40,7 @@
 #include "target-select.h"
 #include "tls.h"
 #include "freebsd.h"
+#include "nacl.h"
 #include "gc.h"
 
 namespace
@@ -48,13 +49,17 @@ namespace
 using namespace gold;
 
 // A class to handle the PLT data.
+// This is an abstract base class that handles most of the linker details
+// but does not know the actual contents of PLT entries.  The derived
+// classes below fill in those details.
 
 class Output_data_plt_i386 : public Output_section_data
 {
  public:
   typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, false> Reloc_section;
 
-  Output_data_plt_i386(Layout*, Output_data_space*, Output_data_space*);
+  Output_data_plt_i386(Layout*, uint64_t addralign,
+                      Output_data_space*, Output_data_space*);
 
   // Add an entry to the PLT.
   void
@@ -90,14 +95,14 @@ class Output_data_plt_i386 : public Output_section_data
   { return this->count_ + this->irelative_count_; }
 
   // Return the offset of the first non-reserved PLT entry.
-  static unsigned int
+  unsigned int
   first_plt_entry_offset()
-  { return plt_entry_size; }
+  { return this->get_plt_entry_size(); }
 
   // Return the size of a PLT entry.
-  static unsigned int
-  get_plt_entry_size()
-  { return plt_entry_size; }
+  unsigned int
+  get_plt_entry_size() const
+  { return this->do_get_plt_entry_size(); }
 
   // Return the PLT address to use for a global symbol.
   uint64_t
@@ -107,43 +112,73 @@ class Output_data_plt_i386 : public Output_section_data
   uint64_t
   address_for_local(const Relobj*, unsigned int symndx);
 
- protected:
+  // Add .eh_frame information for the PLT.
   void
-  do_adjust_output_section(Output_section* os);
+  add_eh_frame(Layout* layout)
+  { this->do_add_eh_frame(layout); }
 
-  // Write to a map file.
+ protected:
+  // Fill the first PLT entry, given the pointer to the PLT section data
+  // and the runtime address of the GOT.
   void
-  do_print_to_mapfile(Mapfile* mapfile) const
-  { mapfile->print_output_data(this, _("** PLT")); }
+  fill_first_plt_entry(unsigned char* pov,
+                      elfcpp::Elf_types<32>::Elf_Addr got_address)
+  { this->do_fill_first_plt_entry(pov, got_address); }
+
+  // Fill a normal PLT entry, given the pointer to the entry's data in the
+  // section, the runtime address of the GOT, the offset into the GOT of
+  // the corresponding slot, the offset into the relocation section of the
+  // corresponding reloc, and the offset of this entry within the whole
+  // PLT.  Return the offset from this PLT entry's runtime address that
+  // should be used to compute the initial value of the GOT slot.
+  unsigned int
+  fill_plt_entry(unsigned char* pov,
+                elfcpp::Elf_types<32>::Elf_Addr got_address,
+                unsigned int got_offset,
+                unsigned int plt_offset,
+                unsigned int plt_rel_offset)
+  {
+    return this->do_fill_plt_entry(pov, got_address, got_offset,
+                                  plt_offset, plt_rel_offset);
+  }
 
- private:
-  // The size of an entry in the PLT.
-  static const int plt_entry_size = 16;
+  virtual unsigned int
+  do_get_plt_entry_size() const = 0;
 
-  // The first entry in the PLT for an executable.
-  static const unsigned char exec_first_plt_entry[plt_entry_size];
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov,
+                         elfcpp::Elf_types<32>::Elf_Addr got_address) = 0;
 
-  // The first entry in the PLT for a shared object.
-  static const unsigned char dyn_first_plt_entry[plt_entry_size];
+  virtual unsigned int
+  do_fill_plt_entry(unsigned char* pov,
+                   elfcpp::Elf_types<32>::Elf_Addr got_address,
+                   unsigned int got_offset,
+                   unsigned int plt_offset,
+                   unsigned int plt_rel_offset) = 0;
 
-  // Other entries in the PLT for an executable.
-  static const unsigned char exec_plt_entry[plt_entry_size];
+  virtual void
+  do_add_eh_frame(Layout*) = 0;
 
-  // Other entries in the PLT for a shared object.
-  static const unsigned char dyn_plt_entry[plt_entry_size];
+  void
+  do_adjust_output_section(Output_section* os);
+
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** PLT")); }
 
   // The .eh_frame unwind information for the PLT.
+  // The CIE is common across variants of the PLT format.
   static const int plt_eh_frame_cie_size = 16;
-  static const int plt_eh_frame_fde_size = 32;
   static const unsigned char plt_eh_frame_cie[plt_eh_frame_cie_size];
-  static const unsigned char plt_eh_frame_fde[plt_eh_frame_fde_size];
 
+ private:
   // Set the final size.
   void
   set_final_data_size()
   {
     this->set_data_size((this->count_ + this->irelative_count_ + 1)
-                       * plt_entry_size);
+                       * this->get_plt_entry_size());
   }
 
   // Write out the PLT data.
@@ -193,6 +228,101 @@ class Output_data_plt_i386 : public Output_section_data
   std::vector<Local_ifunc> local_ifuncs_;
 };
 
+// This is an abstract class for the standard PLT layout.
+// The derived classes below handle the actual PLT contents
+// for the executable (non-PIC) and shared-library (PIC) cases.
+// The unwind information is uniform across those two, so it's here.
+
+class Output_data_plt_i386_standard : public Output_data_plt_i386
+{
+ public:
+  Output_data_plt_i386_standard(Layout* layout,
+                               Output_data_space* got_plt,
+                               Output_data_space* got_irelative)
+    : Output_data_plt_i386(layout, plt_entry_size, got_plt, got_irelative)
+  { }
+
+ protected:
+  virtual unsigned int
+  do_get_plt_entry_size() const
+  { return plt_entry_size; }
+
+  virtual void
+  do_add_eh_frame(Layout* layout)
+  {
+    layout->add_eh_frame_for_plt(this, plt_eh_frame_cie, plt_eh_frame_cie_size,
+                                plt_eh_frame_fde, plt_eh_frame_fde_size);
+  }
+
+  // The size of an entry in the PLT.
+  static const int plt_entry_size = 16;
+
+  // The .eh_frame unwind information for the PLT.
+  static const int plt_eh_frame_fde_size = 32;
+  static const unsigned char plt_eh_frame_fde[plt_eh_frame_fde_size];
+};
+
+// Actually fill the PLT contents for an executable (non-PIC).
+
+class Output_data_plt_i386_exec : public Output_data_plt_i386_standard
+{
+public:
+  Output_data_plt_i386_exec(Layout* layout,
+                           Output_data_space* got_plt,
+                           Output_data_space* got_irelative)
+    : Output_data_plt_i386_standard(layout, got_plt, got_irelative)
+  { }
+
+ protected:
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov,
+                         elfcpp::Elf_types<32>::Elf_Addr got_address);
+
+  virtual unsigned int
+  do_fill_plt_entry(unsigned char* pov,
+                   elfcpp::Elf_types<32>::Elf_Addr got_address,
+                   unsigned int got_offset,
+                   unsigned int plt_offset,
+                   unsigned int plt_rel_offset);
+
+ private:
+  // The first entry in the PLT for an executable.
+  static const unsigned char first_plt_entry[plt_entry_size];
+
+  // Other entries in the PLT for an executable.
+  static const unsigned char plt_entry[plt_entry_size];
+};
+
+// Actually fill the PLT contents for a shared library (PIC).
+
+class Output_data_plt_i386_dyn : public Output_data_plt_i386_standard
+{
+ public:
+  Output_data_plt_i386_dyn(Layout* layout,
+                          Output_data_space* got_plt,
+                          Output_data_space* got_irelative)
+    : Output_data_plt_i386_standard(layout, got_plt, got_irelative)
+  { }
+
+ protected:
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov, elfcpp::Elf_types<32>::Elf_Addr);
+
+  virtual unsigned int
+  do_fill_plt_entry(unsigned char* pov,
+                   elfcpp::Elf_types<32>::Elf_Addr,
+                   unsigned int got_offset,
+                   unsigned int plt_offset,
+                   unsigned int plt_rel_offset);
+
+ private:
+  // The first entry in the PLT for a shared object.
+  static const unsigned char first_plt_entry[plt_entry_size];
+
+  // Other entries in the PLT for a shared object.
+  static const unsigned char plt_entry[plt_entry_size];
+};
+
 // The i386 target class.
 // TLS info comes from
 //   http://people.redhat.com/drepper/tls.pdf
@@ -203,28 +333,28 @@ class Target_i386 : public Sized_target<32, false>
  public:
   typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, false> Reloc_section;
 
-  Target_i386()
-    : Sized_target<32, false>(&i386_info),
+  Target_i386(const Target::Target_info* info = &i386_info)
+    : Sized_target<32, false>(info),
       got_(NULL), plt_(NULL), got_plt_(NULL), got_irelative_(NULL),
       got_tlsdesc_(NULL), global_offset_table_(NULL), rel_dyn_(NULL),
       rel_irelative_(NULL), copy_relocs_(elfcpp::R_386_COPY), dynbss_(NULL),
       got_mod_index_offset_(-1U), tls_base_symbol_defined_(false)
   { }
 
-  // Process the relocations to determine unreferenced sections for 
+  // Process the relocations to determine unreferenced sections for
   // garbage collection.
   void
   gc_process_relocs(Symbol_table* symtab,
-                    Layout* layout,
-                    Sized_relobj_file<32, false>* object,
-                    unsigned int data_shndx,
-                    unsigned int sh_type,
-                    const unsigned char* prelocs,
-                    size_t reloc_count,
-                    Output_section* output_section,
-                    bool needs_special_offset_handling,
-                    size_t local_symbol_count,
-                    const unsigned char* plocal_symbols);
+                   Layout* layout,
+                   Sized_relobj_file<32, false>* object,
+                   unsigned int data_shndx,
+                   unsigned int sh_type,
+                   const unsigned char* prelocs,
+                   size_t reloc_count,
+                   Output_section* output_section,
+                   bool needs_special_offset_handling,
+                   size_t local_symbol_count,
+                   const unsigned char* plocal_symbols);
 
   // Scan the relocations to look for symbol adjustments.
   void
@@ -372,6 +502,28 @@ class Target_i386 : public Sized_target<32, false>
   unsigned int
   plt_entry_size() const;
 
+ protected:
+  // Instantiate the plt_ member.
+  // This chooses the right PLT flavor for an executable or a shared object.
+  Output_data_plt_i386*
+  make_data_plt(Layout* layout,
+               Output_data_space* got_plt,
+               Output_data_space* got_irelative,
+               bool dyn)
+  { return this->do_make_data_plt(layout, got_plt, got_irelative, dyn); }
+
+  virtual Output_data_plt_i386*
+  do_make_data_plt(Layout* layout,
+                  Output_data_space* got_plt,
+                  Output_data_space* got_irelative,
+                  bool dyn)
+  {
+    if (dyn)
+      return new Output_data_plt_i386_dyn(layout, got_plt, got_irelative);
+    else
+      return new Output_data_plt_i386_exec(layout, got_plt, got_irelative);
+  }
+
  private:
   // The class which scans relocations.
   struct Scan
@@ -398,23 +550,23 @@ class Target_i386 : public Sized_target<32, false>
 
     inline bool
     local_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
-                                       Target_i386* target,
-                                       Sized_relobj_file<32, false>* object,
-                                       unsigned int data_shndx,
-                                       Output_section* output_section,
-                                       const elfcpp::Rel<32, false>& reloc,
+                                       Target_i386* target,
+                                       Sized_relobj_file<32, false>* object,
+                                       unsigned int data_shndx,
+                                       Output_section* output_section,
+                                       const elfcpp::Rel<32, false>& reloc,
                                        unsigned int r_type,
-                                       const elfcpp::Sym<32, false>& lsym);
+                                       const elfcpp::Sym<32, false>& lsym);
 
     inline bool
     global_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
                                         Target_i386* target,
-                                        Sized_relobj_file<32, false>* object,
-                                        unsigned int data_shndx,
-                                        Output_section* output_section,
+                                        Sized_relobj_file<32, false>* object,
+                                        unsigned int data_shndx,
+                                        Output_section* output_section,
                                         const elfcpp::Rel<32, false>& reloc,
                                         unsigned int r_type,
-                                        Symbol* gsym);
+                                        Symbol* gsym);
 
     inline bool
     possible_function_pointer_reloc(unsigned int r_type);
@@ -452,8 +604,8 @@ class Target_i386 : public Sized_target<32, false>
     // Return whether the static relocation needs to be applied.
     inline bool
     should_apply_static_reloc(const Sized_symbol<32>* gsym,
-                              unsigned int r_type,
-                              bool is_32bit,
+                             unsigned int r_type,
+                             bool is_32bit,
                              Output_section* output_section);
 
     // Do a relocation.  Return false if the caller should not issue
@@ -470,7 +622,7 @@ class Target_i386 : public Sized_target<32, false>
     // Do a TLS relocation.
     inline void
     relocate_tls(const Relocate_info<32, false>*, Target_i386* target,
-                 size_t relnum, const elfcpp::Rel<32, false>&,
+                size_t relnum, const elfcpp::Rel<32, false>&,
                 unsigned int r_type, const Sized_symbol<32>*,
                 const Symbol_value<32>*,
                 unsigned char*, elfcpp::Elf_types<32>::Elf_Addr,
@@ -629,7 +781,7 @@ class Target_i386 : public Sized_target<32, false>
   // Add a potential copy relocation.
   void
   copy_reloc(Symbol_table* symtab, Layout* layout,
-             Sized_relobj_file<32, false>* object,
+            Sized_relobj_file<32, false>* object,
             unsigned int shndx, Output_section* output_section,
             Symbol* sym, const elfcpp::Rel<32, false>& reloc)
   {
@@ -697,6 +849,8 @@ const Target::Target_info Target_i386::i386_info =
   0x08048000,          // default_text_segment_address
   0x1000,              // abi_pagesize (overridable by -z max-page-size)
   0x1000,              // common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
   elfcpp::SHN_UNDEF,   // small_common_shndx
   elfcpp::SHN_UNDEF,   // large_common_shndx
   0,                   // small_common_section_flags
@@ -824,9 +978,11 @@ Target_i386::rel_irelative_section(Layout* layout)
 // section just for PLT entries.
 
 Output_data_plt_i386::Output_data_plt_i386(Layout* layout,
+                                          uint64_t addralign,
                                           Output_data_space* got_plt,
                                           Output_data_space* got_irelative)
-  : Output_section_data(16), layout_(layout), tls_desc_rel_(NULL),
+  : Output_section_data(addralign),
+    layout_(layout), tls_desc_rel_(NULL),
     irelative_rel_(NULL), got_plt_(got_plt), got_irelative_(got_irelative),
     count_(0), irelative_count_(0), global_ifuncs_(), local_ifuncs_()
 {
@@ -834,11 +990,6 @@ Output_data_plt_i386::Output_data_plt_i386(Layout* layout,
   layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
                                  elfcpp::SHF_ALLOC, this->rel_,
                                  ORDER_DYNAMIC_PLT_RELOCS, false);
-
-  // Add unwind information if requested.
-  if (parameters->options().ld_generated_unwind_info())
-    layout->add_eh_frame_for_plt(this, plt_eh_frame_cie, plt_eh_frame_cie_size,
-                                plt_eh_frame_fde, plt_eh_frame_fde_size);
 }
 
 void
@@ -861,7 +1012,7 @@ Output_data_plt_i386::add_entry(Symbol_table* symtab, Layout* layout,
   if (gsym->type() == elfcpp::STT_GNU_IFUNC
       && gsym->can_use_relative_reloc(false))
     {
-      gsym->set_plt_offset(this->irelative_count_ * plt_entry_size);
+      gsym->set_plt_offset(this->irelative_count_ * this->get_plt_entry_size());
       ++this->irelative_count_;
       section_offset_type got_offset =
        this->got_irelative_->current_data_size();
@@ -878,7 +1029,7 @@ Output_data_plt_i386::add_entry(Symbol_table* symtab, Layout* layout,
     {
       // When setting the PLT offset we skip the initial reserved PLT
       // entry.
-      gsym->set_plt_offset((this->count_ + 1) * plt_entry_size);
+      gsym->set_plt_offset((this->count_ + 1) * this->get_plt_entry_size());
 
       ++this->count_;
 
@@ -909,7 +1060,7 @@ Output_data_plt_i386::add_local_ifunc_entry(
     Sized_relobj_file<32, false>* relobj,
     unsigned int local_sym_index)
 {
-  unsigned int plt_offset = this->irelative_count_ * plt_entry_size;
+  unsigned int plt_offset = this->irelative_count_ * this->get_plt_entry_size();
   ++this->irelative_count_;
 
   section_offset_type got_offset = this->got_irelative_->current_data_size();
@@ -998,7 +1149,7 @@ Output_data_plt_i386::address_for_global(const Symbol* gsym)
   uint64_t offset = 0;
   if (gsym->type() == elfcpp::STT_GNU_IFUNC
       && gsym->can_use_relative_reloc(false))
-    offset = (this->count_ + 1) * plt_entry_size;
+    offset = (this->count_ + 1) * this->get_plt_entry_size();
   return this->address() + offset;
 }
 
@@ -1008,12 +1159,12 @@ Output_data_plt_i386::address_for_global(const Symbol* gsym)
 uint64_t
 Output_data_plt_i386::address_for_local(const Relobj*, unsigned int)
 {
-  return this->address() + (this->count_ + 1) * plt_entry_size;
+  return this->address() + (this->count_ + 1) * this->get_plt_entry_size();
 }
 
 // The first entry in the PLT for an executable.
 
-const unsigned char Output_data_plt_i386::exec_first_plt_entry[plt_entry_size] =
+const unsigned char Output_data_plt_i386_exec::first_plt_entry[plt_entry_size] =
 {
   0xff, 0x35,  // pushl contents of memory address
   0, 0, 0, 0,  // replaced with address of .got + 4
@@ -1022,18 +1173,36 @@ const unsigned char Output_data_plt_i386::exec_first_plt_entry[plt_entry_size] =
   0, 0, 0, 0   // unused
 };
 
+void
+Output_data_plt_i386_exec::do_fill_first_plt_entry(
+    unsigned char* pov,
+    elfcpp::Elf_types<32>::Elf_Addr got_address)
+{
+  memcpy(pov, first_plt_entry, plt_entry_size);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_address + 4);
+  elfcpp::Swap<32, false>::writeval(pov + 8, got_address + 8);
+}
+
 // The first entry in the PLT for a shared object.
 
-const unsigned char Output_data_plt_i386::dyn_first_plt_entry[plt_entry_size] =
+const unsigned char Output_data_plt_i386_dyn::first_plt_entry[plt_entry_size] =
 {
   0xff, 0xb3, 4, 0, 0, 0,      // pushl 4(%ebx)
   0xff, 0xa3, 8, 0, 0, 0,      // jmp *8(%ebx)
   0, 0, 0, 0                   // unused
 };
 
+void
+Output_data_plt_i386_dyn::do_fill_first_plt_entry(
+    unsigned char* pov,
+    elfcpp::Elf_types<32>::Elf_Addr)
+{
+  memcpy(pov, first_plt_entry, plt_entry_size);
+}
+
 // Subsequent entries in the PLT for an executable.
 
-const unsigned char Output_data_plt_i386::exec_plt_entry[plt_entry_size] =
+const unsigned char Output_data_plt_i386_exec::plt_entry[plt_entry_size] =
 {
   0xff, 0x25,  // jmp indirect
   0, 0, 0, 0,  // replaced with address of symbol in .got
@@ -1043,9 +1212,25 @@ const unsigned char Output_data_plt_i386::exec_plt_entry[plt_entry_size] =
   0, 0, 0, 0   // replaced with offset to start of .plt
 };
 
+unsigned int
+Output_data_plt_i386_exec::do_fill_plt_entry(
+    unsigned char* pov,
+    elfcpp::Elf_types<32>::Elf_Addr got_address,
+    unsigned int got_offset,
+    unsigned int plt_offset,
+    unsigned int plt_rel_offset)
+{
+  memcpy(pov, plt_entry, plt_entry_size);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+                                             got_address + got_offset);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 7, plt_rel_offset);
+  elfcpp::Swap<32, false>::writeval(pov + 12, - (plt_offset + 12 + 4));
+  return 6;
+}
+
 // Subsequent entries in the PLT for a shared object.
 
-const unsigned char Output_data_plt_i386::dyn_plt_entry[plt_entry_size] =
+const unsigned char Output_data_plt_i386_dyn::plt_entry[plt_entry_size] =
 {
   0xff, 0xa3,  // jmp *offset(%ebx)
   0, 0, 0, 0,  // replaced with offset of symbol in .got
@@ -1055,6 +1240,20 @@ const unsigned char Output_data_plt_i386::dyn_plt_entry[plt_entry_size] =
   0, 0, 0, 0   // replaced with offset to start of .plt
 };
 
+unsigned int
+Output_data_plt_i386_dyn::do_fill_plt_entry(unsigned char* pov,
+                                           elfcpp::Elf_types<32>::Elf_Addr,
+                                           unsigned int got_offset,
+                                           unsigned int plt_offset,
+                                           unsigned int plt_rel_offset)
+{
+  memcpy(pov, plt_entry, plt_entry_size);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_offset);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 7, plt_rel_offset);
+  elfcpp::Swap<32, false>::writeval(pov + 12, - (plt_offset + 12 + 4));
+  return 6;
+}
+
 // The .eh_frame unwind information for the PLT.
 
 const unsigned char
@@ -1077,7 +1276,7 @@ Output_data_plt_i386::plt_eh_frame_cie[plt_eh_frame_cie_size] =
 };
 
 const unsigned char
-Output_data_plt_i386::plt_eh_frame_fde[plt_eh_frame_fde_size] =
+Output_data_plt_i386_standard::plt_eh_frame_fde[plt_eh_frame_fde_size] =
 {
   0, 0, 0, 0,                          // Replaced with offset to .plt.
   0, 0, 0, 0,                          // Replaced with size of .plt.
@@ -1130,15 +1329,8 @@ Output_data_plt_i386::do_write(Output_file* of)
   elfcpp::Elf_types<32>::Elf_Addr plt_address = this->address();
   elfcpp::Elf_types<32>::Elf_Addr got_address = this->got_plt_->address();
 
-  if (parameters->options().output_is_position_independent())
-    memcpy(pov, dyn_first_plt_entry, plt_entry_size);
-  else
-    {
-      memcpy(pov, exec_first_plt_entry, plt_entry_size);
-      elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_address + 4);
-      elfcpp::Swap<32, false>::writeval(pov + 8, got_address + 8);
-    }
-  pov += plt_entry_size;
+  this->fill_first_plt_entry(pov, got_address);
+  pov += this->get_plt_entry_size();
 
   unsigned char* got_pov = got_view;
 
@@ -1155,40 +1347,29 @@ Output_data_plt_i386::do_write(Output_file* of)
 
   const int rel_size = elfcpp::Elf_sizes<32>::rel_size;
 
-  unsigned int plt_offset = plt_entry_size;
+  unsigned int plt_offset = this->get_plt_entry_size();
   unsigned int plt_rel_offset = 0;
   unsigned int got_offset = 12;
   const unsigned int count = this->count_ + this->irelative_count_;
   for (unsigned int i = 0;
        i < count;
        ++i,
-        pov += plt_entry_size,
+        pov += this->get_plt_entry_size(),
         got_pov += 4,
-        plt_offset += plt_entry_size,
+        plt_offset += this->get_plt_entry_size(),
         plt_rel_offset += rel_size,
         got_offset += 4)
     {
       // Set and adjust the PLT entry itself.
-
-      if (parameters->options().output_is_position_independent())
-       {
-         memcpy(pov, dyn_plt_entry, plt_entry_size);
-         elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_offset);
-       }
-      else
-       {
-         memcpy(pov, exec_plt_entry, plt_entry_size);
-         elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
-                                                     (got_address
-                                                      + got_offset));
-       }
-
-      elfcpp::Swap_unaligned<32, false>::writeval(pov + 7, plt_rel_offset);
-      elfcpp::Swap<32, false>::writeval(pov + 12,
-                                       - (plt_offset + plt_entry_size));
+      unsigned int lazy_offset = this->fill_plt_entry(pov,
+                                                     got_address,
+                                                     got_offset,
+                                                     plt_offset,
+                                                     plt_rel_offset);
 
       // Set the entry in the GOT.
-      elfcpp::Swap<32, false>::writeval(got_pov, plt_address + plt_offset + 6);
+      elfcpp::Swap<32, false>::writeval(got_pov,
+                                       plt_address + plt_offset + lazy_offset);
     }
 
   // If any STT_GNU_IFUNC symbols have PLT entries, we need to change
@@ -1235,8 +1416,16 @@ Target_i386::make_plt_section(Symbol_table* symtab, Layout* layout)
       // Create the GOT sections first.
       this->got_section(symtab, layout);
 
-      this->plt_ = new Output_data_plt_i386(layout, this->got_plt_,
-                                           this->got_irelative_);
+      const bool dyn = parameters->options().output_is_position_independent();
+      this->plt_ = this->make_data_plt(layout,
+                                      this->got_plt_,
+                                      this->got_irelative_,
+                                      dyn);
+
+      // Add unwind information if requested.
+      if (parameters->options().ld_generated_unwind_info())
+       this->plt_->add_eh_frame(layout);
+
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
                                      (elfcpp::SHF_ALLOC
                                       | elfcpp::SHF_EXECINSTR),
@@ -1292,7 +1481,7 @@ Target_i386::plt_entry_count() const
 unsigned int
 Target_i386::first_plt_entry_offset() const
 {
-  return Output_data_plt_i386::first_plt_entry_offset();
+  return this->plt_->first_plt_entry_offset();
 }
 
 // Return the size of each PLT entry.
@@ -1300,7 +1489,7 @@ Target_i386::first_plt_entry_offset() const
 unsigned int
 Target_i386::plt_entry_size() const
 {
-  return Output_data_plt_i386::get_plt_entry_size();
+  return this->plt_->get_plt_entry_size();
 }
 
 // Get the section to use for TLS_DESC relocations.
@@ -1341,7 +1530,7 @@ Target_i386::define_tls_base_symbol(Symbol_table* symtab, Layout* layout)
 
 unsigned int
 Target_i386::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
-                                Sized_relobj_file<32, false>* object)
+                                Sized_relobj_file<32, false>* object)
 {
   if (this->got_mod_index_offset_ == -1U)
     {
@@ -1350,7 +1539,7 @@ Target_i386::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
       Output_data_got<32, false>* got = this->got_section(symtab, layout);
       unsigned int got_offset = got->add_constant(0);
       rel_dyn->add_local(object, 0, elfcpp::R_386_TLS_DTPMOD32, got,
-                         got_offset);
+                        got_offset);
       got->add_constant(0);
       this->got_mod_index_offset_ = got_offset;
     }
@@ -1505,7 +1694,7 @@ Target_i386::Scan::reloc_needs_plt_for_ifunc(
   int flags = Scan::get_reference_flags(r_type);
   if (flags & Symbol::TLS_REF)
     gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
-               object->name().c_str(), r_type);
+              object->name().c_str(), r_type);
   return flags != 0;
 }
 
@@ -1513,14 +1702,14 @@ Target_i386::Scan::reloc_needs_plt_for_ifunc(
 
 inline void
 Target_i386::Scan::local(Symbol_table* symtab,
-                        Layout* layout,
-                        Target_i386* target,
-                        Sized_relobj_file<32, false>* object,
-                        unsigned int data_shndx,
-                        Output_section* output_section,
-                        const elfcpp::Rel<32, false>& reloc,
-                        unsigned int r_type,
-                        const elfcpp::Sym<32, false>& lsym)
+                               Layout* layout,
+                               Target_i386* target,
+                               Sized_relobj_file<32, false>* object,
+                               unsigned int data_shndx,
+                               Output_section* output_section,
+                               const elfcpp::Rel<32, false>& reloc,
+                               unsigned int r_type,
+                               const elfcpp::Sym<32, false>& lsym)
 {
   // A local STT_GNU_IFUNC symbol may require a PLT entry.
   if (lsym.get_st_type() == elfcpp::STT_GNU_IFUNC
@@ -1545,13 +1734,13 @@ Target_i386::Scan::local(Symbol_table* symtab,
       // an R_386_RELATIVE relocation so the dynamic loader can
       // relocate it easily.
       if (parameters->options().output_is_position_independent())
-        {
-          Reloc_section* rel_dyn = target->rel_dyn_section(layout);
-          unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+       {
+         Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+         unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
          rel_dyn->add_local_relative(object, r_sym, elfcpp::R_386_RELATIVE,
                                      output_section, data_shndx,
                                      reloc.get_r_offset());
-        }
+       }
       break;
 
     case elfcpp::R_386_16:
@@ -1562,15 +1751,15 @@ Target_i386::Scan::local(Symbol_table* symtab,
       // data section, we need to be careful not to apply this
       // relocation statically.
       if (parameters->options().output_is_position_independent())
-        {
-          Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+       {
+         Reloc_section* rel_dyn = target->rel_dyn_section(layout);
          unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
-          if (lsym.get_st_type() != elfcpp::STT_SECTION)
+         if (lsym.get_st_type() != elfcpp::STT_SECTION)
            rel_dyn->add_local(object, r_sym, r_type, output_section,
                               data_shndx, reloc.get_r_offset());
-          else
-            {
-              gold_assert(lsym.get_st_value() == 0);
+         else
+           {
+             gold_assert(lsym.get_st_value() == 0);
              unsigned int shndx = lsym.get_st_shndx();
              bool is_ordinary;
              shndx = object->adjust_sym_shndx(r_sym, shndx,
@@ -1582,8 +1771,8 @@ Target_i386::Scan::local(Symbol_table* symtab,
                rel_dyn->add_local_section(object, shndx,
                                           r_type, output_section,
                                           data_shndx, reloc.get_r_offset());
-            }
-        }
+           }
+       }
       break;
 
     case elfcpp::R_386_PC32:
@@ -1604,9 +1793,9 @@ Target_i386::Scan::local(Symbol_table* symtab,
 
     case elfcpp::R_386_GOT32:
       {
-        // The symbol requires a GOT entry.
-        Output_data_got<32, false>* got = target->got_section(symtab, layout);
-        unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+       // The symbol requires a GOT entry.
+       Output_data_got<32, false>* got = target->got_section(symtab, layout);
+       unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
 
        // For a STT_GNU_IFUNC symbol we want the PLT offset.  That
        // lets function pointers compare correctly with shared
@@ -1616,20 +1805,20 @@ Target_i386::Scan::local(Symbol_table* symtab,
          is_new = got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD);
        else
          is_new = got->add_local(object, r_sym, GOT_TYPE_STANDARD);
-        if (is_new)
-          {
-            // If we are generating a shared object, we need to add a
-            // dynamic RELATIVE relocation for this symbol's GOT entry.
-            if (parameters->options().output_is_position_independent())
-              {
-                Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+       if (is_new)
+         {
+           // If we are generating a shared object, we need to add a
+           // dynamic RELATIVE relocation for this symbol's GOT entry.
+           if (parameters->options().output_is_position_independent())
+             {
+               Reloc_section* rel_dyn = target->rel_dyn_section(layout);
                unsigned int got_offset =
                  object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
                rel_dyn->add_local_relative(object, r_sym,
                                            elfcpp::R_386_RELATIVE,
                                            got, got_offset);
-              }
-          }
+             }
+         }
       }
       break;
 
@@ -1664,24 +1853,24 @@ Target_i386::Scan::local(Symbol_table* symtab,
       {
        bool output_is_shared = parameters->options().shared();
        const tls::Tls_optimization optimized_type
-            = Target_i386::optimize_tls_reloc(!output_is_shared, r_type);
+           = Target_i386::optimize_tls_reloc(!output_is_shared, r_type);
        switch (r_type)
          {
          case elfcpp::R_386_TLS_GD:          // Global-dynamic
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // Create a pair of GOT entries for the module index and
-               // dtv-relative offset.
-                Output_data_got<32, false>* got
-                    = target->got_section(symtab, layout);
-                unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+               // Create a pair of GOT entries for the module index and
+               // dtv-relative offset.
+               Output_data_got<32, false>* got
+                   = target->got_section(symtab, layout);
+               unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
                unsigned int shndx = lsym.get_st_shndx();
                bool is_ordinary;
                shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
                if (!is_ordinary)
                  object->error(_("local symbol %u has bad shndx %u"),
                              r_sym, shndx);
-                else
+               else
                  got->add_local_pair_with_rel(object, r_sym, shndx,
                                               GOT_TYPE_TLS_PAIR,
                                               target->rel_dyn_section(layout),
@@ -1693,16 +1882,16 @@ Target_i386::Scan::local(Symbol_table* symtab,
 
          case elfcpp::R_386_TLS_GOTDESC:     // Global-dynamic (from ~oliva)
            target->define_tls_base_symbol(symtab, layout);
-            if (optimized_type == tls::TLSOPT_NONE)
-              {
-                // Create a double GOT entry with an R_386_TLS_DESC
-                // reloc.  The R_386_TLS_DESC reloc is resolved
-                // lazily, so the GOT entry needs to be in an area in
-                // .got.plt, not .got.  Call got_section to make sure
-                // the section has been created.
+           if (optimized_type == tls::TLSOPT_NONE)
+             {
+               // Create a double GOT entry with an R_386_TLS_DESC
+               // reloc.  The R_386_TLS_DESC reloc is resolved
+               // lazily, so the GOT entry needs to be in an area in
+               // .got.plt, not .got.  Call got_section to make sure
+               // the section has been created.
                target->got_section(symtab, layout);
-                Output_data_got<32, false>* got = target->got_tlsdesc_section();
-                unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+               Output_data_got<32, false>* got = target->got_tlsdesc_section();
+               unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
                if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
                  {
                    unsigned int got_offset = got->add_constant(0);
@@ -1717,9 +1906,9 @@ Target_i386::Scan::local(Symbol_table* symtab,
                    Reloc_section* rt = target->rel_tls_desc_section(layout);
                    rt->add_absolute(elfcpp::R_386_TLS_DESC, got, got_offset);
                  }
-              }
-            else if (optimized_type != tls::TLSOPT_TO_LE)
-              unsupported_reloc_local(object, r_type);
+             }
+           else if (optimized_type != tls::TLSOPT_TO_LE)
+             unsupported_reloc_local(object, r_type);
            break;
 
          case elfcpp::R_386_TLS_DESC_CALL:
@@ -1728,8 +1917,8 @@ Target_i386::Scan::local(Symbol_table* symtab,
          case elfcpp::R_386_TLS_LDM:         // Local-dynamic
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // Create a GOT entry for the module index.
-               target->got_mod_index_entry(symtab, layout, object);
+               // Create a GOT entry for the module index.
+               target->got_mod_index_entry(symtab, layout, object);
              }
            else if (optimized_type != tls::TLSOPT_TO_LE)
              unsupported_reloc_local(object, r_type);
@@ -1744,32 +1933,32 @@ Target_i386::Scan::local(Symbol_table* symtab,
            layout->set_has_static_tls();
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // For the R_386_TLS_IE relocation, we need to create a
-               // dynamic relocation when building a shared library.
-               if (r_type == elfcpp::R_386_TLS_IE
-                   && parameters->options().shared())
-                 {
-                    Reloc_section* rel_dyn = target->rel_dyn_section(layout);
-                    unsigned int r_sym
-                        = elfcpp::elf_r_sym<32>(reloc.get_r_info());
-                    rel_dyn->add_local_relative(object, r_sym,
-                                                elfcpp::R_386_RELATIVE,
-                                                output_section, data_shndx,
-                                                reloc.get_r_offset());
-                 }
-               // Create a GOT entry for the tp-relative offset.
-                Output_data_got<32, false>* got
-                    = target->got_section(symtab, layout);
-                unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
-               unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32
-                                          ? elfcpp::R_386_TLS_TPOFF32
-                                          : elfcpp::R_386_TLS_TPOFF);
-               unsigned int got_type = (r_type == elfcpp::R_386_TLS_IE_32
-                                        ? GOT_TYPE_TLS_OFFSET
-                                        : GOT_TYPE_TLS_NOFFSET);
-                got->add_local_with_rel(object, r_sym, got_type,
-                                        target->rel_dyn_section(layout),
-                                        dyn_r_type);
+               // For the R_386_TLS_IE relocation, we need to create a
+               // dynamic relocation when building a shared library.
+               if (r_type == elfcpp::R_386_TLS_IE
+                   && parameters->options().shared())
+                 {
+                   Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+                   unsigned int r_sym
+                       = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+                   rel_dyn->add_local_relative(object, r_sym,
+                                               elfcpp::R_386_RELATIVE,
+                                               output_section, data_shndx,
+                                               reloc.get_r_offset());
+                 }
+               // Create a GOT entry for the tp-relative offset.
+               Output_data_got<32, false>* got
+                   = target->got_section(symtab, layout);
+               unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+               unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32
+                                          ? elfcpp::R_386_TLS_TPOFF32
+                                          : elfcpp::R_386_TLS_TPOFF);
+               unsigned int got_type = (r_type == elfcpp::R_386_TLS_IE_32
+                                        ? GOT_TYPE_TLS_OFFSET
+                                        : GOT_TYPE_TLS_NOFFSET);
+               got->add_local_with_rel(object, r_sym, got_type,
+                                       target->rel_dyn_section(layout),
+                                       dyn_r_type);
              }
            else if (optimized_type != tls::TLSOPT_TO_LE)
              unsupported_reloc_local(object, r_type);
@@ -1780,15 +1969,15 @@ Target_i386::Scan::local(Symbol_table* symtab,
            layout->set_has_static_tls();
            if (output_is_shared)
              {
-               // We need to create a dynamic relocation.
-                gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
-                unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
-                unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_LE_32
-                                           ? elfcpp::R_386_TLS_TPOFF32
-                                           : elfcpp::R_386_TLS_TPOFF);
-                Reloc_section* rel_dyn = target->rel_dyn_section(layout);
-                rel_dyn->add_local(object, r_sym, dyn_r_type, output_section,
-                                   data_shndx, reloc.get_r_offset());
+               // We need to create a dynamic relocation.
+               gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
+               unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+               unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_LE_32
+                                          ? elfcpp::R_386_TLS_TPOFF32
+                                          : elfcpp::R_386_TLS_TPOFF);
+               Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+               rel_dyn->add_local(object, r_sym, dyn_r_type, output_section,
+                                  data_shndx, reloc.get_r_offset());
              }
            break;
 
@@ -1837,7 +2026,7 @@ Target_i386::Scan::possible_function_pointer_reloc(unsigned int r_type)
     case elfcpp::R_386_GOTOFF:
     case elfcpp::R_386_GOT32:
       {
-        return true;
+       return true;
       }
     default:
       return false;
@@ -1879,14 +2068,14 @@ Target_i386::Scan::global_reloc_may_be_function_pointer(
 
 inline void
 Target_i386::Scan::global(Symbol_table* symtab,
-                         Layout* layout,
-                         Target_i386* target,
-                         Sized_relobj_file<32, false>* object,
-                         unsigned int data_shndx,
-                          Output_section* output_section,
-                         const elfcpp::Rel<32, false>& reloc,
-                         unsigned int r_type,
-                         Symbol* gsym)
+                                Layout* layout,
+                                Target_i386* target,
+                                Sized_relobj_file<32, false>* object,
+                                unsigned int data_shndx,
+                                Output_section* output_section,
+                                const elfcpp::Rel<32, false>& reloc,
+                                unsigned int r_type,
+                                Symbol* gsym)
 {
   // A STT_GNU_IFUNC symbol may require a PLT entry.
   if (gsym->type() == elfcpp::STT_GNU_IFUNC
@@ -1904,25 +2093,25 @@ Target_i386::Scan::global(Symbol_table* symtab,
     case elfcpp::R_386_16:
     case elfcpp::R_386_8:
       {
-        // Make a PLT entry if necessary.
-        if (gsym->needs_plt_entry())
-          {
-            target->make_plt_entry(symtab, layout, gsym);
-            // Since this is not a PC-relative relocation, we may be
-            // taking the address of a function. In that case we need to
-            // set the entry in the dynamic symbol table to the address of
-            // the PLT entry.
-            if (gsym->is_from_dynobj() && !parameters->options().shared())
-              gsym->set_needs_dynsym_value();
-          }
-        // Make a dynamic relocation if necessary.
-        if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
-          {
-            if (gsym->may_need_copy_reloc())
-              {
-               target->copy_reloc(symtab, layout, object,
-                                  data_shndx, output_section, gsym, reloc);
-              }
+       // Make a PLT entry if necessary.
+       if (gsym->needs_plt_entry())
+         {
+           target->make_plt_entry(symtab, layout, gsym);
+           // Since this is not a PC-relative relocation, we may be
+           // taking the address of a function. In that case we need to
+           // set the entry in the dynamic symbol table to the address of
+           // the PLT entry.
+           if (gsym->is_from_dynobj() && !parameters->options().shared())
+             gsym->set_needs_dynsym_value();
+         }
+       // Make a dynamic relocation if necessary.
+       if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
+         {
+           if (gsym->may_need_copy_reloc())
+             {
+               target->copy_reloc(symtab, layout, object,
+                                  data_shndx, output_section, gsym, reloc);
+             }
            else if (r_type == elfcpp::R_386_32
                     && gsym->type() == elfcpp::STT_GNU_IFUNC
                     && gsym->can_use_relative_reloc(false)
@@ -1941,21 +2130,21 @@ Target_i386::Scan::global(Symbol_table* symtab,
                                                      object, data_shndx,
                                                      reloc.get_r_offset());
              }
-            else if (r_type == elfcpp::R_386_32
-                     && gsym->can_use_relative_reloc(false))
-              {
-                Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+           else if (r_type == elfcpp::R_386_32
+                    && gsym->can_use_relative_reloc(false))
+             {
+               Reloc_section* rel_dyn = target->rel_dyn_section(layout);
                rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
                                             output_section, object,
                                             data_shndx, reloc.get_r_offset());
-              }
-            else
-              {
-                Reloc_section* rel_dyn = target->rel_dyn_section(layout);
-                rel_dyn->add_global(gsym, r_type, output_section, object,
-                                    data_shndx, reloc.get_r_offset());
-              }
-          }
+             }
+           else
+             {
+               Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+               rel_dyn->add_global(gsym, r_type, output_section, object,
+                                   data_shndx, reloc.get_r_offset());
+             }
+         }
       }
       break;
 
@@ -1963,42 +2152,42 @@ Target_i386::Scan::global(Symbol_table* symtab,
     case elfcpp::R_386_PC16:
     case elfcpp::R_386_PC8:
       {
-        // Make a PLT entry if necessary.
-        if (gsym->needs_plt_entry())
-          {
-            // These relocations are used for function calls only in
-            // non-PIC code.  For a 32-bit relocation in a shared library,
-            // we'll need a text relocation anyway, so we can skip the
-            // PLT entry and let the dynamic linker bind the call directly
-            // to the target.  For smaller relocations, we should use a
-            // PLT entry to ensure that the call can reach.
-            if (!parameters->options().shared()
-                || r_type != elfcpp::R_386_PC32)
-              target->make_plt_entry(symtab, layout, gsym);
-          }
-        // Make a dynamic relocation if necessary.
-        if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
-          {
-            if (gsym->may_need_copy_reloc())
-              {
-               target->copy_reloc(symtab, layout, object,
-                                  data_shndx, output_section, gsym, reloc);
-              }
-            else
-              {
-                Reloc_section* rel_dyn = target->rel_dyn_section(layout);
-                rel_dyn->add_global(gsym, r_type, output_section, object,
-                                    data_shndx, reloc.get_r_offset());
-              }
-          }
+       // Make a PLT entry if necessary.
+       if (gsym->needs_plt_entry())
+         {
+           // These relocations are used for function calls only in
+           // non-PIC code.  For a 32-bit relocation in a shared library,
+           // we'll need a text relocation anyway, so we can skip the
+           // PLT entry and let the dynamic linker bind the call directly
+           // to the target.  For smaller relocations, we should use a
+           // PLT entry to ensure that the call can reach.
+           if (!parameters->options().shared()
+               || r_type != elfcpp::R_386_PC32)
+             target->make_plt_entry(symtab, layout, gsym);
+         }
+       // Make a dynamic relocation if necessary.
+       if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
+         {
+           if (gsym->may_need_copy_reloc())
+             {
+               target->copy_reloc(symtab, layout, object,
+                                  data_shndx, output_section, gsym, reloc);
+             }
+           else
+             {
+               Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+               rel_dyn->add_global(gsym, r_type, output_section, object,
+                                   data_shndx, reloc.get_r_offset());
+             }
+         }
       }
       break;
 
     case elfcpp::R_386_GOT32:
       {
-        // The symbol requires a GOT entry.
-        Output_data_got<32, false>* got = target->got_section(symtab, layout);
-        if (gsym->final_value_is_known())
+       // The symbol requires a GOT entry.
+       Output_data_got<32, false>* got = target->got_section(symtab, layout);
+       if (gsym->final_value_is_known())
          {
            // For a STT_GNU_IFUNC symbol we want the PLT address.
            if (gsym->type() == elfcpp::STT_GNU_IFUNC)
@@ -2006,11 +2195,11 @@ Target_i386::Scan::global(Symbol_table* symtab,
            else
              got->add_global(gsym, GOT_TYPE_STANDARD);
          }
-        else
-          {
-            // If this symbol is not fully resolved, we need to add a
-            // GOT entry with a dynamic relocation.
-            Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+       else
+         {
+           // If this symbol is not fully resolved, we need to add a
+           // GOT entry with a dynamic relocation.
+           Reloc_section* rel_dyn = target->rel_dyn_section(layout);
 
            // Use a GLOB_DAT rather than a RELATIVE reloc if:
            //
@@ -2024,17 +2213,17 @@ Target_i386::Scan::global(Symbol_table* symtab,
            //
            // 3) This is a STT_GNU_IFUNC symbol in position dependent
            // code, again so that function address comparisons work.
-            if (gsym->is_from_dynobj()
-                || gsym->is_undefined()
-                || gsym->is_preemptible()
+           if (gsym->is_from_dynobj()
+               || gsym->is_undefined()
+               || gsym->is_preemptible()
                || (gsym->visibility() == elfcpp::STV_PROTECTED
                    && parameters->options().shared())
                || (gsym->type() == elfcpp::STT_GNU_IFUNC
                    && parameters->options().output_is_position_independent()))
-              got->add_global_with_rel(gsym, GOT_TYPE_STANDARD,
-                                       rel_dyn, elfcpp::R_386_GLOB_DAT);
-            else
-              {
+             got->add_global_with_rel(gsym, GOT_TYPE_STANDARD,
+                                      rel_dyn, elfcpp::R_386_GLOB_DAT);
+           else
+             {
                // For a STT_GNU_IFUNC symbol we want to write the PLT
                // offset into the GOT, so that function pointer
                // comparisons work correctly.
@@ -2050,14 +2239,14 @@ Target_i386::Scan::global(Symbol_table* symtab,
                        && !parameters->options().shared())
                      gsym->set_needs_dynsym_value();
                  }
-                if (is_new)
+               if (is_new)
                  {
                    unsigned int got_off = gsym->got_offset(GOT_TYPE_STANDARD);
                    rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
                                                 got, got_off);
                  }
-              }
-          }
+             }
+         }
       }
       break;
 
@@ -2070,8 +2259,8 @@ Target_i386::Scan::global(Symbol_table* symtab,
       // if the symbol is defined in the output file and is protected
       // or hidden.
       if (gsym->is_defined()
-          && !gsym->is_from_dynobj()
-          && !gsym->is_preemptible())
+         && !gsym->is_from_dynobj()
+         && !gsym->is_preemptible())
        break;
       target->make_plt_entry(symtab, layout, gsym);
       break;
@@ -2113,29 +2302,29 @@ Target_i386::Scan::global(Symbol_table* symtab,
       {
        const bool is_final = gsym->final_value_is_known();
        const tls::Tls_optimization optimized_type
-            = Target_i386::optimize_tls_reloc(is_final, r_type);
+           = Target_i386::optimize_tls_reloc(is_final, r_type);
        switch (r_type)
          {
          case elfcpp::R_386_TLS_GD:          // Global-dynamic
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // Create a pair of GOT entries for the module index and
-               // dtv-relative offset.
-                Output_data_got<32, false>* got
-                    = target->got_section(symtab, layout);
-                got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
-                                             target->rel_dyn_section(layout),
-                                             elfcpp::R_386_TLS_DTPMOD32,
-                                             elfcpp::R_386_TLS_DTPOFF32);
+               // Create a pair of GOT entries for the module index and
+               // dtv-relative offset.
+               Output_data_got<32, false>* got
+                   = target->got_section(symtab, layout);
+               got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
+                                            target->rel_dyn_section(layout),
+                                            elfcpp::R_386_TLS_DTPMOD32,
+                                            elfcpp::R_386_TLS_DTPOFF32);
              }
            else if (optimized_type == tls::TLSOPT_TO_IE)
              {
-               // Create a GOT entry for the tp-relative offset.
-                Output_data_got<32, false>* got
-                    = target->got_section(symtab, layout);
-                got->add_global_with_rel(gsym, GOT_TYPE_TLS_NOFFSET,
-                                         target->rel_dyn_section(layout),
-                                         elfcpp::R_386_TLS_TPOFF);
+               // Create a GOT entry for the tp-relative offset.
+               Output_data_got<32, false>* got
+                   = target->got_section(symtab, layout);
+               got->add_global_with_rel(gsym, GOT_TYPE_TLS_NOFFSET,
+                                        target->rel_dyn_section(layout),
+                                        elfcpp::R_386_TLS_TPOFF);
              }
            else if (optimized_type != tls::TLSOPT_TO_LE)
              unsupported_reloc_global(object, r_type, gsym);
@@ -2143,30 +2332,30 @@ Target_i386::Scan::global(Symbol_table* symtab,
 
          case elfcpp::R_386_TLS_GOTDESC:     // Global-dynamic (~oliva url)
            target->define_tls_base_symbol(symtab, layout);
-            if (optimized_type == tls::TLSOPT_NONE)
-              {
-                // Create a double GOT entry with an R_386_TLS_DESC
-                // reloc.  The R_386_TLS_DESC reloc is resolved
-                // lazily, so the GOT entry needs to be in an area in
-                // .got.plt, not .got.  Call got_section to make sure
-                // the section has been created.
+           if (optimized_type == tls::TLSOPT_NONE)
+             {
+               // Create a double GOT entry with an R_386_TLS_DESC
+               // reloc.  The R_386_TLS_DESC reloc is resolved
+               // lazily, so the GOT entry needs to be in an area in
+               // .got.plt, not .got.  Call got_section to make sure
+               // the section has been created.
                target->got_section(symtab, layout);
-                Output_data_got<32, false>* got = target->got_tlsdesc_section();
+               Output_data_got<32, false>* got = target->got_tlsdesc_section();
                Reloc_section* rt = target->rel_tls_desc_section(layout);
-                got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt,
-                                             elfcpp::R_386_TLS_DESC, 0);
-              }
-            else if (optimized_type == tls::TLSOPT_TO_IE)
-              {
-               // Create a GOT entry for the tp-relative offset.
-                Output_data_got<32, false>* got
-                    = target->got_section(symtab, layout);
-                got->add_global_with_rel(gsym, GOT_TYPE_TLS_NOFFSET,
-                                         target->rel_dyn_section(layout),
-                                         elfcpp::R_386_TLS_TPOFF);
-              }
-            else if (optimized_type != tls::TLSOPT_TO_LE)
-              unsupported_reloc_global(object, r_type, gsym);
+               got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt,
+                                            elfcpp::R_386_TLS_DESC, 0);
+             }
+           else if (optimized_type == tls::TLSOPT_TO_IE)
+             {
+               // Create a GOT entry for the tp-relative offset.
+               Output_data_got<32, false>* got
+                   = target->got_section(symtab, layout);
+               got->add_global_with_rel(gsym, GOT_TYPE_TLS_NOFFSET,
+                                        target->rel_dyn_section(layout),
+                                        elfcpp::R_386_TLS_TPOFF);
+             }
+           else if (optimized_type != tls::TLSOPT_TO_LE)
+             unsupported_reloc_global(object, r_type, gsym);
            break;
 
          case elfcpp::R_386_TLS_DESC_CALL:
@@ -2175,8 +2364,8 @@ Target_i386::Scan::global(Symbol_table* symtab,
          case elfcpp::R_386_TLS_LDM:         // Local-dynamic
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // Create a GOT entry for the module index.
-               target->got_mod_index_entry(symtab, layout, object);
+               // Create a GOT entry for the module index.
+               target->got_mod_index_entry(symtab, layout, object);
              }
            else if (optimized_type != tls::TLSOPT_TO_LE)
              unsupported_reloc_global(object, r_type, gsym);
@@ -2191,29 +2380,29 @@ Target_i386::Scan::global(Symbol_table* symtab,
            layout->set_has_static_tls();
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // For the R_386_TLS_IE relocation, we need to create a
-               // dynamic relocation when building a shared library.
-               if (r_type == elfcpp::R_386_TLS_IE
-                   && parameters->options().shared())
-                 {
-                    Reloc_section* rel_dyn = target->rel_dyn_section(layout);
-                    rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
-                                                 output_section, object,
-                                                 data_shndx,
-                                                 reloc.get_r_offset());
-                 }
-               // Create a GOT entry for the tp-relative offset.
-                Output_data_got<32, false>* got
-                    = target->got_section(symtab, layout);
-               unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32
-                                          ? elfcpp::R_386_TLS_TPOFF32
-                                          : elfcpp::R_386_TLS_TPOFF);
-               unsigned int got_type = (r_type == elfcpp::R_386_TLS_IE_32
-                                        ? GOT_TYPE_TLS_OFFSET
-                                        : GOT_TYPE_TLS_NOFFSET);
-                got->add_global_with_rel(gsym, got_type,
-                                         target->rel_dyn_section(layout),
-                                         dyn_r_type);
+               // For the R_386_TLS_IE relocation, we need to create a
+               // dynamic relocation when building a shared library.
+               if (r_type == elfcpp::R_386_TLS_IE
+                   && parameters->options().shared())
+                 {
+                   Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+                   rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
+                                                output_section, object,
+                                                data_shndx,
+                                                reloc.get_r_offset());
+                 }
+               // Create a GOT entry for the tp-relative offset.
+               Output_data_got<32, false>* got
+                   = target->got_section(symtab, layout);
+               unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32
+                                          ? elfcpp::R_386_TLS_TPOFF32
+                                          : elfcpp::R_386_TLS_TPOFF);
+               unsigned int got_type = (r_type == elfcpp::R_386_TLS_IE_32
+                                        ? GOT_TYPE_TLS_OFFSET
+                                        : GOT_TYPE_TLS_NOFFSET);
+               got->add_global_with_rel(gsym, got_type,
+                                        target->rel_dyn_section(layout),
+                                        dyn_r_type);
              }
            else if (optimized_type != tls::TLSOPT_TO_LE)
              unsupported_reloc_global(object, r_type, gsym);
@@ -2224,13 +2413,13 @@ Target_i386::Scan::global(Symbol_table* symtab,
            layout->set_has_static_tls();
            if (parameters->options().shared())
              {
-               // We need to create a dynamic relocation.
-                unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_LE_32
-                                           ? elfcpp::R_386_TLS_TPOFF32
-                                           : elfcpp::R_386_TLS_TPOFF);
-                Reloc_section* rel_dyn = target->rel_dyn_section(layout);
-                rel_dyn->add_global(gsym, dyn_r_type, output_section, object,
-                                    data_shndx, reloc.get_r_offset());
+               // We need to create a dynamic relocation.
+               unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_LE_32
+                                          ? elfcpp::R_386_TLS_TPOFF32
+                                          : elfcpp::R_386_TLS_TPOFF);
+               Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+               rel_dyn->add_global(gsym, dyn_r_type, output_section, object,
+                                   data_shndx, reloc.get_r_offset());
              }
            break;
 
@@ -2260,20 +2449,20 @@ Target_i386::Scan::global(Symbol_table* symtab,
 
 void
 Target_i386::gc_process_relocs(Symbol_table* symtab,
-                               Layout* layout,
-                               Sized_relobj_file<32, false>* object,
-                               unsigned int data_shndx,
-                               unsigned int,
-                               const unsigned char* prelocs,
-                               size_t reloc_count,
-                               Output_section* output_section,
-                               bool needs_special_offset_handling,
-                               size_t local_symbol_count,
-                               const unsigned char* plocal_symbols)
+                                     Layout* layout,
+                                     Sized_relobj_file<32, false>* object,
+                                     unsigned int data_shndx,
+                                     unsigned int,
+                                     const unsigned char* prelocs,
+                                     size_t reloc_count,
+                                     Output_section* output_section,
+                                     bool needs_special_offset_handling,
+                                     size_t local_symbol_count,
+                                     const unsigned char* plocal_symbols)
 {
   gold::gc_process_relocs<32, false, Target_i386, elfcpp::SHT_REL,
-                         Target_i386::Scan,
-                          Target_i386::Relocatable_size_for_reloc>(
+                         Target_i386::Scan,
+                         Target_i386::Relocatable_size_for_reloc>(
     symtab,
     layout,
     this,
@@ -2291,16 +2480,16 @@ Target_i386::gc_process_relocs(Symbol_table* symtab,
 
 void
 Target_i386::scan_relocs(Symbol_table* symtab,
-                        Layout* layout,
-                        Sized_relobj_file<32, false>* object,
-                        unsigned int data_shndx,
-                        unsigned int sh_type,
-                        const unsigned char* prelocs,
-                        size_t reloc_count,
-                        Output_section* output_section,
-                        bool needs_special_offset_handling,
-                        size_t local_symbol_count,
-                        const unsigned char* plocal_symbols)
+                               Layout* layout,
+                               Sized_relobj_file<32, false>* object,
+                               unsigned int data_shndx,
+                               unsigned int sh_type,
+                               const unsigned char* prelocs,
+                               size_t reloc_count,
+                               Output_section* output_section,
+                               bool needs_special_offset_handling,
+                               size_t local_symbol_count,
+                               const unsigned char* plocal_symbols)
 {
   if (sh_type == elfcpp::SHT_RELA)
     {
@@ -2402,8 +2591,8 @@ Target_i386::do_finalize_sections(
 
 inline bool
 Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym,
-                                                 unsigned int r_type,
-                                                 bool is_32bit,
+                                                unsigned int r_type,
+                                                bool is_32bit,
                                                 Output_section* output_section)
 {
   // If the output section is not allocated, then we didn't call
@@ -2420,8 +2609,8 @@ Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym,
   // (c) the relocation is not 32 bits wide.
   if (gsym == NULL)
     return !(parameters->options().output_is_position_independent()
-             && (ref_flags & Symbol::ABSOLUTE_REF)
-             && !is_32bit);
+            && (ref_flags & Symbol::ABSOLUTE_REF)
+            && !is_32bit);
 
   // For global symbols, we use the same helper routines used in the
   // scan pass.  If we did not create a dynamic relocation, or if we
@@ -2429,8 +2618,8 @@ Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym,
   // relocation.
   bool has_dyn = gsym->needs_dynamic_reloc(ref_flags);
   bool is_rel = (ref_flags & Symbol::ABSOLUTE_REF)
-                && gsym->can_use_relative_reloc(ref_flags
-                                                & Symbol::FUNCTION_CALL);
+               && gsym->can_use_relative_reloc(ref_flags
+                                               & Symbol::FUNCTION_CALL);
   return !has_dyn || is_rel;
 }
 
@@ -2438,21 +2627,21 @@ Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym,
 
 inline bool
 Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
-                               Target_i386* target,
-                               Output_section* output_section,
-                               size_t relnum,
-                               const elfcpp::Rel<32, false>& rel,
-                               unsigned int r_type,
-                               const Sized_symbol<32>* gsym,
-                               const Symbol_value<32>* psymval,
-                               unsigned char* view,
-                               elfcpp::Elf_types<32>::Elf_Addr address,
-                               section_size_type view_size)
+                                      Target_i386* target,
+                                      Output_section* output_section,
+                                      size_t relnum,
+                                      const elfcpp::Rel<32, false>& rel,
+                                      unsigned int r_type,
+                                      const Sized_symbol<32>* gsym,
+                                      const Symbol_value<32>* psymval,
+                                      unsigned char* view,
+                                      elfcpp::Elf_types<32>::Elf_Addr address,
+                                      section_size_type view_size)
 {
   if (this->skip_call_tls_get_addr_)
     {
       if ((r_type != elfcpp::R_386_PLT32
-           && r_type != elfcpp::R_386_PC32)
+          && r_type != elfcpp::R_386_PC32)
          || gsym == NULL
          || strcmp(gsym->name(), "___tls_get_addr") != 0)
        gold_error_at_location(relinfo, relnum, rel.get_r_offset(),
@@ -2508,18 +2697,18 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
     {
     case elfcpp::R_386_GOT32:
       if (gsym != NULL)
-        {
-          gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
-          got_offset = (gsym->got_offset(GOT_TYPE_STANDARD)
-                        - target->got_size());
-        }
+       {
+         gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+         got_offset = (gsym->got_offset(GOT_TYPE_STANDARD)
+                       - target->got_size());
+       }
       else
-        {
-          unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
-          gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
-          got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
-                        - target->got_size());
-        }
+       {
+         unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+         gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+         got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
+                       - target->got_size());
+       }
       have_got_offset = true;
       break;
 
@@ -2536,32 +2725,32 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
 
     case elfcpp::R_386_32:
       if (should_apply_static_reloc(gsym, r_type, true, output_section))
-        Relocate_functions<32, false>::rel32(view, object, psymval);
+       Relocate_functions<32, false>::rel32(view, object, psymval);
       break;
 
     case elfcpp::R_386_PC32:
       if (should_apply_static_reloc(gsym, r_type, true, output_section))
-        Relocate_functions<32, false>::pcrel32(view, object, psymval, address);
+       Relocate_functions<32, false>::pcrel32(view, object, psymval, address);
       break;
 
     case elfcpp::R_386_16:
       if (should_apply_static_reloc(gsym, r_type, false, output_section))
-        Relocate_functions<32, false>::rel16(view, object, psymval);
+       Relocate_functions<32, false>::rel16(view, object, psymval);
       break;
 
     case elfcpp::R_386_PC16:
       if (should_apply_static_reloc(gsym, r_type, false, output_section))
-        Relocate_functions<32, false>::pcrel16(view, object, psymval, address);
+       Relocate_functions<32, false>::pcrel16(view, object, psymval, address);
       break;
 
     case elfcpp::R_386_8:
       if (should_apply_static_reloc(gsym, r_type, false, output_section))
-        Relocate_functions<32, false>::rel8(view, object, psymval);
+       Relocate_functions<32, false>::rel8(view, object, psymval);
       break;
 
     case elfcpp::R_386_PC8:
       if (should_apply_static_reloc(gsym, r_type, false, output_section))
-        Relocate_functions<32, false>::pcrel8(view, object, psymval, address);
+       Relocate_functions<32, false>::pcrel8(view, object, psymval, address);
       break;
 
     case elfcpp::R_386_PLT32:
@@ -2626,7 +2815,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
     case elfcpp::R_386_TLS_LE:             // Local-exec
     case elfcpp::R_386_TLS_LE_32:
       this->relocate_tls(relinfo, target, relnum, rel, r_type, gsym, psymval,
-                         view, address, view_size);
+                        view, address, view_size);
       break;
 
     case elfcpp::R_386_32PLT:
@@ -2653,7 +2842,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
 
 inline void
 Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
-                                    Target_i386* target,
+                                   Target_i386* target,
                                    size_t relnum,
                                    const elfcpp::Rel<32, false>& rel,
                                    unsigned int r_type,
@@ -2691,37 +2880,37 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
          break;
        }
       else
-        {
-          unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
-                                   ? GOT_TYPE_TLS_NOFFSET
-                                   : GOT_TYPE_TLS_PAIR);
-          unsigned int got_offset;
-          if (gsym != NULL)
-            {
-              gold_assert(gsym->has_got_offset(got_type));
-              got_offset = gsym->got_offset(got_type) - target->got_size();
-            }
-          else
-            {
-              unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
-              gold_assert(object->local_has_got_offset(r_sym, got_type));
-              got_offset = (object->local_got_offset(r_sym, got_type)
+       {
+         unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
+                                  ? GOT_TYPE_TLS_NOFFSET
+                                  : GOT_TYPE_TLS_PAIR);
+         unsigned int got_offset;
+         if (gsym != NULL)
+           {
+             gold_assert(gsym->has_got_offset(got_type));
+             got_offset = gsym->got_offset(got_type) - target->got_size();
+           }
+         else
+           {
+             unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+             gold_assert(object->local_has_got_offset(r_sym, got_type));
+             got_offset = (object->local_got_offset(r_sym, got_type)
                            - target->got_size());
-            }
-          if (optimized_type == tls::TLSOPT_TO_IE)
+           }
+         if (optimized_type == tls::TLSOPT_TO_IE)
            {
              this->tls_gd_to_ie(relinfo, relnum, tls_segment, rel, r_type,
-                                 got_offset, view, view_size);
-              break;
+                                got_offset, view, view_size);
+             break;
+           }
+         else if (optimized_type == tls::TLSOPT_NONE)
+           {
+             // Relocate the field with the offset of the pair of GOT
+             // entries.
+             Relocate_functions<32, false>::rel32(view, got_offset);
+             break;
            }
-          else if (optimized_type == tls::TLSOPT_NONE)
-            {
-              // Relocate the field with the offset of the pair of GOT
-              // entries.
-              Relocate_functions<32, false>::rel32(view, got_offset);
-              break;
-            }
-        }
+       }
       gold_error_at_location(relinfo, relnum, rel.get_r_offset(),
                             _("unsupported reloc %u"),
                             r_type);
@@ -2731,7 +2920,7 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
     case elfcpp::R_386_TLS_DESC_CALL:
       this->local_dynamic_type_ = LOCAL_DYNAMIC_GNU;
       if (optimized_type == tls::TLSOPT_TO_LE)
-        {
+       {
          if (tls_segment == NULL)
            {
              gold_assert(parameters->errors()->error_count() > 0
@@ -2739,16 +2928,16 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
              return;
            }
          this->tls_desc_gd_to_le(relinfo, relnum, tls_segment,
-                                 rel, r_type, value, view,
-                                 view_size);
+                                 rel, r_type, value, view,
+                                 view_size);
          break;
-        }
+       }
       else
-        {
-          unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
-                                   ? GOT_TYPE_TLS_NOFFSET
-                                   : GOT_TYPE_TLS_DESC);
-          unsigned int got_offset = 0;
+       {
+         unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
+                                  ? GOT_TYPE_TLS_NOFFSET
+                                  : GOT_TYPE_TLS_DESC);
+         unsigned int got_offset = 0;
          if (r_type == elfcpp::R_386_TLS_GOTDESC
              && optimized_type == tls::TLSOPT_NONE)
            {
@@ -2758,19 +2947,19 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
              got_offset = (target->got_size()
                            + target->got_plt_section()->data_size());
            }
-          if (gsym != NULL)
-            {
-              gold_assert(gsym->has_got_offset(got_type));
-              got_offset += gsym->got_offset(got_type) - target->got_size();
-            }
-          else
-            {
-              unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
-              gold_assert(object->local_has_got_offset(r_sym, got_type));
-              got_offset += (object->local_got_offset(r_sym, got_type)
+         if (gsym != NULL)
+           {
+             gold_assert(gsym->has_got_offset(got_type));
+             got_offset += gsym->got_offset(got_type) - target->got_size();
+           }
+         else
+           {
+             unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+             gold_assert(object->local_has_got_offset(r_sym, got_type));
+             got_offset += (object->local_got_offset(r_sym, got_type)
                             - target->got_size());
-            }
-          if (optimized_type == tls::TLSOPT_TO_IE)
+           }
+         if (optimized_type == tls::TLSOPT_TO_IE)
            {
              if (tls_segment == NULL)
                {
@@ -2779,20 +2968,20 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
                  return;
                }
              this->tls_desc_gd_to_ie(relinfo, relnum, tls_segment, rel, r_type,
-                                      got_offset, view, view_size);
-              break;
+                                     got_offset, view, view_size);
+             break;
+           }
+         else if (optimized_type == tls::TLSOPT_NONE)
+           {
+             if (r_type == elfcpp::R_386_TLS_GOTDESC)
+               {
+                 // Relocate the field with the offset of the pair of GOT
+                 // entries.
+                 Relocate_functions<32, false>::rel32(view, got_offset);
+               }
+             break;
            }
-          else if (optimized_type == tls::TLSOPT_NONE)
-            {
-              if (r_type == elfcpp::R_386_TLS_GOTDESC)
-                {
-                  // Relocate the field with the offset of the pair of GOT
-                  // entries.
-                  Relocate_functions<32, false>::rel32(view, got_offset);
-                }
-              break;
-            }
-        }
+       }
       gold_error_at_location(relinfo, relnum, rel.get_r_offset(),
                             _("unsupported reloc %u"),
                             r_type);
@@ -2820,15 +3009,15 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
          break;
        }
       else if (optimized_type == tls::TLSOPT_NONE)
-        {
-          // Relocate the field with the offset of the GOT entry for
-          // the module index.
-          unsigned int got_offset;
-          got_offset = (target->got_mod_index_entry(NULL, NULL, NULL)
+       {
+         // Relocate the field with the offset of the GOT entry for
+         // the module index.
+         unsigned int got_offset;
+         got_offset = (target->got_mod_index_entry(NULL, NULL, NULL)
                        - target->got_size());
-          Relocate_functions<32, false>::rel32(view, got_offset);
-          break;
-        }
+         Relocate_functions<32, false>::rel32(view, got_offset);
+         break;
+       }
       gold_error_at_location(relinfo, relnum, rel.get_r_offset(),
                             _("unsupported reloc %u"),
                             r_type);
@@ -2874,33 +3063,33 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
          break;
        }
       else if (optimized_type == tls::TLSOPT_NONE)
-        {
-          // Relocate the field with the offset of the GOT entry for
-          // the tp-relative offset of the symbol.
+       {
+         // Relocate the field with the offset of the GOT entry for
+         // the tp-relative offset of the symbol.
          unsigned int got_type = (r_type == elfcpp::R_386_TLS_IE_32
-                                  ? GOT_TYPE_TLS_OFFSET
-                                  : GOT_TYPE_TLS_NOFFSET);
-          unsigned int got_offset;
-          if (gsym != NULL)
-            {
-              gold_assert(gsym->has_got_offset(got_type));
-              got_offset = gsym->got_offset(got_type);
-            }
-          else
-            {
-              unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
-              gold_assert(object->local_has_got_offset(r_sym, got_type));
-              got_offset = object->local_got_offset(r_sym, got_type);
-            }
-          // For the R_386_TLS_IE relocation, we need to apply the
-          // absolute address of the GOT entry.
-          if (r_type == elfcpp::R_386_TLS_IE)
-            got_offset += target->got_plt_section()->address();
-          // All GOT offsets are relative to the end of the GOT.
-          got_offset -= target->got_size();
-          Relocate_functions<32, false>::rel32(view, got_offset);
-          break;
-        }
+                                  ? GOT_TYPE_TLS_OFFSET
+                                  : GOT_TYPE_TLS_NOFFSET);
+         unsigned int got_offset;
+         if (gsym != NULL)
+           {
+             gold_assert(gsym->has_got_offset(got_type));
+             got_offset = gsym->got_offset(got_type);
+           }
+         else
+           {
+             unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+             gold_assert(object->local_has_got_offset(r_sym, got_type));
+             got_offset = object->local_got_offset(r_sym, got_type);
+           }
+         // For the R_386_TLS_IE relocation, we need to apply the
+         // absolute address of the GOT entry.
+         if (r_type == elfcpp::R_386_TLS_IE)
+           got_offset += target->got_plt_section()->address();
+         // All GOT offsets are relative to the end of the GOT.
+         got_offset -= target->got_size();
+         Relocate_functions<32, false>::rel32(view, got_offset);
+         break;
+       }
       gold_error_at_location(relinfo, relnum, rel.get_r_offset(),
                             _("unsupported reloc %u"),
                             r_type);
@@ -2910,32 +3099,32 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
       // If we're creating a shared library, a dynamic relocation will
       // have been created for this location, so do not apply it now.
       if (!parameters->options().shared())
-        {
+       {
          if (tls_segment == NULL)
            {
              gold_assert(parameters->errors()->error_count() > 0
                          || issue_undefined_symbol_error(gsym));
              return;
            }
-          value -= tls_segment->memsz();
-          Relocate_functions<32, false>::rel32(view, value);
-        }
+         value -= tls_segment->memsz();
+         Relocate_functions<32, false>::rel32(view, value);
+       }
       break;
 
     case elfcpp::R_386_TLS_LE_32:
       // If we're creating a shared library, a dynamic relocation will
       // have been created for this location, so do not apply it now.
       if (!parameters->options().shared())
-        {
+       {
          if (tls_segment == NULL)
            {
              gold_assert(parameters->errors()->error_count() > 0
                          || issue_undefined_symbol_error(gsym));
              return;
            }
-          value = tls_segment->memsz() - value;
-          Relocate_functions<32, false>::rel32(view, value);
-        }
+         value = tls_segment->memsz() - value;
+         Relocate_functions<32, false>::rel32(view, value);
+       }
       break;
     }
 }
@@ -2965,7 +3154,7 @@ Target_i386::Relocate::tls_gd_to_le(const Relocate_info<32, false>* relinfo,
   unsigned char op2 = view[-2];
 
   tls::check_tls(relinfo, relnum, rel.get_r_offset(),
-                 op2 == 0x8d || op2 == 0x04);
+                op2 == 0x8d || op2 == 0x04);
   tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[4] == 0xe8);
 
   int roff = 5;
@@ -2975,15 +3164,15 @@ Target_i386::Relocate::tls_gd_to_le(const Relocate_info<32, false>* relinfo,
       tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -3);
       tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[-3] == 0x8d);
       tls::check_tls(relinfo, relnum, rel.get_r_offset(),
-                     ((op1 & 0xc7) == 0x05 && op1 != (4 << 3)));
+                    ((op1 & 0xc7) == 0x05 && op1 != (4 << 3)));
       memcpy(view - 3, "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12);
     }
   else
     {
       tls::check_tls(relinfo, relnum, rel.get_r_offset(),
-                     (op1 & 0xf8) == 0x80 && (op1 & 7) != 4);
+                    (op1 & 0xf8) == 0x80 && (op1 & 7) != 4);
       if (rel.get_r_offset() + 9 < view_size
-          && view[9] == 0x90)
+         && view[9] == 0x90)
        {
          // There is a trailing nop.  Use the size byte subl.
          memcpy(view - 2, "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12);
@@ -3027,7 +3216,7 @@ Target_i386::Relocate::tls_gd_to_ie(const Relocate_info<32, false>* relinfo,
   unsigned char op2 = view[-2];
 
   tls::check_tls(relinfo, relnum, rel.get_r_offset(),
-                 op2 == 0x8d || op2 == 0x04);
+                op2 == 0x8d || op2 == 0x04);
   tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[4] == 0xe8);
 
   int roff = 5;
@@ -3040,24 +3229,24 @@ Target_i386::Relocate::tls_gd_to_ie(const Relocate_info<32, false>* relinfo,
       tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -3);
       tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[-3] == 0x8d);
       tls::check_tls(relinfo, relnum, rel.get_r_offset(),
-                     ((op1 & 0xc7) == 0x05 && op1 != (4 << 3)));
+                    ((op1 & 0xc7) == 0x05 && op1 != (4 << 3)));
       memcpy(view - 3, "\x65\xa1\0\0\0\0\x03\x83\0\0\0", 12);
     }
   else
     {
       tls::check_tls(relinfo, relnum, rel.get_r_offset(),
-                     (op1 & 0xf8) == 0x80 && (op1 & 7) != 4);
+                    (op1 & 0xf8) == 0x80 && (op1 & 7) != 4);
       if (rel.get_r_offset() + 9 < view_size
-          && view[9] == 0x90)
+         && view[9] == 0x90)
        {
-          // FIXME: This is not the right instruction sequence.
+         // FIXME: This is not the right instruction sequence.
          // There is a trailing nop.  Use the size byte subl.
          memcpy(view - 2, "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12);
          roff = 6;
        }
       else
        {
-          // FIXME: This is not the right instruction sequence.
+         // FIXME: This is not the right instruction sequence.
          // Use the five byte subl.
          memcpy(view - 2, "\x65\xa1\0\0\0\0\x2d\0\0\0", 11);
        }
@@ -3091,7 +3280,7 @@ Target_i386::Relocate::tls_desc_gd_to_le(
       tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2);
       tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 4);
       tls::check_tls(relinfo, relnum, rel.get_r_offset(),
-                     view[-2] == 0x8d && view[-1] == 0x83);
+                    view[-2] == 0x8d && view[-1] == 0x83);
       view[-1] = 0x05;
       value -= tls_segment->memsz();
       Relocate_functions<32, false>::rel32(view, value);
@@ -3103,7 +3292,7 @@ Target_i386::Relocate::tls_desc_gd_to_le(
       gold_assert(r_type == elfcpp::R_386_TLS_DESC_CALL);
       tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 2);
       tls::check_tls(relinfo, relnum, rel.get_r_offset(),
-                     view[0] == 0xff && view[1] == 0x10);
+                    view[0] == 0xff && view[1] == 0x10);
       view[0] = 0x66;
       view[1] = 0x90;
     }
@@ -3130,7 +3319,7 @@ Target_i386::Relocate::tls_desc_gd_to_ie(
       tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2);
       tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 4);
       tls::check_tls(relinfo, relnum, rel.get_r_offset(),
-                     view[-2] == 0x8d && view[-1] == 0x83);
+                    view[-2] == 0x8d && view[-1] == 0x83);
       view[-2] = 0x8b;
       Relocate_functions<32, false>::rel32(view, value);
     }
@@ -3141,7 +3330,7 @@ Target_i386::Relocate::tls_desc_gd_to_ie(
       gold_assert(r_type == elfcpp::R_386_TLS_DESC_CALL);
       tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 2);
       tls::check_tls(relinfo, relnum, rel.get_r_offset(),
-                     view[0] == 0xff && view[1] == 0x10);
+                    view[0] == 0xff && view[1] == 0x10);
       view[0] = 0x66;
       view[1] = 0x90;
     }
@@ -3168,7 +3357,7 @@ Target_i386::Relocate::tls_ld_to_le(const Relocate_info<32, false>* relinfo,
 
   // FIXME: Does this test really always pass?
   tls::check_tls(relinfo, relnum, rel.get_r_offset(),
-                 view[-2] == 0x8d && view[-1] == 0x83);
+                view[-2] == 0x8d && view[-1] == 0x83);
 
   tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[4] == 0xe8);
 
@@ -3218,7 +3407,7 @@ Target_i386::Relocate::tls_ie_to_le(const Relocate_info<32, false>* relinfo,
            {
              // movl XX,%reg  ==>  movl $YY,%reg
              tls::check_tls(relinfo, relnum, rel.get_r_offset(),
-                             (op1 & 0xc7) == 0x05);
+                            (op1 & 0xc7) == 0x05);
              view[-2] = 0xc7;
              view[-1] = 0xc0 | ((op1 >> 3) & 7);
            }
@@ -3226,7 +3415,7 @@ Target_i386::Relocate::tls_ie_to_le(const Relocate_info<32, false>* relinfo,
            {
              // addl XX,%reg  ==>  addl $YY,%reg
              tls::check_tls(relinfo, relnum, rel.get_r_offset(),
-                             (op1 & 0xc7) == 0x05);
+                            (op1 & 0xc7) == 0x05);
              view[-2] = 0x81;
              view[-1] = 0xc0 | ((op1 >> 3) & 7);
            }
@@ -3245,7 +3434,7 @@ Target_i386::Relocate::tls_ie_to_le(const Relocate_info<32, false>* relinfo,
       unsigned char op1 = view[-1];
       unsigned char op2 = view[-2];
       tls::check_tls(relinfo, relnum, rel.get_r_offset(),
-                     (op1 & 0xc0) == 0x80 && (op1 & 7) != 4);
+                    (op1 & 0xc0) == 0x80 && (op1 & 7) != 4);
       if (op2 == 0x8b)
        {
          // movl %gs:XX(%reg1),%reg2  ==>  movl $YY,%reg2
@@ -3471,7 +3660,7 @@ Target_i386::do_code_fill(section_size_type length) const
       jmp[0] = 0xe9;
       elfcpp::Swap_unaligned<32, false>::writeval(jmp + 1, length - 5);
       return (std::string(reinterpret_cast<char*>(&jmp[0]), 5)
-              + std::string(length - 5, static_cast<char>(0x90)));
+             + std::string(length - 5, static_cast<char>(0x90)));
     }
 
   // Nop sequences of various lengths.
@@ -3481,45 +3670,45 @@ Target_i386::do_code_fill(section_size_type length) const
   const char nop4[4] = { '\x8d', '\x74', '\x26',     // leal 0(%esi,1),%esi
                         '\x00'};
   const char nop5[5] = { '\x90', '\x8d', '\x74',     // nop
-                        '\x26', '\x00' };           // leal 0(%esi,1),%esi
+                        '\x26', '\x00' };           // leal 0(%esi,1),%esi
   const char nop6[6] = { '\x8d', '\xb6', '\x00',     // leal 0L(%esi),%esi
-                        '\x00', '\x00', '\x00' };
+                        '\x00', '\x00', '\x00' };
   const char nop7[7] = { '\x8d', '\xb4', '\x26',     // leal 0L(%esi,1),%esi
-                        '\x00', '\x00', '\x00',
+                        '\x00', '\x00', '\x00',
                         '\x00' };
   const char nop8[8] = { '\x90', '\x8d', '\xb4',     // nop
-                        '\x26', '\x00', '\x00',     // leal 0L(%esi,1),%esi
+                        '\x26', '\x00', '\x00',     // leal 0L(%esi,1),%esi
                         '\x00', '\x00' };
   const char nop9[9] = { '\x89', '\xf6', '\x8d',     // movl %esi,%esi
-                        '\xbc', '\x27', '\x00',     // leal 0L(%edi,1),%edi
+                        '\xbc', '\x27', '\x00',     // leal 0L(%edi,1),%edi
                         '\x00', '\x00', '\x00' };
   const char nop10[10] = { '\x8d', '\x76', '\x00',   // leal 0(%esi),%esi
-                          '\x8d', '\xbc', '\x27',   // leal 0L(%edi,1),%edi
+                          '\x8d', '\xbc', '\x27',   // leal 0L(%edi,1),%edi
                           '\x00', '\x00', '\x00',
                           '\x00' };
   const char nop11[11] = { '\x8d', '\x74', '\x26',   // leal 0(%esi,1),%esi
-                          '\x00', '\x8d', '\xbc',   // leal 0L(%edi,1),%edi
+                          '\x00', '\x8d', '\xbc',   // leal 0L(%edi,1),%edi
                           '\x27', '\x00', '\x00',
                           '\x00', '\x00' };
   const char nop12[12] = { '\x8d', '\xb6', '\x00',   // leal 0L(%esi),%esi
-                          '\x00', '\x00', '\x00',   // leal 0L(%edi),%edi
+                          '\x00', '\x00', '\x00',   // leal 0L(%edi),%edi
                           '\x8d', '\xbf', '\x00',
                           '\x00', '\x00', '\x00' };
   const char nop13[13] = { '\x8d', '\xb6', '\x00',   // leal 0L(%esi),%esi
-                          '\x00', '\x00', '\x00',   // leal 0L(%edi,1),%edi
+                          '\x00', '\x00', '\x00',   // leal 0L(%edi,1),%edi
                           '\x8d', '\xbc', '\x27',
                           '\x00', '\x00', '\x00',
-                           '\x00' };
+                          '\x00' };
   const char nop14[14] = { '\x8d', '\xb4', '\x26',   // leal 0L(%esi,1),%esi
-                          '\x00', '\x00', '\x00',   // leal 0L(%edi,1),%edi
+                          '\x00', '\x00', '\x00',   // leal 0L(%edi,1),%edi
                           '\x00', '\x8d', '\xbc',
                           '\x27', '\x00', '\x00',
-                           '\x00', '\x00' };
+                          '\x00', '\x00' };
   const char nop15[15] = { '\xeb', '\x0d', '\x90',   // jmp .+15
-                          '\x90', '\x90', '\x90',   // nop,nop,nop,...
+                          '\x90', '\x90', '\x90',   // nop,nop,nop,...
                           '\x90', '\x90', '\x90',
                           '\x90', '\x90', '\x90',
-                           '\x90', '\x90', '\x90' };
+                          '\x90', '\x90', '\x90' };
 
   const char* nops[16] = {
     NULL,
@@ -3563,12 +3752,12 @@ Target_i386::do_is_call_to_non_split(const Symbol* sym, unsigned int) const
 
 void
 Target_i386::do_calls_non_split(Relobj* object, unsigned int shndx,
-                               section_offset_type fnoffset,
-                               section_size_type fnsize,
-                               unsigned char* view,
-                               section_size_type view_size,
-                               std::string* from,
-                               std::string* to) const
+                                      section_offset_type fnoffset,
+                                      section_size_type fnsize,
+                                      unsigned char* view,
+                                      section_size_type view_size,
+                                      std::string* from,
+                                      std::string* to) const
 {
   // The function starts with a comparison of the stack pointer and a
   // field in the TCB.  This is followed by a jump.
@@ -3615,7 +3804,8 @@ Target_i386::do_calls_non_split(Relobj* object, unsigned int shndx,
   *to = "__morestack_non_split";
 }
 
-// The selector for i386 object files.
+// The selector for i386 object files.  Note this is never instantiated
+// directly.  It's only used in Target_selector_i386_nacl, below.
 
 class Target_selector_i386 : public Target_selector_freebsd
 {
@@ -3631,6 +3821,327 @@ public:
   { return new Target_i386(); }
 };
 
-Target_selector_i386 target_selector_i386;
+// NaCl variant.  It uses different PLT contents.
+
+class Output_data_plt_i386_nacl : public Output_data_plt_i386
+{
+ public:
+  Output_data_plt_i386_nacl(Layout* layout,
+                           Output_data_space* got_plt,
+                           Output_data_space* got_irelative)
+    : Output_data_plt_i386(layout, plt_entry_size, got_plt, got_irelative)
+  { }
+
+ protected:
+  virtual unsigned int
+  do_get_plt_entry_size() const
+  { return plt_entry_size; }
+
+  virtual void
+  do_add_eh_frame(Layout* layout)
+  {
+    layout->add_eh_frame_for_plt(this, plt_eh_frame_cie, plt_eh_frame_cie_size,
+                                plt_eh_frame_fde, plt_eh_frame_fde_size);
+  }
+
+  // The size of an entry in the PLT.
+  static const int plt_entry_size = 64;
+
+  // The .eh_frame unwind information for the PLT.
+  static const int plt_eh_frame_fde_size = 32;
+  static const unsigned char plt_eh_frame_fde[plt_eh_frame_fde_size];
+};
+
+class Output_data_plt_i386_nacl_exec : public Output_data_plt_i386_nacl
+{
+public:
+  Output_data_plt_i386_nacl_exec(Layout* layout,
+                                Output_data_space* got_plt,
+                                Output_data_space* got_irelative)
+    : Output_data_plt_i386_nacl(layout, got_plt, got_irelative)
+  { }
+
+ protected:
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov,
+                         elfcpp::Elf_types<32>::Elf_Addr got_address);
+
+  virtual unsigned int
+  do_fill_plt_entry(unsigned char* pov,
+                   elfcpp::Elf_types<32>::Elf_Addr got_address,
+                   unsigned int got_offset,
+                   unsigned int plt_offset,
+                   unsigned int plt_rel_offset);
+
+ private:
+  // The first entry in the PLT for an executable.
+  static const unsigned char first_plt_entry[plt_entry_size];
+
+  // Other entries in the PLT for an executable.
+  static const unsigned char plt_entry[plt_entry_size];
+};
+
+class Output_data_plt_i386_nacl_dyn : public Output_data_plt_i386_nacl
+{
+ public:
+  Output_data_plt_i386_nacl_dyn(Layout* layout,
+                               Output_data_space* got_plt,
+                               Output_data_space* got_irelative)
+    : Output_data_plt_i386_nacl(layout, got_plt, got_irelative)
+  { }
+
+ protected:
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov, elfcpp::Elf_types<32>::Elf_Addr);
+
+  virtual unsigned int
+  do_fill_plt_entry(unsigned char* pov,
+                   elfcpp::Elf_types<32>::Elf_Addr,
+                   unsigned int got_offset,
+                   unsigned int plt_offset,
+                   unsigned int plt_rel_offset);
+
+ private:
+  // The first entry in the PLT for a shared object.
+  static const unsigned char first_plt_entry[plt_entry_size];
+
+  // Other entries in the PLT for a shared object.
+  static const unsigned char plt_entry[plt_entry_size];
+};
+
+class Target_i386_nacl : public Target_i386
+{
+ public:
+  Target_i386_nacl()
+    : Target_i386(&i386_nacl_info)
+  { }
+
+ protected:
+  virtual Output_data_plt_i386*
+  do_make_data_plt(Layout* layout,
+                  Output_data_space* got_plt,
+                  Output_data_space* got_irelative,
+                  bool dyn)
+  {
+    if (dyn)
+      return new Output_data_plt_i386_nacl_dyn(layout, got_plt, got_irelative);
+    else
+      return new Output_data_plt_i386_nacl_exec(layout, got_plt, got_irelative);
+  }
+
+ private:
+  static const Target::Target_info i386_nacl_info;
+};
+
+const Target::Target_info Target_i386_nacl::i386_nacl_info =
+{
+  32,                  // size
+  false,               // is_big_endian
+  elfcpp::EM_386,      // machine_code
+  false,               // has_make_symbol
+  false,               // has_resolve
+  true,                        // has_code_fill
+  true,                        // is_default_stack_executable
+  true,                        // can_icf_inline_merge_sections
+  '\0',                        // wrap_char
+  "/lib/ld-nacl-x86-32.so.1", // dynamic_linker
+  0x20000,             // default_text_segment_address
+  0x10000,             // abi_pagesize (overridable by -z max-page-size)
+  0x10000,             // common_pagesize (overridable by -z common-page-size)
+  true,                 // isolate_execinstr
+  0x10000000,           // rosegment_gap
+  elfcpp::SHN_UNDEF,   // small_common_shndx
+  elfcpp::SHN_UNDEF,   // large_common_shndx
+  0,                   // small_common_section_flags
+  0,                   // large_common_section_flags
+  NULL,                        // attributes_section
+  NULL                 // attributes_vendor
+};
+
+#define        NACLMASK        0xe0            // 32-byte alignment mask
+
+const unsigned char
+Output_data_plt_i386_nacl_exec::first_plt_entry[plt_entry_size] =
+{
+  0xff, 0x35,                          // pushl contents of memory address
+  0, 0, 0, 0,                          // replaced with address of .got + 4
+  0x8b, 0x0d,                          // movl contents of address, %ecx
+  0, 0, 0, 0,                          // replaced with address of .got + 8
+  0x83, 0xe1, NACLMASK,                // andl $NACLMASK, %ecx
+  0xff, 0xe1,                          // jmp *%ecx
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90
+};
+
+void
+Output_data_plt_i386_nacl_exec::do_fill_first_plt_entry(
+    unsigned char* pov,
+    elfcpp::Elf_types<32>::Elf_Addr got_address)
+{
+  memcpy(pov, first_plt_entry, plt_entry_size);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_address + 4);
+  elfcpp::Swap<32, false>::writeval(pov + 8, got_address + 8);
+}
+
+// The first entry in the PLT for a shared object.
+
+const unsigned char
+Output_data_plt_i386_nacl_dyn::first_plt_entry[plt_entry_size] =
+{
+  0xff, 0xb3, 4, 0, 0, 0,      // pushl 4(%ebx)
+  0x8b, 0x4b, 0x08,            // mov 0x8(%ebx), %ecx
+  0x83, 0xe1, NACLMASK,         // andl $NACLMASK, %ecx
+  0xff, 0xe1,                   // jmp *%ecx
+  0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90,  // nops
+  0x90, 0x90, 0x90, 0x90, 0x90   // nops
+};
+
+void
+Output_data_plt_i386_nacl_dyn::do_fill_first_plt_entry(
+    unsigned char* pov,
+    elfcpp::Elf_types<32>::Elf_Addr)
+{
+  memcpy(pov, first_plt_entry, plt_entry_size);
+}
+
+// Subsequent entries in the PLT for an executable.
+
+const unsigned char
+Output_data_plt_i386_nacl_exec::plt_entry[plt_entry_size] =
+{
+  0x8b, 0x0d,                    // movl contents of address, %ecx */
+  0, 0, 0, 0,                    // replaced with address of symbol in .got
+  0x83, 0xe1, NACLMASK,          // andl $NACLMASK, %ecx
+  0xff, 0xe1,                    // jmp *%ecx
+
+  // Pad to the next 32-byte boundary with nop instructions.
+  0x90,
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+
+  // Lazy GOT entries point here (32-byte aligned).
+  0x68,                       // pushl immediate
+  0, 0, 0, 0,                 // replaced with offset into relocation table
+  0xe9,                       // jmp relative
+  0, 0, 0, 0,                 // replaced with offset to start of .plt
+
+  // Pad to the next 32-byte boundary with nop instructions.
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+  0x90, 0x90
+};
+
+unsigned int
+Output_data_plt_i386_nacl_exec::do_fill_plt_entry(
+    unsigned char* pov,
+    elfcpp::Elf_types<32>::Elf_Addr got_address,
+    unsigned int got_offset,
+    unsigned int plt_offset,
+    unsigned int plt_rel_offset)
+{
+  memcpy(pov, plt_entry, plt_entry_size);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+                                             got_address + got_offset);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 33, plt_rel_offset);
+  elfcpp::Swap<32, false>::writeval(pov + 38, - (plt_offset + 38 + 4));
+  return 32;
+}
+
+// Subsequent entries in the PLT for a shared object.
+
+const unsigned char
+Output_data_plt_i386_nacl_dyn::plt_entry[plt_entry_size] =
+{
+  0x8b, 0x8b,          // movl offset(%ebx), %ecx
+  0, 0, 0, 0,          // replaced with offset of symbol in .got
+  0x83, 0xe1, 0xe0,    // andl $NACLMASK, %ecx
+  0xff, 0xe1,          // jmp *%ecx
+
+  // Pad to the next 32-byte boundary with nop instructions.
+  0x90,
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+
+  // Lazy GOT entries point here (32-byte aligned).
+  0x68,                // pushl immediate
+  0, 0, 0, 0,          // replaced with offset into relocation table.
+  0xe9,                // jmp relative
+  0, 0, 0, 0,          // replaced with offset to start of .plt.
+
+  // Pad to the next 32-byte boundary with nop instructions.
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+  0x90, 0x90
+};
+
+unsigned int
+Output_data_plt_i386_nacl_dyn::do_fill_plt_entry(
+    unsigned char* pov,
+    elfcpp::Elf_types<32>::Elf_Addr,
+    unsigned int got_offset,
+    unsigned int plt_offset,
+    unsigned int plt_rel_offset)
+{
+  memcpy(pov, plt_entry, plt_entry_size);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_offset);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 33, plt_rel_offset);
+  elfcpp::Swap<32, false>::writeval(pov + 38, - (plt_offset + 38 + 4));
+  return 32;
+}
+
+const unsigned char
+Output_data_plt_i386_nacl::plt_eh_frame_fde[plt_eh_frame_fde_size] =
+{
+  0, 0, 0, 0,                          // Replaced with offset to .plt.
+  0, 0, 0, 0,                          // Replaced with size of .plt.
+  0,                                   // Augmentation size.
+  elfcpp::DW_CFA_def_cfa_offset, 8,    // DW_CFA_def_cfa_offset: 8.
+  elfcpp::DW_CFA_advance_loc + 6,      // Advance 6 to __PLT__ + 6.
+  elfcpp::DW_CFA_def_cfa_offset, 12,   // DW_CFA_def_cfa_offset: 12.
+  elfcpp::DW_CFA_advance_loc + 58,     // Advance 58 to __PLT__ + 64.
+  elfcpp::DW_CFA_def_cfa_expression,   // DW_CFA_def_cfa_expression.
+  13,                                  // Block length.
+  elfcpp::DW_OP_breg4, 4,              // Push %esp + 4.
+  elfcpp::DW_OP_breg8, 0,              // Push %eip.
+  elfcpp::DW_OP_const1u, 63,            // Push 0x3f.
+  elfcpp::DW_OP_and,                   // & (%eip & 0x3f).
+  elfcpp::DW_OP_const1u, 37,            // Push 0x25.
+  elfcpp::DW_OP_ge,                    // >= ((%eip & 0x3f) >= 0x25)
+  elfcpp::DW_OP_lit2,                  // Push 2.
+  elfcpp::DW_OP_shl,                   // << (((%eip & 0x3f) >= 0x25) << 2)
+  elfcpp::DW_OP_plus,                  // + ((((%eip&0x3f)>=0x25)<<2)+%esp+4
+  elfcpp::DW_CFA_nop,                  // Align to 32 bytes.
+  elfcpp::DW_CFA_nop
+};
+
+// The selector for i386-nacl object files.
+
+class Target_selector_i386_nacl
+  : public Target_selector_nacl<Target_selector_i386, Target_i386_nacl>
+{
+ public:
+  Target_selector_i386_nacl()
+    : Target_selector_nacl<Target_selector_i386,
+                          Target_i386_nacl>("x86-32",
+                                            "elf32-i386-nacl",
+                                            "elf_i386_nacl")
+  { }
+};
+
+Target_selector_i386_nacl target_selector_i386;
 
 } // End anonymous namespace.
index 6436a35e2ee7ca7f6dc239f08f7ec26995242d66..9a61e774c26412a4b27d8b7480509d5e6da4947c 100644 (file)
@@ -1,6 +1,6 @@
 // inremental.cc -- incremental linking support for gold
 
-// Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
 // Written by Mikolaj Zalewski <mikolajz@google.com>.
 
 // This file is part of gold.
@@ -143,7 +143,7 @@ vexplain_no_incremental(const char* format, va_list args)
   if (vasprintf(&buf, format, args) < 0)
     gold_nomem();
   gold_info(_("the link might take longer: "
-              "cannot perform incremental link: %s"), buf);
+             "cannot perform incremental link: %s"), buf);
   free(buf);
 }
 
@@ -296,7 +296,7 @@ Sized_incremental_binary<size, big_endian>::setup_readers()
   unsigned int main_strtab_shndx =
       this->elf_file_.section_link(main_symtab_shndx);
   gold_assert(main_strtab_shndx != elfcpp::SHN_UNDEF
-              && main_strtab_shndx < this->elf_file_.shnum());
+             && main_strtab_shndx < this->elf_file_.shnum());
   this->main_strtab_loc_ = this->elf_file_.section_contents(main_strtab_shndx);
 
   // Walk the list of input files (a) to setup an Input_reader for each
@@ -322,7 +322,7 @@ Sized_incremental_binary<size, big_endian>::setup_readers()
        case INCREMENTAL_INPUT_ARCHIVE:
          {
            Incremental_library* lib =
-               new Incremental_library(input_file.filename(), i,
+               new Incremental_library(input_file.filename(), i,
                                        &this->input_entry_readers_[i]);
            this->library_map_[i] = lib;
            unsigned int member_count = input_file.get_member_count();
@@ -382,16 +382,16 @@ check_input_args(std::vector<const Input_argument*>& input_args_map,
          check_input_args(input_args_map, lib->begin(), lib->end());
        }
       else
-        {
-          gold_assert(p->is_file());
-          unsigned int arg_serial = p->file().arg_serial();
-          if (arg_serial > 0)
+       {
+         gold_assert(p->is_file());
+         unsigned int arg_serial = p->file().arg_serial();
+         if (arg_serial > 0)
            {
              gold_assert(arg_serial <= input_args_map.size());
              gold_assert(input_args_map[arg_serial - 1] == 0);
              input_args_map[arg_serial - 1] = &*p;
            }
-        }
+       }
     }
 }
 
@@ -421,11 +421,11 @@ Sized_incremental_binary<size, big_endian>::do_check_inputs(
   if (incremental_inputs->command_line() != inputs.command_line())
     {
       gold_debug(DEBUG_INCREMENTAL,
-                "old command line: %s",
-                inputs.command_line());
+                "old command line: %s",
+                inputs.command_line());
       gold_debug(DEBUG_INCREMENTAL,
-                "new command line: %s",
-                incremental_inputs->command_line().c_str());
+                "new command line: %s",
+                incremental_inputs->command_line().c_str());
       explain_no_incremental(_("command line changed"));
       return false;
     }
@@ -546,14 +546,14 @@ Sized_incremental_binary<size, big_endian>::do_init_layout(Layout* layout)
       Shdr shdr(pshdr);
       const char* name;
       if (!shstrtab.get_c_string(shdr.get_sh_name(), &name))
-        name = NULL;
+       name = NULL;
       gold_debug(DEBUG_INCREMENTAL,
                 "Output section: %2d %08lx %08lx %08lx %3d %s",
-                i,
-                static_cast<long>(shdr.get_sh_addr()),
-                static_cast<long>(shdr.get_sh_offset()),
-                static_cast<long>(shdr.get_sh_size()),
-                shdr.get_sh_type(), name ? name : "<null>");
+                i,
+                static_cast<long>(shdr.get_sh_addr()),
+                static_cast<long>(shdr.get_sh_offset()),
+                static_cast<long>(shdr.get_sh_size()),
+                shdr.get_sh_type(), name ? name : "<null>");
       this->section_map_[i] = layout->init_fixed_output_section(name, shdr);
       pshdr += shdr_size;
     }
@@ -583,7 +583,7 @@ Sized_incremental_binary<size, big_endian>::do_reserve_layout(
        {
          bool is_def;
          bool is_copy;
-          unsigned int output_symndx =
+         unsigned int output_symndx =
              input_file.get_output_symbol_index(i, &is_def, &is_copy);
          if (is_copy)
            {
@@ -592,7 +592,7 @@ Sized_incremental_binary<size, big_endian>::do_reserve_layout(
              elfcpp::Sym<size, big_endian> gsym(sym_p);
              unsigned int shndx = gsym.get_st_shndx();
              if (shndx < 1 || shndx >= this->section_map_.size())
-               continue;
+               continue;
              Output_section* os = this->section_map_[shndx];
              off_t offset = gsym.get_st_value() - os->address();
              os->reserve(offset, gsym.get_st_size());
@@ -610,9 +610,9 @@ Sized_incremental_binary<size, big_endian>::do_reserve_layout(
   for (unsigned int i = 0; i < shnum; i++)
     {
       typename Input_entry_reader::Input_section_info sect =
-          input_file.get_input_section(i);
+         input_file.get_input_section(i);
       if (sect.output_shndx == 0 || sect.sh_offset == -1)
-        continue;
+       continue;
       Output_section* os = this->section_map_[sect.output_shndx];
       gold_assert(os != NULL);
       os->reserve(sect.sh_offset, sect.sh_size);
@@ -781,7 +781,7 @@ Sized_incremental_binary<size, big_endian>::do_apply_incremental_relocs(
       // output file.
       unsigned int offset = isymtab.get_list_head(i);
       while (offset > 0)
-        {
+       {
          Incremental_global_symbol_reader<big_endian> sym_info =
              this->inputs_reader().global_symbol_reader_at_offset(offset);
          unsigned int r_base = sym_info.reloc_offset();
@@ -803,12 +803,12 @@ Sized_incremental_binary<size, big_endian>::do_apply_incremental_relocs(
                                                              view_size);
 
              gold_debug(DEBUG_INCREMENTAL,
-                        "  %08lx: %s + %d: type %d addend %ld",
-                        (long)(section_offset + r_offset),
-                        os->name(),
-                        (int)r_offset,
-                        r_type,
-                        (long)r_addend);
+                        "  %08lx: %s + %d: type %d addend %ld",
+                        (long)(section_offset + r_offset),
+                        os->name(),
+                        (int)r_offset,
+                        r_type,
+                        (long)r_addend);
 
              target->apply_relocation(&relinfo, r_offset, r_type, r_addend,
                                       gsym, view, address, view_size);
@@ -818,7 +818,7 @@ Sized_incremental_binary<size, big_endian>::do_apply_incremental_relocs(
              of->write_output_view(section_offset, view_size, view);
            }
          offset = sym_info.next_offset();
-        }
+       }
     }
 }
 
@@ -848,15 +848,16 @@ namespace
 template<int size, bool big_endian>
 Incremental_binary*
 make_sized_incremental_binary(Output_file* file,
-                              const elfcpp::Ehdr<size, big_endian>& ehdr)
+                             const elfcpp::Ehdr<size, big_endian>& ehdr)
 {
-  Target* target = select_target(ehdr.get_e_machine(), size, big_endian,
-                                 ehdr.get_e_ident()[elfcpp::EI_OSABI],
-                                 ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]);
+  Target* target = select_target(NULL, 0, // XXX
+                                ehdr.get_e_machine(), size, big_endian,
+                                ehdr.get_e_ident()[elfcpp::EI_OSABI],
+                                ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]);
   if (target == NULL)
     {
       explain_no_incremental(_("unsupported ELF machine number %d"),
-               ehdr.get_e_machine());
+              ehdr.get_e_machine());
       return NULL;
     }
 
@@ -893,7 +894,7 @@ open_incremental_binary(Output_file* file)
   bool big_endian = false;
   std::string error;
   if (!elfcpp::Elf_recognizer::is_valid_header(p, want, &size, &big_endian,
-                                               &error))
+                                              &error))
     {
       explain_no_incremental(error.c_str());
       return NULL;
@@ -903,44 +904,44 @@ open_incremental_binary(Output_file* file)
   if (size == 32)
     {
       if (big_endian)
-        {
+       {
 #ifdef HAVE_TARGET_32_BIG
-          result = make_sized_incremental_binary<32, true>(
-              file, elfcpp::Ehdr<32, true>(p));
+         result = make_sized_incremental_binary<32, true>(
+             file, elfcpp::Ehdr<32, true>(p));
 #else
-          explain_no_incremental(_("unsupported file: 32-bit, big-endian"));
+         explain_no_incremental(_("unsupported file: 32-bit, big-endian"));
 #endif
-        }
+       }
       else
-        {
+       {
 #ifdef HAVE_TARGET_32_LITTLE
-          result = make_sized_incremental_binary<32, false>(
-              file, elfcpp::Ehdr<32, false>(p));
+         result = make_sized_incremental_binary<32, false>(
+             file, elfcpp::Ehdr<32, false>(p));
 #else
-          explain_no_incremental(_("unsupported file: 32-bit, little-endian"));
+         explain_no_incremental(_("unsupported file: 32-bit, little-endian"));
 #endif
-        }
+       }
     }
   else if (size == 64)
     {
       if (big_endian)
-        {
+       {
 #ifdef HAVE_TARGET_64_BIG
-          result = make_sized_incremental_binary<64, true>(
-              file, elfcpp::Ehdr<64, true>(p));
+         result = make_sized_incremental_binary<64, true>(
+             file, elfcpp::Ehdr<64, true>(p));
 #else
-          explain_no_incremental(_("unsupported file: 64-bit, big-endian"));
+         explain_no_incremental(_("unsupported file: 64-bit, big-endian"));
 #endif
-        }
+       }
       else
-        {
+       {
 #ifdef HAVE_TARGET_64_LITTLE
-          result = make_sized_incremental_binary<64, false>(
-              file, elfcpp::Ehdr<64, false>(p));
+         result = make_sized_incremental_binary<64, false>(
+             file, elfcpp::Ehdr<64, false>(p));
 #else
-          explain_no_incremental(_("unsupported file: 64-bit, little-endian"));
+         explain_no_incremental(_("unsupported file: 64-bit, little-endian"));
 #endif
-        }
+       }
     }
   else
     gold_unreachable();
@@ -975,7 +976,7 @@ Incremental_inputs::report_command_line(int argc, const char* const* argv)
          || is_prefix_of("--incremental-base=", argv[i])
          || is_prefix_of("--incremental-patch=", argv[i])
          || is_prefix_of("--debug=", argv[i]))
-        continue;
+       continue;
       if (strcmp(argv[i], "--incremental-base") == 0
          || strcmp(argv[i], "--incremental-patch") == 0
          || strcmp(argv[i], "--debug") == 0)
@@ -990,20 +991,20 @@ Incremental_inputs::report_command_line(int argc, const char* const* argv)
       // Now append argv[i], but with all single-quotes escaped
       const char* argpos = argv[i];
       while (1)
-        {
-          const int len = strcspn(argpos, "'");
-          args.append(argpos, len);
-          if (argpos[len] == '\0')
-            break;
-          args.append("'\"'\"'");
-          argpos += len + 1;
-        }
+       {
+         const int len = strcspn(argpos, "'");
+         args.append(argpos, len);
+         if (argpos[len] == '\0')
+           break;
+         args.append("'\"'\"'");
+         argpos += len + 1;
+       }
       args.append("'");
     }
 
   this->command_line_ = args;
   this->strtab_->add(this->command_line_.c_str(), false,
-                     &this->command_line_key_);
+                    &this->command_line_key_);
 }
 
 // Record the input archive file ARCHIVE.  This is called by the
@@ -1105,7 +1106,7 @@ Incremental_inputs::report_object(Object* obj, unsigned int arg_serial,
   if (!obj->is_dynamic())
     {
       this->current_object_entry_ =
-          new Incremental_object_entry(filename_key, obj, arg_serial, mtime);
+         new Incremental_object_entry(filename_key, obj, arg_serial, mtime);
       input_entry = this->current_object_entry_;
       if (arch != NULL)
        {
@@ -1211,28 +1212,28 @@ Incremental_inputs::create_data_sections(Symbol_table* symtab)
 #ifdef HAVE_TARGET_32_LITTLE
     case Parameters::TARGET_32_LITTLE:
       this->inputs_section_ =
-          new Output_section_incremental_inputs<32, false>(this, symtab);
+         new Output_section_incremental_inputs<32, false>(this, symtab);
       reloc_align = 4;
       break;
 #endif
 #ifdef HAVE_TARGET_32_BIG
     case Parameters::TARGET_32_BIG:
       this->inputs_section_ =
-          new Output_section_incremental_inputs<32, true>(this, symtab);
+         new Output_section_incremental_inputs<32, true>(this, symtab);
       reloc_align = 4;
       break;
 #endif
 #ifdef HAVE_TARGET_64_LITTLE
     case Parameters::TARGET_64_LITTLE:
       this->inputs_section_ =
-          new Output_section_incremental_inputs<64, false>(this, symtab);
+         new Output_section_incremental_inputs<64, false>(this, symtab);
       reloc_align = 8;
       break;
 #endif
 #ifdef HAVE_TARGET_64_BIG
     case Parameters::TARGET_64_BIG:
       this->inputs_section_ =
-          new Output_section_incremental_inputs<64, true>(this, symtab);
+         new Output_section_incremental_inputs<64, true>(this, symtab);
       reloc_align = 8;
       break;
 #endif
@@ -1335,8 +1336,8 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
                  continue;
                if (sym->is_forwarder())
                  sym = this->symtab_->resolve_forwards(sym);
-               if (sym->symtab_index() != -1U)
-                 ++nsyms_out;
+               if (sym->symtab_index() != -1U)
+                 ++nsyms_out;
              }
            info_offset += nsyms_out * 4;
          }
@@ -1484,13 +1485,13 @@ Output_section_incremental_inputs<size, big_endian>::write_input_files(
     {
       gold_assert(static_cast<unsigned int>(pov - oview) == (*p)->get_offset());
       section_offset_type filename_offset =
-          strtab->get_offset_from_key((*p)->get_filename_key());
+         strtab->get_offset_from_key((*p)->get_filename_key());
       const Timespec& mtime = (*p)->get_mtime();
       unsigned int flags = (*p)->type();
       if ((*p)->is_in_system_directory())
-        flags |= INCREMENTAL_INPUT_IN_SYSTEM_DIR;
+       flags |= INCREMENTAL_INPUT_IN_SYSTEM_DIR;
       if ((*p)->as_needed())
-        flags |= INCREMENTAL_INPUT_AS_NEEDED;
+       flags |= INCREMENTAL_INPUT_AS_NEEDED;
       Swap32::writeval(pov, filename_offset);
       Swap32::writeval(pov + 4, (*p)->get_info_offset());
       Swap64::writeval(pov + 8, mtime.seconds);
@@ -1628,7 +1629,7 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
                    // but exclude linker-predefined symbols and symbols
                    // copied from shared objects.
                    if (!sym->is_predefined()
-                       && !sym->is_copied_from_dynobj())
+                       && !sym->is_copied_from_dynobj())
                      shndx = -1U;
                  }
                else if (sym->object() == obj && sym->is_defined())
@@ -1710,8 +1711,8 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
                  continue;
                if (sym->is_forwarder())
                  sym = this->symtab_->resolve_forwards(sym);
-               if (sym->symtab_index() == -1U)
-                 continue;
+               if (sym->symtab_index() == -1U)
+                 continue;
                unsigned int flags = 0;
                // If the symbol has hidden or internal visibility, we
                // mark it as defined in the shared object so we don't
@@ -1911,9 +1912,9 @@ class Global_symbol_visitor_got_plt
     const Got_offset_list* got_offsets = sym->got_offset_list();
     if (got_offsets != NULL)
       {
-        this->info_.sym_index = sym->symtab_index();
-        this->info_.input_index = 0;
-        Got_visitor v(this->info_);
+       this->info_.sym_index = sym->symtab_index();
+       this->info_.input_index = 0;
+       Got_visitor v(this->info_);
        got_offsets->for_all_got_offsets(&v);
       }
     if (sym->has_plt_offset())
@@ -2044,12 +2045,12 @@ Sized_relobj_incr<size, big_endian>::do_layout(
   for (unsigned int i = 1; i < shnum; i++)
     {
       typename Input_entry_reader::Input_section_info sect =
-          this->input_reader_.get_input_section(i - 1);
+         this->input_reader_.get_input_section(i - 1);
       // Add the section to the incremental inputs layout.
       incremental_inputs->report_input_section(this, i, sect.name,
                                               sect.sh_size);
       if (sect.output_shndx == 0 || sect.sh_offset == -1)
-        continue;
+       continue;
       Output_section* os = this->ibase_->output_section(sect.output_shndx);
       gold_assert(os != NULL);
       out_sections[i] = os;
@@ -2074,13 +2075,13 @@ Sized_relobj_incr<size, big_endian>::do_layout(
     {
       const char* signature = this->input_reader_.get_comdat_group_signature(i);
       if (signature == NULL || signature[0] == '\0')
-        this->error(_("COMDAT group has no signature"));
+       this->error(_("COMDAT group has no signature"));
       bool keep = layout->find_or_add_kept_section(signature, this, i, true,
                                                   true, NULL);
       if (keep)
        incremental_inputs->report_comdat_group(this, signature);
       else
-        this->error(_("COMDAT group %s included twice in incremental link"),
+       this->error(_("COMDAT group %s included twice in incremental link"),
                    signature);
     }
 
@@ -2160,7 +2161,7 @@ Sized_relobj_incr<size, big_endian>::do_add_symbols(
       // Local hidden symbols start out as globals, but get converted to
       // to local during output.
       if (st_bind == elfcpp::STB_LOCAL)
-        st_bind = elfcpp::STB_GLOBAL;
+       st_bind = elfcpp::STB_GLOBAL;
 
       unsigned int input_shndx = info.shndx();
       if (input_shndx == 0 || input_shndx == -1U)
@@ -2193,7 +2194,7 @@ Sized_relobj_incr<size, big_endian>::do_add_symbols(
       Symbol* res = symtab->add_from_incrobj(this, name, NULL, &sym);
 
       if (shndx != elfcpp::SHN_UNDEF)
-        ++this->defined_count_;
+       ++this->defined_count_;
 
       // If this is a linker-defined symbol that hasn't yet been defined,
       // define it now.
@@ -2486,7 +2487,7 @@ Sized_relobj_incr<size, big_endian>::do_count_local_symbols(
       elfcpp::Sym<size, big_endian> sym(symp);
       const char* name;
       if (!strtab.get_c_string(sym.get_st_name(), &name))
-        name = "";
+       name = "";
       gold_debug(DEBUG_INCREMENTAL, "Local symbol %d: %s", i, name);
       name = pool->add(name, true, NULL);
       this->local_symbols_.push_back(Local_symbol(name,
@@ -2589,7 +2590,7 @@ Sized_relobj_incr<size, big_endian>::do_relocate(const Symbol_table*,
   unsigned char* dyn_oview = NULL;
   if (dyn_output_size > 0)
     dyn_oview = of->get_output_view(this->local_dynsym_offset_,
-                                    dyn_output_size);
+                                   dyn_output_size);
 
   // Write the local symbols.
   unsigned char* ov = oview;
@@ -2633,18 +2634,18 @@ Sized_relobj_incr<size, big_endian>::do_relocate(const Symbol_table*,
 
       // Write the symbol to the output dynamic symbol table.
       if (lsym.needs_dynsym_entry)
-        {
-          gold_assert(dyn_ov < dyn_oview + dyn_output_size);
-          elfcpp::Sym_write<size, big_endian> osym(dyn_ov);
-          osym.put_st_name(dynpool->get_offset(lsym.name));
-          osym.put_st_value(lsym.st_value);
-          osym.put_st_size(lsym.st_size);
+       {
+         gold_assert(dyn_ov < dyn_oview + dyn_output_size);
+         elfcpp::Sym_write<size, big_endian> osym(dyn_ov);
+         osym.put_st_name(dynpool->get_offset(lsym.name));
+         osym.put_st_value(lsym.st_value);
+         osym.put_st_size(lsym.st_size);
          osym.put_st_info(elfcpp::STB_LOCAL,
                           static_cast<elfcpp::STT>(lsym.st_type));
-          osym.put_st_other(0);
-          osym.put_st_shndx(st_shndx);
-          dyn_ov += sym_size;
-        }
+         osym.put_st_other(0);
+         osym.put_st_shndx(st_shndx);
+         dyn_ov += sym_size;
+       }
     }
 
   if (output_size > 0)
@@ -2658,7 +2659,7 @@ Sized_relobj_incr<size, big_endian>::do_relocate(const Symbol_table*,
     {
       gold_assert(dyn_ov - dyn_oview == dyn_output_size);
       of->write_output_view(this->local_dynsym_offset_, dyn_output_size,
-                            dyn_oview);
+                           dyn_oview);
     }
 }
 
@@ -2768,7 +2769,7 @@ Sized_incr_dynobj<size, big_endian>::do_add_symbols(
       // Local hidden symbols start out as globals, but get converted to
       // to local during output.
       if (st_bind == elfcpp::STB_LOCAL)
-        st_bind = elfcpp::STB_GLOBAL;
+       st_bind = elfcpp::STB_GLOBAL;
 
       if (!is_def)
        {
index 65d1432d7b3dff6b6e3842736b63796f2bc8bc4e..7155f22e7fdb91e3049927abf81a3c44aa77574c 100644 (file)
@@ -1,6 +1,7 @@
 // layout.cc -- lay out output file sections for gold
 
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -155,9 +156,9 @@ off_t
 Free_list::allocate(off_t len, uint64_t align, off_t minoff)
 {
   gold_debug(DEBUG_INCREMENTAL,
-            "Free_list::allocate(%08lx, %d, %08lx)",
-            static_cast<long>(len), static_cast<int>(align),
-            static_cast<long>(minoff));
+            "Free_list::allocate(%08lx, %d, %08lx)",
+            static_cast<long>(len), static_cast<int>(align),
+            static_cast<long>(minoff));
   if (len == 0)
     return align_address(minoff, align);
 
@@ -222,17 +223,17 @@ void
 Free_list::print_stats()
 {
   fprintf(stderr, _("%s: total free lists: %u\n"),
-          program_name, Free_list::num_lists);
+         program_name, Free_list::num_lists);
   fprintf(stderr, _("%s: total free list nodes: %u\n"),
-          program_name, Free_list::num_nodes);
+         program_name, Free_list::num_nodes);
   fprintf(stderr, _("%s: calls to Free_list::remove: %u\n"),
-          program_name, Free_list::num_removes);
+         program_name, Free_list::num_removes);
   fprintf(stderr, _("%s: nodes visited: %u\n"),
-          program_name, Free_list::num_remove_visits);
+         program_name, Free_list::num_remove_visits);
   fprintf(stderr, _("%s: calls to Free_list::allocate: %u\n"),
-          program_name, Free_list::num_allocates);
+         program_name, Free_list::num_allocates);
   fprintf(stderr, _("%s: nodes visited: %u\n"),
-          program_name, Free_list::num_allocate_visits);
+         program_name, Free_list::num_allocate_visits);
 }
 
 // Layout::Relaxation_debug_check methods.
@@ -256,7 +257,7 @@ Layout::Relaxation_debug_check::check_output_data_for_reset_values(
       ++p)
     gold_assert((*p)->address_and_file_offset_have_reset_values());
 }
-  
+
 // Save information of SECTIONS for checking later.
 
 void
@@ -319,7 +320,7 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task)
   Layout* layout = this->layout_;
   off_t file_size = layout->finalize(this->input_objects_,
                                     this->symtab_,
-                                     this->target_,
+                                    this->target_,
                                     task);
 
   // Now we know the final size of the output file and we know where
@@ -349,8 +350,8 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task)
       // incremental information from the file before (possibly)
       // overwriting it.
       if (parameters->incremental_update())
-        layout->incremental_base()->apply_incremental_relocs(this->symtab_,
-                                                            this->layout_,
+       layout->incremental_base()->apply_incremental_relocs(this->symtab_,
+                                                            this->layout_,
                                                             of);
 
       of->resize(file_size);
@@ -579,7 +580,7 @@ Layout::include_section(Sized_relobj_file<size, big_endian>*, const char* name,
        {
          // Debugging sections can only be recognized by name.
          if (is_prefix_of(".debug", name)
-              && !is_lines_only_debug_section(name))
+             && !is_lines_only_debug_section(name))
            return false;
        }
       if (parameters->options().strip_debug_gdb()
@@ -587,17 +588,17 @@ Layout::include_section(Sized_relobj_file<size, big_endian>*, const char* name,
        {
          // Debugging sections can only be recognized by name.
          if (is_prefix_of(".debug", name)
-              && !is_gdb_debug_section(name))
+             && !is_gdb_debug_section(name))
            return false;
        }
       if (parameters->options().strip_lto_sections()
-          && !parameters->options().relocatable()
-          && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
-        {
-          // Ignore LTO sections containing intermediate code.
-          if (is_prefix_of(".gnu.lto_", name))
-            return false;
-        }
+         && !parameters->options().relocatable()
+         && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
+       {
+         // Ignore LTO sections containing intermediate code.
+         if (is_prefix_of(".gnu.lto_", name))
+           return false;
+       }
       // The GNU linker strips .gnu_debuglink sections, so we do too.
       // This is a feature used to keep debugging information in
       // separate files.
@@ -713,27 +714,27 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key,
 
       if (lookup_type == elfcpp::SHT_PROGBITS)
        {
-          if (flags == 0)
-            {
-              Output_section* same_name = this->find_output_section(name);
-              if (same_name != NULL
-                  && (same_name->type() == elfcpp::SHT_PROGBITS
+         if (flags == 0)
+           {
+             Output_section* same_name = this->find_output_section(name);
+             if (same_name != NULL
+                 && (same_name->type() == elfcpp::SHT_PROGBITS
                      || same_name->type() == elfcpp::SHT_INIT_ARRAY
                      || same_name->type() == elfcpp::SHT_FINI_ARRAY
                      || same_name->type() == elfcpp::SHT_PREINIT_ARRAY)
-                  && (same_name->flags() & elfcpp::SHF_TLS) == 0)
-                os = same_name;
-            }
-          else if ((flags & elfcpp::SHF_TLS) == 0)
-            {
-              elfcpp::Elf_Xword zero_flags = 0;
-              const Key zero_key(name_key, std::make_pair(lookup_type,
+                 && (same_name->flags() & elfcpp::SHF_TLS) == 0)
+               os = same_name;
+           }
+         else if ((flags & elfcpp::SHF_TLS) == 0)
+           {
+             elfcpp::Elf_Xword zero_flags = 0;
+             const Key zero_key(name_key, std::make_pair(lookup_type,
                                                          zero_flags));
-              Section_name_map::iterator p =
-                  this->section_name_map_.find(zero_key);
-              if (p != this->section_name_map_.end())
+             Section_name_map::iterator p =
+                 this->section_name_map_.find(zero_key);
+             if (p != this->section_name_map_.end())
                os = p->second;
-            }
+           }
        }
 
       if (os == NULL)
@@ -925,7 +926,7 @@ Layout::init_fixed_output_section(const char* name,
   Stringpool::Key name_key;
   name = this->namepool_.add(name, true, &name_key);
   Output_section* os = this->get_output_section(name, name_key, sh_type,
-                                               sh_flags, ORDER_INVALID, false);
+                                               sh_flags, ORDER_INVALID, false);
   os->set_fixed_layout(sh_addr, sh_offset, sh_size, sh_addralign);
   if (sh_type != elfcpp::SHT_NOBITS)
     this->free_list_.remove(sh_offset, sh_offset + sh_size);
@@ -1321,7 +1322,7 @@ Layout::add_to_gdb_index(bool is_type_unit,
                                                       false, ORDER_INVALID,
                                                       false);
       if (os == NULL)
-        return;
+       return;
 
       this->gdb_index_data_ = new Gdb_index(os);
       os->add_output_section_data(this->gdb_index_data_);
@@ -1379,22 +1380,22 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
     os = new Output_compressed_section(&parameters->options(), name, type,
                                       flags);
   else if ((flags & elfcpp::SHF_ALLOC) == 0
-           && parameters->options().strip_debug_non_line()
-           && strcmp(".debug_abbrev", name) == 0)
+          && parameters->options().strip_debug_non_line()
+          && strcmp(".debug_abbrev", name) == 0)
     {
       os = this->debug_abbrev_ = new Output_reduced_debug_abbrev_section(
-          name, type, flags);
+         name, type, flags);
       if (this->debug_info_)
-        this->debug_info_->set_abbreviations(this->debug_abbrev_);
+       this->debug_info_->set_abbreviations(this->debug_abbrev_);
     }
   else if ((flags & elfcpp::SHF_ALLOC) == 0
-           && parameters->options().strip_debug_non_line()
-           && strcmp(".debug_info", name) == 0)
+          && parameters->options().strip_debug_non_line()
+          && strcmp(".debug_info", name) == 0)
     {
       os = this->debug_info_ = new Output_reduced_debug_info_section(
-          name, type, flags);
+         name, type, flags);
       if (this->debug_abbrev_)
-        this->debug_info_->set_abbreviations(this->debug_abbrev_);
+       this->debug_info_->set_abbreviations(this->debug_abbrev_);
     }
   else
     {
@@ -1497,18 +1498,18 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
       // a minimum size, so we must prevent allocations from the
       // free list that leave a hole smaller than the minimum.
       if (strcmp(name, ".debug_info") == 0)
-        os->set_free_space_fill(new Output_fill_debug_info(false));
+       os->set_free_space_fill(new Output_fill_debug_info(false));
       else if (strcmp(name, ".debug_types") == 0)
-        os->set_free_space_fill(new Output_fill_debug_info(true));
+       os->set_free_space_fill(new Output_fill_debug_info(true));
       else if (strcmp(name, ".debug_line") == 0)
-        os->set_free_space_fill(new Output_fill_debug_line());
+       os->set_free_space_fill(new Output_fill_debug_line());
     }
 
   // If we have already attached the sections to segments, then we
   // need to attach this one now.  This happens for sections created
   // directly by the linker.
   if (this->sections_are_attached_)
-    this->attach_section_to_segment(os);
+    this->attach_section_to_segment(&parameters->target(), os);
 
   return os;
 }
@@ -1585,12 +1586,12 @@ Layout::default_section_order(Output_section* os, bool is_relro_local)
 // seen all the input sections.
 
 void
-Layout::attach_sections_to_segments()
+Layout::attach_sections_to_segments(const Target* target)
 {
   for (Section_list::iterator p = this->section_list_.begin();
        p != this->section_list_.end();
        ++p)
-    this->attach_section_to_segment(*p);
+    this->attach_section_to_segment(target, *p);
 
   this->sections_are_attached_ = true;
 }
@@ -1598,18 +1599,19 @@ Layout::attach_sections_to_segments()
 // Attach an output section to a segment.
 
 void
-Layout::attach_section_to_segment(Output_section* os)
+Layout::attach_section_to_segment(const Target* target, Output_section* os)
 {
   if ((os->flags() & elfcpp::SHF_ALLOC) == 0)
     this->unattached_section_list_.push_back(os);
   else
-    this->attach_allocated_section_to_segment(os);
+    this->attach_allocated_section_to_segment(target, os);
 }
 
 // Attach an allocated output section to a segment.
 
 void
-Layout::attach_allocated_section_to_segment(Output_section* os)
+Layout::attach_allocated_section_to_segment(const Target* target,
+                                           Output_section* os)
 {
   elfcpp::Elf_Xword flags = os->flags();
   gold_assert((flags & elfcpp::SHF_ALLOC) != 0);
@@ -1649,9 +1651,9 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
       if (!parameters->options().omagic()
          && ((*p)->flags() & elfcpp::PF_W) != (seg_flags & elfcpp::PF_W))
        continue;
-      if (parameters->options().rosegment()
-          && ((*p)->flags() & elfcpp::PF_X) != (seg_flags & elfcpp::PF_X))
-        continue;
+      if ((target->isolate_execinstr() || parameters->options().rosegment())
+         && ((*p)->flags() & elfcpp::PF_X) != (seg_flags & elfcpp::PF_X))
+       continue;
       // If -Tbss was specified, we need to separate the data and BSS
       // segments.
       if (parameters->options().user_set_Tbss())
@@ -1681,7 +1683,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
   if (p == this->segment_list_.end())
     {
       Output_segment* oseg = this->make_output_segment(elfcpp::PT_LOAD,
-                                                       seg_flags);
+                                                      seg_flags);
       if (os->is_large_data_section())
        oseg->set_is_large_data_segment();
       oseg->add_output_section_to_load(this, os, seg_flags);
@@ -1695,24 +1697,24 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
     {
       // See if we already have an equivalent PT_NOTE segment.
       for (p = this->segment_list_.begin();
-           p != segment_list_.end();
-           ++p)
-        {
-          if ((*p)->type() == elfcpp::PT_NOTE
-              && (((*p)->flags() & elfcpp::PF_W)
-                  == (seg_flags & elfcpp::PF_W)))
-            {
-              (*p)->add_output_section_to_nonload(os, seg_flags);
-              break;
-            }
-        }
+          p != segment_list_.end();
+          ++p)
+       {
+         if ((*p)->type() == elfcpp::PT_NOTE
+             && (((*p)->flags() & elfcpp::PF_W)
+                 == (seg_flags & elfcpp::PF_W)))
+           {
+             (*p)->add_output_section_to_nonload(os, seg_flags);
+             break;
+           }
+       }
 
       if (p == this->segment_list_.end())
-        {
-          Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
-                                                           seg_flags);
-          oseg->add_output_section_to_nonload(os, seg_flags);
-        }
+       {
+         Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
+                                                          seg_flags);
+         oseg->add_output_section_to_nonload(os, seg_flags);
+       }
     }
 
   // If we see a loadable SHF_TLS section, we create a PT_TLS
@@ -1883,9 +1885,9 @@ Layout::define_section_symbols(Symbol_table* symtab)
        {
          const std::string name_string(name);
          const std::string start_name(cident_section_start_prefix
-                                       + name_string);
+                                      + name_string);
          const std::string stop_name(cident_section_stop_prefix
-                                      + name_string);
+                                     + name_string);
 
          symtab->define_in_output_data(start_name.c_str(),
                                        NULL, // version
@@ -1951,7 +1953,7 @@ Layout::define_group_signatures(Symbol_table* symtab)
 // necessary.
 
 Output_segment*
-Layout::find_first_load_seg()
+Layout::find_first_load_seg(const Target* target)
 {
   Output_segment* best = NULL;
   for (Segment_list::const_iterator p = this->segment_list_.begin();
@@ -1961,11 +1963,13 @@ Layout::find_first_load_seg()
       if ((*p)->type() == elfcpp::PT_LOAD
          && ((*p)->flags() & elfcpp::PF_R) != 0
          && (parameters->options().omagic()
-             || ((*p)->flags() & elfcpp::PF_W) == 0))
-        {
-          if (best == NULL || this->segment_precedes(*p, best))
-            best = *p;
-        }
+             || ((*p)->flags() & elfcpp::PF_W) == 0)
+         && (!target->isolate_execinstr()
+             || ((*p)->flags() & elfcpp::PF_X) == 0))
+       {
+         if (best == NULL || this->segment_precedes(*p, best))
+           best = *p;
+       }
     }
   if (best != NULL)
     return best;
@@ -2023,10 +2027,10 @@ Layout::restore_segments(const Segment_states* segment_states)
            this->relro_segment_ = segment;
 
          ++list_iter;
-       } 
+       }
       else
        {
-         list_iter = this->segment_list_.erase(list_iter); 
+         list_iter = this->segment_list_.erase(list_iter);
          // This is a segment created during section layout.  It should be
          // safe to remove it since we should have removed all pointers to it.
          delete segment;
@@ -2059,7 +2063,7 @@ Layout::clean_up_after_relaxation()
 
       (*p)->reset_address_and_file_offset();
     }
-  
+
   // Reset special output object address and file offsets.
   for (Data_list::iterator p = this->special_output_list_.begin();
        p != this->special_output_list_.end();
@@ -2073,7 +2077,7 @@ Layout::clean_up_after_relaxation()
        p != this->script_output_section_data_list_.end();
        ++p)
     delete *p;
-  this->script_output_section_data_list_.clear(); 
+  this->script_output_section_data_list_.clear();
 }
 
 // Prepare for relaxation.
@@ -2096,7 +2100,7 @@ Layout::prepare_for_relaxation()
 
   if (is_debugging_enabled(DEBUG_RELAXATION))
     this->relaxation_debug_check_->check_output_data_for_reset_values(
-        this->section_list_, this->special_output_list_);
+       this->section_list_, this->special_output_list_);
 
   // Also enable recording of output section data from scripts.
   this->record_output_section_data_from_script_ = true;
@@ -2105,7 +2109,7 @@ Layout::prepare_for_relaxation()
 // Relaxation loop body:  If target has no relaxation, this runs only once
 // Otherwise, the target relaxation hook is called at the end of
 // each iteration.  If the hook returns true, it means re-layout of
-// section is required.  
+// section is required.
 //
 // The number of segments created by a linking script without a PHDRS
 // clause may be affected by section sizes and alignments.  There is
@@ -2115,8 +2119,8 @@ Layout::prepare_for_relaxation()
 // layout.  In order to be able to restart the section layout, we keep
 // a copy of the segment list right before the relaxation loop and use
 // that to restore the segments.
-// 
-// PASS is the current relaxation pass number. 
+//
+// PASS is the current relaxation pass number.
 // SYMTAB is a symbol table.
 // PLOAD_SEG is the address of a pointer for the load segment.
 // PHDR_SEG is a pointer to the PHDR segment.
@@ -2148,7 +2152,7 @@ Layout::relaxation_loop_body(
   else if (parameters->options().relocatable())
     load_seg = NULL;
   else
-    load_seg = this->find_first_load_seg();
+    load_seg = this->find_first_load_seg(target);
 
   if (parameters->options().oformat_enum()
       != General_options::OBJECT_FORMAT_ELF)
@@ -2205,9 +2209,9 @@ Layout::relaxation_loop_body(
          load_seg->add_initial_output_data(z);
        }
       if (load_seg != NULL)
-        load_seg->add_initial_output_data(segment_headers);
+       load_seg->add_initial_output_data(segment_headers);
       if (phdr_seg != NULL)
-        phdr_seg->add_initial_output_data(segment_headers);
+       phdr_seg->add_initial_output_data(segment_headers);
     }
 
   // Lay out the file header.
@@ -2268,11 +2272,11 @@ Layout::find_section_order_index(const std::string& section_name)
        ++it)
     {
        if (fnmatch((*it).c_str(), section_name.c_str(), FNM_NOESCAPE) == 0)
-         {
-           map_it = this->input_section_position_.find(*it);
-           gold_assert(map_it != this->input_section_position_.end());
-           return map_it->second;
-         }
+        {
+          map_it = this->input_section_position_.find(*it);
+          gold_assert(map_it != this->input_section_position_.end());
+          return map_it->second;
+        }
     }
   return 0;
 }
@@ -2290,7 +2294,7 @@ Layout::read_layout_from_file()
   in.open(filename);
   if (!in)
     gold_fatal(_("unable to open --section-ordering-file file %s: %s"),
-               filename, strerror(errno));
+              filename, strerror(errno));
 
   std::getline(in, line);   // this chops off the trailing \n, if any
   unsigned int position = 1;
@@ -2299,17 +2303,17 @@ Layout::read_layout_from_file()
   while (in)
     {
       if (!line.empty() && line[line.length() - 1] == '\r')   // Windows
-        line.resize(line.length() - 1);
+       line.resize(line.length() - 1);
       // Ignore comments, beginning with '#'
       if (line[0] == '#')
-        {
-          std::getline(in, line);
-          continue;
-        }
+       {
+         std::getline(in, line);
+         continue;
+       }
       this->input_section_position_[line] = position;
       // Store all glob patterns in a vector.
       if (is_wildcard_string(line.c_str()))
-        this->input_section_glob_.push_back(line);
+       this->input_section_glob_.push_back(line);
       position++;
       std::getline(in, line);
     }
@@ -2373,7 +2377,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
       std::vector<Symbol*> dynamic_symbols;
       unsigned int local_dynamic_count;
       Versions versions(*this->script_options()->version_script_info(),
-                        &this->dynpool_);
+                       &this->dynpool_);
       this->create_dynamic_symtab(input_objects, symtab, &dynstr,
                                  &local_dynamic_count, &dynamic_symbols,
                                  &versions);
@@ -2384,7 +2388,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
       if ((!parameters->options().shared()
           || parameters->options().dynamic_linker() != NULL)
          && this->interp_segment_ == NULL)
-        this->create_interp(target);
+       this->create_interp(target);
 
       // Finish the .dynamic section to hold the dynamic data, and put
       // it in a PT_DYNAMIC segment.
@@ -2403,7 +2407,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
       // after we call create_version_sections.
       this->set_dynamic_symbol_size(symtab);
     }
-  
+
   // Create segment headers.
   Output_segment_headers* segment_headers =
     (parameters->options().relocatable()
@@ -2422,7 +2426,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
   // a linker script.
   if (this->script_options_->saw_sections_clause())
     this->place_orphan_sections_in_script();
-  
+
   Output_segment* load_seg;
   off_t off;
   unsigned int shndx;
@@ -2431,7 +2435,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
   // Take a snapshot of the section layout as needed.
   if (target->may_relax())
     this->prepare_for_relaxation();
-  
+
   // Run the relaxation loop to lay out sections.
   do
     {
@@ -2873,8 +2877,8 @@ Layout::create_incremental_info_sections(Symbol_table* symtab)
   const char* incremental_strtab_name =
     this->namepool_.add(".gnu_incremental_strtab", false, NULL);
   Output_section* incremental_strtab_os = this->make_output_section(incremental_strtab_name,
-                                                        elfcpp::SHT_STRTAB, 0,
-                                                        ORDER_INVALID, false);
+                                                       elfcpp::SHT_STRTAB, 0,
+                                                       ORDER_INVALID, false);
   Output_data_strtab* strtab_data =
       new Output_data_strtab(incr->get_stringpool());
   incremental_strtab_os->add_output_section_data(strtab_data);
@@ -3054,13 +3058,15 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
 
   // Find the PT_LOAD segments, and set their addresses and offsets
   // and their section's addresses and offsets.
-  uint64_t addr;
+  uint64_t start_addr;
   if (parameters->options().user_set_Ttext())
-    addr = parameters->options().Ttext();
+    start_addr = parameters->options().Ttext();
   else if (parameters->options().output_is_position_independent())
-    addr = 0;
+    start_addr = 0;
   else
-    addr = target->default_text_segment_address();
+    start_addr = target->default_text_segment_address();
+
+  uint64_t addr = start_addr;
   off_t off = 0;
 
   // If LOAD_SEG is NULL, then the file header and segment headers
@@ -3085,15 +3091,39 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
   const bool check_sections = parameters->options().check_sections();
   Output_segment* last_load_segment = NULL;
 
+  unsigned int shndx_begin = *pshndx;
+  unsigned int shndx_load_seg = *pshndx;
+
   for (Segment_list::iterator p = this->segment_list_.begin();
        p != this->segment_list_.end();
        ++p)
     {
       if ((*p)->type() == elfcpp::PT_LOAD)
        {
-         if (load_seg != NULL && load_seg != *p)
-           gold_unreachable();
-         load_seg = NULL;
+         if (target->isolate_execinstr())
+           {
+             // When we hit the segment that should contain the
+             // file headers, reset the file offset so we place
+             // it and subsequent segments appropriately.
+             // We'll fix up the preceding segments below.
+             if (load_seg == *p)
+               {
+                 if (off == 0)
+                   load_seg = NULL;
+                 else
+                   {
+                     off = 0;
+                     shndx_load_seg = *pshndx;
+                   }
+               }
+           }
+         else
+           {
+             // Verify that the file headers fall into the first segment.
+             if (load_seg != NULL && load_seg != *p)
+               gold_unreachable();
+             load_seg = NULL;
+           }
 
          bool are_addresses_set = (*p)->are_addresses_set();
          if (are_addresses_set)
@@ -3145,16 +3175,37 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
              addr = align_address(addr, (*p)->maximum_alignment());
              aligned_addr = addr;
 
-             if ((addr & (abi_pagesize - 1)) != 0)
-                addr = addr + abi_pagesize;
+             if (load_seg == *p)
+               {
+                 // This is the segment that will contain the file
+                 // headers, so its offset will have to be exactly zero.
+                 gold_assert(orig_off == 0);
+
+                 // If the target wants a fixed minimum distance from the
+                 // text segment to the read-only segment, move up now.
+                 uint64_t min_addr = start_addr + target->rosegment_gap();
+                 if (addr < min_addr)
+                   addr = min_addr;
+
+                 // But this is not the first segment!  To make its
+                 // address congruent with its offset, that address better
+                 // be aligned to the ABI-mandated page size.
+                 addr = align_address(addr, abi_pagesize);
+                 aligned_addr = addr;
+               }
+             else
+               {
+                 if ((addr & (abi_pagesize - 1)) != 0)
+                   addr = addr + abi_pagesize;
 
-             off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
+                 off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
+               }
            }
 
          if (!parameters->options().nmagic()
              && !parameters->options().omagic())
            off = align_file_offset(off, addr, abi_pagesize);
-         else if (load_seg == NULL)
+         else
            {
              // This is -N or -n with a section script which prevents
              // us from using a load segment.  We need to ensure that
@@ -3173,7 +3224,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
          uint64_t new_addr = (*p)->set_section_addresses(this, false, addr,
                                                          &increase_relro,
                                                          &has_relro,
-                                                          &off, pshndx);
+                                                         &off, pshndx);
 
          // Now that we know the size of this segment, we may be able
          // to save a page in memory, at the cost of wasting some
@@ -3212,7 +3263,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
                  new_addr = (*p)->set_section_addresses(this, true, addr,
                                                         &increase_relro,
                                                         &has_relro,
-                                                         &off, pshndx);
+                                                        &off, pshndx);
                }
            }
 
@@ -3239,6 +3290,38 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
        }
     }
 
+  if (load_seg != NULL && target->isolate_execinstr())
+    {
+      // Process the early segments again, setting their file offsets
+      // so they land after the segments starting at LOAD_SEG.
+      off = align_file_offset(off, 0, target->abi_pagesize());
+
+      for (Segment_list::iterator p = this->segment_list_.begin();
+          *p != load_seg;
+          ++p)
+       {
+         if ((*p)->type() == elfcpp::PT_LOAD)
+           {
+             // We repeat the whole job of assigning addresses and
+             // offsets, but we really only want to change the offsets and
+             // must ensure that the addresses all come out the same as
+             // they did the first time through.
+             bool has_relro = false;
+             const uint64_t old_addr = (*p)->vaddr();
+             const uint64_t old_end = old_addr + (*p)->memsz();
+             uint64_t new_addr = (*p)->set_section_addresses(this, true,
+                                                             old_addr,
+                                                             &increase_relro,
+                                                             &has_relro,
+                                                             &off,
+                                                             &shndx_begin);
+             gold_assert(new_addr == old_end);
+           }
+       }
+
+      gold_assert(shndx_begin == shndx_load_seg);
+    }
+
   // Handle the non-PT_LOAD segments, setting their offsets from their
   // section's offsets.
   for (Segment_list::iterator p = this->segment_list_.begin();
@@ -3326,16 +3409,16 @@ Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass)
        }
 
       if (pass == BEFORE_INPUT_SECTIONS_PASS
-          && (*p)->after_input_sections())
-        continue;
+         && (*p)->after_input_sections())
+       continue;
       else if (pass == POSTPROCESSING_SECTIONS_PASS
-               && (!(*p)->after_input_sections()
-                   || (*p)->type() == elfcpp::SHT_STRTAB))
-        continue;
+              && (!(*p)->after_input_sections()
+                  || (*p)->type() == elfcpp::SHT_STRTAB))
+       continue;
       else if (pass == STRTAB_AFTER_POSTPROCESSING_SECTIONS_PASS
-               && (!(*p)->after_input_sections()
-                   || (*p)->type() != elfcpp::SHT_STRTAB))
-        continue;
+              && (!(*p)->after_input_sections()
+                  || (*p)->type() != elfcpp::SHT_STRTAB))
+       continue;
 
       if (!parameters->incremental_update())
        {
@@ -3352,7 +3435,7 @@ Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass)
          if (off == -1)
            {
              if (is_debugging_enabled(DEBUG_INCREMENTAL))
-               this->free_list_.dump();
+               this->free_list_.dump();
              gold_assert((*p)->output_section() != NULL);
              gold_fallback(_("out of patch space for section %s; "
                              "relink with --incremental-full"),
@@ -3377,7 +3460,7 @@ Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass)
 
       off += (*p)->data_size();
       if (off > maxoff)
-        maxoff = off;
+       maxoff = off;
 
       // At this point the name must be set.
       if (pass != STRTAB_AFTER_POSTPROCESSING_SECTIONS_PASS)
@@ -3525,7 +3608,7 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
        ++p)
     {
       unsigned int index = (*p)->finalize_local_symbols(local_symbol_index,
-                                                        off, symtab);
+                                                       off, symtab);
       off += (index - local_symbol_index) * symsize;
       local_symbol_index = index;
     }
@@ -3619,7 +3702,7 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
       else
        {
          symtab_off = this->allocate(off, align, *poff);
-          if (off == -1)
+         if (off == -1)
            gold_fallback(_("out of patch space for symbol table; "
                            "relink with --incremental-full"));
          gold_debug(DEBUG_INCREMENTAL,
@@ -3722,7 +3805,7 @@ Layout::allocated_output_section_count() const
 
 void
 Layout::create_dynamic_symtab(const Input_objects* input_objects,
-                              Symbol_table* symtab,
+                             Symbol_table* symtab,
                              Output_section** pdynstr,
                              unsigned int* plocal_dynamic_count,
                              std::vector<Symbol*>* pdynamic_symbols,
@@ -4301,45 +4384,45 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
       {
       case elfcpp::SHT_FINI_ARRAY:
        odyn->add_section_address(elfcpp::DT_FINI_ARRAY, *p);
-       odyn->add_section_size(elfcpp::DT_FINI_ARRAYSZ, *p); 
+       odyn->add_section_size(elfcpp::DT_FINI_ARRAYSZ, *p);
        break;
       case elfcpp::SHT_INIT_ARRAY:
        odyn->add_section_address(elfcpp::DT_INIT_ARRAY, *p);
-       odyn->add_section_size(elfcpp::DT_INIT_ARRAYSZ, *p); 
+       odyn->add_section_size(elfcpp::DT_INIT_ARRAYSZ, *p);
        break;
       case elfcpp::SHT_PREINIT_ARRAY:
        odyn->add_section_address(elfcpp::DT_PREINIT_ARRAY, *p);
-       odyn->add_section_size(elfcpp::DT_PREINIT_ARRAYSZ, *p); 
+       odyn->add_section_size(elfcpp::DT_PREINIT_ARRAYSZ, *p);
        break;
       default:
        break;
       }
-  
+
   // Add a DT_RPATH entry if needed.
   const General_options::Dir_list& rpath(parameters->options().rpath());
   if (!rpath.empty())
     {
       std::string rpath_val;
       for (General_options::Dir_list::const_iterator p = rpath.begin();
-           p != rpath.end();
-           ++p)
-        {
-          if (rpath_val.empty())
-            rpath_val = p->name();
-          else
-            {
-              // Eliminate duplicates.
-              General_options::Dir_list::const_iterator q;
-              for (q = rpath.begin(); q != p; ++q)
+          p != rpath.end();
+          ++p)
+       {
+         if (rpath_val.empty())
+           rpath_val = p->name();
+         else
+           {
+             // Eliminate duplicates.
+             General_options::Dir_list::const_iterator q;
+             for (q = rpath.begin(); q != p; ++q)
                if (q->name() == p->name())
-                  break;
-              if (q == p)
-                {
-                  rpath_val += ':';
-                  rpath_val += p->name();
-                }
-            }
-        }
+                 break;
+             if (q == p)
+               {
+                 rpath_val += ':';
+                 rpath_val += p->name();
+               }
+           }
+       }
 
       odyn->add_string(elfcpp::DT_RPATH, rpath_val);
       if (parameters->options().enable_new_dtags())
@@ -4351,17 +4434,17 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
   if (!this->script_options_->saw_sections_clause())
     {
       for (Segment_list::const_iterator p = this->segment_list_.begin();
-           p != this->segment_list_.end();
-           ++p)
-        {
-          if ((*p)->type() == elfcpp::PT_LOAD
+          p != this->segment_list_.end();
+          ++p)
+       {
+         if ((*p)->type() == elfcpp::PT_LOAD
              && ((*p)->flags() & elfcpp::PF_W) == 0
-              && (*p)->has_dynamic_reloc())
-            {
-              have_textrel = true;
-              break;
-            }
-        }
+             && (*p)->has_dynamic_reloc())
+           {
+             have_textrel = true;
+             break;
+           }
+       }
     }
   else
     {
@@ -4370,17 +4453,17 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
       // relocations.  If those sections wind up in writable segments,
       // then we have created an unnecessary DT_TEXTREL entry.
       for (Section_list::const_iterator p = this->section_list_.begin();
-           p != this->section_list_.end();
-           ++p)
-        {
-          if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0
-              && ((*p)->flags() & elfcpp::SHF_WRITE) == 0
-              && (*p)->has_dynamic_reloc())
-            {
-              have_textrel = true;
-              break;
-            }
-        }
+          p != this->section_list_.end();
+          ++p)
+       {
+         if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0
+             && ((*p)->flags() & elfcpp::SHF_WRITE) == 0
+             && (*p)->has_dynamic_reloc())
+           {
+             have_textrel = true;
+             break;
+           }
+       }
     }
 
   if (parameters->options().filter() != NULL)
@@ -4652,7 +4735,7 @@ Layout::find_or_add_kept_section(const std::string& name,
                                 unsigned int shndx,
                                 bool is_comdat,
                                 bool is_group_name,
-                                 Kept_section** kept_section)
+                                Kept_section** kept_section)
 {
   // It's normal to see a couple of entries here, for the x86 thunk
   // sections.  If we see more than a few, we're linking a C++
@@ -4691,12 +4774,12 @@ Layout::find_or_add_kept_section(const std::string& name,
       // If the kept group is from a plugin object, and we're in the
       // replacement phase, accept the new one as a replacement.
       if (ins.first->second.object() == NULL
-          && parameters->options().plugins()->in_replacement_phase())
-        {
+         && parameters->options().plugins()->in_replacement_phase())
+       {
          ins.first->second.set_object(object);
          ins.first->second.set_shndx(shndx);
-          return true;
-        }
+         return true;
+       }
       return false;
     }
   else if (is_group_name)
index f81ea3b9a737a1ece0c2ca2753aa5dc6970b8cb0..4643e325d5015358a9f6b1a004c5b3fda3984899 100644 (file)
@@ -1,6 +1,7 @@
 // layout.h -- lay out output file sections for gold  -*- C++ -*-
 
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -171,7 +172,7 @@ class Layout_task_runner : public Task_function_runner
   Layout_task_runner(const General_options& options,
                     const Input_objects* input_objects,
                     Symbol_table* symtab,
-                     Target* target,
+                    Target* target,
                     Layout* layout,
                     Mapfile* mapfile)
     : options_(options), input_objects_(input_objects), symtab_(symtab),
@@ -526,7 +527,7 @@ class Layout
   std::map<Section_id, unsigned int>*
   get_section_order_map()
   { return &this->section_order_map_; }
+
   bool
   is_section_ordering_specified()
   { return this->section_ordering_specified_; }
@@ -709,11 +710,11 @@ class Layout
   {
     // Debugging sections can only be recognized by name.
     return (strncmp(name, ".debug", sizeof(".debug") - 1) == 0
-            || strncmp(name, ".zdebug", sizeof(".zdebug") - 1) == 0
-            || strncmp(name, ".gnu.linkonce.wi.",
-                       sizeof(".gnu.linkonce.wi.") - 1) == 0
-            || strncmp(name, ".line", sizeof(".line") - 1) == 0
-            || strncmp(name, ".stab", sizeof(".stab") - 1) == 0);
+           || strncmp(name, ".zdebug", sizeof(".zdebug") - 1) == 0
+           || strncmp(name, ".gnu.linkonce.wi.",
+                      sizeof(".gnu.linkonce.wi.") - 1) == 0
+           || strncmp(name, ".line", sizeof(".line") - 1) == 0
+           || strncmp(name, ".stab", sizeof(".stab") - 1) == 0);
   }
 
   // Return true if RELOBJ is an input file whose base name matches
@@ -736,7 +737,7 @@ class Layout
   // *KEPT_SECTION is set to the internal copy and the function return
   // false.
   bool
-  find_or_add_kept_section(const std::string& name, Relobj* object, 
+  find_or_add_kept_section(const std::string& name, Relobj* object,
                           unsigned int shndx, bool is_comdat,
                           bool is_group_name, Kept_section** kept_section);
 
@@ -903,7 +904,7 @@ class Layout
 
   // Attach sections to segments.
   void
-  attach_sections_to_segments();
+  attach_sections_to_segments(const Target*);
 
   // For relaxation clean up, we need to know output section data created
   // from a linker script.
@@ -982,7 +983,7 @@ class Layout
   // Find the first read-only PT_LOAD segment, creating one if
   // necessary.
   Output_segment*
-  find_first_load_seg();
+  find_first_load_seg(const Target*);
 
   // Count the local symbols in the regular symbol table and the dynamic
   // symbol table, and build the respective string pools.
@@ -1079,7 +1080,7 @@ class Layout
 
   // Attach a section to a segment.
   void
-  attach_section_to_segment(Output_section*);
+  attach_section_to_segment(const Target*, Output_section*);
 
   // Get section order.
   Output_section_order
@@ -1087,7 +1088,7 @@ class Layout
 
   // Attach an allocated section to a segment.
   void
-  attach_allocated_section_to_segment(Output_section*);
+  attach_allocated_section_to_segment(const Target*, Output_section*);
 
   // Make the .eh_frame section.
   Output_section*
@@ -1134,7 +1135,7 @@ class Layout
   bool
   segment_precedes(const Output_segment* seg1, const Output_segment* seg2);
 
-  // Use to save and restore segments during relaxation. 
+  // Use to save and restore segments during relaxation.
   typedef Unordered_map<const Output_segment*, const Output_segment*>
     Segment_states;
 
@@ -1205,12 +1206,12 @@ class Layout
     Relaxation_debug_check()
       : section_infos_()
     { }
+
     // Check that sections and special data are in reset states.
     void
     check_output_data_for_reset_values(const Layout::Section_list&,
                                       const Layout::Data_list&);
-  
+
     // Record information of a section list.
     void
     read_sections(const Layout::Section_list&);
@@ -1218,7 +1219,7 @@ class Layout
     // Verify a section list with recorded information.
     void
     verify_sections(const Layout::Section_list&);
+
    private:
     // Information we care about a section.
     struct Section_info
diff --git a/gold/nacl.cc b/gold/nacl.cc
new file mode 100644 (file)
index 0000000..71be4e9
--- /dev/null
@@ -0,0 +1,46 @@
+// nacl.cc -- Native Client support for gold
+
+// Copyright 2012 Free Software Foundation, Inc.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
+#include "gold.h"
+
+#include <cstdio>
+
+#include "nacl.h"
+#include "elfcpp.h"
+
+namespace gold
+{
+
+// Copied from object.cc:Object::error.
+void
+Sniff_file::error(const char* format, ...) const
+{
+  va_list args;
+  va_start(args, format);
+  char* buf = NULL;
+  if (vasprintf(&buf, format, args) < 0)
+    gold_nomem();
+  va_end(args);
+  gold_error(_("%s: %s"), this->file_.filename().c_str(), buf);
+  free(buf);
+}
+
+} // end namespace gold
diff --git a/gold/nacl.h b/gold/nacl.h
new file mode 100644 (file)
index 0000000..bf5853d
--- /dev/null
@@ -0,0 +1,243 @@
+// nacl.h -- Native Client support for gold    -*- C++ -*-
+
+// Copyright 2012 Free Software Foundation, Inc.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
+#include "elfcpp_file.h"
+#include "fileread.h"
+#include "layout.h"
+#include "target-select.h"
+#include "target.h"
+
+#ifndef GOLD_NACL_H
+#define GOLD_NACL_H
+
+namespace gold
+{
+
+class Sniff_file
+{
+ public:
+  Sniff_file(Input_file* input_file, off_t offset)
+    : file_(input_file->file()), offset_(offset)
+  { }
+
+  class Location
+  {
+   public:
+    Location(off_t file_offset, off_t data_size)
+      : offset_(file_offset), size_(data_size)
+    { }
+
+    inline off_t offset() const
+    { return this->offset_; }
+
+    inline section_size_type size() const
+    { return this->size_; }
+
+   private:
+    off_t offset_;
+    section_size_type size_;
+  };
+
+  class View
+  {
+   public:
+    View(File_read& file, off_t file_offset, off_t data_size)
+      : data_(file.get_view(0, file_offset, data_size, false, false))
+    { }
+
+    const unsigned char* data()
+    { return this->data_; }
+
+   private:
+    const unsigned char* data_;
+  };
+
+  View view(off_t file_offset, off_t data_size)
+  {
+    return View(this->file_, this->offset_ + file_offset, data_size);
+  }
+
+  View view(Location loc)
+  {
+    return this->view(loc.offset(), loc.size());
+  }
+
+  // Report an error.
+  void
+  error(const char* format, ...) const ATTRIBUTE_PRINTF_2;
+
+ private:
+  File_read& file_;
+  off_t offset_;
+};
+
+
+template<class base_selector, class nacl_target>
+class Target_selector_nacl : public base_selector
+{
+ public:
+  Target_selector_nacl(const char* nacl_abi_name,
+                       const char* bfd_name, const char* emulation)
+    : base_selector(), is_nacl_(false), nacl_abi_name_(nacl_abi_name),
+      bfd_name_(bfd_name), emulation_(emulation)
+  { }
+
+ protected:
+  virtual Target*
+  do_instantiate_target()
+  {
+    if (this->is_nacl_)
+      return new nacl_target();
+    return this->base_selector::do_instantiate_target();
+  }
+
+  virtual Target*
+  do_recognize(Input_file* file, off_t offset,
+               int machine, int osabi, int abiversion)
+  {
+    this->is_nacl_ = file != NULL && this->recognize_nacl_file(file, offset);
+    if (this->is_nacl_)
+      return this->instantiate_target();
+    return this->base_selector::do_recognize(file, offset,
+                                             machine, osabi, abiversion);
+  }
+
+  virtual Target*
+  do_recognize_by_bfd_name(const char* name)
+  {
+    gold_assert(this->bfd_name_ != NULL);
+    this->is_nacl_ = strcmp(name, this->bfd_name_) == 0;
+    if (this->is_nacl_)
+      return this->instantiate_target();
+    return this->base_selector::do_recognize_by_bfd_name(name);
+  }
+
+  virtual void
+  do_supported_bfd_names(std::vector<const char*>* names)
+  {
+    gold_assert(this->bfd_name_ != NULL);
+    this->base_selector::do_supported_bfd_names(names);
+    names->push_back(this->bfd_name_);
+  }
+
+  virtual void
+  do_supported_emulations(std::vector<const char*>* emulations)
+  {
+    gold_assert(this->emulation_ != NULL);
+    this->base_selector::do_supported_emulations(emulations);
+    emulations->push_back(this->emulation_);
+  }
+
+  virtual const char*
+  do_target_bfd_name(const Target* target)
+  {
+    return (!this->is_our_target(target)
+            ? NULL
+            : (this->is_nacl_
+               ? this->bfd_name_
+               : base_selector::do_target_bfd_name(target)));
+  }
+
+ private:
+  bool
+  recognize_nacl_file(Input_file* input_file, off_t offset)
+  {
+    if (this->is_big_endian())
+      {
+#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
+# ifdef HAVE_TARGET_32_BIG
+        if (this->get_size() == 32)
+          return do_recognize_nacl_file<32, true>(input_file, offset);
+# endif
+# ifdef HAVE_TARGET_64_BIG
+        if (this->get_size() == 64)
+          return do_recognize_nacl_file<64, true>(input_file, offset);
+# endif
+#endif
+        gold_unreachable();
+      }
+    else
+      {
+#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE)
+# ifdef HAVE_TARGET_32_LITTLE
+        if (this->get_size() == 32)
+          return do_recognize_nacl_file<32, false>(input_file, offset);
+# endif
+# ifdef HAVE_TARGET_64_LITTLE
+        if (this->get_size() == 64)
+          return do_recognize_nacl_file<64, false>(input_file, offset);
+# endif
+#endif
+        gold_unreachable();
+      }
+  }
+
+  template<int size, bool big_endian>
+  bool
+  do_recognize_nacl_file(Input_file* input_file, off_t offset)
+  {
+    Sniff_file file(input_file, offset);
+    elfcpp::Elf_file<size, big_endian, Sniff_file> elf_file(&file);
+    const unsigned int shnum = elf_file.shnum();
+    for (unsigned int shndx = 1; shndx < shnum; ++shndx)
+      {
+        if (elf_file.section_type(shndx) == elfcpp::SHT_NOTE)
+          {
+            Sniff_file::Location loc = elf_file.section_contents(shndx);
+            if (loc.size() < (3 * 4
+                              + align_address(sizeof "NaCl", 4)
+                              + align_address(nacl_abi_name_.size() + 1, 4)))
+              continue;
+            Sniff_file::View view(file.view(loc));
+            const unsigned char* note_data = view.data();
+            if ((elfcpp::Swap<32, big_endian>::readval(note_data + 0)
+                 == sizeof "NaCl")
+                && (elfcpp::Swap<32, big_endian>::readval(note_data + 4)
+                    == nacl_abi_name_.size() + 1)
+                && (elfcpp::Swap<32, big_endian>::readval(note_data + 8)
+                    == elfcpp::NT_VERSION))
+              {
+                const unsigned char* name = note_data + 12;
+                const unsigned char* desc = (name
+                                             + align_address(sizeof "NaCl", 4));
+                if (memcmp(name, "NaCl", sizeof "NaCl") == 0
+                    && memcmp(desc, nacl_abi_name_.c_str(),
+                              nacl_abi_name_.size() + 1) == 0)
+                  return true;
+              }
+          }
+      }
+    return false;
+  }
+
+  // Whether we decided this was the NaCl target variant.
+  bool is_nacl_;
+  // The string found in the NaCl ABI note.
+  std::string nacl_abi_name_;
+  // BFD name of NaCl target, for compatibility.
+  const char* const bfd_name_;
+  // GNU linker emulation for this NaCl target, for compatibility.
+  const char* const emulation_;
+};
+
+} // end namespace gold
+
+#endif // !defined(GOLD_NACL_H)
index 15e5d05407858a62d1577db29419a8aac7e0b089..e43ffdca2b6d819f4d0c5a1ffa9eb4164b5450f6 100644 (file)
@@ -1,6 +1,7 @@
 // object.cc -- support for an object file for linking in gold
 
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -268,28 +269,28 @@ Object::handle_split_stack_section(const char* name)
 // Class Relobj
 
 // To copy the symbols data read from the file to a local data structure.
-// This function is called from do_layout only while doing garbage 
+// This function is called from do_layout only while doing garbage
 // collection.
 
 void
-Relobj::copy_symbols_data(Symbols_data* gc_sd, Read_symbols_data* sd, 
-                          unsigned int section_header_size)
+Relobj::copy_symbols_data(Symbols_data* gc_sd, Read_symbols_data* sd,
+                         unsigned int section_header_size)
 {
-  gc_sd->section_headers_data = 
-         new unsigned char[(section_header_size)];
+  gc_sd->section_headers_data =
+        new unsigned char[(section_header_size)];
   memcpy(gc_sd->section_headers_data, sd->section_headers->data(),
-         section_header_size);
-  gc_sd->section_names_data = 
-         new unsigned char[sd->section_names_size];
+        section_header_size);
+  gc_sd->section_names_data =
+        new unsigned char[sd->section_names_size];
   memcpy(gc_sd->section_names_data, sd->section_names->data(),
-         sd->section_names_size);
+        sd->section_names_size);
   gc_sd->section_names_size = sd->section_names_size;
   if (sd->symbols != NULL)
     {
-      gc_sd->symbols_data = 
-             new unsigned char[sd->symbols_size];
+      gc_sd->symbols_data =
+            new unsigned char[sd->symbols_size];
       memcpy(gc_sd->symbols_data, sd->symbols->data(),
-            sd->symbols_size);
+           sd->symbols_size);
     }
   else
     {
@@ -300,9 +301,9 @@ Relobj::copy_symbols_data(Symbols_data* gc_sd, Read_symbols_data* sd,
   if (sd->symbol_names != NULL)
     {
       gc_sd->symbol_names_data =
-             new unsigned char[sd->symbol_names_size];
+            new unsigned char[sd->symbol_names_size];
       memcpy(gc_sd->symbol_names_data, sd->symbol_names->data(),
-            sd->symbol_names_size);
+           sd->symbol_names_size);
     }
   else
     {
@@ -318,22 +319,22 @@ Relobj::copy_symbols_data(Symbols_data* gc_sd, Read_symbols_data* sd,
 bool
 Relobj::is_section_name_included(const char* name)
 {
-  if (is_prefix_of(".ctors", name) 
-      || is_prefix_of(".dtors", name) 
-      || is_prefix_of(".note", name) 
-      || is_prefix_of(".init", name) 
-      || is_prefix_of(".fini", name) 
-      || is_prefix_of(".gcc_except_table", name) 
-      || is_prefix_of(".jcr", name) 
-      || is_prefix_of(".preinit_array", name) 
-      || (is_prefix_of(".text", name) 
-          && strstr(name, "personality")) 
-      || (is_prefix_of(".data", name) 
-          &&  strstr(name, "personality")) 
+  if (is_prefix_of(".ctors", name)
+      || is_prefix_of(".dtors", name)
+      || is_prefix_of(".note", name)
+      || is_prefix_of(".init", name)
+      || is_prefix_of(".fini", name)
+      || is_prefix_of(".gcc_except_table", name)
+      || is_prefix_of(".jcr", name)
+      || is_prefix_of(".preinit_array", name)
+      || (is_prefix_of(".text", name)
+         && strstr(name, "personality"))
+      || (is_prefix_of(".data", name)
+         &&  strstr(name, "personality"))
       || (is_prefix_of(".gnu.linkonce.d", name)
          && strstr(name, "personality")))
     {
-      return true; 
+      return true;
     }
   return false;
 }
@@ -669,11 +670,11 @@ Sized_relobj_file<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
   if (memmem(names, sd->section_names_size, ".eh_frame", 10) != NULL)
     {
       if (this->find_eh_frame(pshdrs, names, sd->section_names_size))
-        this->has_eh_frame_ = true;
+       this->has_eh_frame_ = true;
     }
   if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
     this->compressed_sections_ =
-        build_compressed_section_map(pshdrs, this->shnum(), names,
+       build_compressed_section_map(pshdrs, this->shnum(), names,
                                     sd->section_names_size, this);
 
   if (this->has_eh_frame_
@@ -874,7 +875,7 @@ Sized_relobj_file<size, big_endian>::include_section_group(
        }
       typename This::Shdr member_shdr(shdrs + sym_shndx * This::shdr_size);
       if (member_shdr.get_sh_name() < section_names_size)
-        signature = section_names + member_shdr.get_sh_name();
+       signature = section_names + member_shdr.get_sh_name();
     }
 
   // Record this section group in the layout, and see whether we've already
@@ -928,18 +929,18 @@ Sized_relobj_file<size, big_endian>::include_section_group(
       // Check for an earlier section number, since we're going to get
       // it wrong--we may have already decided to include the section.
       if (shndx < index)
-        this->error(_("invalid section group %u refers to earlier section %u"),
-                    index, shndx);
+       this->error(_("invalid section group %u refers to earlier section %u"),
+                   index, shndx);
 
       // Get the name of the member section.
       typename This::Shdr member_shdr(shdrs + shndx * This::shdr_size);
       if (member_shdr.get_sh_name() >= section_names_size)
-        {
-          // This is an error, but it will be diagnosed eventually
-          // in do_layout, so we don't need to do anything here but
-          // ignore it.
-          continue;
-        }
+       {
+         // This is an error, but it will be diagnosed eventually
+         // in do_layout, so we don't need to do anything here but
+         // ignore it.
+         continue;
+       }
       std::string mname(section_names + member_shdr.get_sh_name());
 
       if (include_group)
@@ -949,11 +950,11 @@ Sized_relobj_file<size, big_endian>::include_section_group(
                                             member_shdr.get_sh_size());
        }
       else
-        {
-          (*omit)[shndx] = true;
+       {
+         (*omit)[shndx] = true;
 
          if (is_comdat)
-            {
+           {
              Relobj* kept_object = kept_section->object();
              if (kept_section->is_comdat())
                {
@@ -987,8 +988,8 @@ Sized_relobj_file<size, big_endian>::include_section_group(
                    this->set_kept_comdat_section(shndx, kept_object,
                                                  kept_section->shndx());
                }
-            }
-        }
+           }
+       }
     }
 
   if (relocate_group)
@@ -1162,15 +1163,15 @@ Sized_relobj_file<size, big_endian>::layout_eh_frame_section(
 // Lay out the input sections.  We walk through the sections and check
 // whether they should be included in the link.  If they should, we
 // pass them to the Layout object, which will return an output section
-// and an offset.  
-// During garbage collection (--gc-sections) and identical code folding 
-// (--icf), this function is called twice.  When it is called the first 
+// and an offset.
+// During garbage collection (--gc-sections) and identical code folding
+// (--icf), this function is called twice.  When it is called the first
 // time, it is for setting up some sections as roots to a work-list for
-// --gc-sections and to do comdat processing.  Actual layout happens the 
-// second time around after all the relevant sections have been determined.  
-// The first time, is_worklist_ready or is_icf_ready is false. It is then 
-// set to true after the garbage collection worklist or identical code 
-// folding is processed and the relevant sections to be kept are 
+// --gc-sections and to do comdat processing.  Actual layout happens the
+// second time around after all the relevant sections have been determined.
+// The first time, is_worklist_ready or is_icf_ready is false. It is then
+// set to true after the garbage collection worklist or identical code
+// folding is processed and the relevant sections to be kept are
 // determined.  Then, this function is called again to layout the sections.
 
 template<int size, bool big_endian>
@@ -1180,18 +1181,18 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
                                               Read_symbols_data* sd)
 {
   const unsigned int shnum = this->shnum();
-  bool is_gc_pass_one = ((parameters->options().gc_sections() 
-                          && !symtab->gc()->is_worklist_ready())
-                         || (parameters->options().icf_enabled()
-                             && !symtab->icf()->is_icf_ready()));
-  bool is_gc_pass_two = ((parameters->options().gc_sections() 
-                          && symtab->gc()->is_worklist_ready())
-                         || (parameters->options().icf_enabled()
-                             && symtab->icf()->is_icf_ready()));
+  bool is_gc_pass_one = ((parameters->options().gc_sections()
+                         && !symtab->gc()->is_worklist_ready())
+                        || (parameters->options().icf_enabled()
+                            && !symtab->icf()->is_icf_ready()));
+
+  bool is_gc_pass_two = ((parameters->options().gc_sections()
+                         && symtab->gc()->is_worklist_ready())
+                        || (parameters->options().icf_enabled()
+                            && symtab->icf()->is_icf_ready()));
 
   bool is_gc_or_icf = (parameters->options().gc_sections()
-                       || parameters->options().icf_enabled()); 
+                      || parameters->options().icf_enabled());
 
   // Both is_gc_pass_one and is_gc_pass_two should not be true.
   gold_assert(!(is_gc_pass_one  && is_gc_pass_two));
@@ -1201,8 +1202,8 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
   Symbols_data* gc_sd = NULL;
   if (is_gc_pass_one)
     {
-      // During garbage collection save the symbols data to use it when 
-      // re-entering this function.   
+      // During garbage collection save the symbols data to use it when
+      // re-entering this function.
       gc_sd = new Symbols_data;
       this->copy_symbols_data(gc_sd, sd, This::shdr_size * shnum);
       this->set_symbols_data(gc_sd);
@@ -1218,7 +1219,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
   section_size_type symbols_size;
   const unsigned char* symbol_names_data = NULL;
   section_size_type symbol_names_size;
+
   if (is_gc_or_icf)
     {
       section_headers_data = gc_sd->section_headers_data;
@@ -1233,10 +1234,10 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       section_headers_data = sd->section_headers->data();
       section_names_size = sd->section_names_size;
       if (sd->symbols != NULL)
-        symbols_data = sd->symbols->data();
+       symbols_data = sd->symbols->data();
       symbols_size = sd->symbols_size;
       if (sd->symbol_names != NULL)
-        symbol_names_data = sd->symbol_names->data();
+       symbol_names_data = sd->symbol_names->data();
       symbol_names_size = sd->symbol_names_size;
     }
 
@@ -1245,9 +1246,9 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
   const unsigned char* pshdrs;
 
   // Get the section names.
-  const unsigned char* pnamesu = (is_gc_or_icf) 
-                                 ? gc_sd->section_names_data
-                                 : sd->section_names->data();
+  const unsigned char* pnamesu = (is_gc_or_icf)
+                                ? gc_sd->section_names_data
+                                : sd->section_names->data();
 
   const char* pnames = reinterpret_cast<const char*>(pnamesu);
 
@@ -1271,7 +1272,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
 
       // Count the number of sections whose layout will be deferred.
       if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
-        ++num_sections_to_defer;
+       ++num_sections_to_defer;
 
       unsigned int sh_type = shdr.get_sh_type();
       if (sh_type == elfcpp::SHT_REL || sh_type == elfcpp::SHT_RELA)
@@ -1308,12 +1309,12 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
   if (this->input_file()->just_symbols())
     {
       if (!is_gc_pass_two)
-        {
-          delete sd->section_headers;
-          sd->section_headers = NULL;
-          delete sd->section_names;
-          sd->section_names = NULL;
-        }
+       {
+         delete sd->section_headers;
+         sd->section_headers = NULL;
+         delete sd->section_names;
+         sd->section_names = NULL;
+       }
       return;
     }
 
@@ -1360,22 +1361,22 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       const char* name = pnames + shdr.get_sh_name();
 
       if (!is_gc_pass_two)
-        { 
-          if (this->handle_gnu_warning_section(name, i, symtab))
-            { 
-             if (!relocatable && !parameters->options().shared())
-               omit[i] = true;
+       {
+         if (this->handle_gnu_warning_section(name, i, symtab))
+           {
+             if (!relocatable && !parameters->options().shared())
+               omit[i] = true;
            }
 
-          // The .note.GNU-stack section is special.  It gives the
-          // protection flags that this object file requires for the stack
-          // in memory.
-          if (strcmp(name, ".note.GNU-stack") == 0)
-            {
+         // The .note.GNU-stack section is special.  It gives the
+         // protection flags that this object file requires for the stack
+         // in memory.
+         if (strcmp(name, ".note.GNU-stack") == 0)
+           {
              seen_gnu_stack = true;
              gnu_stack_flags |= shdr.get_sh_flags();
              omit[i] = true;
-            }
+           }
 
          // The .note.GNU-split-stack section is also special.  It
          // indicates that the object was compiled with
@@ -1392,23 +1393,23 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
              omit[i] = true;
            }
 
-          bool discard = omit[i];
-          if (!discard)
-            {
+         bool discard = omit[i];
+         if (!discard)
+           {
              if (shdr.get_sh_type() == elfcpp::SHT_GROUP)
-               {
-                 if (!this->include_section_group(symtab, layout, i, name, 
-                                                   shdrs, pnames, 
-                                                   section_names_size,
-                                                  &omit))
+               {
+                 if (!this->include_section_group(symtab, layout, i, name,
+                                                  shdrs, pnames,
+                                                  section_names_size,
+                                                  &omit))
+                   discard = true;
+               }
+             else if ((shdr.get_sh_flags() & elfcpp::SHF_GROUP) == 0
+                      && Layout::is_linkonce(name))
+               {
+                 if (!this->include_linkonce_section(layout, i, name, shdr))
                    discard = true;
-               }
-              else if ((shdr.get_sh_flags() & elfcpp::SHF_GROUP) == 0
-                       && Layout::is_linkonce(name))
-               {
-                 if (!this->include_linkonce_section(layout, i, name, shdr))
-                   discard = true;
-               }
+               }
            }
 
          // Add the section to the incremental inputs layout.
@@ -1424,32 +1425,32 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
              incremental_inputs->report_input_section(this, i, name, sh_size);
            }
 
-          if (discard)
-            {
+         if (discard)
+           {
              // Do not include this section in the link.
              out_sections[i] = NULL;
-              out_section_offsets[i] = invalid_address;
+             out_section_offsets[i] = invalid_address;
              continue;
-            }
-        }
+           }
+       }
+
       if (is_gc_pass_one && parameters->options().gc_sections())
-        {
-          if (this->is_section_name_included(name)
-              || shdr.get_sh_type() == elfcpp::SHT_INIT_ARRAY 
-              || shdr.get_sh_type() == elfcpp::SHT_FINI_ARRAY)
-            {
-              symtab->gc()->worklist().push(Section_id(this, i)); 
-            }
-          // If the section name XXX can be represented as a C identifier
-          // it cannot be discarded if there are references to
-          // __start_XXX and __stop_XXX symbols.  These need to be
-          // specially handled.
-          if (is_cident(name))
-            {
-              symtab->gc()->add_cident_section(name, Section_id(this, i));
-            }
-        }
+       {
+         if (this->is_section_name_included(name)
+             || shdr.get_sh_type() == elfcpp::SHT_INIT_ARRAY
+             || shdr.get_sh_type() == elfcpp::SHT_FINI_ARRAY)
+           {
+             symtab->gc()->worklist().push(Section_id(this, i));
+           }
+         // If the section name XXX can be represented as a C identifier
+         // it cannot be discarded if there are references to
+         // __start_XXX and __stop_XXX symbols.  These need to be
+         // specially handled.
+         if (is_cident(name))
+           {
+             symtab->gc()->add_cident_section(name, Section_id(this, i));
+           }
+       }
 
       // When doing a relocatable link we are going to copy input
       // reloc sections into the output.  We only want to copy the
@@ -1475,115 +1476,115 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       // determine which sections are being discarded, and discard the
       // corresponding information.
       if (!relocatable
-          && strcmp(name, ".eh_frame") == 0
-          && this->check_eh_frame_flags(&shdr))
-        {
-          if (is_gc_pass_one)
-            {
-              out_sections[i] = reinterpret_cast<Output_section*>(1);
-              out_section_offsets[i] = invalid_address;
-            }
-          else if (should_defer_layout)
+         && strcmp(name, ".eh_frame") == 0
+         && this->check_eh_frame_flags(&shdr))
+       {
+         if (is_gc_pass_one)
+           {
+             out_sections[i] = reinterpret_cast<Output_section*>(1);
+             out_section_offsets[i] = invalid_address;
+           }
+         else if (should_defer_layout)
            this->deferred_layout_.push_back(Deferred_layout(i, name,
                                                             pshdrs,
                                                             reloc_shndx[i],
                                                             reloc_type[i]));
          else
-            eh_frame_sections.push_back(i);
-          continue;
-        }
+           eh_frame_sections.push_back(i);
+         continue;
+       }
 
       if (is_gc_pass_two && parameters->options().gc_sections())
-        {
-          // This is executed during the second pass of garbage 
-          // collection. do_layout has been called before and some 
-          // sections have been already discarded. Simply ignore 
-          // such sections this time around.
-          if (out_sections[i] == NULL)
-            {
-              gold_assert(out_section_offsets[i] == invalid_address);
-              continue; 
-            }
-          if (((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0)
-              && symtab->gc()->is_section_garbage(this, i))
-              {
-                if (parameters->options().print_gc_sections())
-                  gold_info(_("%s: removing unused section from '%s'" 
-                              " in file '%s'"),
-                            program_name, this->section_name(i).c_str(), 
-                            this->name().c_str());
-                out_sections[i] = NULL;
-                out_section_offsets[i] = invalid_address;
-                continue;
-              }
-        }
+       {
+         // This is executed during the second pass of garbage
+         // collection. do_layout has been called before and some
+         // sections have been already discarded. Simply ignore
+         // such sections this time around.
+         if (out_sections[i] == NULL)
+           {
+             gold_assert(out_section_offsets[i] == invalid_address);
+             continue;
+           }
+         if (((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0)
+             && symtab->gc()->is_section_garbage(this, i))
+             {
+               if (parameters->options().print_gc_sections())
+                 gold_info(_("%s: removing unused section from '%s'"
+                             " in file '%s'"),
+                           program_name, this->section_name(i).c_str(),
+                           this->name().c_str());
+               out_sections[i] = NULL;
+               out_section_offsets[i] = invalid_address;
+               continue;
+             }
+       }
 
       if (is_gc_pass_two && parameters->options().icf_enabled())
-        {
-          if (out_sections[i] == NULL)
-            {
-              gold_assert(out_section_offsets[i] == invalid_address);
-              continue;
-            }
-          if (((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0)
-              && symtab->icf()->is_section_folded(this, i))
-              {
-                if (parameters->options().print_icf_sections())
-                  {
-                    Section_id folded =
-                                symtab->icf()->get_folded_section(this, i);
-                    Relobj* folded_obj =
-                                reinterpret_cast<Relobj*>(folded.first);
-                    gold_info(_("%s: ICF folding section '%s' in file '%s'"
-                                "into '%s' in file '%s'"),
-                              program_name, this->section_name(i).c_str(),
-                              this->name().c_str(),
-                              folded_obj->section_name(folded.second).c_str(),
-                              folded_obj->name().c_str());
-                  }
-                out_sections[i] = NULL;
-                out_section_offsets[i] = invalid_address;
-                continue;
-              }
-        }
+       {
+         if (out_sections[i] == NULL)
+           {
+             gold_assert(out_section_offsets[i] == invalid_address);
+             continue;
+           }
+         if (((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0)
+             && symtab->icf()->is_section_folded(this, i))
+             {
+               if (parameters->options().print_icf_sections())
+                 {
+                   Section_id folded =
+                               symtab->icf()->get_folded_section(this, i);
+                   Relobj* folded_obj =
+                               reinterpret_cast<Relobj*>(folded.first);
+                   gold_info(_("%s: ICF folding section '%s' in file '%s'"
+                               "into '%s' in file '%s'"),
+                             program_name, this->section_name(i).c_str(),
+                             this->name().c_str(),
+                             folded_obj->section_name(folded.second).c_str(),
+                             folded_obj->name().c_str());
+                 }
+               out_sections[i] = NULL;
+               out_section_offsets[i] = invalid_address;
+               continue;
+             }
+       }
 
       // Defer layout here if input files are claimed by plugins.  When gc
       // is turned on this function is called twice.  For the second call
       // should_defer_layout should be false.
       if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
-        {
-          gold_assert(!is_gc_pass_two);
-          this->deferred_layout_.push_back(Deferred_layout(i, name, 
-                                                           pshdrs,
-                                                           reloc_shndx[i],
-                                                           reloc_type[i]));
-          // Put dummy values here; real values will be supplied by
-          // do_layout_deferred_sections.
-          out_sections[i] = reinterpret_cast<Output_section*>(2);
-          out_section_offsets[i] = invalid_address;
-          continue;
-        }
+       {
+         gold_assert(!is_gc_pass_two);
+         this->deferred_layout_.push_back(Deferred_layout(i, name,
+                                                          pshdrs,
+                                                          reloc_shndx[i],
+                                                          reloc_type[i]));
+         // Put dummy values here; real values will be supplied by
+         // do_layout_deferred_sections.
+         out_sections[i] = reinterpret_cast<Output_section*>(2);
+         out_section_offsets[i] = invalid_address;
+         continue;
+       }
 
       // During gc_pass_two if a section that was previously deferred is
       // found, do not layout the section as layout_deferred_sections will
       // do it later from gold.cc.
-      if (is_gc_pass_two 
-          && (out_sections[i] == reinterpret_cast<Output_section*>(2)))
-        continue;
+      if (is_gc_pass_two
+         && (out_sections[i] == reinterpret_cast<Output_section*>(2)))
+       continue;
 
       if (is_gc_pass_one)
-        {
-          // This is during garbage collection. The out_sections are 
-          // assigned in the second call to this function. 
-          out_sections[i] = reinterpret_cast<Output_section*>(1);
-          out_section_offsets[i] = invalid_address;
-        }
+       {
+         // This is during garbage collection. The out_sections are
+         // assigned in the second call to this function.
+         out_sections[i] = reinterpret_cast<Output_section*>(1);
+         out_section_offsets[i] = invalid_address;
+       }
       else
-        {
-          // When garbage collection is switched on the actual layout
-          // only happens in the second call.
-          this->layout_section(layout, i, name, shdr, reloc_shndx[i],
-                               reloc_type[i]);
+       {
+         // When garbage collection is switched on the actual layout
+         // only happens in the second call.
+         this->layout_section(layout, i, name, shdr, reloc_shndx[i],
+                              reloc_type[i]);
 
          // When generating a .gdb_index section, we do additional
          // processing of .debug_info and .debug_types sections after all
@@ -1599,15 +1600,15 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
                       || strcmp(name, ".zdebug_types") == 0)
                debug_types_sections.push_back(i);
            }
-        }
+       }
     }
 
   if (!is_gc_pass_two)
     layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags, this);
 
   // When doing a relocatable link handle the reloc sections at the
-  // end.  Garbage collection  and Identical Code Folding is not 
-  // turned on for relocatable code. 
+  // end.  Garbage collection  and Identical Code Folding is not
+  // turned on for relocatable code.
   if (emit_relocs)
     this->size_relocatable_relocs();
 
@@ -1631,20 +1632,20 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
 
       Output_section* data_section = out_sections[data_shndx];
       if (data_section == reinterpret_cast<Output_section*>(2))
-        {
-          // The layout for the data section was deferred, so we need
-          // to defer the relocation section, too.
+       {
+         // The layout for the data section was deferred, so we need
+         // to defer the relocation section, too.
          const char* name = pnames + shdr.get_sh_name();
-          this->deferred_layout_relocs_.push_back(
-              Deferred_layout(i, name, pshdr, 0, elfcpp::SHT_NULL));
+         this->deferred_layout_relocs_.push_back(
+             Deferred_layout(i, name, pshdr, 0, elfcpp::SHT_NULL));
          out_sections[i] = reinterpret_cast<Output_section*>(2);
-          out_section_offsets[i] = invalid_address;
-          continue;
-        }
+         out_section_offsets[i] = invalid_address;
+         continue;
+       }
       if (data_section == NULL)
        {
          out_sections[i] = NULL;
-          out_section_offsets[i] = invalid_address;
+         out_section_offsets[i] = invalid_address;
          continue;
        }
 
@@ -1736,7 +1737,7 @@ Sized_relobj_file<size, big_endian>::do_layout_deferred_sections(Layout* layout)
       // If the section is not included, it is because the garbage collector
       // decided it is not needed.  Avoid reverting that decision.
       if (!this->is_section_included(deferred->shndx_))
-        continue;
+       continue;
 
       if (parameters->options().relocatable()
          || deferred->name_ != ".eh_frame"
@@ -1780,7 +1781,7 @@ Sized_relobj_file<size, big_endian>::do_layout_deferred_sections(Layout* layout)
       if (data_section == NULL)
        {
          out_sections[shndx] = NULL;
-          out_section_offsets[shndx] = invalid_address;
+         out_section_offsets[shndx] = invalid_address;
          continue;
        }
 
@@ -1855,7 +1856,7 @@ Sized_relobj_file<size, big_endian>::do_should_include_member(
       sd->symbols->data() + sd->external_symbols_offset;
   const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
   size_t symcount = ((sd->symbols_size - sd->external_symbols_offset)
-                         / sym_size);
+                        / sym_size);
 
   const unsigned char* p = syms;
 
@@ -1901,7 +1902,7 @@ Sized_relobj_file<size, big_endian>::do_for_all_global_symbols(
       sd->symbols->data() + sd->external_symbols_offset;
   const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
   size_t symcount = ((sd->symbols_size - sd->external_symbols_offset)
-                     / sym_size);
+                    / sym_size);
   const unsigned char* p = syms;
 
   for (size_t i = 0; i < symcount; ++i, p += sym_size)
@@ -2026,16 +2027,16 @@ Sized_relobj_file<size, big_endian>::do_count_local_symbols(Stringpool* pool,
 
       if ((shndx < shnum && out_sections[shndx] == NULL)
          || shndx == this->discarded_eh_frame_shndx_)
-        {
+       {
          lv.set_no_output_symtab_entry();
-          gold_assert(!lv.needs_output_dynsym_entry());
-          continue;
-        }
+         gold_assert(!lv.needs_output_dynsym_entry());
+         continue;
+       }
 
       if (sym.get_st_type() == elfcpp::STT_SECTION)
        {
          lv.set_no_output_symtab_entry();
-          gold_assert(!lv.needs_output_dynsym_entry());
+         gold_assert(!lv.needs_output_dynsym_entry());
          continue;
        }
 
@@ -2052,10 +2053,10 @@ Sized_relobj_file<size, big_endian>::do_count_local_symbols(Stringpool* pool,
 
       // If needed, add the symbol to the dynamic symbol table string pool.
       if (lv.needs_output_dynsym_entry())
-        {
-          dynpool->add(name, true, NULL);
-          ++dyncount;
-        }
+       {
+         dynpool->add(name, true, NULL);
+         ++dyncount;
+       }
 
       if (strip_all
          || (discard_all && lv.may_be_discarded_from_output_symtab()))
@@ -2089,10 +2090,10 @@ Sized_relobj_file<size, big_endian>::do_count_local_symbols(Stringpool* pool,
       // Discard the local symbol if -retain_symbols_file is specified
       // and the local symbol is not in that file.
       if (!parameters->options().should_retain_symbol(name))
-        {
-          lv.set_no_output_symtab_entry();
-          continue;
-        }
+       {
+         lv.set_no_output_symtab_entry();
+         continue;
+       }
 
       // Add the symbol to the symbol table string pool.
       pool->add(name, true, NULL);
@@ -2122,9 +2123,9 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
 
   bool is_ordinary;
   unsigned int shndx = lv_in->input_shndx(&is_ordinary);
-  
+
   // Set the output symbol value.
-  
+
   if (!is_ordinary)
     {
       if (shndx == elfcpp::SHN_ABS || Symbol::is_common_shndx(shndx))
@@ -2146,7 +2147,7 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
          lv_out->set_output_value(0);
          return This::CFLV_ERROR;
        }
-      
+
       Output_section* os = out_sections[shndx];
       Address secoffset = out_offsets[shndx];
       if (symtab->is_section_folded(this, shndx))
@@ -2161,7 +2162,7 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
          os = folded_obj->output_section(folded.second);
          gold_assert(os != NULL);
          secoffset = folded_obj->get_output_section_offset(folded.second);
-         
+
          // This could be a relaxed input section.
          if (secoffset == invalid_address)
            {
@@ -2171,7 +2172,7 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
              secoffset = relaxed_section->address() - os->address();
            }
        }
-      
+
       if (os == NULL)
        {
          // This local symbol belongs to a section we are discarding.
@@ -2183,7 +2184,7 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
       else if (secoffset == invalid_address)
        {
          uint64_t start;
-         
+
          // This is a SHF_MERGE section or one which otherwise
          // requires special handling.
          if (shndx == this->discarded_eh_frame_shndx_)
@@ -2336,10 +2337,10 @@ Sized_relobj_file<size, big_endian>::do_set_local_dynsym_indexes(
     {
       Symbol_value<size>& lv(this->local_values_[i]);
       if (lv.needs_output_dynsym_entry())
-        {
-          lv.set_output_dynsym_index(index);
-          ++index;
-        }
+       {
+         lv.set_output_dynsym_index(index);
+         ++index;
+       }
     }
   return index;
 }
@@ -2368,12 +2369,12 @@ Sized_relobj_file<size, big_endian>::do_section_flags(unsigned int shndx)
   if (sd != NULL)
     {
       const unsigned char* pshdrs = sd->section_headers_data
-                                    + This::shdr_size * shndx;
+                                   + This::shdr_size * shndx;
       typename This::Shdr shdr(pshdrs);
-      return shdr.get_sh_flags(); 
+      return shdr.get_sh_flags();
     }
   // If sd is NULL, read the section header from the file.
-  return this->elf_file_.section_flags(shndx); 
+  return this->elf_file_.section_flags(shndx);
 }
 
 // Get the section's ent size from Symbols_data.  Called by get_section_contents
@@ -2387,9 +2388,9 @@ Sized_relobj_file<size, big_endian>::do_section_entsize(unsigned int shndx)
   gold_assert(sd != NULL);
 
   const unsigned char* pshdrs = sd->section_headers_data
-                                + This::shdr_size * shndx;
+                               + This::shdr_size * shndx;
   typename This::Shdr shdr(pshdrs);
-  return shdr.get_sh_entsize(); 
+  return shdr.get_sh_entsize();
 }
 
 // Write out the local symbols.
@@ -2454,7 +2455,7 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
   unsigned char* dyn_oview = NULL;
   if (dyn_output_size > 0)
     dyn_oview = of->get_output_view(this->local_dynsym_offset_,
-                                    dyn_output_size);
+                                   dyn_output_size);
 
   const Output_sections out_sections(this->output_sections());
 
@@ -2490,38 +2491,38 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
 
       // Write the symbol to the output symbol table.
       if (lv.has_output_symtab_entry())
-        {
-          elfcpp::Sym_write<size, big_endian> osym(ov);
-
-          gold_assert(isym.get_st_name() < strtab_size);
-          const char* name = pnames + isym.get_st_name();
-          osym.put_st_name(sympool->get_offset(name));
-          osym.put_st_value(this->local_values_[i].value(this, 0));
-          osym.put_st_size(isym.get_st_size());
-          osym.put_st_info(isym.get_st_info());
-          osym.put_st_other(isym.get_st_other());
-          osym.put_st_shndx(st_shndx);
-
-          ov += sym_size;
-        }
+       {
+         elfcpp::Sym_write<size, big_endian> osym(ov);
+
+         gold_assert(isym.get_st_name() < strtab_size);
+         const char* name = pnames + isym.get_st_name();
+         osym.put_st_name(sympool->get_offset(name));
+         osym.put_st_value(this->local_values_[i].value(this, 0));
+         osym.put_st_size(isym.get_st_size());
+         osym.put_st_info(isym.get_st_info());
+         osym.put_st_other(isym.get_st_other());
+         osym.put_st_shndx(st_shndx);
+
+         ov += sym_size;
+       }
 
       // Write the symbol to the output dynamic symbol table.
       if (lv.has_output_dynsym_entry())
-        {
-          gold_assert(dyn_ov < dyn_oview + dyn_output_size);
-          elfcpp::Sym_write<size, big_endian> osym(dyn_ov);
-
-          gold_assert(isym.get_st_name() < strtab_size);
-          const char* name = pnames + isym.get_st_name();
-          osym.put_st_name(dynpool->get_offset(name));
-          osym.put_st_value(this->local_values_[i].value(this, 0));
-          osym.put_st_size(isym.get_st_size());
-          osym.put_st_info(isym.get_st_info());
-          osym.put_st_other(isym.get_st_other());
-          osym.put_st_shndx(st_shndx);
-
-          dyn_ov += sym_size;
-        }
+       {
+         gold_assert(dyn_ov < dyn_oview + dyn_output_size);
+         elfcpp::Sym_write<size, big_endian> osym(dyn_ov);
+
+         gold_assert(isym.get_st_name() < strtab_size);
+         const char* name = pnames + isym.get_st_name();
+         osym.put_st_name(dynpool->get_offset(name));
+         osym.put_st_value(this->local_values_[i].value(this, 0));
+         osym.put_st_size(isym.get_st_size());
+         osym.put_st_info(isym.get_st_info());
+         osym.put_st_other(isym.get_st_other());
+         osym.put_st_shndx(st_shndx);
+
+         dyn_ov += sym_size;
+       }
     }
 
 
@@ -2536,7 +2537,7 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
     {
       gold_assert(dyn_ov - dyn_oview == dyn_output_size);
       of->write_output_view(this->local_dynsym_offset_, dyn_output_size,
-                            dyn_oview);
+                           dyn_oview);
     }
 }
 
@@ -2591,26 +2592,26 @@ Sized_relobj_file<size, big_endian>::get_symbol_location_info(
          && static_cast<off_t>(sym.get_st_value()) <= offset
          && (static_cast<off_t>(sym.get_st_value() + sym.get_st_size())
              > offset))
-        {
-          if (sym.get_st_name() > names_size)
+       {
+         if (sym.get_st_name() > names_size)
            info->enclosing_symbol_name = "(invalid)";
          else
-            {
-              info->enclosing_symbol_name = symbol_names + sym.get_st_name();
-              if (parameters->options().do_demangle())
-                {
-                  char* demangled_name = cplus_demangle(
-                      info->enclosing_symbol_name.c_str(),
-                      DMGL_ANSI | DMGL_PARAMS);
-                  if (demangled_name != NULL)
-                    {
-                      info->enclosing_symbol_name.assign(demangled_name);
-                      free(demangled_name);
-                    }
-                }
-            }
+           {
+             info->enclosing_symbol_name = symbol_names + sym.get_st_name();
+             if (parameters->options().do_demangle())
+               {
+                 char* demangled_name = cplus_demangle(
+                     info->enclosing_symbol_name.c_str(),
+                     DMGL_ANSI | DMGL_PARAMS);
+                 if (demangled_name != NULL)
+                   {
+                     info->enclosing_symbol_name.assign(demangled_name);
+                     free(demangled_name);
+                   }
+               }
+           }
          return true;
-        }
+       }
     }
 
   return false;
@@ -2738,10 +2739,10 @@ Sized_relobj_file<size, big_endian>::do_discard_decompressed_sections()
        ++p)
     {
       if (p->second.contents != NULL)
-        {
-          delete[] p->second.contents;
-          p->second.contents = NULL;
-        }
+       {
+         delete[] p->second.contents;
+         p->second.contents = NULL;
+       }
     }
 }
 
@@ -2934,7 +2935,8 @@ make_elf_sized_object(const std::string& name, Input_file* input_file,
                      off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr,
                      bool* punconfigured)
 {
-  Target* target = select_target(ehdr.get_e_machine(), size, big_endian,
+  Target* target = select_target(input_file, offset,
+                                ehdr.get_e_machine(), size, big_endian,
                                 ehdr.get_e_ident()[elfcpp::EI_OSABI],
                                 ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]);
   if (target == NULL)
@@ -2994,7 +2996,7 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
   bool big_endian = false;
   int size = 0;
   if (!elfcpp::Elf_recognizer::is_valid_header(p, bytes, &size,
-                                               &big_endian, &error))
+                                              &big_endian, &error))
     {
       gold_error(_("%s: %s"), name.c_str(), error.c_str());
       return NULL;
index 7fc5730ee732134382ed61a8afa6f73855dddcc4..d69b62c1430149f7ee9c96869bc7b5d8d619028f 100644 (file)
@@ -1,6 +1,7 @@
 // parameters.cc -- general parameters for a link using gold
 
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -212,7 +213,7 @@ Parameters::check_target_endianness()
          gold_assert(endianness == General_options::ENDIANNESS_LITTLE);
          big_endian = false;;
        }
-      
+
       if (this->target().is_big_endian() != big_endian)
        gold_error(_("input file does not match -EB/EL option"));
     }
@@ -352,7 +353,8 @@ parameters_force_valid_target()
   else
     is_big_endian = GOLD_DEFAULT_BIG_ENDIAN;
 
-  Target* target = select_target(elfcpp::GOLD_DEFAULT_MACHINE,
+  Target* target = select_target(NULL, 0,
+                                elfcpp::GOLD_DEFAULT_MACHINE,
                                 GOLD_DEFAULT_SIZE,
                                 is_big_endian,
                                 elfcpp::GOLD_DEFAULT_OSABI,
index b4433047906fda032d3a1a0146f3929bd3688486..1bc9dfa780dff81f2ff84fce1ef3d5fc47fbc059 100644 (file)
@@ -1,6 +1,6 @@
 // powerpc.cc -- powerpc target support for gold.
 
-// Copyright 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
 // Written by David S. Miller <davem@davemloft.net>
 //        and David Edelsohn <edelsohn@gnu.org>
 
@@ -62,20 +62,20 @@ class Target_powerpc : public Sized_target<size, big_endian>
   {
   }
 
-  // Process the relocations to determine unreferenced sections for 
+  // Process the relocations to determine unreferenced sections for
   // garbage collection.
   void
   gc_process_relocs(Symbol_table* symtab,
-                   Layout* layout,
-                   Sized_relobj_file<size, big_endian>* object,
-                   unsigned int data_shndx,
-                   unsigned int sh_type,
-                   const unsigned char* prelocs,
-                   size_t reloc_count,
-                   Output_section* output_section,
-                   bool needs_special_offset_handling,
-                   size_t local_symbol_count,
-                   const unsigned char* plocal_symbols);
+                   Layout* layout,
+                   Sized_relobj_file<size, big_endian>* object,
+                   unsigned int data_shndx,
+                   unsigned int sh_type,
+                   const unsigned char* prelocs,
+                   size_t reloc_count,
+                   Output_section* output_section,
+                   bool needs_special_offset_handling,
+                   size_t local_symbol_count,
+                   const unsigned char* plocal_symbols);
 
   // Scan the relocations to look for symbol adjustments.
   void
@@ -210,21 +210,21 @@ class Target_powerpc : public Sized_target<size, big_endian>
     inline bool
     local_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
                                        Target_powerpc* ,
-                                       Sized_relobj_file<size, big_endian>* ,
-                                       unsigned int ,
-                                       Output_section* ,
-                                       const elfcpp::Rela<size, big_endian>& ,
+                                       Sized_relobj_file<size, big_endian>* ,
                                        unsigned int ,
-                                       const elfcpp::Sym<size, big_endian>&)
+                                       Output_section* ,
+                                       const elfcpp::Rela<size, big_endian>& ,
+                                       unsigned int ,
+                                       const elfcpp::Sym<size, big_endian>&)
     { return false; }
 
     inline bool
     global_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
                                         Target_powerpc* ,
-                                        Sized_relobj_file<size, big_endian>* ,
-                                        unsigned int ,
-                                        Output_section* ,
-                                        const elfcpp::Rela<size,
+                                        Sized_relobj_file<size, big_endian>* ,
+                                        unsigned int ,
+                                        Output_section* ,
+                                        const elfcpp::Rela<size,
                                                            big_endian>& ,
                                         unsigned int , Symbol*)
     { return false; }
@@ -270,7 +270,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
     inline void
     relocate_tls(const Relocate_info<size, big_endian>*,
                 Target_powerpc* target,
-                 size_t relnum, const elfcpp::Rela<size, big_endian>&,
+                size_t relnum, const elfcpp::Rela<size, big_endian>&,
                 unsigned int r_type, const Sized_symbol<size>*,
                 const Symbol_value<size>*,
                 unsigned char*,
@@ -330,7 +330,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
   // Copy a relocation against a global symbol.
   void
   copy_reloc(Symbol_table* symtab, Layout* layout,
-             Sized_relobj_file<size, big_endian>* object,
+            Sized_relobj_file<size, big_endian>* object,
             unsigned int shndx, Output_section* output_section,
             Symbol* sym, const elfcpp::Rela<size, big_endian>& reloc)
   {
@@ -389,6 +389,8 @@ Target::Target_info Target_powerpc<32, true>::powerpc_info =
   0x10000000,          // default_text_segment_address
   64 * 1024,           // abi_pagesize (overridable by -z max-page-size)
   4 * 1024,            // common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
   elfcpp::SHN_UNDEF,   // small_common_shndx
   elfcpp::SHN_UNDEF,   // large_common_shndx
   0,                   // small_common_section_flags
@@ -413,6 +415,8 @@ Target::Target_info Target_powerpc<32, false>::powerpc_info =
   0x10000000,          // default_text_segment_address
   64 * 1024,           // abi_pagesize (overridable by -z max-page-size)
   4 * 1024,            // common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
   elfcpp::SHN_UNDEF,   // small_common_shndx
   elfcpp::SHN_UNDEF,   // large_common_shndx
   0,                   // small_common_section_flags
@@ -437,6 +441,8 @@ Target::Target_info Target_powerpc<64, true>::powerpc_info =
   0x10000000,          // default_text_segment_address
   64 * 1024,           // abi_pagesize (overridable by -z max-page-size)
   8 * 1024,            // common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
   elfcpp::SHN_UNDEF,   // small_common_shndx
   elfcpp::SHN_UNDEF,   // large_common_shndx
   0,                   // small_common_section_flags
@@ -461,6 +467,8 @@ Target::Target_info Target_powerpc<64, false>::powerpc_info =
   0x10000000,          // default_text_segment_address
   64 * 1024,           // abi_pagesize (overridable by -z max-page-size)
   8 * 1024,            // common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
   elfcpp::SHN_UNDEF,   // small_common_shndx
   elfcpp::SHN_UNDEF,   // large_common_shndx
   0,                   // small_common_section_flags
@@ -952,7 +960,7 @@ static const unsigned int addis_r12_r2    = 0x3d820000;  /* addis %r12,%r2,xxx@h
 static const unsigned int std_r2_40r1     = 0xf8410028;  /* std   %r2,40(%r1)         */
 static const unsigned int ld_r11_0r12     = 0xe96c0000;  /* ld    %r11,xxx+0@l(%r12)  */
 static const unsigned int ld_r2_0r12      = 0xe84c0000;  /* ld    %r2,xxx+8@l(%r12)   */
-                                                         /* ld    %r11,xxx+16@l(%r12) */
+                                                        /* ld    %r11,xxx+16@l(%r12) */
 
 
 // Write out the PLT.
@@ -1311,27 +1319,27 @@ Target_powerpc<size, big_endian>::Scan::local(
       // executable), we need to create a dynamic relocation for
       // this location.
       if (parameters->options().output_is_position_independent())
-        {
-          Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+       {
+         Reloc_section* rela_dyn = target->rela_dyn_section(layout);
 
          check_non_pic(object, r_type);
-          if (lsym.get_st_type() != elfcpp::STT_SECTION)
-            {
-              unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-              rela_dyn->add_local(object, r_sym, r_type, output_section,
+         if (lsym.get_st_type() != elfcpp::STT_SECTION)
+           {
+             unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+             rela_dyn->add_local(object, r_sym, r_type, output_section,
                                  data_shndx, reloc.get_r_offset(),
                                  reloc.get_r_addend());
-            }
-          else
-            {
+           }
+         else
+           {
              unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-              gold_assert(lsym.get_st_value() == 0);
-              rela_dyn->add_local_relative(object, r_sym, r_type,
+             gold_assert(lsym.get_st_value() == 0);
+             rela_dyn->add_local_relative(object, r_sym, r_type,
                                           output_section, data_shndx,
                                           reloc.get_r_offset(),
                                           reloc.get_r_addend(), false);
-            }
-        }
+           }
+       }
       break;
 
     case elfcpp::R_POWERPC_REL24:
@@ -1352,8 +1360,8 @@ Target_powerpc<size, big_endian>::Scan::local(
     case elfcpp::R_PPC64_TOC16_DS:
     case elfcpp::R_PPC64_TOC16_LO_DS:
       {
-        // The symbol requires a GOT entry.
-        Output_data_got<size, big_endian>* got;
+       // The symbol requires a GOT entry.
+       Output_data_got<size, big_endian>* got;
        unsigned int r_sym;
 
        got = target->got_section(symtab, layout);
@@ -1374,7 +1382,7 @@ Target_powerpc<size, big_endian>::Scan::local(
                                             elfcpp::R_POWERPC_RELATIVE,
                                             got, off, 0, false);
              }
-          }
+         }
        else
          got->add_local(object, r_sym, GOT_TYPE_STANDARD);
       }
@@ -1446,8 +1454,8 @@ Target_powerpc<size, big_endian>::Scan::global(
       // if the symbol is defined in the output file and is protected
       // or hidden.
       if (gsym->is_defined()
-          && !gsym->is_from_dynobj()
-          && !gsym->is_preemptible())
+         && !gsym->is_from_dynobj()
+         && !gsym->is_preemptible())
        break;
       target->make_plt_entry(symtab, layout, gsym);
       break;
@@ -1459,38 +1467,38 @@ Target_powerpc<size, big_endian>::Scan::global(
     case elfcpp::R_POWERPC_ADDR32:
     case elfcpp::R_PPC64_ADDR64:
       {
-        // Make a PLT entry if necessary.
-        if (gsym->needs_plt_entry())
-          {
-            target->make_plt_entry(symtab, layout, gsym);
-            // Since this is not a PC-relative relocation, we may be
-            // taking the address of a function. In that case we need to
-            // set the entry in the dynamic symbol table to the address of
-            // the PLT entry.
-            if (gsym->is_from_dynobj() && !parameters->options().shared())
-              gsym->set_needs_dynsym_value();
-          }
-        // Make a dynamic relocation if necessary.
-        if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
-          {
-            if (gsym->may_need_copy_reloc())
-              {
-               target->copy_reloc(symtab, layout, object,
-                                  data_shndx, output_section, gsym, reloc);
-              }
-            else if ((r_type == elfcpp::R_POWERPC_ADDR32
+       // Make a PLT entry if necessary.
+       if (gsym->needs_plt_entry())
+         {
+           target->make_plt_entry(symtab, layout, gsym);
+           // Since this is not a PC-relative relocation, we may be
+           // taking the address of a function. In that case we need to
+           // set the entry in the dynamic symbol table to the address of
+           // the PLT entry.
+           if (gsym->is_from_dynobj() && !parameters->options().shared())
+             gsym->set_needs_dynsym_value();
+         }
+       // Make a dynamic relocation if necessary.
+       if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
+         {
+           if (gsym->may_need_copy_reloc())
+             {
+               target->copy_reloc(symtab, layout, object,
+                                  data_shndx, output_section, gsym, reloc);
+             }
+           else if ((r_type == elfcpp::R_POWERPC_ADDR32
                      || r_type == elfcpp::R_PPC64_ADDR64)
-                     && gsym->can_use_relative_reloc(false))
-              {
-                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-                rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE,
+                    && gsym->can_use_relative_reloc(false))
+             {
+               Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+               rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE,
                                              output_section, object,
                                              data_shndx, reloc.get_r_offset(),
                                              reloc.get_r_addend(), false);
-              }
-            else
-              {
-                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+             }
+           else
+             {
+               Reloc_section* rela_dyn = target->rela_dyn_section(layout);
 
                check_non_pic(object, r_type);
                if (gsym->is_from_dynobj()
@@ -1506,8 +1514,8 @@ Target_powerpc<size, big_endian>::Scan::global(
                                                data_shndx,
                                                reloc.get_r_offset(),
                                                reloc.get_r_addend(), false);
-              }
-          }
+             }
+         }
       }
       break;
 
@@ -1552,31 +1560,31 @@ Target_powerpc<size, big_endian>::Scan::global(
     case elfcpp::R_PPC64_TOC16_DS:
     case elfcpp::R_PPC64_TOC16_LO_DS:
       {
-        // The symbol requires a GOT entry.
-        Output_data_got<size, big_endian>* got;
+       // The symbol requires a GOT entry.
+       Output_data_got<size, big_endian>* got;
 
        got = target->got_section(symtab, layout);
-        if (gsym->final_value_is_known())
-          got->add_global(gsym, GOT_TYPE_STANDARD);
-        else
-          {
-            // If this symbol is not fully resolved, we need to add a
-            // dynamic relocation for it.
-            Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-            if (gsym->is_from_dynobj()
-                || gsym->is_undefined()
-                || gsym->is_preemptible())
-              got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn,
+       if (gsym->final_value_is_known())
+         got->add_global(gsym, GOT_TYPE_STANDARD);
+       else
+         {
+           // If this symbol is not fully resolved, we need to add a
+           // dynamic relocation for it.
+           Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+           if (gsym->is_from_dynobj()
+               || gsym->is_undefined()
+               || gsym->is_preemptible())
+             got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn,
                                       elfcpp::R_POWERPC_GLOB_DAT);
-            else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
-              {
+           else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
+             {
                unsigned int off = got->add_constant(0);
 
                gsym->set_got_offset(GOT_TYPE_STANDARD, off);
                rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE,
                                              got, off, 0, false);
              }
-          }
+         }
       }
       break;
 
@@ -1788,20 +1796,20 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     case elfcpp::R_PPC64_GOT16_DS:
     case elfcpp::R_PPC64_GOT16_LO_DS:
       if (gsym != NULL)
-        {
-          gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
-          got_offset = gsym->got_offset(GOT_TYPE_STANDARD);
-        }
+       {
+         gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+         got_offset = gsym->got_offset(GOT_TYPE_STANDARD);
+       }
       else
-        {
-          unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
-          gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
-          got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
-        }
+       {
+         unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+         gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+         got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
+       }
       break;
 
       // R_PPC_PLTREL24 is rather special.  If non-zero,
-      // the addend specifies the GOT pointer offset within .got2.  
+      // the addend specifies the GOT pointer offset within .got2.
     case elfcpp::R_PPC_PLTREL24:
       if (addend >= 32768)
        {
@@ -2132,7 +2140,8 @@ public:
                       : (big_endian ? "elf32ppc" : "elf32lppc")))
   { }
 
-  Target* do_recognize(int machine, int, int)
+  virtual Target*
+  do_recognize(Input_file*, off_t, int machine, int, int)
   {
     switch (size)
       {
@@ -2153,7 +2162,8 @@ public:
     return this->instantiate_target();
   }
 
-  Target* do_instantiate_target()
+  virtual Target*
+  do_instantiate_target()
   { return new Target_powerpc<size, big_endian>(); }
 };
 
index a85bb8118bf41c0d32b884152fccaed1e5114ef6..7b78311e7b0a5edd2b965b187d7243bee2f4c7a0 100644 (file)
@@ -66,20 +66,20 @@ class Target_sparc : public Sized_target<size, big_endian>
   {
   }
 
-  // Process the relocations to determine unreferenced sections for 
+  // Process the relocations to determine unreferenced sections for
   // garbage collection.
   void
   gc_process_relocs(Symbol_table* symtab,
-                   Layout* layout,
-                   Sized_relobj_file<size, big_endian>* object,
-                   unsigned int data_shndx,
-                   unsigned int sh_type,
-                   const unsigned char* prelocs,
-                   size_t reloc_count,
-                   Output_section* output_section,
-                   bool needs_special_offset_handling,
-                   size_t local_symbol_count,
-                   const unsigned char* plocal_symbols);
+                   Layout* layout,
+                   Sized_relobj_file<size, big_endian>* object,
+                   unsigned int data_shndx,
+                   unsigned int sh_type,
+                   const unsigned char* prelocs,
+                   size_t reloc_count,
+                   Output_section* output_section,
+                   bool needs_special_offset_handling,
+                   size_t local_symbol_count,
+                   const unsigned char* plocal_symbols);
 
   // Scan the relocations to look for symbol adjustments.
   void
@@ -248,24 +248,24 @@ class Target_sparc : public Sized_target<size, big_endian>
 
     inline bool
     local_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
-                                       Target_sparc* ,
-                                       Sized_relobj_file<size, big_endian>* ,
-                                               unsigned int ,
-                                       Output_section* ,
-                                       const elfcpp::Rela<size, big_endian>& ,
+                                       Target_sparc* ,
+                                       Sized_relobj_file<size, big_endian>* ,
                                        unsigned int ,
-                                       const elfcpp::Sym<size, big_endian>&)
+                                       Output_section* ,
+                                       const elfcpp::Rela<size, big_endian>& ,
+                                       unsigned int ,
+                                       const elfcpp::Sym<size, big_endian>&)
     { return false; }
 
     inline bool
     global_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
-                                        Target_sparc* ,
-                                        Sized_relobj_file<size, big_endian>* ,
-                                        unsigned int ,
-                                        Output_section* ,
-                                        const elfcpp::Rela<size,
-                                                           big_endian>& ,
-                                        unsigned int , Symbol*)
+                                        Target_sparc* ,
+                                        Sized_relobj_file<size, big_endian>* ,
+                                        unsigned int ,
+                                        Output_section* ,
+                                        const elfcpp::Rela<size,
+                                                           big_endian>& ,
+                                        unsigned int , Symbol*)
     { return false; }
 
 
@@ -326,7 +326,7 @@ class Target_sparc : public Sized_target<size, big_endian>
     // Do a TLS relocation.
     inline void
     relocate_tls(const Relocate_info<size, big_endian>*, Target_sparc* target,
-                 size_t relnum, const elfcpp::Rela<size, big_endian>&,
+                size_t relnum, const elfcpp::Rela<size, big_endian>&,
                 unsigned int r_type, const Sized_symbol<size>*,
                 const Symbol_value<size>*,
                 unsigned char*,
@@ -408,7 +408,7 @@ class Target_sparc : public Sized_target<size, big_endian>
   // Copy a relocation against a global symbol.
   void
   copy_reloc(Symbol_table* symtab, Layout* layout,
-             Sized_relobj_file<size, big_endian>* object,
+            Sized_relobj_file<size, big_endian>* object,
             unsigned int shndx, Output_section* output_section,
             Symbol* sym, const elfcpp::Rela<size, big_endian>& reloc)
   {
@@ -473,6 +473,8 @@ Target::Target_info Target_sparc<32, true>::sparc_info =
   0x00010000,          // default_text_segment_address
   64 * 1024,           // abi_pagesize (overridable by -z max-page-size)
   8 * 1024,            // common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
   elfcpp::SHN_UNDEF,   // small_common_shndx
   elfcpp::SHN_UNDEF,   // large_common_shndx
   0,                   // small_common_section_flags
@@ -497,6 +499,8 @@ Target::Target_info Target_sparc<64, true>::sparc_info =
   0x100000,            // default_text_segment_address
   64 * 1024,           // abi_pagesize (overridable by -z max-page-size)
   8 * 1024,            // common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
   elfcpp::SHN_UNDEF,   // small_common_shndx
   elfcpp::SHN_UNDEF,   // large_common_shndx
   0,                   // small_common_section_flags
@@ -2218,7 +2222,7 @@ Target_sparc<size, big_endian>::Scan::reloc_needs_plt_for_ifunc(
   int flags = Scan::get_reference_flags(r_type);
   if (flags & Symbol::TLS_REF)
     gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
-               object->name().c_str(), r_type);
+              object->name().c_str(), r_type);
   return flags != 0;
 }
 
@@ -2265,14 +2269,14 @@ Target_sparc<size, big_endian>::Scan::local(
       // an R_SPARC_RELATIVE relocation so the dynamic loader can
       // relocate it easily.
       if (parameters->options().output_is_position_independent())
-        {
-          Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-          unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-          rela_dyn->add_local_relative(object, r_sym, elfcpp::R_SPARC_RELATIVE,
+       {
+         Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+         unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+         rela_dyn->add_local_relative(object, r_sym, elfcpp::R_SPARC_RELATIVE,
                                       output_section, data_shndx,
                                       reloc.get_r_offset(),
                                       reloc.get_r_addend(), is_ifunc);
-        }
+       }
       break;
 
     case elfcpp::R_SPARC_HIX22:
@@ -2301,26 +2305,26 @@ Target_sparc<size, big_endian>::Scan::local(
       // executable), we need to create a dynamic relocation for
       // this location.
       if (parameters->options().output_is_position_independent())
-        {
-          Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-          unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+       {
+         Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+         unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
 
          check_non_pic(object, r_type);
-          if (lsym.get_st_type() != elfcpp::STT_SECTION)
-            {
-              rela_dyn->add_local(object, r_sym, orig_r_type, output_section,
+         if (lsym.get_st_type() != elfcpp::STT_SECTION)
+           {
+             rela_dyn->add_local(object, r_sym, orig_r_type, output_section,
                                  data_shndx, reloc.get_r_offset(),
                                  reloc.get_r_addend());
-            }
-          else
-            {
-              gold_assert(lsym.get_st_value() == 0);
+           }
+         else
+           {
+             gold_assert(lsym.get_st_value() == 0);
              rela_dyn->add_symbolless_local_addend(object, r_sym, orig_r_type,
                                                    output_section, data_shndx,
                                                    reloc.get_r_offset(),
                                                    reloc.get_r_addend());
-            }
-        }
+           }
+       }
       break;
 
     case elfcpp::R_SPARC_WDISP30:
@@ -2348,9 +2352,9 @@ Target_sparc<size, big_endian>::Scan::local(
     case elfcpp::R_SPARC_GOT13:
     case elfcpp::R_SPARC_GOT22:
       {
-        // The symbol requires a GOT entry.
-        Output_data_got<size, big_endian>* got;
-        unsigned int r_sym;
+       // The symbol requires a GOT entry.
+       Output_data_got<size, big_endian>* got;
+       unsigned int r_sym;
 
        got = target->got_section(symtab, layout);
        r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
@@ -2397,7 +2401,7 @@ Target_sparc<size, big_endian>::Scan::local(
       {
        bool output_is_shared = parameters->options().shared();
        const tls::Tls_optimization optimized_type
-            = optimize_tls_reloc(!output_is_shared, r_type);
+           = optimize_tls_reloc(!output_is_shared, r_type);
        switch (r_type)
          {
          case elfcpp::R_SPARC_TLS_GD_HI22: // Global-dynamic
@@ -2406,11 +2410,11 @@ Target_sparc<size, big_endian>::Scan::local(
          case elfcpp::R_SPARC_TLS_GD_CALL:
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // Create a pair of GOT entries for the module index and
-               // dtv-relative offset.
-                Output_data_got<size, big_endian>* got
-                    = target->got_section(symtab, layout);
-                unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+               // Create a pair of GOT entries for the module index and
+               // dtv-relative offset.
+               Output_data_got<size, big_endian>* got
+                   = target->got_section(symtab, layout);
+               unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
                unsigned int shndx = lsym.get_st_shndx();
                bool is_ordinary;
                shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
@@ -2418,7 +2422,7 @@ Target_sparc<size, big_endian>::Scan::local(
                  object->error(_("local symbol %u has bad shndx %u"),
                                r_sym, shndx);
                else
-                 got->add_local_pair_with_rel(object, r_sym, 
+                 got->add_local_pair_with_rel(object, r_sym,
                                               lsym.get_st_shndx(),
                                               GOT_TYPE_TLS_PAIR,
                                               target->rela_dyn_section(layout),
@@ -2490,11 +2494,11 @@ Target_sparc<size, big_endian>::Scan::local(
            layout->set_has_static_tls();
            if (output_is_shared)
              {
-               // We need to create a dynamic relocation.
-                gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
-                unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-                rela_dyn->add_symbolless_local_addend(object, r_sym, r_type,
+               // We need to create a dynamic relocation.
+               gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
+               unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+               Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+               rela_dyn->add_symbolless_local_addend(object, r_sym, r_type,
                                                      output_section, data_shndx,
                                                      reloc.get_r_offset(), 0);
              }
@@ -2596,8 +2600,8 @@ Target_sparc<size, big_endian>::Scan::global(
       // if the symbol is defined in the output file and is protected
       // or hidden.
       if (gsym->is_defined()
-          && !gsym->is_from_dynobj()
-          && !gsym->is_preemptible())
+         && !gsym->is_from_dynobj()
+         && !gsym->is_preemptible())
        break;
       target->make_plt_entry(symtab, layout, gsym);
       break;
@@ -2665,24 +2669,24 @@ Target_sparc<size, big_endian>::Scan::global(
     case elfcpp::R_SPARC_6:
     case elfcpp::R_SPARC_5:
       {
-        // Make a PLT entry if necessary.
-        if (gsym->needs_plt_entry())
-          {
-            target->make_plt_entry(symtab, layout, gsym);
-            // Since this is not a PC-relative relocation, we may be
-            // taking the address of a function. In that case we need to
-            // set the entry in the dynamic symbol table to the address of
-            // the PLT entry.
-            if (gsym->is_from_dynobj() && !parameters->options().shared())
-              gsym->set_needs_dynsym_value();
-          }
-        // Make a dynamic relocation if necessary.
-        if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
-          {
+       // Make a PLT entry if necessary.
+       if (gsym->needs_plt_entry())
+         {
+           target->make_plt_entry(symtab, layout, gsym);
+           // Since this is not a PC-relative relocation, we may be
+           // taking the address of a function. In that case we need to
+           // set the entry in the dynamic symbol table to the address of
+           // the PLT entry.
+           if (gsym->is_from_dynobj() && !parameters->options().shared())
+             gsym->set_needs_dynsym_value();
+         }
+       // Make a dynamic relocation if necessary.
+       if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
+         {
            unsigned int r_off = reloc.get_r_offset();
 
            // The assembler can sometimes emit unaligned relocations
-           // for dwarf2 cfi directives. 
+           // for dwarf2 cfi directives.
            switch (r_type)
              {
              case elfcpp::R_SPARC_16:
@@ -2711,11 +2715,11 @@ Target_sparc<size, big_endian>::Scan::global(
                break;
              }
 
-            if (gsym->may_need_copy_reloc())
-              {
-               target->copy_reloc(symtab, layout, object,
-                                  data_shndx, output_section, gsym, reloc);
-              }
+           if (gsym->may_need_copy_reloc())
+             {
+               target->copy_reloc(symtab, layout, object,
+                                  data_shndx, output_section, gsym, reloc);
+             }
            else if (((size == 64 && r_type == elfcpp::R_SPARC_64)
                      || (size == 32 && r_type == elfcpp::R_SPARC_32))
                     && gsym->type() == elfcpp::STT_GNU_IFUNC
@@ -2737,19 +2741,19 @@ Target_sparc<size, big_endian>::Scan::global(
                                                       reloc.get_r_offset(),
                                                       reloc.get_r_addend());
              }
-            else if ((r_type == elfcpp::R_SPARC_32
+           else if ((r_type == elfcpp::R_SPARC_32
                      || r_type == elfcpp::R_SPARC_64)
-                     && gsym->can_use_relative_reloc(false))
-              {
-                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-                rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE,
+                    && gsym->can_use_relative_reloc(false))
+             {
+               Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+               rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE,
                                              output_section, object,
                                              data_shndx, reloc.get_r_offset(),
                                              reloc.get_r_addend(), is_ifunc);
-              }
-            else
-              {
-                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+             }
+           else
+             {
+               Reloc_section* rela_dyn = target->rela_dyn_section(layout);
 
                check_non_pic(object, r_type);
                if (gsym->is_from_dynobj()
@@ -2765,8 +2769,8 @@ Target_sparc<size, big_endian>::Scan::global(
                                                         object, data_shndx,
                                                         reloc.get_r_offset(),
                                                         reloc.get_r_addend());
-              }
-          }
+             }
+         }
       }
       break;
 
@@ -2774,8 +2778,8 @@ Target_sparc<size, big_endian>::Scan::global(
     case elfcpp::R_SPARC_GOTDATA_OP_HIX22:
     case elfcpp::R_SPARC_GOTDATA_OP_LOX10:
       if (gsym->is_defined()
-          && !gsym->is_from_dynobj()
-          && !gsym->is_preemptible()
+         && !gsym->is_from_dynobj()
+         && !gsym->is_preemptible()
          && !is_ifunc)
        {
          // We will optimize this into a GOT relative relocation
@@ -2786,11 +2790,11 @@ Target_sparc<size, big_endian>::Scan::global(
     case elfcpp::R_SPARC_GOT13:
     case elfcpp::R_SPARC_GOT22:
       {
-        // The symbol requires a GOT entry.
-        Output_data_got<size, big_endian>* got;
+       // The symbol requires a GOT entry.
+       Output_data_got<size, big_endian>* got;
 
        got = target->got_section(symtab, layout);
-        if (gsym->final_value_is_known())
+       if (gsym->final_value_is_known())
          {
            // For a STT_GNU_IFUNC symbol we want the PLT address.
            if (gsym->type() == elfcpp::STT_GNU_IFUNC)
@@ -2798,10 +2802,10 @@ Target_sparc<size, big_endian>::Scan::global(
            else
              got->add_global(gsym, GOT_TYPE_STANDARD);
          }
-        else
-          {
-            // If this symbol is not fully resolved, we need to add a
-            // GOT entry with a dynamic relocation.
+       else
+         {
+           // If this symbol is not fully resolved, we need to add a
+           // GOT entry with a dynamic relocation.
            bool is_ifunc = gsym->type() == elfcpp::STT_GNU_IFUNC;
 
            // Use a GLOB_DAT rather than a RELATIVE reloc if:
@@ -2816,10 +2820,10 @@ Target_sparc<size, big_endian>::Scan::global(
            //
            // 3) This is a STT_GNU_IFUNC symbol in position dependent
            // code, again so that function address comparisons work.
-            Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-            if (gsym->is_from_dynobj()
-                || gsym->is_undefined()
-                || gsym->is_preemptible()
+           Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+           if (gsym->is_from_dynobj()
+               || gsym->is_undefined()
+               || gsym->is_preemptible()
                || (gsym->visibility() == elfcpp::STV_PROTECTED
                    && parameters->options().shared())
                || (gsym->type() == elfcpp::STT_GNU_IFUNC
@@ -2838,8 +2842,8 @@ Target_sparc<size, big_endian>::Scan::global(
                got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn,
                                         r_type);
              }
-            else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
-              {
+           else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
+             {
                unsigned int off = got->add_constant(0);
 
                gsym->set_got_offset(GOT_TYPE_STANDARD, off);
@@ -2854,7 +2858,7 @@ Target_sparc<size, big_endian>::Scan::global(
                rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE,
                                              got, off, 0, is_ifunc);
              }
-          }
+         }
       }
       break;
 
@@ -2881,7 +2885,7 @@ Target_sparc<size, big_endian>::Scan::global(
       {
        const bool is_final = gsym->final_value_is_known();
        const tls::Tls_optimization optimized_type
-            = optimize_tls_reloc(is_final, r_type);
+           = optimize_tls_reloc(is_final, r_type);
        switch (r_type)
          {
          case elfcpp::R_SPARC_TLS_GD_HI22: // Global-dynamic
@@ -2890,11 +2894,11 @@ Target_sparc<size, big_endian>::Scan::global(
          case elfcpp::R_SPARC_TLS_GD_CALL:
            if (optimized_type == tls::TLSOPT_NONE)
              {
-                // Create a pair of GOT entries for the module index and
-                // dtv-relative offset.
-                Output_data_got<size, big_endian>* got
-                    = target->got_section(symtab, layout);
-                got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
+               // Create a pair of GOT entries for the module index and
+               // dtv-relative offset.
+               Output_data_got<size, big_endian>* got
+                   = target->got_section(symtab, layout);
+               got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
                                              target->rela_dyn_section(layout),
                                              (size == 64
                                               ? elfcpp::R_SPARC_TLS_DTPMOD64
@@ -2909,10 +2913,10 @@ Target_sparc<size, big_endian>::Scan::global(
              }
            else if (optimized_type == tls::TLSOPT_TO_IE)
              {
-                // Create a GOT entry for the tp-relative offset.
-                Output_data_got<size, big_endian>* got
-                    = target->got_section(symtab, layout);
-                got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
+               // Create a GOT entry for the tp-relative offset.
+               Output_data_got<size, big_endian>* got
+                   = target->got_section(symtab, layout);
+               got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
                                         target->rela_dyn_section(layout),
                                         (size == 64 ?
                                          elfcpp::R_SPARC_TLS_TPOFF64 :
@@ -3235,16 +3239,16 @@ Target_sparc<size, big_endian>::Relocate::relocate(
     case elfcpp::R_SPARC_GOT13:
     case elfcpp::R_SPARC_GOT22:
       if (gsym != NULL)
-        {
-          gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
-          got_offset = gsym->got_offset(GOT_TYPE_STANDARD);
-        }
+       {
+         gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+         got_offset = gsym->got_offset(GOT_TYPE_STANDARD);
+       }
       else
-        {
-          unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
-          gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
-          got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
-        }
+       {
+         unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+         gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+         got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
+       }
       break;
 
     default:
@@ -3268,7 +3272,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
       if (rela.get_r_offset() & 0x1)
        {
          // The assembler can sometimes emit unaligned relocations
-         // for dwarf2 cfi directives. 
+         // for dwarf2 cfi directives.
          Reloc::ua16(view, object, psymval, addend);
        }
       else
@@ -3282,7 +3286,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
          if (rela.get_r_offset() & 0x3)
            {
              // The assembler can sometimes emit unaligned relocations
-             // for dwarf2 cfi directives. 
+             // for dwarf2 cfi directives.
              Reloc::ua32(view, object, psymval, addend);
            }
          else
@@ -3435,7 +3439,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
          if (rela.get_r_offset() & 0x7)
            {
              // The assembler can sometimes emit unaligned relocations
-             // for dwarf2 cfi directives. 
+             // for dwarf2 cfi directives.
              Reloc::ua64(view, object, psymval, addend);
            }
          else
@@ -3649,22 +3653,22 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
          break;
        }
       else
-        {
-          unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
-                                   ? GOT_TYPE_TLS_OFFSET
-                                   : GOT_TYPE_TLS_PAIR);
-          if (gsym != NULL)
-            {
-              gold_assert(gsym->has_got_offset(got_type));
-              value = gsym->got_offset(got_type);
-            }
-          else
-            {
-              unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
-              gold_assert(object->local_has_got_offset(r_sym, got_type));
-              value = object->local_got_offset(r_sym, got_type);
-            }
-          if (optimized_type == tls::TLSOPT_TO_IE)
+       {
+         unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
+                                  ? GOT_TYPE_TLS_OFFSET
+                                  : GOT_TYPE_TLS_PAIR);
+         if (gsym != NULL)
+           {
+             gold_assert(gsym->has_got_offset(got_type));
+             value = gsym->got_offset(got_type);
+           }
+         else
+           {
+             unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+             gold_assert(object->local_has_got_offset(r_sym, got_type));
+             value = object->local_got_offset(r_sym, got_type);
+           }
+         if (optimized_type == tls::TLSOPT_TO_IE)
            {
              Insntype* wv = reinterpret_cast<Insntype*>(view);
              Insntype val;
@@ -3729,10 +3733,10 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
                  elfcpp::Swap<32, true>::writeval(wv, 0x9001c008);
                  break;
                }
-              break;
+             break;
            }
-          else if (optimized_type == tls::TLSOPT_NONE)
-            {
+         else if (optimized_type == tls::TLSOPT_NONE)
+           {
              switch (r_type)
                {
                case elfcpp::R_SPARC_TLS_GD_HI22:
@@ -3759,8 +3763,8 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
                  break;
                }
              break;
-            }
-        }
+           }
+       }
       gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
                             _("unsupported reloc %u"),
                             r_type);
@@ -3789,10 +3793,10 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
          break;
        }
       else if (optimized_type == tls::TLSOPT_NONE)
-        {
-          // Relocate the field with the offset of the GOT entry for
-          // the module index.
-          unsigned int got_offset;
+       {
+         // Relocate the field with the offset of the GOT entry for
+         // the module index.
+         unsigned int got_offset;
 
          got_offset = target->got_mod_index_entry(NULL, NULL, NULL);
          switch (r_type)
@@ -3820,8 +3824,8 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
              }
              break;
            }
-          break;
-        }
+         break;
+       }
       gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
                             _("unsupported reloc %u"),
                             r_type);
@@ -4255,7 +4259,7 @@ Target_sparc<size, big_endian>::do_make_elf_object(
   elfcpp::Elf_Half machine = ehdr.get_e_machine();
   elfcpp::Elf_Word flags = ehdr.get_e_flags();
   elfcpp::Elf_Word omm, mm;
-  
+
   switch (machine)
     {
     case elfcpp::EM_SPARC32PLUS:
@@ -4346,7 +4350,8 @@ public:
                      (size == 64 ? "elf64_sparc" : "elf32_sparc"))
   { }
 
-  Target* do_recognize(int machine, int, int)
+  virtual Target*
+  do_recognize(Input_file*, off_t, int machine, int, int)
   {
     switch (size)
       {
@@ -4368,7 +4373,8 @@ public:
     return this->instantiate_target();
   }
 
-  Target* do_instantiate_target()
+  virtual Target*
+  do_instantiate_target()
   { return new Target_sparc<size, big_endian>(); }
 };
 
index 9370a8714ab6a027160d343de24aecef8598cd82..e17cb7d48b1b2022eb4c4319d453b7efb06657bf 100644 (file)
@@ -1,6 +1,7 @@
 // target-select.cc -- select a target for an object file
 
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -98,8 +99,9 @@ Target_selector::do_target_bfd_name(const Target* target)
 // Find the target for an ELF file.
 
 Target*
-select_target(int machine, int size, bool is_big_endian, int osabi,
-             int abiversion)
+select_target(Input_file* input_file, off_t offset,
+             int machine, int size, bool is_big_endian,
+             int osabi, int abiversion)
 {
   for (Target_selector* p = target_selectors; p != NULL; p = p->next())
     {
@@ -108,7 +110,8 @@ select_target(int machine, int size, bool is_big_endian, int osabi,
          && p->get_size() == size
          && (p->is_big_endian() ? is_big_endian : !is_big_endian))
        {
-         Target* ret = p->recognize(machine, osabi, abiversion);
+         Target* ret = p->recognize(input_file, offset,
+                                    machine, osabi, abiversion);
          if (ret != NULL)
            return ret;
        }
index 310c0b97d8c567cc85998927157e0c5e94b3686b..2e16c2a8682040518c20ec24209e2db139805f69 100644 (file)
@@ -1,6 +1,7 @@
 // target-select.h -- select a target for an object file  -*- C++ -*-
 
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -30,6 +31,7 @@
 namespace gold
 {
 
+class Input_file;
 class Target;
 class Target_selector;
 
@@ -76,8 +78,9 @@ class Target_selector
   // If we can handle this target, return a pointer to a target
   // structure.  The size and endianness are known.
   Target*
-  recognize(int machine, int osabi, int abiversion)
-  { return this->do_recognize(machine, osabi, abiversion); }
+  recognize(Input_file* input_file, off_t offset,
+           int machine, int osabi, int abiversion)
+  { return this->do_recognize(input_file, offset, machine, osabi, abiversion); }
 
   // If NAME matches the target, return a pointer to a target
   // structure.
@@ -160,7 +163,7 @@ class Target_selector
   // checks, or to check for multiple machine codes if the machine_
   // field is EM_NONE.
   virtual Target*
-  do_recognize(int, int, int)
+  do_recognize(Input_file*, off_t, int, int, int)
   { return this->instantiate_target(); }
 
   // Recognize a target by name.  When this is called we already know
@@ -241,7 +244,8 @@ class Target_selector
 // Select the target for an ELF file.
 
 extern Target*
-select_target(int machine, int size, bool big_endian, int osabi,
+select_target(Input_file*, off_t,
+             int machine, int size, bool big_endian, int osabi,
              int abiversion);
 
 // Select a target using a BFD name.
index b174058a162e1fa469de1eac2a108f210135e276..81c8114e5f2883c05f4b0c43f9fccc484bb4dafa 100644 (file)
@@ -143,6 +143,16 @@ class Target
                      this->abi_pagesize());
   }
 
+  // Return whether PF_X segments must contain nothing but the contents of
+  // SHF_EXECINSTR sections (no non-executable data, no headers).
+  bool
+  isolate_execinstr() const
+  { return this->pti_->isolate_execinstr; }
+
+  uint64_t
+  rosegment_gap() const
+  { return this->pti_->rosegment_gap; }
+
   // If we see some object files with .note.GNU-stack sections, and
   // some objects files without them, this returns whether we should
   // consider the object files without them to imply that the stack
@@ -345,7 +355,7 @@ class Target
       return pass < 2;
 
     return this->do_relax(pass, input_objects, symtab, layout, task);
-  } 
+  }
 
   // Return the target-specific name of attributes section.  This is
   // NULL if a target does not use attributes section or if it uses
@@ -365,7 +375,7 @@ class Target
   {
     return ((this->pti_->attributes_section != NULL
             && strcmp(name, this->pti_->attributes_section) == 0)
-           || strcmp(name, ".gnu.attributes") == 0); 
+           || strcmp(name, ".gnu.attributes") == 0);
   }
 
   // Return a bit mask of argument types for attribute with TAG.
@@ -384,7 +394,7 @@ class Target
   // which may be used for expensive, target-specific initialization.
   void
   select_as_default_target()
-  { this->do_select_as_default_target(); } 
+  { this->do_select_as_default_target(); }
 
   // Return the value to store in the EI_OSABI field in the ELF
   // header.
@@ -436,6 +446,11 @@ class Target
     uint64_t abi_pagesize;
     // The common page size used by actual implementations.
     uint64_t common_pagesize;
+    // Whether PF_X segments must contain nothing but the contents of
+    // SHF_EXECINSTR sections (no non-executable data, no headers).
+    bool isolate_execinstr;
+    // If nonzero, distance from the text segment to the read-only segment.
+    uint64_t rosegment_gap;
     // The special section index for small common symbols; SHN_UNDEF
     // if none.
     elfcpp::Elf_Half small_common_shndx;
@@ -563,7 +578,7 @@ class Target
     this->processor_specific_flags_ = flags;
     this->are_processor_specific_flags_set_ = true;
   }
-  
+
 #ifdef HAVE_TARGET_32_LITTLE
   // Virtual functions which may be overridden by the child class.
   virtual Object*
@@ -620,7 +635,7 @@ class Target
                  section_offset_type offset, size_t len) const;
 
   // This must be overridden by the child class if it has target-specific
-  // attributes subsection in the attribute section. 
+  // attributes subsection in the attribute section.
   virtual int
   do_attribute_arg_type(int) const
   { gold_unreachable(); }
@@ -789,7 +804,7 @@ 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
@@ -819,7 +834,7 @@ class Sized_target : public Target
                               section_size_type /* view_size */,
                               unsigned char* /* preloc_out*/)
   { gold_unreachable(); }
+
   // Return the number of entries in the GOT.  This is only used for
   // laying out the incremental link info sections.  A target needs
   // to implement this to support incremental linking.
index 93e716a75598da9c48ef531afb7f78c61468989b..e963d4d4fbee253f4987d7fbc903a8a6c6264a6b 100644 (file)
@@ -1,6 +1,6 @@
 // testfile.cc -- Dummy ELF objects for testing purposes.
 
-// Copyright 2006, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2011, 2012 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -100,6 +100,8 @@ const Target::Target_info Target_test<size, big_endian>::test_target_info =
   0x08000000,                          // default_text_segment_address
   0x1000,                              // abi_pagesize
   0x1000,                              // common_pagesize
+  false,                                // isolate_execinstr
+  0,                                    // rosegment_gap
   elfcpp::SHN_UNDEF,                   // small_common_shndx
   elfcpp::SHN_UNDEF,                   // large_common_shndx
   0,                                   // small_common_section_flags
@@ -154,15 +156,15 @@ class Target_selector_test : public Target_selector
     : Target_selector(0xffff, size, big_endian, NULL, NULL)
   { }
 
-  Target*
+  virtual Target*
   do_instantiate_target()
   {
     gold_unreachable();
     return NULL;
   }
 
-  Target*
-  do_recognize(int, int, int)
+  virtual Target*
+  do_recognize(Input_file*, off_t, int, int, int)
   {
     if (size == 32)
       {
@@ -198,11 +200,11 @@ class Target_selector_test : public Target_selector
     return NULL;
   }
 
-  Target*
+  virtual Target*
   do_recognize_by_name(const char*)
   { return NULL; }
 
-  void
+  virtual void
   do_supported_names(std::vector<const char*>*)
   { }
 };
index d67924b37911cb0d39e2dc35e5e6a7da309055e0..1339e6ff6b16ae259153979764d5120b17f96f8c 100644 (file)
@@ -40,6 +40,7 @@
 #include "target-select.h"
 #include "tls.h"
 #include "freebsd.h"
+#include "nacl.h"
 #include "gc.h"
 #include "icf.h"
 
@@ -49,6 +50,9 @@ namespace
 using namespace gold;
 
 // A class to handle the PLT data.
+// This is an abstract base class that handles most of the linker details
+// but does not know the actual contents of PLT entries.  The derived
+// classes below fill in those details.
 
 template<int size>
 class Output_data_plt_x86_64 : public Output_section_data
@@ -56,20 +60,23 @@ class Output_data_plt_x86_64 : public Output_section_data
  public:
   typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, false> Reloc_section;
 
-  Output_data_plt_x86_64(Layout* layout, Output_data_got<64, false>* got,
+  Output_data_plt_x86_64(Layout* layout, uint64_t addralign,
+                        Output_data_got<64, false>* got,
                         Output_data_space* got_plt,
                         Output_data_space* got_irelative)
-    : Output_section_data(16), layout_(layout), tlsdesc_rel_(NULL),
+    : Output_section_data(addralign), layout_(layout), tlsdesc_rel_(NULL),
       irelative_rel_(NULL), got_(got), got_plt_(got_plt),
       got_irelative_(got_irelative), count_(0), irelative_count_(0),
       tlsdesc_got_offset_(-1U), free_list_()
   { this->init(layout); }
 
-  Output_data_plt_x86_64(Layout* layout, Output_data_got<64, false>* got,
+  Output_data_plt_x86_64(Layout* layout, uint64_t plt_entry_size,
+                        Output_data_got<64, false>* got,
                         Output_data_space* got_plt,
                         Output_data_space* got_irelative,
                         unsigned int plt_count)
-    : Output_section_data((plt_count + 1) * plt_entry_size, 16, false),
+    : Output_section_data((plt_count + 1) * plt_entry_size,
+                         plt_entry_size, false),
       layout_(layout), tlsdesc_rel_(NULL), irelative_rel_(NULL), got_(got),
       got_plt_(got_plt), got_irelative_(got_irelative), count_(plt_count),
       irelative_count_(0), tlsdesc_got_offset_(-1U), free_list_()
@@ -118,7 +125,10 @@ class Output_data_plt_x86_64 : public Output_section_data
   // Return the offset of the reserved TLSDESC_PLT entry.
   unsigned int
   get_tlsdesc_plt_offset() const
-  { return (this->count_ + this->irelative_count_ + 1) * plt_entry_size; }
+  {
+    return ((this->count_ + this->irelative_count_ + 1)
+           * this->get_plt_entry_size());
+  }
 
   // Return the .rela.plt section data.
   Reloc_section*
@@ -145,21 +155,21 @@ class Output_data_plt_x86_64 : public Output_section_data
   { return this->count_ + this->irelative_count_; }
 
   // Return the offset of the first non-reserved PLT entry.
-  static unsigned int
+  unsigned int
   first_plt_entry_offset()
-  { return plt_entry_size; }
+  { return this->get_plt_entry_size(); }
 
   // Return the size of a PLT entry.
-  static unsigned int
-  get_plt_entry_size()
-  { return plt_entry_size; }
+  unsigned int
+  get_plt_entry_size() const
+  { return this->do_get_plt_entry_size(); }
 
   // Reserve a slot in the PLT for an existing symbol in an incremental update.
   void
   reserve_slot(unsigned int plt_index)
   {
-    this->free_list_.remove((plt_index + 1) * plt_entry_size,
-                           (plt_index + 2) * plt_entry_size);
+    this->free_list_.remove((plt_index + 1) * this->get_plt_entry_size(),
+                           (plt_index + 2) * this->get_plt_entry_size());
   }
 
   // Return the PLT address to use for a global symbol.
@@ -170,7 +180,74 @@ class Output_data_plt_x86_64 : public Output_section_data
   uint64_t
   address_for_local(const Relobj*, unsigned int symndx);
 
+  // Add .eh_frame information for the PLT.
+  void
+  add_eh_frame(Layout* layout)
+  { this->do_add_eh_frame(layout); }
+
  protected:
+  // Fill in the first PLT entry.
+  void
+  fill_first_plt_entry(unsigned char* pov,
+                      typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+                      typename elfcpp::Elf_types<size>::Elf_Addr plt_address)
+  { this->do_fill_first_plt_entry(pov, got_address, plt_address); }
+
+  // Fill in a normal PLT entry.  Returns the offset into the entry that
+  // should be the initial GOT slot value.
+  unsigned int
+  fill_plt_entry(unsigned char* pov,
+                typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+                typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+                unsigned int got_offset,
+                unsigned int plt_offset,
+                unsigned int plt_index)
+  {
+    return this->do_fill_plt_entry(pov, got_address, plt_address,
+                                  got_offset, plt_offset, plt_index);
+  }
+
+  // Fill in the reserved TLSDESC PLT entry.
+  void
+  fill_tlsdesc_entry(unsigned char* pov,
+                    typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+                    typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+                    typename elfcpp::Elf_types<size>::Elf_Addr got_base,
+                    unsigned int tlsdesc_got_offset,
+                    unsigned int plt_offset)
+  {
+    this->do_fill_tlsdesc_entry(pov, got_address, plt_address, got_base,
+                               tlsdesc_got_offset, plt_offset);
+  }
+
+  virtual unsigned int
+  do_get_plt_entry_size() const = 0;
+
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov,
+                         typename elfcpp::Elf_types<size>::Elf_Addr got_addr,
+                         typename elfcpp::Elf_types<size>::Elf_Addr plt_addr)
+    = 0;
+
+  virtual unsigned int
+  do_fill_plt_entry(unsigned char* pov,
+                   typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+                   typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+                   unsigned int got_offset,
+                   unsigned int plt_offset,
+                   unsigned int plt_index) = 0;
+
+  virtual void
+  do_fill_tlsdesc_entry(unsigned char* pov,
+                       typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+                       typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+                       typename elfcpp::Elf_types<size>::Elf_Addr got_base,
+                       unsigned int tlsdesc_got_offset,
+                       unsigned int plt_offset) = 0;
+
+  virtual void
+  do_add_eh_frame(Layout* layout) = 0;
+
   void
   do_adjust_output_section(Output_section* os);
 
@@ -179,27 +256,11 @@ class Output_data_plt_x86_64 : public Output_section_data
   do_print_to_mapfile(Mapfile* mapfile) const
   { mapfile->print_output_data(this, _("** PLT")); }
 
- private:
-  // The size of an entry in the PLT.
-  static const int plt_entry_size = 16;
-
-  // The first entry in the PLT.
-  // From the AMD64 ABI: "Unlike Intel386 ABI, this ABI uses the same
-  // procedure linkage table for both programs and shared objects."
-  static const unsigned char first_plt_entry[plt_entry_size];
-
-  // Other entries in the PLT for an executable.
-  static const unsigned char plt_entry[plt_entry_size];
-
-  // The reserved TLSDESC entry in the PLT for an executable.
-  static const unsigned char tlsdesc_plt_entry[plt_entry_size];
-
-  // The .eh_frame unwind information for the PLT.
+  // The CIE of the .eh_frame unwind information for the PLT.
   static const int plt_eh_frame_cie_size = 16;
-  static const int plt_eh_frame_fde_size = 32;
   static const unsigned char plt_eh_frame_cie[plt_eh_frame_cie_size];
-  static const unsigned char plt_eh_frame_fde[plt_eh_frame_fde_size];
 
+ private:
   // Set the final size.
   void
   set_final_data_size();
@@ -237,6 +298,84 @@ class Output_data_plt_x86_64 : public Output_section_data
   Free_list free_list_;
 };
 
+template<int size>
+class Output_data_plt_x86_64_standard : public Output_data_plt_x86_64<size>
+{
+ public:
+  Output_data_plt_x86_64_standard(Layout* layout,
+                                 Output_data_got<64, false>* got,
+                                 Output_data_space* got_plt,
+                                 Output_data_space* got_irelative)
+    : Output_data_plt_x86_64<size>(layout, plt_entry_size,
+                                  got, got_plt, got_irelative)
+  { }
+
+  Output_data_plt_x86_64_standard(Layout* layout,
+                                 Output_data_got<64, false>* got,
+                                 Output_data_space* got_plt,
+                                 Output_data_space* got_irelative,
+                                 unsigned int plt_count)
+    : Output_data_plt_x86_64<size>(layout, plt_entry_size,
+                                  got, got_plt, got_irelative,
+                                  plt_count)
+  { }
+
+ protected:
+  virtual unsigned int
+  do_get_plt_entry_size() const
+  { return plt_entry_size; }
+
+  virtual void
+  do_add_eh_frame(Layout* layout)
+  {
+    layout->add_eh_frame_for_plt(this,
+                                this->plt_eh_frame_cie,
+                                this->plt_eh_frame_cie_size,
+                                plt_eh_frame_fde,
+                                plt_eh_frame_fde_size);
+  }
+
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov,
+                         typename elfcpp::Elf_types<size>::Elf_Addr got_addr,
+                         typename elfcpp::Elf_types<size>::Elf_Addr plt_addr);
+
+  virtual unsigned int
+  do_fill_plt_entry(unsigned char* pov,
+                   typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+                   typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+                   unsigned int got_offset,
+                   unsigned int plt_offset,
+                   unsigned int plt_index);
+
+  virtual void
+  do_fill_tlsdesc_entry(unsigned char* pov,
+                       typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+                       typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+                       typename elfcpp::Elf_types<size>::Elf_Addr got_base,
+                       unsigned int tlsdesc_got_offset,
+                       unsigned int plt_offset);
+
+ private:
+  // The size of an entry in the PLT.
+  static const int plt_entry_size = 16;
+
+  // The first entry in the PLT.
+  // From the AMD64 ABI: "Unlike Intel386 ABI, this ABI uses the same
+  // procedure linkage table for both programs and shared objects."
+  static const unsigned char first_plt_entry[plt_entry_size];
+
+  // Other entries in the PLT for an executable.
+  static const unsigned char plt_entry[plt_entry_size];
+
+  // The reserved TLSDESC entry in the PLT for an executable.
+  static const unsigned char tlsdesc_plt_entry[plt_entry_size];
+
+  // The .eh_frame unwind information for the PLT.
+  static const int plt_eh_frame_fde_size = 32;
+  static const unsigned char plt_eh_frame_fde[plt_eh_frame_fde_size];
+};
+
 // The x86_64 target class.
 // See the ABI at
 //   http://www.x86-64.org/documentation/abi.pdf
@@ -252,8 +391,8 @@ class Target_x86_64 : public Sized_target<size, false>
   // uses only Elf64_Rela relocation entries with explicit addends."
   typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, false> Reloc_section;
 
-  Target_x86_64()
-    : Sized_target<size, false>(&x86_64_info),
+  Target_x86_64(const Target::Target_info* info = &x86_64_info)
+    : Sized_target<size, false>(info),
       got_(NULL), plt_(NULL), got_plt_(NULL), got_irelative_(NULL),
       got_tlsdesc_(NULL), global_offset_table_(NULL), rela_dyn_(NULL),
       rela_irelative_(NULL), copy_relocs_(elfcpp::R_X86_64_COPY),
@@ -268,16 +407,16 @@ class Target_x86_64 : public Sized_target<size, false>
   // Scan the relocations to look for symbol adjustments.
   void
   gc_process_relocs(Symbol_table* symtab,
-                   Layout* layout,
-                   Sized_relobj_file<size, false>* object,
-                   unsigned int data_shndx,
-                   unsigned int sh_type,
-                   const unsigned char* prelocs,
-                   size_t reloc_count,
-                   Output_section* output_section,
-                   bool needs_special_offset_handling,
-                   size_t local_symbol_count,
-                   const unsigned char* plocal_symbols);
+                   Layout* layout,
+                   Sized_relobj_file<size, false>* object,
+                   unsigned int data_shndx,
+                   unsigned int sh_type,
+                   const unsigned char* prelocs,
+                   size_t reloc_count,
+                   Output_section* output_section,
+                   bool needs_special_offset_handling,
+                   size_t local_symbol_count,
+                   const unsigned char* plocal_symbols);
 
   // Scan the relocations to look for symbol adjustments.
   void
@@ -439,7 +578,7 @@ class Target_x86_64 : public Sized_target<size, false>
   // necessary dynamic relocations.
   void
   reserve_local_got_entry(unsigned int got_index,
-                         Sized_relobj<size, false>* obj,
+                         Sized_relobj<size, false>* obj,
                          unsigned int r_sym,
                          unsigned int got_type);
 
@@ -477,6 +616,48 @@ class Target_x86_64 : public Sized_target<size, false>
     return this->tlsdesc_reloc_info_.size() - 1;
   }
 
+  Output_data_plt_x86_64<size>*
+  make_data_plt(Layout* layout,
+               Output_data_got<64, false>* got,
+               Output_data_space* got_plt,
+               Output_data_space* got_irelative)
+  {
+    return this->do_make_data_plt(layout, got, got_plt, got_irelative);
+  }
+
+  Output_data_plt_x86_64<size>*
+  make_data_plt(Layout* layout,
+               Output_data_got<64, false>* got,
+               Output_data_space* got_plt,
+               Output_data_space* got_irelative,
+               unsigned int plt_count)
+  {
+    return this->do_make_data_plt(layout, got, got_plt, got_irelative,
+                                 plt_count);
+  }
+
+  virtual Output_data_plt_x86_64<size>*
+  do_make_data_plt(Layout* layout,
+                  Output_data_got<64, false>* got,
+                  Output_data_space* got_plt,
+                  Output_data_space* got_irelative)
+  {
+    return new Output_data_plt_x86_64_standard<size>(layout, got, got_plt,
+                                                    got_irelative);
+  }
+
+  virtual Output_data_plt_x86_64<size>*
+  do_make_data_plt(Layout* layout,
+                  Output_data_got<64, false>* got,
+                  Output_data_space* got_plt,
+                  Output_data_space* got_irelative,
+                  unsigned int plt_count)
+  {
+    return new Output_data_plt_x86_64_standard<size>(layout, got, got_plt,
+                                                    got_irelative,
+                                                    plt_count);
+  }
+
  private:
   // The class which scans relocations.
   class Scan
@@ -508,22 +689,22 @@ class Target_x86_64 : public Sized_target<size, false>
     inline bool
     local_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
                                        Target_x86_64* target,
-                                       Sized_relobj_file<size, false>* object,
-                                       unsigned int data_shndx,
-                                       Output_section* output_section,
-                                       const elfcpp::Rela<size, false>& reloc,
+                                       Sized_relobj_file<size, false>* object,
+                                       unsigned int data_shndx,
+                                       Output_section* output_section,
+                                       const elfcpp::Rela<size, false>& reloc,
                                        unsigned int r_type,
-                                       const elfcpp::Sym<size, false>& lsym);
+                                       const elfcpp::Sym<size, false>& lsym);
 
     inline bool
     global_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
-                                        Target_x86_64* target,
-                                        Sized_relobj_file<size, false>* object,
-                                        unsigned int data_shndx,
-                                        Output_section* output_section,
-                                        const elfcpp::Rela<size, false>& reloc,
+                                        Target_x86_64* target,
+                                        Sized_relobj_file<size, false>* object,
+                                        unsigned int data_shndx,
+                                        Output_section* output_section,
+                                        const elfcpp::Rela<size, false>& reloc,
                                         unsigned int r_type,
-                                        Symbol* gsym);
+                                        Symbol* gsym);
 
   private:
     static void
@@ -580,7 +761,7 @@ class Target_x86_64 : public Sized_target<size, false>
     // Do a TLS relocation.
     inline void
     relocate_tls(const Relocate_info<size, false>*, Target_x86_64*,
-                 size_t relnum, const elfcpp::Rela<size, false>&,
+                size_t relnum, const elfcpp::Rela<size, false>&,
                 unsigned int r_type, const Sized_symbol<size>*,
                 const Symbol_value<size>*,
                 unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
@@ -731,7 +912,7 @@ class Target_x86_64 : public Sized_target<size, false>
   // Add a potential copy relocation.
   void
   copy_reloc(Symbol_table* symtab, Layout* layout,
-             Sized_relobj_file<size, false>* object,
+            Sized_relobj_file<size, false>* object,
             unsigned int shndx, Output_section* output_section,
             Symbol* sym, const elfcpp::Rela<size, false>& reloc)
   {
@@ -818,6 +999,8 @@ const Target::Target_info Target_x86_64<64>::x86_64_info =
   0x400000,            // default_text_segment_address
   0x1000,              // abi_pagesize (overridable by -z max-page-size)
   0x1000,              // common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
   elfcpp::SHN_UNDEF,   // small_common_shndx
   elfcpp::SHN_X86_64_LCOMMON,  // large_common_shndx
   0,                   // small_common_section_flags
@@ -842,6 +1025,8 @@ const Target::Target_info Target_x86_64<32>::x86_64_info =
   0x400000,            // default_text_segment_address
   0x1000,              // abi_pagesize (overridable by -z max-page-size)
   0x1000,              // common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
   elfcpp::SHN_UNDEF,   // small_common_shndx
   elfcpp::SHN_X86_64_LCOMMON,  // large_common_shndx
   0,                   // small_common_section_flags
@@ -988,18 +1173,13 @@ Output_data_plt_x86_64<size>::init(Layout* layout)
   layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
                                  elfcpp::SHF_ALLOC, this->rel_,
                                  ORDER_DYNAMIC_PLT_RELOCS, false);
-
-  // Add unwind information if requested.
-  if (parameters->options().ld_generated_unwind_info())
-    layout->add_eh_frame_for_plt(this, plt_eh_frame_cie, plt_eh_frame_cie_size,
-                                plt_eh_frame_fde, plt_eh_frame_fde_size);
 }
 
 template<int size>
 void
 Output_data_plt_x86_64<size>::do_adjust_output_section(Output_section* os)
 {
-  os->set_entsize(plt_entry_size);
+  os->set_entsize(this->get_plt_entry_size());
 }
 
 // Add an entry to the PLT.
@@ -1040,7 +1220,7 @@ Output_data_plt_x86_64<size>::add_entry(Symbol_table* symtab, Layout* layout,
       // Note that when setting the PLT offset for a non-IRELATIVE
       // entry we skip the initial reserved PLT entry.
       plt_index = *pcount + offset;
-      plt_offset = plt_index * plt_entry_size;
+      plt_offset = plt_index * this->get_plt_entry_size();
 
       ++*pcount;
 
@@ -1057,7 +1237,8 @@ Output_data_plt_x86_64<size>::add_entry(Symbol_table* symtab, Layout* layout,
       // FIXME: This is probably not correct for IRELATIVE relocs.
 
       // For incremental updates, find an available slot.
-      plt_offset = this->free_list_.allocate(plt_entry_size, plt_entry_size, 0);
+      plt_offset = this->free_list_.allocate(this->get_plt_entry_size(),
+                                            this->get_plt_entry_size(), 0);
       if (plt_offset == -1)
        gold_fallback(_("out of patch space (PLT);"
                        " relink with --incremental-full"));
@@ -1065,7 +1246,7 @@ Output_data_plt_x86_64<size>::add_entry(Symbol_table* symtab, Layout* layout,
       // The GOT and PLT entries have a 1-1 correspondance, so the GOT offset
       // can be calculated from the PLT index, adjusting for the three
       // reserved entries at the beginning of the GOT.
-      plt_index = plt_offset / plt_entry_size - 1;
+      plt_index = plt_offset / this->get_plt_entry_size() - 1;
       got_offset = (plt_index - offset + reserved) * 8;
     }
 
@@ -1090,7 +1271,7 @@ Output_data_plt_x86_64<size>::add_local_ifunc_entry(
     Sized_relobj_file<size, false>* relobj,
     unsigned int local_sym_index)
 {
-  unsigned int plt_offset = this->irelative_count_ * plt_entry_size;
+  unsigned int plt_offset = this->irelative_count_ * this->get_plt_entry_size();
   ++this->irelative_count_;
 
   section_offset_type got_offset = this->got_irelative_->current_data_size();
@@ -1202,7 +1383,7 @@ Output_data_plt_x86_64<size>::address_for_global(const Symbol* gsym)
   uint64_t offset = 0;
   if (gsym->type() == elfcpp::STT_GNU_IFUNC
       && gsym->can_use_relative_reloc(false))
-    offset = (this->count_ + 1) * plt_entry_size;
+    offset = (this->count_ + 1) * this->get_plt_entry_size();
   return this->address() + offset;
 }
 
@@ -1213,7 +1394,7 @@ template<int size>
 uint64_t
 Output_data_plt_x86_64<size>::address_for_local(const Relobj*, unsigned int)
 {
-  return this->address() + (this->count_ + 1) * plt_entry_size;
+  return this->address() + (this->count_ + 1) * this->get_plt_entry_size();
 }
 
 // Set the final size.
@@ -1224,14 +1405,14 @@ Output_data_plt_x86_64<size>::set_final_data_size()
   unsigned int count = this->count_ + this->irelative_count_;
   if (this->has_tlsdesc_entry())
     ++count;
-  this->set_data_size((count + 1) * plt_entry_size);
+  this->set_data_size((count + 1) * this->get_plt_entry_size());
 }
 
 // The first entry in the PLT for an executable.
 
 template<int size>
 const unsigned char
-Output_data_plt_x86_64<size>::first_plt_entry[plt_entry_size] =
+Output_data_plt_x86_64_standard<size>::first_plt_entry[plt_entry_size] =
 {
   // From AMD64 ABI Draft 0.98, page 76
   0xff, 0x35,  // pushq contents of memory address
@@ -1241,11 +1422,28 @@ Output_data_plt_x86_64<size>::first_plt_entry[plt_entry_size] =
   0x90, 0x90, 0x90, 0x90   // noop (x4)
 };
 
+template<int size>
+void
+Output_data_plt_x86_64_standard<size>::do_fill_first_plt_entry(
+    unsigned char* pov,
+    typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+    typename elfcpp::Elf_types<size>::Elf_Addr plt_address)
+{
+  memcpy(pov, first_plt_entry, plt_entry_size);
+  // We do a jmp relative to the PC at the end of this instruction.
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+                                             (got_address + 8
+                                              - (plt_address + 6)));
+  elfcpp::Swap<32, false>::writeval(pov + 8,
+                                   (got_address + 16
+                                    - (plt_address + 12)));
+}
+
 // Subsequent entries in the PLT for an executable.
 
 template<int size>
 const unsigned char
-Output_data_plt_x86_64<size>::plt_entry[plt_entry_size] =
+Output_data_plt_x86_64_standard<size>::plt_entry[plt_entry_size] =
 {
   // From AMD64 ABI Draft 0.98, page 76
   0xff, 0x25,  // jmpq indirect
@@ -1256,11 +1454,34 @@ Output_data_plt_x86_64<size>::plt_entry[plt_entry_size] =
   0, 0, 0, 0   // replaced with offset to start of .plt
 };
 
+template<int size>
+unsigned int
+Output_data_plt_x86_64_standard<size>::do_fill_plt_entry(
+    unsigned char* pov,
+    typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+    typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+    unsigned int got_offset,
+    unsigned int plt_offset,
+    unsigned int plt_index)
+{
+  memcpy(pov, plt_entry, plt_entry_size);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+                                             (got_address + got_offset
+                                              - (plt_address + plt_offset
+                                                 + 6)));
+
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 7, plt_index);
+  elfcpp::Swap<32, false>::writeval(pov + 12,
+                                   - (plt_offset + plt_entry_size));
+
+  return 6;
+}
+
 // The reserved TLSDESC entry in the PLT for an executable.
 
 template<int size>
 const unsigned char
-Output_data_plt_x86_64<size>::tlsdesc_plt_entry[plt_entry_size] =
+Output_data_plt_x86_64_standard<size>::tlsdesc_plt_entry[plt_entry_size] =
 {
   // From Alexandre Oliva, "Thread-Local Storage Descriptors for IA32
   // and AMD64/EM64T", Version 0.9.4 (2005-10-10).
@@ -1272,10 +1493,32 @@ Output_data_plt_x86_64<size>::tlsdesc_plt_entry[plt_entry_size] =
   0x40, 0
 };
 
+template<int size>
+void
+Output_data_plt_x86_64_standard<size>::do_fill_tlsdesc_entry(
+    unsigned char* pov,
+    typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+    typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+    typename elfcpp::Elf_types<size>::Elf_Addr got_base,
+    unsigned int tlsdesc_got_offset,
+    unsigned int plt_offset)
+{
+  memcpy(pov, tlsdesc_plt_entry, plt_entry_size);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+                                             (got_address + 8
+                                              - (plt_address + plt_offset
+                                                 + 6)));
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 8,
+                                             (got_base
+                                              + tlsdesc_got_offset
+                                              - (plt_address + plt_offset
+                                                 + 12)));
+}
+
 // The .eh_frame unwind information for the PLT.
 
 template<int size>
-const unsigned char 
+const unsigned char
 Output_data_plt_x86_64<size>::plt_eh_frame_cie[plt_eh_frame_cie_size] =
 {
   1,                           // CIE version.
@@ -1296,7 +1539,7 @@ Output_data_plt_x86_64<size>::plt_eh_frame_cie[plt_eh_frame_cie_size] =
 
 template<int size>
 const unsigned char
-Output_data_plt_x86_64<size>::plt_eh_frame_fde[plt_eh_frame_fde_size] =
+Output_data_plt_x86_64_standard<size>::plt_eh_frame_fde[plt_eh_frame_fde_size] =
 {
   0, 0, 0, 0,                          // Replaced with offset to .plt.
   0, 0, 0, 0,                          // Replaced with size of .plt.
@@ -1356,15 +1599,8 @@ Output_data_plt_x86_64<size>::do_write(Output_file* of)
   typename elfcpp::Elf_types<size>::Elf_Addr got_address
     = this->got_plt_->address();
 
-  memcpy(pov, first_plt_entry, plt_entry_size);
-  // We do a jmp relative to the PC at the end of this instruction.
-  elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
-                                             (got_address + 8
-                                              - (plt_address + 6)));
-  elfcpp::Swap<32, false>::writeval(pov + 8,
-                                   (got_address + 16
-                                    - (plt_address + 12)));
-  pov += plt_entry_size;
+  this->fill_first_plt_entry(pov, got_address, plt_address);
+  pov += this->get_plt_entry_size();
 
   unsigned char* got_pov = got_view;
 
@@ -1379,47 +1615,35 @@ Output_data_plt_x86_64<size>::do_write(Output_file* of)
   memset(got_pov, 0, 16);
   got_pov += 16;
 
-  unsigned int plt_offset = plt_entry_size;
+  unsigned int plt_offset = this->get_plt_entry_size();
   unsigned int got_offset = 24;
   const unsigned int count = this->count_ + this->irelative_count_;
   for (unsigned int plt_index = 0;
        plt_index < count;
        ++plt_index,
-        pov += plt_entry_size,
+        pov += this->get_plt_entry_size(),
         got_pov += 8,
-        plt_offset += plt_entry_size,
+        plt_offset += this->get_plt_entry_size(),
         got_offset += 8)
     {
       // Set and adjust the PLT entry itself.
-      memcpy(pov, plt_entry, plt_entry_size);
-      elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
-                                                 (got_address + got_offset
-                                                  - (plt_address + plt_offset
-                                                     + 6)));
-
-      elfcpp::Swap_unaligned<32, false>::writeval(pov + 7, plt_index);
-      elfcpp::Swap<32, false>::writeval(pov + 12,
-                                       - (plt_offset + plt_entry_size));
+      unsigned int lazy_offset = this->fill_plt_entry(pov,
+                                                     got_address, plt_address,
+                                                     got_offset, plt_offset,
+                                                     plt_index);
 
       // Set the entry in the GOT.
-      elfcpp::Swap<64, false>::writeval(got_pov, plt_address + plt_offset + 6);
+      elfcpp::Swap<64, false>::writeval(got_pov,
+                                       plt_address + plt_offset + lazy_offset);
     }
 
   if (this->has_tlsdesc_entry())
     {
       // Set and adjust the reserved TLSDESC PLT entry.
       unsigned int tlsdesc_got_offset = this->get_tlsdesc_got_offset();
-      memcpy(pov, tlsdesc_plt_entry, plt_entry_size);
-      elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
-                                                 (got_address + 8
-                                                  - (plt_address + plt_offset
-                                                     + 6)));
-      elfcpp::Swap_unaligned<32, false>::writeval(pov + 8,
-                                                 (got_base
-                                                  + tlsdesc_got_offset
-                                                  - (plt_address + plt_offset
-                                                     + 12)));
-      pov += plt_entry_size;
+      this->fill_tlsdesc_entry(pov, got_address, plt_address, got_base,
+                              tlsdesc_got_offset, plt_offset);
+      pov += this->get_plt_entry_size();
     }
 
   gold_assert(static_cast<section_size_type>(pov - oview) == oview_size);
@@ -1440,9 +1664,13 @@ Target_x86_64<size>::make_plt_section(Symbol_table* symtab, Layout* layout)
       // Create the GOT sections first.
       this->got_section(symtab, layout);
 
-      this->plt_ = new Output_data_plt_x86_64<size>(layout, this->got_,
-                                                   this->got_plt_,
-                                                   this->got_irelative_);
+      this->plt_ = this->make_data_plt(layout, this->got_, this->got_plt_,
+                                      this->got_irelative_);
+
+      // Add unwind information if requested.
+      if (parameters->options().ld_generated_unwind_info())
+       this->plt_->add_eh_frame(layout);
+
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
                                      (elfcpp::SHF_ALLOC
                                       | elfcpp::SHF_EXECINSTR),
@@ -1515,7 +1743,7 @@ template<int size>
 unsigned int
 Target_x86_64<size>::first_plt_entry_offset() const
 {
-  return Output_data_plt_x86_64<size>::first_plt_entry_offset();
+  return this->plt_->first_plt_entry_offset();
 }
 
 // Return the size of each PLT entry.
@@ -1524,7 +1752,7 @@ template<int size>
 unsigned int
 Target_x86_64<size>::plt_entry_size() const
 {
-  return Output_data_plt_x86_64<size>::get_plt_entry_size();
+  return this->plt_->get_plt_entry_size();
 }
 
 // Create the GOT and PLT sections for an incremental update.
@@ -1581,10 +1809,15 @@ Target_x86_64<size>::init_got_plt_for_update(Symbol_table* symtab,
                                  ORDER_NON_RELRO_FIRST, false);
 
   // Create the PLT section.
-  this->plt_ = new Output_data_plt_x86_64<size>(layout, this->got_,
-                                               this->got_plt_,
-                                               this->got_irelative_,
-                                               plt_count);
+  this->plt_ = this->make_data_plt(layout, this->got_,
+                                  this->got_plt_,
+                                  this->got_irelative_,
+                                  plt_count);
+
+  // Add unwind information if requested.
+  if (parameters->options().ld_generated_unwind_info())
+    this->plt_->add_eh_frame(layout);
+
   layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
                                  elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR,
                                  this->plt_, ORDER_PLT, false);
@@ -1758,7 +1991,7 @@ Target_x86_64<size>::define_tls_base_symbol(Symbol_table* symtab,
 template<int size>
 void
 Target_x86_64<size>::reserve_tlsdesc_entries(Symbol_table* symtab,
-                                             Layout* layout)
+                                            Layout* layout)
 {
   if (this->plt_ == NULL)
     this->make_plt_section(symtab, layout);
@@ -1788,7 +2021,7 @@ Target_x86_64<size>::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
       Output_data_got<64, false>* got = this->got_section(symtab, layout);
       unsigned int got_offset = got->add_constant(0);
       rela_dyn->add_local(object, 0, elfcpp::R_X86_64_DTPMOD64, got,
-                          got_offset, 0);
+                         got_offset, 0);
       got->add_constant(0);
       this->got_mod_index_offset_ = got_offset;
     }
@@ -1996,10 +2229,10 @@ Target_x86_64<size>::Scan::check_non_pic(Relobj* object, unsigned int r_type,
       // section.  But we can still wind up issuing more than one
       // error per object file.
       if (this->issued_non_pic_error_)
-        return;
+       return;
       gold_assert(parameters->options().output_is_position_independent());
       object->error(_("requires unsupported dynamic reloc %u; "
-                      "recompile with -fPIC"),
+                     "recompile with -fPIC"),
                    r_type);
       this->issued_non_pic_error_ = true;
       return;
@@ -2021,7 +2254,7 @@ Target_x86_64<size>::Scan::reloc_needs_plt_for_ifunc(
   int flags = Scan::get_reference_flags(r_type);
   if (flags & Symbol::TLS_REF)
     gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
-               object->name().c_str(), r_type);
+              object->name().c_str(), r_type);
   return flags != 0;
 }
 
@@ -2062,15 +2295,15 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
       // R_X86_64_RELATIVE relocation so the dynamic loader can
       // relocate it easily.
       if (parameters->options().output_is_position_independent())
-        {
-          unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-          Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+       {
+         unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+         Reloc_section* rela_dyn = target->rela_dyn_section(layout);
          rela_dyn->add_local_relative(object, r_sym,
                                       elfcpp::R_X86_64_RELATIVE,
                                       output_section, data_shndx,
                                       reloc.get_r_offset(),
                                       reloc.get_r_addend(), is_ifunc);
-        }
+       }
       break;
 
     case elfcpp::R_X86_64_32:
@@ -2082,7 +2315,7 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
       // location.  We can't use an R_X86_64_RELATIVE relocation
       // because that is always a 64-bit relocation.
       if (parameters->options().output_is_position_independent())
-        {
+       {
          // Use R_X86_64_RELATIVE relocation for R_X86_64_32 under x32.
          if (size == 32 && r_type == elfcpp::R_X86_64_32)
            {
@@ -2096,17 +2329,17 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
              break;
            }
 
-          this->check_non_pic(object, r_type, NULL);
+         this->check_non_pic(object, r_type, NULL);
 
-          Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+         Reloc_section* rela_dyn = target->rela_dyn_section(layout);
          unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-          if (lsym.get_st_type() != elfcpp::STT_SECTION)
+         if (lsym.get_st_type() != elfcpp::STT_SECTION)
            rela_dyn->add_local(object, r_sym, r_type, output_section,
                                data_shndx, reloc.get_r_offset(),
                                reloc.get_r_addend());
-          else
-            {
-              gold_assert(lsym.get_st_value() == 0);
+         else
+           {
+             gold_assert(lsym.get_st_value() == 0);
              unsigned int shndx = lsym.get_st_shndx();
              bool is_ordinary;
              shndx = object->adjust_sym_shndx(r_sym, shndx,
@@ -2119,8 +2352,8 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
                                            r_type, output_section,
                                            data_shndx, reloc.get_r_offset(),
                                            reloc.get_r_addend());
-            }
-        }
+           }
+       }
       break;
 
     case elfcpp::R_X86_64_PC64:
@@ -2150,9 +2383,9 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
     case elfcpp::R_X86_64_GOTPCREL:
     case elfcpp::R_X86_64_GOTPLT64:
       {
-        // The symbol requires a GOT entry.
-        Output_data_got<64, false>* got = target->got_section(symtab, layout);
-        unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+       // The symbol requires a GOT entry.
+       Output_data_got<64, false>* got = target->got_section(symtab, layout);
+       unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
 
        // For a STT_GNU_IFUNC symbol we want the PLT offset.  That
        // lets function pointers compare correctly with shared
@@ -2162,13 +2395,13 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
          is_new = got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD);
        else
          is_new = got->add_local(object, r_sym, GOT_TYPE_STANDARD);
-        if (is_new)
-          {
-            // If we are generating a shared object, we need to add a
-            // dynamic relocation for this symbol's GOT entry.
-            if (parameters->options().output_is_position_independent())
-              {
-                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+       if (is_new)
+         {
+           // If we are generating a shared object, we need to add a
+           // dynamic relocation for this symbol's GOT entry.
+           if (parameters->options().output_is_position_independent())
+             {
+               Reloc_section* rela_dyn = target->rela_dyn_section(layout);
                // R_X86_64_RELATIVE assumes a 64-bit relocation.
                if (r_type != elfcpp::R_X86_64_GOT32)
                  {
@@ -2178,19 +2411,19 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
                                                 elfcpp::R_X86_64_RELATIVE,
                                                 got, got_offset, 0, is_ifunc);
                  }
-                else
-                  {
-                    this->check_non_pic(object, r_type, NULL);
-
-                    gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
-                    rela_dyn->add_local(
-                        object, r_sym, r_type, got,
-                        object->local_got_offset(r_sym, GOT_TYPE_STANDARD), 0);
-                  }
-              }
-          }
-        // For GOTPLT64, we'd normally want a PLT section, but since
-        // we know this is a local symbol, no PLT is needed.
+               else
+                 {
+                   this->check_non_pic(object, r_type, NULL);
+
+                   gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
+                   rela_dyn->add_local(
+                       object, r_sym, r_type, got,
+                       object->local_got_offset(r_sym, GOT_TYPE_STANDARD), 0);
+                 }
+             }
+         }
+       // For GOTPLT64, we'd normally want a PLT section, but since
+       // we know this is a local symbol, no PLT is needed.
       }
       break;
 
@@ -2219,50 +2452,50 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
       {
        bool output_is_shared = parameters->options().shared();
        const tls::Tls_optimization optimized_type
-            = Target_x86_64<size>::optimize_tls_reloc(!output_is_shared,
+           = Target_x86_64<size>::optimize_tls_reloc(!output_is_shared,
                                                      r_type);
        switch (r_type)
          {
-          case elfcpp::R_X86_64_TLSGD:       // General-dynamic
-            if (optimized_type == tls::TLSOPT_NONE)
-              {
-                // Create a pair of GOT entries for the module index and
-                // dtv-relative offset.
-                Output_data_got<64, false>* got
-                    = target->got_section(symtab, layout);
-                unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+         case elfcpp::R_X86_64_TLSGD:       // General-dynamic
+           if (optimized_type == tls::TLSOPT_NONE)
+             {
+               // Create a pair of GOT entries for the module index and
+               // dtv-relative offset.
+               Output_data_got<64, false>* got
+                   = target->got_section(symtab, layout);
+               unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
                unsigned int shndx = lsym.get_st_shndx();
                bool is_ordinary;
                shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
                if (!is_ordinary)
                  object->error(_("local symbol %u has bad shndx %u"),
                              r_sym, shndx);
-                else
+               else
                  got->add_local_pair_with_rel(object, r_sym,
                                               shndx,
                                               GOT_TYPE_TLS_PAIR,
                                               target->rela_dyn_section(layout),
                                               elfcpp::R_X86_64_DTPMOD64, 0);
-              }
-            else if (optimized_type != tls::TLSOPT_TO_LE)
+             }
+           else if (optimized_type != tls::TLSOPT_TO_LE)
              unsupported_reloc_local(object, r_type);
-            break;
+           break;
 
-          case elfcpp::R_X86_64_GOTPC32_TLSDESC:
-            target->define_tls_base_symbol(symtab, layout);
+         case elfcpp::R_X86_64_GOTPC32_TLSDESC:
+           target->define_tls_base_symbol(symtab, layout);
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // Create reserved PLT and GOT entries for the resolver.
-               target->reserve_tlsdesc_entries(symtab, layout);
-
-               // Generate a double GOT entry with an
-               // R_X86_64_TLSDESC reloc.  The R_X86_64_TLSDESC reloc
-               // is resolved lazily, so the GOT entry needs to be in
-               // an area in .got.plt, not .got.  Call got_section to
-               // make sure the section has been created.
+               // Create reserved PLT and GOT entries for the resolver.
+               target->reserve_tlsdesc_entries(symtab, layout);
+
+               // Generate a double GOT entry with an
+               // R_X86_64_TLSDESC reloc.  The R_X86_64_TLSDESC reloc
+               // is resolved lazily, so the GOT entry needs to be in
+               // an area in .got.plt, not .got.  Call got_section to
+               // make sure the section has been created.
                target->got_section(symtab, layout);
-                Output_data_got<64, false>* got = target->got_tlsdesc_section();
-                unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+               Output_data_got<64, false>* got = target->got_tlsdesc_section();
+               unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
                if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
                  {
                    unsigned int got_offset = got->add_constant(0);
@@ -2283,47 +2516,47 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
              unsupported_reloc_local(object, r_type);
            break;
 
-          case elfcpp::R_X86_64_TLSDESC_CALL:
+         case elfcpp::R_X86_64_TLSDESC_CALL:
            break;
 
-          case elfcpp::R_X86_64_TLSLD:       // Local-dynamic
+         case elfcpp::R_X86_64_TLSLD:       // Local-dynamic
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // Create a GOT entry for the module index.
-               target->got_mod_index_entry(symtab, layout, object);
+               // Create a GOT entry for the module index.
+               target->got_mod_index_entry(symtab, layout, object);
              }
            else if (optimized_type != tls::TLSOPT_TO_LE)
              unsupported_reloc_local(object, r_type);
            break;
 
-          case elfcpp::R_X86_64_DTPOFF32:
-          case elfcpp::R_X86_64_DTPOFF64:
+         case elfcpp::R_X86_64_DTPOFF32:
+         case elfcpp::R_X86_64_DTPOFF64:
            break;
 
-          case elfcpp::R_X86_64_GOTTPOFF:    // Initial-exec
+         case elfcpp::R_X86_64_GOTTPOFF:    // Initial-exec
            layout->set_has_static_tls();
-            if (optimized_type == tls::TLSOPT_NONE)
-              {
-               // Create a GOT entry for the tp-relative offset.
-               Output_data_got<64, false>* got
-                   = target->got_section(symtab, layout);
-               unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-               got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET,
+           if (optimized_type == tls::TLSOPT_NONE)
+             {
+               // Create a GOT entry for the tp-relative offset.
+               Output_data_got<64, false>* got
+                   = target->got_section(symtab, layout);
+               unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+               got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET,
                                        target->rela_dyn_section(layout),
                                        elfcpp::R_X86_64_TPOFF64);
-              }
-            else if (optimized_type != tls::TLSOPT_TO_LE)
-              unsupported_reloc_local(object, r_type);
-            break;
+             }
+           else if (optimized_type != tls::TLSOPT_TO_LE)
+             unsupported_reloc_local(object, r_type);
+           break;
 
-          case elfcpp::R_X86_64_TPOFF32:     // Local-exec
+         case elfcpp::R_X86_64_TPOFF32:     // Local-exec
            layout->set_has_static_tls();
-            if (output_is_shared)
-              unsupported_reloc_local(object, r_type);
+           if (output_is_shared)
+             unsupported_reloc_local(object, r_type);
            break;
 
-          default:
-            gold_unreachable();
+         default:
+           gold_unreachable();
          }
       }
       break;
@@ -2369,7 +2602,7 @@ Target_x86_64<size>::Scan::possible_function_pointer_reloc(unsigned int r_type)
     case elfcpp::R_X86_64_GOTPCREL:
     case elfcpp::R_X86_64_GOTPLT64:
       {
-        return true;
+       return true;
       }
     }
   return false;
@@ -2396,7 +2629,7 @@ Target_x86_64<size>::Scan::local_reloc_may_be_function_pointer(
   // not possible to distinguish pointer taken versus a call by looking at
   // the relocation types.
   return (parameters->options().shared()
-          || possible_function_pointer_reloc(r_type));
+         || possible_function_pointer_reloc(r_type));
 }
 
 // For safe ICF, scan a relocation for a global symbol to check if it
@@ -2419,10 +2652,10 @@ Target_x86_64<size>::Scan::global_reloc_may_be_function_pointer(
   // When building a shared library, do not fold symbols whose visibility
   // is hidden, internal or protected.
   return ((parameters->options().shared()
-           && (gsym->visibility() == elfcpp::STV_INTERNAL
+          && (gsym->visibility() == elfcpp::STV_INTERNAL
               || gsym->visibility() == elfcpp::STV_PROTECTED
               || gsym->visibility() == elfcpp::STV_HIDDEN))
-          || possible_function_pointer_reloc(r_type));
+         || possible_function_pointer_reloc(r_type));
 }
 
 // Scan a relocation for a global symbol.
@@ -2430,14 +2663,14 @@ Target_x86_64<size>::Scan::global_reloc_may_be_function_pointer(
 template<int size>
 inline void
 Target_x86_64<size>::Scan::global(Symbol_table* symtab,
-                            Layout* layout,
-                            Target_x86_64<size>* target,
-                            Sized_relobj_file<size, false>* object,
-                            unsigned int data_shndx,
-                            Output_section* output_section,
-                            const elfcpp::Rela<size, false>& reloc,
-                            unsigned int r_type,
-                            Symbol* gsym)
+                           Layout* layout,
+                           Target_x86_64<size>* target,
+                           Sized_relobj_file<size, false>* object,
+                           unsigned int data_shndx,
+                           Output_section* output_section,
+                           const elfcpp::Rela<size, false>& reloc,
+                           unsigned int r_type,
+                           Symbol* gsym)
 {
   // A STT_GNU_IFUNC symbol may require a PLT entry.
   if (gsym->type() == elfcpp::STT_GNU_IFUNC
@@ -2457,25 +2690,25 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
     case elfcpp::R_X86_64_16:
     case elfcpp::R_X86_64_8:
       {
-        // Make a PLT entry if necessary.
-        if (gsym->needs_plt_entry())
-          {
-            target->make_plt_entry(symtab, layout, gsym);
-            // Since this is not a PC-relative relocation, we may be
-            // taking the address of a function. In that case we need to
-            // set the entry in the dynamic symbol table to the address of
-            // the PLT entry.
-            if (gsym->is_from_dynobj() && !parameters->options().shared())
-              gsym->set_needs_dynsym_value();
-          }
-        // Make a dynamic relocation if necessary.
-        if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
-          {
-            if (gsym->may_need_copy_reloc())
-              {
-                target->copy_reloc(symtab, layout, object,
-                                   data_shndx, output_section, gsym, reloc);
-              }
+       // Make a PLT entry if necessary.
+       if (gsym->needs_plt_entry())
+         {
+           target->make_plt_entry(symtab, layout, gsym);
+           // Since this is not a PC-relative relocation, we may be
+           // taking the address of a function. In that case we need to
+           // set the entry in the dynamic symbol table to the address of
+           // the PLT entry.
+           if (gsym->is_from_dynobj() && !parameters->options().shared())
+             gsym->set_needs_dynsym_value();
+         }
+       // Make a dynamic relocation if necessary.
+       if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
+         {
+           if (gsym->may_need_copy_reloc())
+             {
+               target->copy_reloc(symtab, layout, object,
+                                  data_shndx, output_section, gsym, reloc);
+             }
            else if (((size == 64 && r_type == elfcpp::R_X86_64_64)
                      || (size == 32 && r_type == elfcpp::R_X86_64_32))
                     && gsym->type() == elfcpp::STT_GNU_IFUNC
@@ -2497,25 +2730,25 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
                                                       reloc.get_r_offset(),
                                                       reloc.get_r_addend());
              }
-            else if (r_type == elfcpp::R_X86_64_64
-                     && gsym->can_use_relative_reloc(false))
-              {
-                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+           else if (r_type == elfcpp::R_X86_64_64
+                    && gsym->can_use_relative_reloc(false))
+             {
+               Reloc_section* rela_dyn = target->rela_dyn_section(layout);
                rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_RELATIVE,
                                              output_section, object,
                                              data_shndx,
                                              reloc.get_r_offset(),
                                              reloc.get_r_addend(), false);
-              }
-            else
-              {
-                this->check_non_pic(object, r_type, gsym);
-                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-                rela_dyn->add_global(gsym, r_type, output_section, object,
-                                     data_shndx, reloc.get_r_offset(),
-                                     reloc.get_r_addend());
-              }
-          }
+             }
+           else
+             {
+               this->check_non_pic(object, r_type, gsym);
+               Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+               rela_dyn->add_global(gsym, r_type, output_section, object,
+                                    data_shndx, reloc.get_r_offset(),
+                                    reloc.get_r_addend());
+             }
+         }
       }
       break;
 
@@ -2524,26 +2757,26 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
     case elfcpp::R_X86_64_PC16:
     case elfcpp::R_X86_64_PC8:
       {
-        // Make a PLT entry if necessary.
-        if (gsym->needs_plt_entry())
-          target->make_plt_entry(symtab, layout, gsym);
-        // Make a dynamic relocation if necessary.
-        if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
-          {
-            if (gsym->may_need_copy_reloc())
-              {
-                target->copy_reloc(symtab, layout, object,
-                                   data_shndx, output_section, gsym, reloc);
-              }
-            else
-              {
-                this->check_non_pic(object, r_type, gsym);
-                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-                rela_dyn->add_global(gsym, r_type, output_section, object,
-                                     data_shndx, reloc.get_r_offset(),
-                                     reloc.get_r_addend());
-              }
-          }
+       // Make a PLT entry if necessary.
+       if (gsym->needs_plt_entry())
+         target->make_plt_entry(symtab, layout, gsym);
+       // Make a dynamic relocation if necessary.
+       if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
+         {
+           if (gsym->may_need_copy_reloc())
+             {
+               target->copy_reloc(symtab, layout, object,
+                                  data_shndx, output_section, gsym, reloc);
+             }
+           else
+             {
+               this->check_non_pic(object, r_type, gsym);
+               Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+               rela_dyn->add_global(gsym, r_type, output_section, object,
+                                    data_shndx, reloc.get_r_offset(),
+                                    reloc.get_r_addend());
+             }
+         }
       }
       break;
 
@@ -2553,9 +2786,9 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
     case elfcpp::R_X86_64_GOTPCREL:
     case elfcpp::R_X86_64_GOTPLT64:
       {
-        // The symbol requires a GOT entry.
-        Output_data_got<64, false>* got = target->got_section(symtab, layout);
-        if (gsym->final_value_is_known())
+       // The symbol requires a GOT entry.
+       Output_data_got<64, false>* got = target->got_section(symtab, layout);
+       if (gsym->final_value_is_known())
          {
            // For a STT_GNU_IFUNC symbol we want the PLT address.
            if (gsym->type() == elfcpp::STT_GNU_IFUNC)
@@ -2563,11 +2796,11 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
            else
              got->add_global(gsym, GOT_TYPE_STANDARD);
          }
-        else
-          {
-            // If this symbol is not fully resolved, we need to add a
-            // dynamic relocation for it.
-            Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+       else
+         {
+           // If this symbol is not fully resolved, we need to add a
+           // dynamic relocation for it.
+           Reloc_section* rela_dyn = target->rela_dyn_section(layout);
 
            // Use a GLOB_DAT rather than a RELATIVE reloc if:
            //
@@ -2588,10 +2821,10 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
                    && parameters->options().shared())
                || (gsym->type() == elfcpp::STT_GNU_IFUNC
                    && parameters->options().output_is_position_independent()))
-              got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn,
+             got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn,
                                       elfcpp::R_X86_64_GLOB_DAT);
-            else
-              {
+           else
+             {
                // For a STT_GNU_IFUNC symbol we want to write the PLT
                // offset into the GOT, so that function pointer
                // comparisons work correctly.
@@ -2607,20 +2840,20 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
                        && !parameters->options().shared())
                      gsym->set_needs_dynsym_value();
                  }
-                if (is_new)
+               if (is_new)
                  {
                    unsigned int got_off = gsym->got_offset(GOT_TYPE_STANDARD);
                    rela_dyn->add_global_relative(gsym,
                                                  elfcpp::R_X86_64_RELATIVE,
                                                  got, got_off, 0, false);
                  }
-              }
-          }
-        // For GOTPLT64, we also need a PLT entry (but only if the
-        // symbol is not fully resolved).
-        if (r_type == elfcpp::R_X86_64_GOTPLT64
-            && !gsym->final_value_is_known())
-          target->make_plt_entry(symtab, layout, gsym);
+             }
+         }
+       // For GOTPLT64, we also need a PLT entry (but only if the
+       // symbol is not fully resolved).
+       if (r_type == elfcpp::R_X86_64_GOTPLT64
+           && !gsym->final_value_is_known())
+         target->make_plt_entry(symtab, layout, gsym);
       }
       break;
 
@@ -2633,8 +2866,8 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
       // if the symbol is defined in the output file and is protected
       // or hidden.
       if (gsym->is_defined()
-          && !gsym->is_from_dynobj()
-          && !gsym->is_preemptible())
+         && !gsym->is_from_dynobj()
+         && !gsym->is_preemptible())
        break;
       target->make_plt_entry(symtab, layout, gsym);
       break;
@@ -2677,27 +2910,27 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
       {
        const bool is_final = gsym->final_value_is_known();
        const tls::Tls_optimization optimized_type
-            = Target_x86_64<size>::optimize_tls_reloc(is_final, r_type);
+           = Target_x86_64<size>::optimize_tls_reloc(is_final, r_type);
        switch (r_type)
          {
-          case elfcpp::R_X86_64_TLSGD:       // General-dynamic
+         case elfcpp::R_X86_64_TLSGD:       // General-dynamic
            if (optimized_type == tls::TLSOPT_NONE)
              {
-                // Create a pair of GOT entries for the module index and
-                // dtv-relative offset.
-                Output_data_got<64, false>* got
-                    = target->got_section(symtab, layout);
-                got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
+               // Create a pair of GOT entries for the module index and
+               // dtv-relative offset.
+               Output_data_got<64, false>* got
+                   = target->got_section(symtab, layout);
+               got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
                                              target->rela_dyn_section(layout),
                                              elfcpp::R_X86_64_DTPMOD64,
                                              elfcpp::R_X86_64_DTPOFF64);
              }
            else if (optimized_type == tls::TLSOPT_TO_IE)
              {
-                // Create a GOT entry for the tp-relative offset.
-                Output_data_got<64, false>* got
-                    = target->got_section(symtab, layout);
-                got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
+               // Create a GOT entry for the tp-relative offset.
+               Output_data_got<64, false>* got
+                   = target->got_section(symtab, layout);
+               got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
                                         target->rela_dyn_section(layout),
                                         elfcpp::R_X86_64_TPOFF64);
              }
@@ -2705,30 +2938,30 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
              unsupported_reloc_global(object, r_type, gsym);
            break;
 
-          case elfcpp::R_X86_64_GOTPC32_TLSDESC:
-            target->define_tls_base_symbol(symtab, layout);
+         case elfcpp::R_X86_64_GOTPC32_TLSDESC:
+           target->define_tls_base_symbol(symtab, layout);
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // Create reserved PLT and GOT entries for the resolver.
-               target->reserve_tlsdesc_entries(symtab, layout);
-
-               // Create a double GOT entry with an R_X86_64_TLSDESC
-               // reloc.  The R_X86_64_TLSDESC reloc is resolved
-               // lazily, so the GOT entry needs to be in an area in
-               // .got.plt, not .got.  Call got_section to make sure
-               // the section has been created.
+               // Create reserved PLT and GOT entries for the resolver.
+               target->reserve_tlsdesc_entries(symtab, layout);
+
+               // Create a double GOT entry with an R_X86_64_TLSDESC
+               // reloc.  The R_X86_64_TLSDESC reloc is resolved
+               // lazily, so the GOT entry needs to be in an area in
+               // .got.plt, not .got.  Call got_section to make sure
+               // the section has been created.
                target->got_section(symtab, layout);
-                Output_data_got<64, false>* got = target->got_tlsdesc_section();
+               Output_data_got<64, false>* got = target->got_tlsdesc_section();
                Reloc_section* rt = target->rela_tlsdesc_section(layout);
-                got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt,
+               got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt,
                                              elfcpp::R_X86_64_TLSDESC, 0);
              }
            else if (optimized_type == tls::TLSOPT_TO_IE)
              {
-               // Create a GOT entry for the tp-relative offset.
-                Output_data_got<64, false>* got
-                    = target->got_section(symtab, layout);
-                got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
+               // Create a GOT entry for the tp-relative offset.
+               Output_data_got<64, false>* got
+                   = target->got_section(symtab, layout);
+               got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
                                         target->rela_dyn_section(layout),
                                         elfcpp::R_X86_64_TPOFF64);
              }
@@ -2736,46 +2969,46 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
              unsupported_reloc_global(object, r_type, gsym);
            break;
 
-          case elfcpp::R_X86_64_TLSDESC_CALL:
+         case elfcpp::R_X86_64_TLSDESC_CALL:
            break;
 
-          case elfcpp::R_X86_64_TLSLD:       // Local-dynamic
+         case elfcpp::R_X86_64_TLSLD:       // Local-dynamic
            if (optimized_type == tls::TLSOPT_NONE)
              {
-               // Create a GOT entry for the module index.
-               target->got_mod_index_entry(symtab, layout, object);
+               // Create a GOT entry for the module index.
+               target->got_mod_index_entry(symtab, layout, object);
              }
            else if (optimized_type != tls::TLSOPT_TO_LE)
              unsupported_reloc_global(object, r_type, gsym);
            break;
 
-          case elfcpp::R_X86_64_DTPOFF32:
-          case elfcpp::R_X86_64_DTPOFF64:
+         case elfcpp::R_X86_64_DTPOFF32:
+         case elfcpp::R_X86_64_DTPOFF64:
            break;
 
-          case elfcpp::R_X86_64_GOTTPOFF:    // Initial-exec
+         case elfcpp::R_X86_64_GOTTPOFF:    // Initial-exec
            layout->set_has_static_tls();
-            if (optimized_type == tls::TLSOPT_NONE)
-              {
-               // Create a GOT entry for the tp-relative offset.
-               Output_data_got<64, false>* got
-                   = target->got_section(symtab, layout);
-               got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
+           if (optimized_type == tls::TLSOPT_NONE)
+             {
+               // Create a GOT entry for the tp-relative offset.
+               Output_data_got<64, false>* got
+                   = target->got_section(symtab, layout);
+               got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
                                         target->rela_dyn_section(layout),
                                         elfcpp::R_X86_64_TPOFF64);
-              }
-            else if (optimized_type != tls::TLSOPT_TO_LE)
-              unsupported_reloc_global(object, r_type, gsym);
-            break;
+             }
+           else if (optimized_type != tls::TLSOPT_TO_LE)
+             unsupported_reloc_global(object, r_type, gsym);
+           break;
 
-          case elfcpp::R_X86_64_TPOFF32:     // Local-exec
+         case elfcpp::R_X86_64_TPOFF32:     // Local-exec
            layout->set_has_static_tls();
-            if (parameters->options().shared())
-              unsupported_reloc_local(object, r_type);
+           if (parameters->options().shared())
+             unsupported_reloc_local(object, r_type);
            break;
 
-          default:
-            gold_unreachable();
+         default:
+           gold_unreachable();
          }
       }
       break;
@@ -2785,7 +3018,7 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
     default:
       gold_error(_("%s: unsupported reloc %u against global symbol %s"),
                 object->name().c_str(), r_type,
-                 gsym->demangled_name().c_str());
+                gsym->demangled_name().c_str());
       break;
     }
 }
@@ -2811,7 +3044,7 @@ Target_x86_64<size>::gc_process_relocs(Symbol_table* symtab,
     }
 
    gold::gc_process_relocs<size, false, Target_x86_64<size>, elfcpp::SHT_RELA,
-                           typename Target_x86_64<size>::Scan,
+                          typename Target_x86_64<size>::Scan,
                           typename Target_x86_64<size>::Relocatable_size_for_reloc>(
     symtab,
     layout,
@@ -2824,7 +3057,7 @@ Target_x86_64<size>::gc_process_relocs(Symbol_table* symtab,
     needs_special_offset_handling,
     local_symbol_count,
     plocal_symbols);
+
 }
 // Scan relocations for a section.
 
@@ -2878,7 +3111,7 @@ Target_x86_64<size>::do_finalize_sections(
                                  : this->plt_->rela_plt());
   layout->add_target_dynamic_tags(false, this->got_plt_, rel_plt,
                                  this->rela_dyn_, true, false);
-                                 
+
   // Fill in some more dynamic tags.
   Output_data_dynamic* const odyn = layout->dynamic_data();
   if (odyn != NULL)
@@ -2973,7 +3206,7 @@ Target_x86_64<size>::Relocate::relocate(
   if (this->skip_call_tls_get_addr_)
     {
       if ((r_type != elfcpp::R_X86_64_PLT32
-           && r_type != elfcpp::R_X86_64_PC32)
+          && r_type != elfcpp::R_X86_64_PC32)
          || gsym == NULL
          || strcmp(gsym->name(), "__tls_get_addr") != 0)
        {
@@ -3025,17 +3258,17 @@ Target_x86_64<size>::Relocate::relocate(
     case elfcpp::R_X86_64_GOTPCREL:
     case elfcpp::R_X86_64_GOTPCREL64:
       if (gsym != NULL)
-        {
-          gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
-          got_offset = gsym->got_offset(GOT_TYPE_STANDARD) - target->got_size();
-        }
+       {
+         gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+         got_offset = gsym->got_offset(GOT_TYPE_STANDARD) - target->got_size();
+       }
       else
-        {
-          unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
-          gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
-          got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
-                        - target->got_size());
-        }
+       {
+         unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+         gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+         got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
+                       - target->got_size());
+       }
       have_got_offset = true;
       break;
 
@@ -3056,7 +3289,7 @@ Target_x86_64<size>::Relocate::relocate(
 
     case elfcpp::R_X86_64_PC64:
       Relocate_functions<size, false>::pcrela64(view, object, psymval, addend,
-                                              address);
+                                             address);
       break;
 
     case elfcpp::R_X86_64_32:
@@ -3099,7 +3332,7 @@ Target_x86_64<size>::Relocate::relocate(
 
     case elfcpp::R_X86_64_PLT32:
       gold_assert(gsym == NULL
-                  || gsym->has_plt_offset()
+                 || gsym->has_plt_offset()
                  || gsym->final_value_is_known()
                  || (gsym->is_defined()
                      && !gsym->is_from_dynobj()
@@ -3113,9 +3346,9 @@ Target_x86_64<size>::Relocate::relocate(
 
     case elfcpp::R_X86_64_PLTOFF64:
       {
-        gold_assert(gsym);
-        gold_assert(gsym->has_plt_offset()
-                    || gsym->final_value_is_known());
+       gold_assert(gsym);
+       gold_assert(gsym->has_plt_offset()
+                   || gsym->final_value_is_known());
        typename elfcpp::Elf_types<size>::Elf_Addr got_address;
        got_address = target->got_section(NULL, NULL)->address();
        Relocate_functions<size, false>::rela64(view, object, psymval,
@@ -3129,7 +3362,7 @@ Target_x86_64<size>::Relocate::relocate(
 
     case elfcpp::R_X86_64_GOTPC32:
       {
-        gold_assert(gsym);
+       gold_assert(gsym);
        typename elfcpp::Elf_types<size>::Elf_Addr value;
        value = target->got_plt_section()->address();
        Relocate_functions<size, false>::pcrela32(view, value, addend, address);
@@ -3146,7 +3379,7 @@ Target_x86_64<size>::Relocate::relocate(
 
     case elfcpp::R_X86_64_GOTPC64:
       {
-        gold_assert(gsym);
+       gold_assert(gsym);
        typename elfcpp::Elf_types<size>::Elf_Addr value;
        value = target->got_plt_section()->address();
        Relocate_functions<size, false>::pcrela64(view, value, addend, address);
@@ -3164,19 +3397,19 @@ Target_x86_64<size>::Relocate::relocate(
 
     case elfcpp::R_X86_64_GOTPCREL:
       {
-        gold_assert(have_got_offset);
-        typename elfcpp::Elf_types<size>::Elf_Addr value;
-        value = target->got_plt_section()->address() + got_offset;
-        Relocate_functions<size, false>::pcrela32(view, value, addend, address);
+       gold_assert(have_got_offset);
+       typename elfcpp::Elf_types<size>::Elf_Addr value;
+       value = target->got_plt_section()->address() + got_offset;
+       Relocate_functions<size, false>::pcrela32(view, value, addend, address);
       }
       break;
 
     case elfcpp::R_X86_64_GOTPCREL64:
       {
-        gold_assert(have_got_offset);
-        typename elfcpp::Elf_types<size>::Elf_Addr value;
-        value = target->got_plt_section()->address() + got_offset;
-        Relocate_functions<size, false>::pcrela64(view, value, addend, address);
+       gold_assert(have_got_offset);
+       typename elfcpp::Elf_types<size>::Elf_Addr value;
+       value = target->got_plt_section()->address() + got_offset;
+       Relocate_functions<size, false>::pcrela64(view, value, addend, address);
       }
       break;
 
@@ -3204,7 +3437,7 @@ Target_x86_64<size>::Relocate::relocate(
     case elfcpp::R_X86_64_GOTTPOFF:         // Initial-exec
     case elfcpp::R_X86_64_TPOFF32:          // Local-exec
       this->relocate_tls(relinfo, target, relnum, rela, r_type, gsym, psymval,
-                         view, address, view_size);
+                        view, address, view_size);
       break;
 
     case elfcpp::R_X86_64_SIZE32:
@@ -3276,40 +3509,40 @@ Target_x86_64<size>::Relocate::relocate_tls(
          break;
        }
       else
-        {
-          unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
-                                   ? GOT_TYPE_TLS_OFFSET
-                                   : GOT_TYPE_TLS_PAIR);
-          unsigned int got_offset;
-          if (gsym != NULL)
-            {
-              gold_assert(gsym->has_got_offset(got_type));
-              got_offset = gsym->got_offset(got_type) - target->got_size();
-            }
-          else
-            {
-              unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
-              gold_assert(object->local_has_got_offset(r_sym, got_type));
-              got_offset = (object->local_got_offset(r_sym, got_type)
-                            - target->got_size());
-            }
-          if (optimized_type == tls::TLSOPT_TO_IE)
-            {
-              value = target->got_plt_section()->address() + got_offset;
-              this->tls_gd_to_ie(relinfo, relnum, tls_segment, rela, r_type,
-                                 value, view, address, view_size);
-              break;
-            }
-          else if (optimized_type == tls::TLSOPT_NONE)
-            {
-              // Relocate the field with the offset of the pair of GOT
-              // entries.
+       {
+         unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
+                                  ? GOT_TYPE_TLS_OFFSET
+                                  : GOT_TYPE_TLS_PAIR);
+         unsigned int got_offset;
+         if (gsym != NULL)
+           {
+             gold_assert(gsym->has_got_offset(got_type));
+             got_offset = gsym->got_offset(got_type) - target->got_size();
+           }
+         else
+           {
+             unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+             gold_assert(object->local_has_got_offset(r_sym, got_type));
+             got_offset = (object->local_got_offset(r_sym, got_type)
+                           - target->got_size());
+           }
+         if (optimized_type == tls::TLSOPT_TO_IE)
+           {
+             value = target->got_plt_section()->address() + got_offset;
+             this->tls_gd_to_ie(relinfo, relnum, tls_segment, rela, r_type,
+                                value, view, address, view_size);
+             break;
+           }
+         else if (optimized_type == tls::TLSOPT_NONE)
+           {
+             // Relocate the field with the offset of the pair of GOT
+             // entries.
              value = target->got_plt_section()->address() + got_offset;
-              Relocate_functions<size, false>::pcrela32(view, value, addend,
+             Relocate_functions<size, false>::pcrela32(view, value, addend,
                                                        address);
-              break;
-            }
-        }
+             break;
+           }
+       }
       gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
                             _("unsupported reloc %u"), r_type);
       break;
@@ -3330,16 +3563,16 @@ Target_x86_64<size>::Relocate::relocate_tls(
              return;
            }
          this->tls_desc_gd_to_le(relinfo, relnum, tls_segment,
-                                 rela, r_type, value, view,
-                                 view_size);
+                                 rela, r_type, value, view,
+                                 view_size);
          break;
        }
       else
-        {
-          unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
-                                   ? GOT_TYPE_TLS_OFFSET
-                                   : GOT_TYPE_TLS_DESC);
-          unsigned int got_offset = 0;
+       {
+         unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
+                                  ? GOT_TYPE_TLS_OFFSET
+                                  : GOT_TYPE_TLS_DESC);
+         unsigned int got_offset = 0;
          if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC
              && optimized_type == tls::TLSOPT_NONE)
            {
@@ -3349,45 +3582,45 @@ Target_x86_64<size>::Relocate::relocate_tls(
              got_offset = (target->got_size()
                            + target->got_plt_section()->data_size());
            }
-          if (gsym != NULL)
-            {
-              gold_assert(gsym->has_got_offset(got_type));
-              got_offset += gsym->got_offset(got_type) - target->got_size();
-            }
-          else
-            {
-              unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
-              gold_assert(object->local_has_got_offset(r_sym, got_type));
-              got_offset += (object->local_got_offset(r_sym, got_type)
+         if (gsym != NULL)
+           {
+             gold_assert(gsym->has_got_offset(got_type));
+             got_offset += gsym->got_offset(got_type) - target->got_size();
+           }
+         else
+           {
+             unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+             gold_assert(object->local_has_got_offset(r_sym, got_type));
+             got_offset += (object->local_got_offset(r_sym, got_type)
                             - target->got_size());
-            }
-          if (optimized_type == tls::TLSOPT_TO_IE)
-            {
+           }
+         if (optimized_type == tls::TLSOPT_TO_IE)
+           {
              if (tls_segment == NULL)
                {
                  gold_assert(parameters->errors()->error_count() > 0
                              || issue_undefined_symbol_error(gsym));
                  return;
                }
-              value = target->got_plt_section()->address() + got_offset;
-              this->tls_desc_gd_to_ie(relinfo, relnum, tls_segment,
-                                      rela, r_type, value, view, address,
-                                      view_size);
-              break;
-            }
-          else if (optimized_type == tls::TLSOPT_NONE)
-            {
-              if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC)
-                {
-                  // Relocate the field with the offset of the pair of GOT
-                  // entries.
-                 value = target->got_plt_section()->address() + got_offset;
-                  Relocate_functions<size, false>::pcrela32(view, value, addend,
+             value = target->got_plt_section()->address() + got_offset;
+             this->tls_desc_gd_to_ie(relinfo, relnum, tls_segment,
+                                     rela, r_type, value, view, address,
+                                     view_size);
+             break;
+           }
+         else if (optimized_type == tls::TLSOPT_NONE)
+           {
+             if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC)
+               {
+                 // Relocate the field with the offset of the pair of GOT
+                 // entries.
+                 value = target->got_plt_section()->address() + got_offset;
+                 Relocate_functions<size, false>::pcrela32(view, value, addend,
                                                            address);
-                }
-              break;
-            }
-        }
+               }
+             break;
+           }
+       }
       gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
                             _("unsupported reloc %u"), r_type);
       break;
@@ -3399,7 +3632,7 @@ Target_x86_64<size>::Relocate::relocate_tls(
          optimized_type = tls::TLSOPT_NONE;
        }
       if (optimized_type == tls::TLSOPT_TO_LE)
-        {
+       {
          if (tls_segment == NULL)
            {
              gold_assert(parameters->errors()->error_count() > 0
@@ -3409,19 +3642,19 @@ Target_x86_64<size>::Relocate::relocate_tls(
          this->tls_ld_to_le(relinfo, relnum, tls_segment, rela, r_type,
                             value, view, view_size);
          break;
-        }
+       }
       else if (optimized_type == tls::TLSOPT_NONE)
-        {
-          // Relocate the field with the offset of the GOT entry for
-          // the module index.
-          unsigned int got_offset;
-          got_offset = (target->got_mod_index_entry(NULL, NULL, NULL)
+       {
+         // Relocate the field with the offset of the GOT entry for
+         // the module index.
+         unsigned int got_offset;
+         got_offset = (target->got_mod_index_entry(NULL, NULL, NULL)
                        - target->got_size());
          value = target->got_plt_section()->address() + got_offset;
-          Relocate_functions<size, false>::pcrela32(view, value, addend,
+         Relocate_functions<size, false>::pcrela32(view, value, addend,
                                                    address);
-          break;
-        }
+         break;
+       }
       gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
                             _("unsupported reloc %u"), r_type);
       break;
@@ -3477,29 +3710,29 @@ Target_x86_64<size>::Relocate::relocate_tls(
          break;
        }
       else if (optimized_type == tls::TLSOPT_NONE)
-        {
-          // Relocate the field with the offset of the GOT entry for
-          // the tp-relative offset of the symbol.
-          unsigned int got_offset;
-          if (gsym != NULL)
-            {
-              gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_OFFSET));
-              got_offset = (gsym->got_offset(GOT_TYPE_TLS_OFFSET)
-                            - target->got_size());
-            }
-          else
-            {
-              unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
-              gold_assert(object->local_has_got_offset(r_sym,
-                                                       GOT_TYPE_TLS_OFFSET));
-              got_offset = (object->local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET)
-                            - target->got_size());
-            }
+       {
+         // Relocate the field with the offset of the GOT entry for
+         // the tp-relative offset of the symbol.
+         unsigned int got_offset;
+         if (gsym != NULL)
+           {
+             gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_OFFSET));
+             got_offset = (gsym->got_offset(GOT_TYPE_TLS_OFFSET)
+                           - target->got_size());
+           }
+         else
+           {
+             unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+             gold_assert(object->local_has_got_offset(r_sym,
+                                                      GOT_TYPE_TLS_OFFSET));
+             got_offset = (object->local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET)
+                           - target->got_size());
+           }
          value = target->got_plt_section()->address() + got_offset;
-          Relocate_functions<size, false>::pcrela32(view, value, addend,
+         Relocate_functions<size, false>::pcrela32(view, value, addend,
                                                    address);
-          break;
-        }
+         break;
+       }
       gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
                             _("unsupported reloc type %u"),
                             r_type);
@@ -3545,7 +3778,7 @@ Target_x86_64<size>::Relocate::tls_gd_to_ie(
 
   tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 12);
   tls::check_tls(relinfo, relnum, rela.get_r_offset(),
-                 (memcmp(view + 4, "\x66\x66\x48\xe8", 4) == 0));
+                (memcmp(view + 4, "\x66\x66\x48\xe8", 4) == 0));
 
   if (size == 64)
     {
@@ -3653,7 +3886,7 @@ Target_x86_64<size>::Relocate::tls_desc_gd_to_ie(
       tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3);
       tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4);
       tls::check_tls(relinfo, relnum, rela.get_r_offset(),
-                     view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05);
+                    view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05);
       view[-2] = 0x8b;
       const elfcpp::Elf_Xword addend = rela.get_r_addend();
       Relocate_functions<size, false>::pcrela32(view, value, addend, address);
@@ -3665,7 +3898,7 @@ Target_x86_64<size>::Relocate::tls_desc_gd_to_ie(
       gold_assert(r_type == elfcpp::R_X86_64_TLSDESC_CALL);
       tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 2);
       tls::check_tls(relinfo, relnum, rela.get_r_offset(),
-                     view[0] == 0xff && view[1] == 0x10);
+                    view[0] == 0xff && view[1] == 0x10);
       view[0] = 0x66;
       view[1] = 0x90;
     }
@@ -3692,7 +3925,7 @@ Target_x86_64<size>::Relocate::tls_desc_gd_to_le(
       tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3);
       tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4);
       tls::check_tls(relinfo, relnum, rela.get_r_offset(),
-                     view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05);
+                    view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05);
       view[-2] = 0xc7;
       view[-1] = 0xc0;
       value -= tls_segment->memsz();
@@ -3705,7 +3938,7 @@ Target_x86_64<size>::Relocate::tls_desc_gd_to_le(
       gold_assert(r_type == elfcpp::R_X86_64_TLSDESC_CALL);
       tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 2);
       tls::check_tls(relinfo, relnum, rela.get_r_offset(),
-                     view[0] == 0xff && view[1] == 0x10);
+                    view[0] == 0xff && view[1] == 0x10);
       view[0] = 0x66;
       view[1] = 0x90;
     }
@@ -3731,7 +3964,7 @@ Target_x86_64<size>::Relocate::tls_ld_to_le(
   tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 9);
 
   tls::check_tls(relinfo, relnum, rela.get_r_offset(),
-                 view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x3d);
+                view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x3d);
 
   tls::check_tls(relinfo, relnum, rela.get_r_offset(), view[4] == 0xe8);
 
@@ -3775,7 +4008,7 @@ Target_x86_64<size>::Relocate::tls_ie_to_le(
     {
       // movq
       if (op1 == 0x4c)
-        view[-3] = 0x49;
+       view[-3] = 0x49;
       view[-2] = 0xc7;
       view[-1] = 0xc0 | reg;
     }
@@ -3783,7 +4016,7 @@ Target_x86_64<size>::Relocate::tls_ie_to_le(
     {
       // Special handling for %rsp.
       if (op1 == 0x4c)
-        view[-3] = 0x49;
+       view[-3] = 0x49;
       view[-2] = 0x81;
       view[-1] = 0xc0 | reg;
     }
@@ -3791,7 +4024,7 @@ Target_x86_64<size>::Relocate::tls_ie_to_le(
     {
       // addq
       if (op1 == 0x4c)
-        view[-3] = 0x4d;
+       view[-3] = 0x4d;
       view[-2] = 0x8d;
       view[-1] = 0x80 | reg | (reg << 3);
     }
@@ -4030,7 +4263,7 @@ Target_x86_64<size>::do_code_fill(section_size_type length) const
       jmp[0] = 0xe9;
       elfcpp::Swap_unaligned<32, false>::writeval(jmp + 1, length - 5);
       return (std::string(reinterpret_cast<char*>(&jmp[0]), 5)
-              + std::string(length - 5, static_cast<char>(0x90)));
+             + std::string(length - 5, static_cast<char>(0x90)));
     }
 
   // Nop sequences of various lengths.
@@ -4038,47 +4271,47 @@ Target_x86_64<size>::do_code_fill(section_size_type length) const
   const char nop2[2] = { '\x66', '\x90' };         // xchg %ax %ax
   const char nop3[3] = { '\x0f', '\x1f', '\x00' }; // nop (%rax)
   const char nop4[4] = { '\x0f', '\x1f', '\x40',   // nop 0(%rax)
-                        '\x00'};
+                        '\x00'};
   const char nop5[5] = { '\x0f', '\x1f', '\x44',   // nop 0(%rax,%rax,1)
                         '\x00', '\x00' };
   const char nop6[6] = { '\x66', '\x0f', '\x1f',   // nopw 0(%rax,%rax,1)
-                        '\x44', '\x00', '\x00' };
+                        '\x44', '\x00', '\x00' };
   const char nop7[7] = { '\x0f', '\x1f', '\x80',   // nopl 0L(%rax)
-                        '\x00', '\x00', '\x00',
+                        '\x00', '\x00', '\x00',
                         '\x00' };
   const char nop8[8] = { '\x0f', '\x1f', '\x84',   // nopl 0L(%rax,%rax,1)
-                        '\x00', '\x00', '\x00',
+                        '\x00', '\x00', '\x00',
                         '\x00', '\x00' };
   const char nop9[9] = { '\x66', '\x0f', '\x1f',   // nopw 0L(%rax,%rax,1)
-                        '\x84', '\x00', '\x00',
+                        '\x84', '\x00', '\x00',
                         '\x00', '\x00', '\x00' };
   const char nop10[10] = { '\x66', '\x2e', '\x0f', // nopw %cs:0L(%rax,%rax,1)
-                          '\x1f', '\x84', '\x00',
+                          '\x1f', '\x84', '\x00',
                           '\x00', '\x00', '\x00',
                           '\x00' };
   const char nop11[11] = { '\x66', '\x66', '\x2e', // data16
-                          '\x0f', '\x1f', '\x84', // nopw %cs:0L(%rax,%rax,1)
+                          '\x0f', '\x1f', '\x84', // nopw %cs:0L(%rax,%rax,1)
                           '\x00', '\x00', '\x00',
                           '\x00', '\x00' };
   const char nop12[12] = { '\x66', '\x66', '\x66', // data16; data16
-                          '\x2e', '\x0f', '\x1f', // nopw %cs:0L(%rax,%rax,1)
+                          '\x2e', '\x0f', '\x1f', // nopw %cs:0L(%rax,%rax,1)
                           '\x84', '\x00', '\x00',
                           '\x00', '\x00', '\x00' };
   const char nop13[13] = { '\x66', '\x66', '\x66', // data16; data16; data16
-                          '\x66', '\x2e', '\x0f', // nopw %cs:0L(%rax,%rax,1)
+                          '\x66', '\x2e', '\x0f', // nopw %cs:0L(%rax,%rax,1)
                           '\x1f', '\x84', '\x00',
                           '\x00', '\x00', '\x00',
-                           '\x00' };
+                          '\x00' };
   const char nop14[14] = { '\x66', '\x66', '\x66', // data16; data16; data16
-                          '\x66', '\x66', '\x2e', // data16
+                          '\x66', '\x66', '\x2e', // data16
                           '\x0f', '\x1f', '\x84', // nopw %cs:0L(%rax,%rax,1)
                           '\x00', '\x00', '\x00',
-                           '\x00', '\x00' };
+                          '\x00', '\x00' };
   const char nop15[15] = { '\x66', '\x66', '\x66', // data16; data16; data16
-                          '\x66', '\x66', '\x66', // data16; data16
+                          '\x66', '\x66', '\x66', // data16; data16
                           '\x2e', '\x0f', '\x1f', // nopw %cs:0L(%rax,%rax,1)
                           '\x84', '\x00', '\x00',
-                           '\x00', '\x00', '\x00' };
+                          '\x00', '\x00', '\x00' };
 
   const char* nops[16] = {
     NULL,
@@ -4187,7 +4420,8 @@ Target_x86_64<size>::do_calls_non_split(Relobj* object, unsigned int shndx,
   *to = "__morestack_non_split";
 }
 
-// The selector for x86_64 object files.
+// The selector for x86_64 object files.  Note this is never instantiated
+// directly.  It's only used in Target_selector_x86_64_nacl, below.
 
 template<int size>
 class Target_selector_x86_64 : public Target_selector_freebsd
@@ -4195,9 +4429,9 @@ class Target_selector_x86_64 : public Target_selector_freebsd
 public:
   Target_selector_x86_64()
     : Target_selector_freebsd(elfcpp::EM_X86_64, size, false,
-                             (size == 64 
+                             (size == 64
                               ? "elf64-x86-64" : "elf32-x86-64"),
-                             (size == 64 
+                             (size == 64
                               ? "elf64-x86-64-freebsd"
                               : "elf32-x86-64-freebsd"),
                              (size == 64 ? "elf_x86_64" : "elf32_x86_64"))
@@ -4209,7 +4443,359 @@ public:
 
 };
 
-Target_selector_x86_64<64> target_selector_x86_64;
-Target_selector_x86_64<32> target_selector_x32;
+// NaCl variant.  It uses different PLT contents.
+
+template<int size>
+class Output_data_plt_x86_64_nacl : public Output_data_plt_x86_64<size>
+{
+ public:
+  Output_data_plt_x86_64_nacl(Layout* layout,
+                             Output_data_got<64, false>* got,
+                             Output_data_space* got_plt,
+                             Output_data_space* got_irelative)
+    : Output_data_plt_x86_64<size>(layout, plt_entry_size,
+                                  got, got_plt, got_irelative)
+  { }
+
+  Output_data_plt_x86_64_nacl(Layout* layout,
+                             Output_data_got<64, false>* got,
+                             Output_data_space* got_plt,
+                             Output_data_space* got_irelative,
+                             unsigned int plt_count)
+    : Output_data_plt_x86_64<size>(layout, plt_entry_size,
+                                  got, got_plt, got_irelative,
+                                  plt_count)
+  { }
+
+ protected:
+  virtual unsigned int
+  do_get_plt_entry_size() const
+  { return plt_entry_size; }
+
+  virtual void
+  do_add_eh_frame(Layout* layout)
+  {
+    layout->add_eh_frame_for_plt(this,
+                                this->plt_eh_frame_cie,
+                                this->plt_eh_frame_cie_size,
+                                plt_eh_frame_fde,
+                                plt_eh_frame_fde_size);
+  }
+
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov,
+                         typename elfcpp::Elf_types<size>::Elf_Addr got_addr,
+                         typename elfcpp::Elf_types<size>::Elf_Addr plt_addr);
+
+  virtual unsigned int
+  do_fill_plt_entry(unsigned char* pov,
+                   typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+                   typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+                   unsigned int got_offset,
+                   unsigned int plt_offset,
+                   unsigned int plt_index);
+
+  virtual void
+  do_fill_tlsdesc_entry(unsigned char* pov,
+                       typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+                       typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+                       typename elfcpp::Elf_types<size>::Elf_Addr got_base,
+                       unsigned int tlsdesc_got_offset,
+                       unsigned int plt_offset);
+
+ private:
+  // The size of an entry in the PLT.
+  static const int plt_entry_size = 64;
+
+  // The first entry in the PLT.
+  static const unsigned char first_plt_entry[plt_entry_size];
+
+  // Other entries in the PLT for an executable.
+  static const unsigned char plt_entry[plt_entry_size];
+
+  // The reserved TLSDESC entry in the PLT for an executable.
+  static const unsigned char tlsdesc_plt_entry[plt_entry_size];
+
+  // The .eh_frame unwind information for the PLT.
+  static const int plt_eh_frame_fde_size = 32;
+  static const unsigned char plt_eh_frame_fde[plt_eh_frame_fde_size];
+};
+
+template<int size>
+class Target_x86_64_nacl : public Target_x86_64<size>
+{
+ public:
+  Target_x86_64_nacl()
+    : Target_x86_64<size>(&x86_64_nacl_info)
+  { }
+
+  virtual Output_data_plt_x86_64<size>*
+  do_make_data_plt(Layout* layout,
+                  Output_data_got<64, false>* got,
+                  Output_data_space* got_plt,
+                  Output_data_space* got_irelative)
+  {
+    return new Output_data_plt_x86_64_nacl<size>(layout, got, got_plt,
+                                                got_irelative);
+  }
+
+  virtual Output_data_plt_x86_64<size>*
+  do_make_data_plt(Layout* layout,
+                  Output_data_got<64, false>* got,
+                  Output_data_space* got_plt,
+                  Output_data_space* got_irelative,
+                  unsigned int plt_count)
+  {
+    return new Output_data_plt_x86_64_nacl<size>(layout, got, got_plt,
+                                                got_irelative,
+                                                plt_count);
+  }
+
+ private:
+  static const Target::Target_info x86_64_nacl_info;
+};
+
+template<>
+const Target::Target_info Target_x86_64_nacl<64>::x86_64_nacl_info =
+{
+  64,                  // size
+  false,               // is_big_endian
+  elfcpp::EM_X86_64,   // machine_code
+  false,               // has_make_symbol
+  false,               // has_resolve
+  true,                        // has_code_fill
+  true,                        // is_default_stack_executable
+  true,                        // can_icf_inline_merge_sections
+  '\0',                        // wrap_char
+  "/lib64/ld-nacl-x86-64.so.1", // dynamic_linker
+  0x20000,             // default_text_segment_address
+  0x10000,             // abi_pagesize (overridable by -z max-page-size)
+  0x10000,             // common_pagesize (overridable by -z common-page-size)
+  true,                 // isolate_execinstr
+  0x10000000,           // rosegment_gap
+  elfcpp::SHN_UNDEF,   // small_common_shndx
+  elfcpp::SHN_X86_64_LCOMMON,  // large_common_shndx
+  0,                   // small_common_section_flags
+  elfcpp::SHF_X86_64_LARGE,    // large_common_section_flags
+  NULL,                        // attributes_section
+  NULL                 // attributes_vendor
+};
+
+template<>
+const Target::Target_info Target_x86_64_nacl<32>::x86_64_nacl_info =
+{
+  32,                  // size
+  false,               // is_big_endian
+  elfcpp::EM_X86_64,   // machine_code
+  false,               // has_make_symbol
+  false,               // has_resolve
+  true,                        // has_code_fill
+  true,                        // is_default_stack_executable
+  true,                        // can_icf_inline_merge_sections
+  '\0',                        // wrap_char
+  "/lib/ld-nacl-x86-64.so.1", // dynamic_linker
+  0x20000,             // default_text_segment_address
+  0x10000,             // abi_pagesize (overridable by -z max-page-size)
+  0x10000,             // common_pagesize (overridable by -z common-page-size)
+  true,                 // isolate_execinstr
+  0x10000000,           // rosegment_gap
+  elfcpp::SHN_UNDEF,   // small_common_shndx
+  elfcpp::SHN_X86_64_LCOMMON,  // large_common_shndx
+  0,                   // small_common_section_flags
+  elfcpp::SHF_X86_64_LARGE,    // large_common_section_flags
+  NULL,                        // attributes_section
+  NULL                 // attributes_vendor
+};
+
+#define        NACLMASK        0xe0            // 32-byte alignment mask.
+
+// The first entry in the PLT.
+
+template<int size>
+const unsigned char
+Output_data_plt_x86_64_nacl<size>::first_plt_entry[plt_entry_size] =
+{
+  0xff, 0x35,                         // pushq contents of memory address
+  0, 0, 0, 0,                         // replaced with address of .got + 8
+  0x4c, 0x8b, 0x1d,                   // mov GOT+16(%rip), %r11
+  0, 0, 0, 0,                         // replaced with address of .got + 16
+  0x41, 0x83, 0xe3, NACLMASK,         // and $-32, %r11d
+  0x4d, 0x01, 0xfb,                   // add %r15, %r11
+  0x41, 0xff, 0xe3,                   // jmpq *%r11
+
+  // 9-byte nop sequence to pad out to the next 32-byte boundary.
+  0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopl %cs:0x0(%rax,%rax,1)
+
+  // 32 bytes of nop to pad out to the standard size
+  0x66, 0x66, 0x66, 0x66, 0x66, 0x66,    // excess data32 prefixes
+  0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1)
+  0x66, 0x66, 0x66, 0x66, 0x66, 0x66,    // excess data32 prefixes
+  0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1)
+  0x66,                                  // excess data32 prefix
+  0x90                                   // nop
+};
+
+template<int size>
+void
+Output_data_plt_x86_64_nacl<size>::do_fill_first_plt_entry(
+    unsigned char* pov,
+    typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+    typename elfcpp::Elf_types<size>::Elf_Addr plt_address)
+{
+  memcpy(pov, first_plt_entry, plt_entry_size);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+                                             (got_address + 8
+                                              - (plt_address + 2 + 4)));
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 9,
+                                             (got_address + 16
+                                              - (plt_address + 9 + 4)));
+}
+
+// Subsequent entries in the PLT.
+
+template<int size>
+const unsigned char
+Output_data_plt_x86_64_nacl<size>::plt_entry[plt_entry_size] =
+{
+  0x4c, 0x8b, 0x1d,              // mov name@GOTPCREL(%rip),%r11
+  0, 0, 0, 0,                    // replaced with address of symbol in .got
+  0x41, 0x83, 0xe3, NACLMASK,    // and $-32, %r11d
+  0x4d, 0x01, 0xfb,              // add %r15, %r11
+  0x41, 0xff, 0xe3,              // jmpq *%r11
+
+  // 15-byte nop sequence to pad out to the next 32-byte boundary.
+  0x66, 0x66, 0x66, 0x66, 0x66, 0x66,    // excess data32 prefixes
+  0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1)
+
+  // Lazy GOT entries point here (32-byte aligned).
+  0x68,                       // pushq immediate
+  0, 0, 0, 0,                 // replaced with index into relocation table
+  0xe9,                       // jmp relative
+  0, 0, 0, 0,                 // replaced with offset to start of .plt0
+
+  // 22 bytes of nop to pad out to the standard size.
+  0x66, 0x66, 0x66, 0x66, 0x66, 0x66,    // excess data32 prefixes
+  0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1)
+  0x0f, 0x1f, 0x80, 0, 0, 0, 0,          // nopl 0x0(%rax)
+};
+
+template<int size>
+unsigned int
+Output_data_plt_x86_64_nacl<size>::do_fill_plt_entry(
+    unsigned char* pov,
+    typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+    typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+    unsigned int got_offset,
+    unsigned int plt_offset,
+    unsigned int plt_index)
+{
+  memcpy(pov, plt_entry, plt_entry_size);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 3,
+                                             (got_address + got_offset
+                                              - (plt_address + plt_offset
+                                                 + 3 + 4)));
+
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 33, plt_index);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 38,
+                                             - (plt_offset + 38 + 4));
+
+  return 32;
+}
+
+// The reserved TLSDESC entry in the PLT.
+
+template<int size>
+const unsigned char
+Output_data_plt_x86_64_nacl<size>::tlsdesc_plt_entry[plt_entry_size] =
+{
+  0xff, 0x35,                  // pushq x(%rip)
+  0, 0, 0, 0,  // replaced with address of linkmap GOT entry (at PLTGOT + 8)
+  0x4c, 0x8b, 0x1d,            // mov y(%rip),%r11
+  0, 0, 0, 0,  // replaced with offset of reserved TLSDESC_GOT entry
+  0x41, 0x83, 0xe3, NACLMASK,  // and $-32, %r11d
+  0x4d, 0x01, 0xfb,             // add %r15, %r11
+  0x41, 0xff, 0xe3,             // jmpq *%r11
+
+  // 41 bytes of nop to pad out to the standard size.
+  0x66, 0x66, 0x66, 0x66, 0x66, 0x66,    // excess data32 prefixes
+  0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1)
+  0x66, 0x66, 0x66, 0x66, 0x66, 0x66,    // excess data32 prefixes
+  0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1)
+  0x66, 0x66,                            // excess data32 prefixes
+  0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1)
+};
+
+template<int size>
+void
+Output_data_plt_x86_64_nacl<size>::do_fill_tlsdesc_entry(
+    unsigned char* pov,
+    typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+    typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+    typename elfcpp::Elf_types<size>::Elf_Addr got_base,
+    unsigned int tlsdesc_got_offset,
+    unsigned int plt_offset)
+{
+  memcpy(pov, tlsdesc_plt_entry, plt_entry_size);
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+                                             (got_address + 8
+                                              - (plt_address + plt_offset
+                                                 + 2 + 4)));
+  elfcpp::Swap_unaligned<32, false>::writeval(pov + 9,
+                                             (got_base
+                                              + tlsdesc_got_offset
+                                              - (plt_address + plt_offset
+                                                 + 9 + 4)));
+}
+
+// The .eh_frame unwind information for the PLT.
+
+template<int size>
+const unsigned char
+Output_data_plt_x86_64_nacl<size>::plt_eh_frame_fde[plt_eh_frame_fde_size] =
+{
+  0, 0, 0, 0,                          // Replaced with offset to .plt.
+  0, 0, 0, 0,                          // Replaced with size of .plt.
+  0,                                   // Augmentation size.
+  elfcpp::DW_CFA_def_cfa_offset, 16,   // DW_CFA_def_cfa_offset: 16.
+  elfcpp::DW_CFA_advance_loc + 6,      // Advance 6 to __PLT__ + 6.
+  elfcpp::DW_CFA_def_cfa_offset, 24,   // DW_CFA_def_cfa_offset: 24.
+  elfcpp::DW_CFA_advance_loc + 58,     // Advance 58 to __PLT__ + 64.
+  elfcpp::DW_CFA_def_cfa_expression,   // DW_CFA_def_cfa_expression.
+  13,                                  // Block length.
+  elfcpp::DW_OP_breg7, 8,              // Push %rsp + 8.
+  elfcpp::DW_OP_breg16, 0,             // Push %rip.
+  elfcpp::DW_OP_const1u, 63,           // Push 0x3f.
+  elfcpp::DW_OP_and,                   // & (%rip & 0x3f).
+  elfcpp::DW_OP_const1u, 37,            // Push 0x25.
+  elfcpp::DW_OP_ge,                    // >= ((%rip & 0x3f) >= 0x25)
+  elfcpp::DW_OP_lit3,                  // Push 3.
+  elfcpp::DW_OP_shl,                   // << (((%rip & 0x3f) >= 0x25) << 3)
+  elfcpp::DW_OP_plus,                  // + ((((%rip&0x3f)>=0x25)<<3)+%rsp+8
+  elfcpp::DW_CFA_nop,                  // Align to 32 bytes.
+  elfcpp::DW_CFA_nop
+};
+
+// The selector for x86_64-nacl object files.
+
+template<int size>
+class Target_selector_x86_64_nacl
+  : public Target_selector_nacl<Target_selector_x86_64<size>,
+                               Target_x86_64_nacl<size> >
+{
+ public:
+  Target_selector_x86_64_nacl()
+    : Target_selector_nacl<Target_selector_x86_64<size>,
+                          Target_x86_64_nacl<size> >("x86-64",
+                                                     size == 64
+                                                     ? "elf64-x86-64-nacl"
+                                                     : "elf32-x86-64-nacl",
+                                                     size == 64
+                                                     ? "elf_x86_64_nacl"
+                                                     : "elf32_x86_64_nacl")
+  { }
+};
+
+Target_selector_x86_64_nacl<64> target_selector_x86_64;
+Target_selector_x86_64_nacl<32> target_selector_x32;
 
 } // End anonymous namespace.