diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index e261ac65446..dd9ada0b95d 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -165,6 +165,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( @@ -184,6 +191,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 477712f5053..0d466c2cd74 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 69237b81a82..de304bcec23 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 689fbf3b95a..4eabb55e6df 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 51dce9e144c..477161dc658 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -882,6 +882,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 { @@ -972,6 +976,7 @@ impl Default for TargetOptions { llvm_abiname: "".to_string(), relax_elf_relocations: false, llvm_args: vec![], + use_ctors_section: false, } } } @@ -1312,6 +1317,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()) { @@ -1541,6 +1547,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 e1d75418243..84bde9a52f7 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -447,7 +447,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); @@ -473,6 +474,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.