LLVM: lib/DebugInfo/PDB/Native/SymbolCache.cpp Source File (original) (raw)

2

40

41using namespace llvm;

44

45

46

74

75

77

79 : Session(Session), Dbi(Dbi) {

80

81 Cache.push_back(nullptr);

82 SourceFiles.push_back(nullptr);

83

84 if (Dbi)

85 Compilands.resize(Dbi->modules().getModuleCount());

86}

87

88std::unique_ptr

92

93std::unique_ptr

95 auto Tpi = Session.getPDBFile().getPDBTpiStream();

96 if (!Tpi) {

98 return nullptr;

99 }

100 auto &Types = Tpi->typeCollection();

101 return std::unique_ptr(

103}

104

105std::unique_ptr

107 return std::unique_ptr(

109}

110

115

116 const auto Kind = Index.getSimpleKind();

117 const auto It =

119 return Builtin.Kind == Kind;

120 });

122 return 0;

124}

125

132 return 0;

133 }

134

137

138

140 NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];

141

142 switch (UnmodifiedNRS.getSymTag()) {

145 static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));

148 static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));

149 default:

150

151

152 assert(false && "Invalid LF_MODIFIER record");

153 break;

154 }

155 return 0;

156}

157

159

160 const auto Entry = TypeIndexToSymbolId.find(Index);

161 if (Entry != TypeIndexToSymbolId.end())

162 return Entry->second;

163

164

165 if (Index.isSimple()) {

167 assert(TypeIndexToSymbolId.count(Index) == 0);

168 TypeIndexToSymbolId[Index] = Result;

169 return Result;

170 }

171

172

173 auto Tpi = Session.getPDBFile().getPDBTpiStream();

174 if (!Tpi) {

176 return 0;

177 }

180

183

184 if (!EFD)

186 else if (*EFD != Index) {

189

190

191 assert(TypeIndexToSymbolId.count(Index) == 0);

192 TypeIndexToSymbolId[Index] = Result;

193 return Result;

194 }

195 }

196

197

198

200 switch (CVT.kind()) {

201 case codeview::LF_ENUM:

202 Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));

203 break;

204 case codeview::LF_ARRAY:

205 Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,

206 std::move(CVT));

207 break;

208 case codeview::LF_CLASS:

209 case codeview::LF_STRUCTURE:

210 case codeview::LF_INTERFACE:

211 Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));

212 break;

213 case codeview::LF_UNION:

214 Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));

215 break;

216 case codeview::LF_POINTER:

217 Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,

218 std::move(CVT));

219 break;

220 case codeview::LF_MODIFIER:

221 Id = createSymbolForModifiedType(Index, std::move(CVT));

222 break;

223 case codeview::LF_PROCEDURE:

224 Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(

225 Index, std::move(CVT));

226 break;

227 case codeview::LF_MFUNCTION:

228 Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(

229 Index, std::move(CVT));

230 break;

231 case codeview::LF_VTSHAPE:

232 Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(

233 Index, std::move(CVT));

234 break;

235 default:

236 Id = createSymbolPlaceholder();

237 break;

238 }

239 if (Id != 0) {

240 assert(TypeIndexToSymbolId.count(Index) == 0);

241 TypeIndexToSymbolId[Index] = Id;

242 }

243 return Id;

244}

245

246std::unique_ptr

248 assert(SymbolId < Cache.size());

249

250

251 if (SymbolId == 0 || SymbolId >= Cache.size())

252 return nullptr;

253

254

255

257 if (!NRS)

258 return nullptr;

259

261}

262

264 return *Cache[SymbolId];

265}

266

268 if (!Dbi)

269 return 0;

270

271 return Dbi->modules().getModuleCount();

272}

273

275 auto Iter = GlobalOffsetToSymbolId.find(Offset);

276 if (Iter != GlobalOffsetToSymbolId.end())

277 return Iter->second;

278

282 switch (CVS.kind()) {

283 case SymbolKind::S_UDT: {

286 break;

287 }

288 default:

289 Id = createSymbolPlaceholder();

290 break;

291 }

292 if (Id != 0) {

293 assert(GlobalOffsetToSymbolId.count(Offset) == 0);

294 GlobalOffsetToSymbolId[Offset] = Id;

295 }

296

297 return Id;

298}

299

303 uint32_t RecordOffset) const {

304 auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset});

305 if (Iter != SymTabOffsetToSymbolId.end())

306 return Iter->second;

307

309 SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id});

310 return Id;

311}

312

313std::unique_ptr

316 switch (Type) {

318 return findFunctionSymbolBySectOffset(Sect, Offset);

320 return findPublicSymbolBySectOffset(Sect, Offset);

323 if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))

324 return nullptr;

326 }

328

329

330 if (auto Sym = findFunctionSymbolBySectOffset(Sect, Offset))

331 return Sym;

332 return nullptr;

333 }

334 default:

335 return nullptr;

336 }

337}

338

339std::unique_ptr

341 auto Iter = AddressToSymbolId.find({Sect, Offset});

342 if (Iter != AddressToSymbolId.end())

344

345 if (!Dbi)

346 return nullptr;

347

350 return nullptr;

351

354 if (!ExpectedModS) {

356 return nullptr;

357 }

358 CVSymbolArray Syms = ExpectedModS->getSymbolArray();

359

360

361 for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) {

362 if (I->kind() != S_LPROC32 && I->kind() != S_GPROC32)

363 continue;

365 if (Sect == PS.Segment && Offset >= PS.CodeOffset &&

366 Offset < PS.CodeOffset + PS.CodeSize) {

367

368 auto Found = AddressToSymbolId.find({PS.Segment, PS.CodeOffset});

369 if (Found != AddressToSymbolId.end())

371

372

374 AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset}, Id});

376 }

377

378

379 I = Syms.at(PS.End);

380 }

381 return nullptr;

382}

383

384std::unique_ptr

385SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {

386 auto Iter = AddressToPublicSymId.find({Sect, Offset});

387 if (Iter != AddressToPublicSymId.end())

389

390 auto Publics = Session.getPDBFile().getPDBPublicsStream();

391 if (!Publics) {

393 return nullptr;

394 }

395

396 auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream();

397 if (!ExpectedSyms) {

399 return nullptr;

400 }

401 BinaryStreamRef SymStream =

402 ExpectedSyms->getSymbolArray().getUnderlyingStream();

403

404

405

406 auto AddrMap = Publics->getAddressMap();

407 auto First = AddrMap.begin();

408 auto It = AddrMap.begin();

409 size_t Count = AddrMap.size();

410 size_t Half;

411 while (Count > 0) {

413 Half = Count / 2;

414 It += Half;

416 if (!Sym) {

418 return nullptr;

419 }

420

421 auto PS =

423 if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <= Offset)) {

425 Count -= Half + 1;

426 } else

428 }

429 if (It == AddrMap.begin())

430 return nullptr;

431 --It;

432

434 if (!Sym) {

436 return nullptr;

437 }

438

439

441 auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset});

442 if (Found != AddressToPublicSymId.end())

444

445

447 AddressToPublicSymId.insert({{PS.Segment, PS.Offset}, Id});

449}

450

451std::vectorSymbolCache::LineTableEntry

452SymbolCache::findLineTable(uint16_t Modi) const {

453

454 auto [LineTableIter, Inserted] = LineTable.try_emplace(Modi);

455 if (!Inserted)

456 return LineTableIter->second;

457

458 std::vector &ModuleLineTable = LineTableIter->second;

459

460

461

462 Expected ExpectedModS =

463 Session.getModuleDebugStream(Modi);

464 if (!ExpectedModS) {

466 return ModuleLineTable;

467 }

468

469 std::vector<std::vector> EntryList;

470 for (const auto &SS : ExpectedModS->getSubsectionsArray()) {

471 if (SS.kind() != DebugSubsectionKind::Lines)

472 continue;

473

474 DebugLinesSubsectionRef Lines;

475 BinaryStreamReader Reader(SS.getRecordData());

476 if (auto EC = Lines.initialize(Reader)) {

478 continue;

479 }

480

481 uint32_t RelocSegment = Lines.header()->RelocSegment;

482 uint32_t RelocOffset = Lines.header()->RelocOffset;

483 for (const LineColumnEntry &Group : Lines) {

484 if (Group.LineNumbers.empty())

485 continue;

486

487 std::vector Entries;

488

489

490

491 auto ColIt = Group.Columns.begin();

492 auto ColsEnd = Group.Columns.end();

493

494

495 uint64_t StartAddr =

496 Session.getVAFromSectOffset(RelocSegment, RelocOffset);

497 LineInfo FirstLine(Group.LineNumbers.front().Flags);

498 uint32_t ColNum =

499 (Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0;

500 Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex, false});

501

502 for (const LineNumberEntry &LN : Group.LineNumbers) {

503 uint64_t VA =

504 Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.Offset);

506 ColNum = 0;

507

508 if (Lines.hasColumnInfo() && ColIt != ColsEnd) {

509 ColNum = ColIt->StartColumn;

510 ++ColIt;

511 }

512 Entries.push_back({VA, Line, ColNum, Group.NameIndex, false});

513 }

514

515

516 uint64_t EndAddr = StartAddr + Lines.header()->CodeSize;

517 LineInfo LastLine(Group.LineNumbers.back().Flags);

518 ColNum = (Lines.hasColumnInfo()) ? Group.Columns.back().StartColumn : 0;

519 Entries.push_back({EndAddr, LastLine, ColNum, Group.NameIndex, true});

520

521 EntryList.push_back(Entries);

522 }

523 }

524

525

526 llvm::sort(EntryList, [](const std::vector &LHS,

527 const std::vector &RHS) {

528 return LHS[0].Addr < RHS[0].Addr;

529 });

530 for (std::vector &I : EntryList)

532

533 return ModuleLineTable;

534}

535

536std::unique_ptr

539 if (!Session.moduleIndexForVA(VA, Modi))

540 return nullptr;

541

542 std::vector Lines = findLineTable(Modi);

543 if (Lines.empty())

544 return nullptr;

545

546

547

549 return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));

550 });

551

552

553 if (LineIter == Lines.end() || LineIter->Addr > VA) {

554 if (LineIter == Lines.begin() || std::prev(LineIter)->IsTerminalEntry)

555 return nullptr;

556 --LineIter;

557 }

558

560 Session.getModuleDebugStream(Modi);

561 if (!ExpectedModS) {

563 return nullptr;

564 }

566 ExpectedModS->findChecksumsSubsection();

567 if (!ExpectedChecksums) {

569 return nullptr;

570 }

571

572

573

574 std::vector LineNumbers;

575 while (LineIter != Lines.end()) {

576 if (LineIter->IsTerminalEntry) {

577 ++LineIter;

578 continue;

579 }

580

581

582

583 if (LineIter->Addr > VA + Length)

584 break;

585

587 Session.addressForVA(LineIter->Addr, LineSect, LineOff);

588 uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr;

589 auto ChecksumIter =

590 ExpectedChecksums->getArray().at(LineIter->FileNameIndex);

592 NativeLineNumber LineNum(Session, LineIter->Line, LineIter->ColumnNumber,

593 LineSect, LineOff, LineLength, SrcFileId, Modi);

595 ++LineIter;

596 }

597 return std::make_unique(std::move(LineNumbers));

598}

599

600std::unique_ptr

602 if (!Dbi)

603 return nullptr;

604

605 if (Index >= Compilands.size())

606 return nullptr;

607

608 if (Compilands[Index] == 0) {

610 Compilands[Index] =

612 }

613

614 return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);

615}

616

617std::unique_ptr

619 assert(FileId < SourceFiles.size());

620

621

622 if (FileId == 0)

623 return nullptr;

624

625 return std::make_unique(*SourceFiles[FileId].get());

626}

627

630 auto [Iter, Inserted] =

631 FileNameOffsetToId.try_emplace(Checksums.FileNameOffset);

632 if (!Inserted)

633 return Iter->second;

634

636 auto SrcFile = std::make_unique(Session, Id, Checksums);

637 SourceFiles.push_back(std::move(SrcFile));

638 Iter->second = Id;

639 return Id;

640}

641

642

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static const struct BuiltinTypeEntry BuiltinTypes[]

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

reference get()

Returns a reference to the stored T value.

Iterator at(uint32_t Offset) const

given an offset into the array's underlying stream, return an iterator to the record at that offset.

Iterator begin(bool *HadError=nullptr) const

Provides amortized O(1) random access to a CodeView type stream.

ModifierOptions Modifiers

static Error deserializeAs(CVSymbol Symbol, T &Record)

static Error deserializeAs(CVType &CVT, T &Record)

LLVM_ABI DbiModuleDescriptor getModuleDescriptor(uint32_t Modi) const

PDB_SymType getSymTag() const override

bool moduleIndexForSectOffset(uint32_t Sect, uint32_t Offset, uint16_t &ModuleIndex) const

Expected< ModuleDebugStreamRef > getModuleDebugStream(uint32_t Index) const

static std::unique_ptr< PDBSymbol > create(const IPDBSession &PDBSession, std::unique_ptr< IPDBRawSymbol > RawSymbol)

LLVM_ABI std::unique_ptr< IPDBEnumSymbols > createGlobalsEnumerator(codeview::SymbolKind Kind)

Definition SymbolCache.cpp:106

LLVM_ABI SymIndexId getOrCreateInlineSymbol(codeview::InlineSiteSym Sym, uint64_t ParentAddr, uint16_t Modi, uint32_t RecordOffset) const

Definition SymbolCache.cpp:300

LLVM_ABI std::unique_ptr< IPDBEnumSymbols > createTypeEnumerator(codeview::TypeLeafKind Kind)

Definition SymbolCache.cpp:89

LLVM_ABI std::unique_ptr< PDBSymbol > getSymbolById(SymIndexId SymbolId) const

Definition SymbolCache.cpp:247

LLVM_ABI SymbolCache(NativeSession &Session, DbiStream *Dbi)

Definition SymbolCache.cpp:78

LLVM_ABI SymIndexId getOrCreateSourceFile(const codeview::FileChecksumEntry &Checksum) const

Definition SymbolCache.cpp:629

LLVM_ABI SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI) const

Definition SymbolCache.cpp:158

LLVM_ABI NativeRawSymbol & getNativeSymbolById(SymIndexId SymbolId) const

Definition SymbolCache.cpp:263

LLVM_ABI std::unique_ptr< PDBSymbolCompiland > getOrCreateCompiland(uint32_t Index)

Definition SymbolCache.cpp:601

LLVM_ABI uint32_t getNumCompilands() const

Definition SymbolCache.cpp:267

LLVM_ABI std::unique_ptr< IPDBSourceFile > getSourceFileById(SymIndexId FileId) const

Definition SymbolCache.cpp:618

LLVM_ABI std::unique_ptr< IPDBEnumLineNumbers > findLineNumbersByVA(uint64_t VA, uint32_t Length) const

Definition SymbolCache.cpp:537

SymIndexId createSymbol(Args &&...ConstructorArgs) const

LLVM_ABI std::unique_ptr< PDBSymbol > findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type)

Definition SymbolCache.cpp:314

LLVM_ABI SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset)

Definition SymbolCache.cpp:274

LLVM_ABI bool isUdtForwardRef(CVType CVT)

Given an arbitrary codeview type, determine if it is an LF_STRUCTURE, LF_CLASS, LF_INTERFACE,...

CVRecord< TypeLeafKind > CVType

VarStreamArray< CVSymbol > CVSymbolArray

CVRecord< SymbolKind > CVSymbol

TypeLeafKind

Duplicate copy of the above enum, but using the official CV names.

SymbolKind

Duplicate copy of the above enum, but using the official CV names.

ModifierOptions

Equivalent to CV_modifier_t.

LLVM_ABI Expected< CVSymbol > readSymbolFromStream(BinaryStreamRef Stream, uint32_t Offset)

PDB_BuiltinType

These values correspond to the Basictype enumeration, and are documented here: https://msdn....

PDB_SymType

These values correspond to the SymTagEnum enumeration, and are documented here: https://msdn....

This is an optimization pass for GlobalISel generic memory operations.

auto partition_point(R &&Range, Predicate P)

Binary search for the first iterator in a range where a predicate is false.

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)

void sort(IteratorTy Start, IteratorTy End)

FunctionAddr VTableAddr Count

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

void cantFail(Error Err, const char *Msg=nullptr)

Report a fatal error if Err is a failure value.

auto find_if(R &&Range, UnaryPredicate P)

Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.

void consumeError(Error Err)

Consume a Error without doing anything.

Definition SymbolCache.cpp:47

codeview::SimpleTypeKind Kind

Definition SymbolCache.cpp:48

uint32_t Size

Definition SymbolCache.cpp:50

PDB_BuiltinType Type

Definition SymbolCache.cpp:49

support::ulittle32_t Offset

support::ulittle32_t Flags