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