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(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

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 (Record->getDefinition() || Record->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 && hasOffset())

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.