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 necessary
46// 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've
75    // 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
126SymIndexId
127SymbolCache::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, records
151    // 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 that
190      // 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 was
198  // 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 symbol
255  // 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 but
329    // 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    return nullptr;
393
394  auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream();
395  if (!ExpectedSyms)
396    return nullptr;
397  BinaryStreamRef SymStream =
398      ExpectedSyms->getSymbolArray().getUnderlyingStream();
399
400  // Use binary search to find the first public symbol with an address greater
401  // than or equal to Sect, Offset.
402  auto AddrMap = Publics->getAddressMap();
403  auto First = AddrMap.begin();
404  auto It = AddrMap.begin();
405  size_t Count = AddrMap.size();
406  size_t Half;
407  while (Count > 0) {
408    It = First;
409    Half = Count / 2;
410    It += Half;
411    Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
412    if (!Sym) {
413      consumeError(Sym.takeError());
414      return nullptr;
415    }
416
417    auto PS =
418        cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
419    if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <= Offset)) {
420      First = ++It;
421      Count -= Half + 1;
422    } else
423      Count = Half;
424  }
425  if (It == AddrMap.begin())
426    return nullptr;
427  --It;
428
429  Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
430  if (!Sym) {
431    consumeError(Sym.takeError());
432    return nullptr;
433  }
434
435  // Check if the symbol is already cached.
436  auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
437  auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset});
438  if (Found != AddressToPublicSymId.end())
439    return getSymbolById(Found->second);
440
441  // Otherwise, create a new symbol.
442  SymIndexId Id = createSymbol<NativePublicSymbol>(PS);
443  AddressToPublicSymId.insert({{PS.Segment, PS.Offset}, Id});
444  return getSymbolById(Id);
445}
446
447std::vector<SymbolCache::LineTableEntry>
448SymbolCache::findLineTable(uint16_t Modi) const {
449  // Check if this module has already been added.
450  auto LineTableIter = LineTable.find(Modi);
451  if (LineTableIter != LineTable.end())
452    return LineTableIter->second;
453
454  std::vector<LineTableEntry> &ModuleLineTable = LineTable[Modi];
455
456  // If there is an error or there are no lines, just return the
457  // empty vector.
458  Expected<ModuleDebugStreamRef> ExpectedModS =
459      Session.getModuleDebugStream(Modi);
460  if (!ExpectedModS) {
461    consumeError(ExpectedModS.takeError());
462    return ModuleLineTable;
463  }
464
465  std::vector<std::vector<LineTableEntry>> EntryList;
466  for (const auto &SS : ExpectedModS->getSubsectionsArray()) {
467    if (SS.kind() != DebugSubsectionKind::Lines)
468      continue;
469
470    DebugLinesSubsectionRef Lines;
471    BinaryStreamReader Reader(SS.getRecordData());
472    if (auto EC = Lines.initialize(Reader)) {
473      consumeError(std::move(EC));
474      continue;
475    }
476
477    uint32_t RelocSegment = Lines.header()->RelocSegment;
478    uint32_t RelocOffset = Lines.header()->RelocOffset;
479    for (const LineColumnEntry &Group : Lines) {
480      if (Group.LineNumbers.empty())
481        continue;
482
483      std::vector<LineTableEntry> Entries;
484
485      // If there are column numbers, then they should be in a parallel stream
486      // to the line numbers.
487      auto ColIt = Group.Columns.begin();
488      auto ColsEnd = Group.Columns.end();
489
490      // Add a line to mark the beginning of this section.
491      uint64_t StartAddr =
492          Session.getVAFromSectOffset(RelocSegment, RelocOffset);
493      LineInfo FirstLine(Group.LineNumbers.front().Flags);
494      uint32_t ColNum =
495          (Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0;
496      Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex, false});
497
498      for (const LineNumberEntry &LN : Group.LineNumbers) {
499        uint64_t VA =
500            Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.Offset);
501        LineInfo Line(LN.Flags);
502        ColNum = 0;
503
504        if (Lines.hasColumnInfo() && ColIt != ColsEnd) {
505          ColNum = ColIt->StartColumn;
506          ++ColIt;
507        }
508        Entries.push_back({VA, Line, ColNum, Group.NameIndex, false});
509      }
510
511      // Add a terminal entry line to mark the end of this subsection.
512      uint64_t EndAddr = StartAddr + Lines.header()->CodeSize;
513      LineInfo LastLine(Group.LineNumbers.back().Flags);
514      ColNum = (Lines.hasColumnInfo()) ? Group.Columns.back().StartColumn : 0;
515      Entries.push_back({EndAddr, LastLine, ColNum, Group.NameIndex, true});
516
517      EntryList.push_back(Entries);
518    }
519  }
520
521  // Sort EntryList, and add flattened contents to the line table.
522  llvm::sort(EntryList, [](const std::vector<LineTableEntry> &LHS,
523                           const std::vector<LineTableEntry> &RHS) {
524    return LHS[0].Addr < RHS[0].Addr;
525  });
526  for (std::vector<LineTableEntry> &I : EntryList)
527    llvm::append_range(ModuleLineTable, I);
528
529  return ModuleLineTable;
530}
531
532std::unique_ptr<IPDBEnumLineNumbers>
533SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
534  uint16_t Modi;
535  if (!Session.moduleIndexForVA(VA, Modi))
536    return nullptr;
537
538  std::vector<LineTableEntry> Lines = findLineTable(Modi);
539  if (Lines.empty())
540    return nullptr;
541
542  // Find the first line in the line table whose address is not greater than
543  // the one we are searching for.
544  auto LineIter = llvm::partition_point(Lines, [&](const LineTableEntry &E) {
545    return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));
546  });
547
548  // Try to back up if we've gone too far.
549  if (LineIter == Lines.end() || LineIter->Addr > VA) {
550    if (LineIter == Lines.begin() || std::prev(LineIter)->IsTerminalEntry)
551      return nullptr;
552    --LineIter;
553  }
554
555  Expected<ModuleDebugStreamRef> ExpectedModS =
556      Session.getModuleDebugStream(Modi);
557  if (!ExpectedModS) {
558    consumeError(ExpectedModS.takeError());
559    return nullptr;
560  }
561  Expected<DebugChecksumsSubsectionRef> ExpectedChecksums =
562      ExpectedModS->findChecksumsSubsection();
563  if (!ExpectedChecksums) {
564    consumeError(ExpectedChecksums.takeError());
565    return nullptr;
566  }
567
568  // Populate a vector of NativeLineNumbers that have addresses in the given
569  // address range.
570  std::vector<NativeLineNumber> LineNumbers;
571  while (LineIter != Lines.end()) {
572    if (LineIter->IsTerminalEntry) {
573      ++LineIter;
574      continue;
575    }
576
577    // If the line is still within the address range, create a NativeLineNumber
578    // and add to the list.
579    if (LineIter->Addr > VA + Length)
580      break;
581
582    uint32_t LineSect, LineOff;
583    Session.addressForVA(LineIter->Addr, LineSect, LineOff);
584    uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr;
585    auto ChecksumIter =
586        ExpectedChecksums->getArray().at(LineIter->FileNameIndex);
587    uint32_t SrcFileId = getOrCreateSourceFile(*ChecksumIter);
588    NativeLineNumber LineNum(Session, LineIter->Line, LineIter->ColumnNumber,
589                             LineSect, LineOff, LineLength, SrcFileId, Modi);
590    LineNumbers.push_back(LineNum);
591    ++LineIter;
592  }
593  return std::make_unique<NativeEnumLineNumbers>(std::move(LineNumbers));
594}
595
596std::unique_ptr<PDBSymbolCompiland>
597SymbolCache::getOrCreateCompiland(uint32_t Index) {
598  if (!Dbi)
599    return nullptr;
600
601  if (Index >= Compilands.size())
602    return nullptr;
603
604  if (Compilands[Index] == 0) {
605    const DbiModuleList &Modules = Dbi->modules();
606    Compilands[Index] =
607        createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
608  }
609
610  return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
611}
612
613std::unique_ptr<IPDBSourceFile>
614SymbolCache::getSourceFileById(SymIndexId FileId) const {
615  assert(FileId < SourceFiles.size());
616
617  // Id 0 is reserved.
618  if (FileId == 0)
619    return nullptr;
620
621  return std::unique_ptr<NativeSourceFile>(
622      new NativeSourceFile(*SourceFiles[FileId].get()));
623}
624
625SymIndexId
626SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const {
627  auto Iter = FileNameOffsetToId.find(Checksums.FileNameOffset);
628  if (Iter != FileNameOffsetToId.end())
629    return Iter->second;
630
631  SymIndexId Id = SourceFiles.size();
632  auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums);
633  SourceFiles.push_back(std::move(SrcFile));
634  FileNameOffsetToId[Checksums.FileNameOffset] = Id;
635  return Id;
636}
637
638
639