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" 16 #include "clang/CodeGen/CodeGenABITypes.h" 17 #include "clang/CodeGen/ConstantInitBuilder.h" 18 #include "llvm/Analysis/ValueTracking.h" 19 #include "llvm/Support/SipHash.h" 20 21 using namespace clang; 22 using namespace CodeGen; 23 24 /// Given a pointer-authentication schema, return a concrete "other" 25 /// discriminator for it. 26 llvm::ConstantInt *CodeGenModule::getPointerAuthOtherDiscriminator( 27 const PointerAuthSchema &Schema, GlobalDecl Decl, QualType Type) { 28 switch (Schema.getOtherDiscrimination()) { 29 case PointerAuthSchema::Discrimination::None: 30 return nullptr; 31 32 case PointerAuthSchema::Discrimination::Type: 33 assert(!Type.isNull() && "type not provided for type-discriminated schema"); 34 return llvm::ConstantInt::get( 35 IntPtrTy, getContext().getPointerAuthTypeDiscriminator(Type)); 36 37 case PointerAuthSchema::Discrimination::Decl: 38 assert(Decl.getDecl() && 39 "declaration not provided for decl-discriminated schema"); 40 return llvm::ConstantInt::get(IntPtrTy, 41 getPointerAuthDeclDiscriminator(Decl)); 42 43 case PointerAuthSchema::Discrimination::Constant: 44 return llvm::ConstantInt::get(IntPtrTy, Schema.getConstantDiscrimination()); 45 } 46 llvm_unreachable("bad discrimination kind"); 47 } 48 49 uint16_t CodeGen::getPointerAuthTypeDiscriminator(CodeGenModule &CGM, 50 QualType FunctionType) { 51 return CGM.getContext().getPointerAuthTypeDiscriminator(FunctionType); 52 } 53 54 uint16_t CodeGen::getPointerAuthDeclDiscriminator(CodeGenModule &CGM, 55 GlobalDecl Declaration) { 56 return CGM.getPointerAuthDeclDiscriminator(Declaration); 57 } 58 59 /// Return the "other" decl-specific discriminator for the given decl. 60 uint16_t 61 CodeGenModule::getPointerAuthDeclDiscriminator(GlobalDecl Declaration) { 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. 74 CGPointerAuthInfo CodeGenModule::getFunctionPointerAuthInfo(QualType T) { 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; 83 if (T->isFunctionPointerType() || T->isFunctionReferenceType()) 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 93 llvm::Value * 94 CodeGenFunction::EmitPointerAuthBlendDiscriminator(llvm::Value *StorageAddress, 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. 103 CGPointerAuthInfo CodeGenFunction::EmitPointerAuthInfo( 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 128 /// Return the natural pointer authentication for values of the given 129 /// pointee type. 130 static CGPointerAuthInfo 131 getPointerAuthInfoForPointeeType(CodeGenModule &CGM, QualType PointeeType) { 132 if (PointeeType.isNull()) 133 return CGPointerAuthInfo(); 134 135 // Function pointers use the function-pointer schema by default. 136 if (PointeeType->isFunctionType()) 137 return CGM.getFunctionPointerAuthInfo(PointeeType); 138 139 // Normal data pointers never use direct pointer authentication by default. 140 return CGPointerAuthInfo(); 141 } 142 143 CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForPointeeType(QualType T) { 144 return ::getPointerAuthInfoForPointeeType(*this, T); 145 } 146 147 /// Return the natural pointer authentication for values of the given 148 /// pointer type. 149 static CGPointerAuthInfo getPointerAuthInfoForType(CodeGenModule &CGM, 150 QualType PointerType) { 151 assert(PointerType->isSignableType()); 152 153 // Block pointers are currently not signed. 154 if (PointerType->isBlockPointerType()) 155 return CGPointerAuthInfo(); 156 157 auto PointeeType = PointerType->getPointeeType(); 158 159 if (PointeeType.isNull()) 160 return CGPointerAuthInfo(); 161 162 return ::getPointerAuthInfoForPointeeType(CGM, PointeeType); 163 } 164 165 CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForType(QualType T) { 166 return ::getPointerAuthInfoForType(*this, T); 167 } 168 169 static bool isZeroConstant(const llvm::Value *Value) { 170 if (const auto *CI = dyn_cast<llvm::ConstantInt>(Value)) 171 return CI->isZero(); 172 return false; 173 } 174 175 static bool equalAuthPolicies(const CGPointerAuthInfo &Left, 176 const CGPointerAuthInfo &Right) { 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 // Return the discriminator or return zero if the discriminator is null. 186 static llvm::Value *getDiscriminatorOrZero(const CGPointerAuthInfo &Info, 187 CGBuilderTy &Builder) { 188 llvm::Value *Discriminator = Info.getDiscriminator(); 189 return Discriminator ? Discriminator : Builder.getSize(0); 190 } 191 192 llvm::Value * 193 CodeGenFunction::emitPointerAuthResignCall(llvm::Value *Value, 194 const CGPointerAuthInfo &CurAuth, 195 const CGPointerAuthInfo &NewAuth) { 196 assert(CurAuth && NewAuth); 197 198 if (CurAuth.getAuthenticationMode() != 199 PointerAuthenticationMode::SignAndAuth || 200 NewAuth.getAuthenticationMode() != 201 PointerAuthenticationMode::SignAndAuth) { 202 llvm::Value *AuthedValue = EmitPointerAuthAuth(CurAuth, Value); 203 return EmitPointerAuthSign(NewAuth, AuthedValue); 204 } 205 // Convert the pointer to intptr_t before signing it. 206 auto *OrigType = Value->getType(); 207 Value = Builder.CreatePtrToInt(Value, IntPtrTy); 208 209 auto *CurKey = Builder.getInt32(CurAuth.getKey()); 210 auto *NewKey = Builder.getInt32(NewAuth.getKey()); 211 212 llvm::Value *CurDiscriminator = getDiscriminatorOrZero(CurAuth, Builder); 213 llvm::Value *NewDiscriminator = getDiscriminatorOrZero(NewAuth, Builder); 214 215 // call i64 @llvm.ptrauth.resign(i64 %pointer, 216 // i32 %curKey, i64 %curDiscriminator, 217 // i32 %newKey, i64 %newDiscriminator) 218 auto *Intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_resign); 219 Value = EmitRuntimeCall( 220 Intrinsic, {Value, CurKey, CurDiscriminator, NewKey, NewDiscriminator}); 221 222 // Convert back to the original type. 223 Value = Builder.CreateIntToPtr(Value, OrigType); 224 return Value; 225 } 226 227 llvm::Value *CodeGenFunction::emitPointerAuthResign( 228 llvm::Value *Value, QualType Type, const CGPointerAuthInfo &CurAuthInfo, 229 const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull) { 230 // Fast path: if neither schema wants a signature, we're done. 231 if (!CurAuthInfo && !NewAuthInfo) 232 return Value; 233 234 llvm::Value *Null = nullptr; 235 // If the value is obviously null, we're done. 236 if (auto *PointerValue = dyn_cast<llvm::PointerType>(Value->getType())) { 237 Null = CGM.getNullPointer(PointerValue, Type); 238 } else { 239 assert(Value->getType()->isIntegerTy()); 240 Null = llvm::ConstantInt::get(IntPtrTy, 0); 241 } 242 if (Value == Null) 243 return Value; 244 245 // If both schemas sign the same way, we're done. 246 if (equalAuthPolicies(CurAuthInfo, NewAuthInfo)) { 247 const llvm::Value *CurD = CurAuthInfo.getDiscriminator(); 248 const llvm::Value *NewD = NewAuthInfo.getDiscriminator(); 249 if (CurD == NewD) 250 return Value; 251 252 if ((CurD == nullptr && isZeroConstant(NewD)) || 253 (NewD == nullptr && isZeroConstant(CurD))) 254 return Value; 255 } 256 257 llvm::BasicBlock *InitBB = Builder.GetInsertBlock(); 258 llvm::BasicBlock *ResignBB = nullptr, *ContBB = nullptr; 259 260 // Null pointers have to be mapped to null, and the ptrauth_resign 261 // intrinsic doesn't do that. 262 if (!IsKnownNonNull && !llvm::isKnownNonZero(Value, CGM.getDataLayout())) { 263 ContBB = createBasicBlock("resign.cont"); 264 ResignBB = createBasicBlock("resign.nonnull"); 265 266 auto *IsNonNull = Builder.CreateICmpNE(Value, Null); 267 Builder.CreateCondBr(IsNonNull, ResignBB, ContBB); 268 EmitBlock(ResignBB); 269 } 270 271 // Perform the auth/sign/resign operation. 272 if (!NewAuthInfo) 273 Value = EmitPointerAuthAuth(CurAuthInfo, Value); 274 else if (!CurAuthInfo) 275 Value = EmitPointerAuthSign(NewAuthInfo, Value); 276 else 277 Value = emitPointerAuthResignCall(Value, CurAuthInfo, NewAuthInfo); 278 279 // Clean up with a phi if we branched before. 280 if (ContBB) { 281 EmitBlock(ContBB); 282 auto *Phi = Builder.CreatePHI(Value->getType(), 2); 283 Phi->addIncoming(Null, InitBB); 284 Phi->addIncoming(Value, ResignBB); 285 Value = Phi; 286 } 287 288 return Value; 289 } 290 291 llvm::Constant * 292 CodeGenModule::getConstantSignedPointer(llvm::Constant *Pointer, unsigned Key, 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 /// Does a given PointerAuthScheme require us to sign a value 317 bool CodeGenModule::shouldSignPointer(const PointerAuthSchema &Schema) { 318 auto AuthenticationMode = Schema.getAuthenticationMode(); 319 return AuthenticationMode == PointerAuthenticationMode::SignAndStrip || 320 AuthenticationMode == PointerAuthenticationMode::SignAndAuth; 321 } 322 323 /// Sign a constant pointer using the given scheme, producing a constant 324 /// with the same IR type. 325 llvm::Constant *CodeGenModule::getConstantSignedPointer( 326 llvm::Constant *Pointer, const PointerAuthSchema &Schema, 327 llvm::Constant *StorageAddress, GlobalDecl SchemaDecl, 328 QualType SchemaType) { 329 assert(shouldSignPointer(Schema)); 330 llvm::ConstantInt *OtherDiscriminator = 331 getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType); 332 333 return getConstantSignedPointer(Pointer, Schema.getKey(), StorageAddress, 334 OtherDiscriminator); 335 } 336 337 /// If applicable, sign a given constant function pointer with the ABI rules for 338 /// functionType. 339 llvm::Constant *CodeGenModule::getFunctionPointer(llvm::Constant *Pointer, 340 QualType FunctionType) { 341 assert(FunctionType->isFunctionType() || 342 FunctionType->isFunctionReferenceType() || 343 FunctionType->isFunctionPointerType()); 344 345 if (auto PointerAuth = getFunctionPointerAuthInfo(FunctionType)) 346 return getConstantSignedPointer( 347 Pointer, PointerAuth.getKey(), /*StorageAddress=*/nullptr, 348 cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator())); 349 350 return Pointer; 351 } 352 353 llvm::Constant *CodeGenModule::getFunctionPointer(GlobalDecl GD, 354 llvm::Type *Ty) { 355 const auto *FD = cast<FunctionDecl>(GD.getDecl()); 356 QualType FuncType = FD->getType(); 357 358 // Annoyingly, K&R functions have prototypes in the clang AST, but 359 // expressions referring to them are unprototyped. 360 if (!FD->hasPrototype()) 361 if (const auto *Proto = FuncType->getAs<FunctionProtoType>()) 362 FuncType = Context.getFunctionNoProtoType(Proto->getReturnType(), 363 Proto->getExtInfo()); 364 365 return getFunctionPointer(getRawFunctionPointer(GD, Ty), FuncType); 366 } 367 368 CGPointerAuthInfo CodeGenModule::getMemberFunctionPointerAuthInfo(QualType FT) { 369 assert(FT->getAs<MemberPointerType>() && "MemberPointerType expected"); 370 const auto &Schema = getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers; 371 if (!Schema) 372 return CGPointerAuthInfo(); 373 374 assert(!Schema.isAddressDiscriminated() && 375 "function pointers cannot use address-specific discrimination"); 376 377 llvm::ConstantInt *Discriminator = 378 getPointerAuthOtherDiscriminator(Schema, GlobalDecl(), FT); 379 return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(), 380 /* IsIsaPointer */ false, 381 /* AuthenticatesNullValues */ false, Discriminator); 382 } 383 384 llvm::Constant *CodeGenModule::getMemberFunctionPointer(llvm::Constant *Pointer, 385 QualType FT) { 386 if (CGPointerAuthInfo PointerAuth = getMemberFunctionPointerAuthInfo(FT)) 387 return getConstantSignedPointer( 388 Pointer, PointerAuth.getKey(), nullptr, 389 cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator())); 390 391 return Pointer; 392 } 393 394 llvm::Constant *CodeGenModule::getMemberFunctionPointer(const FunctionDecl *FD, 395 llvm::Type *Ty) { 396 QualType FT = FD->getType(); 397 FT = getContext().getMemberPointerType( 398 FT, cast<CXXMethodDecl>(FD)->getParent()->getTypeForDecl()); 399 return getMemberFunctionPointer(getRawFunctionPointer(FD, Ty), FT); 400 } 401 402 std::optional<PointerAuthQualifier> 403 CodeGenModule::computeVTPointerAuthentication(const CXXRecordDecl *ThisClass) { 404 auto DefaultAuthentication = getCodeGenOpts().PointerAuth.CXXVTablePointers; 405 if (!DefaultAuthentication) 406 return std::nullopt; 407 const CXXRecordDecl *PrimaryBase = 408 Context.baseForVTableAuthentication(ThisClass); 409 410 unsigned Key = DefaultAuthentication.getKey(); 411 bool AddressDiscriminated = DefaultAuthentication.isAddressDiscriminated(); 412 auto DefaultDiscrimination = DefaultAuthentication.getOtherDiscrimination(); 413 unsigned TypeBasedDiscriminator = 414 Context.getPointerAuthVTablePointerDiscriminator(PrimaryBase); 415 unsigned Discriminator; 416 if (DefaultDiscrimination == PointerAuthSchema::Discrimination::Type) { 417 Discriminator = TypeBasedDiscriminator; 418 } else if (DefaultDiscrimination == 419 PointerAuthSchema::Discrimination::Constant) { 420 Discriminator = DefaultAuthentication.getConstantDiscrimination(); 421 } else { 422 assert(DefaultDiscrimination == PointerAuthSchema::Discrimination::None); 423 Discriminator = 0; 424 } 425 if (auto ExplicitAuthentication = 426 PrimaryBase->getAttr<VTablePointerAuthenticationAttr>()) { 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) 438 Key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDA; 439 else { 440 assert(ExplicitKey == 441 VTablePointerAuthenticationAttr::ProcessDependent); 442 Key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDB; 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 } 462 return PointerAuthQualifier::Create(Key, AddressDiscriminated, Discriminator, 463 PointerAuthenticationMode::SignAndAuth, 464 /* IsIsaPointer */ false, 465 /* AuthenticatesNullValues */ false); 466 } 467 468 std::optional<PointerAuthQualifier> 469 CodeGenModule::getVTablePointerAuthentication(const CXXRecordDecl *Record) { 470 if (!Record->getDefinition() || !Record->isPolymorphic()) 471 return std::nullopt; 472 473 auto Existing = VTablePtrAuthInfos.find(Record); 474 std::optional<PointerAuthQualifier> 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 484 std::optional<CGPointerAuthInfo> 485 CodeGenModule::getVTablePointerAuthInfo(CodeGenFunction *CGF, 486 const CXXRecordDecl *Record, 487 llvm::Value *StorageAddress) { 488 auto Authentication = getVTablePointerAuthentication(Record); 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 = 501 CGF->EmitPointerAuthBlendDiscriminator(StorageAddress, Discriminator); 502 else 503 Discriminator = CGF->Builder.CreatePtrToInt(StorageAddress, IntPtrTy); 504 } 505 506 return CGPointerAuthInfo(Authentication->getKey(), 507 PointerAuthenticationMode::SignAndAuth, 508 /* IsIsaPointer */ false, 509 /* AuthenticatesNullValues */ false, Discriminator); 510 } 511 512 llvm::Value *CodeGenFunction::authPointerToPointerCast(llvm::Value *ResultPtr, 513 QualType SourceType, 514 QualType DestType) { 515 CGPointerAuthInfo CurAuthInfo, NewAuthInfo; 516 if (SourceType->isSignableType()) 517 CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType); 518 519 if (DestType->isSignableType()) 520 NewAuthInfo = getPointerAuthInfoForType(CGM, DestType); 521 522 if (!CurAuthInfo && !NewAuthInfo) 523 return ResultPtr; 524 525 // If only one side of the cast is a function pointer, then we still need to 526 // resign to handle casts to/from opaque pointers. 527 if (!CurAuthInfo && DestType->isFunctionPointerType()) 528 CurAuthInfo = CGM.getFunctionPointerAuthInfo(SourceType); 529 530 if (!NewAuthInfo && SourceType->isFunctionPointerType()) 531 NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType); 532 533 return emitPointerAuthResign(ResultPtr, DestType, CurAuthInfo, NewAuthInfo, 534 /*IsKnownNonNull=*/false); 535 } 536 537 Address CodeGenFunction::authPointerToPointerCast(Address Ptr, 538 QualType SourceType, 539 QualType DestType) { 540 CGPointerAuthInfo CurAuthInfo, NewAuthInfo; 541 if (SourceType->isSignableType()) 542 CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType); 543 544 if (DestType->isSignableType()) 545 NewAuthInfo = getPointerAuthInfoForType(CGM, DestType); 546 547 if (!CurAuthInfo && !NewAuthInfo) 548 return Ptr; 549 550 if (!CurAuthInfo && DestType->isFunctionPointerType()) { 551 // When casting a non-signed pointer to a function pointer, just set the 552 // auth info on Ptr to the assumed schema. The pointer will be resigned to 553 // the effective type when used. 554 Ptr.setPointerAuthInfo(CGM.getFunctionPointerAuthInfo(SourceType)); 555 return Ptr; 556 } 557 558 if (!NewAuthInfo && SourceType->isFunctionPointerType()) { 559 NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType); 560 Ptr = Ptr.getResignedAddress(NewAuthInfo, *this); 561 Ptr.setPointerAuthInfo(CGPointerAuthInfo()); 562 return Ptr; 563 } 564 565 return Ptr; 566 } 567 568 Address CodeGenFunction::getAsNaturalAddressOf(Address Addr, 569 QualType PointeeTy) { 570 CGPointerAuthInfo Info = 571 PointeeTy.isNull() ? CGPointerAuthInfo() 572 : CGM.getPointerAuthInfoForPointeeType(PointeeTy); 573 return Addr.getResignedAddress(Info, *this); 574 } 575 576 Address Address::getResignedAddress(const CGPointerAuthInfo &NewInfo, 577 CodeGenFunction &CGF) const { 578 assert(isValid() && "pointer isn't valid"); 579 CGPointerAuthInfo CurInfo = getPointerAuthInfo(); 580 llvm::Value *Val; 581 582 // Nothing to do if neither the current or the new ptrauth info needs signing. 583 if (!CurInfo.isSigned() && !NewInfo.isSigned()) 584 return Address(getBasePointer(), getElementType(), getAlignment(), 585 isKnownNonNull()); 586 587 assert(ElementType && "Effective type has to be set"); 588 assert(!Offset && "unexpected non-null offset"); 589 590 // If the current and the new ptrauth infos are the same and the offset is 591 // null, just cast the base pointer to the effective type. 592 if (CurInfo == NewInfo && !hasOffset()) 593 Val = getBasePointer(); 594 else 595 Val = CGF.emitPointerAuthResign(getBasePointer(), QualType(), CurInfo, 596 NewInfo, isKnownNonNull()); 597 598 Val = CGF.Builder.CreateBitCast(Val, getType()); 599 return Address(Val, getElementType(), getAlignment(), NewInfo, 600 /*Offset=*/nullptr, isKnownNonNull()); 601 } 602 603 llvm::Value *Address::emitRawPointerSlow(CodeGenFunction &CGF) const { 604 return CGF.getAsNaturalPointerTo(*this, QualType()); 605 } 606 607 llvm::Value *LValue::getPointer(CodeGenFunction &CGF) const { 608 assert(isSimple()); 609 return emitResignedPointer(getType(), CGF); 610 } 611 612 llvm::Value *LValue::emitResignedPointer(QualType PointeeTy, 613 CodeGenFunction &CGF) const { 614 assert(isSimple()); 615 return CGF.getAsNaturalAddressOf(Addr, PointeeTy).getBasePointer(); 616 } 617 618 llvm::Value *LValue::emitRawPointer(CodeGenFunction &CGF) const { 619 assert(isSimple()); 620 return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; 621 } 622