79 : Session(Session), Dbi(Dbi), AddressToSymbolId(IMapAllocator) {
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;
135 if (
Record.ModifiedType.isSimple())
136 return createSimpleType(
Record.ModifiedType,
Record.Modifiers);
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});
317 return findFunctionSymbolByVA(VA);
320 Session.addressForVA(VA, Sect,
Offset);
321 return findPublicSymbolBySectOffset(Sect,
Offset);
325 if (!Session.moduleIndexForVA(VA, Modi))
332 if (
auto Sym = findFunctionSymbolByVA(VA))
341std::unique_ptr<PDBSymbol> SymbolCache::findFunctionSymbolByVA(
uint64_t VA) {
346 auto Iter = AddressToSymbolId.
find(VA);
347 if (Iter.valid() && !IMapTy::KeyTraits::startLess(VA, Iter.start()))
360 if (!FuncSymCachedModIndexes.
insert(Modi).second)
373 auto Iter = AddressToSymbolId.
find(Start);
374 while (Iter.valid() && IMapTy::KeyTraits::nonEmpty(Start, Stop)) {
375 if (IMapTy::KeyTraits::startLess(Start, Iter.start()))
376 Ranges.push_back({Start, std::min(Iter.start(), Stop)});
382 if (IMapTy::KeyTraits::nonEmpty(Start, Stop))
391 if (
I->kind() != S_LPROC32 &&
I->kind() != S_GPROC32)
395 uint64_t SymStart = Session.getVAFromSectOffset(PS.Segment, PS.CodeOffset);
396 uint64_t SymStop = SymStart + PS.CodeSize;
397 if (
LLVM_UNLIKELY(!IMapTy::KeyTraits::nonEmpty(SymStart, SymStop))) {
402 Session.checkSymbolRange(SymStart, SymStop);
406 if (!Session.moduleIndexForVA(SymStart, SymModi) || SymModi != Modi)
409 auto Ranges = getInsertRanges(SymStart, SymStop);
412 for (
auto [Start, Stop] : Ranges)
413 AddressToSymbolId.insert(Start, Stop, Id);
426std::unique_ptr<PDBSymbol>
427SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t
Offset) {
428 auto Iter = AddressToPublicSymId.find({Sect,
Offset});
429 if (Iter != AddressToPublicSymId.end())
432 auto Publics = Session.getPDBFile().getPDBPublicsStream();
438 auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream();
443 BinaryStreamRef SymStream =
444 ExpectedSyms->getSymbolArray().getUnderlyingStream();
448 auto AddrMap =
Publics->getAddressMap();
449 auto First = AddrMap.begin();
450 auto It = AddrMap.begin();
451 size_t Count = AddrMap.size();
465 if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <=
Offset)) {
471 if (It == AddrMap.begin())
483 auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset});
484 if (Found != AddressToPublicSymId.end())
489 AddressToPublicSymId.insert({{PS.Segment, PS.Offset},
Id});
493std::vector<SymbolCache::LineTableEntry>
494SymbolCache::findLineTable(uint16_t Modi)
const {
496 auto [LineTableIter,
Inserted] = LineTable.try_emplace(Modi);
498 return LineTableIter->second;
500 std::vector<LineTableEntry> &ModuleLineTable = LineTableIter->second;
504 Expected<ModuleDebugStreamRef> ExpectedModS =
505 Session.getModuleDebugStream(Modi);
508 return ModuleLineTable;
511 std::vector<std::vector<LineTableEntry>> EntryList;
512 for (
const auto &SS : ExpectedModS->getSubsectionsArray()) {
513 if (
SS.kind() != DebugSubsectionKind::Lines)
516 DebugLinesSubsectionRef
Lines;
517 BinaryStreamReader Reader(
SS.getRecordData());
518 if (
auto EC =
Lines.initialize(Reader)) {
523 uint32_t RelocSegment =
Lines.header()->RelocSegment;
524 uint32_t RelocOffset =
Lines.header()->RelocOffset;
525 for (
const LineColumnEntry &Group :
Lines) {
526 if (Group.LineNumbers.empty())
529 std::vector<LineTableEntry> Entries;
533 auto ColIt = Group.Columns.begin();
534 auto ColsEnd = Group.Columns.end();
538 Session.getVAFromSectOffset(RelocSegment, RelocOffset);
539 LineInfo FirstLine(Group.LineNumbers.front().Flags);
541 (
Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0;
542 Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex,
false});
544 for (
const LineNumberEntry &LN : Group.LineNumbers) {
546 Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.
Offset);
550 if (
Lines.hasColumnInfo() && ColIt != ColsEnd) {
551 ColNum = ColIt->StartColumn;
554 Entries.push_back({VA,
Line, ColNum, Group.NameIndex,
false});
558 uint64_t EndAddr = StartAddr +
Lines.header()->CodeSize;
559 LineInfo LastLine(Group.LineNumbers.back().Flags);
560 ColNum = (
Lines.hasColumnInfo()) ? Group.Columns.back().StartColumn : 0;
561 Entries.push_back({EndAddr, LastLine, ColNum, Group.NameIndex,
true});
563 EntryList.push_back(Entries);
568 llvm::sort(EntryList, [](
const std::vector<LineTableEntry> &
LHS,
569 const std::vector<LineTableEntry> &
RHS) {
570 return LHS[0].Addr <
RHS[0].Addr;
572 for (std::vector<LineTableEntry> &
I : EntryList)
575 return ModuleLineTable;
578std::unique_ptr<IPDBEnumLineNumbers>
581 if (!Session.moduleIndexForVA(VA, Modi))
584 std::vector<LineTableEntry>
Lines = findLineTable(Modi);
591 return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));
595 if (LineIter ==
Lines.end() || LineIter->Addr > VA) {
596 if (LineIter ==
Lines.begin() || std::prev(LineIter)->IsTerminalEntry)
602 Session.getModuleDebugStream(Modi);
608 ExpectedModS->findChecksumsSubsection();
609 if (!ExpectedChecksums) {
617 while (LineIter !=
Lines.end()) {
618 if (LineIter->IsTerminalEntry) {
625 if (LineIter->Addr > VA +
Length)
629 Session.addressForVA(LineIter->Addr, LineSect, LineOff);
630 uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr;
632 ExpectedChecksums->getArray().at(LineIter->FileNameIndex);
635 LineSect, LineOff, LineLength, SrcFileId, Modi);
639 return std::make_unique<NativeEnumLineNumbers>(std::move(
LineNumbers));
642std::unique_ptr<PDBSymbolCompiland>
647 if (Index >= Compilands.size())
650 if (Compilands[Index] == 0) {
659std::unique_ptr<IPDBSourceFile>
661 assert(FileId < SourceFiles.size());
667 return std::make_unique<NativeSourceFile>(*SourceFiles[FileId].
get());
672 auto [Iter, Inserted] =
678 auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums);
679 SourceFiles.push_back(std::move(SrcFile));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
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.
const_iterator find(KeyT x) const
find - Return an iterator pointing to the first interval ending at or after x, or end().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
static Error deserializeAs(CVSymbol Symbol, T &Record)
static Error deserializeAs(CVType &CVT, T &Record)
std::pair< iterator, bool > insert(const ValueT &V)
LLVM_ABI DbiModuleDescriptor getModuleDescriptor(uint32_t Modi) const
PDB_SymType getSymTag() const override
Expected< ModuleDebugStreamRef > getModuleDebugStream(uint32_t Index) const
bool moduleIndexForVA(uint64_t VA, uint16_t &ModuleIndex) 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 > findSymbolByVA(uint64_t VA, PDB_SymType Type)
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 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