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