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