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