Skip to content

Commit eef710d

Browse files
Emit attributes for functions always.
Branch protection, sign return address, guarded control stack flags are only emitted as module flags if not specified per function. The inliner might inline functions with different set of flags as it doesn't see the flags. In case of LTO build the module flags get merged with the `min` rule which means if one of the modules is not build with PAC/BTI then the features will be turned off on all functions due to the functions takes the branch-protection and sign-return-address features from the module flags. The sign-return-address is function level option therefore it is expected functions from files that are compiled with -mbranch-protection=pac-ret to be protected but in LTO case this might not happen. This patch adds the flags to functions in case of an LTO build therefore they don't need to rely on the module flag.
1 parent c5c2d72 commit eef710d

File tree

7 files changed

+94
-44
lines changed

7 files changed

+94
-44
lines changed

clang/include/clang/Basic/TargetInfo.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,6 +1377,21 @@ class TargetInfo : public TransferrableTargetInfo,
13771377

13781378
BranchProtectionInfo() = default;
13791379

1380+
BranchProtectionInfo(const LangOptions &LangOpts) {
1381+
SignReturnAddr =
1382+
LangOpts.hasSignReturnAddress()
1383+
? (LangOpts.isSignReturnAddressScopeAll()
1384+
? LangOptions::SignReturnAddressScopeKind::All
1385+
: LangOptions::SignReturnAddressScopeKind::NonLeaf)
1386+
: LangOptions::SignReturnAddressScopeKind::None;
1387+
SignKey = LangOpts.isSignReturnAddressWithAKey()
1388+
? LangOptions::SignReturnAddressKeyKind::AKey
1389+
: LangOptions::SignReturnAddressKeyKind::BKey;
1390+
BranchTargetEnforcement = LangOpts.BranchTargetEnforcement;
1391+
BranchProtectionPAuthLR = LangOpts.BranchProtectionPAuthLR;
1392+
GuardedControlStack = LangOpts.GuardedControlStack;
1393+
}
1394+
13801395
const char *getSignReturnAddrStr() const {
13811396
static const char *SignReturnAddrStr[] = {"none", "non-leaf", "all"};
13821397
assert(static_cast<unsigned>(SignReturnAddr) <= 2 &&

clang/lib/CodeGen/Targets/AArch64.cpp

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -109,37 +109,32 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
109109
if (!FD)
110110
return;
111111

112-
const auto *TA = FD->getAttr<TargetAttr>();
113-
if (TA == nullptr)
114-
return;
115-
116-
ParsedTargetAttr Attr =
117-
CGM.getTarget().parseTargetAttr(TA->getFeaturesStr());
118-
if (Attr.BranchProtection.empty())
119-
return;
120-
121-
TargetInfo::BranchProtectionInfo BPI;
122-
StringRef Error;
123-
(void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
124-
Attr.CPU, BPI, Error);
125-
assert(Error.empty());
126-
112+
TargetInfo::BranchProtectionInfo BPI(CGM.getLangOpts());
113+
114+
if (const auto *TA = FD->getAttr<TargetAttr>()) {
115+
ParsedTargetAttr Attr =
116+
CGM.getTarget().parseTargetAttr(TA->getFeaturesStr());
117+
if (!Attr.BranchProtection.empty()) {
118+
StringRef Error;
119+
(void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
120+
Attr.CPU, BPI, Error);
121+
assert(Error.empty());
122+
}
123+
}
127124
auto *Fn = cast<llvm::Function>(GV);
128-
Fn->addFnAttr("sign-return-address", BPI.getSignReturnAddrStr());
129-
130125
if (BPI.SignReturnAddr != LangOptions::SignReturnAddressScopeKind::None) {
126+
Fn->addFnAttr("sign-return-address", BPI.getSignReturnAddrStr());
131127
Fn->addFnAttr("sign-return-address-key",
132128
BPI.SignKey == LangOptions::SignReturnAddressKeyKind::AKey
133129
? "a_key"
134130
: "b_key");
135131
}
136-
137-
Fn->addFnAttr("branch-target-enforcement",
138-
BPI.BranchTargetEnforcement ? "true" : "false");
139-
Fn->addFnAttr("branch-protection-pauth-lr",
140-
BPI.BranchProtectionPAuthLR ? "true" : "false");
141-
Fn->addFnAttr("guarded-control-stack",
142-
BPI.GuardedControlStack ? "true" : "false");
132+
if (BPI.BranchTargetEnforcement)
133+
Fn->addFnAttr("branch-target-enforcement", "true");
134+
if (BPI.BranchProtectionPAuthLR)
135+
Fn->addFnAttr("branch-protection-pauth-lr", "true");
136+
if (BPI.GuardedControlStack)
137+
Fn->addFnAttr("guarded-control-stack", "true");
143138
}
144139

145140
bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF,

clang/lib/CodeGen/Targets/ARM.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,13 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
167167
diag::warn_target_unsupported_branch_protection_attribute)
168168
<< Attr.CPU;
169169
}
170+
} else if (CGM.getTarget().isBranchProtectionSupportedArch(
171+
CGM.getTarget().getTargetOpts().CPU)) {
172+
TargetInfo::BranchProtectionInfo BPI(CGM.getLangOpts());
173+
if (BPI.SignReturnAddr != LangOptions::SignReturnAddressScopeKind::None)
174+
Fn->addFnAttr("sign-return-address", BPI.getSignReturnAddrStr());
175+
if (BPI.BranchTargetEnforcement)
176+
Fn->addFnAttr("branch-target-enforcement", "true");
170177
}
171178

172179
const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>();

clang/test/CodeGen/aarch64-branch-protection-attr.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,29 +67,29 @@ __attribute__ ((target("branch-protection=gcs")))
6767
void gcs() {}
6868
// CHECK: define{{.*}} void @gcs() #[[#GCS:]]
6969

70-
// CHECK-DAG: attributes #[[#NONE]] = { {{.*}} "branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}} "sign-return-address"="none"
70+
// CHECK-DAG: attributes #[[#NONE]] = { {{.*}}
7171

7272
// CHECK-DAG: attributes #[[#STD]] = { {{.*}} "branch-target-enforcement"="true" "guarded-control-stack"="true" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
7373

74-
// CHECK-DAG: attributes #[[#BTI]] = { {{.*}} "branch-target-enforcement"="true" "guarded-control-stack"="false" {{.*}} "sign-return-address"="none"
74+
// CHECK-DAG: attributes #[[#BTI]] = { {{.*}} "branch-target-enforcement"="true"
7575

76-
// CHECK-DAG: attributes #[[#PAC]] = { {{.*}} "branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
76+
// CHECK-DAG: attributes #[[#PAC]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
7777

78-
// CHECK-DAG: attributes #[[#PACLEAF]] = { {{.*}} "branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"
78+
// CHECK-DAG: attributes #[[#PACLEAF]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key"
7979

80-
// CHECK-DAG: attributes #[[#PACBKEY]] = { {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="b_key"
80+
// CHECK-DAG: attributes #[[#PACBKEY]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="b_key"
8181

82-
// CHECK-DAG: attributes #[[#PACBKEYLEAF]] = { {{.*}} "branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="b_key"
82+
// CHECK-DAG: attributes #[[#PACBKEYLEAF]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="b_key"
8383

84-
// CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}}"branch-target-enforcement"="true" "guarded-control-stack"="false" {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key"
84+
// CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}} "branch-target-enforcement"="true" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"
8585

8686

87-
// CHECK-DAG: attributes #[[#PAUTHLR]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
87+
// CHECK-DAG: attributes #[[#PAUTHLR]] = { {{.*}} "branch-protection-pauth-lr"="true" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
8888

89-
// CHECK-DAG: attributes #[[#PAUTHLR_BKEY]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="b_key"
89+
// CHECK-DAG: attributes #[[#PAUTHLR_BKEY]] = { {{.*}} "branch-protection-pauth-lr"="true" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="b_key"
9090

91-
// CHECK-DAG: attributes #[[#PAUTHLR_LEAF]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"
91+
// CHECK-DAG: attributes #[[#PAUTHLR_LEAF]] = { {{.*}} "branch-protection-pauth-lr"="true" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"
9292

93-
// CHECK-DAG: attributes #[[#PAUTHLR_BTI]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="true" "guarded-control-stack"="false" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
93+
// CHECK-DAG: attributes #[[#PAUTHLR_BTI]] = { {{.*}} "branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="true" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
9494

95-
// CHECK-DAG: attributes #[[#GCS]] = { {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="true" {{.*}} "sign-return-address"="none"
95+
// CHECK-DAG: attributes #[[#GCS]] = { {{.*}} "guarded-control-stack"="true"

clang/test/CodeGen/aarch64-sign-return-address.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@
1313

1414
// CHECK-LABEL: @foo() #[[#ATTR:]]
1515

16-
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"
17-
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"
18-
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"
16+
// NONE-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"
17+
// NONE-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"
18+
// NONE-NOT: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"
19+
20+
// ALL: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"
21+
// PART: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"="a_key"
22+
// B-KEY: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"="b_key"
23+
// BTE: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"
24+
1925

2026
// Check module attributes
2127

@@ -43,4 +49,4 @@
4349
// BTE-NOT: !"sign-return-address-with-bkey"
4450
// B-KEY: !{i32 8, !"sign-return-address-with-bkey", i32 1}
4551

46-
void foo() {}
52+
void foo() {}

clang/test/CodeGen/arm-branch-protection-attr-2.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,18 @@
55
// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | FileCheck %s --check-prefix=CHECK --check-prefix=PART
66
// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=bti %s | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
77

8-
// Check there are no branch protection function attributes
8+
// Check there is branch protection function attributes
99

1010
// CHECK-LABEL: @foo() #[[#ATTR:]]
1111

12-
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"
13-
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"
14-
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"
12+
// NONE-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"
13+
// NONE-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"
14+
// NONE-NOT: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"
15+
16+
// ALL: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"="all"
17+
// PART: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"="non-leaf"
18+
// BTE: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"
19+
1520

1621
// Check module attributes
1722

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// REQUIRES: arm-registered-target
2+
3+
// RUN: %clang_cc1 -triple=thumbv7m-unknown-unknown-eabi -msign-return-address=non-leaf %s -S -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=SIGN
4+
// RUN: %clang_cc1 -triple=thumbv7m-unknown-unknown-eabi -mbranch-target-enforce %s -S -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
5+
// RUN: %clang_cc1 -triple=thumbv7m-unknown-unknown-eabi -mbranch-target-enforce -msign-return-address=all %s -S -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=ALL
6+
7+
// RUN: %clang_cc1 -flto -triple=thumbv7m-unknown-unknown-eabi -msign-return-address=non-leaf %s -S -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=SIGN
8+
// RUN: %clang_cc1 -flto -triple=thumbv7m-unknown-unknown-eabi -mbranch-target-enforce %s -S -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
9+
// RUN: %clang_cc1 -flto -triple=thumbv7m-unknown-unknown-eabi -mbranch-target-enforce -msign-return-address=all %s -S -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=ALL
10+
11+
// RUN: %clang_cc1 -flto=thin -triple=thumbv7m-unknown-unknown-eabi -msign-return-address=non-leaf %s -S -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=SIGN
12+
// RUN: %clang_cc1 -flto=thin -triple=thumbv7m-unknown-unknown-eabi -mbranch-target-enforce %s -S -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
13+
// RUN: %clang_cc1 -flto=thin -triple=thumbv7m-unknown-unknown-eabi -mbranch-target-enforce -msign-return-address=all %s -S -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=ALL
14+
15+
void foo() {}
16+
17+
// Check there are branch protection function attributes.
18+
// CHECK-LABEL: @foo() #[[#ATTR:]]
19+
20+
// SIGN: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"="non-leaf"
21+
// BTE: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"
22+
// ALL: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"{{.*}} "sign-return-address"="all"

0 commit comments

Comments
 (0)