-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] Implement function pointer signing and authenticated function calls #93906
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
Conversation
@llvm/pr-subscribers-clang-driver @llvm/pr-subscribers-clang-codegen Author: Ahmed Bougacha (ahmedbougacha) ChangesThe functions are currently always signed/authenticated with zero discriminator. Co-Authored-By: John McCall <[email protected]> Patch is 37.62 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/93906.diff 24 Files Affected:
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index 9469a424045bb..502722a6ec4eb 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_BASIC_CODEGENOPTIONS_H
#define LLVM_CLANG_BASIC_CODEGENOPTIONS_H
+#include "clang/Basic/PointerAuthOptions.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/XRayInstr.h"
#include "llvm/ADT/FloatingPointMode.h"
@@ -388,6 +389,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
std::vector<std::string> Reciprocals;
+ /// Configuration for pointer-signing.
+ PointerAuthOptions PointerAuth;
+
/// The preferred width for auto-vectorization transforms. This is intended to
/// override default transforms based on the width of the architected vector
/// registers.
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 773b234cd68fe..6cbb0c8401c15 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -351,6 +351,9 @@ def err_drv_omp_host_ir_file_not_found : Error<
"target regions but cannot be found">;
def err_drv_omp_host_target_not_supported : Error<
"target '%0' is not a supported OpenMP host target">;
+def err_drv_ptrauth_not_supported : Error<
+ "target '%0' does not support native pointer authentication">;
+
def err_drv_expecting_fopenmp_with_fopenmp_targets : Error<
"'-fopenmp-targets' must be used in conjunction with a '-fopenmp' option "
"compatible with offloading; e.g., '-fopenmp=libomp' or '-fopenmp=libiomp5'">;
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 75e88afbd9705..5216822e45b1b 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -346,6 +346,8 @@ class LangOptionsBase {
BKey
};
+ using PointerAuthenticationMode = ::clang::PointerAuthenticationMode;
+
enum class ThreadModelKind {
/// POSIX Threads.
POSIX,
diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h
index e5cdcc31ebfb7..32b179e3f9460 100644
--- a/clang/include/clang/Basic/PointerAuthOptions.h
+++ b/clang/include/clang/Basic/PointerAuthOptions.h
@@ -14,10 +14,146 @@
#ifndef LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
#define LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetOptions.h"
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
namespace clang {
constexpr unsigned PointerAuthKeyNone = -1;
+class PointerAuthSchema {
+public:
+ enum class Kind : unsigned {
+ None,
+ ARM8_3,
+ };
+
+ /// Hardware pointer-signing keys in ARM8.3.
+ ///
+ /// These values are the same used in ptrauth.h.
+ enum class ARM8_3Key : unsigned {
+ ASIA = 0,
+ ASIB = 1,
+ ASDA = 2,
+ ASDB = 3
+ };
+
+ /// Forms of extra discrimination.
+ enum class Discrimination : unsigned {
+ /// No additional discrimination.
+ None,
+
+ /// Discriminate using a constant value.
+ Constant,
+ };
+
+private:
+ Kind TheKind : 2;
+ unsigned IsAddressDiscriminated : 1;
+ unsigned IsIsaPointer : 1;
+ unsigned AuthenticatesNullValues : 1;
+ PointerAuthenticationMode SelectedAuthenticationMode : 2;
+ Discrimination DiscriminationKind : 2;
+ unsigned Key : 4;
+ unsigned ConstantDiscriminator : 16;
+
+public:
+ PointerAuthSchema() : TheKind(Kind::None) {}
+
+ PointerAuthSchema(
+ ARM8_3Key Key, bool IsAddressDiscriminated,
+ PointerAuthenticationMode AuthenticationMode,
+ Discrimination OtherDiscrimination,
+ std::optional<uint16_t> ConstantDiscriminatorOrNone = std::nullopt,
+ bool IsIsaPointer = false, bool AuthenticatesNullValues = false)
+ : TheKind(Kind::ARM8_3), IsAddressDiscriminated(IsAddressDiscriminated),
+ IsIsaPointer(IsIsaPointer),
+ AuthenticatesNullValues(AuthenticatesNullValues),
+ SelectedAuthenticationMode(AuthenticationMode),
+ DiscriminationKind(OtherDiscrimination), Key(unsigned(Key)) {
+ assert((getOtherDiscrimination() != Discrimination::Constant ||
+ ConstantDiscriminatorOrNone) &&
+ "constant discrimination requires a constant!");
+ if (ConstantDiscriminatorOrNone)
+ ConstantDiscriminator = *ConstantDiscriminatorOrNone;
+ }
+
+ PointerAuthSchema(
+ ARM8_3Key Key, bool IsAddressDiscriminated,
+ Discrimination OtherDiscrimination,
+ std::optional<uint16_t> ConstantDiscriminatorOrNone = std::nullopt,
+ bool IsIsaPointer = false, bool AuthenticatesNullValues = false)
+ : PointerAuthSchema(Key, IsAddressDiscriminated,
+ PointerAuthenticationMode::SignAndAuth,
+ OtherDiscrimination, ConstantDiscriminatorOrNone,
+ IsIsaPointer, AuthenticatesNullValues) {}
+
+ Kind getKind() const { return TheKind; }
+
+ explicit operator bool() const { return isEnabled(); }
+
+ bool isEnabled() const { return getKind() != Kind::None; }
+
+ bool isAddressDiscriminated() const {
+ assert(getKind() != Kind::None);
+ return IsAddressDiscriminated;
+ }
+
+ bool isIsaPointer() const {
+ assert(getKind() != Kind::None);
+ return IsIsaPointer;
+ }
+
+ bool authenticatesNullValues() const {
+ assert(getKind() != Kind::None);
+ return AuthenticatesNullValues;
+ }
+
+ bool hasOtherDiscrimination() const {
+ return getOtherDiscrimination() != Discrimination::None;
+ }
+
+ Discrimination getOtherDiscrimination() const {
+ assert(getKind() != Kind::None);
+ return DiscriminationKind;
+ }
+
+ uint16_t getConstantDiscrimination() const {
+ assert(getOtherDiscrimination() == Discrimination::Constant);
+ return (uint16_t)ConstantDiscriminator;
+ }
+
+ unsigned getKey() const {
+ switch (getKind()) {
+ case Kind::None:
+ llvm_unreachable("calling getKey() on disabled schema");
+ case Kind::ARM8_3:
+ return unsigned(getARM8_3Key());
+ }
+ llvm_unreachable("bad key kind");
+ }
+
+ PointerAuthenticationMode getAuthenticationMode() const {
+ return SelectedAuthenticationMode;
+ }
+
+ ARM8_3Key getARM8_3Key() const {
+ assert(getKind() == Kind::ARM8_3);
+ return ARM8_3Key(Key);
+ }
+};
+
+struct PointerAuthOptions {
+ /// The ABI for C function pointers.
+ PointerAuthSchema FunctionPointers;
+};
+
} // end namespace clang
#endif
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index 1a2a39411e58d..e60e5aad6c70d 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -305,6 +305,16 @@ class CompilerInvocation : public CompilerInvocationBase {
/// executable), for finding the builtin compiler path.
static std::string GetResourcesPath(const char *Argv0, void *MainAddr);
+ /// Populate \p Opts with the default set of pointer authentication-related
+ /// options given \p LangOpts and \p Triple. Return true if defaults are
+ /// available.
+ ///
+ /// Note: This is intended to be used by tools which must be aware of
+ /// pointer authentication-related code generation, e.g. lldb.
+ static bool setDefaultPointerAuthOptions(PointerAuthOptions &Opts,
+ const LangOptions &LangOpts,
+ const llvm::Triple &Triple);
+
/// Retrieve a module hash string that is suitable for uniquely
/// identifying the conditions under which the module was built.
std::string getModuleHash() const;
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index b2e3b6fa64284..1f528f9490cd2 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5999,8 +5999,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// If this is a predefined lib function (e.g. malloc), emit the call
// using exactly the normal call path.
if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID))
- return emitLibraryCall(
- *this, FD, E, cast<llvm::Constant>(EmitScalarExpr(E->getCallee())));
+ return emitLibraryCall(*this, FD, E, CGM.getRawFunctionPointer(FD));
// Check that a call to a target specific builtin has the correct target
// features.
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 97449a5e51e73..c33f37bf5b8c4 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -5677,6 +5677,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
!isa_and_nonnull<FunctionDecl>(TargetDecl))
EmitKCFIOperandBundle(ConcreteCallee, BundleList);
+ // Add the pointer-authentication bundle.
+ EmitPointerAuthOperandBundle(ConcreteCallee.getPointerAuthInfo(), BundleList);
+
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl))
if (FD->hasAttr<StrictFPAttr>())
// All calls within a strictfp function are marked strictfp
diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h
index 6b676ac196db2..4b0e1561b4ef5 100644
--- a/clang/lib/CodeGen/CGCall.h
+++ b/clang/lib/CodeGen/CGCall.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_CGCALL_H
#define LLVM_CLANG_LIB_CODEGEN_CGCALL_H
+#include "CGPointerAuthInfo.h"
#include "CGValue.h"
#include "EHScopeStack.h"
#include "clang/AST/ASTFwd.h"
@@ -69,6 +70,10 @@ class CGCallee {
Last = Virtual
};
+ struct OrdinaryInfoStorage {
+ CGCalleeInfo AbstractInfo;
+ CGPointerAuthInfo PointerAuthInfo;
+ };
struct BuiltinInfoStorage {
const FunctionDecl *Decl;
unsigned ID;
@@ -85,7 +90,7 @@ class CGCallee {
SpecialKind KindOrFunctionPointer;
union {
- CGCalleeInfo AbstractInfo;
+ OrdinaryInfoStorage OrdinaryInfo;
BuiltinInfoStorage BuiltinInfo;
PseudoDestructorInfoStorage PseudoDestructorInfo;
VirtualInfoStorage VirtualInfo;
@@ -104,10 +109,13 @@ class CGCallee {
/// Construct a callee. Call this constructor directly when this
/// isn't a direct call.
- CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr)
+ CGCallee(
+ const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr,
+ const CGPointerAuthInfo &pointerAuthInfo = /*FIXME*/ CGPointerAuthInfo())
: KindOrFunctionPointer(
SpecialKind(reinterpret_cast<uintptr_t>(functionPtr))) {
- AbstractInfo = abstractInfo;
+ OrdinaryInfo.AbstractInfo = abstractInfo;
+ OrdinaryInfo.PointerAuthInfo = pointerAuthInfo;
assert(functionPtr && "configuring callee without function pointer");
assert(functionPtr->getType()->isPointerTy());
}
@@ -128,12 +136,12 @@ class CGCallee {
static CGCallee forDirect(llvm::Constant *functionPtr,
const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
- return CGCallee(abstractInfo, functionPtr);
+ return CGCallee(abstractInfo, functionPtr, CGPointerAuthInfo());
}
static CGCallee forDirect(llvm::FunctionCallee functionPtr,
const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
- return CGCallee(abstractInfo, functionPtr.getCallee());
+ return CGCallee(abstractInfo, functionPtr.getCallee(), CGPointerAuthInfo());
}
static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr,
@@ -173,7 +181,11 @@ class CGCallee {
if (isVirtual())
return VirtualInfo.MD;
assert(isOrdinary());
- return AbstractInfo;
+ return OrdinaryInfo.AbstractInfo;
+ }
+ const CGPointerAuthInfo &getPointerAuthInfo() const {
+ assert(isOrdinary());
+ return OrdinaryInfo.PointerAuthInfo;
}
llvm::Value *getFunctionPointer() const {
assert(isOrdinary());
@@ -184,6 +196,10 @@ class CGCallee {
KindOrFunctionPointer =
SpecialKind(reinterpret_cast<uintptr_t>(functionPtr));
}
+ void setPointerAuthInfo(CGPointerAuthInfo pointerAuth) {
+ assert(isOrdinary());
+ OrdinaryInfo.PointerAuthInfo = pointerAuth;
+ }
bool isVirtual() const {
return KindOrFunctionPointer == SpecialKind::Virtual;
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index d6478cc6835d8..152f51f5865e0 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -2850,22 +2850,22 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
return LV;
}
-static llvm::Constant *EmitFunctionDeclPointer(CodeGenModule &CGM,
- GlobalDecl GD) {
+llvm::Constant *CodeGenModule::getRawFunctionPointer(GlobalDecl GD,
+ llvm::Type *Ty) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
if (FD->hasAttr<WeakRefAttr>()) {
- ConstantAddress aliasee = CGM.GetWeakRefReference(FD);
+ ConstantAddress aliasee = GetWeakRefReference(FD);
return aliasee.getPointer();
}
- llvm::Constant *V = CGM.GetAddrOfFunction(GD);
+ llvm::Constant *V = GetAddrOfFunction(GD, Ty);
return V;
}
static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF, const Expr *E,
GlobalDecl GD) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
- llvm::Value *V = EmitFunctionDeclPointer(CGF.CGM, GD);
+ llvm::Constant *V = CGF.CGM.getFunctionPointer(GD);
CharUnits Alignment = CGF.getContext().getDeclAlign(FD);
return CGF.MakeAddrLValue(V, E->getType(), Alignment,
AlignmentSource::Decl);
@@ -5501,7 +5501,7 @@ static CGCallee EmitDirectCallee(CodeGenFunction &CGF, GlobalDecl GD) {
// name to make it clear it's not the actual builtin.
if (CGF.CurFn->getName() != FDInlineName &&
OnlyHasInlineBuiltinDeclaration(FD)) {
- llvm::Constant *CalleePtr = EmitFunctionDeclPointer(CGF.CGM, GD);
+ llvm::Constant *CalleePtr = CGF.CGM.getRawFunctionPointer(GD);
llvm::Function *Fn = llvm::cast<llvm::Function>(CalleePtr);
llvm::Module *M = Fn->getParent();
llvm::Function *Clone = M->getFunction(FDInlineName);
@@ -5524,7 +5524,7 @@ static CGCallee EmitDirectCallee(CodeGenFunction &CGF, GlobalDecl GD) {
return CGCallee::forBuiltin(builtinID, FD);
}
- llvm::Constant *CalleePtr = EmitFunctionDeclPointer(CGF.CGM, GD);
+ llvm::Constant *CalleePtr = CGF.CGM.getRawFunctionPointer(GD);
if (CGF.CGM.getLangOpts().CUDA && !CGF.CGM.getLangOpts().CUDAIsDevice &&
FD->hasAttr<CUDAGlobalAttr>())
CalleePtr = CGF.CGM.getCUDARuntime().getKernelStub(
@@ -5581,7 +5581,8 @@ CGCallee CodeGenFunction::EmitCallee(const Expr *E) {
GD = GlobalDecl(VD);
CGCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(), GD);
- CGCallee callee(calleeInfo, calleePtr);
+ CGPointerAuthInfo pointerAuth = CGM.getFunctionPointerAuthInfo(functionType);
+ CGCallee callee(calleeInfo, calleePtr, pointerAuth);
return callee;
}
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index de9380c0e63be..bfb545a2fe1f6 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -1956,8 +1956,25 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
if (D->hasAttr<WeakRefAttr>())
return CGM.GetWeakRefReference(D).getPointer();
+ auto PtrAuthSign = [&](llvm::Constant *C) {
+ CGPointerAuthInfo AuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
+
+ if (AuthInfo) {
+ if (hasNonZeroOffset())
+ return ConstantLValue(nullptr);
+
+ C = applyOffset(C);
+ C = CGM.getConstantSignedPointer(
+ C, AuthInfo.getKey(), nullptr,
+ cast_or_null<llvm::Constant>(AuthInfo.getDiscriminator()));
+ return ConstantLValue(C, /*applied offset*/ true);
+ }
+
+ return ConstantLValue(C);
+ };
+
if (auto FD = dyn_cast<FunctionDecl>(D))
- return CGM.GetAddrOfFunction(FD);
+ return PtrAuthSign(CGM.getRawFunctionPointer(FD));
if (auto VD = dyn_cast<VarDecl>(D)) {
// We can never refer to a variable with local storage.
diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp
index 756c00aa42c8c..adfa721ac89d3 100644
--- a/clang/lib/CodeGen/CGPointerAuth.cpp
+++ b/clang/lib/CodeGen/CGPointerAuth.cpp
@@ -28,6 +28,24 @@
using namespace clang;
using namespace CodeGen;
+/// Return the abstract pointer authentication schema for a pointer to the given
+/// function type.
+CGPointerAuthInfo CodeGenModule::getFunctionPointerAuthInfo(QualType T) {
+ auto &Schema = getCodeGenOpts().PointerAuth.FunctionPointers;
+ if (!Schema)
+ return CGPointerAuthInfo();
+
+ assert(!Schema.isAddressDiscriminated() &&
+ "function pointers cannot use address-specific discrimination");
+
+ assert(!Schema.hasOtherDiscrimination() &&
+ "function pointers don't support any discrimination yet");
+
+ return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
+ /*IsaPointer=*/false, /*AuthenticatesNull=*/false,
+ /*Discriminator=*/nullptr);
+}
+
/// Build a signed-pointer "ptrauth" constant.
static llvm::ConstantPtrAuth *
buildConstantAddress(CodeGenModule &CGM, llvm::Constant *pointer, unsigned key,
@@ -75,3 +93,36 @@ CodeGen::getConstantSignedPointer(CodeGenModule &CGM,
return CGM.getConstantSignedPointer(pointer, key, storageAddress,
otherDiscriminator);
}
+
+/// If applicable, sign a given constant function pointer with the ABI rules for
+/// functionType.
+llvm::Constant *CodeGenModule::getFunctionPointer(llvm::Constant *pointer,
+ QualType functionType,
+ GlobalDecl GD) {
+ assert(functionType->isFunctionType() ||
+ functionType->isFunctionReferenceType() ||
+ functionType->isFunctionPointerType());
+
+ if (auto pointerAuth = getFunctionPointerAuthInfo(functionType)) {
+ return getConstantSignedPointer(
+ pointer, pointerAuth.getKey(), nullptr,
+ cast_or_null<llvm::Constant>(pointerAuth.getDiscriminator()));
+ }
+
+ return pointer;
+}
+
+llvm::Constant *CodeGenModule::getFunctionPointer(GlobalDecl GD,
+ llvm::Type *Ty) {
+ const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+
+ // Annoyingly, K&R functions have prototypes in the clang AST, but
+ // expressions referring to them are unprototyped.
+ QualType FuncType = FD->getType();
+ if (!FD->hasPrototype())
+ if (const auto *Proto = FuncType->getAs<FunctionProtoType>())
+ FuncType = Context.getFunctionNoProtoType(Proto->getReturnType(),
+ Proto->getExtInfo());
+
+ return getFunctionPointer(getRawFunctionPointer(GD, Ty), FuncType, GD);
+}
diff --git a/clang/lib/CodeGen/CGPointerAuthInfo.h b/clang/lib/CodeGen/CGPointerAuthInfo.h
new file mode 100644
index 0000000000000..e870c3145acba
--- /dev/null
+++ b/clang/lib/CodeGen/CGPointerAuthInfo.h
@@ -0,0 +1,96 @@
+//===----- CGPointerAuthInfo.h - -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Pointer auth info class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_CGPOINTERAUTHINFO_H
+#define LLVM_CLANG_LIB_CODEGEN_CGPOINTERAUTHINFO_H
+
+#include "clang/AST/Type.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Value.h"
+
+namespace clang {
+namespace CodeGen {
+
+class CGPointerAuthInfo {
+private:
+ PointerAuthenticationMode AuthenticationMode : 2;
+ bool IsIsaPointer : 1;
+ bool AuthenticatesNullValues : 1;
+ unsigned Key : 28;
+ llvm::Value *Discriminator;
+
+public:
+ CGPointerAuthInfo()
+ : AuthenticationMode(PointerAuthenticationMode...
[truncated]
|
@llvm/pr-subscribers-backend-x86 Author: Ahmed Bougacha (ahmedbougacha) ChangesThe functions are currently always signed/authenticated with zero discriminator. Co-Authored-By: John McCall <[email protected]> Patch is 37.62 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/93906.diff 24 Files Affected:
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index 9469a424045bb..502722a6ec4eb 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_BASIC_CODEGENOPTIONS_H
#define LLVM_CLANG_BASIC_CODEGENOPTIONS_H
+#include "clang/Basic/PointerAuthOptions.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/XRayInstr.h"
#include "llvm/ADT/FloatingPointMode.h"
@@ -388,6 +389,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
std::vector<std::string> Reciprocals;
+ /// Configuration for pointer-signing.
+ PointerAuthOptions PointerAuth;
+
/// The preferred width for auto-vectorization transforms. This is intended to
/// override default transforms based on the width of the architected vector
/// registers.
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 773b234cd68fe..6cbb0c8401c15 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -351,6 +351,9 @@ def err_drv_omp_host_ir_file_not_found : Error<
"target regions but cannot be found">;
def err_drv_omp_host_target_not_supported : Error<
"target '%0' is not a supported OpenMP host target">;
+def err_drv_ptrauth_not_supported : Error<
+ "target '%0' does not support native pointer authentication">;
+
def err_drv_expecting_fopenmp_with_fopenmp_targets : Error<
"'-fopenmp-targets' must be used in conjunction with a '-fopenmp' option "
"compatible with offloading; e.g., '-fopenmp=libomp' or '-fopenmp=libiomp5'">;
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 75e88afbd9705..5216822e45b1b 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -346,6 +346,8 @@ class LangOptionsBase {
BKey
};
+ using PointerAuthenticationMode = ::clang::PointerAuthenticationMode;
+
enum class ThreadModelKind {
/// POSIX Threads.
POSIX,
diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h
index e5cdcc31ebfb7..32b179e3f9460 100644
--- a/clang/include/clang/Basic/PointerAuthOptions.h
+++ b/clang/include/clang/Basic/PointerAuthOptions.h
@@ -14,10 +14,146 @@
#ifndef LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
#define LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetOptions.h"
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
namespace clang {
constexpr unsigned PointerAuthKeyNone = -1;
+class PointerAuthSchema {
+public:
+ enum class Kind : unsigned {
+ None,
+ ARM8_3,
+ };
+
+ /// Hardware pointer-signing keys in ARM8.3.
+ ///
+ /// These values are the same used in ptrauth.h.
+ enum class ARM8_3Key : unsigned {
+ ASIA = 0,
+ ASIB = 1,
+ ASDA = 2,
+ ASDB = 3
+ };
+
+ /// Forms of extra discrimination.
+ enum class Discrimination : unsigned {
+ /// No additional discrimination.
+ None,
+
+ /// Discriminate using a constant value.
+ Constant,
+ };
+
+private:
+ Kind TheKind : 2;
+ unsigned IsAddressDiscriminated : 1;
+ unsigned IsIsaPointer : 1;
+ unsigned AuthenticatesNullValues : 1;
+ PointerAuthenticationMode SelectedAuthenticationMode : 2;
+ Discrimination DiscriminationKind : 2;
+ unsigned Key : 4;
+ unsigned ConstantDiscriminator : 16;
+
+public:
+ PointerAuthSchema() : TheKind(Kind::None) {}
+
+ PointerAuthSchema(
+ ARM8_3Key Key, bool IsAddressDiscriminated,
+ PointerAuthenticationMode AuthenticationMode,
+ Discrimination OtherDiscrimination,
+ std::optional<uint16_t> ConstantDiscriminatorOrNone = std::nullopt,
+ bool IsIsaPointer = false, bool AuthenticatesNullValues = false)
+ : TheKind(Kind::ARM8_3), IsAddressDiscriminated(IsAddressDiscriminated),
+ IsIsaPointer(IsIsaPointer),
+ AuthenticatesNullValues(AuthenticatesNullValues),
+ SelectedAuthenticationMode(AuthenticationMode),
+ DiscriminationKind(OtherDiscrimination), Key(unsigned(Key)) {
+ assert((getOtherDiscrimination() != Discrimination::Constant ||
+ ConstantDiscriminatorOrNone) &&
+ "constant discrimination requires a constant!");
+ if (ConstantDiscriminatorOrNone)
+ ConstantDiscriminator = *ConstantDiscriminatorOrNone;
+ }
+
+ PointerAuthSchema(
+ ARM8_3Key Key, bool IsAddressDiscriminated,
+ Discrimination OtherDiscrimination,
+ std::optional<uint16_t> ConstantDiscriminatorOrNone = std::nullopt,
+ bool IsIsaPointer = false, bool AuthenticatesNullValues = false)
+ : PointerAuthSchema(Key, IsAddressDiscriminated,
+ PointerAuthenticationMode::SignAndAuth,
+ OtherDiscrimination, ConstantDiscriminatorOrNone,
+ IsIsaPointer, AuthenticatesNullValues) {}
+
+ Kind getKind() const { return TheKind; }
+
+ explicit operator bool() const { return isEnabled(); }
+
+ bool isEnabled() const { return getKind() != Kind::None; }
+
+ bool isAddressDiscriminated() const {
+ assert(getKind() != Kind::None);
+ return IsAddressDiscriminated;
+ }
+
+ bool isIsaPointer() const {
+ assert(getKind() != Kind::None);
+ return IsIsaPointer;
+ }
+
+ bool authenticatesNullValues() const {
+ assert(getKind() != Kind::None);
+ return AuthenticatesNullValues;
+ }
+
+ bool hasOtherDiscrimination() const {
+ return getOtherDiscrimination() != Discrimination::None;
+ }
+
+ Discrimination getOtherDiscrimination() const {
+ assert(getKind() != Kind::None);
+ return DiscriminationKind;
+ }
+
+ uint16_t getConstantDiscrimination() const {
+ assert(getOtherDiscrimination() == Discrimination::Constant);
+ return (uint16_t)ConstantDiscriminator;
+ }
+
+ unsigned getKey() const {
+ switch (getKind()) {
+ case Kind::None:
+ llvm_unreachable("calling getKey() on disabled schema");
+ case Kind::ARM8_3:
+ return unsigned(getARM8_3Key());
+ }
+ llvm_unreachable("bad key kind");
+ }
+
+ PointerAuthenticationMode getAuthenticationMode() const {
+ return SelectedAuthenticationMode;
+ }
+
+ ARM8_3Key getARM8_3Key() const {
+ assert(getKind() == Kind::ARM8_3);
+ return ARM8_3Key(Key);
+ }
+};
+
+struct PointerAuthOptions {
+ /// The ABI for C function pointers.
+ PointerAuthSchema FunctionPointers;
+};
+
} // end namespace clang
#endif
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index 1a2a39411e58d..e60e5aad6c70d 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -305,6 +305,16 @@ class CompilerInvocation : public CompilerInvocationBase {
/// executable), for finding the builtin compiler path.
static std::string GetResourcesPath(const char *Argv0, void *MainAddr);
+ /// Populate \p Opts with the default set of pointer authentication-related
+ /// options given \p LangOpts and \p Triple. Return true if defaults are
+ /// available.
+ ///
+ /// Note: This is intended to be used by tools which must be aware of
+ /// pointer authentication-related code generation, e.g. lldb.
+ static bool setDefaultPointerAuthOptions(PointerAuthOptions &Opts,
+ const LangOptions &LangOpts,
+ const llvm::Triple &Triple);
+
/// Retrieve a module hash string that is suitable for uniquely
/// identifying the conditions under which the module was built.
std::string getModuleHash() const;
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index b2e3b6fa64284..1f528f9490cd2 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5999,8 +5999,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// If this is a predefined lib function (e.g. malloc), emit the call
// using exactly the normal call path.
if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID))
- return emitLibraryCall(
- *this, FD, E, cast<llvm::Constant>(EmitScalarExpr(E->getCallee())));
+ return emitLibraryCall(*this, FD, E, CGM.getRawFunctionPointer(FD));
// Check that a call to a target specific builtin has the correct target
// features.
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 97449a5e51e73..c33f37bf5b8c4 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -5677,6 +5677,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
!isa_and_nonnull<FunctionDecl>(TargetDecl))
EmitKCFIOperandBundle(ConcreteCallee, BundleList);
+ // Add the pointer-authentication bundle.
+ EmitPointerAuthOperandBundle(ConcreteCallee.getPointerAuthInfo(), BundleList);
+
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl))
if (FD->hasAttr<StrictFPAttr>())
// All calls within a strictfp function are marked strictfp
diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h
index 6b676ac196db2..4b0e1561b4ef5 100644
--- a/clang/lib/CodeGen/CGCall.h
+++ b/clang/lib/CodeGen/CGCall.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_CGCALL_H
#define LLVM_CLANG_LIB_CODEGEN_CGCALL_H
+#include "CGPointerAuthInfo.h"
#include "CGValue.h"
#include "EHScopeStack.h"
#include "clang/AST/ASTFwd.h"
@@ -69,6 +70,10 @@ class CGCallee {
Last = Virtual
};
+ struct OrdinaryInfoStorage {
+ CGCalleeInfo AbstractInfo;
+ CGPointerAuthInfo PointerAuthInfo;
+ };
struct BuiltinInfoStorage {
const FunctionDecl *Decl;
unsigned ID;
@@ -85,7 +90,7 @@ class CGCallee {
SpecialKind KindOrFunctionPointer;
union {
- CGCalleeInfo AbstractInfo;
+ OrdinaryInfoStorage OrdinaryInfo;
BuiltinInfoStorage BuiltinInfo;
PseudoDestructorInfoStorage PseudoDestructorInfo;
VirtualInfoStorage VirtualInfo;
@@ -104,10 +109,13 @@ class CGCallee {
/// Construct a callee. Call this constructor directly when this
/// isn't a direct call.
- CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr)
+ CGCallee(
+ const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr,
+ const CGPointerAuthInfo &pointerAuthInfo = /*FIXME*/ CGPointerAuthInfo())
: KindOrFunctionPointer(
SpecialKind(reinterpret_cast<uintptr_t>(functionPtr))) {
- AbstractInfo = abstractInfo;
+ OrdinaryInfo.AbstractInfo = abstractInfo;
+ OrdinaryInfo.PointerAuthInfo = pointerAuthInfo;
assert(functionPtr && "configuring callee without function pointer");
assert(functionPtr->getType()->isPointerTy());
}
@@ -128,12 +136,12 @@ class CGCallee {
static CGCallee forDirect(llvm::Constant *functionPtr,
const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
- return CGCallee(abstractInfo, functionPtr);
+ return CGCallee(abstractInfo, functionPtr, CGPointerAuthInfo());
}
static CGCallee forDirect(llvm::FunctionCallee functionPtr,
const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
- return CGCallee(abstractInfo, functionPtr.getCallee());
+ return CGCallee(abstractInfo, functionPtr.getCallee(), CGPointerAuthInfo());
}
static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr,
@@ -173,7 +181,11 @@ class CGCallee {
if (isVirtual())
return VirtualInfo.MD;
assert(isOrdinary());
- return AbstractInfo;
+ return OrdinaryInfo.AbstractInfo;
+ }
+ const CGPointerAuthInfo &getPointerAuthInfo() const {
+ assert(isOrdinary());
+ return OrdinaryInfo.PointerAuthInfo;
}
llvm::Value *getFunctionPointer() const {
assert(isOrdinary());
@@ -184,6 +196,10 @@ class CGCallee {
KindOrFunctionPointer =
SpecialKind(reinterpret_cast<uintptr_t>(functionPtr));
}
+ void setPointerAuthInfo(CGPointerAuthInfo pointerAuth) {
+ assert(isOrdinary());
+ OrdinaryInfo.PointerAuthInfo = pointerAuth;
+ }
bool isVirtual() const {
return KindOrFunctionPointer == SpecialKind::Virtual;
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index d6478cc6835d8..152f51f5865e0 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -2850,22 +2850,22 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
return LV;
}
-static llvm::Constant *EmitFunctionDeclPointer(CodeGenModule &CGM,
- GlobalDecl GD) {
+llvm::Constant *CodeGenModule::getRawFunctionPointer(GlobalDecl GD,
+ llvm::Type *Ty) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
if (FD->hasAttr<WeakRefAttr>()) {
- ConstantAddress aliasee = CGM.GetWeakRefReference(FD);
+ ConstantAddress aliasee = GetWeakRefReference(FD);
return aliasee.getPointer();
}
- llvm::Constant *V = CGM.GetAddrOfFunction(GD);
+ llvm::Constant *V = GetAddrOfFunction(GD, Ty);
return V;
}
static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF, const Expr *E,
GlobalDecl GD) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
- llvm::Value *V = EmitFunctionDeclPointer(CGF.CGM, GD);
+ llvm::Constant *V = CGF.CGM.getFunctionPointer(GD);
CharUnits Alignment = CGF.getContext().getDeclAlign(FD);
return CGF.MakeAddrLValue(V, E->getType(), Alignment,
AlignmentSource::Decl);
@@ -5501,7 +5501,7 @@ static CGCallee EmitDirectCallee(CodeGenFunction &CGF, GlobalDecl GD) {
// name to make it clear it's not the actual builtin.
if (CGF.CurFn->getName() != FDInlineName &&
OnlyHasInlineBuiltinDeclaration(FD)) {
- llvm::Constant *CalleePtr = EmitFunctionDeclPointer(CGF.CGM, GD);
+ llvm::Constant *CalleePtr = CGF.CGM.getRawFunctionPointer(GD);
llvm::Function *Fn = llvm::cast<llvm::Function>(CalleePtr);
llvm::Module *M = Fn->getParent();
llvm::Function *Clone = M->getFunction(FDInlineName);
@@ -5524,7 +5524,7 @@ static CGCallee EmitDirectCallee(CodeGenFunction &CGF, GlobalDecl GD) {
return CGCallee::forBuiltin(builtinID, FD);
}
- llvm::Constant *CalleePtr = EmitFunctionDeclPointer(CGF.CGM, GD);
+ llvm::Constant *CalleePtr = CGF.CGM.getRawFunctionPointer(GD);
if (CGF.CGM.getLangOpts().CUDA && !CGF.CGM.getLangOpts().CUDAIsDevice &&
FD->hasAttr<CUDAGlobalAttr>())
CalleePtr = CGF.CGM.getCUDARuntime().getKernelStub(
@@ -5581,7 +5581,8 @@ CGCallee CodeGenFunction::EmitCallee(const Expr *E) {
GD = GlobalDecl(VD);
CGCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(), GD);
- CGCallee callee(calleeInfo, calleePtr);
+ CGPointerAuthInfo pointerAuth = CGM.getFunctionPointerAuthInfo(functionType);
+ CGCallee callee(calleeInfo, calleePtr, pointerAuth);
return callee;
}
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index de9380c0e63be..bfb545a2fe1f6 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -1956,8 +1956,25 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
if (D->hasAttr<WeakRefAttr>())
return CGM.GetWeakRefReference(D).getPointer();
+ auto PtrAuthSign = [&](llvm::Constant *C) {
+ CGPointerAuthInfo AuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
+
+ if (AuthInfo) {
+ if (hasNonZeroOffset())
+ return ConstantLValue(nullptr);
+
+ C = applyOffset(C);
+ C = CGM.getConstantSignedPointer(
+ C, AuthInfo.getKey(), nullptr,
+ cast_or_null<llvm::Constant>(AuthInfo.getDiscriminator()));
+ return ConstantLValue(C, /*applied offset*/ true);
+ }
+
+ return ConstantLValue(C);
+ };
+
if (auto FD = dyn_cast<FunctionDecl>(D))
- return CGM.GetAddrOfFunction(FD);
+ return PtrAuthSign(CGM.getRawFunctionPointer(FD));
if (auto VD = dyn_cast<VarDecl>(D)) {
// We can never refer to a variable with local storage.
diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp
index 756c00aa42c8c..adfa721ac89d3 100644
--- a/clang/lib/CodeGen/CGPointerAuth.cpp
+++ b/clang/lib/CodeGen/CGPointerAuth.cpp
@@ -28,6 +28,24 @@
using namespace clang;
using namespace CodeGen;
+/// Return the abstract pointer authentication schema for a pointer to the given
+/// function type.
+CGPointerAuthInfo CodeGenModule::getFunctionPointerAuthInfo(QualType T) {
+ auto &Schema = getCodeGenOpts().PointerAuth.FunctionPointers;
+ if (!Schema)
+ return CGPointerAuthInfo();
+
+ assert(!Schema.isAddressDiscriminated() &&
+ "function pointers cannot use address-specific discrimination");
+
+ assert(!Schema.hasOtherDiscrimination() &&
+ "function pointers don't support any discrimination yet");
+
+ return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
+ /*IsaPointer=*/false, /*AuthenticatesNull=*/false,
+ /*Discriminator=*/nullptr);
+}
+
/// Build a signed-pointer "ptrauth" constant.
static llvm::ConstantPtrAuth *
buildConstantAddress(CodeGenModule &CGM, llvm::Constant *pointer, unsigned key,
@@ -75,3 +93,36 @@ CodeGen::getConstantSignedPointer(CodeGenModule &CGM,
return CGM.getConstantSignedPointer(pointer, key, storageAddress,
otherDiscriminator);
}
+
+/// If applicable, sign a given constant function pointer with the ABI rules for
+/// functionType.
+llvm::Constant *CodeGenModule::getFunctionPointer(llvm::Constant *pointer,
+ QualType functionType,
+ GlobalDecl GD) {
+ assert(functionType->isFunctionType() ||
+ functionType->isFunctionReferenceType() ||
+ functionType->isFunctionPointerType());
+
+ if (auto pointerAuth = getFunctionPointerAuthInfo(functionType)) {
+ return getConstantSignedPointer(
+ pointer, pointerAuth.getKey(), nullptr,
+ cast_or_null<llvm::Constant>(pointerAuth.getDiscriminator()));
+ }
+
+ return pointer;
+}
+
+llvm::Constant *CodeGenModule::getFunctionPointer(GlobalDecl GD,
+ llvm::Type *Ty) {
+ const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+
+ // Annoyingly, K&R functions have prototypes in the clang AST, but
+ // expressions referring to them are unprototyped.
+ QualType FuncType = FD->getType();
+ if (!FD->hasPrototype())
+ if (const auto *Proto = FuncType->getAs<FunctionProtoType>())
+ FuncType = Context.getFunctionNoProtoType(Proto->getReturnType(),
+ Proto->getExtInfo());
+
+ return getFunctionPointer(getRawFunctionPointer(GD, Ty), FuncType, GD);
+}
diff --git a/clang/lib/CodeGen/CGPointerAuthInfo.h b/clang/lib/CodeGen/CGPointerAuthInfo.h
new file mode 100644
index 0000000000000..e870c3145acba
--- /dev/null
+++ b/clang/lib/CodeGen/CGPointerAuthInfo.h
@@ -0,0 +1,96 @@
+//===----- CGPointerAuthInfo.h - -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Pointer auth info class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_CGPOINTERAUTHINFO_H
+#define LLVM_CLANG_LIB_CODEGEN_CGPOINTERAUTHINFO_H
+
+#include "clang/AST/Type.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Value.h"
+
+namespace clang {
+namespace CodeGen {
+
+class CGPointerAuthInfo {
+private:
+ PointerAuthenticationMode AuthenticationMode : 2;
+ bool IsIsaPointer : 1;
+ bool AuthenticatesNullValues : 1;
+ unsigned Key : 28;
+ llvm::Value *Discriminator;
+
+public:
+ CGPointerAuthInfo()
+ : AuthenticationMode(PointerAuthenticationMode...
[truncated]
|
@ahatanak @ahmedbougacha Looks like there are some conflicts that should be resolved |
// RUN: %clang_cc1 -triple arm64-apple-ios -emit-llvm %s -o - | FileCheck %s --check-prefixes=ALL,OFF | ||
// RUN: %clang_cc1 -triple arm64e-apple-ios -emit-llvm %s -o - | FileCheck %s --check-prefixes=ALL,OFF | ||
|
||
// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -emit-llvm %s -o - | FileCheck %s --check-prefixes=ALL,CALLS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm OK with any Apple-specific RUN lines if you really want to have all of them, but this one and the next one seem to duplicate each other. I suppose there should be a separate test which checks that arm64e target sets desired ptrauth flags, and then you can just use either arm64e or arm64 with explicitly specified flags in RUN lines in codegen tests.
Feel free to ignore - everything Apple-related is not what I'm going to debate :)
33cdfdd
to
6e7ba73
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but this needs a rebase - the base branch was updated, and now the PR contains unrelated changes.
1201821
to
68d0bb2
Compare
Co-Authored-By: John McCall <[email protected]>
- Remove unneeded declarations. - Fix includes. - Use `llvm::to_underlying`. - Fix variable names. - Fix size and type of bit-fields. - Add test case for `err_drv_ptrauth_not_supported`.
- Remove unused diagnostic. - Change the size of Key fields to 2 bits. - Stop passing the default argument to CGCallee's constructor. - Remove unused functions and variables. - Add a test for indirect calls. - Run tests on linux too.
06529d3
to
99b2bf2
Compare
You can test this locally with the following command:git-clang-format --diff 7c814c13d0df6dbd0ef6a8b2be214d3f6edbb566 99b2bf2e1f70ed6f374a380f91a707c2acd8a318 --extensions 'cpp,h,c' -- clang/lib/CodeGen/CGPointerAuthInfo.h clang/test/CodeGen/ptrauth-function-attributes.c clang/test/CodeGen/ptrauth-function-init-fail.c clang/test/CodeGen/ptrauth-function-init.c clang/test/CodeGen/ptrauth-function-lvalue-cast.c clang/test/CodeGen/ptrauth-function.c clang/test/CodeGen/ptrauth-weak_import.c clang/test/CodeGenCXX/ptrauth.cpp clang/include/clang/Basic/CodeGenOptions.h clang/include/clang/Basic/PointerAuthOptions.h clang/include/clang/Frontend/CompilerInvocation.h clang/lib/CodeGen/CGBuiltin.cpp clang/lib/CodeGen/CGCall.cpp clang/lib/CodeGen/CGCall.h clang/lib/CodeGen/CGExpr.cpp clang/lib/CodeGen/CGExprConstant.cpp clang/lib/CodeGen/CGPointerAuth.cpp clang/lib/CodeGen/CodeGenFunction.cpp clang/lib/CodeGen/CodeGenFunction.h clang/lib/CodeGen/CodeGenModule.h clang/lib/Frontend/CompilerInvocation.cpp clang/lib/Headers/ptrauth.h View the diff from clang-format here.diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h
index aaad4a2b2b..2851958a80 100644
--- a/clang/include/clang/Basic/PointerAuthOptions.h
+++ b/clang/include/clang/Basic/PointerAuthOptions.h
@@ -35,12 +35,7 @@ public:
/// Hardware pointer-signing keys in ARM8.3.
///
/// These values are the same used in ptrauth.h.
- enum class ARM8_3Key : unsigned {
- ASIA = 0,
- ASIB = 1,
- ASDA = 2,
- ASDB = 3
- };
+ enum class ARM8_3Key : unsigned { ASIA = 0, ASIB = 1, ASDA = 2, ASDB = 3 };
/// Forms of extra discrimination.
enum class Discrimination : unsigned {
|
… calls (llvm#93906) The functions are currently always signed/authenticated with zero discriminator. Co-Authored-By: John McCall <[email protected]>
if (ConstantDiscriminatorOrNone) | ||
ConstantDiscriminator = *ConstantDiscriminatorOrNone; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @ahmedbougacha @ahatanak The static verifier is reporting that 'ConstantDiscriminator' is not initialized when taking the false branch of that if. Is that possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mikerice1969 The logic is a bit convoluted here. But essentially this field is only initialized when getOtherDiscrimination() == Discrimination::Constant
. And there is assert above for that and below in getConstantDiscrimination()
. But probably it would be better to initialize it regardless.
When this change is building at Compiler Explorer I noticed it spams build output with warnings:
|
@ahatanak Will you please take a look into all these issues? |
Do we have to fix this just to appease gcc 9.2? It looks like newer versions of gcc (after 9.3) don't emit the warning. |
The functions are currently always signed/authenticated with zero discriminator.
Co-Authored-By: John McCall [email protected]