Skip to content

Commit 3f4bf0e

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#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 rust-lang#92885.
2 parents 691bc38 + e02e958 commit 3f4bf0e

File tree

4 files changed

+73
-13
lines changed

4 files changed

+73
-13
lines changed

compiler/rustc_codegen_llvm/src/context.rs

+24-7
Original file line numberDiff line numberDiff line change
@@ -215,16 +215,19 @@ pub unsafe fn create_module<'ll>(
215215
// to ensure intrinsic calls don't use it.
216216
if !sess.needs_plt() {
217217
let avoid_plt = "RtLibUseGOT\0".as_ptr().cast();
218-
llvm::LLVMRustAddModuleFlag(llmod, avoid_plt, 1);
218+
llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
219219
}
220220

221221
if sess.is_sanitizer_cfi_enabled() {
222222
// FIXME(rcvalle): Add support for non canonical jump tables.
223223
let canonical_jump_tables = "CFI Canonical Jump Tables\0".as_ptr().cast();
224-
// FIXME(rcvalle): Add it with Override behavior flag--LLVMRustAddModuleFlag adds it with
225-
// Warning behavior flag. Add support for specifying the behavior flag to
226-
// LLVMRustAddModuleFlag.
227-
llvm::LLVMRustAddModuleFlag(llmod, canonical_jump_tables, 1);
224+
// FIXME(rcvalle): Add it with Override behavior flag.
225+
llvm::LLVMRustAddModuleFlag(
226+
llmod,
227+
llvm::LLVMModFlagBehavior::Warning,
228+
canonical_jump_tables,
229+
1,
230+
);
228231
}
229232

230233
// Control Flow Guard is currently only supported by the MSVC linker on Windows.
@@ -233,11 +236,21 @@ pub unsafe fn create_module<'ll>(
233236
CFGuard::Disabled => {}
234237
CFGuard::NoChecks => {
235238
// Set `cfguard=1` module flag to emit metadata only.
236-
llvm::LLVMRustAddModuleFlag(llmod, "cfguard\0".as_ptr() as *const _, 1)
239+
llvm::LLVMRustAddModuleFlag(
240+
llmod,
241+
llvm::LLVMModFlagBehavior::Warning,
242+
"cfguard\0".as_ptr() as *const _,
243+
1,
244+
)
237245
}
238246
CFGuard::Checks => {
239247
// Set `cfguard=2` module flag to emit metadata and checks.
240-
llvm::LLVMRustAddModuleFlag(llmod, "cfguard\0".as_ptr() as *const _, 2)
248+
llvm::LLVMRustAddModuleFlag(
249+
llmod,
250+
llvm::LLVMModFlagBehavior::Warning,
251+
"cfguard\0".as_ptr() as *const _,
252+
2,
253+
)
241254
}
242255
}
243256
}
@@ -247,24 +260,28 @@ pub unsafe fn create_module<'ll>(
247260

248261
llvm::LLVMRustAddModuleFlag(
249262
llmod,
263+
llvm::LLVMModFlagBehavior::Error,
250264
"branch-target-enforcement\0".as_ptr().cast(),
251265
bti.into(),
252266
);
253267

254268
llvm::LLVMRustAddModuleFlag(
255269
llmod,
270+
llvm::LLVMModFlagBehavior::Error,
256271
"sign-return-address\0".as_ptr().cast(),
257272
pac.is_some().into(),
258273
);
259274
let pac_opts = pac.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
260275
llvm::LLVMRustAddModuleFlag(
261276
llmod,
277+
llvm::LLVMModFlagBehavior::Error,
262278
"sign-return-address-all\0".as_ptr().cast(),
263279
pac_opts.leaf.into(),
264280
);
265281
let is_bkey = if pac_opts.key == PAuthKey::A { false } else { true };
266282
llvm::LLVMRustAddModuleFlag(
267283
llmod,
284+
llvm::LLVMModFlagBehavior::Error,
268285
"sign-return-address-with-bkey\0".as_ptr().cast(),
269286
is_bkey.into(),
270287
);

compiler/rustc_codegen_llvm/src/debuginfo/mod.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -108,18 +108,29 @@ impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
108108
// This can be overridden using --llvm-opts -dwarf-version,N.
109109
// Android has the same issue (#22398)
110110
if let Some(version) = sess.target.dwarf_version {
111-
llvm::LLVMRustAddModuleFlag(self.llmod, "Dwarf Version\0".as_ptr().cast(), version)
111+
llvm::LLVMRustAddModuleFlag(
112+
self.llmod,
113+
llvm::LLVMModFlagBehavior::Warning,
114+
"Dwarf Version\0".as_ptr().cast(),
115+
version,
116+
)
112117
}
113118

114119
// Indicate that we want CodeView debug information on MSVC
115120
if sess.target.is_like_msvc {
116-
llvm::LLVMRustAddModuleFlag(self.llmod, "CodeView\0".as_ptr().cast(), 1)
121+
llvm::LLVMRustAddModuleFlag(
122+
self.llmod,
123+
llvm::LLVMModFlagBehavior::Warning,
124+
"CodeView\0".as_ptr().cast(),
125+
1,
126+
)
117127
}
118128

119129
// Prevent bitcode readers from deleting the debug info.
120130
let ptr = "Debug Info Version\0".as_ptr();
121131
llvm::LLVMRustAddModuleFlag(
122132
self.llmod,
133+
llvm::LLVMModFlagBehavior::Warning,
123134
ptr.cast(),
124135
llvm::LLVMRustDebugMetadataVersion(),
125136
);

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,26 @@ pub enum LLVMMachineType {
6161
ARM = 0x01c0,
6262
}
6363

64+
/// LLVM's Module::ModFlagBehavior, defined in llvm/include/llvm/IR/Module.h.
65+
///
66+
/// When merging modules (e.g. during LTO), their metadata flags are combined. Conflicts are
67+
/// resolved according to the merge behaviors specified here. Flags differing only in merge
68+
/// behavior are still considered to be in conflict.
69+
///
70+
/// In order for Rust-C LTO to work, we must specify behaviors compatible with Clang. Notably,
71+
/// 'Error' and 'Warning' cannot be mixed for a given flag.
72+
#[derive(Copy, Clone, PartialEq)]
73+
#[repr(C)]
74+
pub enum LLVMModFlagBehavior {
75+
Error = 1,
76+
Warning = 2,
77+
Require = 3,
78+
Override = 4,
79+
Append = 5,
80+
AppendUnique = 6,
81+
Max = 7,
82+
}
83+
6484
// Consts for the LLVM CallConv type, pre-cast to usize.
6585

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

18961916
pub fn LLVMRustIsRustLLVM() -> bool;
18971917

1898-
pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32);
1918+
/// Add LLVM module flags.
1919+
///
1920+
/// In order for Rust-C LTO to work, module flags must be compatible with Clang. What
1921+
/// "compatible" means depends on the merge behaviors involved.
1922+
pub fn LLVMRustAddModuleFlag(
1923+
M: &Module,
1924+
merge_behavior: LLVMModFlagBehavior,
1925+
name: *const c_char,
1926+
value: u32,
1927+
);
18991928

19001929
pub fn LLVMRustMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value;
19011930

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -722,9 +722,12 @@ extern "C" bool LLVMRustIsRustLLVM() {
722722
#endif
723723
}
724724

725-
extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
726-
uint32_t Value) {
727-
unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
725+
extern "C" void LLVMRustAddModuleFlag(
726+
LLVMModuleRef M,
727+
Module::ModFlagBehavior MergeBehavior,
728+
const char *Name,
729+
uint32_t Value) {
730+
unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
728731
}
729732

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

0 commit comments

Comments
 (0)