Skip to content

[AArch64][PAC] Support ptrauth builtins and -fptrauth-intrinsics. #65996

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

Merged
Merged
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
5 changes: 5 additions & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Clang Language Extensions
BlockLanguageSpec
Block-ABI-Apple
AutomaticReferenceCounting
PointerAuthentication
MatrixTypes

Introduction
Expand Down Expand Up @@ -4318,6 +4319,10 @@ reordering of memory accesses and side effect instructions. Other instructions
like simple arithmetic may be reordered around the intrinsic. If you expect to
have no reordering at all, use inline assembly instead.

Pointer Authentication
^^^^^^^^^^^^^^^^^^^^^^
See :doc:`PointerAuthentication`.

X86/X86-64 Language Extensions
------------------------------

Expand Down
485 changes: 485 additions & 0 deletions clang/docs/PointerAuthentication.rst

Large diffs are not rendered by default.

37 changes: 37 additions & 0 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -4354,6 +4354,43 @@ def CoroSuspend : CoroLangBuiltin {
let Prototype = "char(_Constant bool)";
}

// Pointer authentication builtins.
def PtrauthStrip : Builtin {
let Spellings = ["__builtin_ptrauth_strip"];
let Attributes = [CustomTypeChecking, NoThrow, Const];
let Prototype = "void*(void*,int)";
}

def PtrauthBlendDiscriminator : Builtin {
let Spellings = ["__builtin_ptrauth_blend_discriminator"];
let Attributes = [CustomTypeChecking, NoThrow, Const];
let Prototype = "size_t(void*,int)";
}

def PtrauthSignUnauthenticated : Builtin {
let Spellings = ["__builtin_ptrauth_sign_unauthenticated"];
let Attributes = [CustomTypeChecking, NoThrow, Const];
let Prototype = "void*(void*,int,void*)";
}

def PtrauthSignGenericData : Builtin {
let Spellings = ["__builtin_ptrauth_sign_generic_data"];
let Attributes = [CustomTypeChecking, NoThrow, Const];
let Prototype = "size_t(void*,void*)";
}

def PtrauthAuthAndResign : Builtin {
let Spellings = ["__builtin_ptrauth_auth_and_resign"];
let Attributes = [CustomTypeChecking, NoThrow];
let Prototype = "void*(void*,int,void*,int,void*)";
}

def PtrauthAuth : Builtin {
let Spellings = ["__builtin_ptrauth_auth"];
let Attributes = [CustomTypeChecking, NoThrow];
let Prototype = "void*(void*,int,void*)";
}

// OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions.
// We need the generic prototype, since the packet type could be anything.
def ReadPipe : OCLPipeLangBuiltin {
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,7 @@ def ZeroLengthArray : DiagGroup<"zero-length-array">;
def GNUZeroLineDirective : DiagGroup<"gnu-zero-line-directive">;
def GNUZeroVariadicMacroArguments : DiagGroup<"gnu-zero-variadic-macro-arguments">;
def MisleadingIndentation : DiagGroup<"misleading-indentation">;
def PtrAuthNullPointers : DiagGroup<"ptrauth-null-pointers">;

// This covers both the deprecated case (in C++98)
// and the extension case (in C++11 onwards).
Expand Down
16 changes: 16 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,22 @@ def warn_fortify_scanf_overflow : Warning<
def err_function_start_invalid_type: Error<
"argument must be a function">;

def err_ptrauth_disabled :
Error<"this target does not support pointer authentication">;
def err_ptrauth_invalid_key :
Error<"%0 does not identify a valid pointer authentication key for "
"the current target">;
def err_ptrauth_value_bad_type :
Error<"%select{signed value|extra discriminator|blended pointer|blended "
"integer}0 must have %select{pointer|integer|pointer or integer}1 "
"type; type here is %2">;
def warn_ptrauth_sign_null_pointer :
Warning<"signing a null pointer will yield a non-null pointer">,
InGroup<PtrAuthNullPointers>;
def warn_ptrauth_auth_null_pointer :
Warning<"authenticating a null pointer will almost certainly trap">,
InGroup<PtrAuthNullPointers>;

/// main()
// static main() is not an error in C, just in C++.
def warn_static_main : Warning<"'main' should not be declared static">,
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ 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(swiftasynccc,
PP.getTargetInfo().checkCallingConvention(CC_SwiftAsync) ==
clang::TargetInfo::CCCR_OK)
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ 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(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes")

COMPATIBLE_LANGOPT(RecoveryAST, 1, 1, "Preserve expressions in AST when encountering errors")
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "clang/Basic/TargetOptions.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SmallSet.h"
Expand Down Expand Up @@ -1571,6 +1572,11 @@ class TargetInfo : public TransferrableTargetInfo,
return getAddressSpaceMap()[(unsigned)AS];
}

/// Determine whether the given pointer-authentication key is valid.
///
/// The value has been coerced to type 'int'.
virtual bool validatePointerAuthKey(const llvm::APSInt &value) const;

/// Map from the address space field in builtin description strings to the
/// language address space.
virtual LangAS getOpenCLBuiltinAddressSpace(unsigned AS) const {
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4106,6 +4106,14 @@ 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 fno_ptrauth_intrinsics : Flag<["-"], "fno-ptrauth-intrinsics">;
}

def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Enable matrix data type and related builtin functions">,
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -3063,6 +3063,8 @@ class Sema final {
TemplateIdAnnotation *TemplateId,
bool IsMemberSpecialization);

bool checkConstantPointerAuthKey(Expr *keyExpr, unsigned &key);

void DiagnoseFunctionSpecifiers(const DeclSpec &DS);
NamedDecl *getShadowedDeclaration(const TypedefNameDecl *D,
const LookupResult &R);
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,10 @@ bool TargetInfo::validateInputConstraint(
return true;
}

bool TargetInfo::validatePointerAuthKey(const llvm::APSInt &value) const {
return false;
}

void TargetInfo::CheckFixedPointBits() const {
// Check that the number of fractional and integral bits (and maybe sign) can
// fit into the bits given for a fixed point type.
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
Expand Down Expand Up @@ -1450,6 +1451,11 @@ int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
return -1;
}

bool AArch64TargetInfo::validatePointerAuthKey(
const llvm::APSInt &value) const {
return 0 <= value && value <= 3;
}

bool AArch64TargetInfo::hasInt128Type() const { return true; }

AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/AArch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {

int getEHDataRegisterNumber(unsigned RegNo) const override;

bool validatePointerAuthKey(const llvm::APSInt &value) const override;

const char *getBFloat16Mangling() const override { return "u6__bf16"; };
bool hasInt128Type() const override;

Expand Down
67 changes: 67 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5208,6 +5208,73 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__iso_volatile_store64:
return RValue::get(EmitISOVolatileStore(*this, E));

case Builtin::BI__builtin_ptrauth_auth:
case Builtin::BI__builtin_ptrauth_auth_and_resign:
case Builtin::BI__builtin_ptrauth_blend_discriminator:
case Builtin::BI__builtin_ptrauth_sign_generic_data:
case Builtin::BI__builtin_ptrauth_sign_unauthenticated:
case Builtin::BI__builtin_ptrauth_strip: {
// Emit the arguments.
SmallVector<llvm::Value *, 5> Args;
for (auto argExpr : E->arguments())
Args.push_back(EmitScalarExpr(argExpr));

// Cast the value to intptr_t, saving its original type.
llvm::Type *OrigValueType = Args[0]->getType();
if (OrigValueType->isPointerTy())
Args[0] = Builder.CreatePtrToInt(Args[0], IntPtrTy);

switch (BuiltinID) {
case Builtin::BI__builtin_ptrauth_auth_and_resign:
if (Args[4]->getType()->isPointerTy())
Args[4] = Builder.CreatePtrToInt(Args[4], IntPtrTy);
LLVM_FALLTHROUGH;

case Builtin::BI__builtin_ptrauth_auth:
case Builtin::BI__builtin_ptrauth_sign_unauthenticated:
if (Args[2]->getType()->isPointerTy())
Args[2] = Builder.CreatePtrToInt(Args[2], IntPtrTy);
break;

case Builtin::BI__builtin_ptrauth_sign_generic_data:
if (Args[1]->getType()->isPointerTy())
Args[1] = Builder.CreatePtrToInt(Args[1], IntPtrTy);
break;

case Builtin::BI__builtin_ptrauth_blend_discriminator:
case Builtin::BI__builtin_ptrauth_strip:
break;
}

// Call the intrinsic.
auto IntrinsicID = [&]() -> unsigned {
switch (BuiltinID) {
case Builtin::BI__builtin_ptrauth_auth:
return llvm::Intrinsic::ptrauth_auth;
case Builtin::BI__builtin_ptrauth_auth_and_resign:
return llvm::Intrinsic::ptrauth_resign;
case Builtin::BI__builtin_ptrauth_blend_discriminator:
return llvm::Intrinsic::ptrauth_blend;
case Builtin::BI__builtin_ptrauth_sign_generic_data:
return llvm::Intrinsic::ptrauth_sign_generic;
case Builtin::BI__builtin_ptrauth_sign_unauthenticated:
return llvm::Intrinsic::ptrauth_sign;
case Builtin::BI__builtin_ptrauth_strip:
return llvm::Intrinsic::ptrauth_strip;
}
llvm_unreachable("bad ptrauth intrinsic");
}();
auto Intrinsic = CGM.getIntrinsic(IntrinsicID);
llvm::Value *Result = EmitRuntimeCall(Intrinsic, Args);

if (BuiltinID != Builtin::BI__builtin_ptrauth_sign_generic_data &&
BuiltinID != Builtin::BI__builtin_ptrauth_blend_discriminator &&
OrigValueType->isPointerTy()) {
Result = Builder.CreateIntToPtr(Result, OrigValueType);
}
return RValue::get(Result);
}

case Builtin::BI__exception_code:
case Builtin::BI_exception_code:
return RValue::get(EmitSEHExceptionCode());
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7199,6 +7199,10 @@ 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");

// -fsigned-bitfields is default, and clang doesn't yet support
// -funsigned-bitfields.
if (!Args.hasFlag(options::OPT_fsigned_bitfields,
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3293,6 +3293,17 @@ 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);
}

static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags) {
Opts.PointerAuthIntrinsics = Args.hasArg(OPT_fptrauth_intrinsics);
}

/// Check if input file kind and language standard are compatible.
static bool IsInputCompatibleWithStandard(InputKind IK,
const LangStandard &S) {
Expand Down Expand Up @@ -4613,6 +4624,8 @@ bool CompilerInvocation::CreateFromArgsImpl(
Res.getFileSystemOpts().WorkingDir);
ParseAPINotesArgs(Res.getAPINotesOpts(), Args, Diags);

ParsePointerAuthArgs(LangOpts, Args, Diags);

ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes,
Diags);
if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
Expand Down Expand Up @@ -4843,6 +4856,7 @@ void CompilerInvocationBase::generateCC1CommandLine(
GenerateTargetArgs(getTargetOpts(), Consumer);
GenerateHeaderSearchArgs(getHeaderSearchOpts(), Consumer);
GenerateAPINotesArgs(getAPINotesOpts(), Consumer);
GeneratePointerAuthArgs(getLangOpts(), Consumer);
GenerateLangArgs(getLangOpts(), Consumer, T, getFrontendOpts().DashX);
GenerateCodeGenArgs(getCodeGenOpts(), Consumer, T,
getFrontendOpts().OutputFile, &getLangOpts());
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Headers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ set(x86_files
popcntintrin.h
prfchiintrin.h
prfchwintrin.h
ptrauth.h
ptwriteintrin.h
raointintrin.h
rdpruintrin.h
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Headers/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -315,3 +315,8 @@ module opencl_c {
header "opencl-c.h"
header "opencl-c-base.h"
}

module ptrauth {
header "ptrauth.h"
export *
}
Loading