diff options
Diffstat (limited to 'clang/lib/CodeGen/CGPointerAuth.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGPointerAuth.cpp | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp index 4b032306ead7..0a183a8524c1 100644 --- a/clang/lib/CodeGen/CGPointerAuth.cpp +++ b/clang/lib/CodeGen/CGPointerAuth.cpp @@ -125,6 +125,33 @@ CGPointerAuthInfo CodeGenFunction::EmitPointerAuthInfo( Schema.authenticatesNullValues(), Discriminator); } +CGPointerAuthInfo +CodeGenFunction::EmitPointerAuthInfo(PointerAuthQualifier Qual, + Address StorageAddress) { + assert(Qual && "don't call this if you don't know that the Qual is present"); + if (Qual.hasKeyNone()) + return CGPointerAuthInfo(); + + llvm::Value *Discriminator = nullptr; + if (unsigned Extra = Qual.getExtraDiscriminator()) + Discriminator = llvm::ConstantInt::get(IntPtrTy, Extra); + + if (Qual.isAddressDiscriminated()) { + assert(StorageAddress.isValid() && + "address discrimination without address"); + llvm::Value *StoragePtr = StorageAddress.emitRawPointer(*this); + if (Discriminator) + Discriminator = + EmitPointerAuthBlendDiscriminator(StoragePtr, Discriminator); + else + Discriminator = Builder.CreatePtrToInt(StoragePtr, IntPtrTy); + } + + return CGPointerAuthInfo(Qual.getKey(), Qual.getAuthenticationMode(), + Qual.isIsaPointer(), Qual.authenticatesNullValues(), + Discriminator); +} + /// Return the natural pointer authentication for values of the given /// pointee type. static CGPointerAuthInfo @@ -166,6 +193,91 @@ CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForType(QualType T) { return ::getPointerAuthInfoForType(*this, T); } +static std::pair<llvm::Value *, CGPointerAuthInfo> +emitLoadOfOrigPointerRValue(CodeGenFunction &CGF, const LValue &LV, + SourceLocation Loc) { + llvm::Value *Value = CGF.EmitLoadOfScalar(LV, Loc); + CGPointerAuthInfo AuthInfo; + if (PointerAuthQualifier PtrAuth = LV.getQuals().getPointerAuth()) + AuthInfo = CGF.EmitPointerAuthInfo(PtrAuth, LV.getAddress()); + else + AuthInfo = getPointerAuthInfoForType(CGF.CGM, LV.getType()); + return {Value, AuthInfo}; +} + +/// Retrieve a pointer rvalue and its ptrauth info. When possible, avoid +/// needlessly resigning the pointer. +std::pair<llvm::Value *, CGPointerAuthInfo> +CodeGenFunction::EmitOrigPointerRValue(const Expr *E) { + assert(E->getType()->isSignableType()); + + E = E->IgnoreParens(); + if (const auto *Load = dyn_cast<ImplicitCastExpr>(E)) { + if (Load->getCastKind() == CK_LValueToRValue) { + E = Load->getSubExpr()->IgnoreParens(); + + // We're semantically required to not emit loads of certain DREs naively. + if (const auto *RefExpr = dyn_cast<DeclRefExpr>(E)) { + if (ConstantEmission Result = tryEmitAsConstant(RefExpr)) { + // Fold away a use of an intermediate variable. + if (!Result.isReference()) + return {Result.getValue(), + getPointerAuthInfoForType(CGM, RefExpr->getType())}; + + // Fold away a use of an intermediate reference. + LValue LV = Result.getReferenceLValue(*this, RefExpr); + return emitLoadOfOrigPointerRValue(*this, LV, RefExpr->getLocation()); + } + } + + // Otherwise, load and use the pointer + LValue LV = EmitCheckedLValue(E, CodeGenFunction::TCK_Load); + return emitLoadOfOrigPointerRValue(*this, LV, E->getExprLoc()); + } + } + + // Fallback: just use the normal rules for the type. + llvm::Value *Value = EmitScalarExpr(E); + return {Value, getPointerAuthInfoForType(CGM, E->getType())}; +} + +llvm::Value * +CodeGenFunction::EmitPointerAuthQualify(PointerAuthQualifier DestQualifier, + const Expr *E, + Address DestStorageAddress) { + assert(DestQualifier); + auto [Value, CurAuthInfo] = EmitOrigPointerRValue(E); + + CGPointerAuthInfo DestAuthInfo = + EmitPointerAuthInfo(DestQualifier, DestStorageAddress); + return emitPointerAuthResign(Value, E->getType(), CurAuthInfo, DestAuthInfo, + isPointerKnownNonNull(E)); +} + +llvm::Value *CodeGenFunction::EmitPointerAuthQualify( + PointerAuthQualifier DestQualifier, llvm::Value *Value, + QualType PointerType, Address DestStorageAddress, bool IsKnownNonNull) { + assert(DestQualifier); + + CGPointerAuthInfo CurAuthInfo = getPointerAuthInfoForType(CGM, PointerType); + CGPointerAuthInfo DestAuthInfo = + EmitPointerAuthInfo(DestQualifier, DestStorageAddress); + return emitPointerAuthResign(Value, PointerType, CurAuthInfo, DestAuthInfo, + IsKnownNonNull); +} + +llvm::Value *CodeGenFunction::EmitPointerAuthUnqualify( + PointerAuthQualifier CurQualifier, llvm::Value *Value, QualType PointerType, + Address CurStorageAddress, bool IsKnownNonNull) { + assert(CurQualifier); + + CGPointerAuthInfo CurAuthInfo = + EmitPointerAuthInfo(CurQualifier, CurStorageAddress); + CGPointerAuthInfo DestAuthInfo = getPointerAuthInfoForType(CGM, PointerType); + return emitPointerAuthResign(Value, PointerType, CurAuthInfo, DestAuthInfo, + IsKnownNonNull); +} + static bool isZeroConstant(const llvm::Value *Value) { if (const auto *CI = dyn_cast<llvm::ConstantInt>(Value)) return CI->isZero(); @@ -288,6 +400,23 @@ llvm::Value *CodeGenFunction::emitPointerAuthResign( return Value; } +void CodeGenFunction::EmitPointerAuthCopy(PointerAuthQualifier Qual, QualType T, + Address DestAddress, + Address SrcAddress) { + assert(Qual); + llvm::Value *Value = Builder.CreateLoad(SrcAddress); + + // If we're using address-discrimination, we have to re-sign the value. + if (Qual.isAddressDiscriminated()) { + CGPointerAuthInfo SrcPtrAuth = EmitPointerAuthInfo(Qual, SrcAddress); + CGPointerAuthInfo DestPtrAuth = EmitPointerAuthInfo(Qual, DestAddress); + Value = emitPointerAuthResign(Value, T, SrcPtrAuth, DestPtrAuth, + /*IsKnownNonNull=*/false); + } + + Builder.CreateStore(Value, DestAddress); +} + llvm::Constant * CodeGenModule::getConstantSignedPointer(llvm::Constant *Pointer, unsigned Key, llvm::Constant *StorageAddress, |
