From 313c69e905b38ac59a92003076cb2c11655a8ff3 Mon Sep 17 00:00:00 2001 From: Jack Styles Date: Wed, 17 Apr 2024 14:35:43 +0100 Subject: [PATCH] [AArch64] Enable PAuthLR by default for standard branch protection when the feature is available Currently, LLVM implements the `standard` option as `bti+pac-ret` for ARM and AArch64. Following discussions with the GNU developemnt team within Arm it was decided to align the behaviour of `standard` to match across the different compilers. To ensure the behaviour is aligned. LLVM has been updated to implement `standard` as `bti+pac-ret+pc` by default when `+pauth-lr` is passed as part of the `-march` argument. --- clang/lib/Basic/Targets/AArch64.cpp | 2 +- clang/lib/Driver/ToolChains/Clang.cpp | 18 +++++++++++++++++- .../Preprocessor/aarch64-target-features.c | 4 ++++ llvm/docs/ReleaseNotes.rst | 5 +++++ .../llvm/TargetParser/ARMTargetParserCommon.h | 2 +- .../lib/TargetParser/ARMTargetParserCommon.cpp | 3 ++- 6 files changed, 30 insertions(+), 4 deletions(-) diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index c8d243a8fb7aea..5a46a3e6c6fd3e 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -224,7 +224,7 @@ bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef, BranchProtectionInfo &BPI, StringRef &Err) const { llvm::ARM::ParsedBranchProtection PBP; - if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err)) + if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err, HasPAuthLR)) return false; BPI.SignReturnAddr = diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 1988a90a48ae6b..057a0d850ed9b3 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1511,7 +1511,23 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, } else { StringRef DiagMsg; llvm::ARM::ParsedBranchProtection PBP; - if (!llvm::ARM::parseBranchProtection(A->getValue(), PBP, DiagMsg)) + + // To know if we need to enable PAuth-LR As part of the standard branch + // protection option, it needs to be determined if the feature has been + // activated in the `march` argument. This information is stored within the + // CmdArgs variable and can be found using a search. + if (isAArch64) { + auto isPAuthLR = [](const char *member) { + llvm::AArch64::ExtensionInfo pauthlr_extension = + llvm::AArch64::getExtensionByID(llvm::AArch64::AEK_PAUTHLR); + return (pauthlr_extension.Feature.compare(member) == 0); + }; + + if (std::any_of(CmdArgs.begin(), CmdArgs.end(), isPAuthLR)) + EnablePAuthLR = true; + } + if (!llvm::ARM::parseBranchProtection(A->getValue(), PBP, DiagMsg, + EnablePAuthLR)) D.Diag(diag::err_drv_unsupported_option_argument) << A->getSpelling() << DiagMsg; if (!isAArch64 && PBP.Key == "b_key") diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index 85762b7fed4d71..31af14f748b765 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -616,6 +616,9 @@ // ================== Check Armv9.5-A Pointer Authentication Enhancements(PAuth_LR). // RUN: %clang -target arm64-none-linux-gnu -march=armv8-a -x c -E -dM %s -o - | FileCheck -check-prefix=CHECK-PAUTH-LR-OFF %s // RUN: %clang -target arm64-none-linux-gnu -march=armv9.5-a -x c -E -dM %s -o - | FileCheck -check-prefix=CHECK-PAUTH-LR-OFF %s +// RUN: %clang -target arm64-none-linux-gnu -march=armv9.5-a -mbranch-protection=standard -x c -E -dM %s -o - | FileCheck -check-prefixes=CHECK-PAUTH-LR-OFF,CHECK-BRANCH-PROTECTION-NO-PC %s +// RUN: %clang -target arm64-none-linux-gnu -march=armv9.5-a+pauth-lr -mbranch-protection=standard -x c -E -dM %s -o - | FileCheck -check-prefixes=CHECK-PAUTH-LR,CHECK-BRANCH-PROTECTION-PC %s +// RUN: %clang -target arm64-none-linux-gnu -march=armv9.5-a+nopauth-lr -mbranch-protection=standard -x c -E -dM %s -o - | FileCheck -check-prefixes=CHECK-PAUTH-LR-OFF,CHECK-BRANCH-PROTECTION-NO-PC %s // RUN: %clang -target arm64-none-linux-gnu -march=armv8-a+pauth -mbranch-protection=none -x c -E -dM %s -o - | FileCheck -check-prefix=CHECK-PAUTH-LR-OFF %s // RUN: %clang -target arm64-none-linux-gnu -march=armv8-a+pauth-lr -mbranch-protection=none -x c -E -dM %s -o - | FileCheck -check-prefix=CHECK-PAUTH-LR %s // RUN: %clang -target arm64-none-linux-gnu -march=armv8-a+pauth-lr -mbranch-protection=bti -x c -E -dM %s -o - | FileCheck -check-prefix=CHECK-PAUTH-LR %s @@ -636,6 +639,7 @@ // RUN: %clang -target arm64-none-linux-gnu -march=armv8-a+pauth-lr -mbranch-protection=pac-ret+pc+b-key -x c -E -dM %s -o - | FileCheck -check-prefixes=CHECK-PAUTH-LR,CHECK-BRANCH-PROTECTION-PC-BKEY %s // RUN: %clang -target arm64-none-linux-gnu -march=armv8-a+pauth-lr -mbranch-protection=pac-ret+pc+leaf -x c -E -dM %s -o - | FileCheck -check-prefixes=CHECK-PAUTH-LR,CHECK-BRANCH-PROTECTION-PC-LEAF %s // RUN: %clang -target arm64-none-linux-gnu -march=armv8-a+pauth-lr -mbranch-protection=pac-ret+pc+leaf+b-key -x c -E -dM %s -o - | FileCheck -check-prefixes=CHECK-PAUTH-LR,CHECK-BRANCH-PROTECTION-PC-LEAF-BKEY %s +// CHECK-BRANCH-PROTECTION-NO-PC: #define __ARM_FEATURE_PAC_DEFAULT 1 // CHECK-BRANCH-PROTECTION-PC: #define __ARM_FEATURE_PAC_DEFAULT 9 // CHECK-BRANCH-PROTECTION-PC-BKEY: #define __ARM_FEATURE_PAC_DEFAULT 10 // CHECK-BRANCH-PROTECTION-PC-LEAF: #define __ARM_FEATURE_PAC_DEFAULT 13 diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 46d79d6c5822b1..2ac18451989887 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -76,6 +76,11 @@ Changes to the AArch64 Backend * Added support for Cortex-A78AE, Cortex-A520AE, Cortex-A720AE, Neoverse-N3, Neoverse-V3 and Neoverse-V3AE CPUs. +* `-mbranch-protection=standard` now enables FEAT_PAuth_LR by + default when the feature is enabled. The new behaviour results + in `standard` being equal to `bti+pac-ret+pc` when `+pauth-lr` + is passed as part of `-mcpu=`options. + Changes to the AMDGPU Backend ----------------------------- diff --git a/llvm/include/llvm/TargetParser/ARMTargetParserCommon.h b/llvm/include/llvm/TargetParser/ARMTargetParserCommon.h index 8ae553ca80ddc3..f6115718e9f5fd 100644 --- a/llvm/include/llvm/TargetParser/ARMTargetParserCommon.h +++ b/llvm/include/llvm/TargetParser/ARMTargetParserCommon.h @@ -46,7 +46,7 @@ struct ParsedBranchProtection { }; bool parseBranchProtection(StringRef Spec, ParsedBranchProtection &PBP, - StringRef &Err); + StringRef &Err, bool EnablePAuthLR = false); } // namespace ARM } // namespace llvm diff --git a/llvm/lib/TargetParser/ARMTargetParserCommon.cpp b/llvm/lib/TargetParser/ARMTargetParserCommon.cpp index 45d04f9bcbfb6a..d6ce6581bb1a92 100644 --- a/llvm/lib/TargetParser/ARMTargetParserCommon.cpp +++ b/llvm/lib/TargetParser/ARMTargetParserCommon.cpp @@ -139,7 +139,7 @@ ARM::EndianKind ARM::parseArchEndian(StringRef Arch) { // returned in `PBP`. Returns false in error, with `Err` containing // an erroneous part of the spec. bool ARM::parseBranchProtection(StringRef Spec, ParsedBranchProtection &PBP, - StringRef &Err) { + StringRef &Err, bool EnablePAuthLR) { PBP = {"none", "a_key", false, false, false}; if (Spec == "none") return true; // defaults are ok @@ -148,6 +148,7 @@ bool ARM::parseBranchProtection(StringRef Spec, ParsedBranchProtection &PBP, PBP.Scope = "non-leaf"; PBP.BranchTargetEnforcement = true; PBP.GuardedControlStack = true; + PBP.BranchProtectionPAuthLR = EnablePAuthLR; return true; }