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/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 
     20 using namespace llvm;
     21 
     22 namespace {}
     23 
     24 DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
     25 
     26 PDB_ErrorCode DIASession::createFromPdb(StringRef Path,
     27                                         std::unique_ptr<IPDBSession> &Session) {
     28   CComPtr<IDiaDataSource> DiaDataSource;
     29   CComPtr<IDiaSession> DiaSession;
     30 
     31   // We assume that CoInitializeEx has already been called by the executable.
     32   HRESULT Result = ::CoCreateInstance(
     33       CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource,
     34       reinterpret_cast<LPVOID *>(&DiaDataSource));
     35   if (FAILED(Result))
     36     return PDB_ErrorCode::NoPdbImpl;
     37 
     38   llvm::SmallVector<UTF16, 128> Path16;
     39   if (!llvm::convertUTF8ToUTF16String(Path, Path16))
     40     return PDB_ErrorCode::InvalidPath;
     41 
     42   const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data());
     43   if (FAILED(Result = DiaDataSource->loadDataFromPdb(Path16Str))) {
     44     if (Result == E_PDB_NOT_FOUND)
     45       return PDB_ErrorCode::InvalidPath;
     46     else if (Result == E_PDB_FORMAT)
     47       return PDB_ErrorCode::InvalidFileFormat;
     48     else if (Result == E_INVALIDARG)
     49       return PDB_ErrorCode::InvalidParameter;
     50     else if (Result == E_UNEXPECTED)
     51       return PDB_ErrorCode::AlreadyLoaded;
     52     else
     53       return PDB_ErrorCode::UnknownError;
     54   }
     55 
     56   if (FAILED(Result = DiaDataSource->openSession(&DiaSession))) {
     57     if (Result == E_OUTOFMEMORY)
     58       return PDB_ErrorCode::NoMemory;
     59     else
     60       return PDB_ErrorCode::UnknownError;
     61   }
     62 
     63   Session.reset(new DIASession(DiaSession));
     64   return PDB_ErrorCode::Success;
     65 }
     66 
     67 uint64_t DIASession::getLoadAddress() const {
     68   uint64_t LoadAddress;
     69   bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
     70   return (success) ? LoadAddress : 0;
     71 }
     72 
     73 void DIASession::setLoadAddress(uint64_t Address) {
     74   Session->put_loadAddress(Address);
     75 }
     76 
     77 std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() const {
     78   CComPtr<IDiaSymbol> GlobalScope;
     79   if (S_OK != Session->get_globalScope(&GlobalScope))
     80     return nullptr;
     81 
     82   auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, GlobalScope);
     83   auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
     84   std::unique_ptr<PDBSymbolExe> ExeSymbol(
     85       static_cast<PDBSymbolExe *>(PdbSymbol.release()));
     86   return ExeSymbol;
     87 }
     88 
     89 std::unique_ptr<PDBSymbol> DIASession::getSymbolById(uint32_t SymbolId) const {
     90   CComPtr<IDiaSymbol> LocatedSymbol;
     91   if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol))
     92     return nullptr;
     93 
     94   auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, LocatedSymbol);
     95   return PDBSymbol::create(*this, std::move(RawSymbol));
     96 }
     97 
     98 std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const {
     99   CComPtr<IDiaEnumSourceFiles> Files;
    100   if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files))
    101     return nullptr;
    102 
    103   return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
    104 }
    105 
    106 std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland(
    107     const PDBSymbolCompiland &Compiland) const {
    108   CComPtr<IDiaEnumSourceFiles> Files;
    109 
    110   const DIARawSymbol &RawSymbol =
    111       static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
    112   if (S_OK !=
    113       Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files))
    114     return nullptr;
    115 
    116   return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
    117 }
    118 
    119 std::unique_ptr<IPDBSourceFile>
    120 DIASession::getSourceFileById(uint32_t FileId) const {
    121   CComPtr<IDiaSourceFile> LocatedFile;
    122   if (S_OK != Session->findFileById(FileId, &LocatedFile))
    123     return nullptr;
    124 
    125   return llvm::make_unique<DIASourceFile>(*this, LocatedFile);
    126 }
    127 
    128 std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const {
    129   CComPtr<IDiaEnumDebugStreams> DiaEnumerator;
    130   if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator))
    131     return nullptr;
    132 
    133   return llvm::make_unique<DIAEnumDebugStreams>(DiaEnumerator);
    134 }
    135