1 //===-- SymbolVendor.cpp ----------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/Symbol/SymbolVendor.h"
10 
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/PluginManager.h"
13 #include "lldb/Symbol/CompileUnit.h"
14 #include "lldb/Symbol/ObjectFile.h"
15 #include "lldb/Symbol/SymbolFile.h"
16 #include "lldb/Utility/Stream.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 // FindPlugin
22 //
23 // Platforms can register a callback to use when creating symbol vendors to
24 // allow for complex debug information file setups, and to also allow for
25 // finding separate debug information files.
26 SymbolVendor *SymbolVendor::FindPlugin(const lldb::ModuleSP &module_sp,
27                                        lldb_private::Stream *feedback_strm) {
28   std::unique_ptr<SymbolVendor> instance_up;
29   SymbolVendorCreateInstance create_callback;
30 
31   for (size_t idx = 0;
32        (create_callback = PluginManager::GetSymbolVendorCreateCallbackAtIndex(
33             idx)) != nullptr;
34        ++idx) {
35     instance_up.reset(create_callback(module_sp, feedback_strm));
36 
37     if (instance_up) {
38       return instance_up.release();
39     }
40   }
41   // The default implementation just tries to create debug information using
42   // the file representation for the module.
43   ObjectFileSP sym_objfile_sp;
44   FileSpec sym_spec = module_sp->GetSymbolFileFileSpec();
45   if (sym_spec && sym_spec != module_sp->GetObjectFile()->GetFileSpec()) {
46     DataBufferSP data_sp;
47     offset_t data_offset = 0;
48     sym_objfile_sp = ObjectFile::FindPlugin(
49         module_sp, &sym_spec, 0, FileSystem::Instance().GetByteSize(sym_spec),
50         data_sp, data_offset);
51   }
52   if (!sym_objfile_sp)
53     sym_objfile_sp = module_sp->GetObjectFile()->shared_from_this();
54   instance_up.reset(new SymbolVendor(module_sp));
55   instance_up->AddSymbolFileRepresentation(sym_objfile_sp);
56   return instance_up.release();
57 }
58 
59 // SymbolVendor constructor
60 SymbolVendor::SymbolVendor(const lldb::ModuleSP &module_sp)
61     : ModuleChild(module_sp), m_sym_file_up() {}
62 
63 // Destructor
64 SymbolVendor::~SymbolVendor() {}
65 
66 // Add a representation given an object file.
67 void SymbolVendor::AddSymbolFileRepresentation(const ObjectFileSP &objfile_sp) {
68   ModuleSP module_sp(GetModule());
69   if (module_sp) {
70     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
71     if (objfile_sp) {
72       m_objfile_sp = objfile_sp;
73       m_sym_file_up.reset(SymbolFile::FindPlugin(objfile_sp.get()));
74     }
75   }
76 }
77 
78 size_t SymbolVendor::GetNumCompileUnits() {
79   ModuleSP module_sp(GetModule());
80   if (module_sp) {
81     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
82     if (m_sym_file_up)
83       return m_sym_file_up->GetNumCompileUnits();
84   }
85   return 0;
86 }
87 
88 lldb::LanguageType SymbolVendor::ParseLanguage(CompileUnit &comp_unit) {
89   ModuleSP module_sp(GetModule());
90   if (module_sp) {
91     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
92     if (m_sym_file_up)
93       return m_sym_file_up->ParseLanguage(comp_unit);
94   }
95   return eLanguageTypeUnknown;
96 }
97 
98 size_t SymbolVendor::ParseFunctions(CompileUnit &comp_unit) {
99   ModuleSP module_sp(GetModule());
100   if (module_sp) {
101     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
102     if (m_sym_file_up)
103       return m_sym_file_up->ParseFunctions(comp_unit);
104   }
105   return 0;
106 }
107 
108 bool SymbolVendor::ParseLineTable(CompileUnit &comp_unit) {
109   ModuleSP module_sp(GetModule());
110   if (module_sp) {
111     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
112     if (m_sym_file_up)
113       return m_sym_file_up->ParseLineTable(comp_unit);
114   }
115   return false;
116 }
117 
118 bool SymbolVendor::ParseDebugMacros(CompileUnit &comp_unit) {
119   ModuleSP module_sp(GetModule());
120   if (module_sp) {
121     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
122     if (m_sym_file_up)
123       return m_sym_file_up->ParseDebugMacros(comp_unit);
124   }
125   return false;
126 }
127 bool SymbolVendor::ParseSupportFiles(CompileUnit &comp_unit,
128                                      FileSpecList &support_files) {
129   ModuleSP module_sp(GetModule());
130   if (module_sp) {
131     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
132     if (m_sym_file_up)
133       return m_sym_file_up->ParseSupportFiles(comp_unit, support_files);
134   }
135   return false;
136 }
137 
138 bool SymbolVendor::ParseIsOptimized(CompileUnit &comp_unit) {
139   ModuleSP module_sp(GetModule());
140   if (module_sp) {
141     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
142     if (m_sym_file_up)
143       return m_sym_file_up->ParseIsOptimized(comp_unit);
144   }
145   return false;
146 }
147 
148 bool SymbolVendor::ParseImportedModules(
149     const SymbolContext &sc, std::vector<SourceModule> &imported_modules) {
150   ModuleSP module_sp(GetModule());
151   if (module_sp) {
152     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
153     if (m_sym_file_up)
154       return m_sym_file_up->ParseImportedModules(sc, imported_modules);
155   }
156   return false;
157 }
158 
159 size_t SymbolVendor::ParseBlocksRecursive(Function &func) {
160   ModuleSP module_sp(GetModule());
161   if (module_sp) {
162     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
163     if (m_sym_file_up)
164       return m_sym_file_up->ParseBlocksRecursive(func);
165   }
166   return 0;
167 }
168 
169 size_t SymbolVendor::ParseTypes(CompileUnit &comp_unit) {
170   ModuleSP module_sp(GetModule());
171   if (module_sp) {
172     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
173     if (m_sym_file_up)
174       return m_sym_file_up->ParseTypes(comp_unit);
175   }
176   return 0;
177 }
178 
179 size_t SymbolVendor::ParseVariablesForContext(const SymbolContext &sc) {
180   ModuleSP module_sp(GetModule());
181   if (module_sp) {
182     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
183     if (m_sym_file_up)
184       return m_sym_file_up->ParseVariablesForContext(sc);
185   }
186   return 0;
187 }
188 
189 Type *SymbolVendor::ResolveTypeUID(lldb::user_id_t type_uid) {
190   ModuleSP module_sp(GetModule());
191   if (module_sp) {
192     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
193     if (m_sym_file_up)
194       return m_sym_file_up->ResolveTypeUID(type_uid);
195   }
196   return nullptr;
197 }
198 
199 uint32_t SymbolVendor::ResolveSymbolContext(const Address &so_addr,
200                                             SymbolContextItem resolve_scope,
201                                             SymbolContext &sc) {
202   ModuleSP module_sp(GetModule());
203   if (module_sp) {
204     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
205     if (m_sym_file_up)
206       return m_sym_file_up->ResolveSymbolContext(so_addr, resolve_scope, sc);
207   }
208   return 0;
209 }
210 
211 uint32_t SymbolVendor::ResolveSymbolContext(const FileSpec &file_spec,
212                                             uint32_t line, bool check_inlines,
213                                             SymbolContextItem resolve_scope,
214                                             SymbolContextList &sc_list) {
215   ModuleSP module_sp(GetModule());
216   if (module_sp) {
217     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
218     if (m_sym_file_up)
219       return m_sym_file_up->ResolveSymbolContext(file_spec, line, check_inlines,
220                                                  resolve_scope, sc_list);
221   }
222   return 0;
223 }
224 
225 size_t
226 SymbolVendor::FindGlobalVariables(ConstString name,
227                                   const CompilerDeclContext *parent_decl_ctx,
228                                   size_t max_matches, VariableList &variables) {
229   ModuleSP module_sp(GetModule());
230   if (module_sp) {
231     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
232     if (m_sym_file_up)
233       return m_sym_file_up->FindGlobalVariables(name, parent_decl_ctx,
234                                                 max_matches, variables);
235   }
236   return 0;
237 }
238 
239 size_t SymbolVendor::FindGlobalVariables(const RegularExpression &regex,
240                                          size_t max_matches,
241                                          VariableList &variables) {
242   ModuleSP module_sp(GetModule());
243   if (module_sp) {
244     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
245     if (m_sym_file_up)
246       return m_sym_file_up->FindGlobalVariables(regex, max_matches, variables);
247   }
248   return 0;
249 }
250 
251 size_t SymbolVendor::FindFunctions(ConstString name,
252                                    const CompilerDeclContext *parent_decl_ctx,
253                                    FunctionNameType name_type_mask,
254                                    bool include_inlines, bool append,
255                                    SymbolContextList &sc_list) {
256   ModuleSP module_sp(GetModule());
257   if (module_sp) {
258     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
259     if (m_sym_file_up)
260       return m_sym_file_up->FindFunctions(name, parent_decl_ctx, name_type_mask,
261                                           include_inlines, append, sc_list);
262   }
263   return 0;
264 }
265 
266 size_t SymbolVendor::FindFunctions(const RegularExpression &regex,
267                                    bool include_inlines, bool append,
268                                    SymbolContextList &sc_list) {
269   ModuleSP module_sp(GetModule());
270   if (module_sp) {
271     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
272     if (m_sym_file_up)
273       return m_sym_file_up->FindFunctions(regex, include_inlines, append,
274                                           sc_list);
275   }
276   return 0;
277 }
278 
279 size_t SymbolVendor::FindTypes(
280     ConstString name, const CompilerDeclContext *parent_decl_ctx,
281     bool append, size_t max_matches,
282     llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
283     TypeMap &types) {
284   ModuleSP module_sp(GetModule());
285   if (module_sp) {
286     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
287     if (m_sym_file_up)
288       return m_sym_file_up->FindTypes(name, parent_decl_ctx, append,
289                                       max_matches, searched_symbol_files,
290                                       types);
291   }
292   if (!append)
293     types.Clear();
294   return 0;
295 }
296 
297 size_t SymbolVendor::FindTypes(const std::vector<CompilerContext> &context,
298                                bool append, TypeMap &types) {
299   ModuleSP module_sp(GetModule());
300   if (module_sp) {
301     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
302     if (m_sym_file_up)
303       return m_sym_file_up->FindTypes(context, append, types);
304   }
305   if (!append)
306     types.Clear();
307   return 0;
308 }
309 
310 size_t SymbolVendor::GetTypes(SymbolContextScope *sc_scope, TypeClass type_mask,
311                               lldb_private::TypeList &type_list) {
312   ModuleSP module_sp(GetModule());
313   if (module_sp) {
314     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
315     if (m_sym_file_up)
316       return m_sym_file_up->GetTypes(sc_scope, type_mask, type_list);
317   }
318   return 0;
319 }
320 
321 CompilerDeclContext
322 SymbolVendor::FindNamespace(ConstString name,
323                             const CompilerDeclContext *parent_decl_ctx) {
324   CompilerDeclContext namespace_decl_ctx;
325   ModuleSP module_sp(GetModule());
326   if (module_sp) {
327     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
328     if (m_sym_file_up)
329       namespace_decl_ctx = m_sym_file_up->FindNamespace(name, parent_decl_ctx);
330   }
331   return namespace_decl_ctx;
332 }
333 
334 void SymbolVendor::Dump(Stream *s) {
335   ModuleSP module_sp(GetModule());
336   if (module_sp) {
337     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
338 
339     s->Printf("%p: ", static_cast<void *>(this));
340     s->Indent();
341     s->PutCString("SymbolVendor");
342     if (m_sym_file_up) {
343       *s << " " << m_sym_file_up->GetPluginName();
344       ObjectFile *objfile = m_sym_file_up->GetObjectFile();
345       if (objfile) {
346         const FileSpec &objfile_file_spec = objfile->GetFileSpec();
347         if (objfile_file_spec) {
348           s->PutCString(" (");
349           objfile_file_spec.Dump(s);
350           s->PutChar(')');
351         }
352       }
353     }
354     s->EOL();
355     if (m_sym_file_up)
356       m_sym_file_up->Dump(*s);
357     s->IndentMore();
358 
359     if (Symtab *symtab = GetSymtab())
360       symtab->Dump(s, nullptr, eSortOrderNone);
361 
362     s->IndentLess();
363   }
364 }
365 
366 CompUnitSP SymbolVendor::GetCompileUnitAtIndex(size_t idx) {
367   ModuleSP module_sp(GetModule());
368   if (module_sp) {
369     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
370     if (m_sym_file_up)
371       return m_sym_file_up->GetCompileUnitAtIndex(idx);
372   }
373   return nullptr;
374 }
375 
376 FileSpec SymbolVendor::GetMainFileSpec() const {
377   if (m_sym_file_up) {
378     const ObjectFile *symfile_objfile = m_sym_file_up->GetObjectFile();
379     if (symfile_objfile)
380       return symfile_objfile->GetFileSpec();
381   }
382 
383   return FileSpec();
384 }
385 
386 Symtab *SymbolVendor::GetSymtab() {
387   if (m_sym_file_up)
388     return m_sym_file_up->GetSymtab();
389   return nullptr;
390 }
391 
392 void SymbolVendor::SectionFileAddressesChanged() {
393   if (m_sym_file_up)
394     m_sym_file_up->SectionFileAddressesChanged();
395 }
396 
397 // PluginInterface protocol
398 lldb_private::ConstString SymbolVendor::GetPluginName() {
399   static ConstString g_name("vendor-default");
400   return g_name;
401 }
402 
403 uint32_t SymbolVendor::GetPluginVersion() { return 1; }
404