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");
131 assert(Qual &&
"don't call this if you don't know that the Qual is present");
135 llvm::Value *Discriminator =
nullptr;
140 assert(StorageAddress.
isValid() &&
141 "address discrimination without address");
171 return ::getPointerAuthInfoForPointeeType(*
this,
T);
186 if (PointeeType.isNull())
189 return ::getPointerAuthInfoForPointeeType(CGM, PointeeType);
193 return ::getPointerAuthInfoForType(*
this,
T);
196static std::pair<llvm::Value *, CGPointerAuthInfo>
205 return {
Value, AuthInfo};
210std::pair<llvm::Value *, CGPointerAuthInfo>
215 if (
const auto *Load = dyn_cast<ImplicitCastExpr>(
E)) {
216 if (Load->getCastKind() == CK_LValueToRValue) {
217 E = Load->getSubExpr()->IgnoreParens();
220 if (
const auto *RefExpr = dyn_cast<DeclRefExpr>(
E)) {
223 if (!
Result.isReference())
224 return {
Result.getValue(),
248 assert(DestQualifier);
260 assert(DestQualifier);
271 Address CurStorageAddress,
bool IsKnownNonNull) {
272 assert(CurQualifier);
282 if (
const auto *CI = dyn_cast<llvm::ConstantInt>(
Value))
289 assert((Left.isSigned() || Right.isSigned()) &&
290 "shouldn't be called if neither is signed");
291 if (Left.isSigned() != Right.isSigned())
293 return Left.getKey() == Right.getKey() &&
294 Left.getAuthenticationMode() == Right.getAuthenticationMode() &&
295 Left.isIsaPointer() == Right.isIsaPointer() &&
296 Left.authenticatesNullValues() == Right.authenticatesNullValues() &&
297 Left.getDiscriminator() == Right.getDiscriminator();
304 return Discriminator ? Discriminator : Builder.getSize(0);
311 assert(CurAuth && NewAuth);
335 Intrinsic, {
Value, CurKey, CurDiscriminator, NewKey, NewDiscriminator});
346 if (!CurAuthInfo && !NewAuthInfo)
349 llvm::Value *Null =
nullptr;
351 if (
auto *PointerValue = dyn_cast<llvm::PointerType>(
Value->
getType())) {
355 Null = llvm::ConstantInt::get(
IntPtrTy, 0);
372 llvm::BasicBlock *InitBB =
Builder.GetInsertBlock();
373 llvm::BasicBlock *ResignBB =
nullptr, *ContBB =
nullptr;
382 Builder.CreateCondBr(IsNonNull, ResignBB, ContBB);
389 else if (!CurAuthInfo)
398 Phi->addIncoming(Null, InitBB);
399 Phi->addIncoming(
Value, ResignBB);
425 llvm::Constant *StorageAddress,
426 llvm::ConstantInt *OtherDiscriminator) {
427 llvm::Constant *AddressDiscriminator;
428 if (StorageAddress) {
430 AddressDiscriminator = StorageAddress;
432 AddressDiscriminator = llvm::Constant::getNullValue(
UnqualPtrTy);
435 llvm::ConstantInt *IntegerDiscriminator;
436 if (OtherDiscriminator) {
437 assert(OtherDiscriminator->getType() ==
Int64Ty);
438 IntegerDiscriminator = OtherDiscriminator;
440 IntegerDiscriminator = llvm::ConstantInt::get(
Int64Ty, 0);
443 return llvm::ConstantPtrAuth::get(
Pointer,
444 llvm::ConstantInt::get(
Int32Ty, Key),
445 IntegerDiscriminator, AddressDiscriminator);
459 llvm::Constant *StorageAddress,
GlobalDecl SchemaDecl,
462 llvm::ConstantInt *OtherDiscriminator =
471 unsigned Key, llvm::Constant *StorageAddress,
472 llvm::ConstantInt *OtherDiscriminator) {
487 Pointer, PointerAuth.getKey(),
nullptr,
488 cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator()));
495 const auto *FD = cast<FunctionDecl>(GD.
getDecl());
500 if (!FD->hasPrototype())
503 Proto->getExtInfo());
514 assert(!Schema.isAddressDiscriminated() &&
515 "function pointers cannot use address-specific discrimination");
517 llvm::ConstantInt *Discriminator =
521 false, Discriminator);
528 Pointer, PointerAuth.getKey(),
nullptr,
529 cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator()));
531 if (
const auto *MFT = dyn_cast<MemberPointerType>(FT.
getTypePtr())) {
532 if (MFT->hasPointeeToToCFIUncheckedCalleeFunctionType())
533 Pointer = llvm::NoCFIValue::get(cast<llvm::GlobalValue>(
Pointer));
543 cast<CXXMethodDecl>(FD)->getParent());
547std::optional<PointerAuthQualifier>
548CodeGenModule::computeVTPointerAuthentication(
const CXXRecordDecl *ThisClass) {
550 if (!DefaultAuthentication)
555 unsigned Key = DefaultAuthentication.getKey();
556 bool AddressDiscriminated = DefaultAuthentication.isAddressDiscriminated();
557 auto DefaultDiscrimination = DefaultAuthentication.getOtherDiscrimination();
558 unsigned TypeBasedDiscriminator =
560 unsigned Discriminator;
562 Discriminator = TypeBasedDiscriminator;
563 }
else if (DefaultDiscrimination ==
565 Discriminator = DefaultAuthentication.getConstantDiscrimination();
570 if (
auto ExplicitAuthentication =
571 PrimaryBase->
getAttr<VTablePointerAuthenticationAttr>()) {
572 auto ExplicitAddressDiscrimination =
573 ExplicitAuthentication->getAddressDiscrimination();
574 auto ExplicitDiscriminator =
575 ExplicitAuthentication->getExtraDiscrimination();
577 unsigned ExplicitKey = ExplicitAuthentication->getKey();
578 if (ExplicitKey == VTablePointerAuthenticationAttr::NoKey)
581 if (ExplicitKey != VTablePointerAuthenticationAttr::DefaultKey) {
582 if (ExplicitKey == VTablePointerAuthenticationAttr::ProcessIndependent)
585 assert(ExplicitKey ==
586 VTablePointerAuthenticationAttr::ProcessDependent);
591 if (ExplicitAddressDiscrimination !=
592 VTablePointerAuthenticationAttr::DefaultAddressDiscrimination)
593 AddressDiscriminated =
594 ExplicitAddressDiscrimination ==
595 VTablePointerAuthenticationAttr::AddressDiscrimination;
597 if (ExplicitDiscriminator ==
598 VTablePointerAuthenticationAttr::TypeDiscrimination)
599 Discriminator = TypeBasedDiscriminator;
600 else if (ExplicitDiscriminator ==
601 VTablePointerAuthenticationAttr::CustomDiscrimination)
602 Discriminator = ExplicitAuthentication->getCustomDiscriminationValue();
603 else if (ExplicitDiscriminator ==
604 VTablePointerAuthenticationAttr::NoExtraDiscrimination)
613std::optional<PointerAuthQualifier>
615 if (!
Record->getDefinition() || !
Record->isPolymorphic())
618 auto Existing = VTablePtrAuthInfos.find(
Record);
619 std::optional<PointerAuthQualifier> Authentication;
620 if (Existing != VTablePtrAuthInfos.end()) {
621 Authentication = Existing->getSecond();
623 Authentication = computeVTPointerAuthentication(
Record);
624 VTablePtrAuthInfos.insert(std::make_pair(
Record, Authentication));
626 return Authentication;
629std::optional<CGPointerAuthInfo>
632 llvm::Value *StorageAddress) {
637 llvm::Value *Discriminator =
nullptr;
638 if (
auto ExtraDiscriminator = Authentication->getExtraDiscriminator())
639 Discriminator = llvm::ConstantInt::get(
IntPtrTy, ExtraDiscriminator);
641 if (Authentication->isAddressDiscriminated()) {
642 assert(StorageAddress &&
643 "address not provided for address-discriminated schema");
654 false, Discriminator);
667 if (!CurAuthInfo && !NewAuthInfo)
692 if (!CurAuthInfo && !NewAuthInfo)
718 return Addr.getResignedAddress(Info, *
this);
723 assert(
isValid() &&
"pointer isn't valid");
732 assert(ElementType &&
"Effective type has to be set");
733 assert(!Offset &&
"unexpected non-null offset");
static std::pair< llvm::Value *, CGPointerAuthInfo > emitLoadOfOrigPointerRValue(CodeGenFunction &CGF, const LValue &LV, SourceLocation Loc)
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 getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const
Return a K&R style C function type like 'int()'.
QualType getMemberPointerType(QualType T, NestedNameSpecifier Qualifier, const CXXRecordDecl *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
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.
const CXXRecordDecl * baseForVTableAuthentication(const CXXRecordDecl *ThisClass) const
Resolve the root record to be used to derive the vtable pointer authentication policy for the specifi...
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::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
PointerAuthenticationMode getAuthenticationMode() const
llvm::Value * getDiscriminator() const
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::Value * EmitPointerAuthQualify(PointerAuthQualifier Qualifier, llvm::Value *Pointer, QualType ValueType, Address StorageAddress, bool IsKnownNonNull)
llvm::Value * getAsNaturalPointerTo(Address Addr, QualType PointeeType)
llvm::Value * emitPointerAuthResignCall(llvm::Value *Pointer, const CGPointerAuthInfo &CurInfo, const CGPointerAuthInfo &NewInfo)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
bool isPointerKnownNonNull(const Expr *E)
llvm::Value * EmitPointerAuthUnqualify(PointerAuthQualifier Qualifier, llvm::Value *Pointer, QualType PointerType, Address StorageAddress, bool IsKnownNonNull)
@ TCK_Load
Checking the operand of a load. Must be suitably sized and aligned.
llvm::Value * EmitPointerAuthSign(const CGPointerAuthInfo &Info, llvm::Value *Pointer)
Address getAsNaturalAddressOf(Address Addr, QualType PointeeTy)
CGPointerAuthInfo EmitPointerAuthInfo(const PointerAuthSchema &Schema, llvm::Value *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType)
Emit the concrete pointer authentication informaton for the given authentication schema.
void EmitPointerAuthCopy(PointerAuthQualifier Qualifier, QualType Type, Address DestField, Address SrcField)
llvm::Value * emitPointerAuthResign(llvm::Value *Pointer, QualType PointerType, const CGPointerAuthInfo &CurAuthInfo, const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull)
ASTContext & getContext() const
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Value * authPointerToPointerCast(llvm::Value *ResultPtr, QualType SourceType, QualType DestType)
LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK)
Same as EmitLValue but additionally we generate checking code to guard against undefined behavior.
llvm::Value * EmitPointerAuthBlendDiscriminator(llvm::Value *StorageAddress, llvm::Value *Discriminator)
Create the discriminator from the storage address and the entity hash.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
ConstantEmission tryEmitAsConstant(const DeclRefExpr *RefExpr)
Try to emit a reference to the given value without producing it as an l-value.
std::pair< llvm::Value *, CGPointerAuthInfo > EmitOrigPointerRValue(const Expr *E)
Retrieve a pointer rvalue and its ptrauth info.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
llvm::Value * EmitPointerAuthAuth(const CGPointerAuthInfo &Info, llvm::Value *Pointer)
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)
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
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.
CGPointerAuthInfo getPointerAuthInfoForType(QualType type)
LValue - This represents an lvalue references.
llvm::Value * emitResignedPointer(QualType PointeeTy, CodeGenFunction &CGF) const
llvm::Value * getPointer(CodeGenFunction &CGF) const
const Qualifiers & getQuals() const
Address getAddress() const
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
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.
Pointer-authentication qualifiers.
bool isIsaPointer() const
static PointerAuthQualifier Create(unsigned Key, bool IsAddressDiscriminated, unsigned ExtraDiscriminator, PointerAuthenticationMode AuthenticationMode, bool IsIsaPointer, bool AuthenticatesNullValues)
bool authenticatesNullValues() const
bool isAddressDiscriminated() const
unsigned getExtraDiscriminator() const
PointerAuthenticationMode getAuthenticationMode() const
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.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
PointerAuthQualifier getPointerAuth() const
Encodes a location in the source.
The base class of the type hierarchy.
bool isBlockPointerType() const
bool isFunctionReferenceType() const
bool isSignableType(const ASTContext &Ctx) const
bool isFunctionPointerType() 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.
llvm::Constant * getConstantSignedPointer(CodeGenModule &CGM, llvm::Constant *Pointer, unsigned Key, llvm::Constant *StorageAddress, llvm::ConstantInt *OtherDiscriminator)
Return a signed constant pointer.
uint16_t getPointerAuthTypeDiscriminator(CodeGenModule &CGM, QualType FunctionType)
Return a type discriminator for the given function type.
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
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.