18#include "llvm/Analysis/ValueTracking.h"
19#include "llvm/Support/SipHash.h"
22using namespace CodeGen;
33 assert(!
Type.isNull() &&
"type not provided for type-discriminated schema");
34 return llvm::ConstantInt::get(
38 assert(
Decl.getDecl() &&
39 "declaration not provided for decl-discriminated schema");
40 return llvm::ConstantInt::get(
IntPtrTy,
46 llvm_unreachable(
"bad discrimination kind");
62 uint16_t &EntityHash = PtrAuthDiscriminatorHashes[
Declaration];
64 if (EntityHash == 0) {
66 EntityHash = llvm::getPointerAuthStableSipHash(Name);
79 assert(!Schema.isAddressDiscriminated() &&
80 "function pointers cannot use address-specific discrimination");
82 llvm::Constant *Discriminator =
nullptr;
95 llvm::Value *Discriminator) {
98 return Builder.CreateCall(Intrinsic, {StorageAddress, Discriminator});
109 llvm::Value *Discriminator =
113 assert(StorageAddress &&
114 "address not provided for address-discriminated schema");
144 return ::getPointerAuthInfoForPointeeType(*
this,
T);
159 if (PointeeType.isNull())
162 return ::getPointerAuthInfoForPointeeType(CGM, PointeeType);
166 return ::getPointerAuthInfoForType(*
this,
T);
170 if (
const auto *CI = dyn_cast<llvm::ConstantInt>(
Value))
177 assert((Left.isSigned() || Right.isSigned()) &&
178 "shouldn't be called if neither is signed");
179 if (Left.isSigned() != Right.isSigned())
181 return Left.getKey() == Right.getKey() &&
182 Left.getAuthenticationMode() == Right.getAuthenticationMode();
189 return Discriminator ? Discriminator : Builder.getSize(0);
196 assert(CurAuth && NewAuth);
220 Intrinsic, {
Value, CurKey, CurDiscriminator, NewKey, NewDiscriminator});
231 if (!CurAuthInfo && !NewAuthInfo)
234 llvm::Value *
Null =
nullptr;
236 if (
auto *PointerValue = dyn_cast<llvm::PointerType>(
Value->
getType())) {
257 llvm::BasicBlock *InitBB =
Builder.GetInsertBlock();
258 llvm::BasicBlock *ResignBB =
nullptr, *ContBB =
nullptr;
267 Builder.CreateCondBr(IsNonNull, ResignBB, ContBB);
274 else if (!CurAuthInfo)
283 Phi->addIncoming(Null, InitBB);
284 Phi->addIncoming(
Value, ResignBB);
293 llvm::Constant *StorageAddress,
294 llvm::ConstantInt *OtherDiscriminator) {
295 llvm::Constant *AddressDiscriminator;
296 if (StorageAddress) {
298 AddressDiscriminator = StorageAddress;
300 AddressDiscriminator = llvm::Constant::getNullValue(
UnqualPtrTy);
303 llvm::ConstantInt *IntegerDiscriminator;
304 if (OtherDiscriminator) {
305 assert(OtherDiscriminator->getType() ==
Int64Ty);
306 IntegerDiscriminator = OtherDiscriminator;
308 IntegerDiscriminator = llvm::ConstantInt::get(
Int64Ty, 0);
311 return llvm::ConstantPtrAuth::get(
Pointer,
312 llvm::ConstantInt::get(
Int32Ty, Key),
313 IntegerDiscriminator, AddressDiscriminator);
327 llvm::Constant *StorageAddress,
GlobalDecl SchemaDecl,
330 llvm::ConstantInt *OtherDiscriminator =
347 Pointer, PointerAuth.getKey(),
nullptr,
348 cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator()));
355 const auto *FD = cast<FunctionDecl>(GD.
getDecl());
360 if (!FD->hasPrototype())
363 Proto->getExtInfo());
375 "function pointers cannot use address-specific discrimination");
377 llvm::ConstantInt *Discriminator =
381 false, Discriminator);
388 Pointer, PointerAuth.getKey(),
nullptr,
389 cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator()));
398 FT, cast<CXXMethodDecl>(FD)->getParent()->getTypeForDecl());
402std::optional<PointerAuthQualifier>
403CodeGenModule::computeVTPointerAuthentication(
const CXXRecordDecl *ThisClass) {
405 if (!DefaultAuthentication)
410 unsigned Key = DefaultAuthentication.getKey();
411 bool AddressDiscriminated = DefaultAuthentication.isAddressDiscriminated();
412 auto DefaultDiscrimination = DefaultAuthentication.getOtherDiscrimination();
413 unsigned TypeBasedDiscriminator =
415 unsigned Discriminator;
417 Discriminator = TypeBasedDiscriminator;
418 }
else if (DefaultDiscrimination ==
420 Discriminator = DefaultAuthentication.getConstantDiscrimination();
425 if (
auto ExplicitAuthentication =
426 PrimaryBase->
getAttr<VTablePointerAuthenticationAttr>()) {
427 auto ExplicitAddressDiscrimination =
428 ExplicitAuthentication->getAddressDiscrimination();
429 auto ExplicitDiscriminator =
430 ExplicitAuthentication->getExtraDiscrimination();
432 unsigned ExplicitKey = ExplicitAuthentication->getKey();
433 if (ExplicitKey == VTablePointerAuthenticationAttr::NoKey)
436 if (ExplicitKey != VTablePointerAuthenticationAttr::DefaultKey) {
437 if (ExplicitKey == VTablePointerAuthenticationAttr::ProcessIndependent)
440 assert(ExplicitKey ==
441 VTablePointerAuthenticationAttr::ProcessDependent);
446 if (ExplicitAddressDiscrimination !=
447 VTablePointerAuthenticationAttr::DefaultAddressDiscrimination)
448 AddressDiscriminated =
449 ExplicitAddressDiscrimination ==
450 VTablePointerAuthenticationAttr::AddressDiscrimination;
452 if (ExplicitDiscriminator ==
453 VTablePointerAuthenticationAttr::TypeDiscrimination)
454 Discriminator = TypeBasedDiscriminator;
455 else if (ExplicitDiscriminator ==
456 VTablePointerAuthenticationAttr::CustomDiscrimination)
457 Discriminator = ExplicitAuthentication->getCustomDiscriminationValue();
458 else if (ExplicitDiscriminator ==
459 VTablePointerAuthenticationAttr::NoExtraDiscrimination)
468std::optional<PointerAuthQualifier>
470 if (!
Record->getDefinition() || !
Record->isPolymorphic())
473 auto Existing = VTablePtrAuthInfos.find(
Record);
474 std::optional<PointerAuthQualifier> Authentication;
475 if (Existing != VTablePtrAuthInfos.end()) {
476 Authentication = Existing->getSecond();
478 Authentication = computeVTPointerAuthentication(
Record);
479 VTablePtrAuthInfos.insert(std::make_pair(
Record, Authentication));
481 return Authentication;
484std::optional<CGPointerAuthInfo>
487 llvm::Value *StorageAddress) {
492 llvm::Value *Discriminator =
nullptr;
493 if (
auto ExtraDiscriminator = Authentication->getExtraDiscriminator())
494 Discriminator = llvm::ConstantInt::get(
IntPtrTy, ExtraDiscriminator);
496 if (Authentication->isAddressDiscriminated()) {
497 assert(StorageAddress &&
498 "address not provided for address-discriminated schema");
509 false, Discriminator);
522 if (!CurAuthInfo && !NewAuthInfo)
547 if (!CurAuthInfo && !NewAuthInfo)
578 assert(
isValid() &&
"pointer isn't valid");
587 assert(ElementType &&
"Effective type has to be set");
588 assert(!Offset &&
"unexpected non-null offset");
static bool isZeroConstant(const llvm::Value *Value)
static llvm::Value * getDiscriminatorOrZero(const CGPointerAuthInfo &Info, CGBuilderTy &Builder)
static bool equalAuthPolicies(const CGPointerAuthInfo &Left, const CGPointerAuthInfo &Right)
static CGPointerAuthInfo getPointerAuthInfoForPointeeType(CodeGenModule &CGM, QualType PointeeType)
Return the natural pointer authentication for values of the given pointee type.
static CGPointerAuthInfo getPointerAuthInfoForType(CodeGenModule &CGM, QualType PointerType)
Return the natural pointer authentication for values of the given pointer type.
llvm::MachO::Record Record
QualType getMemberPointerType(QualType T, const Type *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
QualType getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const
Return a K&R style C function type like 'int()'.
const CXXRecordDecl * baseForVTableAuthentication(const CXXRecordDecl *ThisClass)
Resolve the root record to be used to derive the vtable pointer authentication policy for the specifi...
uint16_t getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD)
Return the "other" discriminator used for the pointer auth schema used for vtable pointers in instanc...
uint16_t getPointerAuthTypeDiscriminator(QualType T)
Return the "other" type-specific discriminator for the given type.
Represents a C++ struct/union/class.
PointerAuthOptions PointerAuth
Configuration for pointer-signing.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * getBasePointer() const
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
void setPointerAuthInfo(const CGPointerAuthInfo &Info)
KnownNonNull_t isKnownNonNull() const
Whether the pointer is known not to be null.
Address getResignedAddress(const CGPointerAuthInfo &NewInfo, CodeGenFunction &CGF) const
const CGPointerAuthInfo & getPointerAuthInfo() const
llvm::PointerType * getType() const
Return the type of the pointer value.
PointerAuthenticationMode getAuthenticationMode() const
llvm::Value * getDiscriminator() const
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::Value * EmitPointerAuthAuth(const CGPointerAuthInfo &Info, llvm::Value *Pointer)
Address getAsNaturalAddressOf(Address Addr, QualType PointeeTy)
llvm::Value * emitPointerAuthResignCall(llvm::Value *Pointer, const CGPointerAuthInfo &CurInfo, const CGPointerAuthInfo &NewInfo)
llvm::Value * getAsNaturalPointerTo(Address Addr, QualType PointeeType)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
llvm::Value * EmitPointerAuthSign(const CGPointerAuthInfo &Info, llvm::Value *Pointer)
llvm::Value * EmitPointerAuthBlendDiscriminator(llvm::Value *StorageAddress, llvm::Value *Discriminator)
Create the discriminator from the storage address and the entity hash.
llvm::Value * emitPointerAuthResign(llvm::Value *Pointer, QualType PointerType, const CGPointerAuthInfo &CurAuthInfo, const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull)
llvm::Value * authPointerToPointerCast(llvm::Value *ResultPtr, QualType SourceType, QualType DestType)
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
CGPointerAuthInfo EmitPointerAuthInfo(const PointerAuthSchema &Schema, llvm::Value *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType)
This class organizes the cross-function state that is used while generating LLVM code.
llvm::Constant * getRawFunctionPointer(GlobalDecl GD, llvm::Type *Ty=nullptr)
Return a function pointer for a reference to the given function.
llvm::Constant * getFunctionPointer(GlobalDecl GD, llvm::Type *Ty=nullptr)
Return the ABI-correct function pointer value for a reference to the given function.
llvm::Constant * getNullPointer(llvm::PointerType *T, QualType QT)
Get target specific null pointer.
CGPointerAuthInfo getMemberFunctionPointerAuthInfo(QualType FT)
llvm::ConstantInt * getPointerAuthOtherDiscriminator(const PointerAuthSchema &Schema, GlobalDecl SchemaDecl, QualType SchemaType)
Given a pointer-authentication schema, return a concrete "other" discriminator for it.
CGPointerAuthInfo getPointerAuthInfoForPointeeType(QualType type)
const llvm::DataLayout & getDataLayout() const
CGPointerAuthInfo getFunctionPointerAuthInfo(QualType T)
Return the abstract pointer authentication schema for a pointer to the given function type.
llvm::Constant * getMemberFunctionPointer(const FunctionDecl *FD, llvm::Type *Ty=nullptr)
std::optional< PointerAuthQualifier > getVTablePointerAuthentication(const CXXRecordDecl *thisClass)
uint16_t getPointerAuthDeclDiscriminator(GlobalDecl GD)
Return the "other" decl-specific discriminator for the given decl.
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
std::optional< CGPointerAuthInfo > getVTablePointerAuthInfo(CodeGenFunction *Context, const CXXRecordDecl *Record, llvm::Value *StorageAddress)
llvm::Constant * getConstantSignedPointer(llvm::Constant *Pointer, const PointerAuthSchema &Schema, llvm::Constant *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType)
Sign a constant pointer using the given scheme, producing a constant with the same IR type.
bool shouldSignPointer(const PointerAuthSchema &Schema)
Does a given PointerAuthScheme require us to sign a value.
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys=std::nullopt)
CGPointerAuthInfo getPointerAuthInfoForType(QualType type)
llvm::Value * emitResignedPointer(QualType PointeeTy, CodeGenFunction &CGF) const
llvm::Value * getPointer(CodeGenFunction &CGF) const
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Decl - This represents one declaration (or definition), e.g.
Represents a function declaration or definition.
Represents a prototype with parameter type info, e.g.
FunctionType - C99 6.7.5.3 - Function Declarators.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
A pointer to member type per C++ 8.3.3 - Pointers to members.
static PointerAuthQualifier Create(unsigned Key, bool IsAddressDiscriminated, unsigned ExtraDiscriminator, PointerAuthenticationMode AuthenticationMode, bool IsIsaPointer, bool AuthenticatesNullValues)
Discrimination getOtherDiscrimination() const
bool isAddressDiscriminated() const
@ None
No additional discrimination.
@ Type
Include a hash of the entity's type.
@ Decl
Include a hash of the entity's identity.
@ Constant
Discriminate using a constant value.
bool authenticatesNullValues() const
PointerAuthenticationMode getAuthenticationMode() const
uint16_t getConstantDiscrimination() const
bool isIsaPointer() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
The base class of the type hierarchy.
bool isBlockPointerType() const
bool isFunctionReferenceType() const
bool isFunctionPointerType() const
bool isSignableType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isFunctionType() const
const T * getAs() const
Member-template getAs<specific type>'.
uint16_t getPointerAuthDeclDiscriminator(CodeGenModule &CGM, GlobalDecl GD)
Return a declaration discriminator for the given global decl.
uint16_t getPointerAuthTypeDiscriminator(CodeGenModule &CGM, QualType FunctionType)
Return a type discriminator for the given function type.
bool Null(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
llvm::IntegerType * Int64Ty
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::PointerType * UnqualPtrTy
PointerAuthSchema CXXVTablePointers
The ABI for C++ virtual table pointers (the pointer to the table itself) as installed in an actual cl...
PointerAuthSchema FunctionPointers
The ABI for C function pointers.
PointerAuthSchema CXXMemberFunctionPointers
The ABI for C++ member function pointers.