Skip to content
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

[PAC][AArch64][ELF] Support signed GOT #77

Open
wants to merge 9 commits into
base: dkovalev/main
Choose a base branch
from
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,10 @@ def warn_drv_fjmc_for_elf_only : Warning<
"-fjmc works only for ELF; option ignored">,
InGroup<OptionIgnored>;

def warn_drv_ptrauth_elf_got_for_elf_only : Warning<
"-fptrauth-elf-got works only for ELF; option ignored">,
InGroup<OptionIgnored>;

def warn_target_override_arm64ec : Warning<
"/arm64EC has been overridden by specified target: %0; option ignored">,
InGroup<OptionIgnored>;
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ 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(ptrauth_elf_got, LangOpts.PointerAuthELFGOT)
EXTENSION(swiftcc,
PP.getTargetInfo().checkCallingConvention(CC_Swift) ==
clang::TargetInfo::CCCR_OK)
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@ LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of template t
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(PointerAuthELFGOT, 1, 0, "authenticate pointers from GOT")

LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes")

Expand Down
9 changes: 9 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4148,6 +4148,15 @@ defm strict_return : BoolFOption<"strict-return",

let Flags = [TargetSpecific] in {
defm ptrauth_intrinsics : OptInCC1FFlag<"ptrauth-intrinsics", "Enable pointer authentication intrinsics">;
defm ptrauth_calls : OptInCC1FFlag<"ptrauth-calls", "Enable signing and authentication of all indirect calls">;
defm ptrauth_returns : OptInCC1FFlag<"ptrauth-returns", "Enable signing and authentication of return addresses">;
defm ptrauth_auth_traps : OptInCC1FFlag<"ptrauth-auth-traps", "Enable traps on authentication failures">;
defm ptrauth_vtable_pointer_address_discrimination :
OptInCC1FFlag<"ptrauth-vtable-pointer-address-discrimination", "Enable address discrimination of vtable pointers">;
defm ptrauth_vtable_pointer_type_discrimination :
OptInCC1FFlag<"ptrauth-vtable-pointer-type-discrimination", "Enable type discrimination of vtable pointers">;
defm ptrauth_init_fini : OptInCC1FFlag<"ptrauth-init-fini", "Enable signing of function pointers in init/fini arrays">;
defm ptrauth_elf_got : OptInCC1FFlag<"ptrauth-elf-got", "Enable authentication of pointers from GOT (ELF only)">;
}

def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
Expand Down
33 changes: 33 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1189,6 +1190,38 @@ void CodeGenModule::Release() {
if (!LangOpts.isSignReturnAddressWithAKey())
getModule().addModuleFlag(llvm::Module::Min,
"sign-return-address-with-bkey", 1);

if (getTriple().isOSLinux() && getTriple().isOSBinFormatELF()) {
using namespace llvm::ELF;
uint64_t PAuthABIVersion =
(LangOpts.PointerAuthIntrinsics
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INTRINSICS) |
(LangOpts.PointerAuthCalls
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_CALLS) |
(LangOpts.PointerAuthReturns
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_RETURNS) |
(LangOpts.PointerAuthAuthTraps
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_AUTHTRAPS) |
(LangOpts.PointerAuthVTPtrAddressDiscrimination
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRADDRDISCR) |
(LangOpts.PointerAuthVTPtrTypeDiscrimination
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRTYPEDISCR) |
(LangOpts.PointerAuthInitFini
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI) |
(LangOpts.PointerAuthELFGOT
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT);
static_assert(AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT ==
AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST,
"Update when new enum items are defined");
if (PAuthABIVersion != 0) {
getModule().addModuleFlag(llvm::Module::Error,
"aarch64-elf-pauthabi-platform",
AARCH64_PAUTH_PLATFORM_LLVM_LINUX);
getModule().addModuleFlag(llvm::Module::Error,
"aarch64-elf-pauthabi-version",
PAuthABIVersion);
}
}
}

if (CodeGenOpts.StackClashProtector)
Expand Down
27 changes: 27 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1782,6 +1782,33 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,

Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_intrinsics,
options::OPT_fno_ptrauth_intrinsics);

Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_calls,
options::OPT_fno_ptrauth_calls);

Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_returns,
options::OPT_fno_ptrauth_returns);

Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_auth_traps,
options::OPT_fno_ptrauth_auth_traps);

Args.addOptInFlag(
CmdArgs, options::OPT_fptrauth_vtable_pointer_address_discrimination,
options::OPT_fno_ptrauth_vtable_pointer_address_discrimination);

Args.addOptInFlag(
CmdArgs, options::OPT_fptrauth_vtable_pointer_type_discrimination,
options::OPT_fno_ptrauth_vtable_pointer_type_discrimination);

Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_init_fini,
options::OPT_fno_ptrauth_init_fini);

Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_elf_got,
options::OPT_fno_ptrauth_elf_got);

if (Args.hasArg(options::OPT_fptrauth_elf_got))
getToolChain().getDriver().Diag(
diag::warn_drv_ptrauth_elf_got_for_elf_only);
}

void Clang::AddLoongArchTargetArgs(const ArgList &Args,
Expand Down
24 changes: 24 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3319,11 +3319,34 @@ 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);
if (Opts.PointerAuthELFGOT)
GenerateArg(Consumer, OPT_fptrauth_elf_got);
}

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);
Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got);
}

/// Check if input file kind and language standard are compatible.
Expand Down Expand Up @@ -4677,6 +4700,7 @@ bool CompilerInvocation::CreateFromArgsImpl(
ParseAPINotesArgs(Res.getAPINotesOpts(), Args, Diags);

ParsePointerAuthArgs(LangOpts, Args, Diags);
LangOpts.PointerAuthELFGOT &= T.isOSBinFormatELF();

ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes,
Diags);
Expand Down
66 changes: 66 additions & 0 deletions clang/test/CodeGen/aarch64-elf-pauthabi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// 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 \
// RUN: -fptrauth-elf-got %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

// RUN: %clang --target=aarch64-linux -S -emit-llvm -o - \
// RUN: -fptrauth-elf-got %s | FileCheck %s --check-prefix=ELFGOT

// ALL: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458}
// ALL: !{i32 1, !"aarch64-elf-pauthabi-version", i32 255}

// 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}

// ELFGOT: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458}
// ELFGOT: !{i32 1, !"aarch64-elf-pauthabi-version", i32 128}

void foo() {}
43 changes: 41 additions & 2 deletions clang/test/Driver/aarch64-ptrauth.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,44 @@
// RUN: %clang -### -c --target=aarch64 %s 2>&1 | FileCheck %s --check-prefix NONE
// NONE: "-cc1"
// NONE-NOT: "-fptrauth-

// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-intrinsics -fptrauth-intrinsics %s 2>&1 | FileCheck %s --check-prefix=INTRIN
// INTRIN: "-cc1"{{.*}} "-fptrauth-intrinsics"

// RUN: not %clang -### -c --target=x86_64 -fptrauth-intrinsics %s 2>&1 | FileCheck %s --check-prefix=ERR
// ERR: error: unsupported option '-fptrauth-intrinsics' for target '{{.*}}'
// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-calls -fptrauth-calls %s 2>&1 | FileCheck %s --check-prefix=CALL
// CALL: "-cc1"{{.*}} "-fptrauth-calls"

// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-returns -fptrauth-returns %s 2>&1 | FileCheck %s --check-prefix=RETURN
// RETURN: "-cc1"{{.*}} "-fptrauth-returns"

// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-auth-traps -fptrauth-auth-traps %s 2>&1 | FileCheck %s --check-prefix=TRAP
// TRAP: "-cc1"{{.*}} "-fptrauth-auth-traps"

// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-vtable-pointer-address-discrimination \
// RUN: -fptrauth-vtable-pointer-address-discrimination %s 2>&1 | FileCheck %s --check-prefix=VPTRADDR
// VPTRADDR: "-cc1"{{.*}} "-fptrauth-vtable-pointer-address-discrimination"

// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-vtable-pointer-type-discrimination \
// RUN: -fptrauth-vtable-pointer-type-discrimination %s 2>&1 | FileCheck %s --check-prefix=VPTRTYPE
// VPTRTYPE: "-cc1"{{.*}} "-fptrauth-vtable-pointer-type-discrimination"

// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-init-fini -fptrauth-init-fini %s 2>&1 | FileCheck %s --check-prefix=INITFINI
// INITFINI: "-cc1"{{.*}} "-fptrauth-init-fini"

// RUN: %clang -### -c --target=aarch64-elf -fno-ptrauth-elf-got -fptrauth-elf-got %s 2>&1 | FileCheck %s --check-prefix=ELFGOT
// ELFGOT: "-cc1"{{.*}} "-fptrauth-elf-got"

// RUN: %clang -### -c --target=aarch64-darwin -fptrauth-elf-got %s 2>&1 | FileCheck %s --check-prefix=NOELFGOT
// NOELFGOT: warning: -fptrauth-elf-got works only for ELF; option ignored [-Woption-ignored]

// RUN: not %clang -### -c --target=x86_64 -fptrauth-intrinsics -fptrauth-calls -fptrauth-returns -fptrauth-auth-traps \
// RUN: -fptrauth-vtable-pointer-address-discrimination -fptrauth-vtable-pointer-type-discrimination \
// RUN: -fptrauth-init-fini -fptrauth-elf-got %s 2>&1 | FileCheck %s --check-prefix=ERR
// ERR: error: unsupported option '-fptrauth-intrinsics' for target '{{.*}}'
// ERR-NEXT: error: unsupported option '-fptrauth-calls' for target '{{.*}}'
// ERR-NEXT: error: unsupported option '-fptrauth-returns' for target '{{.*}}'
// ERR-NEXT: error: unsupported option '-fptrauth-auth-traps' for target '{{.*}}'
// ERR-NEXT: error: unsupported option '-fptrauth-vtable-pointer-address-discrimination' for target '{{.*}}'
// ERR-NEXT: error: unsupported option '-fptrauth-vtable-pointer-type-discrimination' for target '{{.*}}'
// ERR-NEXT: error: unsupported option '-fptrauth-init-fini' for target '{{.*}}'
// ERR-NEXT: error: unsupported option '-fptrauth-elf-got' for target '{{.*}}'
Loading