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