about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-09-24 13:04:19 +0000
committerbors <bors@rust-lang.org>2025-09-24 13:04:19 +0000
commit15283f6fe95e5b604273d13a428bab5fc0788f5a (patch)
tree0dc36ced16f62c9c3445da41a4d9866ff73b3071 /compiler
parente9385f9eea0221ef295a188d49d16f8f5189abf1 (diff)
parent08020def99d2851af0dabde12cc6d203017fa72c (diff)
downloadrust-15283f6fe95e5b604273d13a428bab5fc0788f5a.tar.gz
rust-15283f6fe95e5b604273d13a428bab5fc0788f5a.zip
Auto merge of #146338 - CrooseGit:dev/reucru01/AArch64-enable-GCS, r=Urgau,davidtwco
Extends AArch64 branch protection support to include GCS

Extends existing support for AArch64 branch protection to include support for [Guarded Control Stacks](https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/arm-a-profile-architecture-2022#guarded-control-stack-gcs:~:text=Extraction%20or%20tracking.-,Guarded%20Control%20Stack%20(GCS),-With%20the%202022).
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs9
-rw-r--r--compiler/rustc_interface/src/tests.rs3
-rw-r--r--compiler/rustc_session/src/config.rs1
-rw-r--r--compiler/rustc_session/src/options.rs3
5 files changed, 17 insertions, 4 deletions
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 573c51a9539..dcf6b945497 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -407,13 +407,16 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
         to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));
 
         // For non-naked functions, set branch protection attributes on aarch64.
-        if let Some(BranchProtection { bti, pac_ret }) =
+        if let Some(BranchProtection { bti, pac_ret, gcs }) =
             cx.sess().opts.unstable_opts.branch_protection
         {
             assert!(cx.sess().target.arch == "aarch64");
             if bti {
                 to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement"));
             }
+            if gcs {
+                to_add.push(llvm::CreateAttrString(cx.llcx, "guarded-control-stack"));
+            }
             if let Some(PacRet { leaf, pc, key }) = pac_ret {
                 if pc {
                     to_add.push(llvm::CreateAttrString(cx.llcx, "branch-protection-pauth-lr"));
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 4a8ea11a3a8..057f525c76f 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -370,7 +370,8 @@ pub(crate) unsafe fn create_module<'ll>(
         );
     }
 
-    if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
+    if let Some(BranchProtection { bti, pac_ret, gcs }) = sess.opts.unstable_opts.branch_protection
+    {
         if sess.target.arch == "aarch64" {
             llvm::add_module_flag_u32(
                 llmod,
@@ -403,6 +404,12 @@ pub(crate) unsafe fn create_module<'ll>(
                 "sign-return-address-with-bkey",
                 u32::from(pac_opts.key == PAuthKey::B),
             );
+            llvm::add_module_flag_u32(
+                llmod,
+                llvm::ModuleFlagMergeBehavior::Min,
+                "guarded-control-stack",
+                gcs.into(),
+            );
         } else {
             bug!(
                 "branch-protection used on non-AArch64 target; \
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 7730bddc0f1..800f5efee41 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -772,7 +772,8 @@ fn test_unstable_options_tracking_hash() {
         branch_protection,
         Some(BranchProtection {
             bti: true,
-            pac_ret: Some(PacRet { leaf: true, pc: true, key: PAuthKey::B })
+            pac_ret: Some(PacRet { leaf: true, pc: true, key: PAuthKey::B }),
+            gcs: true,
         })
     );
     tracked!(codegen_backend, Some("abc".to_string()));
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 81ada79dd43..ebb6a93b1dd 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1621,6 +1621,7 @@ pub struct PacRet {
 pub struct BranchProtection {
     pub bti: bool,
     pub pac_ret: Option<PacRet>,
+    pub gcs: bool,
 }
 
 pub(crate) const fn default_lib_output() -> CrateType {
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 3b9d8117786..b2cc169f12c 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -866,7 +866,7 @@ mod desc {
     pub(crate) const parse_polonius: &str = "either no value or `legacy` (the default), or `next`";
     pub(crate) const parse_stack_protector: &str =
         "one of (`none` (default), `basic`, `strong`, or `all`)";
-    pub(crate) const parse_branch_protection: &str = "a `,` separated combination of `bti`, `pac-ret`, followed by a combination of `pc`, `b-key`, or `leaf`";
+    pub(crate) const parse_branch_protection: &str = "a `,` separated combination of `bti`, `gcs`, `pac-ret`, (optionally with `pc`, `b-key`, `leaf` if `pac-ret` is set)";
     pub(crate) const parse_proc_macro_execution_strategy: &str =
         "one of supported execution strategies (`same-thread`, or `cross-thread`)";
     pub(crate) const parse_remap_path_scope: &str =
@@ -1905,6 +1905,7 @@ pub mod parse {
                             Some(pac) => pac.pc = true,
                             _ => return false,
                         },
+                        "gcs" => slot.gcs = true,
                         _ => return false,
                     };
                 }