1 #include "llvm/DebugInfo/PDB/Native/SymbolCache.h" 2 3 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" 4 #include "llvm/DebugInfo/PDB/Native/DbiStream.h" 5 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" 6 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" 7 #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" 8 #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 9 #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" 10 #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" 11 #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h" 12 #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 13 #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 14 #include "llvm/DebugInfo/PDB/PDBSymbol.h" 15 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" 16 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" 17 18 using namespace llvm; 19 using namespace llvm::codeview; 20 using namespace llvm::pdb; 21 22 // Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary 23 // to instantiate a NativeBuiltinSymbol for that type. 24 static const struct BuiltinTypeEntry { 25 codeview::SimpleTypeKind Kind; 26 PDB_BuiltinType Type; 27 uint32_t Size; 28 } BuiltinTypes[] = { 29 {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4}, 30 {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4}, 31 {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4}, 32 {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8}, 33 {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1}, 34 {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1}, 35 {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1}, 36 {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2}, 37 {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1} 38 // This table can be grown as necessary, but these are the only types we've 39 // needed so far. 40 }; 41 42 SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi) 43 : Session(Session), Dbi(Dbi) { 44 // Id 0 is reserved for the invalid symbol. 45 Cache.push_back(nullptr); 46 47 if (Dbi) 48 Compilands.resize(Dbi->modules().getModuleCount()); 49 } 50 51 std::unique_ptr<IPDBEnumSymbols> 52 SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) { 53 auto Tpi = Session.getPDBFile().getPDBTpiStream(); 54 if (!Tpi) { 55 consumeError(Tpi.takeError()); 56 return nullptr; 57 } 58 auto &Types = Tpi->typeCollection(); 59 return std::unique_ptr<IPDBEnumSymbols>( 60 new NativeEnumTypes(Session, Types, Kind)); 61 } 62 63 SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) { 64 // First see if it's already in our cache. 65 const auto Entry = TypeIndexToSymbolId.find(Index); 66 if (Entry != TypeIndexToSymbolId.end()) 67 return Entry->second; 68 69 // Symbols for built-in types are created on the fly. 70 if (Index.isSimple()) { 71 // FIXME: We will eventually need to handle pointers to other simple types, 72 // which are still simple types in the world of CodeView TypeIndexes. 73 if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct) 74 return 0; 75 const auto Kind = Index.getSimpleKind(); 76 const auto It = 77 std::find_if(std::begin(BuiltinTypes), std::end(BuiltinTypes), 78 [Kind](const BuiltinTypeEntry &Builtin) { 79 return Builtin.Kind == Kind; 80 }); 81 if (It == std::end(BuiltinTypes)) 82 return 0; 83 SymIndexId Id = Cache.size(); 84 Cache.emplace_back( 85 llvm::make_unique<NativeTypeBuiltin>(Session, Id, It->Type, It->Size)); 86 TypeIndexToSymbolId[Index] = Id; 87 return Id; 88 } 89 90 // We need to instantiate and cache the desired type symbol. 91 auto Tpi = Session.getPDBFile().getPDBTpiStream(); 92 if (!Tpi) { 93 consumeError(Tpi.takeError()); 94 return 0; 95 } 96 codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection(); 97 codeview::CVType CVT = Types.getType(Index); 98 // TODO(amccarth): Make this handle all types. 99 SymIndexId Id = 0; 100 switch (CVT.kind()) { 101 case codeview::LF_ENUM: 102 Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT)); 103 break; 104 case codeview::LF_POINTER: 105 Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index, 106 std::move(CVT)); 107 break; 108 default: 109 Id = createSymbolPlaceholder(); 110 break; 111 } 112 if (Id != 0) 113 TypeIndexToSymbolId[Index] = Id; 114 return Id; 115 } 116 117 std::unique_ptr<PDBSymbol> 118 SymbolCache::getSymbolById(SymIndexId SymbolId) const { 119 // Id 0 is reserved. 120 if (SymbolId == 0) 121 return nullptr; 122 123 // If the caller has a SymbolId, it'd better be in our SymbolCache. 124 return SymbolId < Cache.size() ? PDBSymbol::create(Session, *Cache[SymbolId]) 125 : nullptr; 126 } 127 128 NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const { 129 return *Cache[SymbolId]; 130 } 131 132 uint32_t SymbolCache::getNumCompilands() const { 133 if (!Dbi) 134 return 0; 135 136 return Dbi->modules().getModuleCount(); 137 } 138 139 std::unique_ptr<PDBSymbolCompiland> 140 SymbolCache::getOrCreateCompiland(uint32_t Index) { 141 if (!Dbi) 142 return nullptr; 143 144 if (Index >= Compilands.size()) 145 return nullptr; 146 147 if (Compilands[Index] == 0) { 148 const DbiModuleList &Modules = Dbi->modules(); 149 Compilands[Index] = 150 createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index)); 151 } 152 153 return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]); 154 } 155