clang 22.0.0git
CGPointerAuth.cpp
Go to the documentation of this file.
1//===--- CGPointerAuth.cpp - IR generation for pointer authentication -----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains common routines relating to the emission of
10// pointer authentication operations.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CodeGenFunction.h"
15#include "CodeGenModule.h"
18#include "llvm/Analysis/ValueTracking.h"
19#include "llvm/Support/SipHash.h"
20
21using namespace clang;
22using namespace CodeGen;
23
24/// Given a pointer-authentication schema, return a concrete "other"
25/// discriminator for it.
28 switch (Schema.getOtherDiscrimination()) {
30 return nullptr;
31
33 assert(!Type.isNull() && "type not provided for type-discriminated schema");
34 return llvm::ConstantInt::get(
36
38 assert(Decl.getDecl() &&
39 "declaration not provided for decl-discriminated schema");
40 return llvm::ConstantInt::get(IntPtrTy,
42
44 return llvm::ConstantInt::get(IntPtrTy, Schema.getConstantDiscrimination());
45 }
46 llvm_unreachable("bad discrimination kind");
47}
48
52}
53
57}
58
59/// Return the "other" decl-specific discriminator for the given decl.
60uint16_t
62 uint16_t &EntityHash = PtrAuthDiscriminatorHashes[Declaration];
63
64 if (EntityHash == 0) {
65 StringRef Name = getMangledName(Declaration);
66 EntityHash = llvm::getPointerAuthStableSipHash(Name);
67 }
68
69 return EntityHash;
70}
71
72/// Return the abstract pointer authentication schema for a pointer to the given
73/// function type.
75 const auto &Schema = getCodeGenOpts().PointerAuth.FunctionPointers;
76 if (!Schema)
77 return CGPointerAuthInfo();
78
79 assert(!Schema.isAddressDiscriminated() &&
80 "function pointers cannot use address-specific discrimination");
81
82 llvm::Constant *Discriminator = nullptr;
84 T = T->getPointeeType();
85 if (T->isFunctionType())
86 Discriminator = getPointerAuthOtherDiscriminator(Schema, GlobalDecl(), T);
87
88 return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
89 /*IsaPointer=*/false, /*AuthenticatesNull=*/false,
90 Discriminator);
91}
92
93llvm::Value *
95 llvm::Value *Discriminator) {
96 StorageAddress = Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
97 auto Intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_blend);
98 return Builder.CreateCall(Intrinsic, {StorageAddress, Discriminator});
99}
100
101/// Emit the concrete pointer authentication informaton for the
102/// given authentication schema.
104 const PointerAuthSchema &Schema, llvm::Value *StorageAddress,
105 GlobalDecl SchemaDecl, QualType SchemaType) {
106 if (!Schema)
107 return CGPointerAuthInfo();
108
109 llvm::Value *Discriminator =
110 CGM.getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType);
111
112 if (Schema.isAddressDiscriminated()) {
113 assert(StorageAddress &&
114 "address not provided for address-discriminated schema");
115
116 if (Discriminator)
117 Discriminator =
118 EmitPointerAuthBlendDiscriminator(StorageAddress, Discriminator);
119 else
120 Discriminator = Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
121 }
122
123 return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
124 Schema.isIsaPointer(),
125 Schema.authenticatesNullValues(), Discriminator);
126}
127
130 Address StorageAddress) {
131 assert(Qual && "don't call this if you don't know that the Qual is present");
132 if (Qual.hasKeyNone())
133 return CGPointerAuthInfo();
134
135 llvm::Value *Discriminator = nullptr;
136 if (unsigned Extra = Qual.getExtraDiscriminator())
137 Discriminator = llvm::ConstantInt::get(IntPtrTy, Extra);
138
139 if (Qual.isAddressDiscriminated()) {
140 assert(StorageAddress.isValid() &&
141 "address discrimination without address");
142 llvm::Value *StoragePtr = StorageAddress.emitRawPointer(*this);
143 if (Discriminator)
144 Discriminator =
145 EmitPointerAuthBlendDiscriminator(StoragePtr, Discriminator);
146 else
147 Discriminator = Builder.CreatePtrToInt(StoragePtr, IntPtrTy);
148 }
149
150 return CGPointerAuthInfo(Qual.getKey(), Qual.getAuthenticationMode(),
152 Discriminator);
153}
154
155/// Return the natural pointer authentication for values of the given
156/// pointee type.
159 if (PointeeType.isNull())
160 return CGPointerAuthInfo();
161
162 // Function pointers use the function-pointer schema by default.
163 if (PointeeType->isFunctionType())
164 return CGM.getFunctionPointerAuthInfo(PointeeType);
165
166 // Normal data pointers never use direct pointer authentication by default.
167 return CGPointerAuthInfo();
168}
169
171 return ::getPointerAuthInfoForPointeeType(*this, T);
172}
173
174/// Return the natural pointer authentication for values of the given
175/// pointer type.
178 assert(PointerType->isSignableType(CGM.getContext()));
179
180 // Block pointers are currently not signed.
182 return CGPointerAuthInfo();
183
184 auto PointeeType = PointerType->getPointeeType();
185
186 if (PointeeType.isNull())
187 return CGPointerAuthInfo();
188
189 return ::getPointerAuthInfoForPointeeType(CGM, PointeeType);
190}
191
193 return ::getPointerAuthInfoForType(*this, T);
194}
195
196static std::pair<llvm::Value *, CGPointerAuthInfo>
199 llvm::Value *Value = CGF.EmitLoadOfScalar(LV, Loc);
200 CGPointerAuthInfo AuthInfo;
201 if (PointerAuthQualifier PtrAuth = LV.getQuals().getPointerAuth())
202 AuthInfo = CGF.EmitPointerAuthInfo(PtrAuth, LV.getAddress());
203 else
204 AuthInfo = getPointerAuthInfoForType(CGF.CGM, LV.getType());
205 return {Value, AuthInfo};
206}
207
208/// Retrieve a pointer rvalue and its ptrauth info. When possible, avoid
209/// needlessly resigning the pointer.
210std::pair<llvm::Value *, CGPointerAuthInfo>
212 assert(E->getType()->isSignableType(getContext()));
213
214 E = E->IgnoreParens();
215 if (const auto *Load = dyn_cast<ImplicitCastExpr>(E)) {
216 if (Load->getCastKind() == CK_LValueToRValue) {
217 E = Load->getSubExpr()->IgnoreParens();
218
219 // We're semantically required to not emit loads of certain DREs naively.
220 if (const auto *RefExpr = dyn_cast<DeclRefExpr>(E)) {
222 // Fold away a use of an intermediate variable.
223 if (!Result.isReference())
224 return {Result.getValue(),
225 getPointerAuthInfoForType(CGM, RefExpr->getType())};
226
227 // Fold away a use of an intermediate reference.
228 LValue LV = Result.getReferenceLValue(*this, RefExpr);
229 return emitLoadOfOrigPointerRValue(*this, LV, RefExpr->getLocation());
230 }
231 }
232
233 // Otherwise, load and use the pointer
235 return emitLoadOfOrigPointerRValue(*this, LV, E->getExprLoc());
236 }
237 }
238
239 // Fallback: just use the normal rules for the type.
240 llvm::Value *Value = EmitScalarExpr(E);
242}
243
244llvm::Value *
246 const Expr *E,
247 Address DestStorageAddress) {
248 assert(DestQualifier);
249 auto [Value, CurAuthInfo] = EmitOrigPointerRValue(E);
250
251 CGPointerAuthInfo DestAuthInfo =
252 EmitPointerAuthInfo(DestQualifier, DestStorageAddress);
253 return emitPointerAuthResign(Value, E->getType(), CurAuthInfo, DestAuthInfo,
255}
256
258 PointerAuthQualifier DestQualifier, llvm::Value *Value,
259 QualType PointerType, Address DestStorageAddress, bool IsKnownNonNull) {
260 assert(DestQualifier);
261
263 CGPointerAuthInfo DestAuthInfo =
264 EmitPointerAuthInfo(DestQualifier, DestStorageAddress);
265 return emitPointerAuthResign(Value, PointerType, CurAuthInfo, DestAuthInfo,
266 IsKnownNonNull);
267}
268
270 PointerAuthQualifier CurQualifier, llvm::Value *Value, QualType PointerType,
271 Address CurStorageAddress, bool IsKnownNonNull) {
272 assert(CurQualifier);
273
274 CGPointerAuthInfo CurAuthInfo =
275 EmitPointerAuthInfo(CurQualifier, CurStorageAddress);
277 return emitPointerAuthResign(Value, PointerType, CurAuthInfo, DestAuthInfo,
278 IsKnownNonNull);
279}
280
281static bool isZeroConstant(const llvm::Value *Value) {
282 if (const auto *CI = dyn_cast<llvm::ConstantInt>(Value))
283 return CI->isZero();
284 return false;
285}
286
287static bool equalAuthPolicies(const CGPointerAuthInfo &Left,
288 const CGPointerAuthInfo &Right) {
289 assert((Left.isSigned() || Right.isSigned()) &&
290 "shouldn't be called if neither is signed");
291 if (Left.isSigned() != Right.isSigned())
292 return false;
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();
298}
299
300// Return the discriminator or return zero if the discriminator is null.
301static llvm::Value *getDiscriminatorOrZero(const CGPointerAuthInfo &Info,
302 CGBuilderTy &Builder) {
303 llvm::Value *Discriminator = Info.getDiscriminator();
304 return Discriminator ? Discriminator : Builder.getSize(0);
305}
306
307llvm::Value *
309 const CGPointerAuthInfo &CurAuth,
310 const CGPointerAuthInfo &NewAuth) {
311 assert(CurAuth && NewAuth);
312
313 if (CurAuth.getAuthenticationMode() !=
315 NewAuth.getAuthenticationMode() !=
317 llvm::Value *AuthedValue = EmitPointerAuthAuth(CurAuth, Value);
318 return EmitPointerAuthSign(NewAuth, AuthedValue);
319 }
320 // Convert the pointer to intptr_t before signing it.
321 auto *OrigType = Value->getType();
322 Value = Builder.CreatePtrToInt(Value, IntPtrTy);
323
324 auto *CurKey = Builder.getInt32(CurAuth.getKey());
325 auto *NewKey = Builder.getInt32(NewAuth.getKey());
326
327 llvm::Value *CurDiscriminator = getDiscriminatorOrZero(CurAuth, Builder);
328 llvm::Value *NewDiscriminator = getDiscriminatorOrZero(NewAuth, Builder);
329
330 // call i64 @llvm.ptrauth.resign(i64 %pointer,
331 // i32 %curKey, i64 %curDiscriminator,
332 // i32 %newKey, i64 %newDiscriminator)
333 auto *Intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_resign);
335 Intrinsic, {Value, CurKey, CurDiscriminator, NewKey, NewDiscriminator});
336
337 // Convert back to the original type.
338 Value = Builder.CreateIntToPtr(Value, OrigType);
339 return Value;
340}
341
343 llvm::Value *Value, QualType Type, const CGPointerAuthInfo &CurAuthInfo,
344 const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull) {
345 // Fast path: if neither schema wants a signature, we're done.
346 if (!CurAuthInfo && !NewAuthInfo)
347 return Value;
348
349 llvm::Value *Null = nullptr;
350 // If the value is obviously null, we're done.
351 if (auto *PointerValue = dyn_cast<llvm::PointerType>(Value->getType())) {
352 Null = CGM.getNullPointer(PointerValue, Type);
353 } else {
354 assert(Value->getType()->isIntegerTy());
355 Null = llvm::ConstantInt::get(IntPtrTy, 0);
356 }
357 if (Value == Null)
358 return Value;
359
360 // If both schemas sign the same way, we're done.
361 if (equalAuthPolicies(CurAuthInfo, NewAuthInfo)) {
362 const llvm::Value *CurD = CurAuthInfo.getDiscriminator();
363 const llvm::Value *NewD = NewAuthInfo.getDiscriminator();
364 if (CurD == NewD)
365 return Value;
366
367 if ((CurD == nullptr && isZeroConstant(NewD)) ||
368 (NewD == nullptr && isZeroConstant(CurD)))
369 return Value;
370 }
371
372 llvm::BasicBlock *InitBB = Builder.GetInsertBlock();
373 llvm::BasicBlock *ResignBB = nullptr, *ContBB = nullptr;
374
375 // Null pointers have to be mapped to null, and the ptrauth_resign
376 // intrinsic doesn't do that.
377 if (!IsKnownNonNull && !llvm::isKnownNonZero(Value, CGM.getDataLayout())) {
378 ContBB = createBasicBlock("resign.cont");
379 ResignBB = createBasicBlock("resign.nonnull");
380
381 auto *IsNonNull = Builder.CreateICmpNE(Value, Null);
382 Builder.CreateCondBr(IsNonNull, ResignBB, ContBB);
383 EmitBlock(ResignBB);
384 }
385
386 // Perform the auth/sign/resign operation.
387 if (!NewAuthInfo)
388 Value = EmitPointerAuthAuth(CurAuthInfo, Value);
389 else if (!CurAuthInfo)
390 Value = EmitPointerAuthSign(NewAuthInfo, Value);
391 else
392 Value = emitPointerAuthResignCall(Value, CurAuthInfo, NewAuthInfo);
393
394 // Clean up with a phi if we branched before.
395 if (ContBB) {
396 EmitBlock(ContBB);
397 auto *Phi = Builder.CreatePHI(Value->getType(), 2);
398 Phi->addIncoming(Null, InitBB);
399 Phi->addIncoming(Value, ResignBB);
400 Value = Phi;
401 }
402
403 return Value;
404}
405
407 Address DestAddress,
408 Address SrcAddress) {
409 assert(Qual);
410 llvm::Value *Value = Builder.CreateLoad(SrcAddress);
411
412 // If we're using address-discrimination, we have to re-sign the value.
413 if (Qual.isAddressDiscriminated()) {
414 CGPointerAuthInfo SrcPtrAuth = EmitPointerAuthInfo(Qual, SrcAddress);
415 CGPointerAuthInfo DestPtrAuth = EmitPointerAuthInfo(Qual, DestAddress);
416 Value = emitPointerAuthResign(Value, T, SrcPtrAuth, DestPtrAuth,
417 /*IsKnownNonNull=*/false);
418 }
419
420 Builder.CreateStore(Value, DestAddress);
421}
422
423llvm::Constant *
425 llvm::Constant *StorageAddress,
426 llvm::ConstantInt *OtherDiscriminator) {
427 llvm::Constant *AddressDiscriminator;
428 if (StorageAddress) {
429 assert(StorageAddress->getType() == UnqualPtrTy);
430 AddressDiscriminator = StorageAddress;
431 } else {
432 AddressDiscriminator = llvm::Constant::getNullValue(UnqualPtrTy);
433 }
434
435 llvm::ConstantInt *IntegerDiscriminator;
436 if (OtherDiscriminator) {
437 assert(OtherDiscriminator->getType() == Int64Ty);
438 IntegerDiscriminator = OtherDiscriminator;
439 } else {
440 IntegerDiscriminator = llvm::ConstantInt::get(Int64Ty, 0);
441 }
442
443 return llvm::ConstantPtrAuth::get(Pointer,
444 llvm::ConstantInt::get(Int32Ty, Key),
445 IntegerDiscriminator, AddressDiscriminator);
446}
447
448/// Does a given PointerAuthScheme require us to sign a value
450 auto AuthenticationMode = Schema.getAuthenticationMode();
451 return AuthenticationMode == PointerAuthenticationMode::SignAndStrip ||
452 AuthenticationMode == PointerAuthenticationMode::SignAndAuth;
453}
454
455/// Sign a constant pointer using the given scheme, producing a constant
456/// with the same IR type.
458 llvm::Constant *Pointer, const PointerAuthSchema &Schema,
459 llvm::Constant *StorageAddress, GlobalDecl SchemaDecl,
460 QualType SchemaType) {
461 assert(shouldSignPointer(Schema));
462 llvm::ConstantInt *OtherDiscriminator =
463 getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType);
464
465 return getConstantSignedPointer(Pointer, Schema.getKey(), StorageAddress,
466 OtherDiscriminator);
467}
468
469llvm::Constant *
471 unsigned Key, llvm::Constant *StorageAddress,
472 llvm::ConstantInt *OtherDiscriminator) {
473 return CGM.getConstantSignedPointer(Pointer, Key, StorageAddress,
474 OtherDiscriminator);
475}
476
477/// If applicable, sign a given constant function pointer with the ABI rules for
478/// functionType.
479llvm::Constant *CodeGenModule::getFunctionPointer(llvm::Constant *Pointer,
481 assert(FunctionType->isFunctionType() ||
484
485 if (auto PointerAuth = getFunctionPointerAuthInfo(FunctionType))
487 Pointer, PointerAuth.getKey(), /*StorageAddress=*/nullptr,
488 cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator()));
489
490 return Pointer;
491}
492
494 llvm::Type *Ty) {
495 const auto *FD = cast<FunctionDecl>(GD.getDecl());
496 QualType FuncType = FD->getType();
497
498 // Annoyingly, K&R functions have prototypes in the clang AST, but
499 // expressions referring to them are unprototyped.
500 if (!FD->hasPrototype())
501 if (const auto *Proto = FuncType->getAs<FunctionProtoType>())
502 FuncType = Context.getFunctionNoProtoType(Proto->getReturnType(),
503 Proto->getExtInfo());
504
505 return getFunctionPointer(getRawFunctionPointer(GD, Ty), FuncType);
506}
507
509 assert(FT->getAs<MemberPointerType>() && "MemberPointerType expected");
511 if (!Schema)
512 return CGPointerAuthInfo();
513
514 assert(!Schema.isAddressDiscriminated() &&
515 "function pointers cannot use address-specific discrimination");
516
517 llvm::ConstantInt *Discriminator =
519 return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
520 /* IsIsaPointer */ false,
521 /* AuthenticatesNullValues */ false, Discriminator);
522}
523
524llvm::Constant *CodeGenModule::getMemberFunctionPointer(llvm::Constant *Pointer,
525 QualType FT) {
528 Pointer, PointerAuth.getKey(), nullptr,
529 cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator()));
530
531 if (const auto *MFT = dyn_cast<MemberPointerType>(FT.getTypePtr())) {
532 if (MFT->hasPointeeToToCFIUncheckedCalleeFunctionType())
533 Pointer = llvm::NoCFIValue::get(cast<llvm::GlobalValue>(Pointer));
534 }
535
536 return Pointer;
537}
538
540 llvm::Type *Ty) {
541 QualType FT = FD->getType();
542 FT = getContext().getMemberPointerType(FT, /*Qualifier=*/std::nullopt,
543 cast<CXXMethodDecl>(FD)->getParent());
545}
546
547std::optional<PointerAuthQualifier>
548CodeGenModule::computeVTPointerAuthentication(const CXXRecordDecl *ThisClass) {
549 auto DefaultAuthentication = getCodeGenOpts().PointerAuth.CXXVTablePointers;
550 if (!DefaultAuthentication)
551 return std::nullopt;
552 const CXXRecordDecl *PrimaryBase =
553 Context.baseForVTableAuthentication(ThisClass);
554
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;
561 if (DefaultDiscrimination == PointerAuthSchema::Discrimination::Type) {
562 Discriminator = TypeBasedDiscriminator;
563 } else if (DefaultDiscrimination ==
565 Discriminator = DefaultAuthentication.getConstantDiscrimination();
566 } else {
567 assert(DefaultDiscrimination == PointerAuthSchema::Discrimination::None);
568 Discriminator = 0;
569 }
570 if (auto ExplicitAuthentication =
571 PrimaryBase->getAttr<VTablePointerAuthenticationAttr>()) {
572 auto ExplicitAddressDiscrimination =
573 ExplicitAuthentication->getAddressDiscrimination();
574 auto ExplicitDiscriminator =
575 ExplicitAuthentication->getExtraDiscrimination();
576
577 unsigned ExplicitKey = ExplicitAuthentication->getKey();
578 if (ExplicitKey == VTablePointerAuthenticationAttr::NoKey)
579 return std::nullopt;
580
581 if (ExplicitKey != VTablePointerAuthenticationAttr::DefaultKey) {
582 if (ExplicitKey == VTablePointerAuthenticationAttr::ProcessIndependent)
584 else {
585 assert(ExplicitKey ==
586 VTablePointerAuthenticationAttr::ProcessDependent);
588 }
589 }
590
591 if (ExplicitAddressDiscrimination !=
592 VTablePointerAuthenticationAttr::DefaultAddressDiscrimination)
593 AddressDiscriminated =
594 ExplicitAddressDiscrimination ==
595 VTablePointerAuthenticationAttr::AddressDiscrimination;
596
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)
605 Discriminator = 0;
606 }
607 return PointerAuthQualifier::Create(Key, AddressDiscriminated, Discriminator,
609 /* IsIsaPointer */ false,
610 /* AuthenticatesNullValues */ false);
611}
612
613std::optional<PointerAuthQualifier>
615 if (!Record->getDefinition() || !Record->isPolymorphic())
616 return std::nullopt;
617
618 auto Existing = VTablePtrAuthInfos.find(Record);
619 std::optional<PointerAuthQualifier> Authentication;
620 if (Existing != VTablePtrAuthInfos.end()) {
621 Authentication = Existing->getSecond();
622 } else {
623 Authentication = computeVTPointerAuthentication(Record);
624 VTablePtrAuthInfos.insert(std::make_pair(Record, Authentication));
625 }
626 return Authentication;
627}
628
629std::optional<CGPointerAuthInfo>
631 const CXXRecordDecl *Record,
632 llvm::Value *StorageAddress) {
633 auto Authentication = getVTablePointerAuthentication(Record);
634 if (!Authentication)
635 return std::nullopt;
636
637 llvm::Value *Discriminator = nullptr;
638 if (auto ExtraDiscriminator = Authentication->getExtraDiscriminator())
639 Discriminator = llvm::ConstantInt::get(IntPtrTy, ExtraDiscriminator);
640
641 if (Authentication->isAddressDiscriminated()) {
642 assert(StorageAddress &&
643 "address not provided for address-discriminated schema");
644 if (Discriminator)
645 Discriminator =
646 CGF->EmitPointerAuthBlendDiscriminator(StorageAddress, Discriminator);
647 else
648 Discriminator = CGF->Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
649 }
650
651 return CGPointerAuthInfo(Authentication->getKey(),
653 /* IsIsaPointer */ false,
654 /* AuthenticatesNullValues */ false, Discriminator);
655}
656
657llvm::Value *CodeGenFunction::authPointerToPointerCast(llvm::Value *ResultPtr,
658 QualType SourceType,
659 QualType DestType) {
660 CGPointerAuthInfo CurAuthInfo, NewAuthInfo;
661 if (SourceType->isSignableType(getContext()))
662 CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType);
663
664 if (DestType->isSignableType(getContext()))
665 NewAuthInfo = getPointerAuthInfoForType(CGM, DestType);
666
667 if (!CurAuthInfo && !NewAuthInfo)
668 return ResultPtr;
669
670 // If only one side of the cast is a function pointer, then we still need to
671 // resign to handle casts to/from opaque pointers.
672 if (!CurAuthInfo && DestType->isFunctionPointerType())
673 CurAuthInfo = CGM.getFunctionPointerAuthInfo(SourceType);
674
675 if (!NewAuthInfo && SourceType->isFunctionPointerType())
676 NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
677
678 return emitPointerAuthResign(ResultPtr, DestType, CurAuthInfo, NewAuthInfo,
679 /*IsKnownNonNull=*/false);
680}
681
683 QualType SourceType,
684 QualType DestType) {
685 CGPointerAuthInfo CurAuthInfo, NewAuthInfo;
686 if (SourceType->isSignableType(getContext()))
687 CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType);
688
689 if (DestType->isSignableType(getContext()))
690 NewAuthInfo = getPointerAuthInfoForType(CGM, DestType);
691
692 if (!CurAuthInfo && !NewAuthInfo)
693 return Ptr;
694
695 if (!CurAuthInfo && DestType->isFunctionPointerType()) {
696 // When casting a non-signed pointer to a function pointer, just set the
697 // auth info on Ptr to the assumed schema. The pointer will be resigned to
698 // the effective type when used.
700 return Ptr;
701 }
702
703 if (!NewAuthInfo && SourceType->isFunctionPointerType()) {
704 NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
705 Ptr = Ptr.getResignedAddress(NewAuthInfo, *this);
707 return Ptr;
708 }
709
710 return Ptr;
711}
712
714 QualType PointeeTy) {
715 CGPointerAuthInfo Info =
716 PointeeTy.isNull() ? CGPointerAuthInfo()
718 return Addr.getResignedAddress(Info, *this);
719}
720
722 CodeGenFunction &CGF) const {
723 assert(isValid() && "pointer isn't valid");
725 llvm::Value *Val;
726
727 // Nothing to do if neither the current or the new ptrauth info needs signing.
728 if (!CurInfo.isSigned() && !NewInfo.isSigned())
731
732 assert(ElementType && "Effective type has to be set");
733 assert(!Offset && "unexpected non-null offset");
734
735 // If the current and the new ptrauth infos are the same and the offset is
736 // null, just cast the base pointer to the effective type.
737 if (CurInfo == NewInfo && !hasOffset())
738 Val = getBasePointer();
739 else
740 Val = CGF.emitPointerAuthResign(getBasePointer(), QualType(), CurInfo,
741 NewInfo, isKnownNonNull());
742
743 return Address(Val, getElementType(), getAlignment(), NewInfo,
744 /*Offset=*/nullptr, isKnownNonNull());
745}
746
747llvm::Value *Address::emitRawPointerSlow(CodeGenFunction &CGF) const {
748 return CGF.getAsNaturalPointerTo(*this, QualType());
749}
750
751llvm::Value *LValue::getPointer(CodeGenFunction &CGF) const {
752 assert(isSimple());
753 return emitResignedPointer(getType(), CGF);
754}
755
757 CodeGenFunction &CGF) const {
758 assert(isSimple());
759 return CGF.getAsNaturalAddressOf(Addr, PointeeTy).getBasePointer();
760}
761
762llvm::Value *LValue::emitRawPointer(CodeGenFunction &CGF) const {
763 assert(isSimple());
764 return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr;
765}
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.
Expr * E
llvm::MachO::Record Record
Definition: MachO.h:31
SourceLocation Loc
Definition: SemaObjC.cpp:754
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.
Definition: DeclCXX.h:258
PointerAuthOptions PointerAuth
Configuration for pointer-signing.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
Definition: Address.h:128
llvm::Value * getBasePointer() const
Definition: Address.h:198
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Definition: Address.h:253
CharUnits getAlignment() const
Definition: Address.h:194
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Definition: Address.h:209
void setPointerAuthInfo(const CGPointerAuthInfo &Info)
Definition: Address.h:221
bool hasOffset() const
Definition: Address.h:244
KnownNonNull_t isKnownNonNull() const
Whether the pointer is known not to be null.
Definition: Address.h:233
Address getResignedAddress(const CGPointerAuthInfo &NewInfo, CodeGenFunction &CGF) const
const CGPointerAuthInfo & getPointerAuthInfo() const
Definition: Address.h:220
bool isValid() const
Definition: Address.h:177
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Definition: CGBuilder.h:140
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
Definition: CGBuilder.h:112
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)
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.
Definition: CGExpr.cpp:1596
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.
Definition: CGExpr.cpp:1864
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.
Definition: CGStmt.cpp:652
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.
Definition: CGExpr.cpp:3096
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.
Definition: CGValue.h:182
llvm::Value * emitResignedPointer(QualType PointeeTy, CodeGenFunction &CGF) const
bool isSimple() const
Definition: CGValue.h:278
llvm::Value * getPointer(CodeGenFunction &CGF) const
const Qualifiers & getQuals() const
Definition: CGValue.h:338
Address getAddress() const
Definition: CGValue.h:361
QualType getType() const
Definition: CGValue.h:291
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
T * getAttr() const
Definition: DeclBase.h:573
This represents one expression.
Definition: Expr.h:112
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3069
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:273
QualType getType() const
Definition: Expr.h:144
Represents a function declaration or definition.
Definition: Decl.h:1999
Represents a prototype with parameter type info, e.g.
Definition: TypeBase.h:5282
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition: TypeBase.h:4478
GlobalDecl - represents a global declaration.
Definition: GlobalDecl.h:57
const Decl * getDecl() const
Definition: GlobalDecl.h:106
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition: TypeBase.h:3669
Pointer-authentication qualifiers.
Definition: TypeBase.h:152
bool isIsaPointer() const
Definition: TypeBase.h:280
static PointerAuthQualifier Create(unsigned Key, bool IsAddressDiscriminated, unsigned ExtraDiscriminator, PointerAuthenticationMode AuthenticationMode, bool IsIsaPointer, bool AuthenticatesNullValues)
Definition: TypeBase.h:239
bool authenticatesNullValues() const
Definition: TypeBase.h:285
bool isAddressDiscriminated() const
Definition: TypeBase.h:265
unsigned getExtraDiscriminator() const
Definition: TypeBase.h:270
PointerAuthenticationMode getAuthenticationMode() const
Definition: TypeBase.h:275
unsigned getKey() const
Definition: TypeBase.h:258
Discrimination getOtherDiscrimination() 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.
PointerAuthenticationMode getAuthenticationMode() const
uint16_t getConstantDiscrimination() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: TypeBase.h:3346
QualType getPointeeType() const
Definition: TypeBase.h:3356
A (possibly-)qualified type.
Definition: TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: TypeBase.h:8343
PointerAuthQualifier getPointerAuth() const
Definition: TypeBase.h:603
Encodes a location in the source.
The base class of the type hierarchy.
Definition: TypeBase.h:1833
bool isBlockPointerType() const
Definition: TypeBase.h:8600
bool isFunctionReferenceType() const
Definition: TypeBase.h:8654
bool isSignableType(const ASTContext &Ctx) const
Definition: TypeBase.h:8592
bool isFunctionPointerType() const
Definition: TypeBase.h:8647
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:752
bool isFunctionType() const
Definition: TypeBase.h:8576
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
QualType getType() const
Definition: Decl.h:722
QualType getType() const
Definition: Value.cpp:237
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
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.