Skip to content

Commit 0e7d5be

Browse files
committed
Use .init_array rather than .ctors
LLVM TargetMachines default to using the (now-legacy) .ctors representation of init functions. Mixing .ctors and .init_array representations can cause issues when linking with lld. This happens in practice for: * Our profiling runtime which is currently implicitly built with .init_array since it is built by clang, which sets this field. * External C/C++ code that may be linked into the same process. To support legacy systems which may use .ctors, targets may now specify that they use .ctors via the use_ctors attribute which defaults to false. For debugging and manual control, -Z use-ctors-section=yes/no will allow manual override. Fixes: #71233
1 parent 825cf51 commit 0e7d5be

File tree

7 files changed

+23
-1
lines changed

7 files changed

+23
-1
lines changed

src/librustc_codegen_llvm/back/write.rs

+8
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,13 @@ pub fn target_machine_factory(
166166

167167
let asm_comments = sess.asm_comments();
168168
let relax_elf_relocations = sess.target.target.options.relax_elf_relocations;
169+
170+
let use_init_array = !sess
171+
.opts
172+
.debugging_opts
173+
.use_ctors_section
174+
.unwrap_or(sess.target.target.options.use_ctors_section);
175+
169176
Arc::new(move || {
170177
let tm = unsafe {
171178
llvm::LLVMRustCreateTargetMachine(
@@ -185,6 +192,7 @@ pub fn target_machine_factory(
185192
asm_comments,
186193
emit_stack_size_section,
187194
relax_elf_relocations,
195+
use_init_array,
188196
)
189197
};
190198

src/librustc_codegen_llvm/llvm/ffi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1956,6 +1956,7 @@ extern "C" {
19561956
AsmComments: bool,
19571957
EmitStackSizeSection: bool,
19581958
RelaxELFRelocations: bool,
1959+
UseInitArray: bool,
19591960
) -> Option<&'static mut TargetMachine>;
19601961
pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
19611962
pub fn LLVMRustAddBuilderLibraryInfo(

src/librustc_interface/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,7 @@ fn test_debugging_options_tracking_hash() {
571571
tracked!(tls_model, Some(TlsModel::GeneralDynamic));
572572
tracked!(treat_err_as_bug, Some(1));
573573
tracked!(unleash_the_miri_inside_of_you, true);
574+
tracked!(use_ctors_section, Some(true));
574575
tracked!(verify_llvm_ir, true);
575576
}
576577

src/librustc_session/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
10101010
`mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)"),
10111011
unstable_options: bool = (false, parse_bool, [UNTRACKED],
10121012
"adds unstable command line options to rustc interface (default: no)"),
1013+
use_ctors_section: Option<bool> = (None, parse_opt_bool, [TRACKED],
1014+
"use legacy .ctors section for initializers rather than .init_array"),
10131015
verbose: bool = (false, parse_bool, [UNTRACKED],
10141016
"in general, enable more debug printouts (default: no)"),
10151017
verify_llvm_ir: bool = (false, parse_bool, [TRACKED],

src/librustc_target/spec/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,10 @@ pub struct TargetOptions {
878878

879879
/// Additional arguments to pass to LLVM, similar to the `-C llvm-args` codegen option.
880880
pub llvm_args: Vec<String>,
881+
882+
/// Whether to use legacy .ctors initialization hooks rather than .init_array. Defaults
883+
/// to false (uses .init_array).
884+
pub use_ctors_section: bool,
881885
}
882886

883887
impl Default for TargetOptions {
@@ -966,6 +970,7 @@ impl Default for TargetOptions {
966970
llvm_abiname: "".to_string(),
967971
relax_elf_relocations: false,
968972
llvm_args: vec![],
973+
use_ctors_section: false,
969974
}
970975
}
971976
}
@@ -1304,6 +1309,7 @@ impl Target {
13041309
key!(llvm_abiname);
13051310
key!(relax_elf_relocations, bool);
13061311
key!(llvm_args, list);
1312+
key!(use_ctors_section, bool);
13071313

13081314
if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
13091315
for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -1531,6 +1537,7 @@ impl ToJson for Target {
15311537
target_option_val!(llvm_abiname);
15321538
target_option_val!(relax_elf_relocations);
15331539
target_option_val!(llvm_args);
1540+
target_option_val!(use_ctors_section);
15341541

15351542
if default.abi_blacklist != self.options.abi_blacklist {
15361543
d.insert(

src/librustc_target/spec/netbsd_base.rs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub fn opts() -> TargetOptions {
2323
pre_link_args: args,
2424
position_independent_executables: true,
2525
relro_level: RelroLevel::Full,
26+
use_ctors_section: true,
2627
..Default::default()
2728
}
2829
}

src/rustllvm/PassWrapper.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,8 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
445445
bool Singlethread,
446446
bool AsmComments,
447447
bool EmitStackSizeSection,
448-
bool RelaxELFRelocations) {
448+
bool RelaxELFRelocations,
449+
bool UseInitArray) {
449450

450451
auto OptLevel = fromRust(RustOptLevel);
451452
auto RM = fromRust(RustReloc);
@@ -471,6 +472,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
471472
Options.MCOptions.PreserveAsmComments = AsmComments;
472473
Options.MCOptions.ABIName = ABIStr;
473474
Options.RelaxELFRelocations = RelaxELFRelocations;
475+
Options.UseInitArray = UseInitArray;
474476

475477
if (TrapUnreachable) {
476478
// Tell LLVM to codegen `unreachable` into an explicit trap instruction.

0 commit comments

Comments
 (0)