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