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 size_t
64 SymbolFileSymtab::GetTypes (SymbolContextScope *sc_scope, uint32_t type_mask, lldb_private::TypeList &type_list)
65 {
66     return 0;
67 }
68 
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 
78 SymbolFileSymtab::~SymbolFileSymtab()
79 {
80 }
81 
82 ClangASTContext &
83 SymbolFileSymtab::GetClangASTContext ()
84 {
85     ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext();
86 
87     return ast;
88 }
89 
90 uint32_t
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                 abilities |= Functions;
119             }
120 
121             if (symtab->AppendSymbolIndexesWithType(eSymbolTypeData, m_data_indexes))
122             {
123                 symtab->SortSymbolIndexesByValue(m_data_indexes, true);
124                 abilities |= GlobalVariables;
125             }
126 
127             lldb_private::Symtab::IndexCollection objc_class_indexes;
128             if (symtab->AppendSymbolIndexesWithType (eSymbolTypeObjCClass, objc_class_indexes))
129             {
130                 symtab->AppendSymbolNamesToMap (objc_class_indexes,
131                                                 true,
132                                                 true,
133                                                 m_objc_class_name_to_index);
134                 m_objc_class_name_to_index.Sort();
135             }
136         }
137     }
138     return abilities;
139 }
140 
141 uint32_t
142 SymbolFileSymtab::GetNumCompileUnits()
143 {
144     // If we don't have any source file symbols we will just have one compile unit for
145     // the entire object file
146     if (m_source_indexes.empty())
147         return 0;
148 
149     // If we have any source file symbols we will logically organize the object symbols
150     // using these.
151     return m_source_indexes.size();
152 }
153 
154 CompUnitSP
155 SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx)
156 {
157     CompUnitSP cu_sp;
158 
159     // If we don't have any source file symbols we will just have one compile unit for
160     // the entire object file
161     if (idx < m_source_indexes.size())
162     {
163         const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]);
164         if (cu_symbol)
165             cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown, false));
166     }
167     return cu_sp;
168 }
169 
170 lldb::LanguageType
171 SymbolFileSymtab::ParseCompileUnitLanguage (const SymbolContext& sc)
172 {
173     return eLanguageTypeUnknown;
174 }
175 
176 
177 size_t
178 SymbolFileSymtab::ParseCompileUnitFunctions (const SymbolContext &sc)
179 {
180     size_t num_added = 0;
181     // We must at least have a valid compile unit
182     assert (sc.comp_unit != NULL);
183     const Symtab *symtab = m_obj_file->GetSymtab();
184     const Symbol *curr_symbol = NULL;
185     const Symbol *next_symbol = NULL;
186 //  const char *prefix = m_obj_file->SymbolPrefix();
187 //  if (prefix == NULL)
188 //      prefix == "";
189 //
190 //  const uint32_t prefix_len = strlen(prefix);
191 
192     // If we don't have any source file symbols we will just have one compile unit for
193     // the entire object file
194     if (m_source_indexes.empty())
195     {
196         // The only time we will have a user ID of zero is when we don't have
197         // and source file symbols and we declare one compile unit for the
198         // entire object file
199         if (!m_func_indexes.empty())
200         {
201 
202         }
203 
204         if (!m_code_indexes.empty())
205         {
206 //          StreamFile s(stdout);
207 //          symtab->Dump(&s, m_code_indexes);
208 
209             uint32_t idx = 0;   // Index into the indexes
210             const uint32_t num_indexes = m_code_indexes.size();
211             for (idx = 0; idx < num_indexes; ++idx)
212             {
213                 uint32_t symbol_idx = m_code_indexes[idx];
214                 curr_symbol = symtab->SymbolAtIndex(symbol_idx);
215                 if (curr_symbol)
216                 {
217                     // Union of all ranges in the function DIE (if the function is discontiguous)
218                     AddressRange func_range(curr_symbol->GetAddress(), 0);
219                     if (func_range.GetBaseAddress().IsSectionOffset())
220                     {
221                         uint32_t symbol_size = curr_symbol->GetByteSize();
222                         if (symbol_size != 0 && !curr_symbol->GetSizeIsSibling())
223                             func_range.SetByteSize(symbol_size);
224                         else if (idx + 1 < num_indexes)
225                         {
226                             next_symbol = symtab->SymbolAtIndex(m_code_indexes[idx + 1]);
227                             if (next_symbol)
228                             {
229                                 func_range.SetByteSize(next_symbol->GetAddressRef().GetOffset() - curr_symbol->GetAddressRef().GetOffset());
230                             }
231                         }
232 
233                         FunctionSP func_sp(new Function(sc.comp_unit,
234                                                             symbol_idx,                 // UserID is the DIE offset
235                                                             LLDB_INVALID_UID,           // We don't have any type info for this function
236                                                             curr_symbol->GetMangled(),  // Linker/mangled name
237                                                             NULL,                       // no return type for a code symbol...
238                                                             func_range));               // first address range
239 
240                         if (func_sp.get() != NULL)
241                         {
242                             sc.comp_unit->AddFunction(func_sp);
243                             ++num_added;
244                         }
245                     }
246                 }
247             }
248 
249         }
250     }
251     else
252     {
253         // We assume we
254     }
255     return num_added;
256 }
257 
258 bool
259 SymbolFileSymtab::ParseCompileUnitLineTable (const SymbolContext &sc)
260 {
261     return false;
262 }
263 
264 bool
265 SymbolFileSymtab::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files)
266 {
267     return false;
268 }
269 
270 bool
271 SymbolFileSymtab::ParseImportedModules (const SymbolContext &sc, std::vector<ConstString> &imported_modules)
272 {
273     return false;
274 }
275 
276 size_t
277 SymbolFileSymtab::ParseFunctionBlocks (const SymbolContext &sc)
278 {
279     return 0;
280 }
281 
282 
283 size_t
284 SymbolFileSymtab::ParseTypes (const SymbolContext &sc)
285 {
286     return 0;
287 }
288 
289 
290 size_t
291 SymbolFileSymtab::ParseVariablesForContext (const SymbolContext& sc)
292 {
293     return 0;
294 }
295 
296 Type*
297 SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid)
298 {
299     return NULL;
300 }
301 
302 bool
303 SymbolFileSymtab::CompleteType (lldb_private::CompilerType& clang_opaque_type)
304 {
305     return false;
306 }
307 
308 uint32_t
309 SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
310 {
311     if (m_obj_file->GetSymtab() == NULL)
312         return 0;
313 
314     uint32_t resolved_flags = 0;
315     if (resolve_scope & eSymbolContextSymbol)
316     {
317         sc.symbol = m_obj_file->GetSymtab()->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
318         if (sc.symbol)
319             resolved_flags |= eSymbolContextSymbol;
320     }
321     return resolved_flags;
322 }
323 
324 //------------------------------------------------------------------
325 // PluginInterface protocol
326 //------------------------------------------------------------------
327 lldb_private::ConstString
328 SymbolFileSymtab::GetPluginName()
329 {
330     return GetPluginNameStatic();
331 }
332 
333 uint32_t
334 SymbolFileSymtab::GetPluginVersion()
335 {
336     return 1;
337 }
338