mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Rollup merge of #93269 - jacobbramley:dev/pauth-option-1, r=petrochenkov
Use error-on-mismatch policy for PAuth module flags. This agrees with Clang, and avoids an error when using LTO with mixed C/Rust. LLVM considers different behaviour flags to be a mismatch, even when the flag value itself is the same. This also makes the flag setting explicit for all uses of LLVMRustAddModuleFlag. ---- I believe that this fixes #92885, but have only reproduced it locally on Linux hosts so cannot confirm that it fixes the issue as reported. I have not included a test for this because it is covered by an existing test (`src/test/run-make-fulldeps/cross-lang-lto-clang`). It is not without its problems, though: * The test requires Clang and `--run-clang-based-tests-with=...` to run, and this is not the case on the CI. * Any test I add would have a similar requirement. * With this patch applied, the test gets further, but it still fails (for other reasons). I don't think that affects #92885.
This commit is contained in:
commit
13b87d8cc7
@ -215,16 +215,19 @@ pub unsafe fn create_module<'ll>(
|
|||||||
// to ensure intrinsic calls don't use it.
|
// to ensure intrinsic calls don't use it.
|
||||||
if !sess.needs_plt() {
|
if !sess.needs_plt() {
|
||||||
let avoid_plt = "RtLibUseGOT\0".as_ptr().cast();
|
let avoid_plt = "RtLibUseGOT\0".as_ptr().cast();
|
||||||
llvm::LLVMRustAddModuleFlag(llmod, avoid_plt, 1);
|
llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if sess.is_sanitizer_cfi_enabled() {
|
if sess.is_sanitizer_cfi_enabled() {
|
||||||
// FIXME(rcvalle): Add support for non canonical jump tables.
|
// FIXME(rcvalle): Add support for non canonical jump tables.
|
||||||
let canonical_jump_tables = "CFI Canonical Jump Tables\0".as_ptr().cast();
|
let canonical_jump_tables = "CFI Canonical Jump Tables\0".as_ptr().cast();
|
||||||
// FIXME(rcvalle): Add it with Override behavior flag--LLVMRustAddModuleFlag adds it with
|
// FIXME(rcvalle): Add it with Override behavior flag.
|
||||||
// Warning behavior flag. Add support for specifying the behavior flag to
|
llvm::LLVMRustAddModuleFlag(
|
||||||
// LLVMRustAddModuleFlag.
|
llmod,
|
||||||
llvm::LLVMRustAddModuleFlag(llmod, canonical_jump_tables, 1);
|
llvm::LLVMModFlagBehavior::Warning,
|
||||||
|
canonical_jump_tables,
|
||||||
|
1,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Control Flow Guard is currently only supported by the MSVC linker on Windows.
|
// Control Flow Guard is currently only supported by the MSVC linker on Windows.
|
||||||
@ -233,11 +236,21 @@ pub unsafe fn create_module<'ll>(
|
|||||||
CFGuard::Disabled => {}
|
CFGuard::Disabled => {}
|
||||||
CFGuard::NoChecks => {
|
CFGuard::NoChecks => {
|
||||||
// Set `cfguard=1` module flag to emit metadata only.
|
// Set `cfguard=1` module flag to emit metadata only.
|
||||||
llvm::LLVMRustAddModuleFlag(llmod, "cfguard\0".as_ptr() as *const _, 1)
|
llvm::LLVMRustAddModuleFlag(
|
||||||
|
llmod,
|
||||||
|
llvm::LLVMModFlagBehavior::Warning,
|
||||||
|
"cfguard\0".as_ptr() as *const _,
|
||||||
|
1,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
CFGuard::Checks => {
|
CFGuard::Checks => {
|
||||||
// Set `cfguard=2` module flag to emit metadata and checks.
|
// Set `cfguard=2` module flag to emit metadata and checks.
|
||||||
llvm::LLVMRustAddModuleFlag(llmod, "cfguard\0".as_ptr() as *const _, 2)
|
llvm::LLVMRustAddModuleFlag(
|
||||||
|
llmod,
|
||||||
|
llvm::LLVMModFlagBehavior::Warning,
|
||||||
|
"cfguard\0".as_ptr() as *const _,
|
||||||
|
2,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -247,24 +260,28 @@ pub unsafe fn create_module<'ll>(
|
|||||||
|
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlag(
|
||||||
llmod,
|
llmod,
|
||||||
|
llvm::LLVMModFlagBehavior::Error,
|
||||||
"branch-target-enforcement\0".as_ptr().cast(),
|
"branch-target-enforcement\0".as_ptr().cast(),
|
||||||
bti.into(),
|
bti.into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlag(
|
||||||
llmod,
|
llmod,
|
||||||
|
llvm::LLVMModFlagBehavior::Error,
|
||||||
"sign-return-address\0".as_ptr().cast(),
|
"sign-return-address\0".as_ptr().cast(),
|
||||||
pac.is_some().into(),
|
pac.is_some().into(),
|
||||||
);
|
);
|
||||||
let pac_opts = pac.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
|
let pac_opts = pac.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlag(
|
||||||
llmod,
|
llmod,
|
||||||
|
llvm::LLVMModFlagBehavior::Error,
|
||||||
"sign-return-address-all\0".as_ptr().cast(),
|
"sign-return-address-all\0".as_ptr().cast(),
|
||||||
pac_opts.leaf.into(),
|
pac_opts.leaf.into(),
|
||||||
);
|
);
|
||||||
let is_bkey = if pac_opts.key == PAuthKey::A { false } else { true };
|
let is_bkey = if pac_opts.key == PAuthKey::A { false } else { true };
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlag(
|
||||||
llmod,
|
llmod,
|
||||||
|
llvm::LLVMModFlagBehavior::Error,
|
||||||
"sign-return-address-with-bkey\0".as_ptr().cast(),
|
"sign-return-address-with-bkey\0".as_ptr().cast(),
|
||||||
is_bkey.into(),
|
is_bkey.into(),
|
||||||
);
|
);
|
||||||
|
@ -108,18 +108,29 @@ impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
|
|||||||
// This can be overridden using --llvm-opts -dwarf-version,N.
|
// This can be overridden using --llvm-opts -dwarf-version,N.
|
||||||
// Android has the same issue (#22398)
|
// Android has the same issue (#22398)
|
||||||
if let Some(version) = sess.target.dwarf_version {
|
if let Some(version) = sess.target.dwarf_version {
|
||||||
llvm::LLVMRustAddModuleFlag(self.llmod, "Dwarf Version\0".as_ptr().cast(), version)
|
llvm::LLVMRustAddModuleFlag(
|
||||||
|
self.llmod,
|
||||||
|
llvm::LLVMModFlagBehavior::Warning,
|
||||||
|
"Dwarf Version\0".as_ptr().cast(),
|
||||||
|
version,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indicate that we want CodeView debug information on MSVC
|
// Indicate that we want CodeView debug information on MSVC
|
||||||
if sess.target.is_like_msvc {
|
if sess.target.is_like_msvc {
|
||||||
llvm::LLVMRustAddModuleFlag(self.llmod, "CodeView\0".as_ptr().cast(), 1)
|
llvm::LLVMRustAddModuleFlag(
|
||||||
|
self.llmod,
|
||||||
|
llvm::LLVMModFlagBehavior::Warning,
|
||||||
|
"CodeView\0".as_ptr().cast(),
|
||||||
|
1,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent bitcode readers from deleting the debug info.
|
// Prevent bitcode readers from deleting the debug info.
|
||||||
let ptr = "Debug Info Version\0".as_ptr();
|
let ptr = "Debug Info Version\0".as_ptr();
|
||||||
llvm::LLVMRustAddModuleFlag(
|
llvm::LLVMRustAddModuleFlag(
|
||||||
self.llmod,
|
self.llmod,
|
||||||
|
llvm::LLVMModFlagBehavior::Warning,
|
||||||
ptr.cast(),
|
ptr.cast(),
|
||||||
llvm::LLVMRustDebugMetadataVersion(),
|
llvm::LLVMRustDebugMetadataVersion(),
|
||||||
);
|
);
|
||||||
|
@ -61,6 +61,26 @@ pub enum LLVMMachineType {
|
|||||||
ARM = 0x01c0,
|
ARM = 0x01c0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// LLVM's Module::ModFlagBehavior, defined in llvm/include/llvm/IR/Module.h.
|
||||||
|
///
|
||||||
|
/// When merging modules (e.g. during LTO), their metadata flags are combined. Conflicts are
|
||||||
|
/// resolved according to the merge behaviors specified here. Flags differing only in merge
|
||||||
|
/// behavior are still considered to be in conflict.
|
||||||
|
///
|
||||||
|
/// In order for Rust-C LTO to work, we must specify behaviors compatible with Clang. Notably,
|
||||||
|
/// 'Error' and 'Warning' cannot be mixed for a given flag.
|
||||||
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub enum LLVMModFlagBehavior {
|
||||||
|
Error = 1,
|
||||||
|
Warning = 2,
|
||||||
|
Require = 3,
|
||||||
|
Override = 4,
|
||||||
|
Append = 5,
|
||||||
|
AppendUnique = 6,
|
||||||
|
Max = 7,
|
||||||
|
}
|
||||||
|
|
||||||
// Consts for the LLVM CallConv type, pre-cast to usize.
|
// Consts for the LLVM CallConv type, pre-cast to usize.
|
||||||
|
|
||||||
/// LLVM CallingConv::ID. Should we wrap this?
|
/// LLVM CallingConv::ID. Should we wrap this?
|
||||||
@ -1895,7 +1915,16 @@ extern "C" {
|
|||||||
|
|
||||||
pub fn LLVMRustIsRustLLVM() -> bool;
|
pub fn LLVMRustIsRustLLVM() -> bool;
|
||||||
|
|
||||||
pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32);
|
/// Add LLVM module flags.
|
||||||
|
///
|
||||||
|
/// In order for Rust-C LTO to work, module flags must be compatible with Clang. What
|
||||||
|
/// "compatible" means depends on the merge behaviors involved.
|
||||||
|
pub fn LLVMRustAddModuleFlag(
|
||||||
|
M: &Module,
|
||||||
|
merge_behavior: LLVMModFlagBehavior,
|
||||||
|
name: *const c_char,
|
||||||
|
value: u32,
|
||||||
|
);
|
||||||
|
|
||||||
pub fn LLVMRustMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value;
|
pub fn LLVMRustMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value;
|
||||||
|
|
||||||
|
@ -722,9 +722,12 @@ extern "C" bool LLVMRustIsRustLLVM() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
|
extern "C" void LLVMRustAddModuleFlag(
|
||||||
uint32_t Value) {
|
LLVMModuleRef M,
|
||||||
unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
|
Module::ModFlagBehavior MergeBehavior,
|
||||||
|
const char *Name,
|
||||||
|
uint32_t Value) {
|
||||||
|
unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
|
extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
|
||||||
|
Loading…
Reference in New Issue
Block a user