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