Skip to content

Commit 6738cfe

Browse files
authored
Mark CXX module initializer with PACBTI attributes (#133716)
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.
1 parent a4d1a9d commit 6738cfe

File tree

4 files changed

+34
-12
lines changed

4 files changed

+34
-12
lines changed

clang/lib/CodeGen/CGDeclCXX.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,11 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction(
448448

449449
if (Linkage == llvm::GlobalVariable::InternalLinkage)
450450
SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
451+
else {
452+
SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn, false);
453+
SetLLVMFunctionAttributesForDefinition(nullptr, Fn);
454+
getTargetCodeGenInfo().setTargetAttributes(nullptr, Fn, *this);
455+
}
451456

452457
Fn->setCallingConv(getRuntimeCC());
453458

clang/lib/CodeGen/Targets/AArch64.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,15 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
136136

137137
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
138138
CodeGen::CodeGenModule &CGM) const override {
139-
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
140-
if (!FD)
139+
auto *Fn = dyn_cast<llvm::Function>(GV);
140+
if (!Fn)
141141
return;
142142

143+
const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
143144
TargetInfo::BranchProtectionInfo BPI(CGM.getLangOpts());
144145

145-
if (const auto *TA = FD->getAttr<TargetAttr>()) {
146+
if (FD && FD->hasAttr<TargetAttr>()) {
147+
const auto *TA = FD->getAttr<TargetAttr>();
146148
ParsedTargetAttr Attr =
147149
CGM.getTarget().parseTargetAttr(TA->getFeaturesStr());
148150
if (!Attr.BranchProtection.empty()) {
@@ -152,7 +154,6 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
152154
assert(Error.empty());
153155
}
154156
}
155-
auto *Fn = cast<llvm::Function>(GV);
156157
setBranchProtectionFnAttributes(BPI, *Fn);
157158
}
158159

clang/lib/CodeGen/Targets/ARM.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,13 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
134134

135135
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
136136
CodeGen::CodeGenModule &CGM) const override {
137-
if (GV->isDeclaration())
137+
auto *Fn = dyn_cast<llvm::Function>(GV);
138+
if (!Fn)
138139
return;
139-
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
140-
if (!FD)
141-
return;
142-
auto *Fn = cast<llvm::Function>(GV);
140+
const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
143141

144-
if (const auto *TA = FD->getAttr<TargetAttr>()) {
142+
if (FD && FD->hasAttr<TargetAttr>()) {
143+
const auto *TA = FD->getAttr<TargetAttr>();
145144
ParsedTargetAttr Attr =
146145
CGM.getTarget().parseTargetAttr(TA->getFeaturesStr());
147146
if (!Attr.BranchProtection.empty()) {
@@ -174,10 +173,10 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
174173
setBranchProtectionFnAttributes(BPI, (*Fn));
175174
}
176175

177-
const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>();
178-
if (!Attr)
176+
if (!FD || !FD->hasAttr<ARMInterruptAttr>())
179177
return;
180178

179+
const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>();
181180
const char *Kind;
182181
switch (Attr->getInterrupt()) {
183182
case ARMInterruptAttr::Generic: Kind = ""; break;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// 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
2+
// RUN: %clang_cc1 -triple thumbv8.1m.main-unknown-none-eabi -std=c++20 %t.pcm -emit-llvm -o - | \
3+
// RUN: FileCheck --check-prefixes=CHECK,CHECK-PAC-ARM %s
4+
5+
// RUN: %clang_cc1 -triple aarch64-unknown-none-elf -emit-module-interface -target-feature +pacbti -msign-return-address=all -msign-return-address-key=b_key -mbranch-target-enforce -std=c++20 %s -o %t.pcm
6+
// RUN: %clang_cc1 -triple aarch64-unknown-none-elf -std=c++20 %t.pcm -emit-llvm -o - | \
7+
// RUN: FileCheck --check-prefixes=CHECK,CHECK-PAC-AARCH64 %s
8+
9+
// CHECK: define void @_ZGIW3foo() #0
10+
// CHECK-PAC-ARM: attributes #0 = { noinline nounwind "branch-target-enforcement" "no-trapping-math"="true" "sign-return-address"="all" "sign-return-address-key"="a_key" "stack-protector-buffer-size"="8" "target-features"="+armv8.1-m.main,+pacbti,+thumb-mode" }
11+
// CHECK-PAC-AARCH64: attributes #0 = { noinline nounwind "branch-target-enforcement" "no-trapping-math"="true" "sign-return-address"="all" "sign-return-address-key"="b_key" "stack-protector-buffer-size"="8" "target-features"="+pacbti" }
12+
13+
module;
14+
15+
export module foo;
16+
17+
export void func();

0 commit comments

Comments
 (0)