diff options
author | Alan Modra <amodra@gmail.com> | 2017-08-29 15:55:33 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2017-08-29 21:29:37 +0930 |
commit | 34e0882b83aedc6fb9c7532c89afaf8e0043b7ce (patch) | |
tree | 639ddded69114a9e5e971bdc0e983698035d7cf6 /elfcpp | |
parent | 34ca2bd7ace5e208d46fea6e7a56a5376de0abfe (diff) | |
download | binutils-34e0882b83aedc6fb9c7532c89afaf8e0043b7ce.zip binutils-34e0882b83aedc6fb9c7532c89afaf8e0043b7ce.tar.gz binutils-34e0882b83aedc6fb9c7532c89afaf8e0043b7ce.tar.bz2 |
[GOLD] PowerPC tls_get_addr_optimize
This implements the special __tls_get_addr_opt call stub for powerpc
gold that returns __thread variable addresses without actually making
a call to __tls_get_addr in most cases. Shared libraries that are
loaded at program load time (ie. dlopen is not used) have a known
layout for their __thread variables, and thus DTPMOD64/DPTREL64 pairs
describing those variables can be set up by ld.so for the
__tls_get_addr_opt call stub fast exit.
Ref https://sourceware.org/ml/libc-alpha/2015-03/msg00626.html
I really, really wish I'd used a differently versioned __tls_get_addr
symbol than the base symbol to indicate glibc support for the
optimized call, rather than having glibc export __tls_get_addr_opt. A
lot of the messing around here, flipping symbols from __tls_get_addr
to __tls_get_addr_opt, is caused by that decision. About the only
benefit is that a user can see at a glance that their disassembled
code is calling __tls_get_addr via the fancy call stub.. Anyway, we
need references to __tls_get_addr to seem like they were to
__tls_get_addr_opt, and in cases like the tsan interceptor, a
definition of __tls_get_addr to seem like one of __tls_get_addr_opt
as well. That's the reason for Symbol::clear_in_reg and
Symbol_table::clone, and why symbols are substituted in Scan::global
and other places dealing with dynamic linking.
elfcpp/
* elfcpp.h (DT_PPC_OPT): Define.
* powerpc.h (PPC_OPT_TLS): Define.
gold/
* options.h (tls_get_addr_optimize): New option.
* symtab.h (Symbol::clear_in_reg, clone): New functions.
(Sized_symbol::clone): New function.
(Symbol_table::clone): New function.
* resolve.cc (Symbol::clone, Sized_symbol::clone): New functions.
* powerpc.cc (Target_powerpc::has_tls_get_addr_opt_,
tls_get_addr_, tls_get_addr_opt_): New vars.
(Target_powerpc::tls_get_addr_opt, tls_get_addr,
is_tls_get_addr_opt, replace_tls_get_addr,
set_has_tls_get_addr_opt, stk_linker): New functions.
(Target_powerpc::Track_tls::maybe_skip_tls_get_addr_call): Add
target param. Update callers. Compare symbols rather than names.
(Target_powerpc::do_define_standard_symbols): Init tls_get_addr_
and tls_get_addr_opt_.
(Target_powerpc::Branch_info::mark_pltcall): Translate tls_get_addr
sym to tls_get_addr_opt.
(Target_powerpc::Branch_info::make_stub): Likewise.
(Stub_table::define_stub_syms): Likewise.
(Target_powerpc::Scan::global): Likewise.
(Target_powerpc::Relocate::relocate): Likewise.
(add_3_12_2, add_3_12_13, bctrl, beqlr, cmpdi_11_0, cmpwi_11_0,
ld_11_1, ld_11_3, ld_12_3, lwz_11_3, lwz_12_3, mr_0_3, mr_3_0,
mtlr_11, std_11_1): New constants.
(Stub_table::eh_frame_added_): Delete.
(Stub_table::tls_get_addr_opt_bctrl_, plt_fde_len_, plt_fde_): New vars.
(Stub_table::init_plt_fde): New functions.
(Stub_table::add_eh_frame, replace_eh_frame): Move definition out
of line. Init and use plt_fde_.
(Stub_table::plt_call_size): Return size for tls_get_addr stub.
Extract alignment code to..
(Stub_table::plt_call_align): ..this new function. Adjust all callers.
(Stub_table::add_plt_call_entry): Set has_tls_get_addr_opt and
tls_get_addr_opt_bctrl, and align after that.
(Stub_table::do_write): Write out tls_get_addr stub.
(Target_powerpc::do_finalize_sections): Emit DT_PPC_OPT
PPC_OPT_TLS/PPC64_OPT_TLS bit.
(Target_powerpc::Relocate::relocate): Don't check for or modify
nop following bl for tls_get_addr stub.
Diffstat (limited to 'elfcpp')
-rw-r--r-- | elfcpp/ChangeLog | 5 | ||||
-rw-r--r-- | elfcpp/elfcpp.h | 3 | ||||
-rw-r--r-- | elfcpp/powerpc.h | 6 |
3 files changed, 14 insertions, 0 deletions
diff --git a/elfcpp/ChangeLog b/elfcpp/ChangeLog index f669248..200d0d4ee 100644 --- a/elfcpp/ChangeLog +++ b/elfcpp/ChangeLog @@ -1,3 +1,8 @@ +2017-08-29 Alan Modra <amodra@gmail.com> + + * elfcpp.h (DT_PPC_OPT): Define. + * powerpc.h (PPC_OPT_TLS): Define. + 2017-07-28 H.J. Lu <hongjiu.lu@intel.com> PR gold/21857 diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h index cccec4c..1f629ce 100644 --- a/elfcpp/elfcpp.h +++ b/elfcpp/elfcpp.h @@ -768,6 +768,9 @@ enum DT // Specify the value of _GLOBAL_OFFSET_TABLE_. DT_PPC_GOT = 0x70000000, + // Specify whether various optimisations are possible. + DT_PPC_OPT = 0x70000001, + // Specify the start of the .glink section. DT_PPC64_GLINK = 0x70000000, diff --git a/elfcpp/powerpc.h b/elfcpp/powerpc.h index 3dc0828..71cac5e 100644 --- a/elfcpp/powerpc.h +++ b/elfcpp/powerpc.h @@ -228,6 +228,12 @@ enum EF_PPC64_ABI = 3 }; +// DT_PPC_OPT bits +enum +{ + PPC_OPT_TLS = 1 +}; + // DT_PPC64_OPT bits enum { |