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.
This commit is contained in:
Victor Campos 2025-04-25 11:04:34 +01:00 committed by GitHub
parent a4d1a9d6d5
commit 6738cfe0a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 34 additions and 12 deletions

View File

@ -448,6 +448,11 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction(
if (Linkage == llvm::GlobalVariable::InternalLinkage)
SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
else {
SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn, false);
SetLLVMFunctionAttributesForDefinition(nullptr, Fn);
getTargetCodeGenInfo().setTargetAttributes(nullptr, Fn, *this);
}
Fn->setCallingConv(getRuntimeCC());

View File

@ -136,13 +136,15 @@ public:
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const override {
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD)
auto *Fn = dyn_cast<llvm::Function>(GV);
if (!Fn)
return;
const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
TargetInfo::BranchProtectionInfo BPI(CGM.getLangOpts());
if (const auto *TA = FD->getAttr<TargetAttr>()) {
if (FD && FD->hasAttr<TargetAttr>()) {
const auto *TA = FD->getAttr<TargetAttr>();
ParsedTargetAttr Attr =
CGM.getTarget().parseTargetAttr(TA->getFeaturesStr());
if (!Attr.BranchProtection.empty()) {
@ -152,7 +154,6 @@ public:
assert(Error.empty());
}
}
auto *Fn = cast<llvm::Function>(GV);
setBranchProtectionFnAttributes(BPI, *Fn);
}

View File

@ -134,14 +134,13 @@ public:
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const override {
if (GV->isDeclaration())
auto *Fn = dyn_cast<llvm::Function>(GV);
if (!Fn)
return;
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD)
return;
auto *Fn = cast<llvm::Function>(GV);
const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
if (const auto *TA = FD->getAttr<TargetAttr>()) {
if (FD && FD->hasAttr<TargetAttr>()) {
const auto *TA = FD->getAttr<TargetAttr>();
ParsedTargetAttr Attr =
CGM.getTarget().parseTargetAttr(TA->getFeaturesStr());
if (!Attr.BranchProtection.empty()) {
@ -174,10 +173,10 @@ public:
setBranchProtectionFnAttributes(BPI, (*Fn));
}
const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>();
if (!Attr)
if (!FD || !FD->hasAttr<ARMInterruptAttr>())
return;
const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>();
const char *Kind;
switch (Attr->getInterrupt()) {
case ARMInterruptAttr::Generic: Kind = ""; break;

View File

@ -0,0 +1,17 @@
// 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-ARM %s
// 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
// RUN: %clang_cc1 -triple aarch64-unknown-none-elf -std=c++20 %t.pcm -emit-llvm -o - | \
// RUN: FileCheck --check-prefixes=CHECK,CHECK-PAC-AARCH64 %s
// CHECK: define void @_ZGIW3foo() #0
// 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" }
// 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" }
module;
export module foo;
export void func();