18#include "llvm/Analysis/ValueTracking.h" 
   19#include "llvm/Support/SipHash.h" 
   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;
 
   83  if (
T->isFunctionPointerType() || 
T->isFunctionReferenceType())
 
   84    T = 
T->getPointeeType();
 
   85  if (
T->isFunctionType())
 
 
   95                                                   llvm::Value *Discriminator) {
 
   97  auto Intrinsic = 
CGM.getIntrinsic(llvm::Intrinsic::ptrauth_blend);
 
   98  return Builder.CreateCall(Intrinsic, {StorageAddress, Discriminator});
 
 
  109  llvm::Value *Discriminator =
 
  110      CGM.getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType);
 
  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);
 
  333  auto *Intrinsic = 
CGM.getIntrinsic(llvm::Intrinsic::ptrauth_resign);
 
  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())) {
 
  352    Null = 
CGM.getNullPointer(PointerValue, 
Type);
 
  355    Null = llvm::ConstantInt::get(
IntPtrTy, 0);
 
  372  llvm::BasicBlock *InitBB = 
Builder.GetInsertBlock();
 
  373  llvm::BasicBlock *ResignBB = 
nullptr, *ContBB = 
nullptr;
 
  377  if (!IsKnownNonNull && !llvm::isKnownNonZero(
Value, 
CGM.getDataLayout())) {
 
  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(
DefaultPtrTy);
 
  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()));
 
 
  500  if (!FD->hasPrototype())
 
  502      FuncType = Context.getFunctionNoProtoType(Proto->getReturnType(),
 
  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())
 
 
  547std::optional<PointerAuthQualifier>
 
  548CodeGenModule::computeVTPointerAuthentication(
const CXXRecordDecl *ThisClass) {
 
  550  if (!DefaultAuthentication)
 
  553      Context.baseForVTableAuthentication(ThisClass);
 
  555  unsigned Key = DefaultAuthentication.getKey();
 
  556  bool AddressDiscriminated = DefaultAuthentication.isAddressDiscriminated();
 
  557  auto DefaultDiscrimination = DefaultAuthentication.getOtherDiscrimination();
 
  558  unsigned TypeBasedDiscriminator =
 
  559      Context.getPointerAuthVTablePointerDiscriminator(PrimaryBase);
 
  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)
 
  673    CurAuthInfo = 
CGM.getFunctionPointerAuthInfo(SourceType);
 
  676    NewAuthInfo = 
CGM.getFunctionPointerAuthInfo(DestType);
 
 
  692  if (!CurAuthInfo && !NewAuthInfo)
 
  704    NewAuthInfo = 
CGM.getFunctionPointerAuthInfo(DestType);
 
 
  717                         : 
CGM.getPointerAuthInfoForPointeeType(PointeeTy);
 
  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");
 
 
  764  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.
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
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.
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)
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.
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
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.
The JSON file list parser is used to communicate input to InstallAPI.
@ 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
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.