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 /gold/symtab.h | |
parent | 34ca2bd7ace5e208d46fea6e7a56a5376de0abfe (diff) | |
download | gdb-34e0882b83aedc6fb9c7532c89afaf8e0043b7ce.zip gdb-34e0882b83aedc6fb9c7532c89afaf8e0043b7ce.tar.gz gdb-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 'gold/symtab.h')
-rw-r--r-- | gold/symtab.h | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/gold/symtab.h b/gold/symtab.h index 88d6c27..a67d5eb 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -329,6 +329,11 @@ class Symbol set_in_reg() { this->in_reg_ = true; } + // Forget this symbol was seen in a regular object. + void + clear_in_reg() + { this->in_reg_ = false; } + // Return whether this symbol has been seen in a dynamic object. bool in_dyn() const @@ -893,6 +898,13 @@ class Symbol set_non_zero_localentry() { this->non_zero_localentry_ = true; } + // Completely override existing symbol. Everything bar name_, + // version_, and is_forced_local_ flag are copied. version_ is + // cleared if from->version_ is clear. Returns true if this symbol + // should be forced local. + bool + clone(const Symbol* from); + protected: // Instances of this class should always be created at a specific // size. @@ -1182,6 +1194,13 @@ class Sized_symbol : public Symbol void allocate_common(Output_data*, Value_type value); + // Completely override existing symbol. Everything bar name_, + // version_, and is_forced_local_ flag are copied. version_ is + // cleared if from->version_ is clear. Returns true if this symbol + // should be forced local. + bool + clone(const Sized_symbol<size>* from); + private: Sized_symbol(const Sized_symbol&); Sized_symbol& operator=(const Sized_symbol&); @@ -1687,6 +1706,15 @@ class Symbol_table version_script() const { return version_script_; } + // Completely override existing symbol. + template<int size> + void + clone(Sized_symbol<size>* to, const Sized_symbol<size>* from) + { + if (to->clone(from)) + this->force_local(to); + } + private: Symbol_table(const Symbol_table&); Symbol_table& operator=(const Symbol_table&); |