diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index bcd579454413..bd920a2e3f2d 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2216,6 +2216,11 @@ void CodeGenModule::getDefaultFunctionAttributes(StringRef Name, llvm::AttrBuilder &FuncAttrs) { getTrivialDefaultFunctionAttributes(Name, HasOptnone, AttrOnCallSite, FuncAttrs); + + if (!AttrOnCallSite) + TargetCodeGenInfo::initPointerAuthFnAttributes(CodeGenOpts.PointerAuth, + FuncAttrs); + // If we're just getting the default, get the default values for mergeable // attributes. if (!AttrOnCallSite) diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index ac40aab97820..4e79cdf0ef08 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -890,19 +890,6 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, FD->getBody()->getStmtClass() == Stmt::CoroutineBodyStmtClass) SanOpts.Mask &= ~SanitizerKind::Null; - // Add pointer authentication attributes. - const CodeGenOptions &CodeGenOpts = CGM.getCodeGenOpts(); - if (CodeGenOpts.PointerAuth.ReturnAddresses) - Fn->addFnAttr("ptrauth-returns"); - if (CodeGenOpts.PointerAuth.FunctionPointers) - Fn->addFnAttr("ptrauth-calls"); - if (CodeGenOpts.PointerAuth.AuthTraps) - Fn->addFnAttr("ptrauth-auth-traps"); - if (CodeGenOpts.PointerAuth.IndirectGotos) - Fn->addFnAttr("ptrauth-indirect-gotos"); - if (CodeGenOpts.PointerAuth.AArch64JumpTableHardening) - Fn->addFnAttr("aarch64-jump-table-hardening"); - // Apply xray attributes to the function (as a string, for now) bool AlwaysXRayAttr = false; if (const auto *XRayAttr = D ? D->getAttr() : nullptr) { diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 75a7d3c7c73f..7d176e421ac4 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -258,6 +258,35 @@ void TargetCodeGenInfo::initBranchProtectionFnAttributes( FuncAttrs.addAttribute("guarded-control-stack"); } +void TargetCodeGenInfo::setPointerAuthFnAttributes( + const PointerAuthOptions &Opts, llvm::Function &F) { + auto UpdateAttr = [&F](bool AttrShouldExist, StringRef AttrName) { + if (AttrShouldExist && !F.hasFnAttribute(AttrName)) + F.addFnAttr(AttrName); + if (!AttrShouldExist && F.hasFnAttribute(AttrName)) + F.removeFnAttr(AttrName); + }; + UpdateAttr(Opts.ReturnAddresses, "ptrauth-returns"); + UpdateAttr((bool)Opts.FunctionPointers, "ptrauth-calls"); + UpdateAttr(Opts.AuthTraps, "ptrauth-auth-traps"); + UpdateAttr(Opts.IndirectGotos, "ptrauth-indirect-gotos"); + UpdateAttr(Opts.AArch64JumpTableHardening, "aarch64-jump-table-hardening"); +} + +void TargetCodeGenInfo::initPointerAuthFnAttributes( + const PointerAuthOptions &Opts, llvm::AttrBuilder &FuncAttrs) { + if (Opts.ReturnAddresses) + FuncAttrs.addAttribute("ptrauth-returns"); + if (Opts.FunctionPointers) + FuncAttrs.addAttribute("ptrauth-calls"); + if (Opts.AuthTraps) + FuncAttrs.addAttribute("ptrauth-auth-traps"); + if (Opts.IndirectGotos) + FuncAttrs.addAttribute("ptrauth-indirect-gotos"); + if (Opts.AArch64JumpTableHardening) + FuncAttrs.addAttribute("aarch64-jump-table-hardening"); +} + namespace { class DefaultTargetCodeGenInfo : public TargetCodeGenInfo { public: diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index 77831ab3f806..2783e222eb80 100644 --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -459,6 +459,15 @@ public: initBranchProtectionFnAttributes(const TargetInfo::BranchProtectionInfo &BPI, llvm::AttrBuilder &FuncAttrs); + // Set the ptrauth-* attributes of the Function accordingly to the Opts. + // Remove attributes that contradict with current Opts. + static void setPointerAuthFnAttributes(const PointerAuthOptions &Opts, + llvm::Function &F); + + // Add the ptrauth-* Attributes to the FuncAttrs. + static void initPointerAuthFnAttributes(const PointerAuthOptions &Opts, + llvm::AttrBuilder &FuncAttrs); + protected: static std::string qualifyWindowsLibrary(StringRef Lib); diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index f098f09ebf58..6311d921f3fd 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -155,6 +155,7 @@ public: } } setBranchProtectionFnAttributes(BPI, *Fn); + setPointerAuthFnAttributes(CGM.getCodeGenOpts().PointerAuth, *Fn); } bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF, diff --git a/clang/test/CodeGenCXX/arm64-generated-fn-attr.cpp b/clang/test/CodeGenCXX/arm64-generated-fn-attr.cpp index 18d9da40d469..630b5edbbc1d 100644 --- a/clang/test/CodeGenCXX/arm64-generated-fn-attr.cpp +++ b/clang/test/CodeGenCXX/arm64-generated-fn-attr.cpp @@ -1,4 +1,9 @@ -// RUN: %clang_cc1 -triple aarch64 -mbranch-target-enforce -msign-return-address=all -fcxx-exceptions -fexceptions -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple aarch64 -mbranch-target-enforce -msign-return-address=all \ +// RUN: -fcxx-exceptions -fexceptions -emit-llvm %s -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,BTE-SIGNRA %s +// RUN: %clang_cc1 -triple aarch64 -fptrauth-calls -fptrauth-returns -fptrauth-auth-traps -fptrauth-indirect-gotos \ +// RUN: -fcxx-exceptions -fexceptions -emit-llvm %s -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,PAUTHTEST %s // Check that functions generated by clang have the correct attributes @@ -26,5 +31,7 @@ int testfn() noexcept { // CHECK: define {{.*}} @_ZTW4var2() [[ATTR1]] // CHECK: define {{.*}} @__tls_init() [[ATTR1]] -// CHECK: attributes [[ATTR1]] = { {{.*}}"branch-target-enforcement" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key" -// CHECK: attributes [[ATTR2]] = { {{.*}}"branch-target-enforcement" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key" +// BTE-SIGNRA: attributes [[ATTR1]] = { {{.*}}"branch-target-enforcement" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key" +// BTE-SIGNRA: attributes [[ATTR2]] = { {{.*}}"branch-target-enforcement" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key" +// PAUTHTEST: attributes [[ATTR1]] = { {{.*}}"ptrauth-auth-traps" "ptrauth-calls" "ptrauth-indirect-gotos" "ptrauth-returns" +// PAUTHTEST: attributes [[ATTR2]] = { {{.*}}"ptrauth-auth-traps" "ptrauth-calls" "ptrauth-indirect-gotos" "ptrauth-returns"