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 (Module* module)
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));
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));
57     if (instance_ap.get())
58     {
59         ObjectFile *objfile = module->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(Module *module) :
70     ModuleChild(module),
71     m_mutex (Mutex::eMutexTypeRecursive),
72     m_type_list(),
73     m_compile_units(),
74     m_sym_file_ap()
75 {
76 }
77 
78 //----------------------------------------------------------------------
79 // Destructor
80 //----------------------------------------------------------------------
81 SymbolVendor::~SymbolVendor()
82 {
83 }
84 
85 //----------------------------------------------------------------------
86 // Add a represantion given an object file.
87 //----------------------------------------------------------------------
88 void
89 SymbolVendor::AddSymbolFileRepresentation(const ObjectFileSP &objfile_sp)
90 {
91     Mutex::Locker locker(m_mutex);
92     if (objfile_sp)
93     {
94         m_objfile_sp = objfile_sp;
95         m_sym_file_ap.reset(SymbolFile::FindPlugin(objfile_sp.get()));
96     }
97 }
98 
99 bool
100 SymbolVendor::SetCompileUnitAtIndex (CompUnitSP& cu, uint32_t idx)
101 {
102     Mutex::Locker locker(m_mutex);
103     const uint32_t num_compile_units = GetNumCompileUnits();
104     if (idx < num_compile_units)
105     {
106         // Fire off an assertion if this compile unit already exists for now.
107         // The partial parsing should take care of only setting the compile
108         // unit once, so if this assertion fails, we need to make sure that
109         // we don't have a race condition, or have a second parse of the same
110         // compile unit.
111         assert(m_compile_units[idx].get() == NULL);
112         m_compile_units[idx] = cu;
113         return true;
114     }
115     return false;
116 }
117 
118 uint32_t
119 SymbolVendor::GetNumCompileUnits()
120 {
121     Mutex::Locker locker(m_mutex);
122     if (m_compile_units.empty())
123     {
124         if (m_sym_file_ap.get())
125         {
126             // Resize our array of compile unit shared pointers -- which will
127             // each remain NULL until someone asks for the actual compile unit
128             // information. When this happens, the symbol file will be asked
129             // to parse this compile unit information.
130             m_compile_units.resize(m_sym_file_ap->GetNumCompileUnits());
131         }
132     }
133     return m_compile_units.size();
134 }
135 
136 size_t
137 SymbolVendor::ParseCompileUnitFunctions (const SymbolContext &sc)
138 {
139     Mutex::Locker locker(m_mutex);
140     if (m_sym_file_ap.get())
141         return m_sym_file_ap->ParseCompileUnitFunctions(sc);
142     return 0;
143 }
144 
145 bool
146 SymbolVendor::ParseCompileUnitLineTable (const SymbolContext &sc)
147 {
148     Mutex::Locker locker(m_mutex);
149     if (m_sym_file_ap.get())
150         return m_sym_file_ap->ParseCompileUnitLineTable(sc);
151     return false;
152 }
153 
154 bool
155 SymbolVendor::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files)
156 {
157     Mutex::Locker locker(m_mutex);
158     if (m_sym_file_ap.get())
159         return m_sym_file_ap->ParseCompileUnitSupportFiles(sc, support_files);
160     return false;
161 }
162 
163 size_t
164 SymbolVendor::ParseFunctionBlocks (const SymbolContext &sc)
165 {
166     Mutex::Locker locker(m_mutex);
167     if (m_sym_file_ap.get())
168         return m_sym_file_ap->ParseFunctionBlocks(sc);
169     return 0;
170 }
171 
172 size_t
173 SymbolVendor::ParseTypes (const SymbolContext &sc)
174 {
175     Mutex::Locker locker(m_mutex);
176     if (m_sym_file_ap.get())
177         return m_sym_file_ap->ParseTypes(sc);
178     return 0;
179 }
180 
181 size_t
182 SymbolVendor::ParseVariablesForContext (const SymbolContext& sc)
183 {
184     Mutex::Locker locker(m_mutex);
185     if (m_sym_file_ap.get())
186         return m_sym_file_ap->ParseVariablesForContext(sc);
187     return 0;
188 }
189 
190 Type*
191 SymbolVendor::ResolveTypeUID(lldb::user_id_t type_uid)
192 {
193     Mutex::Locker locker(m_mutex);
194     if (m_sym_file_ap.get())
195         return m_sym_file_ap->ResolveTypeUID(type_uid);
196     return NULL;
197 }
198 
199 
200 uint32_t
201 SymbolVendor::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
202 {
203     Mutex::Locker locker(m_mutex);
204     if (m_sym_file_ap.get())
205         return m_sym_file_ap->ResolveSymbolContext(so_addr, resolve_scope, sc);
206     return 0;
207 }
208 
209 uint32_t
210 SymbolVendor::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
211 {
212     Mutex::Locker locker(m_mutex);
213     if (m_sym_file_ap.get())
214         return m_sym_file_ap->ResolveSymbolContext(file_spec, line, check_inlines, resolve_scope, sc_list);
215     return 0;
216 }
217 
218 uint32_t
219 SymbolVendor::FindGlobalVariables (const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables)
220 {
221     Mutex::Locker locker(m_mutex);
222     if (m_sym_file_ap.get())
223         return m_sym_file_ap->FindGlobalVariables(name, namespace_decl, append, max_matches, variables);
224     return 0;
225 }
226 
227 uint32_t
228 SymbolVendor::FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
229 {
230     Mutex::Locker locker(m_mutex);
231     if (m_sym_file_ap.get())
232         return m_sym_file_ap->FindGlobalVariables(regex, append, max_matches, variables);
233     return 0;
234 }
235 
236 uint32_t
237 SymbolVendor::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list)
238 {
239     Mutex::Locker locker(m_mutex);
240     if (m_sym_file_ap.get())
241         return m_sym_file_ap->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list);
242     return 0;
243 }
244 
245 uint32_t
246 SymbolVendor::FindFunctions(const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list)
247 {
248     Mutex::Locker locker(m_mutex);
249     if (m_sym_file_ap.get())
250         return m_sym_file_ap->FindFunctions(regex, include_inlines, append, sc_list);
251     return 0;
252 }
253 
254 
255 uint32_t
256 SymbolVendor::FindTypes (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, TypeList& types)
257 {
258     Mutex::Locker locker(m_mutex);
259     if (m_sym_file_ap.get())
260         return m_sym_file_ap->FindTypes(sc, name, namespace_decl, append, max_matches, types);
261     if (!append)
262         types.Clear();
263     return 0;
264 }
265 
266 ClangNamespaceDecl
267 SymbolVendor::FindNamespace(const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *parent_namespace_decl)
268 {
269     Mutex::Locker locker(m_mutex);
270     ClangNamespaceDecl namespace_decl;
271     if (m_sym_file_ap.get())
272         namespace_decl = m_sym_file_ap->FindNamespace (sc, name, parent_namespace_decl);
273     return namespace_decl;
274 }
275 
276 void
277 SymbolVendor::Dump(Stream *s)
278 {
279     Mutex::Locker locker(m_mutex);
280     bool show_context = false;
281 
282     s->Printf("%p: ", this);
283     s->Indent();
284     s->PutCString("SymbolVendor");
285     if (m_sym_file_ap.get())
286     {
287         ObjectFile *objfile = m_sym_file_ap->GetObjectFile();
288         if (objfile)
289         {
290             const FileSpec &objfile_file_spec = objfile->GetFileSpec();
291             if (objfile_file_spec)
292             {
293                 s->PutCString(" (");
294                 objfile_file_spec.Dump(s);
295                 s->PutChar(')');
296             }
297         }
298     }
299     s->EOL();
300     s->IndentMore();
301     m_type_list.Dump(s, show_context);
302 
303     CompileUnitConstIter cu_pos, cu_end;
304     cu_end = m_compile_units.end();
305     for (cu_pos = m_compile_units.begin(); cu_pos != cu_end; ++cu_pos)
306     {
307         // We currently only dump the compile units that have been parsed
308         if (cu_pos->get())
309             (*cu_pos)->Dump(s, show_context);
310     }
311 
312     s->IndentLess();
313 
314 }
315 
316 CompUnitSP
317 SymbolVendor::GetCompileUnitAtIndex(uint32_t idx)
318 {
319     Mutex::Locker locker(m_mutex);
320     CompUnitSP cu_sp;
321     const uint32_t num_compile_units = GetNumCompileUnits();
322     if (idx < num_compile_units)
323     {
324         cu_sp = m_compile_units[idx];
325         if (cu_sp.get() == NULL)
326         {
327             m_compile_units[idx] = m_sym_file_ap->ParseCompileUnitAtIndex(idx);
328             cu_sp = m_compile_units[idx];
329         }
330     }
331     return cu_sp;
332 }
333 
334 
335 //------------------------------------------------------------------
336 // PluginInterface protocol
337 //------------------------------------------------------------------
338 const char *
339 SymbolVendor::GetPluginName()
340 {
341     return "SymbolVendor";
342 }
343 
344 const char *
345 SymbolVendor::GetShortPluginName()
346 {
347     return "vendor-default";
348 }
349 
350 uint32_t
351 SymbolVendor::GetPluginVersion()
352 {
353     return 1;
354 }
355 
356