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/GenericError.h" 15 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" 16 #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" 17 #include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h" 18 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" 19 #include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h" 20 #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 21 #include "llvm/DebugInfo/PDB/Native/RawError.h" 22 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" 23 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" 24 #include "llvm/Support/Allocator.h" 25 #include "llvm/Support/BinaryByteStream.h" 26 #include "llvm/Support/Error.h" 27 #include "llvm/Support/ErrorOr.h" 28 #include "llvm/Support/MemoryBuffer.h" 29 30 #include <algorithm> 31 #include <memory> 32 #include <utility> 33 34 using namespace llvm; 35 using namespace llvm::msf; 36 using namespace llvm::pdb; 37 38 namespace { 39 // Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary 40 // to instantiate a NativeBuiltinSymbol for that type. 41 static const struct BuiltinTypeEntry { 42 codeview::SimpleTypeKind Kind; 43 PDB_BuiltinType Type; 44 uint32_t Size; 45 } BuiltinTypes[] = { 46 {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4}, 47 {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4}, 48 {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4}, 49 {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8}, 50 {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1}, 51 {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1}, 52 {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1}, 53 {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2}, 54 {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1} 55 // This table can be grown as necessary, but these are the only types we've 56 // needed so far. 57 }; 58 } // namespace 59 60 NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile, 61 std::unique_ptr<BumpPtrAllocator> Allocator) 62 : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)) {} 63 64 NativeSession::~NativeSession() = default; 65 66 Error NativeSession::createFromPdb(StringRef Path, 67 std::unique_ptr<IPDBSession> &Session) { 68 ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer = 69 MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1, 70 /*RequiresNullTerminator=*/false); 71 if (!ErrorOrBuffer) 72 return make_error<GenericError>(generic_error_code::invalid_path); 73 74 std::unique_ptr<MemoryBuffer> Buffer = std::move(*ErrorOrBuffer); 75 auto Stream = llvm::make_unique<MemoryBufferByteStream>( 76 std::move(Buffer), llvm::support::little); 77 78 auto Allocator = llvm::make_unique<BumpPtrAllocator>(); 79 auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), *Allocator); 80 if (auto EC = File->parseFileHeaders()) 81 return EC; 82 if (auto EC = File->parseStreamData()) 83 return EC; 84 85 Session = 86 llvm::make_unique<NativeSession>(std::move(File), std::move(Allocator)); 87 88 return Error::success(); 89 } 90 91 Error NativeSession::createFromExe(StringRef Path, 92 std::unique_ptr<IPDBSession> &Session) { 93 return make_error<RawError>(raw_error_code::feature_unsupported); 94 } 95 96 std::unique_ptr<PDBSymbolCompiland> 97 NativeSession::createCompilandSymbol(DbiModuleDescriptor MI) { 98 const auto Id = static_cast<SymIndexId>(SymbolCache.size()); 99 SymbolCache.push_back( 100 llvm::make_unique<NativeCompilandSymbol>(*this, Id, MI)); 101 return llvm::make_unique<PDBSymbolCompiland>( 102 *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone())); 103 } 104 105 SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) { 106 // First see if it's already in our cache. 107 const auto Entry = TypeIndexToSymbolId.find(Index); 108 if (Entry != TypeIndexToSymbolId.end()) 109 return Entry->second; 110 111 // Symbols for built-in types are created on the fly. 112 if (Index.isSimple()) { 113 // FIXME: We will eventually need to handle pointers to other simple types, 114 // which are still simple types in the world of CodeView TypeIndexes. 115 if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct) 116 return 0; 117 const auto Kind = Index.getSimpleKind(); 118 const auto It = 119 std::find_if(std::begin(BuiltinTypes), std::end(BuiltinTypes), 120 [Kind](const BuiltinTypeEntry &Builtin) { 121 return Builtin.Kind == Kind; 122 }); 123 if (It == std::end(BuiltinTypes)) 124 return 0; 125 SymIndexId Id = SymbolCache.size(); 126 SymbolCache.emplace_back( 127 llvm::make_unique<NativeBuiltinSymbol>(*this, Id, It->Type, It->Size)); 128 TypeIndexToSymbolId[Index] = Id; 129 return Id; 130 } 131 132 // TODO: Look up PDB type by type index 133 134 return 0; 135 } 136 137 uint64_t NativeSession::getLoadAddress() const { return 0; } 138 139 void NativeSession::setLoadAddress(uint64_t Address) {} 140 141 std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() { 142 const auto Id = static_cast<SymIndexId>(SymbolCache.size()); 143 SymbolCache.push_back(llvm::make_unique<NativeExeSymbol>(*this, Id)); 144 auto RawSymbol = SymbolCache[Id]->clone(); 145 auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol))); 146 std::unique_ptr<PDBSymbolExe> ExeSymbol( 147 static_cast<PDBSymbolExe *>(PdbSymbol.release())); 148 return ExeSymbol; 149 } 150 151 std::unique_ptr<PDBSymbol> 152 NativeSession::getSymbolById(uint32_t SymbolId) const { 153 // If the caller has a SymbolId, it'd better be in our SymbolCache. 154 return SymbolId < SymbolCache.size() 155 ? PDBSymbol::create(*this, SymbolCache[SymbolId]->clone()) 156 : nullptr; 157 } 158 159 std::unique_ptr<PDBSymbol> 160 NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const { 161 return nullptr; 162 } 163 164 std::unique_ptr<IPDBEnumLineNumbers> 165 NativeSession::findLineNumbers(const PDBSymbolCompiland &Compiland, 166 const IPDBSourceFile &File) const { 167 return nullptr; 168 } 169 170 std::unique_ptr<IPDBEnumLineNumbers> 171 NativeSession::findLineNumbersByAddress(uint64_t Address, 172 uint32_t Length) const { 173 return nullptr; 174 } 175 176 std::unique_ptr<IPDBEnumSourceFiles> 177 NativeSession::findSourceFiles(const PDBSymbolCompiland *Compiland, 178 StringRef Pattern, 179 PDB_NameSearchFlags Flags) const { 180 return nullptr; 181 } 182 183 std::unique_ptr<IPDBSourceFile> 184 NativeSession::findOneSourceFile(const PDBSymbolCompiland *Compiland, 185 StringRef Pattern, 186 PDB_NameSearchFlags Flags) const { 187 return nullptr; 188 } 189 190 std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>> 191 NativeSession::findCompilandsForSourceFile(StringRef Pattern, 192 PDB_NameSearchFlags Flags) const { 193 return nullptr; 194 } 195 196 std::unique_ptr<PDBSymbolCompiland> 197 NativeSession::findOneCompilandForSourceFile(StringRef Pattern, 198 PDB_NameSearchFlags Flags) const { 199 return nullptr; 200 } 201 202 std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getAllSourceFiles() const { 203 return nullptr; 204 } 205 206 std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getSourceFilesForCompiland( 207 const PDBSymbolCompiland &Compiland) const { 208 return nullptr; 209 } 210 211 std::unique_ptr<IPDBSourceFile> 212 NativeSession::getSourceFileById(uint32_t FileId) const { 213 return nullptr; 214 } 215 216 std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const { 217 return nullptr; 218 } 219