1 //===-- SymbolVendor.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 "lldb/Symbol/SymbolVendor.h"
11 
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/PluginManager.h"
14 #include "lldb/Symbol/CompileUnit.h"
15 #include "lldb/Symbol/ObjectFile.h"
16 #include "lldb/Symbol/SymbolFile.h"
17 #include "lldb/Utility/Stream.h"
18 
19 using namespace lldb;
20 using namespace lldb_private;
21 
22 //----------------------------------------------------------------------
23 // FindPlugin
24 //
25 // Platforms can register a callback to use when creating symbol vendors to
26 // allow for complex debug information file setups, and to also allow for
27 // finding separate debug information files.
28 //----------------------------------------------------------------------
FindPlugin(const lldb::ModuleSP & module_sp,lldb_private::Stream * feedback_strm)29 SymbolVendor *SymbolVendor::FindPlugin(const lldb::ModuleSP &module_sp,
30                                        lldb_private::Stream *feedback_strm) {
31   std::unique_ptr<SymbolVendor> instance_ap;
32   SymbolVendorCreateInstance create_callback;
33 
34   for (size_t idx = 0;
35        (create_callback = PluginManager::GetSymbolVendorCreateCallbackAtIndex(
36             idx)) != nullptr;
37        ++idx) {
38     instance_ap.reset(create_callback(module_sp, feedback_strm));
39 
40     if (instance_ap.get()) {
41       return instance_ap.release();
42     }
43   }
44   // The default implementation just tries to create debug information using
45   // the file representation for the module.
46   instance_ap.reset(new SymbolVendor(module_sp));
47   if (instance_ap.get()) {
48     ObjectFile *objfile = module_sp->GetObjectFile();
49     if (objfile)
50       instance_ap->AddSymbolFileRepresentation(objfile->shared_from_this());
51   }
52   return instance_ap.release();
53 }
54 
55 //----------------------------------------------------------------------
56 // SymbolVendor constructor
57 //----------------------------------------------------------------------
SymbolVendor(const lldb::ModuleSP & module_sp)58 SymbolVendor::SymbolVendor(const lldb::ModuleSP &module_sp)
59     : ModuleChild(module_sp), m_type_list(), m_compile_units(),
60       m_sym_file_ap(), m_symtab() {}
61 
62 //----------------------------------------------------------------------
63 // Destructor
64 //----------------------------------------------------------------------
~SymbolVendor()65 SymbolVendor::~SymbolVendor() {}
66 
67 //----------------------------------------------------------------------
68 // Add a representation given an object file.
69 //----------------------------------------------------------------------
AddSymbolFileRepresentation(const ObjectFileSP & objfile_sp)70 void SymbolVendor::AddSymbolFileRepresentation(const ObjectFileSP &objfile_sp) {
71   ModuleSP module_sp(GetModule());
72   if (module_sp) {
73     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
74     if (objfile_sp) {
75       m_objfile_sp = objfile_sp;
76       m_sym_file_ap.reset(SymbolFile::FindPlugin(objfile_sp.get()));
77     }
78   }
79 }
80 
SetCompileUnitAtIndex(size_t idx,const CompUnitSP & cu_sp)81 bool SymbolVendor::SetCompileUnitAtIndex(size_t idx, const CompUnitSP &cu_sp) {
82   ModuleSP module_sp(GetModule());
83   if (module_sp) {
84     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
85     const size_t num_compile_units = GetNumCompileUnits();
86     if (idx < num_compile_units) {
87       // Fire off an assertion if this compile unit already exists for now. The
88       // partial parsing should take care of only setting the compile unit
89       // once, so if this assertion fails, we need to make sure that we don't
90       // have a race condition, or have a second parse of the same compile
91       // unit.
92       assert(m_compile_units[idx].get() == nullptr);
93       m_compile_units[idx] = cu_sp;
94       return true;
95     } else {
96       // This should NOT happen, and if it does, we want to crash and know
97       // about it
98       assert(idx < num_compile_units);
99     }
100   }
101   return false;
102 }
103 
GetNumCompileUnits()104 size_t SymbolVendor::GetNumCompileUnits() {
105   ModuleSP module_sp(GetModule());
106   if (module_sp) {
107     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
108     if (m_compile_units.empty()) {
109       if (m_sym_file_ap.get()) {
110         // Resize our array of compile unit shared pointers -- which will each
111         // remain NULL until someone asks for the actual compile unit
112         // information. When this happens, the symbol file will be asked to
113         // parse this compile unit information.
114         m_compile_units.resize(m_sym_file_ap->GetNumCompileUnits());
115       }
116     }
117   }
118   return m_compile_units.size();
119 }
120 
ParseLanguage(CompileUnit & comp_unit)121 lldb::LanguageType SymbolVendor::ParseLanguage(CompileUnit &comp_unit) {
122   ModuleSP module_sp(GetModule());
123   if (module_sp) {
124     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
125     if (m_sym_file_ap.get())
126       return m_sym_file_ap->ParseLanguage(comp_unit);
127   }
128   return eLanguageTypeUnknown;
129 }
130 
ParseFunctions(CompileUnit & comp_unit)131 size_t SymbolVendor::ParseFunctions(CompileUnit &comp_unit) {
132   ModuleSP module_sp(GetModule());
133   if (module_sp) {
134     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
135     if (m_sym_file_ap.get())
136       return m_sym_file_ap->ParseFunctions(comp_unit);
137   }
138   return 0;
139 }
140 
ParseLineTable(CompileUnit & comp_unit)141 bool SymbolVendor::ParseLineTable(CompileUnit &comp_unit) {
142   ModuleSP module_sp(GetModule());
143   if (module_sp) {
144     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
145     if (m_sym_file_ap.get())
146       return m_sym_file_ap->ParseLineTable(comp_unit);
147   }
148   return false;
149 }
150 
ParseDebugMacros(CompileUnit & comp_unit)151 bool SymbolVendor::ParseDebugMacros(CompileUnit &comp_unit) {
152   ModuleSP module_sp(GetModule());
153   if (module_sp) {
154     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
155     if (m_sym_file_ap.get())
156       return m_sym_file_ap->ParseDebugMacros(comp_unit);
157   }
158   return false;
159 }
ParseSupportFiles(CompileUnit & comp_unit,FileSpecList & support_files)160 bool SymbolVendor::ParseSupportFiles(CompileUnit &comp_unit,
161                                      FileSpecList &support_files) {
162   ModuleSP module_sp(GetModule());
163   if (module_sp) {
164     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
165     if (m_sym_file_ap.get())
166       return m_sym_file_ap->ParseSupportFiles(comp_unit, support_files);
167   }
168   return false;
169 }
170 
ParseIsOptimized(CompileUnit & comp_unit)171 bool SymbolVendor::ParseIsOptimized(CompileUnit &comp_unit) {
172   ModuleSP module_sp(GetModule());
173   if (module_sp) {
174     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
175     if (m_sym_file_ap.get())
176       return m_sym_file_ap->ParseIsOptimized(comp_unit);
177   }
178   return false;
179 }
180 
ParseImportedModules(const SymbolContext & sc,std::vector<ConstString> & imported_modules)181 bool SymbolVendor::ParseImportedModules(
182     const SymbolContext &sc, std::vector<ConstString> &imported_modules) {
183   ModuleSP module_sp(GetModule());
184   if (module_sp) {
185     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
186     if (m_sym_file_ap.get())
187       return m_sym_file_ap->ParseImportedModules(sc, imported_modules);
188   }
189   return false;
190 }
191 
ParseBlocksRecursive(Function & func)192 size_t SymbolVendor::ParseBlocksRecursive(Function &func) {
193   ModuleSP module_sp(GetModule());
194   if (module_sp) {
195     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
196     if (m_sym_file_ap.get())
197       return m_sym_file_ap->ParseBlocksRecursive(func);
198   }
199   return 0;
200 }
201 
ParseTypes(CompileUnit & comp_unit)202 size_t SymbolVendor::ParseTypes(CompileUnit &comp_unit) {
203   ModuleSP module_sp(GetModule());
204   if (module_sp) {
205     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
206     if (m_sym_file_ap.get())
207       return m_sym_file_ap->ParseTypes(comp_unit);
208   }
209   return 0;
210 }
211 
ParseVariablesForContext(const SymbolContext & sc)212 size_t SymbolVendor::ParseVariablesForContext(const SymbolContext &sc) {
213   ModuleSP module_sp(GetModule());
214   if (module_sp) {
215     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
216     if (m_sym_file_ap.get())
217       return m_sym_file_ap->ParseVariablesForContext(sc);
218   }
219   return 0;
220 }
221 
ResolveTypeUID(lldb::user_id_t type_uid)222 Type *SymbolVendor::ResolveTypeUID(lldb::user_id_t type_uid) {
223   ModuleSP module_sp(GetModule());
224   if (module_sp) {
225     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
226     if (m_sym_file_ap.get())
227       return m_sym_file_ap->ResolveTypeUID(type_uid);
228   }
229   return nullptr;
230 }
231 
ResolveSymbolContext(const Address & so_addr,SymbolContextItem resolve_scope,SymbolContext & sc)232 uint32_t SymbolVendor::ResolveSymbolContext(const Address &so_addr,
233                                             SymbolContextItem resolve_scope,
234                                             SymbolContext &sc) {
235   ModuleSP module_sp(GetModule());
236   if (module_sp) {
237     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
238     if (m_sym_file_ap.get())
239       return m_sym_file_ap->ResolveSymbolContext(so_addr, resolve_scope, sc);
240   }
241   return 0;
242 }
243 
ResolveSymbolContext(const FileSpec & file_spec,uint32_t line,bool check_inlines,SymbolContextItem resolve_scope,SymbolContextList & sc_list)244 uint32_t SymbolVendor::ResolveSymbolContext(const FileSpec &file_spec,
245                                             uint32_t line, bool check_inlines,
246                                             SymbolContextItem resolve_scope,
247                                             SymbolContextList &sc_list) {
248   ModuleSP module_sp(GetModule());
249   if (module_sp) {
250     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
251     if (m_sym_file_ap.get())
252       return m_sym_file_ap->ResolveSymbolContext(file_spec, line, check_inlines,
253                                                  resolve_scope, sc_list);
254   }
255   return 0;
256 }
257 
258 size_t
FindGlobalVariables(const ConstString & name,const CompilerDeclContext * parent_decl_ctx,size_t max_matches,VariableList & variables)259 SymbolVendor::FindGlobalVariables(const ConstString &name,
260                                   const CompilerDeclContext *parent_decl_ctx,
261                                   size_t max_matches, VariableList &variables) {
262   ModuleSP module_sp(GetModule());
263   if (module_sp) {
264     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
265     if (m_sym_file_ap.get())
266       return m_sym_file_ap->FindGlobalVariables(name, parent_decl_ctx,
267                                                 max_matches, variables);
268   }
269   return 0;
270 }
271 
FindGlobalVariables(const RegularExpression & regex,size_t max_matches,VariableList & variables)272 size_t SymbolVendor::FindGlobalVariables(const RegularExpression &regex,
273                                          size_t max_matches,
274                                          VariableList &variables) {
275   ModuleSP module_sp(GetModule());
276   if (module_sp) {
277     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
278     if (m_sym_file_ap.get())
279       return m_sym_file_ap->FindGlobalVariables(regex, max_matches, variables);
280   }
281   return 0;
282 }
283 
FindFunctions(const ConstString & name,const CompilerDeclContext * parent_decl_ctx,FunctionNameType name_type_mask,bool include_inlines,bool append,SymbolContextList & sc_list)284 size_t SymbolVendor::FindFunctions(const ConstString &name,
285                                    const CompilerDeclContext *parent_decl_ctx,
286                                    FunctionNameType name_type_mask,
287                                    bool include_inlines, bool append,
288                                    SymbolContextList &sc_list) {
289   ModuleSP module_sp(GetModule());
290   if (module_sp) {
291     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
292     if (m_sym_file_ap.get())
293       return m_sym_file_ap->FindFunctions(name, parent_decl_ctx, name_type_mask,
294                                           include_inlines, append, sc_list);
295   }
296   return 0;
297 }
298 
FindFunctions(const RegularExpression & regex,bool include_inlines,bool append,SymbolContextList & sc_list)299 size_t SymbolVendor::FindFunctions(const RegularExpression &regex,
300                                    bool include_inlines, bool append,
301                                    SymbolContextList &sc_list) {
302   ModuleSP module_sp(GetModule());
303   if (module_sp) {
304     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
305     if (m_sym_file_ap.get())
306       return m_sym_file_ap->FindFunctions(regex, include_inlines, append,
307                                           sc_list);
308   }
309   return 0;
310 }
311 
FindTypes(const ConstString & name,const CompilerDeclContext * parent_decl_ctx,bool append,size_t max_matches,llvm::DenseSet<lldb_private::SymbolFile * > & searched_symbol_files,TypeMap & types)312 size_t SymbolVendor::FindTypes(
313     const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
314     bool append, size_t max_matches,
315     llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
316     TypeMap &types) {
317   ModuleSP module_sp(GetModule());
318   if (module_sp) {
319     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
320     if (m_sym_file_ap.get())
321       return m_sym_file_ap->FindTypes(name, parent_decl_ctx, append,
322                                       max_matches, searched_symbol_files,
323                                       types);
324   }
325   if (!append)
326     types.Clear();
327   return 0;
328 }
329 
FindTypes(const std::vector<CompilerContext> & context,bool append,TypeMap & types)330 size_t SymbolVendor::FindTypes(const std::vector<CompilerContext> &context,
331                                bool append, TypeMap &types) {
332   ModuleSP module_sp(GetModule());
333   if (module_sp) {
334     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
335     if (m_sym_file_ap.get())
336       return m_sym_file_ap->FindTypes(context, append, types);
337   }
338   if (!append)
339     types.Clear();
340   return 0;
341 }
342 
GetTypes(SymbolContextScope * sc_scope,TypeClass type_mask,lldb_private::TypeList & type_list)343 size_t SymbolVendor::GetTypes(SymbolContextScope *sc_scope, TypeClass type_mask,
344                               lldb_private::TypeList &type_list) {
345   ModuleSP module_sp(GetModule());
346   if (module_sp) {
347     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
348     if (m_sym_file_ap.get())
349       return m_sym_file_ap->GetTypes(sc_scope, type_mask, type_list);
350   }
351   return 0;
352 }
353 
354 CompilerDeclContext
FindNamespace(const ConstString & name,const CompilerDeclContext * parent_decl_ctx)355 SymbolVendor::FindNamespace(const ConstString &name,
356                             const CompilerDeclContext *parent_decl_ctx) {
357   CompilerDeclContext namespace_decl_ctx;
358   ModuleSP module_sp(GetModule());
359   if (module_sp) {
360     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
361     if (m_sym_file_ap.get())
362       namespace_decl_ctx = m_sym_file_ap->FindNamespace(name, parent_decl_ctx);
363   }
364   return namespace_decl_ctx;
365 }
366 
Dump(Stream * s)367 void SymbolVendor::Dump(Stream *s) {
368   ModuleSP module_sp(GetModule());
369   if (module_sp) {
370     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
371 
372     bool show_context = false;
373 
374     s->Printf("%p: ", static_cast<void *>(this));
375     s->Indent();
376     s->PutCString("SymbolVendor");
377     if (m_sym_file_ap.get()) {
378       *s << " " << m_sym_file_ap->GetPluginName();
379       ObjectFile *objfile = m_sym_file_ap->GetObjectFile();
380       if (objfile) {
381         const FileSpec &objfile_file_spec = objfile->GetFileSpec();
382         if (objfile_file_spec) {
383           s->PutCString(" (");
384           objfile_file_spec.Dump(s);
385           s->PutChar(')');
386         }
387       }
388     }
389     s->EOL();
390     if (m_sym_file_ap)
391       m_sym_file_ap->Dump(*s);
392     s->IndentMore();
393     m_type_list.Dump(s, show_context);
394 
395     CompileUnitConstIter cu_pos, cu_end;
396     cu_end = m_compile_units.end();
397     for (cu_pos = m_compile_units.begin(); cu_pos != cu_end; ++cu_pos) {
398       // We currently only dump the compile units that have been parsed
399       if (cu_pos->get())
400         (*cu_pos)->Dump(s, show_context);
401     }
402 
403     if (Symtab *symtab = GetSymtab())
404       symtab->Dump(s, nullptr, eSortOrderNone);
405 
406     s->IndentLess();
407   }
408 }
409 
GetCompileUnitAtIndex(size_t idx)410 CompUnitSP SymbolVendor::GetCompileUnitAtIndex(size_t idx) {
411   CompUnitSP cu_sp;
412   ModuleSP module_sp(GetModule());
413   if (module_sp) {
414     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
415     const size_t num_compile_units = GetNumCompileUnits();
416     if (idx < num_compile_units) {
417       cu_sp = m_compile_units[idx];
418       if (cu_sp.get() == nullptr) {
419         m_compile_units[idx] = m_sym_file_ap->ParseCompileUnitAtIndex(idx);
420         cu_sp = m_compile_units[idx];
421       }
422     }
423   }
424   return cu_sp;
425 }
426 
GetMainFileSpec() const427 FileSpec SymbolVendor::GetMainFileSpec() const {
428   if (m_sym_file_ap.get()) {
429     const ObjectFile *symfile_objfile = m_sym_file_ap->GetObjectFile();
430     if (symfile_objfile)
431       return symfile_objfile->GetFileSpec();
432   }
433 
434   return FileSpec();
435 }
436 
GetSymtab()437 Symtab *SymbolVendor::GetSymtab() {
438   ModuleSP module_sp(GetModule());
439   if (!module_sp)
440     return nullptr;
441 
442   std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
443 
444   if (m_symtab)
445     return m_symtab;
446 
447   ObjectFile *objfile = module_sp->GetObjectFile();
448   if (!objfile)
449     return nullptr;
450 
451   m_symtab = objfile->GetSymtab();
452   if (m_symtab && m_sym_file_ap)
453     m_sym_file_ap->AddSymbols(*m_symtab);
454 
455   return m_symtab;
456 }
457 
ClearSymtab()458 void SymbolVendor::ClearSymtab() {
459   ModuleSP module_sp(GetModule());
460   if (module_sp) {
461     ObjectFile *objfile = module_sp->GetObjectFile();
462     if (objfile) {
463       // Clear symbol table from unified section list.
464       objfile->ClearSymtab();
465     }
466   }
467 }
468 
SectionFileAddressesChanged()469 void SymbolVendor::SectionFileAddressesChanged() {
470   ModuleSP module_sp(GetModule());
471   if (module_sp) {
472     ObjectFile *module_objfile = module_sp->GetObjectFile();
473     if (m_sym_file_ap.get()) {
474       ObjectFile *symfile_objfile = m_sym_file_ap->GetObjectFile();
475       if (symfile_objfile != module_objfile)
476         symfile_objfile->SectionFileAddressesChanged();
477     }
478     Symtab *symtab = GetSymtab();
479     if (symtab) {
480       symtab->SectionFileAddressesChanged();
481     }
482   }
483 }
484 
485 //------------------------------------------------------------------
486 // PluginInterface protocol
487 //------------------------------------------------------------------
GetPluginName()488 lldb_private::ConstString SymbolVendor::GetPluginName() {
489   static ConstString g_name("vendor-default");
490   return g_name;
491 }
492 
GetPluginVersion()493 uint32_t SymbolVendor::GetPluginVersion() { return 1; }
494