643 lines · cpp
1#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"2 3#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"4#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"5#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"6#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"7#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"8#include "llvm/DebugInfo/CodeView/SymbolRecord.h"9#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"10#include "llvm/DebugInfo/CodeView/TypeRecord.h"11#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"12#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"13#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"14#include "llvm/DebugInfo/PDB/Native/DbiStream.h"15#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"16#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"17#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"18#include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h"19#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"20#include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"21#include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h"22#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h"23#include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h"24#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"25#include "llvm/DebugInfo/PDB/Native/NativeSession.h"26#include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"27#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"28#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"29#include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"30#include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"31#include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h"32#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"33#include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"34#include "llvm/DebugInfo/PDB/Native/PDBFile.h"35#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"36#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"37#include "llvm/DebugInfo/PDB/Native/TpiStream.h"38#include "llvm/DebugInfo/PDB/PDBSymbol.h"39#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"40 41using namespace llvm;42using namespace llvm::codeview;43using namespace llvm::pdb;44 45// Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary46// to instantiate a NativeBuiltinSymbol for that type.47static const struct BuiltinTypeEntry {48 codeview::SimpleTypeKind Kind;49 PDB_BuiltinType Type;50 uint32_t Size;51} BuiltinTypes[] = {52 {codeview::SimpleTypeKind::None, PDB_BuiltinType::None, 0},53 {codeview::SimpleTypeKind::Void, PDB_BuiltinType::Void, 0},54 {codeview::SimpleTypeKind::HResult, PDB_BuiltinType::HResult, 4},55 {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},56 {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},57 {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},58 {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},59 {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},60 {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},61 {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},62 {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},63 {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},64 {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2},65 {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2},66 {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4},67 {codeview::SimpleTypeKind::Character8, PDB_BuiltinType::Char8, 1},68 {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},69 {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},70 {codeview::SimpleTypeKind::Float32, PDB_BuiltinType::Float, 4},71 {codeview::SimpleTypeKind::Float64, PDB_BuiltinType::Float, 8},72 {codeview::SimpleTypeKind::Float80, PDB_BuiltinType::Float, 10},73 {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1},74 // This table can be grown as necessary, but these are the only types we've75 // needed so far.76};77 78SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)79 : Session(Session), Dbi(Dbi) {80 // Id 0 is reserved for the invalid symbol.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<IPDBEnumSymbols>89SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {90 return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});91}92 93std::unique_ptr<IPDBEnumSymbols>94SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {95 auto Tpi = Session.getPDBFile().getPDBTpiStream();96 if (!Tpi) {97 consumeError(Tpi.takeError());98 return nullptr;99 }100 auto &Types = Tpi->typeCollection();101 return std::unique_ptr<IPDBEnumSymbols>(102 new NativeEnumTypes(Session, Types, std::move(Kinds)));103}104 105std::unique_ptr<IPDBEnumSymbols>106SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {107 return std::unique_ptr<IPDBEnumSymbols>(108 new NativeEnumGlobals(Session, {Kind}));109}110 111SymIndexId SymbolCache::createSimpleType(TypeIndex Index,112 ModifierOptions Mods) const {113 if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)114 return createSymbol<NativeTypePointer>(Index);115 116 const auto Kind = Index.getSimpleKind();117 const auto It =118 llvm::find_if(BuiltinTypes, [Kind](const BuiltinTypeEntry &Builtin) {119 return Builtin.Kind == Kind;120 });121 if (It == std::end(BuiltinTypes))122 return 0;123 return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);124}125 126SymIndexId127SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,128 codeview::CVType CVT) const {129 ModifierRecord Record;130 if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {131 consumeError(std::move(EC));132 return 0;133 }134 135 if (Record.ModifiedType.isSimple())136 return createSimpleType(Record.ModifiedType, Record.Modifiers);137 138 // Make sure we create and cache a record for the unmodified type.139 SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);140 NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];141 142 switch (UnmodifiedNRS.getSymTag()) {143 case PDB_SymType::Enum:144 return createSymbol<NativeTypeEnum>(145 static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));146 case PDB_SymType::UDT:147 return createSymbol<NativeTypeUDT>(148 static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));149 default:150 // No other types can be modified. (LF_POINTER, for example, records151 // its modifiers a different way.152 assert(false && "Invalid LF_MODIFIER record");153 break;154 }155 return 0;156}157 158SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) const {159 // First see if it's already in our cache.160 const auto Entry = TypeIndexToSymbolId.find(Index);161 if (Entry != TypeIndexToSymbolId.end())162 return Entry->second;163 164 // Symbols for built-in types are created on the fly.165 if (Index.isSimple()) {166 SymIndexId Result = createSimpleType(Index, ModifierOptions::None);167 assert(TypeIndexToSymbolId.count(Index) == 0);168 TypeIndexToSymbolId[Index] = Result;169 return Result;170 }171 172 // We need to instantiate and cache the desired type symbol.173 auto Tpi = Session.getPDBFile().getPDBTpiStream();174 if (!Tpi) {175 consumeError(Tpi.takeError());176 return 0;177 }178 codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();179 codeview::CVType CVT = Types.getType(Index);180 181 if (isUdtForwardRef(CVT)) {182 Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);183 184 if (!EFD)185 consumeError(EFD.takeError());186 else if (*EFD != Index) {187 assert(!isUdtForwardRef(Types.getType(*EFD)));188 SymIndexId Result = findSymbolByTypeIndex(*EFD);189 // Record a mapping from ForwardRef -> SymIndex of complete type so that190 // we'll take the fast path next time.191 assert(TypeIndexToSymbolId.count(Index) == 0);192 TypeIndexToSymbolId[Index] = Result;193 return Result;194 }195 }196 197 // At this point if we still have a forward ref udt it means the full decl was198 // not in the PDB. We just have to deal with it and use the forward ref.199 SymIndexId Id = 0;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<PDBSymbol>247SymbolCache::getSymbolById(SymIndexId SymbolId) const {248 assert(SymbolId < Cache.size());249 250 // Id 0 is reserved.251 if (SymbolId == 0 || SymbolId >= Cache.size())252 return nullptr;253 254 // Make sure to handle the case where we've inserted a placeholder symbol255 // for types we don't yet support.256 NativeRawSymbol *NRS = Cache[SymbolId].get();257 if (!NRS)258 return nullptr;259 260 return PDBSymbol::create(Session, *NRS);261}262 263NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {264 return *Cache[SymbolId];265}266 267uint32_t SymbolCache::getNumCompilands() const {268 if (!Dbi)269 return 0;270 271 return Dbi->modules().getModuleCount();272}273 274SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {275 auto Iter = GlobalOffsetToSymbolId.find(Offset);276 if (Iter != GlobalOffsetToSymbolId.end())277 return Iter->second;278 279 SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());280 CVSymbol CVS = SS.readRecord(Offset);281 SymIndexId Id = 0;282 switch (CVS.kind()) {283 case SymbolKind::S_UDT: {284 UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));285 Id = createSymbol<NativeTypeTypedef>(std::move(US));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 300SymIndexId SymbolCache::getOrCreateInlineSymbol(InlineSiteSym Sym,301 uint64_t ParentAddr,302 uint16_t Modi,303 uint32_t RecordOffset) const {304 auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset});305 if (Iter != SymTabOffsetToSymbolId.end())306 return Iter->second;307 308 SymIndexId Id = createSymbol<NativeInlineSiteSymbol>(Sym, ParentAddr);309 SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id});310 return Id;311}312 313std::unique_ptr<PDBSymbol>314SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,315 PDB_SymType Type) {316 switch (Type) {317 case PDB_SymType::Function:318 return findFunctionSymbolBySectOffset(Sect, Offset);319 case PDB_SymType::PublicSymbol:320 return findPublicSymbolBySectOffset(Sect, Offset);321 case PDB_SymType::Compiland: {322 uint16_t Modi;323 if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))324 return nullptr;325 return getOrCreateCompiland(Modi);326 }327 case PDB_SymType::None: {328 // FIXME: Implement for PDB_SymType::Data. The symbolizer calls this but329 // only uses it to find the symbol length.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<PDBSymbol>340SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {341 auto Iter = AddressToSymbolId.find({Sect, Offset});342 if (Iter != AddressToSymbolId.end())343 return getSymbolById(Iter->second);344 345 if (!Dbi)346 return nullptr;347 348 uint16_t Modi;349 if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))350 return nullptr;351 352 Expected<ModuleDebugStreamRef> ExpectedModS =353 Session.getModuleDebugStream(Modi);354 if (!ExpectedModS) {355 consumeError(ExpectedModS.takeError());356 return nullptr;357 }358 CVSymbolArray Syms = ExpectedModS->getSymbolArray();359 360 // Search for the symbol in this module.361 for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) {362 if (I->kind() != S_LPROC32 && I->kind() != S_GPROC32)363 continue;364 auto PS = cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*I));365 if (Sect == PS.Segment && Offset >= PS.CodeOffset &&366 Offset < PS.CodeOffset + PS.CodeSize) {367 // Check if the symbol is already cached.368 auto Found = AddressToSymbolId.find({PS.Segment, PS.CodeOffset});369 if (Found != AddressToSymbolId.end())370 return getSymbolById(Found->second);371 372 // Otherwise, create a new symbol.373 SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS, I.offset());374 AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset}, Id});375 return getSymbolById(Id);376 }377 378 // Jump to the end of this ProcSym.379 I = Syms.at(PS.End);380 }381 return nullptr;382}383 384std::unique_ptr<PDBSymbol>385SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {386 auto Iter = AddressToPublicSymId.find({Sect, Offset});387 if (Iter != AddressToPublicSymId.end())388 return getSymbolById(Iter->second);389 390 auto Publics = Session.getPDBFile().getPDBPublicsStream();391 if (!Publics) {392 consumeError(Publics.takeError());393 return nullptr;394 }395 396 auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream();397 if (!ExpectedSyms) {398 consumeError(ExpectedSyms.takeError());399 return nullptr;400 }401 BinaryStreamRef SymStream =402 ExpectedSyms->getSymbolArray().getUnderlyingStream();403 404 // Use binary search to find the first public symbol with an address greater405 // than or equal to Sect, Offset.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) {412 It = First;413 Half = Count / 2;414 It += Half;415 Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);416 if (!Sym) {417 consumeError(Sym.takeError());418 return nullptr;419 }420 421 auto PS =422 cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));423 if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <= Offset)) {424 First = ++It;425 Count -= Half + 1;426 } else427 Count = Half;428 }429 if (It == AddrMap.begin())430 return nullptr;431 --It;432 433 Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);434 if (!Sym) {435 consumeError(Sym.takeError());436 return nullptr;437 }438 439 // Check if the symbol is already cached.440 auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));441 auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset});442 if (Found != AddressToPublicSymId.end())443 return getSymbolById(Found->second);444 445 // Otherwise, create a new symbol.446 SymIndexId Id = createSymbol<NativePublicSymbol>(PS);447 AddressToPublicSymId.insert({{PS.Segment, PS.Offset}, Id});448 return getSymbolById(Id);449}450 451std::vector<SymbolCache::LineTableEntry>452SymbolCache::findLineTable(uint16_t Modi) const {453 // Check if this module has already been added.454 auto [LineTableIter, Inserted] = LineTable.try_emplace(Modi);455 if (!Inserted)456 return LineTableIter->second;457 458 std::vector<LineTableEntry> &ModuleLineTable = LineTableIter->second;459 460 // If there is an error or there are no lines, just return the461 // empty vector.462 Expected<ModuleDebugStreamRef> ExpectedModS =463 Session.getModuleDebugStream(Modi);464 if (!ExpectedModS) {465 consumeError(ExpectedModS.takeError());466 return ModuleLineTable;467 }468 469 std::vector<std::vector<LineTableEntry>> 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)) {477 consumeError(std::move(EC));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<LineTableEntry> Entries;488 489 // If there are column numbers, then they should be in a parallel stream490 // to the line numbers.491 auto ColIt = Group.Columns.begin();492 auto ColsEnd = Group.Columns.end();493 494 // Add a line to mark the beginning of this section.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);505 LineInfo Line(LN.Flags);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 // Add a terminal entry line to mark the end of this subsection.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 // Sort EntryList, and add flattened contents to the line table.526 llvm::sort(EntryList, [](const std::vector<LineTableEntry> &LHS,527 const std::vector<LineTableEntry> &RHS) {528 return LHS[0].Addr < RHS[0].Addr;529 });530 for (std::vector<LineTableEntry> &I : EntryList)531 llvm::append_range(ModuleLineTable, I);532 533 return ModuleLineTable;534}535 536std::unique_ptr<IPDBEnumLineNumbers>537SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {538 uint16_t Modi;539 if (!Session.moduleIndexForVA(VA, Modi))540 return nullptr;541 542 std::vector<LineTableEntry> Lines = findLineTable(Modi);543 if (Lines.empty())544 return nullptr;545 546 // Find the first line in the line table whose address is not greater than547 // the one we are searching for.548 auto LineIter = llvm::partition_point(Lines, [&](const LineTableEntry &E) {549 return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));550 });551 552 // Try to back up if we've gone too far.553 if (LineIter == Lines.end() || LineIter->Addr > VA) {554 if (LineIter == Lines.begin() || std::prev(LineIter)->IsTerminalEntry)555 return nullptr;556 --LineIter;557 }558 559 Expected<ModuleDebugStreamRef> ExpectedModS =560 Session.getModuleDebugStream(Modi);561 if (!ExpectedModS) {562 consumeError(ExpectedModS.takeError());563 return nullptr;564 }565 Expected<DebugChecksumsSubsectionRef> ExpectedChecksums =566 ExpectedModS->findChecksumsSubsection();567 if (!ExpectedChecksums) {568 consumeError(ExpectedChecksums.takeError());569 return nullptr;570 }571 572 // Populate a vector of NativeLineNumbers that have addresses in the given573 // address range.574 std::vector<NativeLineNumber> LineNumbers;575 while (LineIter != Lines.end()) {576 if (LineIter->IsTerminalEntry) {577 ++LineIter;578 continue;579 }580 581 // If the line is still within the address range, create a NativeLineNumber582 // and add to the list.583 if (LineIter->Addr > VA + Length)584 break;585 586 uint32_t LineSect, LineOff;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);591 uint32_t SrcFileId = getOrCreateSourceFile(*ChecksumIter);592 NativeLineNumber LineNum(Session, LineIter->Line, LineIter->ColumnNumber,593 LineSect, LineOff, LineLength, SrcFileId, Modi);594 LineNumbers.push_back(LineNum);595 ++LineIter;596 }597 return std::make_unique<NativeEnumLineNumbers>(std::move(LineNumbers));598}599 600std::unique_ptr<PDBSymbolCompiland>601SymbolCache::getOrCreateCompiland(uint32_t Index) {602 if (!Dbi)603 return nullptr;604 605 if (Index >= Compilands.size())606 return nullptr;607 608 if (Compilands[Index] == 0) {609 const DbiModuleList &Modules = Dbi->modules();610 Compilands[Index] =611 createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));612 }613 614 return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);615}616 617std::unique_ptr<IPDBSourceFile>618SymbolCache::getSourceFileById(SymIndexId FileId) const {619 assert(FileId < SourceFiles.size());620 621 // Id 0 is reserved.622 if (FileId == 0)623 return nullptr;624 625 return std::make_unique<NativeSourceFile>(*SourceFiles[FileId].get());626}627 628SymIndexId629SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const {630 auto [Iter, Inserted] =631 FileNameOffsetToId.try_emplace(Checksums.FileNameOffset);632 if (!Inserted)633 return Iter->second;634 635 SymIndexId Id = SourceFiles.size();636 auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums);637 SourceFiles.push_back(std::move(SrcFile));638 Iter->second = Id;639 return Id;640}641 642 643