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},
79 : Session(Session), Dbi(Dbi) {
81 Cache.push_back(
nullptr);
82 SourceFiles.push_back(
nullptr);
88std::unique_ptr<IPDBEnumSymbols>
93std::unique_ptr<IPDBEnumSymbols>
100 auto &Types = Tpi->typeCollection();
101 return std::unique_ptr<IPDBEnumSymbols>(
105std::unique_ptr<IPDBEnumSymbols>
107 return std::unique_ptr<IPDBEnumSymbols>(
114 return createSymbol<NativeTypePointer>(
Index);
116 const auto Kind =
Index.getSimpleKind();
119 return Builtin.
Kind == Kind;
123 return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
130 if (
auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT,
Record)) {
135 if (
Record.ModifiedType.isSimple())
136 return createSimpleType(
Record.ModifiedType,
Record.Modifiers);
144 return createSymbol<NativeTypeEnum>(
147 return createSymbol<NativeTypeUDT>(
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()) {
168 TypeIndexToSymbolId[
Index] = Result;
186 else if (*EFD !=
Index) {
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();
241 TypeIndexToSymbolId[
Index] = Id;
246std::unique_ptr<PDBSymbol>
248 assert(SymbolId < Cache.size());
251 if (SymbolId == 0 || SymbolId >= Cache.size())
264 return *Cache[SymbolId];
275 auto Iter = GlobalOffsetToSymbolId.find(
Offset);
276 if (Iter != GlobalOffsetToSymbolId.end())
282 switch (CVS.
kind()) {
283 case SymbolKind::S_UDT: {
284 UDTSym US =
cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
285 Id = createSymbol<NativeTypeTypedef>(std::move(US));
289 Id = createSymbolPlaceholder();
294 GlobalOffsetToSymbolId[
Offset] = Id;
304 auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset});
305 if (Iter != SymTabOffsetToSymbolId.end())
308 SymIndexId Id = createSymbol<NativeInlineSiteSymbol>(
Sym, ParentAddr);
309 SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id});
313std::unique_ptr<PDBSymbol>
318 return findFunctionSymbolBySectOffset(Sect,
Offset);
320 return findPublicSymbolBySectOffset(Sect,
Offset);
330 if (
auto Sym = findFunctionSymbolBySectOffset(Sect,
Offset))
339std::unique_ptr<PDBSymbol>
341 auto Iter = AddressToSymbolId.find({Sect,
Offset});
342 if (Iter != AddressToSymbolId.end())
361 for (
auto I = Syms.
begin(), E = Syms.
end();
I != E; ++
I) {
362 if (
I->kind() != S_LPROC32 &&
I->kind() != S_GPROC32)
364 auto PS =
cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*
I));
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())
373 SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS,
I.offset());
374 AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset},
Id});
384std::unique_ptr<PDBSymbol>
386 auto Iter = AddressToPublicSymId.find({Sect,
Offset});
387 if (Iter != AddressToPublicSymId.end())
398 ExpectedSyms->getSymbolArray().getUnderlyingStream();
402 auto AddrMap =
Publics->getAddressMap();
403 auto First = AddrMap.begin();
404 auto It = AddrMap.begin();
405 size_t Count = AddrMap.size();
418 cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(
Sym.get()));
419 if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <=
Offset)) {
425 if (It == AddrMap.begin())
436 auto PS =
cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(
Sym.get()));
437 auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset});
438 if (Found != AddressToPublicSymId.end())
443 AddressToPublicSymId.insert({{PS.Segment, PS.Offset},
Id});
447std::vector<SymbolCache::LineTableEntry>
448SymbolCache::findLineTable(
uint16_t Modi)
const {
450 auto LineTableIter = LineTable.
find(Modi);
451 if (LineTableIter != LineTable.
end())
452 return LineTableIter->second;
454 std::vector<LineTableEntry> &ModuleLineTable = LineTable[Modi];
462 return ModuleLineTable;
465 std::vector<std::vector<LineTableEntry>> EntryList;
466 for (
const auto &SS : ExpectedModS->getSubsectionsArray()) {
467 if (
SS.kind() != DebugSubsectionKind::Lines)
472 if (
auto EC =
Lines.initialize(Reader)) {
480 if (Group.LineNumbers.empty())
483 std::vector<LineTableEntry> Entries;
487 auto ColIt = Group.Columns.begin();
488 auto ColsEnd = Group.Columns.end();
493 LineInfo FirstLine(Group.LineNumbers.front().Flags);
495 (
Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0;
496 Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex,
false});
504 if (
Lines.hasColumnInfo() && ColIt != ColsEnd) {
505 ColNum = ColIt->StartColumn;
508 Entries.push_back({VA,
Line, ColNum, Group.NameIndex,
false});
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});
517 EntryList.push_back(Entries);
522 llvm::sort(EntryList, [](
const std::vector<LineTableEntry> &LHS,
523 const std::vector<LineTableEntry> &RHS) {
524 return LHS[0].Addr <
RHS[0].Addr;
526 for (std::vector<LineTableEntry> &
I : EntryList)
529 return ModuleLineTable;
532std::unique_ptr<IPDBEnumLineNumbers>
538 std::vector<LineTableEntry>
Lines = findLineTable(Modi);
545 return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));
549 if (LineIter ==
Lines.end() || LineIter->Addr > VA) {
550 if (LineIter ==
Lines.begin() || std::prev(LineIter)->IsTerminalEntry)
562 ExpectedModS->findChecksumsSubsection();
563 if (!ExpectedChecksums) {
571 while (LineIter !=
Lines.end()) {
572 if (LineIter->IsTerminalEntry) {
579 if (LineIter->Addr > VA +
Length)
583 Session.
addressForVA(LineIter->Addr, LineSect, LineOff);
584 uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr;
586 ExpectedChecksums->getArray().at(LineIter->FileNameIndex);
589 LineSect, LineOff, LineLength, SrcFileId, Modi);
593 return std::make_unique<NativeEnumLineNumbers>(std::move(
LineNumbers));
596std::unique_ptr<PDBSymbolCompiland>
601 if (
Index >= Compilands.size())
604 if (Compilands[
Index] == 0) {
613std::unique_ptr<IPDBSourceFile>
615 assert(FileId < SourceFiles.size());
621 return std::make_unique<NativeSourceFile>(*SourceFiles[FileId].
get());
627 if (Iter != FileNameOffsetToId.end())
631 auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums);
632 SourceFiles.push_back(std::move(SrcFile));
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const struct BuiltinTypeEntry BuiltinTypes[]
Provides read only access to a subclass of BinaryStream.
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
iterator find(const_arg_type_t< KeyT > Val)
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
The instances of the Type class are immutable: once they are created, they are never changed.
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.
DbiModuleDescriptor getModuleDescriptor(uint32_t Modi) const
uint32_t getModuleCount() const
const DbiModuleList & modules() const
std::unique_ptr< T > getConcreteSymbolById(SymIndexId SymbolId) const
PDB_SymType getSymTag() const override
bool addressForVA(uint64_t VA, uint32_t &Section, uint32_t &Offset) const override
bool moduleIndexForSectOffset(uint32_t Sect, uint32_t Offset, uint16_t &ModuleIndex) const
uint64_t getVAFromSectOffset(uint32_t Section, uint32_t Offset) const
Expected< ModuleDebugStreamRef > getModuleDebugStream(uint32_t Index) const
bool moduleIndexForVA(uint64_t VA, uint16_t &ModuleIndex) const
Expected< PublicsStream & > getPDBPublicsStream()
Expected< TpiStream & > getPDBTpiStream()
Expected< SymbolStream & > getPDBSymbolStream()
static std::unique_ptr< PDBSymbol > create(const IPDBSession &PDBSession, std::unique_ptr< IPDBRawSymbol > RawSymbol)
std::unique_ptr< IPDBEnumSymbols > createGlobalsEnumerator(codeview::SymbolKind Kind)
SymIndexId getOrCreateInlineSymbol(codeview::InlineSiteSym Sym, uint64_t ParentAddr, uint16_t Modi, uint32_t RecordOffset) const
std::unique_ptr< IPDBEnumSymbols > createTypeEnumerator(codeview::TypeLeafKind Kind)
std::unique_ptr< PDBSymbol > getSymbolById(SymIndexId SymbolId) const
SymbolCache(NativeSession &Session, DbiStream *Dbi)
SymIndexId getOrCreateSourceFile(const codeview::FileChecksumEntry &Checksum) const
SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI) const
NativeRawSymbol & getNativeSymbolById(SymIndexId SymbolId) const
std::unique_ptr< PDBSymbolCompiland > getOrCreateCompiland(uint32_t Index)
uint32_t getNumCompilands() const
std::unique_ptr< IPDBSourceFile > getSourceFileById(SymIndexId FileId) const
std::unique_ptr< IPDBEnumLineNumbers > findLineNumbersByVA(uint64_t VA, uint32_t Length) const
std::unique_ptr< PDBSymbol > findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type)
SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset)
bool isUdtForwardRef(CVType CVT)
Given an arbitrary codeview type, determine if it is an LF_STRUCTURE, LF_CLASS, LF_INTERFACE,...
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.
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.
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