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