Skip to content

Mark CXX module initializer with PACBTI attributes #133716

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

Merged
merged 5 commits into from
Apr 25, 2025

Conversation

vhscampos
Copy link
Member

The CXX module initializer function, which is called at program startup, needs to be tagged with Pointer Authentication and Branch Target Identification marks whenever relevant.

Before this patch, in CPUs set up for PACBTI execution, the function wasn't protected with return address signing and no BTI instruction was inserted at the start of it, thus leading to an execution fault.

This patch fixes the issue by marking the function with the function attributes related to PAC and BTI if relevant.

The CXX module initializer function, which is called at program startup,
needs to be tagged with Pointer Authentication and Branch Target
Identification marks whenever relevant.

Before this patch, in CPUs set up for PACBTI execution, the function
wasn't protected with return address signing and no BTI instruction was
inserted at the start of it, thus leading to an execution fault.

This patch fixes the issue by marking the function with the function
attributes related to PAC and BTI if relevant.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen IR generation bugs: mangling, exceptions, etc. labels Mar 31, 2025
@vhscampos vhscampos requested a review from llvm-beanz March 31, 2025 13:25
@llvmbot
Copy link
Member

llvmbot commented Mar 31, 2025

@llvm/pr-subscribers-backend-aarch64
@llvm/pr-subscribers-backend-arm

@llvm/pr-subscribers-clang

Author: Victor Campos (vhscampos)

Changes

The CXX module initializer function, which is called at program startup, needs to be tagged with Pointer Authentication and Branch Target Identification marks whenever relevant.

Before this patch, in CPUs set up for PACBTI execution, the function wasn't protected with return address signing and no BTI instruction was inserted at the start of it, thus leading to an execution fault.

This patch fixes the issue by marking the function with the function attributes related to PAC and BTI if relevant.


Full diff: https://github.com/llvm/llvm-project/pull/133716.diff

2 Files Affected:

  • (modified) clang/lib/CodeGen/CGDeclCXX.cpp (+6)
  • (added) clang/test/CodeGenCXX/cxx20-module-initializer-pacbti.cpp (+32)
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index a01fa157c2b26..0366e3977b812 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -818,6 +818,12 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
     Fn->addFnAttr("device-init");
   }
 
+  if (getTarget().isBranchProtectionSupportedArch(
+          getTarget().getTargetOpts().CPU)) {
+    TargetInfo::BranchProtectionInfo BPI(getLangOpts());
+    getTargetCodeGenInfo().setBranchProtectionFnAttributes(BPI, (*Fn));
+  }
+
   // We are done with the inits.
   AllImports.clear();
   PrioritizedCXXGlobalInits.clear();
diff --git a/clang/test/CodeGenCXX/cxx20-module-initializer-pacbti.cpp b/clang/test/CodeGenCXX/cxx20-module-initializer-pacbti.cpp
new file mode 100644
index 0000000000000..7ebaa5e8f349e
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx20-module-initializer-pacbti.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -emit-module-interface -target-feature +pacbti -mbranch-target-enforce -std=c++20 %s -o %t.pcm
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -std=c++20 %t.pcm -emit-llvm -o - | \
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-BTI %s
+
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -emit-module-interface -target-feature +pacbti -msign-return-address=non-leaf -std=c++20 %s -o %t.pcm
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -std=c++20 %t.pcm -emit-llvm -o - | \
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-PAC %s
+
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -emit-module-interface -target-feature +pacbti -msign-return-address=all -std=c++20 %s -o %t.pcm
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -std=c++20 %t.pcm -emit-llvm -o - | \
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-PAC-ALL %s
+
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -emit-module-interface -target-feature +pacbti -msign-return-address=non-leaf -mbranch-target-enforce -std=c++20 %s -o %t.pcm
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -std=c++20 %t.pcm -emit-llvm -o - | \
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-PAC-BTI %s
+
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -emit-module-interface -target-feature +pacbti -msign-return-address=all -mbranch-target-enforce -std=c++20 %s -o %t.pcm
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -std=c++20 %t.pcm -emit-llvm -o - | \
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-PAC-BTI-ALL %s
+
+// CHECK: define void @_ZGIW3foo() #0
+// CHECK-BTI: attributes #0 = { nounwind "branch-target-enforcement" }
+// CHECK-PAC: attributes #0 = { nounwind "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" }
+// CHECK-PAC-ALL: attributes #0 = { nounwind "sign-return-address"="all" "sign-return-address-key"="a_key" }
+// CHECK-PAC-BTI: attributes #0 = { nounwind "branch-target-enforcement" "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" }
+// CHECK-PAC-BTI-ALL: attributes #0 = { nounwind "branch-target-enforcement" "sign-return-address"="all" "sign-return-address-key"="a_key" }
+
+module;
+
+export module foo;
+
+export void func();

@llvmbot
Copy link
Member

llvmbot commented Mar 31, 2025

@llvm/pr-subscribers-clang-codegen

Author: Victor Campos (vhscampos)

Changes

The CXX module initializer function, which is called at program startup, needs to be tagged with Pointer Authentication and Branch Target Identification marks whenever relevant.

Before this patch, in CPUs set up for PACBTI execution, the function wasn't protected with return address signing and no BTI instruction was inserted at the start of it, thus leading to an execution fault.

This patch fixes the issue by marking the function with the function attributes related to PAC and BTI if relevant.


Full diff: https://github.com/llvm/llvm-project/pull/133716.diff

2 Files Affected:

  • (modified) clang/lib/CodeGen/CGDeclCXX.cpp (+6)
  • (added) clang/test/CodeGenCXX/cxx20-module-initializer-pacbti.cpp (+32)
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index a01fa157c2b26..0366e3977b812 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -818,6 +818,12 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
     Fn->addFnAttr("device-init");
   }
 
+  if (getTarget().isBranchProtectionSupportedArch(
+          getTarget().getTargetOpts().CPU)) {
+    TargetInfo::BranchProtectionInfo BPI(getLangOpts());
+    getTargetCodeGenInfo().setBranchProtectionFnAttributes(BPI, (*Fn));
+  }
+
   // We are done with the inits.
   AllImports.clear();
   PrioritizedCXXGlobalInits.clear();
diff --git a/clang/test/CodeGenCXX/cxx20-module-initializer-pacbti.cpp b/clang/test/CodeGenCXX/cxx20-module-initializer-pacbti.cpp
new file mode 100644
index 0000000000000..7ebaa5e8f349e
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx20-module-initializer-pacbti.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -emit-module-interface -target-feature +pacbti -mbranch-target-enforce -std=c++20 %s -o %t.pcm
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -std=c++20 %t.pcm -emit-llvm -o - | \
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-BTI %s
+
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -emit-module-interface -target-feature +pacbti -msign-return-address=non-leaf -std=c++20 %s -o %t.pcm
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -std=c++20 %t.pcm -emit-llvm -o - | \
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-PAC %s
+
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -emit-module-interface -target-feature +pacbti -msign-return-address=all -std=c++20 %s -o %t.pcm
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -std=c++20 %t.pcm -emit-llvm -o - | \
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-PAC-ALL %s
+
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -emit-module-interface -target-feature +pacbti -msign-return-address=non-leaf -mbranch-target-enforce -std=c++20 %s -o %t.pcm
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -std=c++20 %t.pcm -emit-llvm -o - | \
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-PAC-BTI %s
+
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -emit-module-interface -target-feature +pacbti -msign-return-address=all -mbranch-target-enforce -std=c++20 %s -o %t.pcm
+// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -std=c++20 %t.pcm -emit-llvm -o - | \
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-PAC-BTI-ALL %s
+
+// CHECK: define void @_ZGIW3foo() #0
+// CHECK-BTI: attributes #0 = { nounwind "branch-target-enforcement" }
+// CHECK-PAC: attributes #0 = { nounwind "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" }
+// CHECK-PAC-ALL: attributes #0 = { nounwind "sign-return-address"="all" "sign-return-address-key"="a_key" }
+// CHECK-PAC-BTI: attributes #0 = { nounwind "branch-target-enforcement" "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" }
+// CHECK-PAC-BTI-ALL: attributes #0 = { nounwind "branch-target-enforcement" "sign-return-address"="all" "sign-return-address-key"="a_key" }
+
+module;
+
+export module foo;
+
+export void func();

@vhscampos vhscampos requested review from iains and ChuanqiXu9 March 31, 2025 13:27
Copy link
Member

@ChuanqiXu9 ChuanqiXu9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I'll leave the formal approval to @efriedma-quic

- Modify setTargetAttributes function to work even without a function
  declaration.
 - Simplify test on the assumption that other tests already test the
   functionaly of the called functions.
Copy link
Collaborator

@efriedma-quic efriedma-quic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@vhscampos vhscampos merged commit 6738cfe into llvm:main Apr 25, 2025
11 checks passed
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
The CXX module initializer function, which is called at program startup,
needs to be tagged with Pointer Authentication and Branch Target
Identification marks whenever relevant.

Before this patch, in CPUs set up for PACBTI execution, the function
wasn't protected with return address signing and no BTI instruction was
inserted at the start of it, thus leading to an execution fault.

This patch fixes the issue by marking the function with the function
attributes related to PAC and BTI if relevant.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
The CXX module initializer function, which is called at program startup,
needs to be tagged with Pointer Authentication and Branch Target
Identification marks whenever relevant.

Before this patch, in CPUs set up for PACBTI execution, the function
wasn't protected with return address signing and no BTI instruction was
inserted at the start of it, thus leading to an execution fault.

This patch fixes the issue by marking the function with the function
attributes related to PAC and BTI if relevant.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
The CXX module initializer function, which is called at program startup,
needs to be tagged with Pointer Authentication and Branch Target
Identification marks whenever relevant.

Before this patch, in CPUs set up for PACBTI execution, the function
wasn't protected with return address signing and no BTI instruction was
inserted at the start of it, thus leading to an execution fault.

This patch fixes the issue by marking the function with the function
attributes related to PAC and BTI if relevant.
Ankur-0429 pushed a commit to Ankur-0429/llvm-project that referenced this pull request May 9, 2025
The CXX module initializer function, which is called at program startup,
needs to be tagged with Pointer Authentication and Branch Target
Identification marks whenever relevant.

Before this patch, in CPUs set up for PACBTI execution, the function
wasn't protected with return address signing and no BTI instruction was
inserted at the start of it, thus leading to an execution fault.

This patch fixes the issue by marking the function with the function
attributes related to PAC and BTI if relevant.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 backend:ARM clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants