From 0e7d5be4b808bd7ccb1d45aa8f7e5026a15aee93 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Thu, 16 Apr 2020 19:40:11 -0700 Subject: [PATCH] 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 --- src/librustc_codegen_llvm/back/write.rs | 8 ++++++++ src/librustc_codegen_llvm/llvm/ffi.rs | 1 + src/librustc_interface/tests.rs | 1 + src/librustc_session/options.rs | 2 ++ src/librustc_target/spec/mod.rs | 7 +++++++ src/librustc_target/spec/netbsd_base.rs | 1 + src/rustllvm/PassWrapper.cpp | 4 +++- 7 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 3ec7ef831b5..6196993310e 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -166,6 +166,13 @@ pub fn target_machine_factory( let asm_comments = sess.asm_comments(); let relax_elf_relocations = sess.target.target.options.relax_elf_relocations; + + let use_init_array = !sess + .opts + .debugging_opts + .use_ctors_section + .unwrap_or(sess.target.target.options.use_ctors_section); + Arc::new(move || { let tm = unsafe { llvm::LLVMRustCreateTargetMachine( @@ -185,6 +192,7 @@ pub fn target_machine_factory( asm_comments, emit_stack_size_section, relax_elf_relocations, + use_init_array, ) }; diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index fd03812cccd..53a7f718197 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -1956,6 +1956,7 @@ extern "C" { AsmComments: bool, EmitStackSizeSection: bool, RelaxELFRelocations: bool, + UseInitArray: bool, ) -> Option<&'static mut TargetMachine>; pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine); pub fn LLVMRustAddBuilderLibraryInfo( diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index cee2e5b5bec..d041a05e25f 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -571,6 +571,7 @@ fn test_debugging_options_tracking_hash() { tracked!(tls_model, Some(TlsModel::GeneralDynamic)); tracked!(treat_err_as_bug, Some(1)); tracked!(unleash_the_miri_inside_of_you, true); + tracked!(use_ctors_section, Some(true)); tracked!(verify_llvm_ir, true); } diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 5b983d1105d..943f0cde010 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -1010,6 +1010,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)"), unstable_options: bool = (false, parse_bool, [UNTRACKED], "adds unstable command line options to rustc interface (default: no)"), + use_ctors_section: Option = (None, parse_opt_bool, [TRACKED], + "use legacy .ctors section for initializers rather than .init_array"), verbose: bool = (false, parse_bool, [UNTRACKED], "in general, enable more debug printouts (default: no)"), verify_llvm_ir: bool = (false, parse_bool, [TRACKED], diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index e853c07632f..579453cd7f8 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -878,6 +878,10 @@ pub struct TargetOptions { /// Additional arguments to pass to LLVM, similar to the `-C llvm-args` codegen option. pub llvm_args: Vec, + + /// Whether to use legacy .ctors initialization hooks rather than .init_array. Defaults + /// to false (uses .init_array). + pub use_ctors_section: bool, } impl Default for TargetOptions { @@ -966,6 +970,7 @@ impl Default for TargetOptions { llvm_abiname: "".to_string(), relax_elf_relocations: false, llvm_args: vec![], + use_ctors_section: false, } } } @@ -1304,6 +1309,7 @@ impl Target { key!(llvm_abiname); key!(relax_elf_relocations, bool); key!(llvm_args, list); + key!(use_ctors_section, bool); if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) { for name in array.iter().filter_map(|abi| abi.as_string()) { @@ -1531,6 +1537,7 @@ impl ToJson for Target { target_option_val!(llvm_abiname); target_option_val!(relax_elf_relocations); target_option_val!(llvm_args); + target_option_val!(use_ctors_section); if default.abi_blacklist != self.options.abi_blacklist { d.insert( diff --git a/src/librustc_target/spec/netbsd_base.rs b/src/librustc_target/spec/netbsd_base.rs index 95c4749f9c7..988346af2d7 100644 --- a/src/librustc_target/spec/netbsd_base.rs +++ b/src/librustc_target/spec/netbsd_base.rs @@ -23,6 +23,7 @@ pub fn opts() -> TargetOptions { pre_link_args: args, position_independent_executables: true, relro_level: RelroLevel::Full, + use_ctors_section: true, ..Default::default() } } diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index e31dd77d8af..0acedc25db8 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -445,7 +445,8 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( bool Singlethread, bool AsmComments, bool EmitStackSizeSection, - bool RelaxELFRelocations) { + bool RelaxELFRelocations, + bool UseInitArray) { auto OptLevel = fromRust(RustOptLevel); auto RM = fromRust(RustReloc); @@ -471,6 +472,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( Options.MCOptions.PreserveAsmComments = AsmComments; Options.MCOptions.ABIName = ABIStr; Options.RelaxELFRelocations = RelaxELFRelocations; + Options.UseInitArray = UseInitArray; if (TrapUnreachable) { // Tell LLVM to codegen `unreachable` into an explicit trap instruction.