clang: lib/CodeGen/CGPointerAuth.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
18#include "llvm/Analysis/ValueTracking.h"
19#include "llvm/Support/SipHash.h"
20
21using namespace clang;
22using namespace CodeGen;
23
24
25
30 return nullptr;
31
33 assert(.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
45 }
46 llvm_unreachable("bad discrimination kind");
47}
48
52}
53
57}
58
59
60uint16_t
62 uint16_t &EntityHash = PtrAuthDiscriminatorHashes[Declaration];
63
64 if (EntityHash == 0) {
66 EntityHash = llvm::getPointerAuthStableSipHash(Name);
67 }
68
69 return EntityHash;
70}
71
72
73
76 if (!Schema)
78
79 assert(!Schema.isAddressDiscriminated() &&
80 "function pointers cannot use address-specific discrimination");
81
82 llvm::Constant *Discriminator = nullptr;
87
88 return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
89 false, 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
102
106 if (!Schema)
108
109 llvm::Value *Discriminator =
111
113 assert(StorageAddress &&
114 "address not provided for address-discriminated schema");
115
116 if (Discriminator)
117 Discriminator =
119 else
120 Discriminator = Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
121 }
122
126}
127
128
129
132 if (PointeeType.isNull())
134
135
138
139
141}
142
144 return ::getPointerAuthInfoForPointeeType(*this, T);
145}
146
147
148
152
153
156
158
159 if (PointeeType.isNull())
161
162 return ::getPointerAuthInfoForPointeeType(CGM, PointeeType);
163}
164
166 return ::getPointerAuthInfoForType(*this, T);
167}
168
170 if (const auto *CI = dyn_castllvm::ConstantInt(Value))
171 return CI->isZero();
172 return false;
173}
174
177 assert((Left.isSigned() || Right.isSigned()) &&
178 "shouldn't be called if neither is signed");
179 if (Left.isSigned() != Right.isSigned())
180 return false;
181 return Left.getKey() == Right.getKey() &&
182 Left.getAuthenticationMode() == Right.getAuthenticationMode();
183}
184
185
189 return Discriminator ? Discriminator : Builder.getSize(0);
190}
191
192llvm::Value *
196 assert(CurAuth && NewAuth);
197
204 }
205
208
209 auto *CurKey = Builder.getInt32(CurAuth.getKey());
210 auto *NewKey = Builder.getInt32(NewAuth.getKey());
211
214
215
216
217
218 auto *Intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_resign);
220 Intrinsic, {Value, CurKey, CurDiscriminator, NewKey, NewDiscriminator});
221
222
225}
226
230
231 if (!CurAuthInfo && !NewAuthInfo)
233
234 llvm::Value *Null = nullptr;
235
236 if (auto *PointerValue = dyn_castllvm::PointerType(Value->getType())) {
238 } else {
241 }
242 if (Value == Null)
244
245
249 if (CurD == NewD)
251
255 }
256
257 llvm::BasicBlock *InitBB = Builder.GetInsertBlock();
258 llvm::BasicBlock *ResignBB = nullptr, *ContBB = nullptr;
259
260
261
265
267 Builder.CreateCondBr(IsNonNull, ResignBB, ContBB);
269 }
270
271
272 if (!NewAuthInfo)
274 else if (!CurAuthInfo)
276 else
278
279
280 if (ContBB) {
283 Phi->addIncoming(Null, InitBB);
284 Phi->addIncoming(Value, ResignBB);
286 }
287
289}
290
291llvm::Constant *
293 llvm::Constant *StorageAddress,
294 llvm::ConstantInt *OtherDiscriminator) {
295 llvm::Constant *AddressDiscriminator;
296 if (StorageAddress) {
297 assert(StorageAddress->getType() == UnqualPtrTy);
298 AddressDiscriminator = StorageAddress;
299 } else {
300 AddressDiscriminator = llvm::Constant::getNullValue(UnqualPtrTy);
301 }
302
303 llvm::ConstantInt *IntegerDiscriminator;
304 if (OtherDiscriminator) {
305 assert(OtherDiscriminator->getType() == Int64Ty);
306 IntegerDiscriminator = OtherDiscriminator;
307 } else {
308 IntegerDiscriminator = llvm::ConstantInt::get(Int64Ty, 0);
309 }
310
311 return llvm::ConstantPtrAuth::get(Pointer,
312 llvm::ConstantInt::get(Int32Ty, Key),
313 IntegerDiscriminator, AddressDiscriminator);
314}
315
316
321}
322
323
324
327 llvm::Constant *StorageAddress, GlobalDecl SchemaDecl,
330 llvm::ConstantInt *OtherDiscriminator =
332
334 OtherDiscriminator);
335}
336
337
338
344
347 Pointer, PointerAuth.getKey(), nullptr,
348 cast_or_nullllvm::ConstantInt(PointerAuth.getDiscriminator()));
349
351}
352
354 llvm::Type *Ty) {
355 const auto *FD = cast(GD.getDecl());
356 QualType FuncType = FD->getType();
357
358
359
360 if (!FD->hasPrototype())
363 Proto->getExtInfo());
364
366}
367
371 if (!Schema)
373
375 "function pointers cannot use address-specific discrimination");
376
377 llvm::ConstantInt *Discriminator =
380 false,
381 false, Discriminator);
382}
383
388 Pointer, PointerAuth.getKey(), nullptr,
389 cast_or_nullllvm::ConstantInt(PointerAuth.getDiscriminator()));
390
392}
393
395 llvm::Type *Ty) {
398 FT, cast(FD)->getParent()->getTypeForDecl());
400}
401
402std::optional
403CodeGenModule::computeVTPointerAuthentication(const CXXRecordDecl *ThisClass) {
405 if (!DefaultAuthentication)
406 return std::nullopt;
409
410 unsigned Key = DefaultAuthentication.getKey();
411 bool AddressDiscriminated = DefaultAuthentication.isAddressDiscriminated();
412 auto DefaultDiscrimination = DefaultAuthentication.getOtherDiscrimination();
413 unsigned TypeBasedDiscriminator =
415 unsigned Discriminator;
417 Discriminator = TypeBasedDiscriminator;
418 } else if (DefaultDiscrimination ==
420 Discriminator = DefaultAuthentication.getConstantDiscrimination();
421 } else {
423 Discriminator = 0;
424 }
425 if (auto ExplicitAuthentication =
426 PrimaryBase->getAttr()) {
427 auto ExplicitAddressDiscrimination =
428 ExplicitAuthentication->getAddressDiscrimination();
429 auto ExplicitDiscriminator =
430 ExplicitAuthentication->getExtraDiscrimination();
431
432 unsigned ExplicitKey = ExplicitAuthentication->getKey();
433 if (ExplicitKey == VTablePointerAuthenticationAttr::NoKey)
434 return std::nullopt;
435
436 if (ExplicitKey != VTablePointerAuthenticationAttr::DefaultKey) {
437 if (ExplicitKey == VTablePointerAuthenticationAttr::ProcessIndependent)
439 else {
440 assert(ExplicitKey ==
441 VTablePointerAuthenticationAttr::ProcessDependent);
443 }
444 }
445
446 if (ExplicitAddressDiscrimination !=
447 VTablePointerAuthenticationAttr::DefaultAddressDiscrimination)
448 AddressDiscriminated =
449 ExplicitAddressDiscrimination ==
450 VTablePointerAuthenticationAttr::AddressDiscrimination;
451
452 if (ExplicitDiscriminator ==
453 VTablePointerAuthenticationAttr::TypeDiscrimination)
454 Discriminator = TypeBasedDiscriminator;
455 else if (ExplicitDiscriminator ==
456 VTablePointerAuthenticationAttr::CustomDiscrimination)
457 Discriminator = ExplicitAuthentication->getCustomDiscriminationValue();
458 else if (ExplicitDiscriminator ==
459 VTablePointerAuthenticationAttr::NoExtraDiscrimination)
460 Discriminator = 0;
461 }
464 false,
465 false);
466}
467
468std::optional
470 if (->getDefinition() ||
->isPolymorphic())
471 return std::nullopt;
472
473 auto Existing = VTablePtrAuthInfos.find(Record);
474 std::optional Authentication;
475 if (Existing != VTablePtrAuthInfos.end()) {
476 Authentication = Existing->getSecond();
477 } else {
478 Authentication = computeVTPointerAuthentication(Record);
479 VTablePtrAuthInfos.insert(std::make_pair(Record, Authentication));
480 }
481 return Authentication;
482}
483
484std::optional
487 llvm::Value *StorageAddress) {
489 if (!Authentication)
490 return std::nullopt;
491
492 llvm::Value *Discriminator = nullptr;
493 if (auto ExtraDiscriminator = Authentication->getExtraDiscriminator())
494 Discriminator = llvm::ConstantInt::get(IntPtrTy, ExtraDiscriminator);
495
496 if (Authentication->isAddressDiscriminated()) {
497 assert(StorageAddress &&
498 "address not provided for address-discriminated schema");
499 if (Discriminator)
500 Discriminator =
502 else
503 Discriminator = CGF->Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
504 }
505
508 false,
509 false, Discriminator);
510}
511
518
521
522 if (!CurAuthInfo && !NewAuthInfo)
523 return ResultPtr;
524
525
526
529
532
534 false);
535}
536
543
546
547 if (!CurAuthInfo && !NewAuthInfo)
548 return Ptr;
549
551
552
553
555 return Ptr;
556 }
557
562 return Ptr;
563 }
564
565 return Ptr;
566}
567
574}
575
578 assert(isValid() && "pointer isn't valid");
580 llvm::Value *Val;
581
582
586
587 assert(ElementType && "Effective type has to be set");
588 assert(!Offset && "unexpected non-null offset");
589
590
591
592 if (CurInfo == NewInfo && ())
594 else
597
601}
602
603llvm::Value *Address::emitRawPointerSlow(CodeGenFunction &CGF) const {
605}
606
610}
611
616}
617
621}
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, const Type *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
QualType getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const
Return a K&R style C function type like 'int()'.
const CXXRecordDecl * baseForVTableAuthentication(const CXXRecordDecl *ThisClass)
Resolve the root record to be used to derive the vtable pointer authentication policy for the specifi...
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.
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
llvm::PointerType * getType() const
Return the type of the pointer value.
PointerAuthenticationMode getAuthenticationMode() const
llvm::Value * getDiscriminator() const
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::Value * EmitPointerAuthAuth(const CGPointerAuthInfo &Info, llvm::Value *Pointer)
Address getAsNaturalAddressOf(Address Addr, QualType PointeeTy)
llvm::Value * emitPointerAuthResignCall(llvm::Value *Pointer, const CGPointerAuthInfo &CurInfo, const CGPointerAuthInfo &NewInfo)
llvm::Value * getAsNaturalPointerTo(Address Addr, QualType PointeeType)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
llvm::Value * EmitPointerAuthSign(const CGPointerAuthInfo &Info, llvm::Value *Pointer)
llvm::Value * EmitPointerAuthBlendDiscriminator(llvm::Value *StorageAddress, llvm::Value *Discriminator)
Create the discriminator from the storage address and the entity hash.
llvm::Value * emitPointerAuthResign(llvm::Value *Pointer, QualType PointerType, const CGPointerAuthInfo &CurAuthInfo, const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull)
llvm::Value * authPointerToPointerCast(llvm::Value *ResultPtr, QualType SourceType, QualType DestType)
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
CGPointerAuthInfo EmitPointerAuthInfo(const PointerAuthSchema &Schema, llvm::Value *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType)
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.
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)
llvm::Value * emitResignedPointer(QualType PointeeTy, CodeGenFunction &CGF) const
llvm::Value * getPointer(CodeGenFunction &CGF) const
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Decl - This represents one declaration (or definition), e.g.
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.
static PointerAuthQualifier Create(unsigned Key, bool IsAddressDiscriminated, unsigned ExtraDiscriminator, PointerAuthenticationMode AuthenticationMode, bool IsIsaPointer, bool AuthenticatesNullValues)
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.
The base class of the type hierarchy.
bool isBlockPointerType() const
bool isFunctionReferenceType() const
bool isFunctionPointerType() const
bool isSignableType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isFunctionType() const
const T * getAs() const
Member-template getAs'.
uint16_t getPointerAuthDeclDiscriminator(CodeGenModule &CGM, GlobalDecl GD)
Return a declaration discriminator for the given global decl.
uint16_t getPointerAuthTypeDiscriminator(CodeGenModule &CGM, QualType FunctionType)
Return a type discriminator for the given function type.
bool Null(InterpState &S, CodePtr OpPC, uint64_t Value, const Descriptor *Desc)
bool IsNonNull(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
llvm::IntegerType * Int64Ty
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::PointerType * UnqualPtrTy
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.