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 ®ex,
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 ®ex,
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