Home | History | Annotate | Download | only in DIA
      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