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