Skip to content

[PAC][clang] Define ptrauth driver flags and preprocessor features #85232

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions clang/include/clang/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
26 changes: 26 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">,
Expand Down
31 changes: 31 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
33 changes: 33 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
32 changes: 32 additions & 0 deletions clang/test/Driver/ptrauth.c
Original file line number Diff line number Diff line change
@@ -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"
113 changes: 113 additions & 0 deletions clang/test/Preprocessor/ptrauth.c
Original file line number Diff line number Diff line change
@@ -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