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