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_CLASS2:
210 case codeview::LF_STRUCTURE:
211 case codeview::LF_STRUCTURE2:
212 case codeview::LF_INTERFACE:
213 case codeview::LF_INTERFACE2:
214 Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
216 case codeview::LF_UNION:
217 case codeview::LF_UNION2:
218 Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
220 case codeview::LF_POINTER:
221 Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
224 case codeview::LF_MODIFIER:
225 Id = createSymbolForModifiedType(Index, std::move(CVT));
227 case codeview::LF_PROCEDURE:
228 Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
229 Index, std::move(CVT));
231 case codeview::LF_MFUNCTION:
232 Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
233 Index, std::move(CVT));
235 case codeview::LF_VTSHAPE:
236 Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
237 Index, std::move(CVT));
240 Id = createSymbolPlaceholder();
244 assert(TypeIndexToSymbolId.count(Index) == 0);
245 TypeIndexToSymbolId[Index] = Id;
250std::unique_ptr<PDBSymbol>
252 assert(SymbolId < Cache.size());
255 if (SymbolId == 0 || SymbolId >= Cache.size())
268 return *Cache[SymbolId];
275 return Dbi->modules().getModuleCount();
279 auto Iter = GlobalOffsetToSymbolId.find(
Offset);
280 if (Iter != GlobalOffsetToSymbolId.end())
286 switch (CVS.
kind()) {
287 case SymbolKind::S_UDT: {
293 Id = createSymbolPlaceholder();
298 GlobalOffsetToSymbolId[
Offset] = Id;
308 auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset});
309 if (Iter != SymTabOffsetToSymbolId.end())
313 SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id});
321 return findFunctionSymbolByVA(VA);
324 Session.addressForVA(VA, Sect,
Offset);
325 return findPublicSymbolBySectOffset(Sect,
Offset);
329 if (!Session.moduleIndexForVA(VA, Modi))
336 if (
auto Sym = findFunctionSymbolByVA(VA))
345std::unique_ptr<PDBSymbol> SymbolCache::findFunctionSymbolByVA(uint64_t VA) {
349 auto findIdInCache = [
this](uint64_t VA) ->
SymIndexId {
350 auto Iter = AddressToSymbolId.
find(VA);
351 if (Iter.valid() && !IMapTy::KeyTraits::startLess(VA, Iter.start()))
364 if (!FuncSymCachedModIndexes.
insert(Modi).second)
377 auto Iter = AddressToSymbolId.
find(Start);
378 while (Iter.valid() && IMapTy::KeyTraits::nonEmpty(Start, Stop)) {
379 if (IMapTy::KeyTraits::startLess(Start, Iter.start()))
380 Ranges.push_back({Start, std::min(Iter.start(), Stop)});
386 if (IMapTy::KeyTraits::nonEmpty(Start, Stop))
395 if (
I->kind() != S_LPROC32 &&
I->kind() != S_GPROC32)
399 uint64_t SymStart = Session.getVAFromSectOffset(PS.Segment, PS.CodeOffset);
400 uint64_t SymStop = SymStart + PS.CodeSize;
401 if (
LLVM_UNLIKELY(!IMapTy::KeyTraits::nonEmpty(SymStart, SymStop))) {
406 Session.checkSymbolRange(SymStart, SymStop);
410 if (!Session.moduleIndexForVA(SymStart, SymModi) || SymModi != Modi)
413 auto Ranges = getInsertRanges(SymStart, SymStop);
416 for (
auto [Start, Stop] : Ranges)
417 AddressToSymbolId.insert(Start, Stop, Id);
430std::unique_ptr<PDBSymbol>
431SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t
Offset) {
432 auto Iter = AddressToPublicSymId.find({Sect,
Offset});
433 if (Iter != AddressToPublicSymId.end())
436 auto Publics = Session.getPDBFile().getPDBPublicsStream();
442 auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream();
447 BinaryStreamRef SymStream =
448 ExpectedSyms->getSymbolArray().getUnderlyingStream();
452 auto AddrMap =
Publics->getAddressMap();
453 auto First = AddrMap.begin();
454 auto It = AddrMap.begin();
455 size_t Count = AddrMap.size();
469 if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <=
Offset)) {
475 if (It == AddrMap.begin())
487 auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset});
488 if (Found != AddressToPublicSymId.end())
493 AddressToPublicSymId.insert({{PS.Segment, PS.Offset},
Id});
497std::vector<SymbolCache::LineTableEntry>
498SymbolCache::findLineTable(uint16_t Modi)
const {
500 auto [LineTableIter,
Inserted] = LineTable.try_emplace(Modi);
502 return LineTableIter->second;
504 std::vector<LineTableEntry> &ModuleLineTable = LineTableIter->second;
508 Expected<ModuleDebugStreamRef> ExpectedModS =
509 Session.getModuleDebugStream(Modi);
512 return ModuleLineTable;
515 std::vector<std::vector<LineTableEntry>> EntryList;
516 for (
const auto &SS : ExpectedModS->getSubsectionsArray()) {
517 if (
SS.kind() != DebugSubsectionKind::Lines)
520 DebugLinesSubsectionRef
Lines;
521 BinaryStreamReader Reader(
SS.getRecordData());
522 if (
auto EC =
Lines.initialize(Reader)) {
527 uint32_t RelocSegment =
Lines.header()->RelocSegment;
528 uint32_t RelocOffset =
Lines.header()->RelocOffset;
529 for (
const LineColumnEntry &Group :
Lines) {
530 if (Group.LineNumbers.empty())
533 std::vector<LineTableEntry> Entries;
537 auto ColIt = Group.Columns.begin();
538 auto ColsEnd = Group.Columns.end();
542 Session.getVAFromSectOffset(RelocSegment, RelocOffset);
543 LineInfo FirstLine(Group.LineNumbers.front().Flags);
545 (
Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0;
546 Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex,
false});
548 for (
const LineNumberEntry &LN : Group.LineNumbers) {
550 Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.
Offset);
554 if (
Lines.hasColumnInfo() && ColIt != ColsEnd) {
555 ColNum = ColIt->StartColumn;
558 Entries.push_back({VA,
Line, ColNum, Group.NameIndex,
false});
563 LineInfo LastLine(Group.LineNumbers.back().Flags);
564 ColNum = (
Lines.hasColumnInfo()) ? Group.Columns.back().StartColumn : 0;
565 Entries.push_back({EndAddr, LastLine, ColNum, Group.NameIndex,
true});
567 EntryList.push_back(Entries);
572 llvm::sort(EntryList, [](
const std::vector<LineTableEntry> &
LHS,
573 const std::vector<LineTableEntry> &
RHS) {
574 return LHS[0].Addr <
RHS[0].Addr;
576 for (std::vector<LineTableEntry> &
I : EntryList)
579 return ModuleLineTable;
582std::unique_ptr<IPDBEnumLineNumbers>
585 if (!Session.moduleIndexForVA(VA, Modi))
588 std::vector<LineTableEntry>
Lines = findLineTable(Modi);
595 return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));
599 if (LineIter ==
Lines.end() || LineIter->Addr > VA) {
600 if (LineIter ==
Lines.begin() || std::prev(LineIter)->IsTerminalEntry)
606 Session.getModuleDebugStream(Modi);
612 ExpectedModS->findChecksumsSubsection();
613 if (!ExpectedChecksums) {
621 while (LineIter !=
Lines.end()) {
622 if (LineIter->IsTerminalEntry) {
629 if (LineIter->Addr > VA +
Length)
633 Session.addressForVA(LineIter->Addr, LineSect, LineOff);
634 uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr;
636 ExpectedChecksums->getArray().at(LineIter->FileNameIndex);
639 LineSect, LineOff, LineLength, SrcFileId, Modi);
643 return std::make_unique<NativeEnumLineNumbers>(std::move(
LineNumbers));
646std::unique_ptr<PDBSymbolCompiland>
651 if (Index >= Compilands.size())
654 if (Compilands[Index] == 0) {
663std::unique_ptr<IPDBSourceFile>
665 assert(FileId < SourceFiles.size());
671 return std::make_unique<NativeSourceFile>(*SourceFiles[FileId].
get());
676 auto [Iter, Inserted] =
682 auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums);
683 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)
@ 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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
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