45// Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary 46// to instantiate a NativeBuiltinSymbol for that type. 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 79 : Session(Session), Dbi(Dbi) {
80// Id 0 is reserved for the invalid symbol. 81 Cache.push_back(
nullptr);
82 SourceFiles.push_back(
nullptr);
88std::unique_ptr<IPDBEnumSymbols>
93std::unique_ptr<IPDBEnumSymbols>
100auto &Types = Tpi->typeCollection();
101return std::unique_ptr<IPDBEnumSymbols>(
105std::unique_ptr<IPDBEnumSymbols>
107return std::unique_ptr<IPDBEnumSymbols>(
114return createSymbol<NativeTypePointer>(Index);
116constauto Kind = Index.getSimpleKind();
119return Builtin.
Kind == Kind;
123return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
130if (
autoEC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT,
Record)) {
135if (
Record.ModifiedType.isSimple())
136return createSimpleType(
Record.ModifiedType,
Record.Modifiers);
138// Make sure we create and cache a record for the unmodified type. 144return createSymbol<NativeTypeEnum>(
147return createSymbol<NativeTypeUDT>(
150// No other types can be modified. (LF_POINTER, for example, records 151// its modifiers a different way. 152assert(
false &&
"Invalid LF_MODIFIER record");
159// First see if it's already in our cache. 160constauto Entry = TypeIndexToSymbolId.find(Index);
161if (Entry != TypeIndexToSymbolId.end())
164// Symbols for built-in types are created on the fly. 165if (Index.isSimple()) {
166SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
167assert(TypeIndexToSymbolId.count(Index) == 0);
168 TypeIndexToSymbolId[Index] = Result;
172// We need to instantiate and cache the desired type symbol. 186elseif (*EFD != Index) {
189// Record a mapping from ForwardRef -> SymIndex of complete type so that 190// we'll take the fast path next time. 191assert(TypeIndexToSymbolId.count(Index) == 0);
192 TypeIndexToSymbolId[Index] = Result;
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. 201case codeview::LF_ENUM:
202 Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
204case codeview::LF_ARRAY:
205 Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
208case codeview::LF_CLASS:
209case codeview::LF_STRUCTURE:
210case codeview::LF_INTERFACE:
211 Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
213case codeview::LF_UNION:
214 Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
216case codeview::LF_POINTER:
217 Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
220case codeview::LF_MODIFIER:
221 Id = createSymbolForModifiedType(Index, std::move(CVT));
223case codeview::LF_PROCEDURE:
224 Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
225 Index, std::move(CVT));
227case codeview::LF_MFUNCTION:
228 Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
229 Index, std::move(CVT));
231case codeview::LF_VTSHAPE:
232 Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
233 Index, std::move(CVT));
236 Id = createSymbolPlaceholder();
240assert(TypeIndexToSymbolId.count(Index) == 0);
241 TypeIndexToSymbolId[Index] = Id;
246std::unique_ptr<PDBSymbol>
248assert(SymbolId < Cache.size());
251if (SymbolId == 0 || SymbolId >= Cache.size())
254// Make sure to handle the case where we've inserted a placeholder symbol 255// for types we don't yet support. 264return *Cache[SymbolId];
275auto Iter = GlobalOffsetToSymbolId.find(
Offset);
276if (Iter != GlobalOffsetToSymbolId.end())
283case SymbolKind::S_UDT: {
284UDTSym US =
cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
285 Id = createSymbol<NativeTypeTypedef>(std::move(US));
289 Id = createSymbolPlaceholder();
294 GlobalOffsetToSymbolId[
Offset] = Id;
304auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset});
305if (Iter != SymTabOffsetToSymbolId.end())
308SymIndexId Id = createSymbol<NativeInlineSiteSymbol>(
Sym, ParentAddr);
309 SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id});
313std::unique_ptr<PDBSymbol>
318return findFunctionSymbolBySectOffset(Sect,
Offset);
320return findPublicSymbolBySectOffset(Sect,
Offset);
328// FIXME: Implement for PDB_SymType::Data. The symbolizer calls this but 329// only uses it to find the symbol length. 330if (
autoSym = findFunctionSymbolBySectOffset(Sect,
Offset))
339std::unique_ptr<PDBSymbol>
341auto Iter = AddressToSymbolId.find({Sect,
Offset});
342if (Iter != AddressToSymbolId.end())
360// Search for the symbol in this module. 361for (
autoI = Syms.
begin(), E = Syms.
end();
I != E; ++
I) {
362if (
I->kind() != S_LPROC32 &&
I->kind() != S_GPROC32)
364auto PS =
cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*
I));
365if (Sect == PS.Segment &&
Offset >= PS.CodeOffset &&
366Offset < PS.CodeOffset + PS.CodeSize) {
367// Check if the symbol is already cached. 368auto Found = AddressToSymbolId.find({PS.Segment, PS.CodeOffset});
369if (Found != AddressToSymbolId.end())
372// Otherwise, create a new symbol. 373SymIndexIdId = createSymbol<NativeFunctionSymbol>(PS,
I.offset());
374 AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset},
Id});
378// Jump to the end of this ProcSym. 384std::unique_ptr<PDBSymbol>
386auto Iter = AddressToPublicSymId.find({Sect,
Offset});
387if (Iter != AddressToPublicSymId.end())
402 ExpectedSyms->getSymbolArray().getUnderlyingStream();
404// Use binary search to find the first public symbol with an address greater 405// than or equal to Sect, Offset. 406auto AddrMap =
Publics->getAddressMap();
407autoFirst = AddrMap.begin();
408auto It = AddrMap.begin();
409size_t Count = AddrMap.size();
422cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(
Sym.get()));
423if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <=
Offset)) {
429if (It == AddrMap.begin())
439// Check if the symbol is already cached. 440auto PS =
cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(
Sym.get()));
441auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset});
442if (Found != AddressToPublicSymId.end())
445// Otherwise, create a new symbol. 447 AddressToPublicSymId.insert({{PS.Segment, PS.Offset},
Id});
451std::vector<SymbolCache::LineTableEntry>
452SymbolCache::findLineTable(
uint16_t Modi)
const{
453// Check if this module has already been added. 456return LineTableIter->second;
458 std::vector<LineTableEntry> &ModuleLineTable = LineTableIter->second;
460// If there is an error or there are no lines, just return the 466return ModuleLineTable;
469 std::vector<std::vector<LineTableEntry>> EntryList;
470for (
constauto &SS : ExpectedModS->getSubsectionsArray()) {
471if (
SS.kind() != DebugSubsectionKind::Lines)
476if (
autoEC =
Lines.initialize(Reader)) {
484if (Group.LineNumbers.empty())
487 std::vector<LineTableEntry> Entries;
489// If there are column numbers, then they should be in a parallel stream 490// to the line numbers. 491auto ColIt = Group.Columns.begin();
492auto ColsEnd = Group.Columns.end();
494// Add a line to mark the beginning of this section. 497LineInfo FirstLine(Group.LineNumbers.front().Flags);
499 (
Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0;
500 Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex,
false});
508if (
Lines.hasColumnInfo() && ColIt != ColsEnd) {
509 ColNum = ColIt->StartColumn;
512 Entries.push_back({VA,
Line, ColNum, Group.NameIndex,
false});
515// Add a terminal entry line to mark the end of this subsection. 517LineInfo 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);
525// Sort EntryList, and add flattened contents to the line table. 526llvm::sort(EntryList, [](
const std::vector<LineTableEntry> &LHS,
527const std::vector<LineTableEntry> &RHS) {
528returnLHS[0].Addr <
RHS[0].Addr;
530for (std::vector<LineTableEntry> &
I : EntryList)
533return ModuleLineTable;
536std::unique_ptr<IPDBEnumLineNumbers>
542 std::vector<LineTableEntry>
Lines = findLineTable(Modi);
546// Find the first line in the line table whose address is not greater than 547// the one we are searching for. 549return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));
552// Try to back up if we've gone too far. 553if (LineIter ==
Lines.end() || LineIter->Addr > VA) {
554if (LineIter ==
Lines.begin() || std::prev(LineIter)->IsTerminalEntry)
566 ExpectedModS->findChecksumsSubsection();
567if (!ExpectedChecksums) {
572// Populate a vector of NativeLineNumbers that have addresses in the given 575while (LineIter !=
Lines.end()) {
576if (LineIter->IsTerminalEntry) {
581// If the line is still within the address range, create a NativeLineNumber 582// and add to the list. 583if (LineIter->Addr > VA +
Length)
587 Session.
addressForVA(LineIter->Addr, LineSect, LineOff);
588uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr;
590 ExpectedChecksums->getArray().at(LineIter->FileNameIndex);
593 LineSect, LineOff, LineLength, SrcFileId, Modi);
597return std::make_unique<NativeEnumLineNumbers>(std::move(
LineNumbers));
600std::unique_ptr<PDBSymbolCompiland>
605if (Index >= Compilands.size())
608if (Compilands[Index] == 0) {
617std::unique_ptr<IPDBSourceFile>
619assert(FileId < SourceFiles.size());
625return std::make_unique<NativeSourceFile>(*SourceFiles[FileId].
get());
631if (Iter != FileNameOffsetToId.end())
635auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums);
636 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.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
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