79 : Session(Session), Dbi(Dbi) {
81 Cache.push_back(
nullptr);
82 SourceFiles.push_back(
nullptr);
85 Compilands.resize(Dbi->modules().getModuleCount());
88std::unique_ptr<IPDBEnumSymbols>
93std::unique_ptr<IPDBEnumSymbols>
95 auto Tpi = Session.getPDBFile().getPDBTpiStream();
100 auto &Types = Tpi->typeCollection();
101 return std::unique_ptr<IPDBEnumSymbols>(
105std::unique_ptr<IPDBEnumSymbols>
107 return std::unique_ptr<IPDBEnumSymbols>(
116 const auto Kind = Index.getSimpleKind();
119 return Builtin.
Kind == Kind;
140 NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
145 static_cast<NativeTypeEnum &
>(UnmodifiedNRS), std::move(Record));
148 static_cast<NativeTypeUDT &
>(UnmodifiedNRS), std::move(Record));
152 assert(
false &&
"Invalid LF_MODIFIER record");
160 const auto Entry = TypeIndexToSymbolId.find(Index);
161 if (Entry != TypeIndexToSymbolId.end())
162 return Entry->second;
165 if (Index.isSimple()) {
167 assert(TypeIndexToSymbolId.count(Index) == 0);
168 TypeIndexToSymbolId[Index] = Result;
173 auto Tpi = Session.getPDBFile().getPDBTpiStream();
186 else if (*EFD != Index) {
191 assert(TypeIndexToSymbolId.count(Index) == 0);
192 TypeIndexToSymbolId[Index] = Result;
200 switch (CVT.
kind()) {
201 case codeview::LF_ENUM:
202 Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
204 case codeview::LF_ARRAY:
205 Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
208 case codeview::LF_CLASS:
209 case codeview::LF_STRUCTURE:
210 case codeview::LF_INTERFACE:
211 Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
213 case codeview::LF_UNION:
214 Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
216 case codeview::LF_POINTER:
217 Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
220 case codeview::LF_MODIFIER:
221 Id = createSymbolForModifiedType(Index, std::move(CVT));
223 case codeview::LF_PROCEDURE:
224 Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
225 Index, std::move(CVT));
227 case codeview::LF_MFUNCTION:
228 Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
229 Index, std::move(CVT));
231 case codeview::LF_VTSHAPE:
232 Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
233 Index, std::move(CVT));
236 Id = createSymbolPlaceholder();
240 assert(TypeIndexToSymbolId.count(Index) == 0);
241 TypeIndexToSymbolId[Index] = Id;
246std::unique_ptr<PDBSymbol>
248 assert(SymbolId < Cache.size());
251 if (SymbolId == 0 || SymbolId >= Cache.size())
264 return *Cache[SymbolId];
271 return Dbi->modules().getModuleCount();
275 auto Iter = GlobalOffsetToSymbolId.find(
Offset);
276 if (Iter != GlobalOffsetToSymbolId.end())
282 switch (CVS.
kind()) {
283 case SymbolKind::S_UDT: {
289 Id = createSymbolPlaceholder();
294 GlobalOffsetToSymbolId[
Offset] = Id;
304 auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset});
305 if (Iter != SymTabOffsetToSymbolId.end())
309 SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id});
313std::unique_ptr<PDBSymbol>
318 return findFunctionSymbolBySectOffset(Sect,
Offset);
320 return findPublicSymbolBySectOffset(Sect,
Offset);
323 if (!Session.moduleIndexForSectOffset(Sect,
Offset, Modi))
330 if (
auto Sym = findFunctionSymbolBySectOffset(Sect,
Offset))
339std::unique_ptr<PDBSymbol>
341 auto Iter = AddressToSymbolId.find({Sect,
Offset});
342 if (Iter != AddressToSymbolId.end())
362 if (
I->kind() != S_LPROC32 &&
I->kind() != S_GPROC32)
365 if (Sect == PS.Segment &&
Offset >= PS.CodeOffset &&
366 Offset < PS.CodeOffset + PS.CodeSize) {
368 auto Found = AddressToSymbolId.find({PS.Segment, PS.CodeOffset});
369 if (Found != AddressToSymbolId.end())
374 AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset},
Id});
384std::unique_ptr<PDBSymbol>
385SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t
Offset) {
386 auto Iter = AddressToPublicSymId.find({Sect,
Offset});
387 if (Iter != AddressToPublicSymId.end())
390 auto Publics = Session.getPDBFile().getPDBPublicsStream();
396 auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream();
401 BinaryStreamRef SymStream =
402 ExpectedSyms->getSymbolArray().getUnderlyingStream();
406 auto AddrMap =
Publics->getAddressMap();
407 auto First = AddrMap.begin();
408 auto It = AddrMap.begin();
409 size_t Count = AddrMap.size();
423 if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <=
Offset)) {
429 if (It == AddrMap.begin())
441 auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset});
442 if (Found != AddressToPublicSymId.end())
447 AddressToPublicSymId.insert({{PS.Segment, PS.Offset},
Id});
451std::vector<SymbolCache::LineTableEntry>
452SymbolCache::findLineTable(uint16_t Modi)
const {
454 auto [LineTableIter,
Inserted] = LineTable.try_emplace(Modi);
456 return LineTableIter->second;
458 std::vector<LineTableEntry> &ModuleLineTable = LineTableIter->second;
462 Expected<ModuleDebugStreamRef> ExpectedModS =
463 Session.getModuleDebugStream(Modi);
466 return ModuleLineTable;
469 std::vector<std::vector<LineTableEntry>> EntryList;
470 for (
const auto &SS : ExpectedModS->getSubsectionsArray()) {
471 if (
SS.kind() != DebugSubsectionKind::Lines)
474 DebugLinesSubsectionRef
Lines;
475 BinaryStreamReader Reader(
SS.getRecordData());
476 if (
auto EC =
Lines.initialize(Reader)) {
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())
487 std::vector<LineTableEntry> Entries;
491 auto ColIt = Group.Columns.begin();
492 auto ColsEnd = Group.Columns.end();
496 Session.getVAFromSectOffset(RelocSegment, RelocOffset);
497 LineInfo FirstLine(Group.LineNumbers.front().Flags);
499 (
Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0;
500 Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex,
false});
502 for (
const LineNumberEntry &LN : Group.LineNumbers) {
504 Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.
Offset);
508 if (
Lines.hasColumnInfo() && ColIt != ColsEnd) {
509 ColNum = ColIt->StartColumn;
512 Entries.push_back({VA,
Line, ColNum, Group.NameIndex,
false});
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});
521 EntryList.push_back(Entries);
526 llvm::sort(EntryList, [](
const std::vector<LineTableEntry> &
LHS,
527 const std::vector<LineTableEntry> &
RHS) {
528 return LHS[0].Addr <
RHS[0].Addr;
530 for (std::vector<LineTableEntry> &
I : EntryList)
533 return ModuleLineTable;
536std::unique_ptr<IPDBEnumLineNumbers>
539 if (!Session.moduleIndexForVA(VA, Modi))
542 std::vector<LineTableEntry>
Lines = findLineTable(Modi);
549 return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));
553 if (LineIter ==
Lines.end() || LineIter->Addr > VA) {
554 if (LineIter ==
Lines.begin() || std::prev(LineIter)->IsTerminalEntry)
560 Session.getModuleDebugStream(Modi);
566 ExpectedModS->findChecksumsSubsection();
567 if (!ExpectedChecksums) {
575 while (LineIter !=
Lines.end()) {
576 if (LineIter->IsTerminalEntry) {
583 if (LineIter->Addr > VA +
Length)
587 Session.addressForVA(LineIter->Addr, LineSect, LineOff);
588 uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr;
590 ExpectedChecksums->getArray().at(LineIter->FileNameIndex);
593 LineSect, LineOff, LineLength, SrcFileId, Modi);
597 return std::make_unique<NativeEnumLineNumbers>(std::move(
LineNumbers));
600std::unique_ptr<PDBSymbolCompiland>
605 if (Index >= Compilands.size())
608 if (Compilands[Index] == 0) {
617std::unique_ptr<IPDBSourceFile>
619 assert(FileId < SourceFiles.size());
625 return std::make_unique<NativeSourceFile>(*SourceFiles[FileId].
get());
630 auto [Iter, Inserted] =
636 auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums);
637 SourceFiles.push_back(std::move(SrcFile));
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)
LLVM_ABI SymIndexId getOrCreateInlineSymbol(codeview::InlineSiteSym Sym, uint64_t ParentAddr, uint16_t Modi, uint32_t RecordOffset) const
LLVM_ABI std::unique_ptr< IPDBEnumSymbols > createTypeEnumerator(codeview::TypeLeafKind Kind)
LLVM_ABI std::unique_ptr< PDBSymbol > getSymbolById(SymIndexId SymbolId) const
LLVM_ABI SymbolCache(NativeSession &Session, DbiStream *Dbi)
LLVM_ABI SymIndexId getOrCreateSourceFile(const codeview::FileChecksumEntry &Checksum) const
LLVM_ABI SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI) const
LLVM_ABI NativeRawSymbol & getNativeSymbolById(SymIndexId SymbolId) const
LLVM_ABI std::unique_ptr< PDBSymbolCompiland > getOrCreateCompiland(uint32_t Index)
LLVM_ABI uint32_t getNumCompilands() const
LLVM_ABI std::unique_ptr< IPDBSourceFile > getSourceFileById(SymIndexId FileId) const
LLVM_ABI std::unique_ptr< IPDBEnumLineNumbers > findLineNumbersByVA(uint64_t VA, uint32_t Length) const
SymIndexId createSymbol(Args &&...ConstructorArgs) const
LLVM_ABI std::unique_ptr< PDBSymbol > findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type)
LLVM_ABI SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset)
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.
codeview::SimpleTypeKind Kind
support::ulittle32_t Offset
support::ulittle32_t Flags