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             }
110 
111             if (symtab->AppendSymbolIndexesWithType(eSymbolTypeData, m_data_indexes))
112             {
113                 symtab->SortSymbolIndexesByValue(m_data_indexes, true);
114                 abilities |= GlobalVariables;
115             }
116 
117             lldb_private::Symtab::IndexCollection objc_class_indexes;
118             if (symtab->AppendSymbolIndexesWithType (eSymbolTypeObjCClass, objc_class_indexes))
119             {
120                 symtab->AppendSymbolNamesToMap (objc_class_indexes,
121                                                 true,
122                                                 true,
123                                                 m_objc_class_name_to_index);
124                 m_objc_class_name_to_index.Sort();
125             }
126         }
127     }
128     return abilities;
129 }
130 
131 uint32_t
132 SymbolFileSymtab::GetNumCompileUnits()
133 {
134     // If we don't have any source file symbols we will just have one compile unit for
135     // the entire object file
136     if (m_source_indexes.empty())
137         return 0;
138 
139     // If we have any source file symbols we will logically orgnize the object symbols
140     // using these.
141     return m_source_indexes.size();
142 }
143 
144 CompUnitSP
145 SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx)
146 {
147     CompUnitSP cu_sp;
148 
149     // If we don't have any source file symbols we will just have one compile unit for
150     // the entire object file
151     if (idx < m_source_indexes.size())
152     {
153         const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]);
154         if (cu_symbol)
155             cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetMangled().GetName().AsCString(), 0, eLanguageTypeUnknown));
156     }
157     return cu_sp;
158 }
159 
160 size_t
161 SymbolFileSymtab::ParseCompileUnitFunctions (const SymbolContext &sc)
162 {
163     size_t num_added = 0;
164     // We must at least have a valid compile unit
165     assert (sc.comp_unit != NULL);
166     const Symtab *symtab = m_obj_file->GetSymtab();
167     const Symbol *curr_symbol = NULL;
168     const Symbol *next_symbol = NULL;
169 //  const char *prefix = m_obj_file->SymbolPrefix();
170 //  if (prefix == NULL)
171 //      prefix == "";
172 //
173 //  const uint32_t prefix_len = strlen(prefix);
174 
175     // If we don't have any source file symbols we will just have one compile unit for
176     // the entire object file
177     if (m_source_indexes.empty())
178     {
179         // The only time we will have a user ID of zero is when we don't have
180         // and source file symbols and we declare one compile unit for the
181         // entire object file
182         if (!m_func_indexes.empty())
183         {
184 
185         }
186 
187         if (!m_code_indexes.empty())
188         {
189 //          StreamFile s(stdout);
190 //          symtab->Dump(&s, m_code_indexes);
191 
192             uint32_t idx = 0;   // Index into the indexes
193             const uint32_t num_indexes = m_code_indexes.size();
194             for (idx = 0; idx < num_indexes; ++idx)
195             {
196                 uint32_t symbol_idx = m_code_indexes[idx];
197                 curr_symbol = symtab->SymbolAtIndex(symbol_idx);
198                 if (curr_symbol)
199                 {
200                     // Union of all ranges in the function DIE (if the function is discontiguous)
201                     AddressRange func_range(curr_symbol->GetAddress(), 0);
202                     if (func_range.GetBaseAddress().IsSectionOffset())
203                     {
204                         uint32_t symbol_size = curr_symbol->GetByteSize();
205                         if (symbol_size != 0 && !curr_symbol->GetSizeIsSibling())
206                             func_range.SetByteSize(symbol_size);
207                         else if (idx + 1 < num_indexes)
208                         {
209                             next_symbol = symtab->SymbolAtIndex(m_code_indexes[idx + 1]);
210                             if (next_symbol)
211                             {
212                                 func_range.SetByteSize(next_symbol->GetAddress().GetOffset() - curr_symbol->GetAddress().GetOffset());
213                             }
214                         }
215 
216                         FunctionSP func_sp(new Function(sc.comp_unit,
217                                                             symbol_idx,                 // UserID is the DIE offset
218                                                             LLDB_INVALID_UID,           // We don't have any type info for this function
219                                                             curr_symbol->GetMangled(),  // Linker/mangled name
220                                                             NULL,                       // no return type for a code symbol...
221                                                             func_range));               // first address range
222 
223                         if (func_sp.get() != NULL)
224                         {
225                             sc.comp_unit->AddFunction(func_sp);
226                             ++num_added;
227                         }
228                     }
229                 }
230             }
231 
232         }
233     }
234     else
235     {
236         // We assume we
237     }
238     return num_added;
239 }
240 
241 bool
242 SymbolFileSymtab::ParseCompileUnitLineTable (const SymbolContext &sc)
243 {
244     return false;
245 }
246 
247 bool
248 SymbolFileSymtab::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files)
249 {
250     return false;
251 }
252 
253 size_t
254 SymbolFileSymtab::ParseFunctionBlocks (const SymbolContext &sc)
255 {
256     return 0;
257 }
258 
259 
260 size_t
261 SymbolFileSymtab::ParseTypes (const SymbolContext &sc)
262 {
263     return 0;
264 }
265 
266 
267 size_t
268 SymbolFileSymtab::ParseVariablesForContext (const SymbolContext& sc)
269 {
270     return 0;
271 }
272 
273 Type*
274 SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid)
275 {
276     return NULL;
277 }
278 
279 lldb::clang_type_t
280 SymbolFileSymtab::ResolveClangOpaqueTypeDefinition (lldb::clang_type_t clang_Type)
281 {
282     return NULL;
283 }
284 
285 ClangNamespaceDecl
286 SymbolFileSymtab::FindNamespace (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl)
287 {
288     return ClangNamespaceDecl();
289 }
290 
291 uint32_t
292 SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
293 {
294     if (m_obj_file->GetSymtab() == NULL)
295         return 0;
296 
297     uint32_t resolved_flags = 0;
298     if (resolve_scope & eSymbolContextSymbol)
299     {
300         sc.symbol = m_obj_file->GetSymtab()->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
301         if (sc.symbol)
302             resolved_flags |= eSymbolContextSymbol;
303     }
304     return resolved_flags;
305 }
306 
307 uint32_t
308 SymbolFileSymtab::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
309 {
310     return 0;
311 }
312 
313 uint32_t
314 SymbolFileSymtab::FindGlobalVariables(const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables)
315 {
316     return 0;
317 }
318 
319 uint32_t
320 SymbolFileSymtab::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
321 {
322     return 0;
323 }
324 
325 uint32_t
326 SymbolFileSymtab::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines,  bool append, SymbolContextList& sc_list)
327 {
328     Timer scoped_timer (__PRETTY_FUNCTION__,
329                         "SymbolFileSymtab::FindFunctions (name = '%s')",
330                         name.GetCString());
331     // If we ever support finding STABS or COFF debug info symbols,
332     // we will need to add support here. We are not trying to find symbols
333     // here, just "lldb_private::Function" objects that come from complete
334     // debug information. Any symbol queries should go through the symbol
335     // table itself in the module's object file.
336     return 0;
337 }
338 
339 uint32_t
340 SymbolFileSymtab::FindFunctions(const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list)
341 {
342     Timer scoped_timer (__PRETTY_FUNCTION__,
343                         "SymbolFileSymtab::FindFunctions (regex = '%s')",
344                         regex.GetText());
345     // If we ever support finding STABS or COFF debug info symbols,
346     // we will need to add support here. We are not trying to find symbols
347     // here, just "lldb_private::Function" objects that come from complete
348     // debug information. Any symbol queries should go through the symbol
349     // table itself in the module's object file.
350     return 0;
351 }
352 
353 static int CountMethodArgs(const char *method_signature)
354 {
355     int num_args = 0;
356 
357     for (const char *colon_pos = strchr(method_signature, ':');
358          colon_pos != NULL;
359          colon_pos = strchr(colon_pos + 1, ':'))
360     {
361         num_args++;
362     }
363 
364     return num_args;
365 }
366 
367 uint32_t
368 SymbolFileSymtab::FindTypes (const lldb_private::SymbolContext& sc,
369                              const lldb_private::ConstString &name,
370                              const ClangNamespaceDecl *namespace_decl,
371                              bool append,
372                              uint32_t max_matches,
373                              lldb_private::TypeList& types)
374 {
375     if (!append)
376         types.Clear();
377 
378     if (!m_objc_class_name_to_index.IsEmpty())
379     {
380         TypeMap::iterator iter = m_objc_class_types.find(name);
381 
382         if (iter != m_objc_class_types.end())
383         {
384             types.Insert(iter->second);
385             return 1;
386         }
387 
388         const Symtab::NameToIndexMap::Entry *match = m_objc_class_name_to_index.FindFirstValueForName(name.GetCString());
389 
390         if (match == NULL)
391             return 0;
392 
393         const bool isForwardDecl = false;
394         const bool isInternal = true;
395 
396         ClangASTContext &ast = GetClangASTContext();
397 
398         lldb::clang_type_t objc_object_type = ast.CreateObjCClass (name.AsCString(),
399                                                                    ast.GetTranslationUnitDecl(),
400                                                                    isForwardDecl,
401                                                                    isInternal,
402                                                                    0xffaaffaaffaaffaall);
403 
404         Declaration decl;
405 
406         lldb::TypeSP type(new Type (match->value,
407                                     this,
408                                     name,
409                                     0,      // byte_size - don't change this from 0, we currently use that to identify these "synthetic" ObjC class types.
410                                     NULL,   // SymbolContextScope*
411                                     0,      // encoding_uid
412                                     Type::eEncodingInvalid,
413                                     decl,
414                                     objc_object_type,
415                                     Type::eResolveStateFull));
416 
417         m_objc_class_types[name] = type;
418 
419         types.Insert(type);
420 
421         return 1;
422     }
423 
424     return 0;
425 }
426 //
427 //uint32_t
428 //SymbolFileSymtab::FindTypes(const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, TypeList& types)
429 //{
430 //  return 0;
431 //}
432 
433 
434 //------------------------------------------------------------------
435 // PluginInterface protocol
436 //------------------------------------------------------------------
437 const char *
438 SymbolFileSymtab::GetPluginName()
439 {
440     return "SymbolFileSymtab";
441 }
442 
443 const char *
444 SymbolFileSymtab::GetShortPluginName()
445 {
446     return GetPluginNameStatic();
447 }
448 
449 uint32_t
450 SymbolFileSymtab::GetPluginVersion()
451 {
452     return 1;
453 }
454