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