18ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
28ab7dd60SZachary Turner
3eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
4641ae73fSAmy Huang #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
5eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
6eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
7a5e3e026SZachary Turner #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
8eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
94d68951eSZachary Turner #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
10eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/CodeView/TypeRecord.h"
11355ffb00SZachary Turner #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
12eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
13eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
148ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
15eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
168ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
17a5e3e026SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
18f8170d87SAmy Huang #include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h"
198ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
20641ae73fSAmy Huang #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
21bc980340SAmy Huang #include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h"
22eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h"
23641ae73fSAmy Huang #include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h"
248ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
258ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
26518cb2d5SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"
275d629966SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
285d629966SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
296345e84dSZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
30da4b63abSZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
31a5e3e026SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h"
32355ffb00SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
335c1873b2SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"
348ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
35641ae73fSAmy Huang #include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
36a5e3e026SZachary Turner #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
378ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
388ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbol.h"
398ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
408ab7dd60SZachary Turner
418ab7dd60SZachary Turner using namespace llvm;
424d68951eSZachary Turner using namespace llvm::codeview;
438ab7dd60SZachary Turner using namespace llvm::pdb;
448ab7dd60SZachary Turner
458ab7dd60SZachary Turner // Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
468ab7dd60SZachary Turner // to instantiate a NativeBuiltinSymbol for that type.
478ab7dd60SZachary Turner static const struct BuiltinTypeEntry {
488ab7dd60SZachary Turner codeview::SimpleTypeKind Kind;
498ab7dd60SZachary Turner PDB_BuiltinType Type;
508ab7dd60SZachary Turner uint32_t Size;
518ab7dd60SZachary Turner } BuiltinTypes[] = {
525907a780SZachary Turner {codeview::SimpleTypeKind::None, PDB_BuiltinType::None, 0},
536345e84dSZachary Turner {codeview::SimpleTypeKind::Void, PDB_BuiltinType::Void, 0},
545c1873b2SZachary Turner {codeview::SimpleTypeKind::HResult, PDB_BuiltinType::HResult, 4},
55bdf0381eSZachary Turner {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
56bdf0381eSZachary Turner {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
578ab7dd60SZachary Turner {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
588ab7dd60SZachary Turner {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
59bdf0381eSZachary Turner {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
608ab7dd60SZachary Turner {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
61bdf0381eSZachary Turner {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
628ab7dd60SZachary Turner {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
638ab7dd60SZachary Turner {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
645c1873b2SZachary Turner {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2},
655c1873b2SZachary Turner {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2},
665c1873b2SZachary Turner {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4},
67*5c9e20d7SZequan Wu {codeview::SimpleTypeKind::Character8, PDB_BuiltinType::Char8, 1},
688ab7dd60SZachary Turner {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
698ab7dd60SZachary Turner {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
705c1873b2SZachary Turner {codeview::SimpleTypeKind::Float32, PDB_BuiltinType::Float, 4},
715c1873b2SZachary Turner {codeview::SimpleTypeKind::Float64, PDB_BuiltinType::Float, 8},
725c1873b2SZachary Turner {codeview::SimpleTypeKind::Float80, PDB_BuiltinType::Float, 10},
735c1873b2SZachary Turner {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1},
748ab7dd60SZachary Turner // This table can be grown as necessary, but these are the only types we've
758ab7dd60SZachary Turner // needed so far.
768ab7dd60SZachary Turner };
778ab7dd60SZachary Turner
SymbolCache(NativeSession & Session,DbiStream * Dbi)788ab7dd60SZachary Turner SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
79bc980340SAmy Huang : Session(Session), Dbi(Dbi) {
808ab7dd60SZachary Turner // Id 0 is reserved for the invalid symbol.
818ab7dd60SZachary Turner Cache.push_back(nullptr);
82f8170d87SAmy Huang SourceFiles.push_back(nullptr);
838ab7dd60SZachary Turner
848ab7dd60SZachary Turner if (Dbi)
858ab7dd60SZachary Turner Compilands.resize(Dbi->modules().getModuleCount());
868ab7dd60SZachary Turner }
878ab7dd60SZachary Turner
888ab7dd60SZachary Turner std::unique_ptr<IPDBEnumSymbols>
createTypeEnumerator(TypeLeafKind Kind)89355ffb00SZachary Turner SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
90355ffb00SZachary Turner return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
91355ffb00SZachary Turner }
92355ffb00SZachary Turner
93355ffb00SZachary Turner std::unique_ptr<IPDBEnumSymbols>
createTypeEnumerator(std::vector<TypeLeafKind> Kinds)94355ffb00SZachary Turner SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
958ab7dd60SZachary Turner auto Tpi = Session.getPDBFile().getPDBTpiStream();
968ab7dd60SZachary Turner if (!Tpi) {
978ab7dd60SZachary Turner consumeError(Tpi.takeError());
988ab7dd60SZachary Turner return nullptr;
998ab7dd60SZachary Turner }
1008ab7dd60SZachary Turner auto &Types = Tpi->typeCollection();
1018ab7dd60SZachary Turner return std::unique_ptr<IPDBEnumSymbols>(
102355ffb00SZachary Turner new NativeEnumTypes(Session, Types, std::move(Kinds)));
1038ab7dd60SZachary Turner }
1048ab7dd60SZachary Turner
105a5e3e026SZachary Turner std::unique_ptr<IPDBEnumSymbols>
createGlobalsEnumerator(codeview::SymbolKind Kind)106a5e3e026SZachary Turner SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
107a5e3e026SZachary Turner return std::unique_ptr<IPDBEnumSymbols>(
108a5e3e026SZachary Turner new NativeEnumGlobals(Session, {Kind}));
109a5e3e026SZachary Turner }
110a5e3e026SZachary Turner
createSimpleType(TypeIndex Index,ModifierOptions Mods) const1114727ac23SZachary Turner SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
112bc980340SAmy Huang ModifierOptions Mods) const {
1136345e84dSZachary Turner if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
1146345e84dSZachary Turner return createSymbol<NativeTypePointer>(Index);
1154727ac23SZachary Turner
1164727ac23SZachary Turner const auto Kind = Index.getSimpleKind();
1179850d3b1SKazu Hirata const auto It =
1189850d3b1SKazu Hirata llvm::find_if(BuiltinTypes, [Kind](const BuiltinTypeEntry &Builtin) {
1199850d3b1SKazu Hirata return Builtin.Kind == Kind;
1209850d3b1SKazu Hirata });
1214727ac23SZachary Turner if (It == std::end(BuiltinTypes))
1224727ac23SZachary Turner return 0;
1236345e84dSZachary Turner return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
1244727ac23SZachary Turner }
1254727ac23SZachary Turner
1264727ac23SZachary Turner SymIndexId
createSymbolForModifiedType(codeview::TypeIndex ModifierTI,codeview::CVType CVT) const1274727ac23SZachary Turner SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
128bc980340SAmy Huang codeview::CVType CVT) const {
1294727ac23SZachary Turner ModifierRecord Record;
1304727ac23SZachary Turner if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
1314727ac23SZachary Turner consumeError(std::move(EC));
1324727ac23SZachary Turner return 0;
1334727ac23SZachary Turner }
1344727ac23SZachary Turner
1354727ac23SZachary Turner if (Record.ModifiedType.isSimple())
1364727ac23SZachary Turner return createSimpleType(Record.ModifiedType, Record.Modifiers);
1374727ac23SZachary Turner
138355ffb00SZachary Turner // Make sure we create and cache a record for the unmodified type.
139355ffb00SZachary Turner SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
140355ffb00SZachary Turner NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
1414727ac23SZachary Turner
142355ffb00SZachary Turner switch (UnmodifiedNRS.getSymTag()) {
143355ffb00SZachary Turner case PDB_SymType::Enum:
144355ffb00SZachary Turner return createSymbol<NativeTypeEnum>(
145355ffb00SZachary Turner static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));
146355ffb00SZachary Turner case PDB_SymType::UDT:
147355ffb00SZachary Turner return createSymbol<NativeTypeUDT>(
148355ffb00SZachary Turner static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));
1494727ac23SZachary Turner default:
1504727ac23SZachary Turner // No other types can be modified. (LF_POINTER, for example, records
1514727ac23SZachary Turner // its modifiers a different way.
1524727ac23SZachary Turner assert(false && "Invalid LF_MODIFIER record");
1534727ac23SZachary Turner break;
1544727ac23SZachary Turner }
155355ffb00SZachary Turner return 0;
1564727ac23SZachary Turner }
1574727ac23SZachary Turner
findSymbolByTypeIndex(codeview::TypeIndex Index) const158bc980340SAmy Huang SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) const {
1598ab7dd60SZachary Turner // First see if it's already in our cache.
1608ab7dd60SZachary Turner const auto Entry = TypeIndexToSymbolId.find(Index);
1618ab7dd60SZachary Turner if (Entry != TypeIndexToSymbolId.end())
1628ab7dd60SZachary Turner return Entry->second;
1638ab7dd60SZachary Turner
1648ab7dd60SZachary Turner // Symbols for built-in types are created on the fly.
1656345e84dSZachary Turner if (Index.isSimple()) {
1666345e84dSZachary Turner SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
1676345e84dSZachary Turner assert(TypeIndexToSymbolId.count(Index) == 0);
1686345e84dSZachary Turner TypeIndexToSymbolId[Index] = Result;
1696345e84dSZachary Turner return Result;
1706345e84dSZachary Turner }
1718ab7dd60SZachary Turner
1728ab7dd60SZachary Turner // We need to instantiate and cache the desired type symbol.
1738ab7dd60SZachary Turner auto Tpi = Session.getPDBFile().getPDBTpiStream();
1748ab7dd60SZachary Turner if (!Tpi) {
1758ab7dd60SZachary Turner consumeError(Tpi.takeError());
1768ab7dd60SZachary Turner return 0;
1778ab7dd60SZachary Turner }
1788ab7dd60SZachary Turner codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
1794d68951eSZachary Turner codeview::CVType CVT = Types.getType(Index);
1804727ac23SZachary Turner
181355ffb00SZachary Turner if (isUdtForwardRef(CVT)) {
182355ffb00SZachary Turner Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);
183355ffb00SZachary Turner
184355ffb00SZachary Turner if (!EFD)
185355ffb00SZachary Turner consumeError(EFD.takeError());
186355ffb00SZachary Turner else if (*EFD != Index) {
187355ffb00SZachary Turner assert(!isUdtForwardRef(Types.getType(*EFD)));
188355ffb00SZachary Turner SymIndexId Result = findSymbolByTypeIndex(*EFD);
189355ffb00SZachary Turner // Record a mapping from ForwardRef -> SymIndex of complete type so that
190355ffb00SZachary Turner // we'll take the fast path next time.
1916345e84dSZachary Turner assert(TypeIndexToSymbolId.count(Index) == 0);
192355ffb00SZachary Turner TypeIndexToSymbolId[Index] = Result;
193355ffb00SZachary Turner return Result;
194355ffb00SZachary Turner }
195355ffb00SZachary Turner }
196355ffb00SZachary Turner
197355ffb00SZachary Turner // At this point if we still have a forward ref udt it means the full decl was
198355ffb00SZachary Turner // not in the PDB. We just have to deal with it and use the forward ref.
199355ffb00SZachary Turner SymIndexId Id = 0;
2008ab7dd60SZachary Turner switch (CVT.kind()) {
2018ab7dd60SZachary Turner case codeview::LF_ENUM:
2024d68951eSZachary Turner Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
2038ab7dd60SZachary Turner break;
204518cb2d5SZachary Turner case codeview::LF_ARRAY:
205518cb2d5SZachary Turner Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
206518cb2d5SZachary Turner std::move(CVT));
207518cb2d5SZachary Turner break;
208355ffb00SZachary Turner case codeview::LF_CLASS:
209355ffb00SZachary Turner case codeview::LF_STRUCTURE:
210355ffb00SZachary Turner case codeview::LF_INTERFACE:
211355ffb00SZachary Turner Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
212355ffb00SZachary Turner break;
213355ffb00SZachary Turner case codeview::LF_UNION:
214355ffb00SZachary Turner Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
215355ffb00SZachary Turner break;
216da4b63abSZachary Turner case codeview::LF_POINTER:
2174d68951eSZachary Turner Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
2184d68951eSZachary Turner std::move(CVT));
219da4b63abSZachary Turner break;
2204727ac23SZachary Turner case codeview::LF_MODIFIER:
2214727ac23SZachary Turner Id = createSymbolForModifiedType(Index, std::move(CVT));
2224727ac23SZachary Turner break;
2236345e84dSZachary Turner case codeview::LF_PROCEDURE:
2246345e84dSZachary Turner Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
2256345e84dSZachary Turner Index, std::move(CVT));
2266345e84dSZachary Turner break;
2276345e84dSZachary Turner case codeview::LF_MFUNCTION:
2286345e84dSZachary Turner Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
2296345e84dSZachary Turner Index, std::move(CVT));
2306345e84dSZachary Turner break;
2315c1873b2SZachary Turner case codeview::LF_VTSHAPE:
2325c1873b2SZachary Turner Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
2335c1873b2SZachary Turner Index, std::move(CVT));
2345c1873b2SZachary Turner break;
2358ab7dd60SZachary Turner default:
236da4b63abSZachary Turner Id = createSymbolPlaceholder();
237da4b63abSZachary Turner break;
2388ab7dd60SZachary Turner }
2396345e84dSZachary Turner if (Id != 0) {
2406345e84dSZachary Turner assert(TypeIndexToSymbolId.count(Index) == 0);
2418ab7dd60SZachary Turner TypeIndexToSymbolId[Index] = Id;
2426345e84dSZachary Turner }
2438ab7dd60SZachary Turner return Id;
2448ab7dd60SZachary Turner }
2458ab7dd60SZachary Turner
2468ab7dd60SZachary Turner std::unique_ptr<PDBSymbol>
getSymbolById(SymIndexId SymbolId) const2478ab7dd60SZachary Turner SymbolCache::getSymbolById(SymIndexId SymbolId) const {
248bdf0381eSZachary Turner assert(SymbolId < Cache.size());
249bdf0381eSZachary Turner
250da4b63abSZachary Turner // Id 0 is reserved.
251c41ce835SZachary Turner if (SymbolId == 0 || SymbolId >= Cache.size())
252da4b63abSZachary Turner return nullptr;
253da4b63abSZachary Turner
254c41ce835SZachary Turner // Make sure to handle the case where we've inserted a placeholder symbol
255cf16437eSNico Weber // for types we don't yet support.
256c41ce835SZachary Turner NativeRawSymbol *NRS = Cache[SymbolId].get();
257c41ce835SZachary Turner if (!NRS)
258c41ce835SZachary Turner return nullptr;
259c41ce835SZachary Turner
260c41ce835SZachary Turner return PDBSymbol::create(Session, *NRS);
2618ab7dd60SZachary Turner }
2628ab7dd60SZachary Turner
getNativeSymbolById(SymIndexId SymbolId) const2638ab7dd60SZachary Turner NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
2648ab7dd60SZachary Turner return *Cache[SymbolId];
2658ab7dd60SZachary Turner }
2668ab7dd60SZachary Turner
getNumCompilands() const2678ab7dd60SZachary Turner uint32_t SymbolCache::getNumCompilands() const {
2688ab7dd60SZachary Turner if (!Dbi)
2698ab7dd60SZachary Turner return 0;
2708ab7dd60SZachary Turner
2718ab7dd60SZachary Turner return Dbi->modules().getModuleCount();
2728ab7dd60SZachary Turner }
2738ab7dd60SZachary Turner
getOrCreateGlobalSymbolByOffset(uint32_t Offset)274a5e3e026SZachary Turner SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
275a5e3e026SZachary Turner auto Iter = GlobalOffsetToSymbolId.find(Offset);
276a5e3e026SZachary Turner if (Iter != GlobalOffsetToSymbolId.end())
277a5e3e026SZachary Turner return Iter->second;
278a5e3e026SZachary Turner
279a5e3e026SZachary Turner SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
280a5e3e026SZachary Turner CVSymbol CVS = SS.readRecord(Offset);
281a5e3e026SZachary Turner SymIndexId Id = 0;
282a5e3e026SZachary Turner switch (CVS.kind()) {
283a5e3e026SZachary Turner case SymbolKind::S_UDT: {
284a5e3e026SZachary Turner UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
285a5e3e026SZachary Turner Id = createSymbol<NativeTypeTypedef>(std::move(US));
286a5e3e026SZachary Turner break;
287a5e3e026SZachary Turner }
288a5e3e026SZachary Turner default:
289a5e3e026SZachary Turner Id = createSymbolPlaceholder();
290a5e3e026SZachary Turner break;
291a5e3e026SZachary Turner }
292a5e3e026SZachary Turner if (Id != 0) {
293a5e3e026SZachary Turner assert(GlobalOffsetToSymbolId.count(Offset) == 0);
294a5e3e026SZachary Turner GlobalOffsetToSymbolId[Offset] = Id;
295a5e3e026SZachary Turner }
296a5e3e026SZachary Turner
297a5e3e026SZachary Turner return Id;
298a5e3e026SZachary Turner }
299a5e3e026SZachary Turner
getOrCreateInlineSymbol(InlineSiteSym Sym,uint64_t ParentAddr,uint16_t Modi,uint32_t RecordOffset) const300bc980340SAmy Huang SymIndexId SymbolCache::getOrCreateInlineSymbol(InlineSiteSym Sym,
301bc980340SAmy Huang uint64_t ParentAddr,
302bc980340SAmy Huang uint16_t Modi,
303bc980340SAmy Huang uint32_t RecordOffset) const {
304bc980340SAmy Huang auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset});
305bc980340SAmy Huang if (Iter != SymTabOffsetToSymbolId.end())
306bc980340SAmy Huang return Iter->second;
307f8170d87SAmy Huang
308bc980340SAmy Huang SymIndexId Id = createSymbol<NativeInlineSiteSymbol>(Sym, ParentAddr);
309bc980340SAmy Huang SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id});
310bc980340SAmy Huang return Id;
311f8170d87SAmy Huang }
312f8170d87SAmy Huang
313641ae73fSAmy Huang std::unique_ptr<PDBSymbol>
findSymbolBySectOffset(uint32_t Sect,uint32_t Offset,PDB_SymType Type)314641ae73fSAmy Huang SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
315641ae73fSAmy Huang PDB_SymType Type) {
316641ae73fSAmy Huang switch (Type) {
317641ae73fSAmy Huang case PDB_SymType::Function:
318641ae73fSAmy Huang return findFunctionSymbolBySectOffset(Sect, Offset);
319641ae73fSAmy Huang case PDB_SymType::PublicSymbol:
320641ae73fSAmy Huang return findPublicSymbolBySectOffset(Sect, Offset);
3210881d0beSAmy Huang case PDB_SymType::Compiland: {
322bc980340SAmy Huang uint16_t Modi;
323bc980340SAmy Huang if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
3240881d0beSAmy Huang return nullptr;
325bc980340SAmy Huang return getOrCreateCompiland(Modi);
3260881d0beSAmy Huang }
327641ae73fSAmy Huang case PDB_SymType::None: {
3280881d0beSAmy Huang // FIXME: Implement for PDB_SymType::Data. The symbolizer calls this but
3290881d0beSAmy Huang // only uses it to find the symbol length.
330641ae73fSAmy Huang if (auto Sym = findFunctionSymbolBySectOffset(Sect, Offset))
331641ae73fSAmy Huang return Sym;
332641ae73fSAmy Huang return nullptr;
333641ae73fSAmy Huang }
334641ae73fSAmy Huang default:
335641ae73fSAmy Huang return nullptr;
336641ae73fSAmy Huang }
337641ae73fSAmy Huang }
338641ae73fSAmy Huang
339641ae73fSAmy Huang std::unique_ptr<PDBSymbol>
findFunctionSymbolBySectOffset(uint32_t Sect,uint32_t Offset)340641ae73fSAmy Huang SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
3410881d0beSAmy Huang auto Iter = AddressToSymbolId.find({Sect, Offset});
3420881d0beSAmy Huang if (Iter != AddressToSymbolId.end())
343641ae73fSAmy Huang return getSymbolById(Iter->second);
344641ae73fSAmy Huang
345641ae73fSAmy Huang if (!Dbi)
346641ae73fSAmy Huang return nullptr;
347641ae73fSAmy Huang
348bc980340SAmy Huang uint16_t Modi;
349bc980340SAmy Huang if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
350641ae73fSAmy Huang return nullptr;
351641ae73fSAmy Huang
352bc980340SAmy Huang Expected<ModuleDebugStreamRef> ExpectedModS =
353bc980340SAmy Huang Session.getModuleDebugStream(Modi);
354f8170d87SAmy Huang if (!ExpectedModS) {
355f8170d87SAmy Huang consumeError(ExpectedModS.takeError());
356641ae73fSAmy Huang return nullptr;
357641ae73fSAmy Huang }
358f8170d87SAmy Huang CVSymbolArray Syms = ExpectedModS->getSymbolArray();
359641ae73fSAmy Huang
360641ae73fSAmy Huang // Search for the symbol in this module.
361641ae73fSAmy Huang for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) {
362641ae73fSAmy Huang if (I->kind() != S_LPROC32 && I->kind() != S_GPROC32)
363641ae73fSAmy Huang continue;
364641ae73fSAmy Huang auto PS = cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*I));
365641ae73fSAmy Huang if (Sect == PS.Segment && Offset >= PS.CodeOffset &&
366641ae73fSAmy Huang Offset < PS.CodeOffset + PS.CodeSize) {
3670881d0beSAmy Huang // Check if the symbol is already cached.
3680881d0beSAmy Huang auto Found = AddressToSymbolId.find({PS.Segment, PS.CodeOffset});
3690881d0beSAmy Huang if (Found != AddressToSymbolId.end())
3700881d0beSAmy Huang return getSymbolById(Found->second);
3710881d0beSAmy Huang
3720881d0beSAmy Huang // Otherwise, create a new symbol.
373bc980340SAmy Huang SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS, I.offset());
3740881d0beSAmy Huang AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset}, Id});
375641ae73fSAmy Huang return getSymbolById(Id);
376641ae73fSAmy Huang }
377641ae73fSAmy Huang
378641ae73fSAmy Huang // Jump to the end of this ProcSym.
379641ae73fSAmy Huang I = Syms.at(PS.End);
380641ae73fSAmy Huang }
381641ae73fSAmy Huang return nullptr;
382641ae73fSAmy Huang }
383641ae73fSAmy Huang
384641ae73fSAmy Huang std::unique_ptr<PDBSymbol>
findPublicSymbolBySectOffset(uint32_t Sect,uint32_t Offset)385641ae73fSAmy Huang SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
386641ae73fSAmy Huang auto Iter = AddressToPublicSymId.find({Sect, Offset});
387641ae73fSAmy Huang if (Iter != AddressToPublicSymId.end())
388641ae73fSAmy Huang return getSymbolById(Iter->second);
389641ae73fSAmy Huang
390641ae73fSAmy Huang auto Publics = Session.getPDBFile().getPDBPublicsStream();
391641ae73fSAmy Huang if (!Publics)
392641ae73fSAmy Huang return nullptr;
393641ae73fSAmy Huang
394641ae73fSAmy Huang auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream();
395641ae73fSAmy Huang if (!ExpectedSyms)
396641ae73fSAmy Huang return nullptr;
397641ae73fSAmy Huang BinaryStreamRef SymStream =
398641ae73fSAmy Huang ExpectedSyms->getSymbolArray().getUnderlyingStream();
399641ae73fSAmy Huang
400641ae73fSAmy Huang // Use binary search to find the first public symbol with an address greater
401641ae73fSAmy Huang // than or equal to Sect, Offset.
402641ae73fSAmy Huang auto AddrMap = Publics->getAddressMap();
403641ae73fSAmy Huang auto First = AddrMap.begin();
404641ae73fSAmy Huang auto It = AddrMap.begin();
405641ae73fSAmy Huang size_t Count = AddrMap.size();
406641ae73fSAmy Huang size_t Half;
407641ae73fSAmy Huang while (Count > 0) {
408641ae73fSAmy Huang It = First;
409641ae73fSAmy Huang Half = Count / 2;
410641ae73fSAmy Huang It += Half;
411641ae73fSAmy Huang Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
412641ae73fSAmy Huang if (!Sym) {
413641ae73fSAmy Huang consumeError(Sym.takeError());
414641ae73fSAmy Huang return nullptr;
415641ae73fSAmy Huang }
416641ae73fSAmy Huang
417641ae73fSAmy Huang auto PS =
418641ae73fSAmy Huang cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
419641ae73fSAmy Huang if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <= Offset)) {
420641ae73fSAmy Huang First = ++It;
421641ae73fSAmy Huang Count -= Half + 1;
422641ae73fSAmy Huang } else
423641ae73fSAmy Huang Count = Half;
424641ae73fSAmy Huang }
425f8170d87SAmy Huang if (It == AddrMap.begin())
426f8170d87SAmy Huang return nullptr;
427641ae73fSAmy Huang --It;
428641ae73fSAmy Huang
429641ae73fSAmy Huang Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
430641ae73fSAmy Huang if (!Sym) {
431641ae73fSAmy Huang consumeError(Sym.takeError());
432641ae73fSAmy Huang return nullptr;
433641ae73fSAmy Huang }
4340881d0beSAmy Huang
4350881d0beSAmy Huang // Check if the symbol is already cached.
436641ae73fSAmy Huang auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
4370881d0beSAmy Huang auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset});
4380881d0beSAmy Huang if (Found != AddressToPublicSymId.end())
4390881d0beSAmy Huang return getSymbolById(Found->second);
4400881d0beSAmy Huang
4410881d0beSAmy Huang // Otherwise, create a new symbol.
442641ae73fSAmy Huang SymIndexId Id = createSymbol<NativePublicSymbol>(PS);
4430881d0beSAmy Huang AddressToPublicSymId.insert({{PS.Segment, PS.Offset}, Id});
444641ae73fSAmy Huang return getSymbolById(Id);
445641ae73fSAmy Huang }
446641ae73fSAmy Huang
447f8170d87SAmy Huang std::vector<SymbolCache::LineTableEntry>
findLineTable(uint16_t Modi) const448f8170d87SAmy Huang SymbolCache::findLineTable(uint16_t Modi) const {
449f8170d87SAmy Huang // Check if this module has already been added.
450f8170d87SAmy Huang auto LineTableIter = LineTable.find(Modi);
451f8170d87SAmy Huang if (LineTableIter != LineTable.end())
452f8170d87SAmy Huang return LineTableIter->second;
453f8170d87SAmy Huang
454f8170d87SAmy Huang std::vector<LineTableEntry> &ModuleLineTable = LineTable[Modi];
455f8170d87SAmy Huang
456f8170d87SAmy Huang // If there is an error or there are no lines, just return the
457f8170d87SAmy Huang // empty vector.
458bc980340SAmy Huang Expected<ModuleDebugStreamRef> ExpectedModS =
459bc980340SAmy Huang Session.getModuleDebugStream(Modi);
460f8170d87SAmy Huang if (!ExpectedModS) {
461f8170d87SAmy Huang consumeError(ExpectedModS.takeError());
462f8170d87SAmy Huang return ModuleLineTable;
463f8170d87SAmy Huang }
464f8170d87SAmy Huang
465f8170d87SAmy Huang std::vector<std::vector<LineTableEntry>> EntryList;
466f8170d87SAmy Huang for (const auto &SS : ExpectedModS->getSubsectionsArray()) {
467f8170d87SAmy Huang if (SS.kind() != DebugSubsectionKind::Lines)
468f8170d87SAmy Huang continue;
469f8170d87SAmy Huang
470f8170d87SAmy Huang DebugLinesSubsectionRef Lines;
471f8170d87SAmy Huang BinaryStreamReader Reader(SS.getRecordData());
472f8170d87SAmy Huang if (auto EC = Lines.initialize(Reader)) {
473f8170d87SAmy Huang consumeError(std::move(EC));
474f8170d87SAmy Huang continue;
475f8170d87SAmy Huang }
476f8170d87SAmy Huang
477f8170d87SAmy Huang uint32_t RelocSegment = Lines.header()->RelocSegment;
478f8170d87SAmy Huang uint32_t RelocOffset = Lines.header()->RelocOffset;
479f8170d87SAmy Huang for (const LineColumnEntry &Group : Lines) {
480f8170d87SAmy Huang if (Group.LineNumbers.empty())
481f8170d87SAmy Huang continue;
482f8170d87SAmy Huang
483f8170d87SAmy Huang std::vector<LineTableEntry> Entries;
4849ee90a49SAmy Huang
4859ee90a49SAmy Huang // If there are column numbers, then they should be in a parallel stream
4869ee90a49SAmy Huang // to the line numbers.
4879ee90a49SAmy Huang auto ColIt = Group.Columns.begin();
4889ee90a49SAmy Huang auto ColsEnd = Group.Columns.end();
4899ee90a49SAmy Huang
4907e13694aSAmy Huang // Add a line to mark the beginning of this section.
4917e13694aSAmy Huang uint64_t StartAddr =
4927e13694aSAmy Huang Session.getVAFromSectOffset(RelocSegment, RelocOffset);
4937e13694aSAmy Huang LineInfo FirstLine(Group.LineNumbers.front().Flags);
4947e13694aSAmy Huang uint32_t ColNum =
4957e13694aSAmy Huang (Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0;
4967e13694aSAmy Huang Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex, false});
4977e13694aSAmy Huang
498f8170d87SAmy Huang for (const LineNumberEntry &LN : Group.LineNumbers) {
499f8170d87SAmy Huang uint64_t VA =
500f8170d87SAmy Huang Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.Offset);
5019ee90a49SAmy Huang LineInfo Line(LN.Flags);
5027e13694aSAmy Huang ColNum = 0;
5039ee90a49SAmy Huang
5049ee90a49SAmy Huang if (Lines.hasColumnInfo() && ColIt != ColsEnd) {
5059ee90a49SAmy Huang ColNum = ColIt->StartColumn;
5069ee90a49SAmy Huang ++ColIt;
5079ee90a49SAmy Huang }
5089ee90a49SAmy Huang Entries.push_back({VA, Line, ColNum, Group.NameIndex, false});
509f8170d87SAmy Huang }
510f8170d87SAmy Huang
511f8170d87SAmy Huang // Add a terminal entry line to mark the end of this subsection.
5127e13694aSAmy Huang uint64_t EndAddr = StartAddr + Lines.header()->CodeSize;
5139ee90a49SAmy Huang LineInfo LastLine(Group.LineNumbers.back().Flags);
5147e13694aSAmy Huang ColNum = (Lines.hasColumnInfo()) ? Group.Columns.back().StartColumn : 0;
5157e13694aSAmy Huang Entries.push_back({EndAddr, LastLine, ColNum, Group.NameIndex, true});
5169ee90a49SAmy Huang
517f8170d87SAmy Huang EntryList.push_back(Entries);
518f8170d87SAmy Huang }
519f8170d87SAmy Huang }
520f8170d87SAmy Huang
521f8170d87SAmy Huang // Sort EntryList, and add flattened contents to the line table.
522352fcfc6SKazu Hirata llvm::sort(EntryList, [](const std::vector<LineTableEntry> &LHS,
523f8170d87SAmy Huang const std::vector<LineTableEntry> &RHS) {
524f8170d87SAmy Huang return LHS[0].Addr < RHS[0].Addr;
525f8170d87SAmy Huang });
526c23ebf17SKazu Hirata for (std::vector<LineTableEntry> &I : EntryList)
527c23ebf17SKazu Hirata llvm::append_range(ModuleLineTable, I);
528f8170d87SAmy Huang
529f8170d87SAmy Huang return ModuleLineTable;
530f8170d87SAmy Huang }
531f8170d87SAmy Huang
532f8170d87SAmy Huang std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbersByVA(uint64_t VA,uint32_t Length) const533f8170d87SAmy Huang SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
534bc980340SAmy Huang uint16_t Modi;
535bc980340SAmy Huang if (!Session.moduleIndexForVA(VA, Modi))
536f8170d87SAmy Huang return nullptr;
537f8170d87SAmy Huang
538f8170d87SAmy Huang std::vector<LineTableEntry> Lines = findLineTable(Modi);
539f8170d87SAmy Huang if (Lines.empty())
540f8170d87SAmy Huang return nullptr;
541f8170d87SAmy Huang
542f8170d87SAmy Huang // Find the first line in the line table whose address is not greater than
543f8170d87SAmy Huang // the one we are searching for.
544f8170d87SAmy Huang auto LineIter = llvm::partition_point(Lines, [&](const LineTableEntry &E) {
545f8170d87SAmy Huang return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));
546f8170d87SAmy Huang });
547f8170d87SAmy Huang
548f8170d87SAmy Huang // Try to back up if we've gone too far.
549f8170d87SAmy Huang if (LineIter == Lines.end() || LineIter->Addr > VA) {
550f8170d87SAmy Huang if (LineIter == Lines.begin() || std::prev(LineIter)->IsTerminalEntry)
551f8170d87SAmy Huang return nullptr;
552f8170d87SAmy Huang --LineIter;
553f8170d87SAmy Huang }
554f8170d87SAmy Huang
555bc980340SAmy Huang Expected<ModuleDebugStreamRef> ExpectedModS =
556bc980340SAmy Huang Session.getModuleDebugStream(Modi);
557f8170d87SAmy Huang if (!ExpectedModS) {
558f8170d87SAmy Huang consumeError(ExpectedModS.takeError());
559f8170d87SAmy Huang return nullptr;
560f8170d87SAmy Huang }
561f8170d87SAmy Huang Expected<DebugChecksumsSubsectionRef> ExpectedChecksums =
562f8170d87SAmy Huang ExpectedModS->findChecksumsSubsection();
563f8170d87SAmy Huang if (!ExpectedChecksums) {
564f8170d87SAmy Huang consumeError(ExpectedChecksums.takeError());
565f8170d87SAmy Huang return nullptr;
566f8170d87SAmy Huang }
567f8170d87SAmy Huang
568f8170d87SAmy Huang // Populate a vector of NativeLineNumbers that have addresses in the given
569f8170d87SAmy Huang // address range.
570f8170d87SAmy Huang std::vector<NativeLineNumber> LineNumbers;
571bc980340SAmy Huang while (LineIter != Lines.end()) {
572f8170d87SAmy Huang if (LineIter->IsTerminalEntry) {
573f8170d87SAmy Huang ++LineIter;
574f8170d87SAmy Huang continue;
575f8170d87SAmy Huang }
576f8170d87SAmy Huang
577f8170d87SAmy Huang // If the line is still within the address range, create a NativeLineNumber
578f8170d87SAmy Huang // and add to the list.
579f8170d87SAmy Huang if (LineIter->Addr > VA + Length)
580f8170d87SAmy Huang break;
581f8170d87SAmy Huang
582f8170d87SAmy Huang uint32_t LineSect, LineOff;
583f8170d87SAmy Huang Session.addressForVA(LineIter->Addr, LineSect, LineOff);
584f8170d87SAmy Huang uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr;
585f8170d87SAmy Huang auto ChecksumIter =
586f8170d87SAmy Huang ExpectedChecksums->getArray().at(LineIter->FileNameIndex);
587f8170d87SAmy Huang uint32_t SrcFileId = getOrCreateSourceFile(*ChecksumIter);
5889ee90a49SAmy Huang NativeLineNumber LineNum(Session, LineIter->Line, LineIter->ColumnNumber,
5890881d0beSAmy Huang LineSect, LineOff, LineLength, SrcFileId, Modi);
590f8170d87SAmy Huang LineNumbers.push_back(LineNum);
591f8170d87SAmy Huang ++LineIter;
592f8170d87SAmy Huang }
593f8170d87SAmy Huang return std::make_unique<NativeEnumLineNumbers>(std::move(LineNumbers));
594f8170d87SAmy Huang }
595f8170d87SAmy Huang
5968ab7dd60SZachary Turner std::unique_ptr<PDBSymbolCompiland>
getOrCreateCompiland(uint32_t Index)5978ab7dd60SZachary Turner SymbolCache::getOrCreateCompiland(uint32_t Index) {
5988ab7dd60SZachary Turner if (!Dbi)
5998ab7dd60SZachary Turner return nullptr;
6008ab7dd60SZachary Turner
6018ab7dd60SZachary Turner if (Index >= Compilands.size())
6028ab7dd60SZachary Turner return nullptr;
6038ab7dd60SZachary Turner
6048ab7dd60SZachary Turner if (Compilands[Index] == 0) {
6058ab7dd60SZachary Turner const DbiModuleList &Modules = Dbi->modules();
6068ab7dd60SZachary Turner Compilands[Index] =
6078ab7dd60SZachary Turner createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
6088ab7dd60SZachary Turner }
6098ab7dd60SZachary Turner
6108ab7dd60SZachary Turner return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
6118ab7dd60SZachary Turner }
612641ae73fSAmy Huang
613f8170d87SAmy Huang std::unique_ptr<IPDBSourceFile>
getSourceFileById(SymIndexId FileId) const614f8170d87SAmy Huang SymbolCache::getSourceFileById(SymIndexId FileId) const {
615f8170d87SAmy Huang assert(FileId < SourceFiles.size());
616f8170d87SAmy Huang
617f8170d87SAmy Huang // Id 0 is reserved.
618f8170d87SAmy Huang if (FileId == 0)
619f8170d87SAmy Huang return nullptr;
620f8170d87SAmy Huang
621f8170d87SAmy Huang return std::unique_ptr<NativeSourceFile>(
622f8170d87SAmy Huang new NativeSourceFile(*SourceFiles[FileId].get()));
623f8170d87SAmy Huang }
624f8170d87SAmy Huang
625f8170d87SAmy Huang SymIndexId
getOrCreateSourceFile(const FileChecksumEntry & Checksums) const626f8170d87SAmy Huang SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const {
627f8170d87SAmy Huang auto Iter = FileNameOffsetToId.find(Checksums.FileNameOffset);
628f8170d87SAmy Huang if (Iter != FileNameOffsetToId.end())
629f8170d87SAmy Huang return Iter->second;
630f8170d87SAmy Huang
631f8170d87SAmy Huang SymIndexId Id = SourceFiles.size();
632f8170d87SAmy Huang auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums);
633f8170d87SAmy Huang SourceFiles.push_back(std::move(SrcFile));
634f8170d87SAmy Huang FileNameOffsetToId[Checksums.FileNameOffset] = Id;
635f8170d87SAmy Huang return Id;
636f8170d87SAmy Huang }
637f8170d87SAmy Huang
638641ae73fSAmy Huang
639