mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
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
This commit is contained in:
parent
825cf51ad7
commit
0e7d5be4b8
@ -166,6 +166,13 @@ pub fn target_machine_factory(
|
|||||||
|
|
||||||
let asm_comments = sess.asm_comments();
|
let asm_comments = sess.asm_comments();
|
||||||
let relax_elf_relocations = sess.target.target.options.relax_elf_relocations;
|
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 || {
|
Arc::new(move || {
|
||||||
let tm = unsafe {
|
let tm = unsafe {
|
||||||
llvm::LLVMRustCreateTargetMachine(
|
llvm::LLVMRustCreateTargetMachine(
|
||||||
@ -185,6 +192,7 @@ pub fn target_machine_factory(
|
|||||||
asm_comments,
|
asm_comments,
|
||||||
emit_stack_size_section,
|
emit_stack_size_section,
|
||||||
relax_elf_relocations,
|
relax_elf_relocations,
|
||||||
|
use_init_array,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1956,6 +1956,7 @@ extern "C" {
|
|||||||
AsmComments: bool,
|
AsmComments: bool,
|
||||||
EmitStackSizeSection: bool,
|
EmitStackSizeSection: bool,
|
||||||
RelaxELFRelocations: bool,
|
RelaxELFRelocations: bool,
|
||||||
|
UseInitArray: bool,
|
||||||
) -> Option<&'static mut TargetMachine>;
|
) -> Option<&'static mut TargetMachine>;
|
||||||
pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
|
pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
|
||||||
pub fn LLVMRustAddBuilderLibraryInfo(
|
pub fn LLVMRustAddBuilderLibraryInfo(
|
||||||
|
@ -571,6 +571,7 @@ fn test_debugging_options_tracking_hash() {
|
|||||||
tracked!(tls_model, Some(TlsModel::GeneralDynamic));
|
tracked!(tls_model, Some(TlsModel::GeneralDynamic));
|
||||||
tracked!(treat_err_as_bug, Some(1));
|
tracked!(treat_err_as_bug, Some(1));
|
||||||
tracked!(unleash_the_miri_inside_of_you, true);
|
tracked!(unleash_the_miri_inside_of_you, true);
|
||||||
|
tracked!(use_ctors_section, Some(true));
|
||||||
tracked!(verify_llvm_ir, true);
|
tracked!(verify_llvm_ir, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1010,6 +1010,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||||||
`mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)"),
|
`mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)"),
|
||||||
unstable_options: bool = (false, parse_bool, [UNTRACKED],
|
unstable_options: bool = (false, parse_bool, [UNTRACKED],
|
||||||
"adds unstable command line options to rustc interface (default: no)"),
|
"adds unstable command line options to rustc interface (default: no)"),
|
||||||
|
use_ctors_section: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||||
|
"use legacy .ctors section for initializers rather than .init_array"),
|
||||||
verbose: bool = (false, parse_bool, [UNTRACKED],
|
verbose: bool = (false, parse_bool, [UNTRACKED],
|
||||||
"in general, enable more debug printouts (default: no)"),
|
"in general, enable more debug printouts (default: no)"),
|
||||||
verify_llvm_ir: bool = (false, parse_bool, [TRACKED],
|
verify_llvm_ir: bool = (false, parse_bool, [TRACKED],
|
||||||
|
@ -878,6 +878,10 @@ pub struct TargetOptions {
|
|||||||
|
|
||||||
/// Additional arguments to pass to LLVM, similar to the `-C llvm-args` codegen option.
|
/// Additional arguments to pass to LLVM, similar to the `-C llvm-args` codegen option.
|
||||||
pub llvm_args: Vec<String>,
|
pub llvm_args: Vec<String>,
|
||||||
|
|
||||||
|
/// 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 {
|
impl Default for TargetOptions {
|
||||||
@ -966,6 +970,7 @@ impl Default for TargetOptions {
|
|||||||
llvm_abiname: "".to_string(),
|
llvm_abiname: "".to_string(),
|
||||||
relax_elf_relocations: false,
|
relax_elf_relocations: false,
|
||||||
llvm_args: vec![],
|
llvm_args: vec![],
|
||||||
|
use_ctors_section: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1304,6 +1309,7 @@ impl Target {
|
|||||||
key!(llvm_abiname);
|
key!(llvm_abiname);
|
||||||
key!(relax_elf_relocations, bool);
|
key!(relax_elf_relocations, bool);
|
||||||
key!(llvm_args, list);
|
key!(llvm_args, list);
|
||||||
|
key!(use_ctors_section, bool);
|
||||||
|
|
||||||
if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
|
if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
|
||||||
for name in array.iter().filter_map(|abi| abi.as_string()) {
|
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!(llvm_abiname);
|
||||||
target_option_val!(relax_elf_relocations);
|
target_option_val!(relax_elf_relocations);
|
||||||
target_option_val!(llvm_args);
|
target_option_val!(llvm_args);
|
||||||
|
target_option_val!(use_ctors_section);
|
||||||
|
|
||||||
if default.abi_blacklist != self.options.abi_blacklist {
|
if default.abi_blacklist != self.options.abi_blacklist {
|
||||||
d.insert(
|
d.insert(
|
||||||
|
@ -23,6 +23,7 @@ pub fn opts() -> TargetOptions {
|
|||||||
pre_link_args: args,
|
pre_link_args: args,
|
||||||
position_independent_executables: true,
|
position_independent_executables: true,
|
||||||
relro_level: RelroLevel::Full,
|
relro_level: RelroLevel::Full,
|
||||||
|
use_ctors_section: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -445,7 +445,8 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
|
|||||||
bool Singlethread,
|
bool Singlethread,
|
||||||
bool AsmComments,
|
bool AsmComments,
|
||||||
bool EmitStackSizeSection,
|
bool EmitStackSizeSection,
|
||||||
bool RelaxELFRelocations) {
|
bool RelaxELFRelocations,
|
||||||
|
bool UseInitArray) {
|
||||||
|
|
||||||
auto OptLevel = fromRust(RustOptLevel);
|
auto OptLevel = fromRust(RustOptLevel);
|
||||||
auto RM = fromRust(RustReloc);
|
auto RM = fromRust(RustReloc);
|
||||||
@ -471,6 +472,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
|
|||||||
Options.MCOptions.PreserveAsmComments = AsmComments;
|
Options.MCOptions.PreserveAsmComments = AsmComments;
|
||||||
Options.MCOptions.ABIName = ABIStr;
|
Options.MCOptions.ABIName = ABIStr;
|
||||||
Options.RelaxELFRelocations = RelaxELFRelocations;
|
Options.RelaxELFRelocations = RelaxELFRelocations;
|
||||||
|
Options.UseInitArray = UseInitArray;
|
||||||
|
|
||||||
if (TrapUnreachable) {
|
if (TrapUnreachable) {
|
||||||
// Tell LLVM to codegen `unreachable` into an explicit trap instruction.
|
// Tell LLVM to codegen `unreachable` into an explicit trap instruction.
|
||||||
|
Loading…
Reference in New Issue
Block a user