mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-23 20:19:49 +00:00
* 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:
parent
1ef7171746
commit
2e702c99c5
@ -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
2
configure
vendored
@ -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*)
|
||||
;;
|
||||
|
46
configure.ac
46
configure.ac
@ -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
|
||||
|
||||
|
364
gold/ChangeLog
364
gold/ChangeLog
@ -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>
|
||||
|
@ -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 \
|
||||
|
@ -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@
|
||||
|
1214
gold/arm.cc
1214
gold/arm.cc
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
|
152
gold/gold.cc
152
gold/gold.cc
@ -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*>(¶meters->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,
|
||||
|
1615
gold/i386.cc
1615
gold/i386.cc
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
{
|
||||
|
463
gold/layout.cc
463
gold/layout.cc
@ -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(¶meters->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(¶meters->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)
|
||||
|
@ -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
46
gold/nacl.cc
Normal 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
243
gold/nacl.h
Normal 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)
|
616
gold/object.cc
616
gold/object.cc
@ -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;
|
||||
|
@ -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,
|
||||
|
210
gold/powerpc.cc
210
gold/powerpc.cc
@ -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>(); }
|
||||
};
|
||||
|
||||
|
326
gold/sparc.cc
326
gold/sparc.cc
@ -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>(); }
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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*>*)
|
||||
{ }
|
||||
};
|
||||
|
1590
gold/x86_64.cc
1590
gold/x86_64.cc
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user