summaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGPointerAuth.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGPointerAuth.cpp')
-rw-r--r--clang/lib/CodeGen/CGPointerAuth.cpp129
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,