Skip to content

Commit ea7625f

Browse files
committed
Set branch protection function attributes
Since LLVM 19, it is necessary to set not only module flags, but also function attributes for branch protection on aarch64. See llvm/llvm-project@e15d67c for the relevant LLVM change.
1 parent d24930c commit ea7625f

File tree

3 files changed

+83
-3
lines changed

3 files changed

+83
-3
lines changed

compiler/rustc_codegen_llvm/src/attributes.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_codegen_ssa::traits::*;
44
use rustc_hir::def_id::DefId;
55
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry};
66
use rustc_middle::ty::{self, TyCtxt};
7-
use rustc_session::config::{FunctionReturn, OptLevel};
7+
use rustc_session::config::{BranchProtection, FunctionReturn, OptLevel, PAuthKey, PacRet};
88
use rustc_span::symbol::sym;
99
use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector};
1010
use smallvec::SmallVec;
@@ -407,8 +407,33 @@ pub fn from_fn_attrs<'ll, 'tcx>(
407407
// And it is a module-level attribute, so the alternative is pulling naked functions into new LLVM modules.
408408
// Otherwise LLVM's "naked" functions come with endbr prefixes per https://github.com/rust-lang/rust/issues/98768
409409
to_add.push(AttributeKind::NoCfCheck.create_attr(cx.llcx));
410-
// Need this for AArch64.
411-
to_add.push(llvm::CreateAttrStringValue(cx.llcx, "branch-target-enforcement", "false"));
410+
if llvm_util::get_version() < (19, 0, 0) {
411+
// Prior to LLVM 19, branch-target-enforcement was disabled by setting the attribute to
412+
// the string "false". Now it is disabled by absence of the attribute.
413+
to_add.push(llvm::CreateAttrStringValue(cx.llcx, "branch-target-enforcement", "false"));
414+
}
415+
} else if llvm_util::get_version() >= (19, 0, 0) {
416+
// For non-naked functions, set branch protection attributes on aarch64.
417+
if let Some(BranchProtection { bti, pac_ret }) =
418+
cx.sess().opts.unstable_opts.branch_protection
419+
{
420+
assert!(cx.sess().target.arch == "aarch64");
421+
if bti {
422+
to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement"));
423+
}
424+
if let Some(PacRet { leaf, key }) = pac_ret {
425+
to_add.push(llvm::CreateAttrStringValue(
426+
cx.llcx,
427+
"sign-return-address",
428+
if leaf { "all" } else { "non-leaf" },
429+
));
430+
to_add.push(llvm::CreateAttrStringValue(
431+
cx.llcx,
432+
"sign-return-address-key",
433+
if key == PAuthKey::A { "a_key" } else { "b_key" },
434+
));
435+
}
436+
}
412437
}
413438
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR)
414439
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR_ZEROED)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Test that the correct module flags are emitted with different branch protection flags.
2+
3+
//@ revisions: BTI PACRET LEAF BKEY NONE
4+
//@ needs-llvm-components: aarch64
5+
//@ [BTI] compile-flags: -Z branch-protection=bti
6+
//@ [PACRET] compile-flags: -Z branch-protection=pac-ret
7+
//@ [LEAF] compile-flags: -Z branch-protection=pac-ret,leaf
8+
//@ [BKEY] compile-flags: -Z branch-protection=pac-ret,b-key
9+
//@ compile-flags: --target aarch64-unknown-linux-gnu
10+
//@ ignore-llvm-version: 19 - 99
11+
12+
#![crate_type = "lib"]
13+
#![feature(no_core, lang_items)]
14+
#![no_core]
15+
16+
#[lang = "sized"]
17+
trait Sized {}
18+
19+
// A basic test function.
20+
pub fn test() {}
21+
22+
// BTI: !"branch-target-enforcement", i32 1
23+
// BTI: !"sign-return-address", i32 0
24+
// BTI: !"sign-return-address-all", i32 0
25+
// BTI: !"sign-return-address-with-bkey", i32 0
26+
27+
// PACRET: !"branch-target-enforcement", i32 0
28+
// PACRET: !"sign-return-address", i32 1
29+
// PACRET: !"sign-return-address-all", i32 0
30+
// PACRET: !"sign-return-address-with-bkey", i32 0
31+
32+
// LEAF: !"branch-target-enforcement", i32 0
33+
// LEAF: !"sign-return-address", i32 1
34+
// LEAF: !"sign-return-address-all", i32 1
35+
// LEAF: !"sign-return-address-with-bkey", i32 0
36+
37+
// BKEY: !"branch-target-enforcement", i32 0
38+
// BKEY: !"sign-return-address", i32 1
39+
// BKEY: !"sign-return-address-all", i32 0
40+
// BKEY: !"sign-return-address-with-bkey", i32 1
41+
42+
// NONE-NOT: branch-target-enforcement
43+
// NONE-NOT: sign-return-address
44+
// NONE-NOT: sign-return-address-all
45+
// NONE-NOT: sign-return-address-with-bkey

tests/codegen/branch-protection.rs

+10
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//@ [LEAF] compile-flags: -Z branch-protection=pac-ret,leaf
88
//@ [BKEY] compile-flags: -Z branch-protection=pac-ret,b-key
99
//@ compile-flags: --target aarch64-unknown-linux-gnu
10+
//@ min-llvm-version: 19
1011

1112
#![crate_type = "lib"]
1213
#![feature(no_core, lang_items)]
@@ -16,23 +17,32 @@
1617
trait Sized {}
1718

1819
// A basic test function.
20+
// CHECK: @test(){{.*}} [[ATTR:#[0-9]+]] {
21+
#[no_mangle]
1922
pub fn test() {}
2023

24+
// BTI: attributes [[ATTR]] = {{.*}} "branch-target-enforcement"
2125
// BTI: !"branch-target-enforcement", i32 1
2226
// BTI: !"sign-return-address", i32 0
2327
// BTI: !"sign-return-address-all", i32 0
2428
// BTI: !"sign-return-address-with-bkey", i32 0
2529

30+
// PACRET: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf"
31+
// PACRET-SAME: "sign-return-address-key"="a_key"
2632
// PACRET: !"branch-target-enforcement", i32 0
2733
// PACRET: !"sign-return-address", i32 1
2834
// PACRET: !"sign-return-address-all", i32 0
2935
// PACRET: !"sign-return-address-with-bkey", i32 0
3036

37+
// LEAF: attributes [[ATTR]] = {{.*}} "sign-return-address"="all"
38+
// LEAF-SAME: "sign-return-address-key"="a_key"
3139
// LEAF: !"branch-target-enforcement", i32 0
3240
// LEAF: !"sign-return-address", i32 1
3341
// LEAF: !"sign-return-address-all", i32 1
3442
// LEAF: !"sign-return-address-with-bkey", i32 0
3543

44+
// BKEY: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf"
45+
// BKEY-SAME: "sign-return-address-key"="b_key"
3646
// BKEY: !"branch-target-enforcement", i32 0
3747
// BKEY: !"sign-return-address", i32 1
3848
// BKEY: !"sign-return-address-all", i32 0

0 commit comments

Comments
 (0)