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 //----------------------------------------------------------------------
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 //----------------------------------------------------------------------
58 SymbolVendor::SymbolVendor(const lldb::ModuleSP &module_sp)
59     : ModuleChild(module_sp), m_type_list(), m_compile_units(),
60       m_sym_file_ap() {}
61 
62 //----------------------------------------------------------------------
63 // Destructor
64 //----------------------------------------------------------------------
65 SymbolVendor::~SymbolVendor() {}
66 
67 //----------------------------------------------------------------------
68 // Add a representation given an object file.
69 //----------------------------------------------------------------------
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 
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 
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 
121 lldb::LanguageType
122 SymbolVendor::ParseCompileUnitLanguage(const SymbolContext &sc) {
123   ModuleSP module_sp(GetModule());
124   if (module_sp) {
125     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
126     if (m_sym_file_ap.get())
127       return m_sym_file_ap->ParseCompileUnitLanguage(sc);
128   }
129   return eLanguageTypeUnknown;
130 }
131 
132 size_t SymbolVendor::ParseCompileUnitFunctions(const SymbolContext &sc) {
133   ModuleSP module_sp(GetModule());
134   if (module_sp) {
135     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
136     if (m_sym_file_ap.get())
137       return m_sym_file_ap->ParseCompileUnitFunctions(sc);
138   }
139   return 0;
140 }
141 
142 bool SymbolVendor::ParseCompileUnitLineTable(const SymbolContext &sc) {
143   ModuleSP module_sp(GetModule());
144   if (module_sp) {
145     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
146     if (m_sym_file_ap.get())
147       return m_sym_file_ap->ParseCompileUnitLineTable(sc);
148   }
149   return false;
150 }
151 
152 bool SymbolVendor::ParseCompileUnitDebugMacros(const SymbolContext &sc) {
153   ModuleSP module_sp(GetModule());
154   if (module_sp) {
155     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
156     if (m_sym_file_ap.get())
157       return m_sym_file_ap->ParseCompileUnitDebugMacros(sc);
158   }
159   return false;
160 }
161 bool SymbolVendor::ParseCompileUnitSupportFiles(const SymbolContext &sc,
162                                                 FileSpecList &support_files) {
163   ModuleSP module_sp(GetModule());
164   if (module_sp) {
165     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
166     if (m_sym_file_ap.get())
167       return m_sym_file_ap->ParseCompileUnitSupportFiles(sc, support_files);
168   }
169   return false;
170 }
171 
172 bool SymbolVendor::ParseCompileUnitIsOptimized(const SymbolContext &sc) {
173   ModuleSP module_sp(GetModule());
174   if (module_sp) {
175     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
176     if (m_sym_file_ap.get())
177       return m_sym_file_ap->ParseCompileUnitIsOptimized(sc);
178   }
179   return false;
180 }
181 
182 bool SymbolVendor::ParseImportedModules(
183     const SymbolContext &sc, std::vector<ConstString> &imported_modules) {
184   ModuleSP module_sp(GetModule());
185   if (module_sp) {
186     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
187     if (m_sym_file_ap.get())
188       return m_sym_file_ap->ParseImportedModules(sc, imported_modules);
189   }
190   return false;
191 }
192 
193 size_t SymbolVendor::ParseFunctionBlocks(const SymbolContext &sc) {
194   ModuleSP module_sp(GetModule());
195   if (module_sp) {
196     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
197     if (m_sym_file_ap.get())
198       return m_sym_file_ap->ParseFunctionBlocks(sc);
199   }
200   return 0;
201 }
202 
203 size_t SymbolVendor::ParseTypes(const SymbolContext &sc) {
204   ModuleSP module_sp(GetModule());
205   if (module_sp) {
206     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
207     if (m_sym_file_ap.get())
208       return m_sym_file_ap->ParseTypes(sc);
209   }
210   return 0;
211 }
212 
213 size_t SymbolVendor::ParseVariablesForContext(const SymbolContext &sc) {
214   ModuleSP module_sp(GetModule());
215   if (module_sp) {
216     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
217     if (m_sym_file_ap.get())
218       return m_sym_file_ap->ParseVariablesForContext(sc);
219   }
220   return 0;
221 }
222 
223 Type *SymbolVendor::ResolveTypeUID(lldb::user_id_t type_uid) {
224   ModuleSP module_sp(GetModule());
225   if (module_sp) {
226     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
227     if (m_sym_file_ap.get())
228       return m_sym_file_ap->ResolveTypeUID(type_uid);
229   }
230   return nullptr;
231 }
232 
233 uint32_t SymbolVendor::ResolveSymbolContext(const Address &so_addr,
234                                             SymbolContextItem resolve_scope,
235                                             SymbolContext &sc) {
236   ModuleSP module_sp(GetModule());
237   if (module_sp) {
238     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
239     if (m_sym_file_ap.get())
240       return m_sym_file_ap->ResolveSymbolContext(so_addr, resolve_scope, sc);
241   }
242   return 0;
243 }
244 
245 uint32_t SymbolVendor::ResolveSymbolContext(const FileSpec &file_spec,
246                                             uint32_t line, bool check_inlines,
247                                             SymbolContextItem resolve_scope,
248                                             SymbolContextList &sc_list) {
249   ModuleSP module_sp(GetModule());
250   if (module_sp) {
251     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
252     if (m_sym_file_ap.get())
253       return m_sym_file_ap->ResolveSymbolContext(file_spec, line, check_inlines,
254                                                  resolve_scope, sc_list);
255   }
256   return 0;
257 }
258 
259 size_t
260 SymbolVendor::FindGlobalVariables(const ConstString &name,
261                                   const CompilerDeclContext *parent_decl_ctx,
262                                   size_t max_matches, VariableList &variables) {
263   ModuleSP module_sp(GetModule());
264   if (module_sp) {
265     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
266     if (m_sym_file_ap.get())
267       return m_sym_file_ap->FindGlobalVariables(name, parent_decl_ctx,
268                                                 max_matches, variables);
269   }
270   return 0;
271 }
272 
273 size_t SymbolVendor::FindGlobalVariables(const RegularExpression &regex,
274                                          size_t max_matches,
275                                          VariableList &variables) {
276   ModuleSP module_sp(GetModule());
277   if (module_sp) {
278     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
279     if (m_sym_file_ap.get())
280       return m_sym_file_ap->FindGlobalVariables(regex, max_matches, variables);
281   }
282   return 0;
283 }
284 
285 size_t SymbolVendor::FindFunctions(const ConstString &name,
286                                    const CompilerDeclContext *parent_decl_ctx,
287                                    FunctionNameType name_type_mask,
288                                    bool include_inlines, bool append,
289                                    SymbolContextList &sc_list) {
290   ModuleSP module_sp(GetModule());
291   if (module_sp) {
292     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
293     if (m_sym_file_ap.get())
294       return m_sym_file_ap->FindFunctions(name, parent_decl_ctx, name_type_mask,
295                                           include_inlines, append, sc_list);
296   }
297   return 0;
298 }
299 
300 size_t SymbolVendor::FindFunctions(const RegularExpression &regex,
301                                    bool include_inlines, bool append,
302                                    SymbolContextList &sc_list) {
303   ModuleSP module_sp(GetModule());
304   if (module_sp) {
305     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
306     if (m_sym_file_ap.get())
307       return m_sym_file_ap->FindFunctions(regex, include_inlines, append,
308                                           sc_list);
309   }
310   return 0;
311 }
312 
313 size_t SymbolVendor::FindTypes(
314     const SymbolContext &sc, const ConstString &name,
315     const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches,
316     llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
317     TypeMap &types) {
318   ModuleSP module_sp(GetModule());
319   if (module_sp) {
320     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
321     if (m_sym_file_ap.get())
322       return m_sym_file_ap->FindTypes(sc, name, parent_decl_ctx, append,
323                                       max_matches, searched_symbol_files,
324                                       types);
325   }
326   if (!append)
327     types.Clear();
328   return 0;
329 }
330 
331 size_t SymbolVendor::FindTypes(const std::vector<CompilerContext> &context,
332                                bool append, TypeMap &types) {
333   ModuleSP module_sp(GetModule());
334   if (module_sp) {
335     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
336     if (m_sym_file_ap.get())
337       return m_sym_file_ap->FindTypes(context, append, types);
338   }
339   if (!append)
340     types.Clear();
341   return 0;
342 }
343 
344 size_t SymbolVendor::GetTypes(SymbolContextScope *sc_scope, TypeClass type_mask,
345                               lldb_private::TypeList &type_list) {
346   ModuleSP module_sp(GetModule());
347   if (module_sp) {
348     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
349     if (m_sym_file_ap.get())
350       return m_sym_file_ap->GetTypes(sc_scope, type_mask, type_list);
351   }
352   return 0;
353 }
354 
355 CompilerDeclContext
356 SymbolVendor::FindNamespace(const SymbolContext &sc, const ConstString &name,
357                             const CompilerDeclContext *parent_decl_ctx) {
358   CompilerDeclContext namespace_decl_ctx;
359   ModuleSP module_sp(GetModule());
360   if (module_sp) {
361     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
362     if (m_sym_file_ap.get())
363       namespace_decl_ctx =
364           m_sym_file_ap->FindNamespace(sc, name, parent_decl_ctx);
365   }
366   return namespace_decl_ctx;
367 }
368 
369 void SymbolVendor::Dump(Stream *s) {
370   ModuleSP module_sp(GetModule());
371   if (module_sp) {
372     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
373 
374     bool show_context = false;
375 
376     s->Printf("%p: ", static_cast<void *>(this));
377     s->Indent();
378     s->PutCString("SymbolVendor");
379     if (m_sym_file_ap.get()) {
380       ObjectFile *objfile = m_sym_file_ap->GetObjectFile();
381       if (objfile) {
382         const FileSpec &objfile_file_spec = objfile->GetFileSpec();
383         if (objfile_file_spec) {
384           s->PutCString(" (");
385           objfile_file_spec.Dump(s);
386           s->PutChar(')');
387         }
388       }
389     }
390     s->EOL();
391     if (m_sym_file_ap)
392       m_sym_file_ap->Dump(*s);
393     s->IndentMore();
394     m_type_list.Dump(s, show_context);
395 
396     CompileUnitConstIter cu_pos, cu_end;
397     cu_end = m_compile_units.end();
398     for (cu_pos = m_compile_units.begin(); cu_pos != cu_end; ++cu_pos) {
399       // We currently only dump the compile units that have been parsed
400       if (cu_pos->get())
401         (*cu_pos)->Dump(s, show_context);
402     }
403 
404     s->IndentLess();
405   }
406 }
407 
408 CompUnitSP SymbolVendor::GetCompileUnitAtIndex(size_t idx) {
409   CompUnitSP cu_sp;
410   ModuleSP module_sp(GetModule());
411   if (module_sp) {
412     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
413     const size_t num_compile_units = GetNumCompileUnits();
414     if (idx < num_compile_units) {
415       cu_sp = m_compile_units[idx];
416       if (cu_sp.get() == nullptr) {
417         m_compile_units[idx] = m_sym_file_ap->ParseCompileUnitAtIndex(idx);
418         cu_sp = m_compile_units[idx];
419       }
420     }
421   }
422   return cu_sp;
423 }
424 
425 FileSpec SymbolVendor::GetMainFileSpec() const {
426   if (m_sym_file_ap.get()) {
427     const ObjectFile *symfile_objfile = m_sym_file_ap->GetObjectFile();
428     if (symfile_objfile)
429       return symfile_objfile->GetFileSpec();
430   }
431 
432   return FileSpec();
433 }
434 
435 Symtab *SymbolVendor::GetSymtab() {
436   ModuleSP module_sp(GetModule());
437   if (module_sp) {
438     ObjectFile *objfile = module_sp->GetObjectFile();
439     if (objfile) {
440       // Get symbol table from unified section list.
441       return objfile->GetSymtab();
442     }
443   }
444   return nullptr;
445 }
446 
447 void SymbolVendor::ClearSymtab() {
448   ModuleSP module_sp(GetModule());
449   if (module_sp) {
450     ObjectFile *objfile = module_sp->GetObjectFile();
451     if (objfile) {
452       // Clear symbol table from unified section list.
453       objfile->ClearSymtab();
454     }
455   }
456 }
457 
458 void SymbolVendor::SectionFileAddressesChanged() {
459   ModuleSP module_sp(GetModule());
460   if (module_sp) {
461     ObjectFile *module_objfile = module_sp->GetObjectFile();
462     if (m_sym_file_ap.get()) {
463       ObjectFile *symfile_objfile = m_sym_file_ap->GetObjectFile();
464       if (symfile_objfile != module_objfile)
465         symfile_objfile->SectionFileAddressesChanged();
466     }
467     Symtab *symtab = GetSymtab();
468     if (symtab) {
469       symtab->SectionFileAddressesChanged();
470     }
471   }
472 }
473 
474 //------------------------------------------------------------------
475 // PluginInterface protocol
476 //------------------------------------------------------------------
477 lldb_private::ConstString SymbolVendor::GetPluginName() {
478   static ConstString g_name("vendor-default");
479   return g_name;
480 }
481 
482 uint32_t SymbolVendor::GetPluginVersion() { return 1; }
483