blob: 99fe750ebac635c456a3ab72ccf5da9655c58239 [file] [log] [blame]
Zachary Turnercffff262015-02-10 21:17:52 +00001//===- 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
Zachary Turnerbe6d1e42015-02-10 23:46:48 +000010#include "llvm/ADT/STLExtras.h"
Zachary Turnercffff262015-02-10 21:17:52 +000011#include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h"
Zachary Turner4b083542015-04-17 22:40:36 +000012#include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
Zachary Turnera5549172015-02-10 22:43:25 +000013#include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
Zachary Turnercffff262015-02-10 21:17:52 +000014#include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
15#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
16#include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
Chandler Carruth71f308a2015-02-13 09:09:03 +000017#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
18#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
Zachary Turnercffff262015-02-10 21:17:52 +000019#include "llvm/Support/ConvertUTF.h"
20
21using namespace llvm;
22
23namespace {}
24
25DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
26
Zachary Turnerccf04152015-02-28 20:23:18 +000027PDB_ErrorCode DIASession::createFromPdb(StringRef Path,
28 std::unique_ptr<IPDBSession> &Session) {
29 CComPtr<IDiaDataSource> DiaDataSource;
30 CComPtr<IDiaSession> DiaSession;
Zachary Turnercffff262015-02-10 21:17:52 +000031
32 // We assume that CoInitializeEx has already been called by the executable.
Zachary Turnerccf04152015-02-28 20:23:18 +000033 HRESULT Result = ::CoCreateInstance(
34 CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource,
35 reinterpret_cast<LPVOID *>(&DiaDataSource));
Zachary Turnercffff262015-02-10 21:17:52 +000036 if (FAILED(Result))
Zachary Turnerccf04152015-02-28 20:23:18 +000037 return PDB_ErrorCode::NoPdbImpl;
Zachary Turnercffff262015-02-10 21:17:52 +000038
39 llvm::SmallVector<UTF16, 128> Path16;
40 if (!llvm::convertUTF8ToUTF16String(Path, Path16))
Zachary Turnerccf04152015-02-28 20:23:18 +000041 return PDB_ErrorCode::InvalidPath;
Zachary Turnercffff262015-02-10 21:17:52 +000042
43 const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data());
Zachary Turnerccf04152015-02-28 20:23:18 +000044 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 }
Zachary Turnercffff262015-02-10 21:17:52 +000056
Zachary Turnerccf04152015-02-28 20:23:18 +000057 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;
Zachary Turnercffff262015-02-10 21:17:52 +000066}
67
Zachary Turner4b083542015-04-17 22:40:36 +000068PDB_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
Zachary Turnercffff262015-02-10 21:17:52 +0000112uint64_t DIASession::getLoadAddress() const {
113 uint64_t LoadAddress;
114 bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
115 return (success) ? LoadAddress : 0;
116}
117
118void DIASession::setLoadAddress(uint64_t Address) {
119 Session->put_loadAddress(Address);
120}
121
122std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() const {
123 CComPtr<IDiaSymbol> GlobalScope;
124 if (S_OK != Session->get_globalScope(&GlobalScope))
125 return nullptr;
126
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000127 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, GlobalScope);
Zachary Turnercffff262015-02-10 21:17:52 +0000128 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
134std::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
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000139 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, LocatedSymbol);
Zachary Turnercffff262015-02-10 21:17:52 +0000140 return PDBSymbol::create(*this, std::move(RawSymbol));
141}
142
Zachary Turner4b083542015-04-17 22:40:36 +0000143std::unique_ptr<PDBSymbol>
Zachary Turnere5cb2692015-05-01 20:24:26 +0000144DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
145 enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
146
Zachary Turner4b083542015-04-17 22:40:36 +0000147 CComPtr<IDiaSymbol> Symbol;
Zachary Turnere5cb2692015-05-01 20:24:26 +0000148 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 }
Zachary Turner4b083542015-04-17 22:40:36 +0000156 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
157 return PDBSymbol::create(*this, std::move(RawSymbol));
158}
159
160std::unique_ptr<IPDBEnumLineNumbers>
161DIASession::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
Zachary Turnera5549172015-02-10 22:43:25 +0000169std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const {
170 CComPtr<IDiaEnumSourceFiles> Files;
171 if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files))
172 return nullptr;
173
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000174 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
Zachary Turnera5549172015-02-10 22:43:25 +0000175}
176
177std::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
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000187 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
Zachary Turnera5549172015-02-10 22:43:25 +0000188}
189
Zachary Turnercffff262015-02-10 21:17:52 +0000190std::unique_ptr<IPDBSourceFile>
191DIASession::getSourceFileById(uint32_t FileId) const {
192 CComPtr<IDiaSourceFile> LocatedFile;
193 if (S_OK != Session->findFileById(FileId, &LocatedFile))
194 return nullptr;
195
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000196 return llvm::make_unique<DIASourceFile>(*this, LocatedFile);
Zachary Turnercffff262015-02-10 21:17:52 +0000197}
198
199std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const {
200 CComPtr<IDiaEnumDebugStreams> DiaEnumerator;
201 if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator))
202 return nullptr;
203
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000204 return llvm::make_unique<DIAEnumDebugStreams>(DiaEnumerator);
Zachary Turnercffff262015-02-10 21:17:52 +0000205}