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