1*307f5ae8SZachary Turner //===-- SymbolFileNativePDB.cpp ---------------------------------*- C++ -*-===//
2*307f5ae8SZachary Turner //
3*307f5ae8SZachary Turner //                     The LLVM Compiler Infrastructure
4*307f5ae8SZachary Turner //
5*307f5ae8SZachary Turner // This file is distributed under the University of Illinois Open Source
6*307f5ae8SZachary Turner // License. See LICENSE.TXT for details.
7*307f5ae8SZachary Turner //
8*307f5ae8SZachary Turner //===----------------------------------------------------------------------===//
9*307f5ae8SZachary Turner 
10*307f5ae8SZachary Turner #include "SymbolFileNativePDB.h"
11*307f5ae8SZachary Turner 
12*307f5ae8SZachary Turner #include "clang/Lex/Lexer.h"
13*307f5ae8SZachary Turner 
14*307f5ae8SZachary Turner #include "lldb/Core/Module.h"
15*307f5ae8SZachary Turner #include "lldb/Core/PluginManager.h"
16*307f5ae8SZachary Turner #include "lldb/Symbol/CompileUnit.h"
17*307f5ae8SZachary Turner #include "lldb/Symbol/LineTable.h"
18*307f5ae8SZachary Turner #include "lldb/Symbol/ObjectFile.h"
19*307f5ae8SZachary Turner #include "lldb/Symbol/SymbolContext.h"
20*307f5ae8SZachary Turner #include "lldb/Symbol/SymbolVendor.h"
21*307f5ae8SZachary Turner 
22*307f5ae8SZachary Turner #include "llvm/DebugInfo/CodeView/CVRecord.h"
23*307f5ae8SZachary Turner #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
24*307f5ae8SZachary Turner #include "llvm/DebugInfo/CodeView/RecordName.h"
25*307f5ae8SZachary Turner #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
26*307f5ae8SZachary Turner #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
27*307f5ae8SZachary Turner #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
28*307f5ae8SZachary Turner #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
29*307f5ae8SZachary Turner #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
30*307f5ae8SZachary Turner #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
31*307f5ae8SZachary Turner #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
32*307f5ae8SZachary Turner #include "llvm/DebugInfo/PDB/PDBTypes.h"
33*307f5ae8SZachary Turner #include "llvm/Object/COFF.h"
34*307f5ae8SZachary Turner #include "llvm/Support/Allocator.h"
35*307f5ae8SZachary Turner #include "llvm/Support/BinaryStreamReader.h"
36*307f5ae8SZachary Turner #include "llvm/Support/ErrorOr.h"
37*307f5ae8SZachary Turner #include "llvm/Support/MemoryBuffer.h"
38*307f5ae8SZachary Turner 
39*307f5ae8SZachary Turner #include "PdbSymUid.h"
40*307f5ae8SZachary Turner #include "PdbUtil.h"
41*307f5ae8SZachary Turner 
42*307f5ae8SZachary Turner using namespace lldb;
43*307f5ae8SZachary Turner using namespace lldb_private;
44*307f5ae8SZachary Turner using namespace lldb_private::npdb;
45*307f5ae8SZachary Turner using namespace llvm::codeview;
46*307f5ae8SZachary Turner using namespace llvm::pdb;
47*307f5ae8SZachary Turner 
48*307f5ae8SZachary Turner static lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
49*307f5ae8SZachary Turner   switch (lang) {
50*307f5ae8SZachary Turner   case PDB_Lang::Cpp:
51*307f5ae8SZachary Turner     return lldb::LanguageType::eLanguageTypeC_plus_plus;
52*307f5ae8SZachary Turner   case PDB_Lang::C:
53*307f5ae8SZachary Turner     return lldb::LanguageType::eLanguageTypeC;
54*307f5ae8SZachary Turner   default:
55*307f5ae8SZachary Turner     return lldb::LanguageType::eLanguageTypeUnknown;
56*307f5ae8SZachary Turner   }
57*307f5ae8SZachary Turner }
58*307f5ae8SZachary Turner 
59*307f5ae8SZachary Turner static std::unique_ptr<PDBFile> loadPDBFile(std::string PdbPath,
60*307f5ae8SZachary Turner                                             llvm::BumpPtrAllocator &Allocator) {
61*307f5ae8SZachary Turner   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer =
62*307f5ae8SZachary Turner       llvm::MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1,
63*307f5ae8SZachary Turner                                   /*RequiresNullTerminator=*/false);
64*307f5ae8SZachary Turner   if (!ErrorOrBuffer)
65*307f5ae8SZachary Turner     return nullptr;
66*307f5ae8SZachary Turner   std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
67*307f5ae8SZachary Turner 
68*307f5ae8SZachary Turner   llvm::StringRef Path = Buffer->getBufferIdentifier();
69*307f5ae8SZachary Turner   auto Stream = llvm::make_unique<llvm::MemoryBufferByteStream>(
70*307f5ae8SZachary Turner       std::move(Buffer), llvm::support::little);
71*307f5ae8SZachary Turner 
72*307f5ae8SZachary Turner   auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), Allocator);
73*307f5ae8SZachary Turner   if (auto EC = File->parseFileHeaders())
74*307f5ae8SZachary Turner     return nullptr;
75*307f5ae8SZachary Turner   if (auto EC = File->parseStreamData())
76*307f5ae8SZachary Turner     return nullptr;
77*307f5ae8SZachary Turner 
78*307f5ae8SZachary Turner   return File;
79*307f5ae8SZachary Turner }
80*307f5ae8SZachary Turner 
81*307f5ae8SZachary Turner static std::unique_ptr<PDBFile>
82*307f5ae8SZachary Turner loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
83*307f5ae8SZachary Turner   // Try to find a matching PDB for an EXE.
84*307f5ae8SZachary Turner   using namespace llvm::object;
85*307f5ae8SZachary Turner   auto expected_binary = createBinary(exe_path);
86*307f5ae8SZachary Turner 
87*307f5ae8SZachary Turner   // If the file isn't a PE/COFF executable, fail.
88*307f5ae8SZachary Turner   if (!expected_binary) {
89*307f5ae8SZachary Turner     llvm::consumeError(expected_binary.takeError());
90*307f5ae8SZachary Turner     return nullptr;
91*307f5ae8SZachary Turner   }
92*307f5ae8SZachary Turner   OwningBinary<Binary> binary = std::move(*expected_binary);
93*307f5ae8SZachary Turner 
94*307f5ae8SZachary Turner   auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary());
95*307f5ae8SZachary Turner   if (!obj)
96*307f5ae8SZachary Turner     return nullptr;
97*307f5ae8SZachary Turner   const llvm::codeview::DebugInfo *pdb_info = nullptr;
98*307f5ae8SZachary Turner 
99*307f5ae8SZachary Turner   // If it doesn't have a debug directory, fail.
100*307f5ae8SZachary Turner   llvm::StringRef pdb_file;
101*307f5ae8SZachary Turner   auto ec = obj->getDebugPDBInfo(pdb_info, pdb_file);
102*307f5ae8SZachary Turner   if (ec)
103*307f5ae8SZachary Turner     return nullptr;
104*307f5ae8SZachary Turner 
105*307f5ae8SZachary Turner   // if the file doesn't exist, is not a pdb, or doesn't have a matching guid,
106*307f5ae8SZachary Turner   // fail.
107*307f5ae8SZachary Turner   llvm::file_magic magic;
108*307f5ae8SZachary Turner   ec = llvm::identify_magic(pdb_file, magic);
109*307f5ae8SZachary Turner   if (ec || magic != llvm::file_magic::pdb)
110*307f5ae8SZachary Turner     return nullptr;
111*307f5ae8SZachary Turner   std::unique_ptr<PDBFile> pdb = loadPDBFile(pdb_file, allocator);
112*307f5ae8SZachary Turner   auto expected_info = pdb->getPDBInfoStream();
113*307f5ae8SZachary Turner   if (!expected_info) {
114*307f5ae8SZachary Turner     llvm::consumeError(expected_info.takeError());
115*307f5ae8SZachary Turner     return nullptr;
116*307f5ae8SZachary Turner   }
117*307f5ae8SZachary Turner   llvm::codeview::GUID guid;
118*307f5ae8SZachary Turner   memcpy(&guid, pdb_info->PDB70.Signature, 16);
119*307f5ae8SZachary Turner 
120*307f5ae8SZachary Turner   if (expected_info->getGuid() != guid)
121*307f5ae8SZachary Turner     return nullptr;
122*307f5ae8SZachary Turner   return pdb;
123*307f5ae8SZachary Turner }
124*307f5ae8SZachary Turner 
125*307f5ae8SZachary Turner static bool IsFunctionPrologue(const CompilandIndexItem &cci,
126*307f5ae8SZachary Turner                                lldb::addr_t addr) {
127*307f5ae8SZachary Turner   // FIXME: Implement this.
128*307f5ae8SZachary Turner   return false;
129*307f5ae8SZachary Turner }
130*307f5ae8SZachary Turner 
131*307f5ae8SZachary Turner static bool IsFunctionEpilogue(const CompilandIndexItem &cci,
132*307f5ae8SZachary Turner                                lldb::addr_t addr) {
133*307f5ae8SZachary Turner   // FIXME: Implement this.
134*307f5ae8SZachary Turner   return false;
135*307f5ae8SZachary Turner }
136*307f5ae8SZachary Turner 
137*307f5ae8SZachary Turner void SymbolFileNativePDB::Initialize() {
138*307f5ae8SZachary Turner   PluginManager::RegisterPlugin(GetPluginNameStatic(),
139*307f5ae8SZachary Turner                                 GetPluginDescriptionStatic(), CreateInstance,
140*307f5ae8SZachary Turner                                 DebuggerInitialize);
141*307f5ae8SZachary Turner }
142*307f5ae8SZachary Turner 
143*307f5ae8SZachary Turner void SymbolFileNativePDB::Terminate() {
144*307f5ae8SZachary Turner   PluginManager::UnregisterPlugin(CreateInstance);
145*307f5ae8SZachary Turner }
146*307f5ae8SZachary Turner 
147*307f5ae8SZachary Turner void SymbolFileNativePDB::DebuggerInitialize(lldb_private::Debugger &debugger) {
148*307f5ae8SZachary Turner }
149*307f5ae8SZachary Turner 
150*307f5ae8SZachary Turner lldb_private::ConstString SymbolFileNativePDB::GetPluginNameStatic() {
151*307f5ae8SZachary Turner   static ConstString g_name("native-pdb");
152*307f5ae8SZachary Turner   return g_name;
153*307f5ae8SZachary Turner }
154*307f5ae8SZachary Turner 
155*307f5ae8SZachary Turner const char *SymbolFileNativePDB::GetPluginDescriptionStatic() {
156*307f5ae8SZachary Turner   return "Microsoft PDB debug symbol cross-platform file reader.";
157*307f5ae8SZachary Turner }
158*307f5ae8SZachary Turner 
159*307f5ae8SZachary Turner lldb_private::SymbolFile *
160*307f5ae8SZachary Turner SymbolFileNativePDB::CreateInstance(lldb_private::ObjectFile *obj_file) {
161*307f5ae8SZachary Turner   return new SymbolFileNativePDB(obj_file);
162*307f5ae8SZachary Turner }
163*307f5ae8SZachary Turner 
164*307f5ae8SZachary Turner SymbolFileNativePDB::SymbolFileNativePDB(lldb_private::ObjectFile *object_file)
165*307f5ae8SZachary Turner     : SymbolFile(object_file) {}
166*307f5ae8SZachary Turner 
167*307f5ae8SZachary Turner SymbolFileNativePDB::~SymbolFileNativePDB() {}
168*307f5ae8SZachary Turner 
169*307f5ae8SZachary Turner uint32_t SymbolFileNativePDB::CalculateAbilities() {
170*307f5ae8SZachary Turner   uint32_t abilities = 0;
171*307f5ae8SZachary Turner   if (!m_obj_file)
172*307f5ae8SZachary Turner     return 0;
173*307f5ae8SZachary Turner 
174*307f5ae8SZachary Turner   if (!m_index) {
175*307f5ae8SZachary Turner     // Lazily load and match the PDB file, but only do this once.
176*307f5ae8SZachary Turner     std::unique_ptr<PDBFile> file_up =
177*307f5ae8SZachary Turner         loadMatchingPDBFile(m_obj_file->GetFileSpec().GetPath(), m_allocator);
178*307f5ae8SZachary Turner 
179*307f5ae8SZachary Turner     if (!file_up) {
180*307f5ae8SZachary Turner       auto module_sp = m_obj_file->GetModule();
181*307f5ae8SZachary Turner       if (!module_sp)
182*307f5ae8SZachary Turner         return 0;
183*307f5ae8SZachary Turner       // See if any symbol file is specified through `--symfile` option.
184*307f5ae8SZachary Turner       FileSpec symfile = module_sp->GetSymbolFileFileSpec();
185*307f5ae8SZachary Turner       if (!symfile)
186*307f5ae8SZachary Turner         return 0;
187*307f5ae8SZachary Turner       file_up = loadPDBFile(symfile.GetPath(), m_allocator);
188*307f5ae8SZachary Turner     }
189*307f5ae8SZachary Turner 
190*307f5ae8SZachary Turner     if (!file_up)
191*307f5ae8SZachary Turner       return 0;
192*307f5ae8SZachary Turner 
193*307f5ae8SZachary Turner     auto expected_index = PdbIndex::create(std::move(file_up));
194*307f5ae8SZachary Turner     if (!expected_index) {
195*307f5ae8SZachary Turner       llvm::consumeError(expected_index.takeError());
196*307f5ae8SZachary Turner       return 0;
197*307f5ae8SZachary Turner     }
198*307f5ae8SZachary Turner     m_index = std::move(*expected_index);
199*307f5ae8SZachary Turner   }
200*307f5ae8SZachary Turner   if (!m_index)
201*307f5ae8SZachary Turner     return 0;
202*307f5ae8SZachary Turner 
203*307f5ae8SZachary Turner   // We don't especially have to be precise here.  We only distinguish between
204*307f5ae8SZachary Turner   // stripped and not stripped.
205*307f5ae8SZachary Turner   abilities = kAllAbilities;
206*307f5ae8SZachary Turner 
207*307f5ae8SZachary Turner   if (m_index->dbi().isStripped())
208*307f5ae8SZachary Turner     abilities &= ~(Blocks | LocalVariables);
209*307f5ae8SZachary Turner   return abilities;
210*307f5ae8SZachary Turner }
211*307f5ae8SZachary Turner 
212*307f5ae8SZachary Turner void SymbolFileNativePDB::InitializeObject() {
213*307f5ae8SZachary Turner   m_obj_load_address = m_obj_file->GetFileOffset();
214*307f5ae8SZachary Turner   m_index->SetLoadAddress(m_obj_load_address);
215*307f5ae8SZachary Turner   m_index->ParseSectionContribs();
216*307f5ae8SZachary Turner }
217*307f5ae8SZachary Turner 
218*307f5ae8SZachary Turner uint32_t SymbolFileNativePDB::GetNumCompileUnits() {
219*307f5ae8SZachary Turner   const DbiModuleList &modules = m_index->dbi().modules();
220*307f5ae8SZachary Turner   uint32_t count = modules.getModuleCount();
221*307f5ae8SZachary Turner   if (count == 0)
222*307f5ae8SZachary Turner     return count;
223*307f5ae8SZachary Turner 
224*307f5ae8SZachary Turner   // The linker can inject an additional "dummy" compilation unit into the
225*307f5ae8SZachary Turner   // PDB. Ignore this special compile unit for our purposes, if it is there.
226*307f5ae8SZachary Turner   // It is always the last one.
227*307f5ae8SZachary Turner   DbiModuleDescriptor last = modules.getModuleDescriptor(count - 1);
228*307f5ae8SZachary Turner   if (last.getModuleName() == "* Linker *")
229*307f5ae8SZachary Turner     --count;
230*307f5ae8SZachary Turner   return count;
231*307f5ae8SZachary Turner }
232*307f5ae8SZachary Turner 
233*307f5ae8SZachary Turner lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbSymUid func_uid,
234*307f5ae8SZachary Turner                                                      const SymbolContext &sc) {
235*307f5ae8SZachary Turner   lldbassert(func_uid.tag() == PDB_SymType::Function);
236*307f5ae8SZachary Turner 
237*307f5ae8SZachary Turner   PdbSymUid cuid = PdbSymUid::makeCompilandId(func_uid.asCuSym().modi);
238*307f5ae8SZachary Turner 
239*307f5ae8SZachary Turner   const CompilandIndexItem *cci = m_index->compilands().GetCompiland(cuid);
240*307f5ae8SZachary Turner   lldbassert(cci);
241*307f5ae8SZachary Turner   CVSymbol sym_record =
242*307f5ae8SZachary Turner       cci->m_debug_stream.readSymbolAtOffset(func_uid.asCuSym().offset);
243*307f5ae8SZachary Turner 
244*307f5ae8SZachary Turner   lldbassert(sym_record.kind() == S_LPROC32 || sym_record.kind() == S_GPROC32);
245*307f5ae8SZachary Turner   SegmentOffsetLength sol = GetSegmentOffsetAndLength(sym_record);
246*307f5ae8SZachary Turner 
247*307f5ae8SZachary Turner   auto file_vm_addr = m_index->MakeVirtualAddress(sol.so);
248*307f5ae8SZachary Turner   if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
249*307f5ae8SZachary Turner     return nullptr;
250*307f5ae8SZachary Turner 
251*307f5ae8SZachary Turner   AddressRange func_range(file_vm_addr, sol.length,
252*307f5ae8SZachary Turner                           sc.module_sp->GetSectionList());
253*307f5ae8SZachary Turner   if (!func_range.GetBaseAddress().IsValid())
254*307f5ae8SZachary Turner     return nullptr;
255*307f5ae8SZachary Turner 
256*307f5ae8SZachary Turner   lldb_private::Type *func_type = nullptr;
257*307f5ae8SZachary Turner 
258*307f5ae8SZachary Turner   // FIXME: Resolve types and mangled names.
259*307f5ae8SZachary Turner   PdbSymUid sig_uid =
260*307f5ae8SZachary Turner       PdbSymUid::makeTypeSymId(PDB_SymType::FunctionSig, TypeIndex{0}, false);
261*307f5ae8SZachary Turner   Mangled mangled(getSymbolName(sym_record));
262*307f5ae8SZachary Turner 
263*307f5ae8SZachary Turner   FunctionSP func_sp = std::make_shared<Function>(
264*307f5ae8SZachary Turner       sc.comp_unit, func_uid.toOpaqueId(), sig_uid.toOpaqueId(), mangled,
265*307f5ae8SZachary Turner       func_type, func_range);
266*307f5ae8SZachary Turner 
267*307f5ae8SZachary Turner   sc.comp_unit->AddFunction(func_sp);
268*307f5ae8SZachary Turner   return func_sp;
269*307f5ae8SZachary Turner }
270*307f5ae8SZachary Turner 
271*307f5ae8SZachary Turner CompUnitSP
272*307f5ae8SZachary Turner SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) {
273*307f5ae8SZachary Turner   lldb::LanguageType lang =
274*307f5ae8SZachary Turner       cci.m_compile_opts ? TranslateLanguage(cci.m_compile_opts->getLanguage())
275*307f5ae8SZachary Turner                          : lldb::eLanguageTypeUnknown;
276*307f5ae8SZachary Turner 
277*307f5ae8SZachary Turner   LazyBool optimized = eLazyBoolNo;
278*307f5ae8SZachary Turner   if (cci.m_compile_opts && cci.m_compile_opts->hasOptimizations())
279*307f5ae8SZachary Turner     optimized = eLazyBoolYes;
280*307f5ae8SZachary Turner 
281*307f5ae8SZachary Turner   llvm::StringRef source_file_name =
282*307f5ae8SZachary Turner       m_index->compilands().GetMainSourceFile(cci);
283*307f5ae8SZachary Turner   lldb_private::FileSpec fs(source_file_name, false);
284*307f5ae8SZachary Turner 
285*307f5ae8SZachary Turner   CompUnitSP cu_sp =
286*307f5ae8SZachary Turner       std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr, fs,
287*307f5ae8SZachary Turner                                     cci.m_uid.toOpaqueId(), lang, optimized);
288*307f5ae8SZachary Turner 
289*307f5ae8SZachary Turner   const PdbCompilandId &cuid = cci.m_uid.asCompiland();
290*307f5ae8SZachary Turner   m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(cuid.modi,
291*307f5ae8SZachary Turner                                                                     cu_sp);
292*307f5ae8SZachary Turner   return cu_sp;
293*307f5ae8SZachary Turner }
294*307f5ae8SZachary Turner 
295*307f5ae8SZachary Turner FunctionSP SymbolFileNativePDB::GetOrCreateFunction(PdbSymUid func_uid,
296*307f5ae8SZachary Turner                                                     const SymbolContext &sc) {
297*307f5ae8SZachary Turner   lldbassert(func_uid.tag() == PDB_SymType::Function);
298*307f5ae8SZachary Turner   auto emplace_result = m_functions.try_emplace(func_uid.toOpaqueId(), nullptr);
299*307f5ae8SZachary Turner   if (emplace_result.second)
300*307f5ae8SZachary Turner     emplace_result.first->second = CreateFunction(func_uid, sc);
301*307f5ae8SZachary Turner 
302*307f5ae8SZachary Turner   lldbassert(emplace_result.first->second);
303*307f5ae8SZachary Turner   return emplace_result.first->second;
304*307f5ae8SZachary Turner }
305*307f5ae8SZachary Turner 
306*307f5ae8SZachary Turner CompUnitSP
307*307f5ae8SZachary Turner SymbolFileNativePDB::GetOrCreateCompileUnit(const CompilandIndexItem &cci) {
308*307f5ae8SZachary Turner   auto emplace_result =
309*307f5ae8SZachary Turner       m_compilands.try_emplace(cci.m_uid.toOpaqueId(), nullptr);
310*307f5ae8SZachary Turner   if (emplace_result.second)
311*307f5ae8SZachary Turner     emplace_result.first->second = CreateCompileUnit(cci);
312*307f5ae8SZachary Turner 
313*307f5ae8SZachary Turner   lldbassert(emplace_result.first->second);
314*307f5ae8SZachary Turner   return emplace_result.first->second;
315*307f5ae8SZachary Turner }
316*307f5ae8SZachary Turner 
317*307f5ae8SZachary Turner lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) {
318*307f5ae8SZachary Turner   if (index >= GetNumCompileUnits())
319*307f5ae8SZachary Turner     return CompUnitSP();
320*307f5ae8SZachary Turner   lldbassert(index < UINT16_MAX);
321*307f5ae8SZachary Turner   if (index >= UINT16_MAX)
322*307f5ae8SZachary Turner     return nullptr;
323*307f5ae8SZachary Turner 
324*307f5ae8SZachary Turner   CompilandIndexItem &item = m_index->compilands().GetOrCreateCompiland(index);
325*307f5ae8SZachary Turner 
326*307f5ae8SZachary Turner   return GetOrCreateCompileUnit(item);
327*307f5ae8SZachary Turner }
328*307f5ae8SZachary Turner 
329*307f5ae8SZachary Turner lldb::LanguageType SymbolFileNativePDB::ParseCompileUnitLanguage(
330*307f5ae8SZachary Turner     const lldb_private::SymbolContext &sc) {
331*307f5ae8SZachary Turner   // What fields should I expect to be filled out on the SymbolContext?  Is it
332*307f5ae8SZachary Turner   // safe to assume that `sc.comp_unit` is valid?
333*307f5ae8SZachary Turner   if (!sc.comp_unit)
334*307f5ae8SZachary Turner     return lldb::eLanguageTypeUnknown;
335*307f5ae8SZachary Turner   PdbSymUid uid = PdbSymUid::fromOpaqueId(sc.comp_unit->GetID());
336*307f5ae8SZachary Turner   lldbassert(uid.tag() == PDB_SymType::Compiland);
337*307f5ae8SZachary Turner 
338*307f5ae8SZachary Turner   CompilandIndexItem *item = m_index->compilands().GetCompiland(uid);
339*307f5ae8SZachary Turner   lldbassert(item);
340*307f5ae8SZachary Turner   if (!item->m_compile_opts)
341*307f5ae8SZachary Turner     return lldb::eLanguageTypeUnknown;
342*307f5ae8SZachary Turner 
343*307f5ae8SZachary Turner   return TranslateLanguage(item->m_compile_opts->getLanguage());
344*307f5ae8SZachary Turner }
345*307f5ae8SZachary Turner 
346*307f5ae8SZachary Turner size_t SymbolFileNativePDB::ParseCompileUnitFunctions(
347*307f5ae8SZachary Turner     const lldb_private::SymbolContext &sc) {
348*307f5ae8SZachary Turner   lldbassert(sc.comp_unit);
349*307f5ae8SZachary Turner   return false;
350*307f5ae8SZachary Turner }
351*307f5ae8SZachary Turner 
352*307f5ae8SZachary Turner static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) {
353*307f5ae8SZachary Turner   // If any of these flags are set, we need to resolve the compile unit.
354*307f5ae8SZachary Turner   uint32_t flags = eSymbolContextCompUnit;
355*307f5ae8SZachary Turner   flags |= eSymbolContextVariable;
356*307f5ae8SZachary Turner   flags |= eSymbolContextFunction;
357*307f5ae8SZachary Turner   flags |= eSymbolContextBlock;
358*307f5ae8SZachary Turner   flags |= eSymbolContextLineEntry;
359*307f5ae8SZachary Turner   return (resolve_scope & flags) != 0;
360*307f5ae8SZachary Turner }
361*307f5ae8SZachary Turner 
362*307f5ae8SZachary Turner uint32_t
363*307f5ae8SZachary Turner SymbolFileNativePDB::ResolveSymbolContext(const lldb_private::Address &addr,
364*307f5ae8SZachary Turner                                           uint32_t resolve_scope,
365*307f5ae8SZachary Turner                                           lldb_private::SymbolContext &sc) {
366*307f5ae8SZachary Turner   uint32_t resolved_flags = 0;
367*307f5ae8SZachary Turner   lldb::addr_t file_addr = addr.GetFileAddress();
368*307f5ae8SZachary Turner 
369*307f5ae8SZachary Turner   if (NeedsResolvedCompileUnit(resolve_scope)) {
370*307f5ae8SZachary Turner     llvm::Optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr);
371*307f5ae8SZachary Turner     if (!modi)
372*307f5ae8SZachary Turner       return 0;
373*307f5ae8SZachary Turner     PdbSymUid cuid = PdbSymUid::makeCompilandId(*modi);
374*307f5ae8SZachary Turner     CompilandIndexItem *cci = m_index->compilands().GetCompiland(cuid);
375*307f5ae8SZachary Turner     if (!cci)
376*307f5ae8SZachary Turner       return 0;
377*307f5ae8SZachary Turner 
378*307f5ae8SZachary Turner     sc.comp_unit = GetOrCreateCompileUnit(*cci).get();
379*307f5ae8SZachary Turner     resolved_flags |= eSymbolContextCompUnit;
380*307f5ae8SZachary Turner   }
381*307f5ae8SZachary Turner 
382*307f5ae8SZachary Turner   if (resolve_scope & eSymbolContextFunction) {
383*307f5ae8SZachary Turner     lldbassert(sc.comp_unit);
384*307f5ae8SZachary Turner     std::vector<SymbolAndUid> matches = m_index->FindSymbolsByVa(file_addr);
385*307f5ae8SZachary Turner     for (const auto &match : matches) {
386*307f5ae8SZachary Turner       if (match.uid.tag() != PDB_SymType::Function)
387*307f5ae8SZachary Turner         continue;
388*307f5ae8SZachary Turner       sc.function = GetOrCreateFunction(match.uid, sc).get();
389*307f5ae8SZachary Turner     }
390*307f5ae8SZachary Turner     resolved_flags |= eSymbolContextFunction;
391*307f5ae8SZachary Turner   }
392*307f5ae8SZachary Turner 
393*307f5ae8SZachary Turner   if (resolve_scope & eSymbolContextLineEntry) {
394*307f5ae8SZachary Turner     lldbassert(sc.comp_unit);
395*307f5ae8SZachary Turner     if (auto *line_table = sc.comp_unit->GetLineTable()) {
396*307f5ae8SZachary Turner       if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
397*307f5ae8SZachary Turner         resolved_flags |= eSymbolContextLineEntry;
398*307f5ae8SZachary Turner     }
399*307f5ae8SZachary Turner   }
400*307f5ae8SZachary Turner 
401*307f5ae8SZachary Turner   return resolved_flags;
402*307f5ae8SZachary Turner }
403*307f5ae8SZachary Turner 
404*307f5ae8SZachary Turner static void AppendLineEntryToSequence(LineTable &table, LineSequence &sequence,
405*307f5ae8SZachary Turner                                       const CompilandIndexItem &cci,
406*307f5ae8SZachary Turner                                       lldb::addr_t base_addr,
407*307f5ae8SZachary Turner                                       uint32_t file_number,
408*307f5ae8SZachary Turner                                       const LineFragmentHeader &block,
409*307f5ae8SZachary Turner                                       const LineNumberEntry &cur) {
410*307f5ae8SZachary Turner   LineInfo cur_info(cur.Flags);
411*307f5ae8SZachary Turner 
412*307f5ae8SZachary Turner   if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto())
413*307f5ae8SZachary Turner     return;
414*307f5ae8SZachary Turner 
415*307f5ae8SZachary Turner   uint64_t addr = base_addr + cur.Offset;
416*307f5ae8SZachary Turner 
417*307f5ae8SZachary Turner   bool is_statement = cur_info.isStatement();
418*307f5ae8SZachary Turner   bool is_prologue = IsFunctionPrologue(cci, addr);
419*307f5ae8SZachary Turner   bool is_epilogue = IsFunctionEpilogue(cci, addr);
420*307f5ae8SZachary Turner 
421*307f5ae8SZachary Turner   uint32_t lno = cur_info.getStartLine();
422*307f5ae8SZachary Turner 
423*307f5ae8SZachary Turner   table.AppendLineEntryToSequence(&sequence, addr, lno, 0, file_number,
424*307f5ae8SZachary Turner                                   is_statement, false, is_prologue, is_epilogue,
425*307f5ae8SZachary Turner                                   false);
426*307f5ae8SZachary Turner }
427*307f5ae8SZachary Turner 
428*307f5ae8SZachary Turner static void TerminateLineSequence(LineTable &table,
429*307f5ae8SZachary Turner                                   const LineFragmentHeader &block,
430*307f5ae8SZachary Turner                                   lldb::addr_t base_addr, uint32_t file_number,
431*307f5ae8SZachary Turner                                   uint32_t last_line,
432*307f5ae8SZachary Turner                                   std::unique_ptr<LineSequence> seq) {
433*307f5ae8SZachary Turner   // The end is always a terminal entry, so insert it regardless.
434*307f5ae8SZachary Turner   table.AppendLineEntryToSequence(seq.get(), base_addr + block.CodeSize,
435*307f5ae8SZachary Turner                                   last_line, 0, file_number, false, false,
436*307f5ae8SZachary Turner                                   false, false, true);
437*307f5ae8SZachary Turner   table.InsertSequence(seq.release());
438*307f5ae8SZachary Turner }
439*307f5ae8SZachary Turner 
440*307f5ae8SZachary Turner bool SymbolFileNativePDB::ParseCompileUnitLineTable(
441*307f5ae8SZachary Turner     const lldb_private::SymbolContext &sc) {
442*307f5ae8SZachary Turner   // Unfortunately LLDB is set up to parse the entire compile unit line table
443*307f5ae8SZachary Turner   // all at once, even if all it really needs is line info for a specific
444*307f5ae8SZachary Turner   // function.  In the future it would be nice if it could set the sc.m_function
445*307f5ae8SZachary Turner   // member, and we could only get the line info for the function in question.
446*307f5ae8SZachary Turner   lldbassert(sc.comp_unit);
447*307f5ae8SZachary Turner   PdbSymUid cu_id = PdbSymUid::fromOpaqueId(sc.comp_unit->GetID());
448*307f5ae8SZachary Turner   lldbassert(cu_id.isCompiland());
449*307f5ae8SZachary Turner   CompilandIndexItem *cci = m_index->compilands().GetCompiland(cu_id);
450*307f5ae8SZachary Turner   lldbassert(cci);
451*307f5ae8SZachary Turner   auto line_table = llvm::make_unique<LineTable>(sc.comp_unit);
452*307f5ae8SZachary Turner 
453*307f5ae8SZachary Turner   // This is basically a copy of the .debug$S subsections from all original COFF
454*307f5ae8SZachary Turner   // object files merged together with address relocations applied.  We are
455*307f5ae8SZachary Turner   // looking for all DEBUG_S_LINES subsections.
456*307f5ae8SZachary Turner   for (const DebugSubsectionRecord &dssr :
457*307f5ae8SZachary Turner        cci->m_debug_stream.getSubsectionsArray()) {
458*307f5ae8SZachary Turner     if (dssr.kind() != DebugSubsectionKind::Lines)
459*307f5ae8SZachary Turner       continue;
460*307f5ae8SZachary Turner 
461*307f5ae8SZachary Turner     DebugLinesSubsectionRef lines;
462*307f5ae8SZachary Turner     llvm::BinaryStreamReader reader(dssr.getRecordData());
463*307f5ae8SZachary Turner     if (auto EC = lines.initialize(reader)) {
464*307f5ae8SZachary Turner       llvm::consumeError(std::move(EC));
465*307f5ae8SZachary Turner       return false;
466*307f5ae8SZachary Turner     }
467*307f5ae8SZachary Turner 
468*307f5ae8SZachary Turner     const LineFragmentHeader *lfh = lines.header();
469*307f5ae8SZachary Turner     uint64_t virtual_addr =
470*307f5ae8SZachary Turner         m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset);
471*307f5ae8SZachary Turner 
472*307f5ae8SZachary Turner     const auto &checksums = cci->m_strings.checksums().getArray();
473*307f5ae8SZachary Turner     const auto &strings = cci->m_strings.strings();
474*307f5ae8SZachary Turner     for (const LineColumnEntry &group : lines) {
475*307f5ae8SZachary Turner       // Indices in this structure are actually offsets of records in the
476*307f5ae8SZachary Turner       // DEBUG_S_FILECHECKSUMS subsection.  Those entries then have an index
477*307f5ae8SZachary Turner       // into the global PDB string table.
478*307f5ae8SZachary Turner       auto iter = checksums.at(group.NameIndex);
479*307f5ae8SZachary Turner       if (iter == checksums.end())
480*307f5ae8SZachary Turner         continue;
481*307f5ae8SZachary Turner 
482*307f5ae8SZachary Turner       llvm::Expected<llvm::StringRef> efn =
483*307f5ae8SZachary Turner           strings.getString(iter->FileNameOffset);
484*307f5ae8SZachary Turner       if (!efn) {
485*307f5ae8SZachary Turner         llvm::consumeError(efn.takeError());
486*307f5ae8SZachary Turner         continue;
487*307f5ae8SZachary Turner       }
488*307f5ae8SZachary Turner 
489*307f5ae8SZachary Turner       // LLDB wants the index of the file in the list of support files.
490*307f5ae8SZachary Turner       auto fn_iter = llvm::find(cci->m_file_list, *efn);
491*307f5ae8SZachary Turner       lldbassert(fn_iter != cci->m_file_list.end());
492*307f5ae8SZachary Turner       uint32_t file_index = std::distance(cci->m_file_list.begin(), fn_iter);
493*307f5ae8SZachary Turner 
494*307f5ae8SZachary Turner       std::unique_ptr<LineSequence> sequence(
495*307f5ae8SZachary Turner           line_table->CreateLineSequenceContainer());
496*307f5ae8SZachary Turner       lldbassert(!group.LineNumbers.empty());
497*307f5ae8SZachary Turner 
498*307f5ae8SZachary Turner       for (const LineNumberEntry &entry : group.LineNumbers) {
499*307f5ae8SZachary Turner         AppendLineEntryToSequence(*line_table, *sequence, *cci, virtual_addr,
500*307f5ae8SZachary Turner                                   file_index, *lfh, entry);
501*307f5ae8SZachary Turner       }
502*307f5ae8SZachary Turner       LineInfo last_line(group.LineNumbers.back().Flags);
503*307f5ae8SZachary Turner       TerminateLineSequence(*line_table, *lfh, virtual_addr, file_index,
504*307f5ae8SZachary Turner                             last_line.getEndLine(), std::move(sequence));
505*307f5ae8SZachary Turner     }
506*307f5ae8SZachary Turner   }
507*307f5ae8SZachary Turner 
508*307f5ae8SZachary Turner   if (line_table->GetSize() == 0)
509*307f5ae8SZachary Turner     return false;
510*307f5ae8SZachary Turner 
511*307f5ae8SZachary Turner   sc.comp_unit->SetLineTable(line_table.release());
512*307f5ae8SZachary Turner   return true;
513*307f5ae8SZachary Turner }
514*307f5ae8SZachary Turner 
515*307f5ae8SZachary Turner bool SymbolFileNativePDB::ParseCompileUnitDebugMacros(
516*307f5ae8SZachary Turner     const lldb_private::SymbolContext &sc) {
517*307f5ae8SZachary Turner   // PDB doesn't contain information about macros
518*307f5ae8SZachary Turner   return false;
519*307f5ae8SZachary Turner }
520*307f5ae8SZachary Turner 
521*307f5ae8SZachary Turner bool SymbolFileNativePDB::ParseCompileUnitSupportFiles(
522*307f5ae8SZachary Turner     const lldb_private::SymbolContext &sc,
523*307f5ae8SZachary Turner     lldb_private::FileSpecList &support_files) {
524*307f5ae8SZachary Turner   lldbassert(sc.comp_unit);
525*307f5ae8SZachary Turner 
526*307f5ae8SZachary Turner   PdbSymUid comp_uid = PdbSymUid::fromOpaqueId(sc.comp_unit->GetID());
527*307f5ae8SZachary Turner   lldbassert(comp_uid.tag() == PDB_SymType::Compiland);
528*307f5ae8SZachary Turner 
529*307f5ae8SZachary Turner   const CompilandIndexItem *cci = m_index->compilands().GetCompiland(comp_uid);
530*307f5ae8SZachary Turner   lldbassert(cci);
531*307f5ae8SZachary Turner 
532*307f5ae8SZachary Turner   for (llvm::StringRef f : cci->m_file_list) {
533*307f5ae8SZachary Turner     FileSpec::Style style =
534*307f5ae8SZachary Turner         f.startswith("/") ? FileSpec::Style::posix : FileSpec::Style::windows;
535*307f5ae8SZachary Turner     FileSpec spec(f, false, style);
536*307f5ae8SZachary Turner     support_files.Append(spec);
537*307f5ae8SZachary Turner   }
538*307f5ae8SZachary Turner 
539*307f5ae8SZachary Turner   return true;
540*307f5ae8SZachary Turner }
541*307f5ae8SZachary Turner 
542*307f5ae8SZachary Turner bool SymbolFileNativePDB::ParseImportedModules(
543*307f5ae8SZachary Turner     const lldb_private::SymbolContext &sc,
544*307f5ae8SZachary Turner     std::vector<lldb_private::ConstString> &imported_modules) {
545*307f5ae8SZachary Turner   // PDB does not yet support module debug info
546*307f5ae8SZachary Turner   return false;
547*307f5ae8SZachary Turner }
548*307f5ae8SZachary Turner 
549*307f5ae8SZachary Turner size_t SymbolFileNativePDB::ParseFunctionBlocks(
550*307f5ae8SZachary Turner     const lldb_private::SymbolContext &sc) {
551*307f5ae8SZachary Turner   lldbassert(sc.comp_unit && sc.function);
552*307f5ae8SZachary Turner   return 0;
553*307f5ae8SZachary Turner }
554*307f5ae8SZachary Turner 
555*307f5ae8SZachary Turner uint32_t SymbolFileNativePDB::FindFunctions(
556*307f5ae8SZachary Turner     const lldb_private::ConstString &name,
557*307f5ae8SZachary Turner     const lldb_private::CompilerDeclContext *parent_decl_ctx,
558*307f5ae8SZachary Turner     uint32_t name_type_mask, bool include_inlines, bool append,
559*307f5ae8SZachary Turner     lldb_private::SymbolContextList &sc_list) {
560*307f5ae8SZachary Turner   // For now we only support lookup by method name.
561*307f5ae8SZachary Turner   if (!(name_type_mask & eFunctionNameTypeMethod))
562*307f5ae8SZachary Turner     return 0;
563*307f5ae8SZachary Turner 
564*307f5ae8SZachary Turner   using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;
565*307f5ae8SZachary Turner 
566*307f5ae8SZachary Turner   std::vector<SymbolAndOffset> matches = m_index->globals().findRecordsByName(
567*307f5ae8SZachary Turner       name.GetStringRef(), m_index->symrecords());
568*307f5ae8SZachary Turner   for (const SymbolAndOffset &match : matches) {
569*307f5ae8SZachary Turner     if (match.second.kind() != S_PROCREF && match.second.kind() != S_LPROCREF)
570*307f5ae8SZachary Turner       continue;
571*307f5ae8SZachary Turner     ProcRefSym proc(match.second.kind());
572*307f5ae8SZachary Turner     cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(match.second, proc));
573*307f5ae8SZachary Turner 
574*307f5ae8SZachary Turner     if (!IsValidRecord(proc))
575*307f5ae8SZachary Turner       continue;
576*307f5ae8SZachary Turner 
577*307f5ae8SZachary Turner     PdbSymUid cuid = PdbSymUid::makeCompilandId(proc);
578*307f5ae8SZachary Turner     CompilandIndexItem &cci = m_index->compilands().GetOrCreateCompiland(cuid);
579*307f5ae8SZachary Turner     lldb_private::SymbolContext sc;
580*307f5ae8SZachary Turner 
581*307f5ae8SZachary Turner     sc.comp_unit = GetOrCreateCompileUnit(cci).get();
582*307f5ae8SZachary Turner     sc.module_sp = sc.comp_unit->GetModule();
583*307f5ae8SZachary Turner     PdbSymUid func_uid = PdbSymUid::makeCuSymId(proc);
584*307f5ae8SZachary Turner     sc.function = GetOrCreateFunction(func_uid, sc).get();
585*307f5ae8SZachary Turner 
586*307f5ae8SZachary Turner     sc_list.Append(sc);
587*307f5ae8SZachary Turner   }
588*307f5ae8SZachary Turner 
589*307f5ae8SZachary Turner   return sc_list.GetSize();
590*307f5ae8SZachary Turner }
591*307f5ae8SZachary Turner 
592*307f5ae8SZachary Turner uint32_t
593*307f5ae8SZachary Turner SymbolFileNativePDB::FindFunctions(const lldb_private::RegularExpression &regex,
594*307f5ae8SZachary Turner                                    bool include_inlines, bool append,
595*307f5ae8SZachary Turner                                    lldb_private::SymbolContextList &sc_list) {
596*307f5ae8SZachary Turner   return 0;
597*307f5ae8SZachary Turner }
598*307f5ae8SZachary Turner 
599*307f5ae8SZachary Turner lldb_private::CompilerDeclContext SymbolFileNativePDB::FindNamespace(
600*307f5ae8SZachary Turner     const lldb_private::SymbolContext &sc,
601*307f5ae8SZachary Turner     const lldb_private::ConstString &name,
602*307f5ae8SZachary Turner     const lldb_private::CompilerDeclContext *parent_decl_ctx) {
603*307f5ae8SZachary Turner   return {};
604*307f5ae8SZachary Turner }
605*307f5ae8SZachary Turner 
606*307f5ae8SZachary Turner lldb_private::TypeSystem *
607*307f5ae8SZachary Turner SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
608*307f5ae8SZachary Turner   auto type_system =
609*307f5ae8SZachary Turner       m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
610*307f5ae8SZachary Turner   if (type_system)
611*307f5ae8SZachary Turner     type_system->SetSymbolFile(this);
612*307f5ae8SZachary Turner   return type_system;
613*307f5ae8SZachary Turner }
614*307f5ae8SZachary Turner 
615*307f5ae8SZachary Turner lldb_private::ConstString SymbolFileNativePDB::GetPluginName() {
616*307f5ae8SZachary Turner   static ConstString g_name("pdb");
617*307f5ae8SZachary Turner   return g_name;
618*307f5ae8SZachary Turner }
619*307f5ae8SZachary Turner 
620*307f5ae8SZachary Turner uint32_t SymbolFileNativePDB::GetPluginVersion() { return 1; }
621