20#include "llvm/Analysis/ValueTracking.h"
21#include "llvm/Support/SipHash.h"
35 assert(!
Type.isNull() &&
"type not provided for type-discriminated schema");
36 return llvm::ConstantInt::get(
40 assert(
Decl.getDecl() &&
41 "declaration not provided for decl-discriminated schema");
42 return llvm::ConstantInt::get(
IntPtrTy,
48 llvm_unreachable(
"bad discrimination kind");
64 uint16_t &EntityHash = PtrAuthDiscriminatorHashes[
Declaration];
66 if (EntityHash == 0) {
68 if (ND->hasAttr<AsmLabelAttr>() &&
69 ND->getAttr<AsmLabelAttr>()->getLabel().starts_with(
76 llvm::raw_svector_ostream Out(Buffer);
78 EntityHash = llvm::getPointerAuthStableSipHash(Out.str());
81 EntityHash = llvm::getPointerAuthStableSipHash(Name);
95 assert(!Schema.isAddressDiscriminated() &&
96 "function pointers cannot use address-specific discrimination");
98 llvm::Constant *Discriminator =
nullptr;
99 if (
T->isFunctionPointerType() ||
T->isFunctionReferenceType())
100 T =
T->getPointeeType();
101 if (
T->isFunctionType())
111 llvm::Value *Discriminator) {
113 auto Intrinsic =
CGM.getIntrinsic(llvm::Intrinsic::ptrauth_blend);
114 return Builder.CreateCall(Intrinsic, {StorageAddress, Discriminator});
125 llvm::Value *Discriminator =
126 CGM.getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType);
129 assert(StorageAddress &&
130 "address not provided for address-discriminated schema");
147 assert(Qual &&
"don't call this if you don't know that the Qual is present");
151 llvm::Value *Discriminator =
nullptr;
156 assert(StorageAddress.
isValid() &&
157 "address discrimination without address");
187 return ::getPointerAuthInfoForPointeeType(*
this,
T);
202 if (PointeeType.isNull())
205 return ::getPointerAuthInfoForPointeeType(CGM, PointeeType);
209 return ::getPointerAuthInfoForType(*
this,
T);
212static std::pair<llvm::Value *, CGPointerAuthInfo>
221 return {
Value, AuthInfo};
226std::pair<llvm::Value *, CGPointerAuthInfo>
231 if (
const auto *Load = dyn_cast<ImplicitCastExpr>(E)) {
232 if (Load->getCastKind() == CK_LValueToRValue) {
236 if (
const auto *RefExpr = dyn_cast<DeclRefExpr>(E)) {
239 if (!
Result.isReference())
240 return {
Result.getValue(),
264 assert(DestQualifier);
276 assert(DestQualifier);
287 Address CurStorageAddress,
bool IsKnownNonNull) {
288 assert(CurQualifier);
298 if (
const auto *CI = dyn_cast<llvm::ConstantInt>(
Value))
305 assert((Left.isSigned() || Right.isSigned()) &&
306 "shouldn't be called if neither is signed");
307 if (Left.isSigned() != Right.isSigned())
309 return Left.getKey() == Right.getKey() &&
310 Left.getAuthenticationMode() == Right.getAuthenticationMode() &&
311 Left.isIsaPointer() == Right.isIsaPointer() &&
312 Left.authenticatesNullValues() == Right.authenticatesNullValues() &&
313 Left.getDiscriminator() == Right.getDiscriminator();
320 return Discriminator ? Discriminator : Builder.getSize(0);
327 assert(CurAuth && NewAuth);
349 auto *Intrinsic =
CGM.getIntrinsic(llvm::Intrinsic::ptrauth_resign);
351 Intrinsic, {
Value, CurKey, CurDiscriminator, NewKey, NewDiscriminator});
362 if (!CurAuthInfo && !NewAuthInfo)
365 llvm::Value *Null =
nullptr;
367 if (
auto *PointerValue = dyn_cast<llvm::PointerType>(
Value->
getType())) {
368 Null =
CGM.getNullPointer(PointerValue,
Type);
371 Null = llvm::ConstantInt::get(
IntPtrTy, 0);
388 llvm::BasicBlock *InitBB =
Builder.GetInsertBlock();
389 llvm::BasicBlock *ResignBB =
nullptr, *ContBB =
nullptr;
393 if (!IsKnownNonNull && !llvm::isKnownNonZero(
Value,
CGM.getDataLayout())) {
398 Builder.CreateCondBr(IsNonNull, ResignBB, ContBB);
405 else if (!CurAuthInfo)
414 Phi->addIncoming(Null, InitBB);
415 Phi->addIncoming(
Value, ResignBB);
441 llvm::Constant *StorageAddress,
442 llvm::ConstantInt *OtherDiscriminator) {
443 llvm::Constant *AddressDiscriminator;
444 if (StorageAddress) {
446 AddressDiscriminator = StorageAddress;
448 AddressDiscriminator = llvm::Constant::getNullValue(
DefaultPtrTy);
451 llvm::ConstantInt *IntegerDiscriminator;
452 if (OtherDiscriminator) {
453 assert(OtherDiscriminator->getType() ==
Int64Ty);
454 IntegerDiscriminator = OtherDiscriminator;
456 IntegerDiscriminator = llvm::ConstantInt::get(
Int64Ty, 0);
459 return llvm::ConstantPtrAuth::get(
460 Pointer, llvm::ConstantInt::get(
Int32Ty, Key), IntegerDiscriminator,
461 AddressDiscriminator,
476 llvm::Constant *StorageAddress,
GlobalDecl SchemaDecl,
479 llvm::ConstantInt *OtherDiscriminator =
488 unsigned Key, llvm::Constant *StorageAddress,
489 llvm::ConstantInt *OtherDiscriminator) {
504 Pointer, PointerAuth.getKey(),
nullptr,
505 cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator()));
517 if (!FD->hasPrototype())
519 FuncType = Context.getFunctionNoProtoType(Proto->getReturnType(),
520 Proto->getExtInfo());
531 assert(!Schema.isAddressDiscriminated() &&
532 "function pointers cannot use address-specific discrimination");
534 llvm::ConstantInt *Discriminator =
538 false, Discriminator);
545 Pointer, PointerAuth.getKey(),
nullptr,
546 cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator()));
548 if (
const auto *MFT = dyn_cast<MemberPointerType>(FT.
getTypePtr())) {
549 if (MFT->hasPointeeToCFIUncheckedCalleeFunctionType())
564std::optional<PointerAuthQualifier>
565CodeGenModule::computeVTPointerAuthentication(
const CXXRecordDecl *ThisClass,
567 auto DefaultAuthentication =
570 if (!DefaultAuthentication)
573 Context.baseForVTableAuthentication(ThisClass);
575 IsVTTEntry ? ThisClass : PrimaryBase;
577 unsigned Key = DefaultAuthentication.getKey();
578 bool AddressDiscriminated = DefaultAuthentication.isAddressDiscriminated();
579 auto DefaultDiscrimination = DefaultAuthentication.getOtherDiscrimination();
580 unsigned TypeBasedDiscriminator =
581 Context.getPointerAuthVTablePointerDiscriminator(TypeDiscriminatorClass,
583 unsigned Discriminator;
585 Discriminator = TypeBasedDiscriminator;
586 }
else if (DefaultDiscrimination ==
588 Discriminator = DefaultAuthentication.getConstantDiscrimination();
593 auto ExplicitAuthentication =
594 PrimaryBase->
getAttr<VTablePointerAuthenticationAttr>();
597 if (!IsVTTEntry && ExplicitAuthentication) {
598 auto ExplicitAddressDiscrimination =
599 ExplicitAuthentication->getAddressDiscrimination();
600 auto ExplicitDiscriminator =
601 ExplicitAuthentication->getExtraDiscrimination();
603 unsigned ExplicitKey = ExplicitAuthentication->getKey();
604 if (ExplicitKey == VTablePointerAuthenticationAttr::NoKey)
607 if (ExplicitKey != VTablePointerAuthenticationAttr::DefaultKey) {
608 if (ExplicitKey == VTablePointerAuthenticationAttr::ProcessIndependent)
611 assert(ExplicitKey ==
612 VTablePointerAuthenticationAttr::ProcessDependent);
617 if (ExplicitAddressDiscrimination !=
618 VTablePointerAuthenticationAttr::DefaultAddressDiscrimination)
619 AddressDiscriminated =
620 ExplicitAddressDiscrimination ==
621 VTablePointerAuthenticationAttr::AddressDiscrimination;
623 if (ExplicitDiscriminator ==
624 VTablePointerAuthenticationAttr::TypeDiscrimination)
625 Discriminator = TypeBasedDiscriminator;
626 else if (ExplicitDiscriminator ==
627 VTablePointerAuthenticationAttr::CustomDiscrimination)
628 Discriminator = ExplicitAuthentication->getCustomDiscriminationValue();
629 else if (ExplicitDiscriminator ==
630 VTablePointerAuthenticationAttr::NoExtraDiscrimination)
639std::optional<PointerAuthQualifier>
642 if (!
Record->getDefinition() || !
Record->isPolymorphic())
646 return computeVTPointerAuthentication(
Record, IsVTTEntry);
648 auto Existing = VTablePtrAuthInfos.find(
Record);
649 if (Existing != VTablePtrAuthInfos.end())
650 return Existing->getSecond();
652 std::optional<PointerAuthQualifier> Authentication =
653 computeVTPointerAuthentication(
Record, IsVTTEntry);
654 VTablePtrAuthInfos.insert(std::make_pair(
Record, Authentication));
655 return Authentication;
660 llvm::Value *StorageAddress,
bool IsVTTEntry) {
665 llvm::Value *Discriminator =
nullptr;
666 if (
auto ExtraDiscriminator = Authentication->getExtraDiscriminator())
667 Discriminator = llvm::ConstantInt::get(
IntPtrTy, ExtraDiscriminator);
669 if (Authentication->isAddressDiscriminated()) {
670 assert(StorageAddress &&
671 "address not provided for address-discriminated schema");
682 false, Discriminator);
695 if (!CurAuthInfo && !NewAuthInfo)
701 CurAuthInfo =
CGM.getFunctionPointerAuthInfo(SourceType);
704 NewAuthInfo =
CGM.getFunctionPointerAuthInfo(DestType);
720 if (!CurAuthInfo && !NewAuthInfo)
727 Ptr.setPointerAuthInfo(
CGM.getFunctionPointerAuthInfo(SourceType));
732 NewAuthInfo =
CGM.getFunctionPointerAuthInfo(DestType);
733 Ptr = Ptr.getResignedAddress(NewAuthInfo, *
this);
745 :
CGM.getPointerAuthInfoForPointeeType(PointeeTy);
746 return Addr.getResignedAddress(Info, *
this);
751 assert(
isValid() &&
"pointer isn't valid");
760 assert(ElementType &&
"Effective type has to be set");
761 assert(!Offset &&
"unexpected non-null offset");
792 return Addr.isValid() ?
Addr.emitRawPointer(CGF) :
nullptr;
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 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 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.
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
MangleContext & getMangleContext()
Gets the mangle context.
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)
CGPointerAuthInfo EmitPointerAuthInfo(const PointerAuthSchema &Schema, llvm::Value *StorageAddress, llvm::ConstantInt *Discriminator)
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)
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.
std::optional< PointerAuthQualifier > getVTablePointerAuthentication(const CXXRecordDecl *thisClass, bool IsVTTEntry=false)
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.
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)
CGCXXABI & getCXXABI() 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)
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, bool IsVTTEntry=false)
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
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
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
virtual void mangleCXXName(GlobalDecl GD, raw_ostream &)=0
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.
Encodes a location in the source.
bool isBlockPointerType() const
bool isFunctionReferenceType() const
bool isSignableType(const ASTContext &Ctx) const
bool isFunctionPointerType() const
bool isFunctionType() const
const T * getAs() const
Member-template getAs<specific type>'.
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
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.
Top level wrappers for InstallAPI frontend operations.
@ Result
The result type of a method or function.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
llvm::IntegerType * Int64Ty
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::PointerType * DefaultPtrTy
static constexpr llvm::StringLiteral FunctionLabelPrefix
PointerAuthSchema CXXVTablePointers
The ABI for C++ virtual table pointers (the pointer to the table itself) as installed in an actual cl...
PointerAuthSchema CXXVTTVTablePointers
The ABI for C++ virtual table pointers as installed in a VTT.
PointerAuthSchema FunctionPointers
The ABI for C function pointers.
PointerAuthSchema CXXMemberFunctionPointers
The ABI for C++ member function pointers.