DIASession.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  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/ADT/STLExtras.h"
  10. #include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h"
  11. #include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
  12. #include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
  13. #include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
  14. #include "llvm/DebugInfo/PDB/DIA/DIASession.h"
  15. #include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
  16. #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
  17. #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
  18. #include "llvm/Support/ConvertUTF.h"
  19. using namespace llvm;
  20. namespace {}
  21. DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
  22. PDB_ErrorCode DIASession::createFromPdb(StringRef Path,
  23. std::unique_ptr<IPDBSession> &Session) {
  24. CComPtr<IDiaDataSource> DiaDataSource;
  25. CComPtr<IDiaSession> DiaSession;
  26. // We assume that CoInitializeEx has already been called by the executable.
  27. HRESULT Result = ::CoCreateInstance(
  28. CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource,
  29. reinterpret_cast<LPVOID *>(&DiaDataSource));
  30. if (FAILED(Result))
  31. return PDB_ErrorCode::NoPdbImpl;
  32. llvm::SmallVector<UTF16, 128> Path16;
  33. if (!llvm::convertUTF8ToUTF16String(Path, Path16))
  34. return PDB_ErrorCode::InvalidPath;
  35. const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data());
  36. if (FAILED(Result = DiaDataSource->loadDataFromPdb(Path16Str))) {
  37. if (Result == E_PDB_NOT_FOUND)
  38. return PDB_ErrorCode::InvalidPath;
  39. else if (Result == E_PDB_FORMAT)
  40. return PDB_ErrorCode::InvalidFileFormat;
  41. else if (Result == E_INVALIDARG)
  42. return PDB_ErrorCode::InvalidParameter;
  43. else if (Result == E_UNEXPECTED)
  44. return PDB_ErrorCode::AlreadyLoaded;
  45. else
  46. return PDB_ErrorCode::UnknownError;
  47. }
  48. if (FAILED(Result = DiaDataSource->openSession(&DiaSession))) {
  49. if (Result == E_OUTOFMEMORY)
  50. return PDB_ErrorCode::NoMemory;
  51. else
  52. return PDB_ErrorCode::UnknownError;
  53. }
  54. Session.reset(new DIASession(DiaSession));
  55. return PDB_ErrorCode::Success;
  56. }
  57. PDB_ErrorCode DIASession::createFromExe(StringRef Path,
  58. std::unique_ptr<IPDBSession> &Session) {
  59. CComPtr<IDiaDataSource> DiaDataSource;
  60. CComPtr<IDiaSession> DiaSession;
  61. // We assume that CoInitializeEx has already been called by the executable.
  62. HRESULT Result = ::CoCreateInstance(
  63. CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource,
  64. reinterpret_cast<LPVOID *>(&DiaDataSource));
  65. if (FAILED(Result))
  66. return PDB_ErrorCode::NoPdbImpl;
  67. llvm::SmallVector<UTF16, 128> Path16;
  68. if (!llvm::convertUTF8ToUTF16String(Path, Path16))
  69. return PDB_ErrorCode::InvalidPath;
  70. const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
  71. if (FAILED(Result =
  72. DiaDataSource->loadDataForExe(Path16Str, nullptr, nullptr))) {
  73. if (Result == E_PDB_NOT_FOUND)
  74. return PDB_ErrorCode::InvalidPath;
  75. else if (Result == E_PDB_FORMAT)
  76. return PDB_ErrorCode::InvalidFileFormat;
  77. else if (Result == E_PDB_INVALID_SIG || Result == E_PDB_INVALID_AGE)
  78. return PDB_ErrorCode::DebugInfoMismatch;
  79. else if (Result == E_INVALIDARG)
  80. return PDB_ErrorCode::InvalidParameter;
  81. else if (Result == E_UNEXPECTED)
  82. return PDB_ErrorCode::AlreadyLoaded;
  83. else
  84. return PDB_ErrorCode::UnknownError;
  85. }
  86. if (FAILED(Result = DiaDataSource->openSession(&DiaSession))) {
  87. if (Result == E_OUTOFMEMORY)
  88. return PDB_ErrorCode::NoMemory;
  89. else
  90. return PDB_ErrorCode::UnknownError;
  91. }
  92. Session.reset(new DIASession(DiaSession));
  93. return PDB_ErrorCode::Success;
  94. }
  95. uint64_t DIASession::getLoadAddress() const {
  96. uint64_t LoadAddress;
  97. bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
  98. return (success) ? LoadAddress : 0;
  99. }
  100. void DIASession::setLoadAddress(uint64_t Address) {
  101. Session->put_loadAddress(Address);
  102. }
  103. std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() const {
  104. CComPtr<IDiaSymbol> GlobalScope;
  105. if (S_OK != Session->get_globalScope(&GlobalScope))
  106. return nullptr;
  107. auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, GlobalScope);
  108. auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
  109. std::unique_ptr<PDBSymbolExe> ExeSymbol(
  110. static_cast<PDBSymbolExe *>(PdbSymbol.release()));
  111. return ExeSymbol;
  112. }
  113. std::unique_ptr<PDBSymbol> DIASession::getSymbolById(uint32_t SymbolId) const {
  114. CComPtr<IDiaSymbol> LocatedSymbol;
  115. if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol))
  116. return nullptr;
  117. auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, LocatedSymbol);
  118. return PDBSymbol::create(*this, std::move(RawSymbol));
  119. }
  120. std::unique_ptr<PDBSymbol>
  121. DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
  122. enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
  123. CComPtr<IDiaSymbol> Symbol;
  124. if (S_OK != Session->findSymbolByVA(Address, EnumVal, &Symbol)) {
  125. ULONGLONG LoadAddr = 0;
  126. if (S_OK != Session->get_loadAddress(&LoadAddr))
  127. return nullptr;
  128. DWORD RVA = static_cast<DWORD>(Address - LoadAddr);
  129. if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol))
  130. return nullptr;
  131. }
  132. auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
  133. return PDBSymbol::create(*this, std::move(RawSymbol));
  134. }
  135. std::unique_ptr<IPDBEnumLineNumbers>
  136. DIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const {
  137. CComPtr<IDiaEnumLineNumbers> LineNumbers;
  138. if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers))
  139. return nullptr;
  140. return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
  141. }
  142. std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const {
  143. CComPtr<IDiaEnumSourceFiles> Files;
  144. if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files))
  145. return nullptr;
  146. return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
  147. }
  148. std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland(
  149. const PDBSymbolCompiland &Compiland) const {
  150. CComPtr<IDiaEnumSourceFiles> Files;
  151. const DIARawSymbol &RawSymbol =
  152. static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
  153. if (S_OK !=
  154. Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files))
  155. return nullptr;
  156. return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
  157. }
  158. std::unique_ptr<IPDBSourceFile>
  159. DIASession::getSourceFileById(uint32_t FileId) const {
  160. CComPtr<IDiaSourceFile> LocatedFile;
  161. if (S_OK != Session->findFileById(FileId, &LocatedFile))
  162. return nullptr;
  163. return llvm::make_unique<DIASourceFile>(*this, LocatedFile);
  164. }
  165. std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const {
  166. CComPtr<IDiaEnumDebugStreams> DiaEnumerator;
  167. if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator))
  168. return nullptr;
  169. return llvm::make_unique<DIAEnumDebugStreams>(DiaEnumerator);
  170. }