Skip to content

Commit 2b35723

Browse files
committed
Default to -Z plt=yes
6009da0 defaulted to `-Z plt=no` (like `clang -fno-plt`) which a not a useful default[1]. On x86-64, if the target symbol is preemptible, there is an `R_X86_64_GLOB_DAT` relocation, and the (very minor) optimization works as intended. However, if the target is non-preemptible, i.e. the target is resolved to the same component, this is actually a pessimization due to the longer instruction. On RISC architectures, there is typically no single instruction which can load a GOT entry and perform an indirect call. `-fno-plt` has a longer code quence. For example, AArch64 needs 3 instructions: adrp x0, _GLOBAL_OFFSET_TABLE_ ldr x0, [x0, #:gotpage_lo15:bar] br x0 This does not end up with a serious code size issue, because LLVM "RtLibUseGOT" is not implemented for non-x86 targets. On x86-32, very new lld[2] (2022-12-31) is needed to support general-dynamic/local-dynamic TLS models. `-Z plt=no` is not an appropriate default, so just default to true for all targets. [1] https://maskray.me/blog/2021-09-19-all-about-procedure-linkage-table#fno-plt [2] llvm/llvm-project@8dc7366
1 parent b22c152 commit 2b35723

File tree

8 files changed

+11
-39
lines changed

8 files changed

+11
-39
lines changed

compiler/rustc_interface/src/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ fn test_unstable_options_tracking_hash() {
766766
tracked!(panic_abort_tests, true);
767767
tracked!(panic_in_drop, PanicStrategy::Abort);
768768
tracked!(pick_stable_methods_before_any_unstable, false);
769-
tracked!(plt, Some(true));
769+
tracked!(plt, false);
770770
tracked!(polonius, true);
771771
tracked!(precise_enum_drop_elaboration, false);
772772
tracked!(print_fuel, Some("abc".to_string()));

compiler/rustc_session/src/options.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1479,10 +1479,10 @@ options! {
14791479
"print some performance-related statistics (default: no)"),
14801480
pick_stable_methods_before_any_unstable: bool = (true, parse_bool, [TRACKED],
14811481
"try to pick stable methods first before picking any unstable methods (default: yes)"),
1482-
plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
1483-
"whether to use the PLT when calling into shared libraries;
1484-
only has effect for PIC code on systems with ELF binaries
1485-
(default: PLT is disabled if full relro is enabled)"),
1482+
plt: bool = (true, parse_bool, [TRACKED],
1483+
"if false, use GOT-generating code sequences for external function calls. \
1484+
This results in longer code sequences, but may avoid a PLT if the function is not bound locally. \
1485+
Only has effect on ELF systems (default: yes)"),
14861486
polonius: bool = (false, parse_bool, [TRACKED],
14871487
"enable polonius-based borrow-checker (default: no)"),
14881488
polymorphize: bool = (false, parse_bool, [TRACKED],

compiler/rustc_session/src/session.rs

+2-17
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use rustc_span::edition::Edition;
3737
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap, Span};
3838
use rustc_span::{sym, SourceFileHashAlgorithm, Symbol};
3939
use rustc_target::asm::InlineAsmArch;
40-
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
40+
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel};
4141
use rustc_target::spec::{
4242
DebuginfoKind, SanitizerSet, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel,
4343
};
@@ -908,22 +908,7 @@ impl Session {
908908

909909
/// Returns `true` if we cannot skip the PLT for shared library calls.
910910
pub fn needs_plt(&self) -> bool {
911-
// Check if the current target usually needs PLT to be enabled.
912-
// The user can use the command line flag to override it.
913-
let needs_plt = self.target.needs_plt;
914-
915-
let dbg_opts = &self.opts.unstable_opts;
916-
917-
let relro_level = dbg_opts.relro_level.unwrap_or(self.target.relro_level);
918-
919-
// Only enable this optimization by default if full relro is also enabled.
920-
// In this case, lazy binding was already unavailable, so nothing is lost.
921-
// This also ensures `-Wl,-z,now` is supported by the linker.
922-
let full_relro = RelroLevel::Full == relro_level;
923-
924-
// If user didn't explicitly forced us to use / skip the PLT,
925-
// then try to skip it where possible.
926-
dbg_opts.plt.unwrap_or(needs_plt || !full_relro)
911+
self.opts.unstable_opts.plt
927912
}
928913

929914
/// Checks if LLVM lifetime markers should be emitted.

compiler/rustc_target/src/spec/mod.rs

-6
Original file line numberDiff line numberDiff line change
@@ -1549,9 +1549,6 @@ pub struct TargetOptions {
15491549
pub position_independent_executables: bool,
15501550
/// Executables that are both statically linked and position-independent are supported.
15511551
pub static_position_independent_executables: bool,
1552-
/// Determines if the target always requires using the PLT for indirect
1553-
/// library calls or not. This controls the default value of the `-Z plt` flag.
1554-
pub needs_plt: bool,
15551552
/// Either partial, full, or off. Full RELRO makes the dynamic linker
15561553
/// resolve all symbols at startup and marks the GOT read-only before
15571554
/// starting the program, preventing overwriting the GOT.
@@ -1871,7 +1868,6 @@ impl Default for TargetOptions {
18711868
no_default_libraries: true,
18721869
position_independent_executables: false,
18731870
static_position_independent_executables: false,
1874-
needs_plt: false,
18751871
relro_level: RelroLevel::None,
18761872
pre_link_objects: Default::default(),
18771873
post_link_objects: Default::default(),
@@ -2544,7 +2540,6 @@ impl Target {
25442540
key!(no_default_libraries, bool);
25452541
key!(position_independent_executables, bool);
25462542
key!(static_position_independent_executables, bool);
2547-
key!(needs_plt, bool);
25482543
key!(relro_level, RelroLevel)?;
25492544
key!(archive_format);
25502545
key!(allow_asm, bool);
@@ -2798,7 +2793,6 @@ impl ToJson for Target {
27982793
target_option_val!(no_default_libraries);
27992794
target_option_val!(position_independent_executables);
28002795
target_option_val!(static_position_independent_executables);
2801-
target_option_val!(needs_plt);
28022796
target_option_val!(relro_level);
28032797
target_option_val!(archive_format);
28042798
target_option_val!(allow_asm);

compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs

-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ pub fn target() -> Target {
88
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mx32"]);
99
base.stack_probes = StackProbeType::X86;
1010
base.has_thread_local = false;
11-
// BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI
12-
// breaks code gen. See LLVM bug 36743
13-
base.needs_plt = true;
1411

1512
Target {
1613
llvm_target: "x86_64-unknown-linux-gnux32".into(),

tests/assembly/pic-relocation-model.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ trait Sized {}
1414
trait Copy {}
1515

1616
// CHECK-LABEL: call_other_fn:
17-
// CHECK: {{(jmpq|callq)}} *other_fn@GOTPCREL(%rip)
17+
// CHECK: {{(jmp|callq)}} other_fn@PLT
1818
#[no_mangle]
1919
pub fn call_other_fn() -> u8 {
2020
unsafe {
@@ -23,7 +23,7 @@ pub fn call_other_fn() -> u8 {
2323
}
2424

2525
// CHECK-LABEL: other_fn:
26-
// CHECK: callq *foreign_fn@GOTPCREL(%rip)
26+
// CHECK: callq foreign_fn@PLT
2727
#[no_mangle]
2828
#[inline(never)]
2929
pub fn other_fn() -> u8 {

tests/assembly/pie-relocation-model.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ pub fn call_other_fn() -> u8 {
2424
}
2525

2626
// CHECK-LABEL: other_fn:
27-
// External functions are still called through GOT, since we don't know if the symbol
28-
// is defined in the binary or in the shared library.
29-
// CHECK: callq *foreign_fn@GOTPCREL(%rip)
27+
// CHECK: callq foreign_fn@PLT
3028
#[no_mangle]
3129
#[inline(never)]
3230
pub fn other_fn() -> u8 {

tests/rustdoc-ui/z-help.stdout

+1-3
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,7 @@
107107
-Z parse-only=val -- parse only; do not compile, assemble, or link (default: no)
108108
-Z perf-stats=val -- print some performance-related statistics (default: no)
109109
-Z pick-stable-methods-before-any-unstable=val -- try to pick stable methods first before picking any unstable methods (default: yes)
110-
-Z plt=val -- whether to use the PLT when calling into shared libraries;
111-
only has effect for PIC code on systems with ELF binaries
112-
(default: PLT is disabled if full relro is enabled)
110+
-Z plt=val -- if false, use GOT-generating code sequences for external function calls. This results in longer code sequences, but may avoid a PLT if the function is not bound locally. Only has effect on ELF systems (default: yes)
113111
-Z polonius=val -- enable polonius-based borrow-checker (default: no)
114112
-Z polymorphize=val -- perform polymorphization analysis
115113
-Z pre-link-arg=val -- a single extra argument to prepend the linker invocation (can be used several times)

0 commit comments

Comments
 (0)