[clang] [PAC][clang] Define ptrauth driver flags and preprocessor features (PR #85232)
Daniil Kovalev via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 14 07:56:47 PDT 2024
https://github.com/kovdan01 updated https://github.com/llvm/llvm-project/pull/85232
>From 1394471c06458bd9de1935d3d546348ba392b452 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] [PAC][clang] Define ptrauth driver flags and preprocessor
features
Define the following clang driver flags:
- `-fptrauth-intrinsics`: `PointerAuthIntrinsics` in `LangOptions`,
`ptrauth_intrinsics` preprocessor feature;
- `-fptrauth-calls`: `PointerAuthCalls` in `LangOptions`, `ptrauth_calls` and
`ptrauth_member_function_pointer_type_discrimination` preprocessor features;
- `-fptrauth-returns`: `PointerAuthReturns` in `LangOptions`,
`ptrauth_returns` preprocessor feature;
- `-fptrauth-auth-traps`: `PointerAuthAuthTraps` in `LangOptions`;
- `-fptrauth-vtable-pointer-address-discrimination`:
`PointerAuthVTPtrAddressDiscrimination` in `LangOptions`,
`ptrauth_vtable_pointer_address_discrimination` preprocessor feature;
- `-fptrauth-vtable-pointer-type-discrimination`:
`PointerAuthVTPtrTypeDiscrimination` in `LangOptions`,
`ptrauth_vtable_pointer_type_discrimination` preprocessor feature;
- `-fptrauth-init-fini`: `PointerAuthInitFini` 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.def | 8 ++
clang/include/clang/Driver/Options.td | 26 +++++
clang/lib/Driver/ToolChains/Clang.cpp | 31 ++++++
clang/lib/Frontend/CompilerInvocation.cpp | 33 +++++++
clang/test/Driver/ptrauth.c | 32 ++++++
clang/test/Preprocessor/ptrauth.c | 113 ++++++++++++++++++++++
7 files changed, 250 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..1c6236aa4f9748 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.PointerAuthIntrinsics)
+FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls)
+FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns)
+FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination)
+FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination)
+FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls)
+FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini)
FEATURE(swiftasynccc,
PP.getTargetInfo().checkCallingConvention(CC_SwiftAsync) ==
clang::TargetInfo::CCCR_OK)
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 472fd9f093a718..4b99e70298462f 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -161,6 +161,14 @@ LANGOPT(DllExportInlines , 1, 1, "dllexported classes dllexport inline methods"
LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of template template arguments")
LANGOPT(ExperimentalLibrary, 1, 0, "enable unstable and experimental library features")
+LANGOPT(PointerAuthIntrinsics, 1, 0, "pointer authentication intrinsics")
+LANGOPT(PointerAuthCalls , 1, 0, "function pointer authentication")
+LANGOPT(PointerAuthReturns, 1, 0, "return pointer authentication")
+LANGOPT(PointerAuthAuthTraps, 1, 0, "pointer authentication failure traps")
+LANGOPT(PointerAuthVTPtrAddressDiscrimination, 1, 0, "incorporate address discrimination in authenticated vtable pointers")
+LANGOPT(PointerAuthVTPtrTypeDiscrimination, 1, 0, "incorporate type discrimination in authenticated vtable pointers")
+LANGOPT(PointerAuthInitFini, 1, 0, "sign function pointers in init/fini arrays")
+
LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes")
COMPATIBLE_LANGOPT(RecoveryAST, 1, 1, "Preserve expressions in AST when encountering errors")
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..dd8bdfe07b0fa2 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7182,6 +7182,37 @@ 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..988f1ef3f0a1e1 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.PointerAuthIntrinsics)
+ GenerateArg(Consumer, OPT_fptrauth_intrinsics);
+ if (Opts.PointerAuthCalls)
+ GenerateArg(Consumer, OPT_fptrauth_calls);
+ if (Opts.PointerAuthReturns)
+ GenerateArg(Consumer, OPT_fptrauth_returns);
+ if (Opts.PointerAuthAuthTraps)
+ GenerateArg(Consumer, OPT_fptrauth_auth_traps);
+ if (Opts.PointerAuthVTPtrAddressDiscrimination)
+ GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_address_discrimination);
+ if (Opts.PointerAuthVTPtrTypeDiscrimination)
+ GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination);
+ if (Opts.PointerAuthInitFini)
+ GenerateArg(Consumer, OPT_fptrauth_init_fini);
+}
+
+static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
+ DiagnosticsEngine &Diags) {
+ Opts.PointerAuthIntrinsics = Args.hasArg(OPT_fptrauth_intrinsics);
+ Opts.PointerAuthCalls = Args.hasArg(OPT_fptrauth_calls);
+ Opts.PointerAuthReturns = Args.hasArg(OPT_fptrauth_returns);
+ Opts.PointerAuthAuthTraps = Args.hasArg(OPT_fptrauth_auth_traps);
+ Opts.PointerAuthVTPtrAddressDiscrimination =
+ Args.hasArg(OPT_fptrauth_vtable_pointer_address_discrimination);
+ Opts.PointerAuthVTPtrTypeDiscrimination =
+ Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination);
+ Opts.PointerAuthInitFini = 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
More information about the cfe-commits
mailing list