1 //===-- SymbolFileSymtab.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 "SymbolFileSymtab.h"
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/PluginManager.h"
13 #include "lldb/Core/RegularExpression.h"
14 #include "lldb/Core/Timer.h"
15 #include "lldb/Symbol/ObjectFile.h"
16 #include "lldb/Symbol/Symtab.h"
17 #include "lldb/Symbol/ObjectFile.h"
18 #include "lldb/Symbol/Symbol.h"
19 #include "lldb/Symbol/CompileUnit.h"
20 #include "lldb/Symbol/SymbolContext.h"
21 #include "lldb/Symbol/Function.h"
22 
23 using namespace lldb;
24 using namespace lldb_private;
25 
26 void
27 SymbolFileSymtab::Initialize()
28 {
29     PluginManager::RegisterPlugin (GetPluginNameStatic(),
30                                    GetPluginDescriptionStatic(),
31                                    CreateInstance);
32 }
33 
34 void
35 SymbolFileSymtab::Terminate()
36 {
37     PluginManager::UnregisterPlugin (CreateInstance);
38 }
39 
40 
41 const char *
42 SymbolFileSymtab::GetPluginNameStatic()
43 {
44     return "symbol-file.symtab";
45 }
46 
47 const char *
48 SymbolFileSymtab::GetPluginDescriptionStatic()
49 {
50     return "Reads debug symbols from an object file's symbol table.";
51 }
52 
53 
54 SymbolFile*
55 SymbolFileSymtab::CreateInstance (ObjectFile* obj_file)
56 {
57     return new SymbolFileSymtab(obj_file);
58 }
59 
60 SymbolFileSymtab::SymbolFileSymtab(ObjectFile* obj_file) :
61     SymbolFile(obj_file),
62     m_source_indexes(),
63     m_func_indexes(),
64     m_code_indexes(),
65     m_objc_class_name_to_index ()
66 {
67 }
68 
69 SymbolFileSymtab::~SymbolFileSymtab()
70 {
71 }
72 
73 ClangASTContext &
74 SymbolFileSymtab::GetClangASTContext ()
75 {
76     ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext();
77 
78     return ast;
79 }
80 
81 uint32_t
82 SymbolFileSymtab::CalculateAbilities ()
83 {
84     uint32_t abilities = 0;
85     if (m_obj_file)
86     {
87         const Symtab *symtab = m_obj_file->GetSymtab();
88         if (symtab)
89         {
90             //----------------------------------------------------------------------
91             // The snippet of code below will get the indexes the module symbol
92             // table entries that are code, data, or function related (debug info),
93             // sort them by value (address) and dump the sorted symbols.
94             //----------------------------------------------------------------------
95             if (symtab->AppendSymbolIndexesWithType(eSymbolTypeSourceFile, m_source_indexes))
96             {
97                 abilities |= CompileUnits;
98             }
99 
100             if (symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugYes, Symtab::eVisibilityAny, m_func_indexes))
101             {
102                 symtab->SortSymbolIndexesByValue(m_func_indexes, true);
103                 abilities |= Functions;
104             }
105 
106             if (symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny, m_code_indexes))
107             {
108                 symtab->SortSymbolIndexesByValue(m_code_indexes, true);
109                 abilities |= Labels;
110             }
111 
112             if (symtab->AppendSymbolIndexesWithType(eSymbolTypeData, m_data_indexes))
113             {
114                 symtab->SortSymbolIndexesByValue(m_data_indexes, true);
115                 abilities |= GlobalVariables;
116             }
117 
118             lldb_private::Symtab::IndexCollection objc_class_indexes;
119             if (symtab->AppendSymbolIndexesWithType (eSymbolTypeObjCClass, objc_class_indexes))
120             {
121                 abilities |= RuntimeTypes;
122                 symtab->AppendSymbolNamesToMap (objc_class_indexes,
123                                                 true,
124                                                 true,
125                                                 m_objc_class_name_to_index);
126                 m_objc_class_name_to_index.Sort();
127             }
128         }
129     }
130     return abilities;
131 }
132 
133 uint32_t
134 SymbolFileSymtab::GetNumCompileUnits()
135 {
136     // If we don't have any source file symbols we will just have one compile unit for
137     // the entire object file
138     if (m_source_indexes.empty())
139         return 0;
140 
141     // If we have any source file symbols we will logically orgnize the object symbols
142     // using these.
143     return m_source_indexes.size();
144 }
145 
146 CompUnitSP
147 SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx)
148 {
149     CompUnitSP cu_sp;
150 
151     // If we don't have any source file symbols we will just have one compile unit for
152     // the entire object file
153 //    if (m_source_indexes.empty())
154 //    {
155 //        const FileSpec &obj_file_spec = m_obj_file->GetFileSpec();
156 //        if (obj_file_spec)
157 //            cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, obj_file_spec, 0, eLanguageTypeUnknown));
158 //
159 //    }
160     /* else */ if (idx < m_source_indexes.size())
161     {
162         const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]);
163         if (cu_symbol)
164             cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, cu_symbol->GetMangled().GetName().AsCString(), 0, eLanguageTypeUnknown));
165     }
166     return cu_sp;
167 }
168 
169 size_t
170 SymbolFileSymtab::ParseCompileUnitFunctions (const SymbolContext &sc)
171 {
172     size_t num_added = 0;
173     // We must at least have a valid compile unit
174     assert (sc.comp_unit != NULL);
175     const Symtab *symtab = m_obj_file->GetSymtab();
176     const Symbol *curr_symbol = NULL;
177     const Symbol *next_symbol = NULL;
178 //  const char *prefix = m_obj_file->SymbolPrefix();
179 //  if (prefix == NULL)
180 //      prefix == "";
181 //
182 //  const uint32_t prefix_len = strlen(prefix);
183 
184     // If we don't have any source file symbols we will just have one compile unit for
185     // the entire object file
186     if (m_source_indexes.empty())
187     {
188         // The only time we will have a user ID of zero is when we don't have
189         // and source file symbols and we declare one compile unit for the
190         // entire object file
191         if (!m_func_indexes.empty())
192         {
193 
194         }
195 
196         if (!m_code_indexes.empty())
197         {
198 //          StreamFile s(stdout);
199 //          symtab->Dump(&s, m_code_indexes);
200 
201             uint32_t idx = 0;   // Index into the indexes
202             const uint32_t num_indexes = m_code_indexes.size();
203             for (idx = 0; idx < num_indexes; ++idx)
204             {
205                 uint32_t symbol_idx = m_code_indexes[idx];
206                 curr_symbol = symtab->SymbolAtIndex(symbol_idx);
207                 if (curr_symbol)
208                 {
209                     // Union of all ranges in the function DIE (if the function is discontiguous)
210                     AddressRange func_range(curr_symbol->GetValue(), 0);
211                     if (func_range.GetBaseAddress().IsSectionOffset())
212                     {
213                         uint32_t symbol_size = curr_symbol->GetByteSize();
214                         if (symbol_size != 0 && !curr_symbol->GetSizeIsSibling())
215                             func_range.SetByteSize(symbol_size);
216                         else if (idx + 1 < num_indexes)
217                         {
218                             next_symbol = symtab->SymbolAtIndex(m_code_indexes[idx + 1]);
219                             if (next_symbol)
220                             {
221                                 func_range.SetByteSize(next_symbol->GetValue().GetOffset() - curr_symbol->GetValue().GetOffset());
222                             }
223                         }
224 
225                         FunctionSP func_sp(new Function(sc.comp_unit,
226                                                             symbol_idx,                 // UserID is the DIE offset
227                                                             LLDB_INVALID_UID,           // We don't have any type info for this function
228                                                             curr_symbol->GetMangled(),  // Linker/mangled name
229                                                             NULL,                       // no return type for a code symbol...
230                                                             func_range));               // first address range
231 
232                         if (func_sp.get() != NULL)
233                         {
234                             sc.comp_unit->AddFunction(func_sp);
235                             ++num_added;
236                         }
237                     }
238                 }
239             }
240 
241         }
242     }
243     else
244     {
245         // We assume we
246     }
247     return num_added;
248 }
249 
250 bool
251 SymbolFileSymtab::ParseCompileUnitLineTable (const SymbolContext &sc)
252 {
253     return false;
254 }
255 
256 bool
257 SymbolFileSymtab::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files)
258 {
259     return false;
260 }
261 
262 size_t
263 SymbolFileSymtab::ParseFunctionBlocks (const SymbolContext &sc)
264 {
265     return 0;
266 }
267 
268 
269 size_t
270 SymbolFileSymtab::ParseTypes (const SymbolContext &sc)
271 {
272     return 0;
273 }
274 
275 
276 size_t
277 SymbolFileSymtab::ParseVariablesForContext (const SymbolContext& sc)
278 {
279     return 0;
280 }
281 
282 Type*
283 SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid)
284 {
285     return NULL;
286 }
287 
288 lldb::clang_type_t
289 SymbolFileSymtab::ResolveClangOpaqueTypeDefinition (lldb::clang_type_t clang_Type)
290 {
291     return NULL;
292 }
293 
294 ClangNamespaceDecl
295 SymbolFileSymtab::FindNamespace (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl)
296 {
297     return ClangNamespaceDecl();
298 }
299 
300 uint32_t
301 SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
302 {
303     if (m_obj_file->GetSymtab() == NULL)
304         return 0;
305 
306     uint32_t resolved_flags = 0;
307     if (resolve_scope & eSymbolContextSymbol)
308     {
309         sc.symbol = m_obj_file->GetSymtab()->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
310         if (sc.symbol)
311             resolved_flags |= eSymbolContextSymbol;
312     }
313     return resolved_flags;
314 }
315 
316 uint32_t
317 SymbolFileSymtab::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
318 {
319     return 0;
320 }
321 
322 uint32_t
323 SymbolFileSymtab::FindGlobalVariables(const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables)
324 {
325     return 0;
326 }
327 
328 uint32_t
329 SymbolFileSymtab::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
330 {
331     return 0;
332 }
333 
334 uint32_t
335 SymbolFileSymtab::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool append, SymbolContextList& sc_list)
336 {
337     Timer scoped_timer (__PRETTY_FUNCTION__,
338                         "SymbolFileSymtab::FindFunctions (name = '%s')",
339                         name.GetCString());
340     // If we ever support finding STABS or COFF debug info symbols,
341     // we will need to add support here. We are not trying to find symbols
342     // here, just "lldb_private::Function" objects that come from complete
343     // debug information. Any symbol queries should go through the symbol
344     // table itself in the module's object file.
345     return 0;
346 }
347 
348 uint32_t
349 SymbolFileSymtab::FindFunctions(const RegularExpression& regex, bool append, SymbolContextList& sc_list)
350 {
351     Timer scoped_timer (__PRETTY_FUNCTION__,
352                         "SymbolFileSymtab::FindFunctions (regex = '%s')",
353                         regex.GetText());
354     // If we ever support finding STABS or COFF debug info symbols,
355     // we will need to add support here. We are not trying to find symbols
356     // here, just "lldb_private::Function" objects that come from complete
357     // debug information. Any symbol queries should go through the symbol
358     // table itself in the module's object file.
359     return 0;
360 }
361 
362 static int CountMethodArgs(const char *method_signature)
363 {
364     int num_args = 0;
365 
366     for (const char *colon_pos = strchr(method_signature, ':');
367          colon_pos != NULL;
368          colon_pos = strchr(colon_pos + 1, ':'))
369     {
370         num_args++;
371     }
372 
373     return num_args;
374 }
375 
376 uint32_t
377 SymbolFileSymtab::FindTypes (const lldb_private::SymbolContext& sc,
378                              const lldb_private::ConstString &name,
379                              const ClangNamespaceDecl *namespace_decl,
380                              bool append,
381                              uint32_t max_matches,
382                              lldb_private::TypeList& types)
383 {
384     if (!append)
385         types.Clear();
386 
387     if (!m_objc_class_name_to_index.IsEmpty())
388     {
389         TypeMap::iterator iter = m_objc_class_types.find(name);
390 
391         if (iter != m_objc_class_types.end())
392         {
393             types.Insert(iter->second);
394             return 1;
395         }
396 
397         const Symtab::NameToIndexMap::Entry *match = m_objc_class_name_to_index.FindFirstValueForName(name.GetCString());
398 
399         if (match == NULL)
400             return 0;
401 
402         const bool isForwardDecl = true;
403         const bool isInternal = true;
404 
405         ClangASTContext &ast = GetClangASTContext();
406 
407         lldb::clang_type_t objc_object_type = ast.CreateObjCClass (name.AsCString(),
408                                                                    ast.GetTranslationUnitDecl(),
409                                                                    isForwardDecl,
410                                                                    isInternal);
411 
412         ast.StartTagDeclarationDefinition (objc_object_type);
413 
414         std::string regex_str("^[-+]\\[");     // Make sure it starts with "+[" or "-["
415         regex_str.append(name.AsCString());    // Followed by the class name
416         regex_str.append("[ \\(]");            // Followed by a space or '(' (for a category)
417         RegularExpression regex(regex_str.c_str());
418 
419         Symtab::IndexCollection indices;
420 
421         lldb::clang_type_t unknown_type = ast.GetUnknownAnyType();
422         std::vector<lldb::clang_type_t> arg_types;
423 
424         if (m_obj_file->GetSymtab()->FindAllSymbolsMatchingRexExAndType (regex, eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny, indices) != 0)
425         {
426             for (Symtab::IndexCollection::iterator pos = indices.begin(), end = indices.end();
427                  pos != end;
428                  ++pos)
429             {
430                 Symbol *symbol = m_obj_file->GetSymtab()->SymbolAtIndex(*pos);
431 
432                 if (!symbol)
433                     continue;
434 
435                 const char *signature = symbol->GetName().AsCString();
436 
437                 //printf ("%s: adding '%s'\n", name.GetCString(), signature);
438                 int num_args = CountMethodArgs(signature);
439 
440                 while (arg_types.size() < num_args)
441                     arg_types.push_back(unknown_type);
442 
443                 bool is_variadic = false;
444                 unsigned type_quals = 0;
445 
446                 lldb::clang_type_t method_type = ast.CreateFunctionType (unknown_type,
447                                                                          arg_types.data(),
448                                                                          num_args,
449                                                                          is_variadic,
450                                                                          type_quals);
451 
452                 ast.AddMethodToObjCObjectType (objc_object_type,
453                                                signature,
454                                                method_type,
455                                                eAccessPublic);
456             }
457         }
458 
459         ast.CompleteTagDeclarationDefinition (objc_object_type);
460 
461         Declaration decl;
462 
463         lldb::TypeSP type(new Type (indices[0],
464                                     this,
465                                     name,
466                                     0,      // byte_size
467                                     NULL,   // SymbolContextScope*
468                                     0,      // encoding_uid
469                                     Type::eEncodingInvalid,
470                                     decl,
471                                     objc_object_type,
472                                     Type::eResolveStateFull));
473 
474         m_objc_class_types[name] = type;
475 
476         types.Insert(type);
477 
478         return 1;
479     }
480 
481     return 0;
482 }
483 //
484 //uint32_t
485 //SymbolFileSymtab::FindTypes(const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, TypeList& types)
486 //{
487 //  return 0;
488 //}
489 
490 
491 //------------------------------------------------------------------
492 // PluginInterface protocol
493 //------------------------------------------------------------------
494 const char *
495 SymbolFileSymtab::GetPluginName()
496 {
497     return "SymbolFileSymtab";
498 }
499 
500 const char *
501 SymbolFileSymtab::GetShortPluginName()
502 {
503     return GetPluginNameStatic();
504 }
505 
506 uint32_t
507 SymbolFileSymtab::GetPluginVersion()
508 {
509     return 1;
510 }
511