brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.0 KiB · 535893b Raw
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