1 //===- NativeSession.cpp - Native implementation of IPDBSession -*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 11 12 #include "llvm/ADT/STLExtras.h" 13 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 14 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" 15 #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" 16 #include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h" 17 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" 18 #include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h" 19 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" 20 #include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h" 21 #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 22 #include "llvm/DebugInfo/PDB/Native/RawError.h" 23 #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 24 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" 25 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" 26 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" 27 #include "llvm/Support/Allocator.h" 28 #include "llvm/Support/BinaryByteStream.h" 29 #include "llvm/Support/Error.h" 30 #include "llvm/Support/ErrorOr.h" 31 #include "llvm/Support/MemoryBuffer.h" 32 33 #include <algorithm> 34 #include <cassert> 35 #include <memory> 36 #include <utility> 37 38 using namespace llvm; 39 using namespace llvm::msf; 40 using namespace llvm::pdb; 41 42 namespace { 43 // Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary 44 // to instantiate a NativeBuiltinSymbol for that type. 45 static const struct BuiltinTypeEntry { 46 codeview::SimpleTypeKind Kind; 47 PDB_BuiltinType Type; 48 uint32_t Size; 49 } BuiltinTypes[] = { 50 {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4}, 51 {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4}, 52 {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4}, 53 {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8}, 54 {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1}, 55 {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1}, 56 {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1}, 57 {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2}, 58 {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1} 59 // This table can be grown as necessary, but these are the only types we've 60 // needed so far. 61 }; 62 } // namespace 63 64 NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile, 65 std::unique_ptr<BumpPtrAllocator> Allocator) 66 : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)) { 67 // Id 0 is reserved for the invalid symbol. 68 SymbolCache.push_back(nullptr); 69 } 70 71 NativeSession::~NativeSession() = default; 72 73 Error NativeSession::createFromPdb(std::unique_ptr<MemoryBuffer> Buffer, 74 std::unique_ptr<IPDBSession> &Session) { 75 StringRef Path = Buffer->getBufferIdentifier(); 76 auto Stream = llvm::make_unique<MemoryBufferByteStream>( 77 std::move(Buffer), llvm::support::little); 78 79 auto Allocator = llvm::make_unique<BumpPtrAllocator>(); 80 auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), *Allocator); 81 if (auto EC = File->parseFileHeaders()) 82 return EC; 83 if (auto EC = File->parseStreamData()) 84 return EC; 85 86 Session = 87 llvm::make_unique<NativeSession>(std::move(File), std::move(Allocator)); 88 89 return Error::success(); 90 } 91 92 Error NativeSession::createFromExe(StringRef Path, 93 std::unique_ptr<IPDBSession> &Session) { 94 return make_error<RawError>(raw_error_code::feature_unsupported); 95 } 96 97 std::unique_ptr<PDBSymbolTypeEnum> 98 NativeSession::createEnumSymbol(codeview::TypeIndex Index) { 99 const auto Id = findSymbolByTypeIndex(Index); 100 return PDBSymbol::createAs<PDBSymbolTypeEnum>(*this, *SymbolCache[Id]); 101 } 102 103 std::unique_ptr<IPDBEnumSymbols> 104 NativeSession::createTypeEnumerator(codeview::TypeLeafKind Kind) { 105 auto Tpi = Pdb->getPDBTpiStream(); 106 if (!Tpi) { 107 consumeError(Tpi.takeError()); 108 return nullptr; 109 } 110 auto &Types = Tpi->typeCollection(); 111 return std::unique_ptr<IPDBEnumSymbols>( 112 new NativeEnumTypes(*this, Types, codeview::LF_ENUM)); 113 } 114 115 SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) { 116 // First see if it's already in our cache. 117 const auto Entry = TypeIndexToSymbolId.find(Index); 118 if (Entry != TypeIndexToSymbolId.end()) 119 return Entry->second; 120 121 // Symbols for built-in types are created on the fly. 122 if (Index.isSimple()) { 123 // FIXME: We will eventually need to handle pointers to other simple types, 124 // which are still simple types in the world of CodeView TypeIndexes. 125 if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct) 126 return 0; 127 const auto Kind = Index.getSimpleKind(); 128 const auto It = 129 std::find_if(std::begin(BuiltinTypes), std::end(BuiltinTypes), 130 [Kind](const BuiltinTypeEntry &Builtin) { 131 return Builtin.Kind == Kind; 132 }); 133 if (It == std::end(BuiltinTypes)) 134 return 0; 135 SymIndexId Id = SymbolCache.size(); 136 SymbolCache.emplace_back( 137 llvm::make_unique<NativeBuiltinSymbol>(*this, Id, It->Type, It->Size)); 138 TypeIndexToSymbolId[Index] = Id; 139 return Id; 140 } 141 142 // We need to instantiate and cache the desired type symbol. 143 auto Tpi = Pdb->getPDBTpiStream(); 144 if (!Tpi) { 145 consumeError(Tpi.takeError()); 146 return 0; 147 } 148 auto &Types = Tpi->typeCollection(); 149 const auto &I = Types.getType(Index); 150 const auto Id = static_cast<SymIndexId>(SymbolCache.size()); 151 // TODO(amccarth): Make this handle all types, not just LF_ENUMs. 152 assert(I.kind() == codeview::LF_ENUM); 153 SymbolCache.emplace_back(llvm::make_unique<NativeEnumSymbol>(*this, Id, I)); 154 TypeIndexToSymbolId[Index] = Id; 155 return Id; 156 } 157 158 uint64_t NativeSession::getLoadAddress() const { return 0; } 159 160 bool NativeSession::setLoadAddress(uint64_t Address) { return false; } 161 162 std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() { 163 return PDBSymbol::createAs<PDBSymbolExe>(*this, getNativeGlobalScope()); 164 } 165 166 std::unique_ptr<PDBSymbol> 167 NativeSession::getSymbolById(uint32_t SymbolId) const { 168 // If the caller has a SymbolId, it'd better be in our SymbolCache. 169 return SymbolId < SymbolCache.size() 170 ? PDBSymbol::create(*this, *SymbolCache[SymbolId]) 171 : nullptr; 172 } 173 174 bool NativeSession::addressForVA(uint64_t VA, uint32_t &Section, 175 uint32_t &Offset) const { 176 return false; 177 } 178 179 bool NativeSession::addressForRVA(uint32_t VA, uint32_t &Section, 180 uint32_t &Offset) const { 181 return false; 182 } 183 184 std::unique_ptr<PDBSymbol> 185 NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const { 186 return nullptr; 187 } 188 189 std::unique_ptr<PDBSymbol> 190 NativeSession::findSymbolByRVA(uint32_t RVA, PDB_SymType Type) const { 191 return nullptr; 192 } 193 194 std::unique_ptr<PDBSymbol> 195 NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, 196 PDB_SymType Type) const { 197 return nullptr; 198 } 199 200 std::unique_ptr<IPDBEnumLineNumbers> 201 NativeSession::findLineNumbers(const PDBSymbolCompiland &Compiland, 202 const IPDBSourceFile &File) const { 203 return nullptr; 204 } 205 206 std::unique_ptr<IPDBEnumLineNumbers> 207 NativeSession::findLineNumbersByAddress(uint64_t Address, 208 uint32_t Length) const { 209 return nullptr; 210 } 211 212 std::unique_ptr<IPDBEnumLineNumbers> 213 NativeSession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const { 214 return nullptr; 215 } 216 217 std::unique_ptr<IPDBEnumLineNumbers> 218 NativeSession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset, 219 uint32_t Length) const { 220 return nullptr; 221 } 222 223 std::unique_ptr<IPDBEnumSourceFiles> 224 NativeSession::findSourceFiles(const PDBSymbolCompiland *Compiland, 225 StringRef Pattern, 226 PDB_NameSearchFlags Flags) const { 227 return nullptr; 228 } 229 230 std::unique_ptr<IPDBSourceFile> 231 NativeSession::findOneSourceFile(const PDBSymbolCompiland *Compiland, 232 StringRef Pattern, 233 PDB_NameSearchFlags Flags) const { 234 return nullptr; 235 } 236 237 std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>> 238 NativeSession::findCompilandsForSourceFile(StringRef Pattern, 239 PDB_NameSearchFlags Flags) const { 240 return nullptr; 241 } 242 243 std::unique_ptr<PDBSymbolCompiland> 244 NativeSession::findOneCompilandForSourceFile(StringRef Pattern, 245 PDB_NameSearchFlags Flags) const { 246 return nullptr; 247 } 248 249 std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getAllSourceFiles() const { 250 return nullptr; 251 } 252 253 std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getSourceFilesForCompiland( 254 const PDBSymbolCompiland &Compiland) const { 255 return nullptr; 256 } 257 258 std::unique_ptr<IPDBSourceFile> 259 NativeSession::getSourceFileById(uint32_t FileId) const { 260 return nullptr; 261 } 262 263 std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const { 264 return nullptr; 265 } 266 267 std::unique_ptr<IPDBEnumTables> NativeSession::getEnumTables() const { 268 return nullptr; 269 } 270 271 std::unique_ptr<IPDBEnumInjectedSources> 272 NativeSession::getInjectedSources() const { 273 return nullptr; 274 } 275 276 std::unique_ptr<IPDBEnumSectionContribs> 277 NativeSession::getSectionContribs() const { 278 return nullptr; 279 } 280 281 NativeExeSymbol &NativeSession::getNativeGlobalScope() { 282 if (ExeSymbol == 0) { 283 ExeSymbol = static_cast<SymIndexId>(SymbolCache.size()); 284 SymbolCache.push_back(llvm::make_unique<NativeExeSymbol>(*this, ExeSymbol)); 285 } 286 return static_cast<NativeExeSymbol &>(*SymbolCache[ExeSymbol]); 287 } 288