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::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const { 162 CComPtr<IDiaEnumLineNumbers> LineNumbers; 163 if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers)) 164 return nullptr; 165 166 return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers); 167 } 168 169 std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const { 170 CComPtr<IDiaEnumSourceFiles> Files; 171 if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files)) 172 return nullptr; 173 174 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files); 175 } 176 177 std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland( 178 const PDBSymbolCompiland &Compiland) const { 179 CComPtr<IDiaEnumSourceFiles> Files; 180 181 const DIARawSymbol &RawSymbol = 182 static_cast<const DIARawSymbol &>(Compiland.getRawSymbol()); 183 if (S_OK != 184 Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files)) 185 return nullptr; 186 187 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files); 188 } 189 190 std::unique_ptr<IPDBSourceFile> 191 DIASession::getSourceFileById(uint32_t FileId) const { 192 CComPtr<IDiaSourceFile> LocatedFile; 193 if (S_OK != Session->findFileById(FileId, &LocatedFile)) 194 return nullptr; 195 196 return llvm::make_unique<DIASourceFile>(*this, LocatedFile); 197 } 198 199 std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const { 200 CComPtr<IDiaEnumDebugStreams> DiaEnumerator; 201 if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator)) 202 return nullptr; 203 204 return llvm::make_unique<DIAEnumDebugStreams>(DiaEnumerator); 205 } 206