[clang] [AArch64][PAC][clang][ELF] Support PAuth ABI compatibility tag (PR #85235)

Daniil Kovalev via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 15 23:07:03 PDT 2024


https://github.com/kovdan01 updated https://github.com/llvm/llvm-project/pull/85235

>From 8e65b4402201f74d5312ed257c4abde4a6615964 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 14 Mar 2024 12:19:26 +0300
Subject: [PATCH 1/2] [PAC][clang] Define ptrauth driver flags and preprocessor
 features

Define the following clang driver flags:

- `-fptrauth-intrinsics`: `PointerAuth.intrinsics()` in `LangOptions`,
  `ptrauth_intrinsics` preprocessor feature;

- `-fptrauth-calls`: `PointerAuth.calls()` in `LangOptions`, `ptrauth_calls` and
  and `ptrauth_member_function_pointer_type_discrimination` preprocessor
  features;

- `-fptrauth-returns`: `PointerAuth.returns()` in `LangOptions`,
  `ptrauth_returns` preprocessor feature;

- `-fptrauth-auth-traps`: `PointerAuth.authTraps()` in `LangOptions`;

- `-fptrauth-vtable-pointer-address-discrimination`:
  `PointerAuth.vtptrAddressDiscrimination()` in `LangOptions`,
  `ptrauth_vtable_pointer_address_discrimination` preprocessor feature;

- `-fptrauth-vtable-pointer-type-discrimination`:
  `PointerAuth.vtptrTypeDiscrimination()` in `LangOptions`,
  `ptrauth_vtable_pointer_type_discrimination` preprocessor feature;

- `-fptrauth-init-fini`: `PointerAuth.initFini()` in `LangOptions`,
  `ptrauth_init_fini` preprocessor feature.

The patch only defines the flags and having corresponding `LangOptions`
set does not affect codegen yet.

Co-authored-by: Ahmed Bougacha <ahmed at bougacha.org>
---
 clang/include/clang/Basic/Features.def    |   7 ++
 clang/include/clang/Basic/LangOptions.h   |  18 ++++
 clang/include/clang/Driver/Options.td     |  26 +++++
 clang/lib/Driver/ToolChains/Clang.cpp     |  32 ++++++
 clang/lib/Frontend/CompilerInvocation.cpp |  33 +++++++
 clang/test/Driver/ptrauth.c               |  32 ++++++
 clang/test/Preprocessor/ptrauth.c         | 113 ++++++++++++++++++++++
 7 files changed, 261 insertions(+)
 create mode 100644 clang/test/Driver/ptrauth.c
 create mode 100644 clang/test/Preprocessor/ptrauth.c

diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def
index 5fad5fc3623cb6..182a44a1079ef2 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -101,6 +101,13 @@ FEATURE(memory_sanitizer,
 FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
 FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
 FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
+FEATURE(ptrauth_intrinsics, LangOpts.PointerAuth.intrinsics())
+FEATURE(ptrauth_calls, LangOpts.PointerAuth.calls())
+FEATURE(ptrauth_returns, LangOpts.PointerAuth.returns())
+FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuth.vtptrAddressDiscrimination())
+FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuth.vtptrTypeDiscrimination())
+FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuth.calls())
+FEATURE(ptrauth_init_fini, LangOpts.PointerAuth.initFini())
 FEATURE(swiftasynccc,
   PP.getTargetInfo().checkCallingConvention(CC_SwiftAsync) ==
   clang::TargetInfo::CCCR_OK)
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 862952d336ef31..e9ade66a8df2ac 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -532,6 +532,24 @@ class LangOptions : public LangOptionsBase {
   // implementation on real-world examples.
   std::string OpenACCMacroOverride;
 
+  struct {
+    bool Flags[7] = {false};
+    bool intrinsics() const { return Flags[0]; }
+    bool &intrinsics() { return Flags[0]; }
+    bool calls() const { return Flags[1]; }
+    bool &calls() { return Flags[1]; }
+    bool returns() const { return Flags[2]; }
+    bool &returns() { return Flags[2]; }
+    bool authTraps() const { return Flags[3]; }
+    bool &authTraps() { return Flags[3]; }
+    bool vtptrAddressDiscrimination() const { return Flags[4]; }
+    bool &vtptrAddressDiscrimination() { return Flags[4]; }
+    bool vtptrTypeDiscrimination() const { return Flags[5]; }
+    bool &vtptrTypeDiscrimination() { return Flags[5]; }
+    bool initFini() const { return Flags[6]; }
+    bool &initFini() { return Flags[6]; }
+  } PointerAuth;
+
   LangOptions();
 
   /// Set language defaults for the given input language and
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index aca8c9b0d5487a..868b164d8f7174 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4085,6 +4085,32 @@ defm strict_return : BoolFOption<"strict-return",
             " of a non-void function as unreachable">,
   PosFlag<SetTrue>>;
 
+let Group = f_Group in {
+  let Visibility = [ClangOption,CC1Option] in {
+    def fptrauth_intrinsics : Flag<["-"], "fptrauth-intrinsics">,
+      HelpText<"Enable pointer-authentication intrinsics">;
+    def fptrauth_calls : Flag<["-"], "fptrauth-calls">,
+      HelpText<"Enable signing and authentication of all indirect calls">;
+    def fptrauth_returns : Flag<["-"], "fptrauth-returns">,
+      HelpText<"Enable signing and authentication of return addresses">;
+    def fptrauth_auth_traps : Flag<["-"], "fptrauth-auth-traps">,
+      HelpText<"Enable traps on authentication failures">;
+    def fptrauth_vtable_pointer_address_discrimination : Flag<["-"], "fptrauth-vtable-pointer-address-discrimination">,
+      HelpText<"Enable address discrimination of vtable pointers">;
+    def fptrauth_vtable_pointer_type_discrimination : Flag<["-"], "fptrauth-vtable-pointer-type-discrimination">,
+      HelpText<"Enable type discrimination of vtable pointers">;
+    def fptrauth_init_fini : Flag<["-"], "fptrauth-init-fini">,
+      HelpText<"Enable signing of function pointers in init/fini arrays">;
+  }
+  def fno_ptrauth_intrinsics : Flag<["-"], "fno-ptrauth-intrinsics">;
+  def fno_ptrauth_calls : Flag<["-"], "fno-ptrauth-calls">;
+  def fno_ptrauth_returns : Flag<["-"], "fno-ptrauth-returns">;
+  def fno_ptrauth_auth_traps : Flag<["-"], "fno-ptrauth-auth-traps">;
+  def fno_ptrauth_vtable_pointer_address_discrimination : Flag<["-"], "fno-ptrauth-vtable-pointer-address-discrimination">;
+  def fno_ptrauth_vtable_pointer_type_discrimination : Flag<["-"], "fno-ptrauth-vtable-pointer-type-discrimination">;
+  def fno_ptrauth_init_fini : Flag<["-"], "fno-ptrauth-init-fini">;
+}
+
 def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
     Visibility<[ClangOption, CC1Option]>,
     HelpText<"Enable matrix data type and related builtin functions">,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index cc568b9a715bbe..800973fa3311e2 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7182,6 +7182,38 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   // -fno-common is the default, set -fcommon only when that flag is set.
   Args.addOptInFlag(CmdArgs, options::OPT_fcommon, options::OPT_fno_common);
 
+  if (Args.hasFlag(options::OPT_fptrauth_intrinsics,
+                   options::OPT_fno_ptrauth_intrinsics, false))
+    CmdArgs.push_back("-fptrauth-intrinsics");
+
+  if (Args.hasFlag(options::OPT_fptrauth_calls,
+                   options::OPT_fno_ptrauth_calls, false))
+    CmdArgs.push_back("-fptrauth-calls");
+
+  if (Args.hasFlag(options::OPT_fptrauth_returns,
+                   options::OPT_fno_ptrauth_returns, false))
+    CmdArgs.push_back("-fptrauth-returns");
+
+  if (Args.hasFlag(options::OPT_fptrauth_auth_traps,
+                   options::OPT_fno_ptrauth_auth_traps, false))
+    CmdArgs.push_back("-fptrauth-auth-traps");
+
+  if (Args.hasFlag(
+          options::OPT_fptrauth_vtable_pointer_address_discrimination,
+          options::OPT_fno_ptrauth_vtable_pointer_address_discrimination,
+          false))
+    CmdArgs.push_back("-fptrauth-vtable-pointer-address-discrimination");
+
+  if (Args.hasFlag(options::OPT_fptrauth_vtable_pointer_type_discrimination,
+                   options::OPT_fno_ptrauth_vtable_pointer_type_discrimination,
+                   false))
+    CmdArgs.push_back("-fptrauth-vtable-pointer-type-discrimination");
+
+  if (Args.hasFlag(options::OPT_fptrauth_init_fini,
+                   options::OPT_fno_ptrauth_init_fini,
+                   false))
+    CmdArgs.push_back("-fptrauth-init-fini");
+
   // -fsigned-bitfields is default, and clang doesn't yet support
   // -funsigned-bitfields.
   if (!Args.hasFlag(options::OPT_fsigned_bitfields,
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 451bdb9386f587..bd34d25b2f1f6d 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3293,6 +3293,37 @@ static void ParseAPINotesArgs(APINotesOptions &Opts, ArgList &Args,
     Opts.ModuleSearchPaths.push_back(A->getValue());
 }
 
+static void GeneratePointerAuthArgs(const LangOptions &Opts,
+                                    ArgumentConsumer Consumer) {
+  if (Opts.PointerAuth.intrinsics())
+    GenerateArg(Consumer, OPT_fptrauth_intrinsics);
+  if (Opts.PointerAuth.calls())
+    GenerateArg(Consumer, OPT_fptrauth_calls);
+  if (Opts.PointerAuth.returns())
+    GenerateArg(Consumer, OPT_fptrauth_returns);
+  if (Opts.PointerAuth.authTraps())
+    GenerateArg(Consumer, OPT_fptrauth_auth_traps);
+  if (Opts.PointerAuth.vtptrAddressDiscrimination())
+    GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_address_discrimination);
+  if (Opts.PointerAuth.vtptrTypeDiscrimination())
+    GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination);
+  if (Opts.PointerAuth.initFini())
+    GenerateArg(Consumer, OPT_fptrauth_init_fini);
+}
+
+static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
+                                 DiagnosticsEngine &Diags) {
+  Opts.PointerAuth.intrinsics() = Args.hasArg(OPT_fptrauth_intrinsics);
+  Opts.PointerAuth.calls() = Args.hasArg(OPT_fptrauth_calls);
+  Opts.PointerAuth.returns() = Args.hasArg(OPT_fptrauth_returns);
+  Opts.PointerAuth.authTraps() = Args.hasArg(OPT_fptrauth_auth_traps);
+  Opts.PointerAuth.vtptrAddressDiscrimination() =
+      Args.hasArg(OPT_fptrauth_vtable_pointer_address_discrimination);
+  Opts.PointerAuth.vtptrTypeDiscrimination() =
+      Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination);
+  Opts.PointerAuth.initFini() = Args.hasArg(OPT_fptrauth_init_fini);
+}
+
 /// Check if input file kind and language standard are compatible.
 static bool IsInputCompatibleWithStandard(InputKind IK,
                                           const LangStandard &S) {
@@ -4610,6 +4641,7 @@ bool CompilerInvocation::CreateFromArgsImpl(
   llvm::Triple T(Res.getTargetOpts().Triple);
   ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags,
                         Res.getFileSystemOpts().WorkingDir);
+  ParsePointerAuthArgs(LangOpts, Args, Diags);
   ParseAPINotesArgs(Res.getAPINotesOpts(), Args, Diags);
 
   ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes,
@@ -4841,6 +4873,7 @@ void CompilerInvocationBase::generateCC1CommandLine(
   GenerateFrontendArgs(getFrontendOpts(), Consumer, getLangOpts().IsHeaderFile);
   GenerateTargetArgs(getTargetOpts(), Consumer);
   GenerateHeaderSearchArgs(getHeaderSearchOpts(), Consumer);
+  GeneratePointerAuthArgs(getLangOpts(), Consumer);
   GenerateAPINotesArgs(getAPINotesOpts(), Consumer);
   GenerateLangArgs(getLangOpts(), Consumer, T, getFrontendOpts().DashX);
   GenerateCodeGenArgs(getCodeGenOpts(), Consumer, T,
diff --git a/clang/test/Driver/ptrauth.c b/clang/test/Driver/ptrauth.c
new file mode 100644
index 00000000000000..2336a5d551b014
--- /dev/null
+++ b/clang/test/Driver/ptrauth.c
@@ -0,0 +1,32 @@
+// Check that we can manually enable specific ptrauth features.
+
+// RUN: %clang -target aarch64 -c %s -### 2>&1 | FileCheck %s --check-prefix NONE
+// NONE: "-cc1"
+// NONE-NOT: "-fptrauth-intrinsics"
+// NONE-NOT: "-fptrauth-calls"
+// NONE-NOT: "-fptrauth-returns"
+// NONE-NOT: "-fptrauth-auth-traps"
+// NONE-NOT: "-fptrauth-vtable-pointer-address-discrimination"
+// NONE-NOT: "-fptrauth-vtable-pointer-type-discrimination"
+// NONE-NOT: "-fptrauth-init-fini"
+
+// RUN: %clang -target aarch64 -fptrauth-intrinsics -c %s -### 2>&1 | FileCheck %s --check-prefix INTRIN
+// INTRIN: "-cc1"{{.*}} {{.*}} "-fptrauth-intrinsics"
+
+// RUN: %clang -target aarch64 -fptrauth-calls -c %s -### 2>&1 | FileCheck %s --check-prefix CALL
+// CALL: "-cc1"{{.*}} {{.*}} "-fptrauth-calls"
+
+// RUN: %clang -target aarch64 -fptrauth-returns -c %s -### 2>&1 | FileCheck %s --check-prefix RETURN
+// RETURN: "-cc1"{{.*}} {{.*}} "-fptrauth-returns"
+
+// RUN: %clang -target aarch64 -fptrauth-auth-traps -c %s -### 2>&1 | FileCheck %s --check-prefix TRAPS
+// TRAPS: "-cc1"{{.*}} {{.*}} "-fptrauth-auth-traps"
+
+// RUN: %clang -target aarch64 -fptrauth-vtable-pointer-address-discrimination -c %s -### 2>&1 | FileCheck %s --check-prefix VPTR_ADDR_DISCR
+// VPTR_ADDR_DISCR: "-cc1"{{.*}} {{.*}} "-fptrauth-vtable-pointer-address-discrimination"
+
+// RUN: %clang -target aarch64 -fptrauth-vtable-pointer-type-discrimination -c %s -### 2>&1 | FileCheck %s --check-prefix VPTR_TYPE_DISCR
+// VPTR_TYPE_DISCR: "-cc1"{{.*}} {{.*}} "-fptrauth-vtable-pointer-type-discrimination"
+
+// RUN: %clang -target aarch64 -fptrauth-init-fini -c %s -### 2>&1 | FileCheck %s --check-prefix INITFINI
+// INITFINI: "-cc1"{{.*}} {{.*}} "-fptrauth-init-fini"
diff --git a/clang/test/Preprocessor/ptrauth.c b/clang/test/Preprocessor/ptrauth.c
new file mode 100644
index 00000000000000..3950b6e0544727
--- /dev/null
+++ b/clang/test/Preprocessor/ptrauth.c
@@ -0,0 +1,113 @@
+// RUN: %clang -E %s --target=aarch64 \
+// RUN:   -fptrauth-intrinsics \
+// RUN:   -fptrauth-calls \
+// RUN:   -fptrauth-returns \
+// RUN:   -fptrauth-vtable-pointer-address-discrimination \
+// RUN:   -fptrauth-vtable-pointer-type-discrimination \
+// RUN:   -fptrauth-init-fini | \
+// RUN:   FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI
+
+// RUN: %clang -E %s --target=aarch64 \
+// RUN:   -fptrauth-calls \
+// RUN:   -fptrauth-returns \
+// RUN:   -fptrauth-vtable-pointer-address-discrimination \
+// RUN:   -fptrauth-vtable-pointer-type-discrimination \
+// RUN:   -fptrauth-init-fini | \
+// RUN:   FileCheck %s --check-prefixes=NOINTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI
+
+// RUN: %clang -E %s --target=aarch64 \
+// RUN:   -fptrauth-intrinsics \
+// RUN:   -fptrauth-returns \
+// RUN:   -fptrauth-vtable-pointer-address-discrimination \
+// RUN:   -fptrauth-vtable-pointer-type-discrimination \
+// RUN:   -fptrauth-init-fini | \
+// RUN:   FileCheck %s --check-prefixes=INTRIN,NOCALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI
+
+// RUN: %clang -E %s --target=aarch64 \
+// RUN:   -fptrauth-intrinsics \
+// RUN:   -fptrauth-calls \
+// RUN:   -fptrauth-vtable-pointer-address-discrimination \
+// RUN:   -fptrauth-vtable-pointer-type-discrimination \
+// RUN:   -fptrauth-init-fini | \
+// RUN:   FileCheck %s --check-prefixes=INTRIN,CALLS,NORETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI
+
+// RUN: %clang -E %s --target=aarch64 \
+// RUN:   -fptrauth-intrinsics \
+// RUN:   -fptrauth-calls \
+// RUN:   -fptrauth-returns \
+// RUN:   -fptrauth-vtable-pointer-type-discrimination \
+// RUN:   -fptrauth-init-fini | \
+// RUN:   FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,NOVPTR_ADDR_DISCR,VPTR_TYPE_DISCR,INITFINI
+
+// RUN: %clang -E %s --target=aarch64 \
+// RUN:   -fptrauth-intrinsics \
+// RUN:   -fptrauth-calls \
+// RUN:   -fptrauth-returns \
+// RUN:   -fptrauth-vtable-pointer-address-discrimination \
+// RUN:   -fptrauth-init-fini | \
+// RUN:   FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,INITFINI
+
+// RUN: %clang -E %s --target=aarch64 \
+// RUN:   -fptrauth-intrinsics \
+// RUN:   -fptrauth-calls \
+// RUN:   -fptrauth-returns \
+// RUN:   -fptrauth-vtable-pointer-address-discrimination \
+// RUN:   -fptrauth-vtable-pointer-type-discrimination | \
+// RUN:   FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,NOINITFINI
+
+#if __has_feature(ptrauth_intrinsics)
+// INTRIN: has_ptrauth_intrinsics
+void has_ptrauth_intrinsics() {}
+#else
+// NOINTRIN: no_ptrauth_intrinsics
+void no_ptrauth_intrinsics() {}
+#endif
+
+#if __has_feature(ptrauth_calls)
+// CALLS: has_ptrauth_calls
+void has_ptrauth_calls() {}
+#else
+// NOCALLS: no_ptrauth_calls
+void no_ptrauth_calls() {}
+#endif
+
+// This is always enabled when ptrauth_calls is enabled
+#if __has_feature(ptrauth_member_function_pointer_type_discrimination)
+// CALLS: has_ptrauth_member_function_pointer_type_discrimination
+void has_ptrauth_member_function_pointer_type_discrimination() {}
+#else
+// NOCALLS: no_ptrauth_member_function_pointer_type_discrimination
+void no_ptrauth_member_function_pointer_type_discrimination() {}
+#endif
+
+#if __has_feature(ptrauth_returns)
+// RETS: has_ptrauth_returns
+void has_ptrauth_returns() {}
+#else
+// NORETS: no_ptrauth_returns
+void no_ptrauth_returns() {}
+#endif
+
+#if __has_feature(ptrauth_vtable_pointer_address_discrimination)
+// VPTR_ADDR_DISCR: has_ptrauth_vtable_pointer_address_discrimination
+void has_ptrauth_vtable_pointer_address_discrimination() {}
+#else
+// NOVPTR_ADDR_DISCR: no_ptrauth_vtable_pointer_address_discrimination
+void no_ptrauth_vtable_pointer_address_discrimination() {}
+#endif
+
+#if __has_feature(ptrauth_vtable_pointer_type_discrimination)
+// VPTR_TYPE_DISCR: has_ptrauth_vtable_pointer_type_discrimination
+void has_ptrauth_vtable_pointer_type_discrimination() {}
+#else
+// NOVPTR_TYPE_DISCR: no_ptrauth_vtable_pointer_type_discrimination
+void no_ptrauth_vtable_pointer_type_discrimination() {}
+#endif
+
+#if __has_feature(ptrauth_init_fini)
+// INITFINI: has_ptrauth_init_fini
+void has_ptrauth_init_fini() {}
+#else
+// NOINITFINI: no_ptrauth_init_fini
+void no_ptrauth_init_fini() {}
+#endif

>From 435c7eae0148f950a56c017fab408a69bedd84af Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Wed, 13 Mar 2024 23:02:04 +0300
Subject: [PATCH 2/2] [PAC][clang][ELF] Support PAuth ABI compatibility tag

Emit PAuth ABI compatibility tag values as llvm module flags:
- `aarch64-elf-pauthabi-platform`
- `aarch64-elf-pauthabi-version`
---
 clang/lib/CodeGen/CodeGenModule.cpp       | 15 ++++++
 clang/test/CodeGen/aarch64-elf-pauthabi.c | 61 +++++++++++++++++++++++
 2 files changed, 76 insertions(+)
 create mode 100644 clang/test/CodeGen/aarch64-elf-pauthabi.c

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 967319bdfc4571..36b1d2caf495af 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -53,6 +53,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/BinaryFormat/ELF.h"
 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
 #include "llvm/IR/AttributeMask.h"
 #include "llvm/IR/CallingConv.h"
@@ -1161,6 +1162,20 @@ void CodeGenModule::Release() {
     if (!LangOpts.isSignReturnAddressWithAKey())
       getModule().addModuleFlag(llvm::Module::Min,
                                 "sign-return-address-with-bkey", 1);
+
+    if (getTriple().isOSLinux() && getTriple().isOSBinFormatELF()) {
+      uint64_t PAuthABIVersion = 0;
+      for (size_t I = 0; I < sizeof(LangOpts.PointerAuth.Flags); ++I)
+        PAuthABIVersion |= LangOpts.PointerAuth.Flags[I] << I;
+      if (PAuthABIVersion != 0) {
+        getModule().addModuleFlag(llvm::Module::Error,
+                                  "aarch64-elf-pauthabi-platform",
+                                  llvm::ELF::AARCH64_PAUTH_PLATFORM_LLVM_LINUX);
+        getModule().addModuleFlag(llvm::Module::Error,
+                                  "aarch64-elf-pauthabi-version",
+                                  PAuthABIVersion);
+      }
+    }
   }
 
   if (CodeGenOpts.StackClashProtector)
diff --git a/clang/test/CodeGen/aarch64-elf-pauthabi.c b/clang/test/CodeGen/aarch64-elf-pauthabi.c
new file mode 100644
index 00000000000000..8f3e2d9b274b5a
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-elf-pauthabi.c
@@ -0,0 +1,61 @@
+// RUN: %clang -target aarch64-linux -S -emit-llvm -o - \
+// RUN:   -fptrauth-intrinsics \
+// RUN:   -fptrauth-calls \
+// RUN:   -fptrauth-returns \
+// RUN:   -fptrauth-auth-traps \
+// RUN:   -fptrauth-vtable-pointer-address-discrimination \
+// RUN:   -fptrauth-vtable-pointer-type-discrimination \
+// RUN:   -fptrauth-init-fini %s | \
+// RUN:   FileCheck %s --check-prefix=ALL
+
+// RUN: %clang -target aarch64-linux -S -emit-llvm -o - \
+// RUN:   -fptrauth-intrinsics %s | FileCheck %s --check-prefix=INTRIN
+
+// RUN: %clang -target aarch64-linux -S -emit-llvm -o - \
+// RUN:   -fptrauth-calls %s | FileCheck %s --check-prefix=CALL
+
+// RUN: %clang -target aarch64-linux -S -emit-llvm -o - \
+// RUN:   -fptrauth-returns %s | FileCheck %s --check-prefix=RET
+
+// RUN: %clang -target aarch64-linux -S -emit-llvm -o - \
+// RUN:   -fptrauth-auth-traps %s | FileCheck %s --check-prefix=TRAP
+
+// RUN: %clang -target aarch64-linux -S -emit-llvm -o - \
+// RUN:   -fptrauth-calls -fptrauth-vtable-pointer-address-discrimination %s | \
+// RUN:   FileCheck %s --check-prefix=VPTRADDR
+
+// RUN: %clang -target aarch64-linux -S -emit-llvm -o - \
+// RUN:   -fptrauth-calls -fptrauth-vtable-pointer-type-discrimination %s | \
+// RUN:   FileCheck %s --check-prefix=VPTRTYPE
+
+// RUN: %clang -target aarch64-linux -S -emit-llvm -o - \
+// RUN:   -fptrauth-calls -fptrauth-init-fini %s | \
+// RUN:   FileCheck %s --check-prefix=INITFINI
+
+// REQUIRES: aarch64-registered-target
+
+// ALL: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458}
+// ALL: !{i32 1, !"aarch64-elf-pauthabi-version", i32 127}
+
+// INTRIN: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458}
+// INTRIN: !{i32 1, !"aarch64-elf-pauthabi-version", i32 1}
+
+// CALL: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458}
+// CALL: !{i32 1, !"aarch64-elf-pauthabi-version", i32 2}
+
+// RET: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458}
+// RET: !{i32 1, !"aarch64-elf-pauthabi-version", i32 4}
+
+// TRAP: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458}
+// TRAP: !{i32 1, !"aarch64-elf-pauthabi-version", i32 8}
+
+// VPTRADDR: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458}
+// VPTRADDR: !{i32 1, !"aarch64-elf-pauthabi-version", i32 18}
+
+// VPTRTYPE: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458}
+// VPTRTYPE: !{i32 1, !"aarch64-elf-pauthabi-version", i32 34}
+
+// INITFINI: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458}
+// INITFINI: !{i32 1, !"aarch64-elf-pauthabi-version", i32 66}
+
+void foo() {}



More information about the cfe-commits mailing list