clang 24.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 "CGCXXABI.h"
15#include "CodeGenFunction.h"
16#include "CodeGenModule.h"
17#include "clang/AST/Attr.h"
20#include "llvm/Analysis/ValueTracking.h"
21#include "llvm/Support/SipHash.h"
22
23using namespace clang;
24using namespace CodeGen;
25
26/// Given a pointer-authentication schema, return a concrete "other"
27/// discriminator for it.
30 switch (Schema.getOtherDiscrimination()) {
32 return nullptr;
33
35 assert(!Type.isNull() && "type not provided for type-discriminated schema");
36 return llvm::ConstantInt::get(
38
40 assert(Decl.getDecl() &&
41 "declaration not provided for decl-discriminated schema");
42 return llvm::ConstantInt::get(IntPtrTy,
44
46 return llvm::ConstantInt::get(IntPtrTy, Schema.getConstantDiscrimination());
47 }
48 llvm_unreachable("bad discrimination kind");
49}
50
55
60
61/// Return the "other" decl-specific discriminator for the given decl.
62uint16_t
64 uint16_t &EntityHash = PtrAuthDiscriminatorHashes[Declaration];
65
66 if (EntityHash == 0) {
67 const auto *ND = cast<NamedDecl>(Declaration.getDecl());
68 if (ND->hasAttr<AsmLabelAttr>() &&
69 ND->getAttr<AsmLabelAttr>()->getLabel().starts_with(
71 // If the declaration comes from LLDB, the asm label has a prefix that
72 // would producing a different discriminator. Compute the real C++ mangled
73 // name instead so the discriminator matches what the original translation
74 // unit used.
75 SmallString<256> Buffer;
76 llvm::raw_svector_ostream Out(Buffer);
78 EntityHash = llvm::getPointerAuthStableSipHash(Out.str());
79 } else {
80 StringRef Name = getMangledName(Declaration);
81 EntityHash = llvm::getPointerAuthStableSipHash(Name);
82 }
83 }
84
85 return EntityHash;
86}
87
88/// Return the abstract pointer authentication schema for a pointer to the given
89/// function type.
91 const auto &Schema = getCodeGenOpts().PointerAuth.FunctionPointers;
92 if (!Schema)
93 return CGPointerAuthInfo();
94
95 assert(!Schema.isAddressDiscriminated() &&
96 "function pointers cannot use address-specific discrimination");
97
98 llvm::Constant *Discriminator = nullptr;
99 if (T->isFunctionPointerType() || T->isFunctionReferenceType())
100 T = T->getPointeeType();
101 if (T->isFunctionType())
102 Discriminator = getPointerAuthOtherDiscriminator(Schema, GlobalDecl(), T);
103
104 return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
105 /*IsaPointer=*/false, /*AuthenticatesNull=*/false,
106 Discriminator);
107}
108
109llvm::Value *
111 llvm::Value *Discriminator) {
112 StorageAddress = Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
113 auto Intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_blend);
114 return Builder.CreateCall(Intrinsic, {StorageAddress, Discriminator});
115}
116
117/// Emit the concrete pointer authentication informaton for the
118/// given authentication schema.
120 const PointerAuthSchema &Schema, llvm::Value *StorageAddress,
121 GlobalDecl SchemaDecl, QualType SchemaType) {
122 if (!Schema)
123 return CGPointerAuthInfo();
124
125 llvm::Value *Discriminator =
126 CGM.getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType);
127
128 if (Schema.isAddressDiscriminated()) {
129 assert(StorageAddress &&
130 "address not provided for address-discriminated schema");
131
132 if (Discriminator)
133 Discriminator =
134 EmitPointerAuthBlendDiscriminator(StorageAddress, Discriminator);
135 else
136 Discriminator = Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
137 }
138
139 return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
140 Schema.isIsaPointer(),
141 Schema.authenticatesNullValues(), Discriminator);
142}
143
146 Address StorageAddress) {
147 assert(Qual && "don't call this if you don't know that the Qual is present");
148 if (Qual.hasKeyNone())
149 return CGPointerAuthInfo();
150
151 llvm::Value *Discriminator = nullptr;
152 if (unsigned Extra = Qual.getExtraDiscriminator())
153 Discriminator = llvm::ConstantInt::get(IntPtrTy, Extra);
154
155 if (Qual.isAddressDiscriminated()) {
156 assert(StorageAddress.isValid() &&
157 "address discrimination without address");
158 llvm::Value *StoragePtr = StorageAddress.emitRawPointer(*this);
159 if (Discriminator)
160 Discriminator =
161 EmitPointerAuthBlendDiscriminator(StoragePtr, Discriminator);
162 else
163 Discriminator = Builder.CreatePtrToInt(StoragePtr, IntPtrTy);
164 }
165
166 return CGPointerAuthInfo(Qual.getKey(), Qual.getAuthenticationMode(),
168 Discriminator);
169}
170
171/// Return the natural pointer authentication for values of the given
172/// pointee type.
175 if (PointeeType.isNull())
176 return CGPointerAuthInfo();
177
178 // Function pointers use the function-pointer schema by default.
179 if (PointeeType->isFunctionType())
180 return CGM.getFunctionPointerAuthInfo(PointeeType);
181
182 // Normal data pointers never use direct pointer authentication by default.
183 return CGPointerAuthInfo();
184}
185
187 return ::getPointerAuthInfoForPointeeType(*this, T);
188}
189
190/// Return the natural pointer authentication for values of the given
191/// pointer type.
194 assert(PointerType->isSignableType(CGM.getContext()));
195
196 // Block pointers are currently not signed.
198 return CGPointerAuthInfo();
199
200 auto PointeeType = PointerType->getPointeeType();
201
202 if (PointeeType.isNull())
203 return CGPointerAuthInfo();
204
205 return ::getPointerAuthInfoForPointeeType(CGM, PointeeType);
206}
207
209 return ::getPointerAuthInfoForType(*this, T);
210}
211
212static std::pair<llvm::Value *, CGPointerAuthInfo>
214 SourceLocation Loc) {
215 llvm::Value *Value = CGF.EmitLoadOfScalar(LV, Loc);
216 CGPointerAuthInfo AuthInfo;
217 if (PointerAuthQualifier PtrAuth = LV.getQuals().getPointerAuth())
218 AuthInfo = CGF.EmitPointerAuthInfo(PtrAuth, LV.getAddress());
219 else
220 AuthInfo = getPointerAuthInfoForType(CGF.CGM, LV.getType());
221 return {Value, AuthInfo};
222}
223
224/// Retrieve a pointer rvalue and its ptrauth info. When possible, avoid
225/// needlessly resigning the pointer.
226std::pair<llvm::Value *, CGPointerAuthInfo>
228 assert(E->getType()->isSignableType(getContext()));
229
230 E = E->IgnoreParens();
231 if (const auto *Load = dyn_cast<ImplicitCastExpr>(E)) {
232 if (Load->getCastKind() == CK_LValueToRValue) {
233 E = Load->getSubExpr()->IgnoreParens();
234
235 // We're semantically required to not emit loads of certain DREs naively.
236 if (const auto *RefExpr = dyn_cast<DeclRefExpr>(E)) {
238 // Fold away a use of an intermediate variable.
239 if (!Result.isReference())
240 return {Result.getValue(),
241 getPointerAuthInfoForType(CGM, RefExpr->getType())};
242
243 // Fold away a use of an intermediate reference.
244 LValue LV = Result.getReferenceLValue(*this, RefExpr);
245 return emitLoadOfOrigPointerRValue(*this, LV, RefExpr->getLocation());
246 }
247 }
248
249 // Otherwise, load and use the pointer
251 return emitLoadOfOrigPointerRValue(*this, LV, E->getExprLoc());
252 }
253 }
254
255 // Fallback: just use the normal rules for the type.
256 llvm::Value *Value = EmitScalarExpr(E);
258}
259
260llvm::Value *
262 const Expr *E,
263 Address DestStorageAddress) {
264 assert(DestQualifier);
265 auto [Value, CurAuthInfo] = EmitOrigPointerRValue(E);
266
267 CGPointerAuthInfo DestAuthInfo =
268 EmitPointerAuthInfo(DestQualifier, DestStorageAddress);
269 return emitPointerAuthResign(Value, E->getType(), CurAuthInfo, DestAuthInfo,
271}
272
274 PointerAuthQualifier DestQualifier, llvm::Value *Value,
275 QualType PointerType, Address DestStorageAddress, bool IsKnownNonNull) {
276 assert(DestQualifier);
277
279 CGPointerAuthInfo DestAuthInfo =
280 EmitPointerAuthInfo(DestQualifier, DestStorageAddress);
281 return emitPointerAuthResign(Value, PointerType, CurAuthInfo, DestAuthInfo,
282 IsKnownNonNull);
283}
284
286 PointerAuthQualifier CurQualifier, llvm::Value *Value, QualType PointerType,
287 Address CurStorageAddress, bool IsKnownNonNull) {
288 assert(CurQualifier);
289
290 CGPointerAuthInfo CurAuthInfo =
291 EmitPointerAuthInfo(CurQualifier, CurStorageAddress);
293 return emitPointerAuthResign(Value, PointerType, CurAuthInfo, DestAuthInfo,
294 IsKnownNonNull);
295}
296
297static bool isZeroConstant(const llvm::Value *Value) {
298 if (const auto *CI = dyn_cast<llvm::ConstantInt>(Value))
299 return CI->isZero();
300 return false;
301}
302
303static bool equalAuthPolicies(const CGPointerAuthInfo &Left,
304 const CGPointerAuthInfo &Right) {
305 assert((Left.isSigned() || Right.isSigned()) &&
306 "shouldn't be called if neither is signed");
307 if (Left.isSigned() != Right.isSigned())
308 return false;
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();
314}
315
316// Return the discriminator or return zero if the discriminator is null.
317static llvm::Value *getDiscriminatorOrZero(const CGPointerAuthInfo &Info,
318 CGBuilderTy &Builder) {
319 llvm::Value *Discriminator = Info.getDiscriminator();
320 return Discriminator ? Discriminator : Builder.getSize(0);
321}
322
323llvm::Value *
325 const CGPointerAuthInfo &CurAuth,
326 const CGPointerAuthInfo &NewAuth) {
327 assert(CurAuth && NewAuth);
328
329 if (CurAuth.getAuthenticationMode() !=
331 NewAuth.getAuthenticationMode() !=
333 llvm::Value *AuthedValue = EmitPointerAuthAuth(CurAuth, Value);
334 return EmitPointerAuthSign(NewAuth, AuthedValue);
335 }
336 // Convert the pointer to intptr_t before signing it.
337 auto *OrigType = Value->getType();
338 Value = Builder.CreatePtrToInt(Value, IntPtrTy);
339
340 auto *CurKey = Builder.getInt32(CurAuth.getKey());
341 auto *NewKey = Builder.getInt32(NewAuth.getKey());
342
343 llvm::Value *CurDiscriminator = getDiscriminatorOrZero(CurAuth, Builder);
344 llvm::Value *NewDiscriminator = getDiscriminatorOrZero(NewAuth, Builder);
345
346 // call i64 @llvm.ptrauth.resign(i64 %pointer,
347 // i32 %curKey, i64 %curDiscriminator,
348 // i32 %newKey, i64 %newDiscriminator)
349 auto *Intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_resign);
351 Intrinsic, {Value, CurKey, CurDiscriminator, NewKey, NewDiscriminator});
352
353 // Convert back to the original type.
354 Value = Builder.CreateIntToPtr(Value, OrigType);
355 return Value;
356}
357
359 llvm::Value *Value, QualType Type, const CGPointerAuthInfo &CurAuthInfo,
360 const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull) {
361 // Fast path: if neither schema wants a signature, we're done.
362 if (!CurAuthInfo && !NewAuthInfo)
363 return Value;
364
365 llvm::Value *Null = nullptr;
366 // If the value is obviously null, we're done.
367 if (auto *PointerValue = dyn_cast<llvm::PointerType>(Value->getType())) {
368 Null = CGM.getNullPointer(PointerValue, Type);
369 } else {
370 assert(Value->getType()->isIntegerTy());
371 Null = llvm::ConstantInt::get(IntPtrTy, 0);
372 }
373 if (Value == Null)
374 return Value;
375
376 // If both schemas sign the same way, we're done.
377 if (equalAuthPolicies(CurAuthInfo, NewAuthInfo)) {
378 const llvm::Value *CurD = CurAuthInfo.getDiscriminator();
379 const llvm::Value *NewD = NewAuthInfo.getDiscriminator();
380 if (CurD == NewD)
381 return Value;
382
383 if ((CurD == nullptr && isZeroConstant(NewD)) ||
384 (NewD == nullptr && isZeroConstant(CurD)))
385 return Value;
386 }
387
388 llvm::BasicBlock *InitBB = Builder.GetInsertBlock();
389 llvm::BasicBlock *ResignBB = nullptr, *ContBB = nullptr;
390
391 // Null pointers have to be mapped to null, and the ptrauth_resign
392 // intrinsic doesn't do that.
393 if (!IsKnownNonNull && !llvm::isKnownNonZero(Value, CGM.getDataLayout())) {
394 ContBB = createBasicBlock("resign.cont");
395 ResignBB = createBasicBlock("resign.nonnull");
396
397 auto *IsNonNull = Builder.CreateICmpNE(Value, Null);
398 Builder.CreateCondBr(IsNonNull, ResignBB, ContBB);
399 EmitBlock(ResignBB);
400 }
401
402 // Perform the auth/sign/resign operation.
403 if (!NewAuthInfo)
404 Value = EmitPointerAuthAuth(CurAuthInfo, Value);
405 else if (!CurAuthInfo)
406 Value = EmitPointerAuthSign(NewAuthInfo, Value);
407 else
408 Value = emitPointerAuthResignCall(Value, CurAuthInfo, NewAuthInfo);
409
410 // Clean up with a phi if we branched before.
411 if (ContBB) {
412 EmitBlock(ContBB);
413 auto *Phi = Builder.CreatePHI(Value->getType(), 2);
414 Phi->addIncoming(Null, InitBB);
415 Phi->addIncoming(Value, ResignBB);
416 Value = Phi;
417 }
418
419 return Value;
420}
421
423 Address DestAddress,
424 Address SrcAddress) {
425 assert(Qual);
426 llvm::Value *Value = Builder.CreateLoad(SrcAddress);
427
428 // If we're using address-discrimination, we have to re-sign the value.
429 if (Qual.isAddressDiscriminated()) {
430 CGPointerAuthInfo SrcPtrAuth = EmitPointerAuthInfo(Qual, SrcAddress);
431 CGPointerAuthInfo DestPtrAuth = EmitPointerAuthInfo(Qual, DestAddress);
432 Value = emitPointerAuthResign(Value, T, SrcPtrAuth, DestPtrAuth,
433 /*IsKnownNonNull=*/false);
434 }
435
436 Builder.CreateStore(Value, DestAddress);
437}
438
439llvm::Constant *
441 llvm::Constant *StorageAddress,
442 llvm::ConstantInt *OtherDiscriminator) {
443 llvm::Constant *AddressDiscriminator;
444 if (StorageAddress) {
445 assert(StorageAddress->getType() == DefaultPtrTy);
446 AddressDiscriminator = StorageAddress;
447 } else {
448 AddressDiscriminator = llvm::Constant::getNullValue(DefaultPtrTy);
449 }
450
451 llvm::ConstantInt *IntegerDiscriminator;
452 if (OtherDiscriminator) {
453 assert(OtherDiscriminator->getType() == Int64Ty);
454 IntegerDiscriminator = OtherDiscriminator;
455 } else {
456 IntegerDiscriminator = llvm::ConstantInt::get(Int64Ty, 0);
457 }
458
459 return llvm::ConstantPtrAuth::get(
460 Pointer, llvm::ConstantInt::get(Int32Ty, Key), IntegerDiscriminator,
461 AddressDiscriminator,
462 /*DeactivationSymbol=*/llvm::Constant::getNullValue(DefaultPtrTy));
463}
464
465/// Does a given PointerAuthScheme require us to sign a value
467 auto AuthenticationMode = Schema.getAuthenticationMode();
468 return AuthenticationMode == PointerAuthenticationMode::SignAndStrip ||
469 AuthenticationMode == PointerAuthenticationMode::SignAndAuth;
470}
471
472/// Sign a constant pointer using the given scheme, producing a constant
473/// with the same IR type.
475 llvm::Constant *Pointer, const PointerAuthSchema &Schema,
476 llvm::Constant *StorageAddress, GlobalDecl SchemaDecl,
477 QualType SchemaType) {
478 assert(shouldSignPointer(Schema));
479 llvm::ConstantInt *OtherDiscriminator =
480 getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType);
481
482 return getConstantSignedPointer(Pointer, Schema.getKey(), StorageAddress,
483 OtherDiscriminator);
484}
485
486llvm::Constant *
488 unsigned Key, llvm::Constant *StorageAddress,
489 llvm::ConstantInt *OtherDiscriminator) {
490 return CGM.getConstantSignedPointer(Pointer, Key, StorageAddress,
491 OtherDiscriminator);
492}
493
494/// If applicable, sign a given constant function pointer with the ABI rules for
495/// functionType.
496llvm::Constant *CodeGenModule::getFunctionPointer(llvm::Constant *Pointer,
498 assert(FunctionType->isFunctionType() ||
501
502 if (auto PointerAuth = getFunctionPointerAuthInfo(FunctionType))
504 Pointer, PointerAuth.getKey(), /*StorageAddress=*/nullptr,
505 cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator()));
506
507 return Pointer;
508}
509
511 llvm::Type *Ty) {
512 const auto *FD = cast<FunctionDecl>(GD.getDecl());
513 QualType FuncType = FD->getType();
514
515 // Annoyingly, K&R functions have prototypes in the clang AST, but
516 // expressions referring to them are unprototyped.
517 if (!FD->hasPrototype())
518 if (const auto *Proto = FuncType->getAs<FunctionProtoType>())
519 FuncType = Context.getFunctionNoProtoType(Proto->getReturnType(),
520 Proto->getExtInfo());
521
522 return getFunctionPointer(getRawFunctionPointer(GD, Ty), FuncType);
523}
524
526 assert(FT->getAs<MemberPointerType>() && "MemberPointerType expected");
528 if (!Schema)
529 return CGPointerAuthInfo();
530
531 assert(!Schema.isAddressDiscriminated() &&
532 "function pointers cannot use address-specific discrimination");
533
534 llvm::ConstantInt *Discriminator =
536 return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
537 /* IsIsaPointer */ false,
538 /* AuthenticatesNullValues */ false, Discriminator);
539}
540
541llvm::Constant *CodeGenModule::getMemberFunctionPointer(llvm::Constant *Pointer,
542 QualType FT) {
545 Pointer, PointerAuth.getKey(), nullptr,
546 cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator()));
547
548 if (const auto *MFT = dyn_cast<MemberPointerType>(FT.getTypePtr())) {
549 if (MFT->hasPointeeToCFIUncheckedCalleeFunctionType())
550 Pointer = llvm::NoCFIValue::get(cast<llvm::GlobalValue>(Pointer));
551 }
552
553 return Pointer;
554}
555
557 llvm::Type *Ty) {
558 QualType FT = FD->getType();
559 FT = getContext().getMemberPointerType(FT, /*Qualifier=*/std::nullopt,
560 cast<CXXMethodDecl>(FD)->getParent());
562}
563
564std::optional<PointerAuthQualifier>
565CodeGenModule::computeVTPointerAuthentication(const CXXRecordDecl *ThisClass,
566 bool IsVTTEntry) {
567 auto DefaultAuthentication =
570 if (!DefaultAuthentication)
571 return std::nullopt;
572 const CXXRecordDecl *PrimaryBase =
573 Context.baseForVTableAuthentication(ThisClass);
574 const CXXRecordDecl *TypeDiscriminatorClass =
575 IsVTTEntry ? ThisClass : PrimaryBase;
576
577 unsigned Key = DefaultAuthentication.getKey();
578 bool AddressDiscriminated = DefaultAuthentication.isAddressDiscriminated();
579 auto DefaultDiscrimination = DefaultAuthentication.getOtherDiscrimination();
580 unsigned TypeBasedDiscriminator =
581 Context.getPointerAuthVTablePointerDiscriminator(TypeDiscriminatorClass,
582 IsVTTEntry);
583 unsigned Discriminator;
584 if (DefaultDiscrimination == PointerAuthSchema::Discrimination::Type) {
585 Discriminator = TypeBasedDiscriminator;
586 } else if (DefaultDiscrimination ==
588 Discriminator = DefaultAuthentication.getConstantDiscrimination();
589 } else {
590 assert(DefaultDiscrimination == PointerAuthSchema::Discrimination::None);
591 Discriminator = 0;
592 }
593 auto ExplicitAuthentication =
594 PrimaryBase->getAttr<VTablePointerAuthenticationAttr>();
595
596 // TODO: enable explicit authentication path for VTT vtable entries.
597 if (!IsVTTEntry && ExplicitAuthentication) {
598 auto ExplicitAddressDiscrimination =
599 ExplicitAuthentication->getAddressDiscrimination();
600 auto ExplicitDiscriminator =
601 ExplicitAuthentication->getExtraDiscrimination();
602
603 unsigned ExplicitKey = ExplicitAuthentication->getKey();
604 if (ExplicitKey == VTablePointerAuthenticationAttr::NoKey)
605 return std::nullopt;
606
607 if (ExplicitKey != VTablePointerAuthenticationAttr::DefaultKey) {
608 if (ExplicitKey == VTablePointerAuthenticationAttr::ProcessIndependent)
610 else {
611 assert(ExplicitKey ==
612 VTablePointerAuthenticationAttr::ProcessDependent);
614 }
615 }
616
617 if (ExplicitAddressDiscrimination !=
618 VTablePointerAuthenticationAttr::DefaultAddressDiscrimination)
619 AddressDiscriminated =
620 ExplicitAddressDiscrimination ==
621 VTablePointerAuthenticationAttr::AddressDiscrimination;
622
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)
631 Discriminator = 0;
632 }
633 return PointerAuthQualifier::Create(Key, AddressDiscriminated, Discriminator,
635 /* IsIsaPointer */ false,
636 /* AuthenticatesNullValues */ false);
637}
638
639std::optional<PointerAuthQualifier>
641 bool IsVTTEntry) {
642 if (!Record->getDefinition() || !Record->isPolymorphic())
643 return std::nullopt;
644
645 if (IsVTTEntry)
646 return computeVTPointerAuthentication(Record, IsVTTEntry);
647
648 auto Existing = VTablePtrAuthInfos.find(Record);
649 if (Existing != VTablePtrAuthInfos.end())
650 return Existing->getSecond();
651
652 std::optional<PointerAuthQualifier> Authentication =
653 computeVTPointerAuthentication(Record, IsVTTEntry);
654 VTablePtrAuthInfos.insert(std::make_pair(Record, Authentication));
655 return Authentication;
656}
657
658std::optional<CGPointerAuthInfo> CodeGenModule::getVTablePointerAuthInfo(
660 llvm::Value *StorageAddress, bool IsVTTEntry) {
661 auto Authentication = getVTablePointerAuthentication(Record, IsVTTEntry);
662 if (!Authentication)
663 return std::nullopt;
664
665 llvm::Value *Discriminator = nullptr;
666 if (auto ExtraDiscriminator = Authentication->getExtraDiscriminator())
667 Discriminator = llvm::ConstantInt::get(IntPtrTy, ExtraDiscriminator);
668
669 if (Authentication->isAddressDiscriminated()) {
670 assert(StorageAddress &&
671 "address not provided for address-discriminated schema");
672 if (Discriminator)
673 Discriminator =
674 CGF->EmitPointerAuthBlendDiscriminator(StorageAddress, Discriminator);
675 else
676 Discriminator = CGF->Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
677 }
678
679 return CGPointerAuthInfo(Authentication->getKey(),
681 /* IsIsaPointer */ false,
682 /* AuthenticatesNullValues */ false, Discriminator);
683}
684
685llvm::Value *CodeGenFunction::authPointerToPointerCast(llvm::Value *ResultPtr,
686 QualType SourceType,
687 QualType DestType) {
688 CGPointerAuthInfo CurAuthInfo, NewAuthInfo;
689 if (SourceType->isSignableType(getContext()))
690 CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType);
691
692 if (DestType->isSignableType(getContext()))
693 NewAuthInfo = getPointerAuthInfoForType(CGM, DestType);
694
695 if (!CurAuthInfo && !NewAuthInfo)
696 return ResultPtr;
697
698 // If only one side of the cast is a function pointer, then we still need to
699 // resign to handle casts to/from opaque pointers.
700 if (!CurAuthInfo && DestType->isFunctionPointerType())
701 CurAuthInfo = CGM.getFunctionPointerAuthInfo(SourceType);
702
703 if (!NewAuthInfo && SourceType->isFunctionPointerType())
704 NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
705
706 return emitPointerAuthResign(ResultPtr, DestType, CurAuthInfo, NewAuthInfo,
707 /*IsKnownNonNull=*/false);
708}
709
711 QualType SourceType,
712 QualType DestType) {
713 CGPointerAuthInfo CurAuthInfo, NewAuthInfo;
714 if (SourceType->isSignableType(getContext()))
715 CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType);
716
717 if (DestType->isSignableType(getContext()))
718 NewAuthInfo = getPointerAuthInfoForType(CGM, DestType);
719
720 if (!CurAuthInfo && !NewAuthInfo)
721 return Ptr;
722
723 if (!CurAuthInfo && DestType->isFunctionPointerType()) {
724 // When casting a non-signed pointer to a function pointer, just set the
725 // auth info on Ptr to the assumed schema. The pointer will be resigned to
726 // the effective type when used.
727 Ptr.setPointerAuthInfo(CGM.getFunctionPointerAuthInfo(SourceType));
728 return Ptr;
729 }
730
731 if (!NewAuthInfo && SourceType->isFunctionPointerType()) {
732 NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
733 Ptr = Ptr.getResignedAddress(NewAuthInfo, *this);
734 Ptr.setPointerAuthInfo(CGPointerAuthInfo());
735 return Ptr;
736 }
737
738 return Ptr;
739}
740
742 QualType PointeeTy) {
743 CGPointerAuthInfo Info =
744 PointeeTy.isNull() ? CGPointerAuthInfo()
745 : CGM.getPointerAuthInfoForPointeeType(PointeeTy);
746 return Addr.getResignedAddress(Info, *this);
747}
748
750 CodeGenFunction &CGF) const {
751 assert(isValid() && "pointer isn't valid");
753 llvm::Value *Val;
754
755 // Nothing to do if neither the current or the new ptrauth info needs signing.
756 if (!CurInfo.isSigned() && !NewInfo.isSigned())
759
760 assert(ElementType && "Effective type has to be set");
761 assert(!Offset && "unexpected non-null offset");
762
763 // If the current and the new ptrauth infos are the same and the offset is
764 // null, just cast the base pointer to the effective type.
765 if (CurInfo == NewInfo && !hasOffset())
766 Val = getBasePointer();
767 else
768 Val = CGF.emitPointerAuthResign(getBasePointer(), QualType(), CurInfo,
769 NewInfo, isKnownNonNull());
770
771 return Address(Val, getElementType(), getAlignment(), NewInfo,
772 /*Offset=*/nullptr, isKnownNonNull());
773}
774
775llvm::Value *Address::emitRawPointerSlow(CodeGenFunction &CGF) const {
776 return CGF.getAsNaturalPointerTo(*this, QualType());
777}
778
779llvm::Value *LValue::getPointer(CodeGenFunction &CGF) const {
780 assert(isSimple());
781 return emitResignedPointer(getType(), CGF);
782}
783
785 CodeGenFunction &CGF) const {
786 assert(isSimple());
787 return CGF.getAsNaturalAddressOf(Addr, PointeeTy).getBasePointer();
788}
789
790llvm::Value *LValue::emitRawPointer(CodeGenFunction &CGF) const {
791 assert(isSimple());
792 return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr;
793}
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
Definition MachO.h:31
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.
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
Address(std::nullptr_t)
Definition Address.h:151
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
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
MangleContext & getMangleContext()
Gets the mangle context.
Definition CGCXXABI.h:113
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)
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:1698
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:1960
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:651
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.
Definition CGExpr.cpp:3508
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)
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.
Definition CGValue.h:183
llvm::Value * emitResignedPointer(QualType PointeeTy, CodeGenFunction &CGF) const
bool isSimple() const
Definition CGValue.h:286
llvm::Value * getPointer(CodeGenFunction &CGF) const
QualType getType() const
Definition CGValue.h:303
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
T * getAttr() const
Definition DeclBase.h:581
This represents one expression.
Definition Expr.h:113
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3119
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:145
Represents a function declaration or definition.
Definition Decl.h:2059
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5421
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4617
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:60
const Decl * getDecl() const
Definition GlobalDecl.h:115
virtual void mangleCXXName(GlobalDecl GD, raw_ostream &)=0
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3767
Pointer-authentication qualifiers.
Definition TypeBase.h:153
static PointerAuthQualifier Create(unsigned Key, bool IsAddressDiscriminated, unsigned ExtraDiscriminator, PointerAuthenticationMode AuthenticationMode, bool IsIsaPointer, bool AuthenticatesNullValues)
Definition TypeBase.h:240
bool authenticatesNullValues() const
Definition TypeBase.h:286
bool isAddressDiscriminated() const
Definition TypeBase.h:266
unsigned getExtraDiscriminator() const
Definition TypeBase.h:271
PointerAuthenticationMode getAuthenticationMode() const
Definition TypeBase.h:276
unsigned getKey() const
Definition TypeBase.h:259
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:3408
QualType getPointeeType() const
Definition TypeBase.h:3418
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8501
Encodes a location in the source.
bool isBlockPointerType() const
Definition TypeBase.h:8758
bool isFunctionReferenceType() const
Definition TypeBase.h:8812
bool isSignableType(const ASTContext &Ctx) const
Definition TypeBase.h:8750
bool isFunctionPointerType() const
Definition TypeBase.h:8805
bool isFunctionType() const
Definition TypeBase.h:8734
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9337
QualType getType() const
Definition Decl.h:724
QualType getType() const
Definition Value.cpp:238
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
Definition CGValue.h:155
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
Definition CGValue.h:146
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.
Definition TypeBase.h:906
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Definition Address.h:327
static constexpr llvm::StringLiteral FunctionLabelPrefix
Definition Mangle.h:336
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.