LCOV - code coverage report
Current view: top level - lib/DebugInfo/PDB/Native - SymbolCache.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 95 109 87.2 %
Date: 2018-10-20 13:21:21 Functions: 12 12 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
       2             : 
       3             : #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
       4             : #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
       5             : #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
       6             : #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
       7             : #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
       8             : #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
       9             : #include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
      10             : #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
      11             : #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
      12             : #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
      13             : #include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"
      14             : #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
      15             : #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
      16             : #include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
      17             : #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
      18             : #include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h"
      19             : #include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
      20             : #include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"
      21             : #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
      22             : #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
      23             : #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
      24             : #include "llvm/DebugInfo/PDB/PDBSymbol.h"
      25             : #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
      26             : #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
      27             : 
      28             : using namespace llvm;
      29             : using namespace llvm::codeview;
      30             : using namespace llvm::pdb;
      31             : 
      32             : // Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
      33             : // to instantiate a NativeBuiltinSymbol for that type.
      34             : static const struct BuiltinTypeEntry {
      35             :   codeview::SimpleTypeKind Kind;
      36             :   PDB_BuiltinType Type;
      37             :   uint32_t Size;
      38             : } BuiltinTypes[] = {
      39             :     {codeview::SimpleTypeKind::None, PDB_BuiltinType::None, 0},
      40             :     {codeview::SimpleTypeKind::Void, PDB_BuiltinType::Void, 0},
      41             :     {codeview::SimpleTypeKind::HResult, PDB_BuiltinType::HResult, 4},
      42             :     {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
      43             :     {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
      44             :     {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
      45             :     {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
      46             :     {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
      47             :     {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
      48             :     {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
      49             :     {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
      50             :     {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
      51             :     {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2},
      52             :     {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2},
      53             :     {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4},
      54             :     {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
      55             :     {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
      56             :     {codeview::SimpleTypeKind::Float32, PDB_BuiltinType::Float, 4},
      57             :     {codeview::SimpleTypeKind::Float64, PDB_BuiltinType::Float, 8},
      58             :     {codeview::SimpleTypeKind::Float80, PDB_BuiltinType::Float, 10},
      59             :     {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1},
      60             :     // This table can be grown as necessary, but these are the only types we've
      61             :     // needed so far.
      62             : };
      63             : 
      64         127 : SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
      65         254 :     : Session(Session), Dbi(Dbi) {
      66             :   // Id 0 is reserved for the invalid symbol.
      67         127 :   Cache.push_back(nullptr);
      68             : 
      69         127 :   if (Dbi)
      70         122 :     Compilands.resize(Dbi->modules().getModuleCount());
      71             : 
      72         127 :   auto &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
      73         127 :   Tpi.buildHashMap();
      74         127 : }
      75             : 
      76             : std::unique_ptr<IPDBEnumSymbols>
      77           4 : SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
      78           4 :   return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
      79             : }
      80             : 
      81             : std::unique_ptr<IPDBEnumSymbols>
      82           8 : SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
      83          16 :   auto Tpi = Session.getPDBFile().getPDBTpiStream();
      84           8 :   if (!Tpi) {
      85           0 :     consumeError(Tpi.takeError());
      86             :     return nullptr;
      87             :   }
      88             :   auto &Types = Tpi->typeCollection();
      89             :   return std::unique_ptr<IPDBEnumSymbols>(
      90          16 :       new NativeEnumTypes(Session, Types, std::move(Kinds)));
      91             : }
      92             : 
      93             : std::unique_ptr<IPDBEnumSymbols>
      94           2 : SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
      95             :   return std::unique_ptr<IPDBEnumSymbols>(
      96           2 :       new NativeEnumGlobals(Session, {Kind}));
      97             : }
      98             : 
      99          52 : SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
     100             :                                          ModifierOptions Mods) {
     101          52 :   if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
     102           5 :     return createSymbol<NativeTypePointer>(Index);
     103             : 
     104             :   const auto Kind = Index.getSimpleKind();
     105             :   const auto It = std::find_if(
     106             :       std::begin(BuiltinTypes), std::end(BuiltinTypes),
     107             :       [Kind](const BuiltinTypeEntry &Builtin) { return Builtin.Kind == Kind; });
     108          47 :   if (It == std::end(BuiltinTypes))
     109             :     return 0;
     110          47 :   return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
     111             : }
     112             : 
     113             : SymIndexId
     114          34 : SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
     115             :                                          codeview::CVType CVT) {
     116             :   ModifierRecord Record;
     117          68 :   if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
     118           0 :     consumeError(std::move(EC));
     119             :     return 0;
     120             :   }
     121             : 
     122          34 :   if (Record.ModifiedType.isSimple())
     123          12 :     return createSimpleType(Record.ModifiedType, Record.Modifiers);
     124             : 
     125             :   // Make sure we create and cache a record for the unmodified type.
     126          22 :   SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
     127          22 :   NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
     128             : 
     129          22 :   switch (UnmodifiedNRS.getSymTag()) {
     130             :   case PDB_SymType::Enum:
     131           2 :     return createSymbol<NativeTypeEnum>(
     132           2 :         static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));
     133             :   case PDB_SymType::UDT:
     134          20 :     return createSymbol<NativeTypeUDT>(
     135          20 :         static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));
     136             :   default:
     137             :     // No other types can be modified.  (LF_POINTER, for example, records
     138             :     // its modifiers a different way.
     139             :     assert(false && "Invalid LF_MODIFIER record");
     140             :     break;
     141             :   }
     142             :   return 0;
     143             : }
     144             : 
     145        1088 : SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
     146             :   // First see if it's already in our cache.
     147        1088 :   const auto Entry = TypeIndexToSymbolId.find(Index);
     148        1088 :   if (Entry != TypeIndexToSymbolId.end())
     149         651 :     return Entry->second;
     150             : 
     151             :   // Symbols for built-in types are created on the fly.
     152         437 :   if (Index.isSimple()) {
     153          40 :     SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
     154             :     assert(TypeIndexToSymbolId.count(Index) == 0);
     155          40 :     TypeIndexToSymbolId[Index] = Result;
     156          40 :     return Result;
     157             :   }
     158             : 
     159             :   // We need to instantiate and cache the desired type symbol.
     160         794 :   auto Tpi = Session.getPDBFile().getPDBTpiStream();
     161         397 :   if (!Tpi) {
     162           0 :     consumeError(Tpi.takeError());
     163           0 :     return 0;
     164             :   }
     165             :   codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
     166         397 :   codeview::CVType CVT = Types.getType(Index);
     167             : 
     168         397 :   if (isUdtForwardRef(CVT)) {
     169          40 :     Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);
     170             : 
     171          40 :     if (!EFD)
     172           0 :       consumeError(EFD.takeError());
     173          40 :     else if (*EFD != Index) {
     174             :       assert(!isUdtForwardRef(Types.getType(*EFD)));
     175          40 :       SymIndexId Result = findSymbolByTypeIndex(*EFD);
     176             :       // Record a mapping from ForwardRef -> SymIndex of complete type so that
     177             :       // we'll take the fast path next time.
     178             :       assert(TypeIndexToSymbolId.count(Index) == 0);
     179          40 :       TypeIndexToSymbolId[Index] = Result;
     180             :       return Result;
     181             :     }
     182             :   }
     183             : 
     184             :   // At this point if we still have a forward ref udt it means the full decl was
     185             :   // not in the PDB.  We just have to deal with it and use the forward ref.
     186             :   SymIndexId Id = 0;
     187         357 :   switch (CVT.kind()) {
     188             :   case codeview::LF_ENUM:
     189          50 :     Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
     190          50 :     break;
     191             :   case codeview::LF_ARRAY:
     192           2 :     Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
     193             :                                                            std::move(CVT));
     194           2 :     break;
     195             :   case codeview::LF_CLASS:
     196             :   case codeview::LF_STRUCTURE:
     197             :   case codeview::LF_INTERFACE:
     198          74 :     Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
     199          74 :     break;
     200             :   case codeview::LF_UNION:
     201           2 :     Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
     202           2 :     break;
     203             :   case codeview::LF_POINTER:
     204          73 :     Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
     205             :                                                                std::move(CVT));
     206          73 :     break;
     207             :   case codeview::LF_MODIFIER:
     208          34 :     Id = createSymbolForModifiedType(Index, std::move(CVT));
     209          34 :     break;
     210             :   case codeview::LF_PROCEDURE:
     211          36 :     Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
     212             :         Index, std::move(CVT));
     213          36 :     break;
     214             :   case codeview::LF_MFUNCTION:
     215          86 :     Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
     216             :         Index, std::move(CVT));
     217          86 :     break;
     218             :   case codeview::LF_VTSHAPE:
     219           0 :     Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
     220             :         Index, std::move(CVT));
     221           0 :     break;
     222           0 :   default:
     223           0 :     Id = createSymbolPlaceholder();
     224           0 :     break;
     225             :   }
     226         357 :   if (Id != 0) {
     227             :     assert(TypeIndexToSymbolId.count(Index) == 0);
     228         357 :     TypeIndexToSymbolId[Index] = Id;
     229             :   }
     230             :   return Id;
     231             : }
     232             : 
     233             : std::unique_ptr<PDBSymbol>
     234         926 : SymbolCache::getSymbolById(SymIndexId SymbolId) const {
     235             :   assert(SymbolId < Cache.size());
     236             : 
     237             :   // Id 0 is reserved.
     238         926 :   if (SymbolId == 0 || SymbolId >= Cache.size())
     239             :     return nullptr;
     240             : 
     241             :   // Make sure to handle the case where we've inserted a placeholder symbol
     242             :   // for types we don't yet suppport.
     243             :   NativeRawSymbol *NRS = Cache[SymbolId].get();
     244         851 :   if (!NRS)
     245             :     return nullptr;
     246             : 
     247         851 :   return PDBSymbol::create(Session, *NRS);
     248             : }
     249             : 
     250         198 : NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
     251         396 :   return *Cache[SymbolId];
     252             : }
     253             : 
     254          71 : uint32_t SymbolCache::getNumCompilands() const {
     255          71 :   if (!Dbi)
     256             :     return 0;
     257             : 
     258          71 :   return Dbi->modules().getModuleCount();
     259             : }
     260             : 
     261           6 : SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
     262           6 :   auto Iter = GlobalOffsetToSymbolId.find(Offset);
     263           6 :   if (Iter != GlobalOffsetToSymbolId.end())
     264           0 :     return Iter->second;
     265             : 
     266          12 :   SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
     267           6 :   CVSymbol CVS = SS.readRecord(Offset);
     268             :   SymIndexId Id = 0;
     269           6 :   switch (CVS.kind()) {
     270             :   case SymbolKind::S_UDT: {
     271           6 :     UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
     272           6 :     Id = createSymbol<NativeTypeTypedef>(std::move(US));
     273             :     break;
     274             :   }
     275           0 :   default:
     276           0 :     Id = createSymbolPlaceholder();
     277           0 :     break;
     278             :   }
     279           6 :   if (Id != 0) {
     280             :     assert(GlobalOffsetToSymbolId.count(Offset) == 0);
     281           6 :     GlobalOffsetToSymbolId[Offset] = Id;
     282             :   }
     283             : 
     284             :   return Id;
     285             : }
     286             : 
     287             : std::unique_ptr<PDBSymbolCompiland>
     288          62 : SymbolCache::getOrCreateCompiland(uint32_t Index) {
     289          62 :   if (!Dbi)
     290             :     return nullptr;
     291             : 
     292         124 :   if (Index >= Compilands.size())
     293             :     return nullptr;
     294             : 
     295          62 :   if (Compilands[Index] == 0) {
     296          56 :     const DbiModuleList &Modules = Dbi->modules();
     297          56 :     Compilands[Index] =
     298          56 :         createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
     299             :   }
     300             : 
     301         124 :   return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
     302             : }

Generated by: LCOV version 1.13