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 <dkova...@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 <ah...@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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits