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