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 SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi) 65 : Session(Session), Dbi(Dbi) { 66 // Id 0 is reserved for the invalid symbol. 67 Cache.push_back(nullptr); 68 69 if (Dbi) 70 Compilands.resize(Dbi->modules().getModuleCount()); 71 } 72 73 std::unique_ptr<IPDBEnumSymbols> 74 SymbolCache::createTypeEnumerator(TypeLeafKind Kind) { 75 return createTypeEnumerator(std::vector<TypeLeafKind>{Kind}); 76 } 77 78 std::unique_ptr<IPDBEnumSymbols> 79 SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) { 80 auto Tpi = Session.getPDBFile().getPDBTpiStream(); 81 if (!Tpi) { 82 consumeError(Tpi.takeError()); 83 return nullptr; 84 } 85 auto &Types = Tpi->typeCollection(); 86 return std::unique_ptr<IPDBEnumSymbols>( 87 new NativeEnumTypes(Session, Types, std::move(Kinds))); 88 } 89 90 std::unique_ptr<IPDBEnumSymbols> 91 SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) { 92 return std::unique_ptr<IPDBEnumSymbols>( 93 new NativeEnumGlobals(Session, {Kind})); 94 } 95 96 SymIndexId SymbolCache::createSimpleType(TypeIndex Index, 97 ModifierOptions Mods) { 98 if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct) 99 return createSymbol<NativeTypePointer>(Index); 100 101 const auto Kind = Index.getSimpleKind(); 102 const auto It = std::find_if( 103 std::begin(BuiltinTypes), std::end(BuiltinTypes), 104 [Kind](const BuiltinTypeEntry &Builtin) { return Builtin.Kind == Kind; }); 105 if (It == std::end(BuiltinTypes)) 106 return 0; 107 return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size); 108 } 109 110 SymIndexId 111 SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI, 112 codeview::CVType CVT) { 113 ModifierRecord Record; 114 if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) { 115 consumeError(std::move(EC)); 116 return 0; 117 } 118 119 if (Record.ModifiedType.isSimple()) 120 return createSimpleType(Record.ModifiedType, Record.Modifiers); 121 122 // Make sure we create and cache a record for the unmodified type. 123 SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType); 124 NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId]; 125 126 switch (UnmodifiedNRS.getSymTag()) { 127 case PDB_SymType::Enum: 128 return createSymbol<NativeTypeEnum>( 129 static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record)); 130 case PDB_SymType::UDT: 131 return createSymbol<NativeTypeUDT>( 132 static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record)); 133 default: 134 // No other types can be modified. (LF_POINTER, for example, records 135 // its modifiers a different way. 136 assert(false && "Invalid LF_MODIFIER record"); 137 break; 138 } 139 return 0; 140 } 141 142 SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) { 143 // First see if it's already in our cache. 144 const auto Entry = TypeIndexToSymbolId.find(Index); 145 if (Entry != TypeIndexToSymbolId.end()) 146 return Entry->second; 147 148 // Symbols for built-in types are created on the fly. 149 if (Index.isSimple()) { 150 SymIndexId Result = createSimpleType(Index, ModifierOptions::None); 151 assert(TypeIndexToSymbolId.count(Index) == 0); 152 TypeIndexToSymbolId[Index] = Result; 153 return Result; 154 } 155 156 // We need to instantiate and cache the desired type symbol. 157 auto Tpi = Session.getPDBFile().getPDBTpiStream(); 158 if (!Tpi) { 159 consumeError(Tpi.takeError()); 160 return 0; 161 } 162 codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection(); 163 codeview::CVType CVT = Types.getType(Index); 164 165 if (isUdtForwardRef(CVT)) { 166 Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index); 167 168 if (!EFD) 169 consumeError(EFD.takeError()); 170 else if (*EFD != Index) { 171 assert(!isUdtForwardRef(Types.getType(*EFD))); 172 SymIndexId Result = findSymbolByTypeIndex(*EFD); 173 // Record a mapping from ForwardRef -> SymIndex of complete type so that 174 // we'll take the fast path next time. 175 assert(TypeIndexToSymbolId.count(Index) == 0); 176 TypeIndexToSymbolId[Index] = Result; 177 return Result; 178 } 179 } 180 181 // At this point if we still have a forward ref udt it means the full decl was 182 // not in the PDB. We just have to deal with it and use the forward ref. 183 SymIndexId Id = 0; 184 switch (CVT.kind()) { 185 case codeview::LF_ENUM: 186 Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT)); 187 break; 188 case codeview::LF_ARRAY: 189 Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index, 190 std::move(CVT)); 191 break; 192 case codeview::LF_CLASS: 193 case codeview::LF_STRUCTURE: 194 case codeview::LF_INTERFACE: 195 Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT)); 196 break; 197 case codeview::LF_UNION: 198 Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT)); 199 break; 200 case codeview::LF_POINTER: 201 Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index, 202 std::move(CVT)); 203 break; 204 case codeview::LF_MODIFIER: 205 Id = createSymbolForModifiedType(Index, std::move(CVT)); 206 break; 207 case codeview::LF_PROCEDURE: 208 Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>( 209 Index, std::move(CVT)); 210 break; 211 case codeview::LF_MFUNCTION: 212 Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>( 213 Index, std::move(CVT)); 214 break; 215 case codeview::LF_VTSHAPE: 216 Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>( 217 Index, std::move(CVT)); 218 break; 219 default: 220 Id = createSymbolPlaceholder(); 221 break; 222 } 223 if (Id != 0) { 224 assert(TypeIndexToSymbolId.count(Index) == 0); 225 TypeIndexToSymbolId[Index] = Id; 226 } 227 return Id; 228 } 229 230 std::unique_ptr<PDBSymbol> 231 SymbolCache::getSymbolById(SymIndexId SymbolId) const { 232 assert(SymbolId < Cache.size()); 233 234 // Id 0 is reserved. 235 if (SymbolId == 0 || SymbolId >= Cache.size()) 236 return nullptr; 237 238 // Make sure to handle the case where we've inserted a placeholder symbol 239 // for types we don't yet suppport. 240 NativeRawSymbol *NRS = Cache[SymbolId].get(); 241 if (!NRS) 242 return nullptr; 243 244 return PDBSymbol::create(Session, *NRS); 245 } 246 247 NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const { 248 return *Cache[SymbolId]; 249 } 250 251 uint32_t SymbolCache::getNumCompilands() const { 252 if (!Dbi) 253 return 0; 254 255 return Dbi->modules().getModuleCount(); 256 } 257 258 SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) { 259 auto Iter = GlobalOffsetToSymbolId.find(Offset); 260 if (Iter != GlobalOffsetToSymbolId.end()) 261 return Iter->second; 262 263 SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream()); 264 CVSymbol CVS = SS.readRecord(Offset); 265 SymIndexId Id = 0; 266 switch (CVS.kind()) { 267 case SymbolKind::S_UDT: { 268 UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS)); 269 Id = createSymbol<NativeTypeTypedef>(std::move(US)); 270 break; 271 } 272 default: 273 Id = createSymbolPlaceholder(); 274 break; 275 } 276 if (Id != 0) { 277 assert(GlobalOffsetToSymbolId.count(Offset) == 0); 278 GlobalOffsetToSymbolId[Offset] = Id; 279 } 280 281 return Id; 282 } 283 284 std::unique_ptr<PDBSymbolCompiland> 285 SymbolCache::getOrCreateCompiland(uint32_t Index) { 286 if (!Dbi) 287 return nullptr; 288 289 if (Index >= Compilands.size()) 290 return nullptr; 291 292 if (Compilands[Index] == 0) { 293 const DbiModuleList &Modules = Dbi->modules(); 294 Compilands[Index] = 295 createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index)); 296 } 297 298 return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]); 299 } 300