* configure.ac (ENABLE_GOLD): Consider *-*-nacl* targets ELF.

* 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
This commit is contained in:
Roland McGrath 2012-05-02 21:37:24 +00:00
parent 1ef7171746
commit 2e702c99c5
24 changed files with 4643 additions and 2596 deletions

View File

@ -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.
@ -586,7 +591,7 @@
* 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.

2
configure vendored
View File

@ -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*)
;;

View 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

View 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)
@ -304,7 +500,7 @@
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
@ -2008,7 +2204,7 @@
* 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
@ -2495,7 +2691,7 @@
* 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.
@ -3251,9 +3447,9 @@
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>
@ -3542,7 +3738,7 @@
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
@ -3550,7 +3746,7 @@
(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
@ -3609,7 +3805,7 @@
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>
@ -3636,43 +3832,43 @@
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>
@ -4707,7 +4903,7 @@
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
@ -4719,7 +4915,7 @@
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
@ -5078,15 +5274,15 @@
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.
@ -5104,12 +5300,12 @@
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_,
@ -5385,7 +5581,7 @@
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.
@ -5556,7 +5752,7 @@
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.
@ -5622,13 +5818,13 @@
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.
@ -5644,10 +5840,10 @@
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.
@ -5850,7 +6046,7 @@
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.
@ -5862,7 +6058,7 @@
(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.
@ -5900,7 +6096,7 @@
* 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,
@ -5954,7 +6150,7 @@
(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.
@ -6296,8 +6492,8 @@
* 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.
@ -6416,14 +6612,14 @@
* 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.
@ -6435,7 +6631,7 @@
(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.
@ -6527,11 +6723,11 @@
(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
@ -6803,7 +6999,7 @@
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.
@ -7514,7 +7710,7 @@
(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,
@ -8505,7 +8701,7 @@
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.
@ -8931,7 +9127,7 @@
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
@ -9158,7 +9354,7 @@
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.
@ -9419,7 +9615,7 @@
* 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.
@ -10345,11 +10541,11 @@
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>
@ -10389,7 +10585,7 @@
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>

View 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 \

View 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@

File diff suppressed because it is too large Load Diff

View 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)

View 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,

File diff suppressed because it is too large Load Diff

View 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)
{

View 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);
off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
// 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));
}
}
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)

View 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

46
gold/nacl.cc Normal file
View File

@ -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

243
gold/nacl.h Normal file
View File

@ -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)

View 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);
{
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);
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;
}
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(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);
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;
}
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;

View 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,

View 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>(); }
};

View 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>(); }
};

View 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;
}

View 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.

View 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.

View 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*>*)
{ }
};

File diff suppressed because it is too large Load Diff