Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use error-on-mismatch policy for PAuth module flags. #93269

Merged
merged 1 commit into from
Jan 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,16 +215,19 @@ pub unsafe fn create_module<'ll>(
// to ensure intrinsic calls don't use it.
if !sess.needs_plt() {
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() {
// FIXME(rcvalle): Add support for non canonical jump tables.
let canonical_jump_tables = "CFI Canonical Jump Tables\0".as_ptr().cast();
// FIXME(rcvalle): Add it with Override behavior flag--LLVMRustAddModuleFlag adds it with
// Warning behavior flag. Add support for specifying the behavior flag to
// LLVMRustAddModuleFlag.
llvm::LLVMRustAddModuleFlag(llmod, canonical_jump_tables, 1);
// FIXME(rcvalle): Add it with Override behavior flag.
llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Warning,
canonical_jump_tables,
1,
);
}

// Control Flow Guard is currently only supported by the MSVC linker on Windows.
Expand All @@ -233,11 +236,21 @@ pub unsafe fn create_module<'ll>(
CFGuard::Disabled => {}
CFGuard::NoChecks => {
// 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 => {
// 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,
)
}
}
}
Expand All @@ -247,24 +260,28 @@ pub unsafe fn create_module<'ll>(

llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Error,
"branch-target-enforcement\0".as_ptr().cast(),
bti.into(),
);

llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Error,
"sign-return-address\0".as_ptr().cast(),
pac.is_some().into(),
);
let pac_opts = pac.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Error,
"sign-return-address-all\0".as_ptr().cast(),
pac_opts.leaf.into(),
);
let is_bkey = if pac_opts.key == PAuthKey::A { false } else { true };
llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Error,
"sign-return-address-with-bkey\0".as_ptr().cast(),
is_bkey.into(),
);
Expand Down
15 changes: 13 additions & 2 deletions compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,18 +108,29 @@ impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
// This can be overridden using --llvm-opts -dwarf-version,N.
// Android has the same issue (#22398)
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
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.
let ptr = "Debug Info Version\0".as_ptr();
llvm::LLVMRustAddModuleFlag(
self.llmod,
llvm::LLVMModFlagBehavior::Warning,
ptr.cast(),
llvm::LLVMRustDebugMetadataVersion(),
);
Expand Down
31 changes: 30 additions & 1 deletion compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,26 @@ pub enum LLVMMachineType {
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.

/// LLVM CallingConv::ID. Should we wrap this?
Expand Down Expand Up @@ -1895,7 +1915,16 @@ extern "C" {

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;

Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -722,9 +722,12 @@ extern "C" bool LLVMRustIsRustLLVM() {
#endif
}

extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
uint32_t Value) {
unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
extern "C" void LLVMRustAddModuleFlag(
LLVMModuleRef M,
Module::ModFlagBehavior MergeBehavior,
const char *Name,
uint32_t Value) {
unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
}

extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
Expand Down