Module.cpp revision 24943d2ee8bfaa7cf5893e4709143924157a5c1e
1//===-- Module.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 "lldb/Core/Module.h"
11#include "lldb/Core/Log.h"
12#include "lldb/Core/ModuleList.h"
13#include "lldb/Core/RegularExpression.h"
14#include "lldb/Core/Timer.h"
15#include "lldb/lldb-private-log.h"
16#include "lldb/Symbol/ObjectFile.h"
17#include "lldb/Symbol/SymbolContext.h"
18#include "lldb/Symbol/SymbolVendor.h"
19
20using namespace lldb;
21using namespace lldb_private;
22
23Module::Module(const FileSpec& file_spec, const ArchSpec& arch, const ConstString *object_name, off_t object_offset) :
24    m_mutex (Mutex::eMutexTypeRecursive),
25    m_mod_time (file_spec.GetModificationTime()),
26    m_arch (arch),
27    m_uuid (),
28    m_file (file_spec),
29    m_flags (),
30    m_object_name (),
31    m_objfile_ap (),
32    m_symfile_ap ()
33{
34    if (object_name)
35        m_object_name = *object_name;
36    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
37    if (log)
38        log->Printf ("%p Module::Module((%s) '%s/%s%s%s%s')",
39                     this,
40                     m_arch.AsCString(),
41                     m_file.GetDirectory().AsCString(""),
42                     m_file.GetFilename().AsCString(""),
43                     m_object_name.IsEmpty() ? "" : "(",
44                     m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""),
45                     m_object_name.IsEmpty() ? "" : ")");
46
47}
48
49Module::~Module()
50{
51    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
52    if (log)
53        log->Printf ("%p Module::~Module((%s) '%s/%s%s%s%s')",
54                     this,
55                     m_arch.AsCString(),
56                     m_file.GetDirectory().AsCString(""),
57                     m_file.GetFilename().AsCString(""),
58                     m_object_name.IsEmpty() ? "" : "(",
59                     m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""),
60                     m_object_name.IsEmpty() ? "" : ")");
61}
62
63
64ModuleSP
65Module::GetSP ()
66{
67    return ModuleList::GetModuleSP (this);
68}
69
70const UUID&
71Module::GetUUID()
72{
73    Mutex::Locker locker (m_mutex);
74    if (m_flags.IsClear(flagsParsedUUID))
75    {
76        ObjectFile * obj_file = GetObjectFile ();
77
78        if (obj_file != NULL)
79        {
80            obj_file->GetUUID(&m_uuid);
81            m_flags.Set(flagsParsedUUID);
82        }
83    }
84    return m_uuid;
85}
86
87void
88Module::ParseAllDebugSymbols()
89{
90    Mutex::Locker locker (m_mutex);
91    uint32_t num_comp_units = GetNumCompileUnits();
92    if (num_comp_units == 0)
93        return;
94
95    TargetSP null_target;
96    SymbolContext sc(null_target, GetSP());
97    uint32_t cu_idx;
98    SymbolVendor *symbols = GetSymbolVendor ();
99
100    for (cu_idx = 0; cu_idx < num_comp_units; cu_idx++)
101    {
102        sc.comp_unit = symbols->GetCompileUnitAtIndex(cu_idx).get();
103        if (sc.comp_unit)
104        {
105            sc.function = NULL;
106            symbols->ParseVariablesForContext(sc);
107
108            symbols->ParseCompileUnitFunctions(sc);
109
110            uint32_t func_idx;
111            for (func_idx = 0; (sc.function = sc.comp_unit->GetFunctionAtIndex(func_idx).get()) != NULL; ++func_idx)
112            {
113                symbols->ParseFunctionBlocks(sc);
114
115                // Parse the variables for this function and all its blocks
116                symbols->ParseVariablesForContext(sc);
117            }
118
119
120            // Parse all types for this compile unit
121            sc.function = NULL;
122            symbols->ParseTypes(sc);
123        }
124    }
125}
126
127void
128Module::CalculateSymbolContext(SymbolContext* sc)
129{
130    sc->module_sp = GetSP();
131}
132
133void
134Module::DumpSymbolContext(Stream *s)
135{
136    s->Printf(", Module{0x%8.8x}", this);
137}
138
139uint32_t
140Module::GetNumCompileUnits()
141{
142    Mutex::Locker locker (m_mutex);
143    Timer scoped_timer(__PRETTY_FUNCTION__, "Module::GetNumCompileUnits (module = %p)", this);
144    SymbolVendor *symbols = GetSymbolVendor ();
145    if (symbols)
146        return symbols->GetNumCompileUnits();
147    return 0;
148}
149
150CompUnitSP
151Module::GetCompileUnitAtIndex (uint32_t index)
152{
153    Mutex::Locker locker (m_mutex);
154    uint32_t num_comp_units = GetNumCompileUnits ();
155    CompUnitSP cu_sp;
156
157    if (index < num_comp_units)
158    {
159        SymbolVendor *symbols = GetSymbolVendor ();
160        if (symbols)
161            cu_sp = symbols->GetCompileUnitAtIndex(index);
162    }
163    return cu_sp;
164}
165
166//CompUnitSP
167//Module::FindCompUnit(lldb::user_id_t uid)
168//{
169//  CompUnitSP cu_sp;
170//  SymbolVendor *symbols = GetSymbolVendor ();
171//  if (symbols)
172//      cu_sp = symbols->FindCompUnit(uid);
173//  return cu_sp;
174//}
175
176bool
177Module::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr)
178{
179    Mutex::Locker locker (m_mutex);
180    Timer scoped_timer(__PRETTY_FUNCTION__, "Module::ResolveFileAddress (vm_addr = 0x%llx)", vm_addr);
181    ObjectFile* ofile = GetObjectFile();
182    if (ofile)
183        return so_addr.ResolveAddressUsingFileSections(vm_addr, ofile->GetSectionList());
184    return false;
185}
186
187uint32_t
188Module::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
189{
190    Mutex::Locker locker (m_mutex);
191    uint32_t resolved_flags = 0;
192
193    // Clear the result symbol context in case we don't find anything
194    sc.Clear();
195
196    // Get the section from the section/offset address.
197    const Section *section = so_addr.GetSection();
198
199    // Make sure the section matches this module before we try and match anything
200    if (section && section->GetModule() == this)
201    {
202        // If the section offset based address resolved itself, then this
203        // is the right module.
204        sc.module_sp = GetSP();
205        resolved_flags |= eSymbolContextModule;
206
207        // Resolve the compile unit, function, block, line table or line
208        // entry if requested.
209        if (resolve_scope & eSymbolContextCompUnit    ||
210            resolve_scope & eSymbolContextFunction    ||
211            resolve_scope & eSymbolContextBlock       ||
212            resolve_scope & eSymbolContextLineEntry   )
213        {
214            SymbolVendor *symbols = GetSymbolVendor ();
215            if (symbols)
216                resolved_flags |= symbols->ResolveSymbolContext (so_addr, resolve_scope, sc);
217        }
218
219        // Resolve the symbol if requested
220        if (resolve_scope & eSymbolContextSymbol)
221        {
222            ObjectFile* ofile = GetObjectFile();
223            if (ofile)
224            {
225                Symtab *symtab = ofile->GetSymtab();
226                if (symtab)
227                {
228                    if (so_addr.IsSectionOffset())
229                    {
230                        sc.symbol = symtab->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
231                        if (sc.symbol)
232                            resolved_flags |= eSymbolContextSymbol;
233                    }
234                }
235            }
236        }
237    }
238    return resolved_flags;
239}
240
241uint32_t
242Module::ResolveSymbolContextForFilePath (const char *file_path, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
243{
244    FileSpec file_spec(file_path);
245    return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list);
246}
247
248uint32_t
249Module::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
250{
251    Mutex::Locker locker (m_mutex);
252    Timer scoped_timer(__PRETTY_FUNCTION__,
253                       "Module::ResolveSymbolContextForFilePath (%s%s%s:%u, check_inlines = %s, resolve_scope = 0x%8.8x)",
254                       file_spec.GetDirectory().AsCString(""),
255                       file_spec.GetDirectory() ? "/" : "",
256                       file_spec.GetFilename().AsCString(""),
257                       line,
258                       check_inlines ? "yes" : "no",
259                       resolve_scope);
260
261    const uint32_t initial_count = sc_list.GetSize();
262
263    SymbolVendor *symbols = GetSymbolVendor  ();
264    if (symbols)
265        symbols->ResolveSymbolContext (file_spec, line, check_inlines, resolve_scope, sc_list);
266
267    return sc_list.GetSize() - initial_count;
268}
269
270
271uint32_t
272Module::FindGlobalVariables(const ConstString &name, bool append, uint32_t max_matches, VariableList& variables)
273{
274    SymbolVendor *symbols = GetSymbolVendor ();
275    if (symbols)
276        return symbols->FindGlobalVariables(name, append, max_matches, variables);
277    return 0;
278}
279uint32_t
280Module::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
281{
282    SymbolVendor *symbols = GetSymbolVendor ();
283    if (symbols)
284        return symbols->FindGlobalVariables(regex, append, max_matches, variables);
285    return 0;
286}
287
288uint32_t
289Module::FindFunctions(const ConstString &name, bool append, SymbolContextList& sc_list)
290{
291    SymbolVendor *symbols = GetSymbolVendor ();
292    if (symbols)
293        return symbols->FindFunctions(name, append, sc_list);
294    return 0;
295}
296
297uint32_t
298Module::FindFunctions(const RegularExpression& regex, bool append, SymbolContextList& sc_list)
299{
300    SymbolVendor *symbols = GetSymbolVendor ();
301    if (symbols)
302        return symbols->FindFunctions(regex, append, sc_list);
303    return 0;
304}
305
306//uint32_t
307//Module::FindTypes(const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, Type::Encoding encoding, const char *udt_name, TypeList& types)
308//{
309//  Timer scoped_timer(__PRETTY_FUNCTION__);
310//  SymbolVendor *symbols = GetSymbolVendor ();
311//  if (symbols)
312//      return symbols->FindTypes(sc, name, append, max_matches, encoding, udt_name, types);
313//  return 0;
314//}
315//
316//uint32_t
317//Module::FindTypes(const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, Type::Encoding encoding, const char *udt_name, TypeList& types)
318//{
319//  Timer scoped_timer(__PRETTY_FUNCTION__);
320//  SymbolVendor *symbols = GetSymbolVendor ();
321//  if (symbols)
322//      return symbols->FindTypes(sc, regex, append, max_matches, encoding, udt_name, types);
323//  return 0;
324//
325//}
326
327SymbolVendor*
328Module::GetSymbolVendor (bool can_create)
329{
330    Mutex::Locker locker (m_mutex);
331    if (m_flags.IsClear(flagsSearchedForSymVendor) && can_create)
332    {
333        ObjectFile *obj_file = GetObjectFile ();
334        if (obj_file != NULL)
335        {
336            Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
337            m_symfile_ap.reset(SymbolVendor::FindPlugin(this));
338            m_flags.Set (flagsSearchedForSymVendor);
339        }
340    }
341    return m_symfile_ap.get();
342}
343
344const FileSpec &
345Module::GetFileSpec () const
346{
347    return m_file;
348}
349
350void
351Module::SetFileSpecAndObjectName (const FileSpec &file, const ConstString &object_name)
352{
353    // Container objects whose paths do not specify a file directly can call
354    // this function to correct the file and object names.
355    m_file = file;
356    m_mod_time = file.GetModificationTime();
357    m_object_name = object_name;
358}
359
360const ArchSpec&
361Module::GetArchitecture () const
362{
363    return m_arch;
364}
365
366void
367Module::Dump(Stream *s)
368{
369    Mutex::Locker locker (m_mutex);
370    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
371    s->Indent();
372    s->Printf("Module %s/%s%s%s%s\n",
373              m_file.GetDirectory().AsCString(),
374              m_file.GetFilename().AsCString(),
375              m_object_name ? "(" : "",
376              m_object_name ? m_object_name.GetCString() : "",
377              m_object_name ? ")" : "");
378
379    s->IndentMore();
380    ObjectFile *objfile = GetObjectFile ();
381
382    if (objfile)
383        objfile->Dump(s);
384
385    SymbolVendor *symbols = GetSymbolVendor ();
386
387    if (symbols)
388        symbols->Dump(s);
389
390    s->IndentLess();
391}
392
393
394TypeList*
395Module::GetTypeList ()
396{
397    SymbolVendor *symbols = GetSymbolVendor ();
398    if (symbols)
399        return &symbols->GetTypeList();
400    return NULL;
401}
402
403const ConstString &
404Module::GetObjectName() const
405{
406    return m_object_name;
407}
408
409ObjectFile *
410Module::GetObjectFile()
411{
412    Mutex::Locker locker (m_mutex);
413    if (m_flags.IsClear(flagsSearchedForObjParser))
414    {
415        m_flags.Set (flagsSearchedForObjParser);
416        Timer scoped_timer(__PRETTY_FUNCTION__,
417                           "Module::GetObjectFile () module = %s", GetFileSpec().GetFilename().AsCString(""));
418        m_objfile_ap.reset(ObjectFile::FindPlugin(this, &m_file, 0, m_file.GetByteSize()));
419    }
420    return m_objfile_ap.get();
421}
422
423
424const Symbol *
425Module::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type)
426{
427    Timer scoped_timer(__PRETTY_FUNCTION__,
428                       "Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)",
429                       name.AsCString(),
430                       symbol_type);
431    ObjectFile *objfile = GetObjectFile();
432    if (objfile)
433    {
434        Symtab *symtab = objfile->GetSymtab();
435        if (symtab)
436            return symtab->FindFirstSymbolWithNameAndType (name, symbol_type);
437    }
438    return NULL;
439}
440void
441Module::SymbolIndicesToSymbolContextList (Symtab *symtab, std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list)
442{
443    // No need to protect this call using m_mutex all other method calls are
444    // already thread safe.
445
446    size_t num_indices = symbol_indexes.size();
447    if (num_indices > 0)
448    {
449        SymbolContext sc;
450        CalculateSymbolContext (&sc);
451        for (size_t i = 0; i < num_indices; i++)
452        {
453            sc.symbol = symtab->SymbolAtIndex (symbol_indexes[i]);
454            if (sc.symbol)
455                sc_list.Append (sc);
456        }
457    }
458}
459
460size_t
461Module::FindSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, SymbolContextList &sc_list)
462{
463    // No need to protect this call using m_mutex all other method calls are
464    // already thread safe.
465
466
467    Timer scoped_timer(__PRETTY_FUNCTION__,
468                       "Module::FindSymbolsWithNameAndType (name = %s, type = %i)",
469                       name.AsCString(),
470                       symbol_type);
471    const size_t initial_size = sc_list.GetSize();
472    ObjectFile *objfile = GetObjectFile ();
473    if (objfile)
474    {
475        Symtab *symtab = objfile->GetSymtab();
476        if (symtab)
477        {
478            std::vector<uint32_t> symbol_indexes;
479            symtab->FindAllSymbolsWithNameAndType (name, symbol_type, symbol_indexes);
480            SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list);
481        }
482    }
483    return sc_list.GetSize() - initial_size;
484}
485
486size_t
487Module::FindSymbolsMatchingRegExAndType (const RegularExpression &regex, SymbolType symbol_type, SymbolContextList &sc_list)
488{
489    // No need to protect this call using m_mutex all other method calls are
490    // already thread safe.
491
492    Timer scoped_timer(__PRETTY_FUNCTION__,
493                       "Module::FindSymbolsMatchingRegExAndType (regex = %s, type = %i)",
494                       regex.GetText(),
495                       symbol_type);
496    const size_t initial_size = sc_list.GetSize();
497    ObjectFile *objfile = GetObjectFile ();
498    if (objfile)
499    {
500        Symtab *symtab = objfile->GetSymtab();
501        if (symtab)
502        {
503            std::vector<uint32_t> symbol_indexes;
504            symtab->FindAllSymbolsMatchingRexExAndType (regex, symbol_type, symbol_indexes);
505            SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list);
506        }
507    }
508    return sc_list.GetSize() - initial_size;
509}
510
511const TimeValue &
512Module::GetModificationTime () const
513{
514    return m_mod_time;
515}
516