Skip to content

Commit 34e0882

Browse files
committed
[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.
1 parent 34ca2bd commit 34e0882

8 files changed

Lines changed: 454 additions & 57 deletions

File tree

‎elfcpp/ChangeLog‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2017-08-29 Alan Modra <amodra@gmail.com>
2+
3+
* elfcpp.h (DT_PPC_OPT): Define.
4+
* powerpc.h (PPC_OPT_TLS): Define.
5+
16
2017-07-28 H.J. Lu <hongjiu.lu@intel.com>
27

38
PR gold/21857

‎elfcpp/elfcpp.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,9 @@ enum DT
768768
// Specify the value of _GLOBAL_OFFSET_TABLE_.
769769
DT_PPC_GOT = 0x70000000,
770770

771+
// Specify whether various optimisations are possible.
772+
DT_PPC_OPT = 0x70000001,
773+
771774
// Specify the start of the .glink section.
772775
DT_PPC64_GLINK = 0x70000000,
773776

‎elfcpp/powerpc.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,12 @@ enum
228228
EF_PPC64_ABI = 3
229229
};
230230

231+
// DT_PPC_OPT bits
232+
enum
233+
{
234+
PPC_OPT_TLS = 1
235+
};
236+
231237
// DT_PPC64_OPT bits
232238
enum
233239
{

‎gold/ChangeLog‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,44 @@
1+
2017-08-29 Alan Modra <amodra@gmail.com>
2+
3+
* options.h (tls_get_addr_optimize): New option.
4+
* symtab.h (Symbol::clear_in_reg, clone): New functions.
5+
(Sized_symbol::clone): New function.
6+
(Symbol_table::clone): New function.
7+
* resolve.cc (Symbol::clone, Sized_symbol::clone): New functions.
8+
* powerpc.cc (Target_powerpc::has_tls_get_addr_opt_,
9+
tls_get_addr_, tls_get_addr_opt_): New vars.
10+
(Target_powerpc::tls_get_addr_opt, tls_get_addr,
11+
is_tls_get_addr_opt, replace_tls_get_addr,
12+
set_has_tls_get_addr_opt, stk_linker): New functions.
13+
(Target_powerpc::Track_tls::maybe_skip_tls_get_addr_call): Add
14+
target param. Update callers. Compare symbols rather than names.
15+
(Target_powerpc::do_define_standard_symbols): Init tls_get_addr_
16+
and tls_get_addr_opt_.
17+
(Target_powerpc::Branch_info::mark_pltcall): Translate tls_get_addr
18+
sym to tls_get_addr_opt.
19+
(Target_powerpc::Branch_info::make_stub): Likewise.
20+
(Stub_table::define_stub_syms): Likewise.
21+
(Target_powerpc::Scan::global): Likewise.
22+
(Target_powerpc::Relocate::relocate): Likewise.
23+
(add_3_12_2, add_3_12_13, bctrl, beqlr, cmpdi_11_0, cmpwi_11_0,
24+
ld_11_1, ld_11_3, ld_12_3, lwz_11_3, lwz_12_3, mr_0_3, mr_3_0,
25+
mtlr_11, std_11_1): New constants.
26+
(Stub_table::eh_frame_added_): Delete.
27+
(Stub_table::tls_get_addr_opt_bctrl_, plt_fde_len_, plt_fde_): New vars.
28+
(Stub_table::init_plt_fde): New functions.
29+
(Stub_table::add_eh_frame, replace_eh_frame): Move definition out
30+
of line. Init and use plt_fde_.
31+
(Stub_table::plt_call_size): Return size for tls_get_addr stub.
32+
Extract alignment code to..
33+
(Stub_table::plt_call_align): ..this new function. Adjust all callers.
34+
(Stub_table::add_plt_call_entry): Set has_tls_get_addr_opt and
35+
tls_get_addr_opt_bctrl, and align after that.
36+
(Stub_table::do_write): Write out tls_get_addr stub.
37+
(Target_powerpc::do_finalize_sections): Emit DT_PPC_OPT
38+
PPC_OPT_TLS/PPC64_OPT_TLS bit.
39+
(Target_powerpc::Relocate::relocate): Don't check for or modify
40+
nop following bl for tls_get_addr stub.
41+
142
2017-08-29 Alan Modra <amodra@gmail.com>
243

344
* symtab.h (Symbol): Split u_ into u1_ and u2_. Adjust accessors

‎gold/options.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,9 @@ class General_options
12941294
DEFINE_bool(tls_optimize, options::TWO_DASHES, '\0', true,
12951295
N_("(PowerPC/64 only) Optimize GD/LD/IE code to IE/LE"),
12961296
N_("(PowerPC/64 only) Don'\''t try to optimize TLS accesses"));
1297+
DEFINE_bool(tls_get_addr_optimize, options::TWO_DASHES, '\0', true,
1298+
N_("(PowerPC/64 only) Use a special __tls_get_addr call"),
1299+
N_("(PowerPC/64 only) Don't use a special __tls_get_addr call"));
12971300

12981301
DEFINE_bool(toc_optimize, options::TWO_DASHES, '\0', true,
12991302
N_("(PowerPC64 only) Optimize TOC code sequences"),

0 commit comments

Comments
 (0)