1 //===- DIASession.cpp - DIA 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/ADT/STLExtras.h" 11 #include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h" 12 #include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h" 13 #include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h" 14 #include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h" 15 #include "llvm/DebugInfo/PDB/DIA/DIASession.h" 16 #include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h" 17 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" 18 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" 19 #include "llvm/Support/ConvertUTF.h" 20 21 using namespace llvm; 22 23 namespace {} 24 25 DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {} 26 27 PDB_ErrorCode DIASession::createFromPdb(StringRef Path, 28 std::unique_ptr<IPDBSession> &Session) { 29 CComPtr<IDiaDataSource> DiaDataSource; 30 CComPtr<IDiaSession> DiaSession; 31 32 // We assume that CoInitializeEx has already been called by the executable. 33 HRESULT Result = ::CoCreateInstance( 34 CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource, 35 reinterpret_cast<LPVOID *>(&DiaDataSource)); 36 if (FAILED(Result)) 37 return PDB_ErrorCode::NoPdbImpl; 38 39 llvm::SmallVector<UTF16, 128> Path16; 40 if (!llvm::convertUTF8ToUTF16String(Path, Path16)) 41 return PDB_ErrorCode::InvalidPath; 42 43 const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data()); 44 if (FAILED(Result = DiaDataSource->loadDataFromPdb(Path16Str))) { 45 if (Result == E_PDB_NOT_FOUND) 46 return PDB_ErrorCode::InvalidPath; 47 else if (Result == E_PDB_FORMAT) 48 return PDB_ErrorCode::InvalidFileFormat; 49 else if (Result == E_INVALIDARG) 50 return PDB_ErrorCode::InvalidParameter; 51 else if (Result == E_UNEXPECTED) 52 return PDB_ErrorCode::AlreadyLoaded; 53 else 54 return PDB_ErrorCode::UnknownError; 55 } 56 57 if (FAILED(Result = DiaDataSource->openSession(&DiaSession))) { 58 if (Result == E_OUTOFMEMORY) 59 return PDB_ErrorCode::NoMemory; 60 else 61 return PDB_ErrorCode::UnknownError; 62 } 63 64 Session.reset(new DIASession(DiaSession)); 65 return PDB_ErrorCode::Success; 66 } 67 68 PDB_ErrorCode DIASession::createFromExe(StringRef Path, 69 std::unique_ptr<IPDBSession> &Session) { 70 CComPtr<IDiaDataSource> DiaDataSource; 71 CComPtr<IDiaSession> DiaSession; 72 73 // We assume that CoInitializeEx has already been called by the executable. 74 HRESULT Result = ::CoCreateInstance( 75 CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource, 76 reinterpret_cast<LPVOID *>(&DiaDataSource)); 77 if (FAILED(Result)) 78 return PDB_ErrorCode::NoPdbImpl; 79 80 llvm::SmallVector<UTF16, 128> Path16; 81 if (!llvm::convertUTF8ToUTF16String(Path, Path16)) 82 return PDB_ErrorCode::InvalidPath; 83 84 const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data()); 85 if (FAILED(Result = 86 DiaDataSource->loadDataForExe(Path16Str, nullptr, nullptr))) { 87 if (Result == E_PDB_NOT_FOUND) 88 return PDB_ErrorCode::InvalidPath; 89 else if (Result == E_PDB_FORMAT) 90 return PDB_ErrorCode::InvalidFileFormat; 91 else if (Result == E_PDB_INVALID_SIG || Result == E_PDB_INVALID_AGE) 92 return PDB_ErrorCode::DebugInfoMismatch; 93 else if (Result == E_INVALIDARG) 94 return PDB_ErrorCode::InvalidParameter; 95 else if (Result == E_UNEXPECTED) 96 return PDB_ErrorCode::AlreadyLoaded; 97 else 98 return PDB_ErrorCode::UnknownError; 99 } 100 101 if (FAILED(Result = DiaDataSource->openSession(&DiaSession))) { 102 if (Result == E_OUTOFMEMORY) 103 return PDB_ErrorCode::NoMemory; 104 else 105 return PDB_ErrorCode::UnknownError; 106 } 107 108 Session.reset(new DIASession(DiaSession)); 109 return PDB_ErrorCode::Success; 110 } 111 112 uint64_t DIASession::getLoadAddress() const { 113 uint64_t LoadAddress; 114 bool success = (S_OK == Session->get_loadAddress(&LoadAddress)); 115 return (success) ? LoadAddress : 0; 116 } 117 118 void DIASession::setLoadAddress(uint64_t Address) { 119 Session->put_loadAddress(Address); 120 } 121 122 std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() const { 123 CComPtr<IDiaSymbol> GlobalScope; 124 if (S_OK != Session->get_globalScope(&GlobalScope)) 125 return nullptr; 126 127 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, GlobalScope); 128 auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol))); 129 std::unique_ptr<PDBSymbolExe> ExeSymbol( 130 static_cast<PDBSymbolExe *>(PdbSymbol.release())); 131 return ExeSymbol; 132 } 133 134 std::unique_ptr<PDBSymbol> DIASession::getSymbolById(uint32_t SymbolId) const { 135 CComPtr<IDiaSymbol> LocatedSymbol; 136 if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol)) 137 return nullptr; 138 139 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, LocatedSymbol); 140 return PDBSymbol::create(*this, std::move(RawSymbol)); 141 } 142 143 std::unique_ptr<PDBSymbol> 144 DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const { 145 enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type); 146 147 CComPtr<IDiaSymbol> Symbol; 148 if (S_OK != Session->findSymbolByVA(Address, EnumVal, &Symbol)) { 149 ULONGLONG LoadAddr = 0; 150 if (S_OK != Session->get_loadAddress(&LoadAddr)) 151 return nullptr; 152 DWORD RVA = static_cast<DWORD>(Address - LoadAddr); 153 if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol)) 154 return nullptr; 155 } 156 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol); 157 return PDBSymbol::create(*this, std::move(RawSymbol)); 158 } 159 160 std::unique_ptr<IPDBEnumLineNumbers> 161 DIASession::findLineNumbers(const PDBSymbolCompiland &Compiland, 162 const IPDBSourceFile &File) const { 163 const DIARawSymbol &RawCompiland = 164 static_cast<const DIARawSymbol &>(Compiland.getRawSymbol()); 165 const DIASourceFile &RawFile = static_cast<const DIASourceFile &>(File); 166 167 CComPtr<IDiaEnumLineNumbers> LineNumbers; 168 if (S_OK != 169 Session->findLines(RawCompiland.getDiaSymbol(), RawFile.getDiaFile(), 170 &LineNumbers)) 171 return nullptr; 172 173 return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers); 174 } 175 176 std::unique_ptr<IPDBEnumLineNumbers> 177 DIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const { 178 CComPtr<IDiaEnumLineNumbers> LineNumbers; 179 if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers)) 180 return nullptr; 181 182 return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers); 183 } 184 185 std::unique_ptr<IPDBEnumSourceFiles> 186 DIASession::findSourceFiles(const PDBSymbolCompiland *Compiland, 187 llvm::StringRef Pattern, 188 PDB_NameSearchFlags Flags) const { 189 IDiaSymbol *DiaCompiland = nullptr; 190 CComBSTR Utf16Pattern; 191 if (!Pattern.empty()) 192 Utf16Pattern = CComBSTR(Pattern.data()); 193 194 if (Compiland) 195 DiaCompiland = static_cast<const DIARawSymbol &>(Compiland->getRawSymbol()) 196 .getDiaSymbol(); 197 198 Flags = static_cast<PDB_NameSearchFlags>( 199 Flags | PDB_NameSearchFlags::NS_FileNameExtMatch); 200 CComPtr<IDiaEnumSourceFiles> SourceFiles; 201 if (S_OK != 202 Session->findFile(DiaCompiland, Utf16Pattern.m_str, Flags, &SourceFiles)) 203 return nullptr; 204 return llvm::make_unique<DIAEnumSourceFiles>(*this, SourceFiles); 205 } 206 207 std::unique_ptr<IPDBSourceFile> 208 DIASession::findOneSourceFile(const PDBSymbolCompiland *Compiland, 209 llvm::StringRef Pattern, 210 PDB_NameSearchFlags Flags) const { 211 auto SourceFiles = findSourceFiles(Compiland, Pattern, Flags); 212 if (!SourceFiles || SourceFiles->getChildCount() == 0) 213 return nullptr; 214 return SourceFiles->getNext(); 215 } 216 217 std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>> 218 DIASession::findCompilandsForSourceFile(llvm::StringRef Pattern, 219 PDB_NameSearchFlags Flags) const { 220 auto File = findOneSourceFile(nullptr, Pattern, Flags); 221 if (!File) 222 return nullptr; 223 return File->getCompilands(); 224 } 225 226 std::unique_ptr<PDBSymbolCompiland> 227 DIASession::findOneCompilandForSourceFile(llvm::StringRef Pattern, 228 PDB_NameSearchFlags Flags) const { 229 auto Compilands = findCompilandsForSourceFile(Pattern, Flags); 230 if (!Compilands || Compilands->getChildCount() == 0) 231 return nullptr; 232 return Compilands->getNext(); 233 } 234 235 std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const { 236 CComPtr<IDiaEnumSourceFiles> Files; 237 if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files)) 238 return nullptr; 239 240 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files); 241 } 242 243 std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland( 244 const PDBSymbolCompiland &Compiland) const { 245 CComPtr<IDiaEnumSourceFiles> Files; 246 247 const DIARawSymbol &RawSymbol = 248 static_cast<const DIARawSymbol &>(Compiland.getRawSymbol()); 249 if (S_OK != 250 Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files)) 251 return nullptr; 252 253 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files); 254 } 255 256 std::unique_ptr<IPDBSourceFile> 257 DIASession::getSourceFileById(uint32_t FileId) const { 258 CComPtr<IDiaSourceFile> LocatedFile; 259 if (S_OK != Session->findFileById(FileId, &LocatedFile)) 260 return nullptr; 261 262 return llvm::make_unique<DIASourceFile>(*this, LocatedFile); 263 } 264 265 std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const { 266 CComPtr<IDiaEnumDebugStreams> DiaEnumerator; 267 if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator)) 268 return nullptr; 269 270 return llvm::make_unique<DIAEnumDebugStreams>(DiaEnumerator); 271 } 272