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
25using namespace lldb;
26using namespace lldb_private;
27
28void
29SymbolFileSymtab::Initialize()
30{
31    PluginManager::RegisterPlugin (GetPluginNameStatic(),
32                                   GetPluginDescriptionStatic(),
33                                   CreateInstance);
34}
35
36void
37SymbolFileSymtab::Terminate()
38{
39    PluginManager::UnregisterPlugin (CreateInstance);
40}
41
42
43lldb_private::ConstString
44SymbolFileSymtab::GetPluginNameStatic()
45{
46    static ConstString g_name("symtab");
47    return g_name;
48}
49
50const char *
51SymbolFileSymtab::GetPluginDescriptionStatic()
52{
53    return "Reads debug symbols from an object file's symbol table.";
54}
55
56
57SymbolFile*
58SymbolFileSymtab::CreateInstance (ObjectFile* obj_file)
59{
60    return new SymbolFileSymtab(obj_file);
61}
62
63size_t
64SymbolFileSymtab::GetTypes (SymbolContextScope *sc_scope, uint32_t type_mask, lldb_private::TypeList &type_list)
65{
66    return 0;
67}
68
69SymbolFileSymtab::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
78SymbolFileSymtab::~SymbolFileSymtab()
79{
80}
81
82ClangASTContext &
83SymbolFileSymtab::GetClangASTContext ()
84{
85    ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext();
86
87    return ast;
88}
89
90uint32_t
91SymbolFileSymtab::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
140uint32_t
141SymbolFileSymtab::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
153CompUnitSP
154SymbolFileSymtab::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
169lldb::LanguageType
170SymbolFileSymtab::ParseCompileUnitLanguage (const SymbolContext& sc)
171{
172    return eLanguageTypeUnknown;
173}
174
175
176size_t
177SymbolFileSymtab::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
257bool
258SymbolFileSymtab::ParseCompileUnitLineTable (const SymbolContext &sc)
259{
260    return false;
261}
262
263bool
264SymbolFileSymtab::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files)
265{
266    return false;
267}
268
269size_t
270SymbolFileSymtab::ParseFunctionBlocks (const SymbolContext &sc)
271{
272    return 0;
273}
274
275
276size_t
277SymbolFileSymtab::ParseTypes (const SymbolContext &sc)
278{
279    return 0;
280}
281
282
283size_t
284SymbolFileSymtab::ParseVariablesForContext (const SymbolContext& sc)
285{
286    return 0;
287}
288
289Type*
290SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid)
291{
292    return NULL;
293}
294
295bool
296SymbolFileSymtab::ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_opaque_type)
297{
298    return false;
299}
300
301ClangNamespaceDecl
302SymbolFileSymtab::FindNamespace (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl)
303{
304    return ClangNamespaceDecl();
305}
306
307uint32_t
308SymbolFileSymtab::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
323uint32_t
324SymbolFileSymtab::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
325{
326    return 0;
327}
328
329uint32_t
330SymbolFileSymtab::FindGlobalVariables(const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables)
331{
332    return 0;
333}
334
335uint32_t
336SymbolFileSymtab::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
337{
338    return 0;
339}
340
341uint32_t
342SymbolFileSymtab::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
355uint32_t
356SymbolFileSymtab::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
369static 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
383uint32_t
384SymbolFileSymtab::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//------------------------------------------------------------------
397lldb_private::ConstString
398SymbolFileSymtab::GetPluginName()
399{
400    return GetPluginNameStatic();
401}
402
403uint32_t
404SymbolFileSymtab::GetPluginVersion()
405{
406    return 1;
407}
408