Symbol.cpp revision 49ce8969d3154e1560106cfe530444c09410f217
1//===-- Symbol.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/Symbol/Symbol.h"
11
12#include "lldb/Core/Module.h"
13#include "lldb/Core/Section.h"
14#include "lldb/Core/Stream.h"
15#include "lldb/Symbol/ObjectFile.h"
16#include "lldb/Symbol/Symtab.h"
17#include "lldb/Target/Process.h"
18#include "lldb/Target/Target.h"
19
20using namespace lldb;
21using namespace lldb_private;
22
23
24Symbol::Symbol() :
25    SymbolContextScope (),
26    m_uid (UINT32_MAX),
27    m_mangled (),
28    m_type_data (0),
29    m_type_data_resolved (false),
30    m_is_synthetic (false),
31    m_is_debug (false),
32    m_is_external (false),
33    m_size_is_sibling (false),
34    m_size_is_synthesized (false),
35    m_calculated_size (false),
36    m_type (eSymbolTypeInvalid),
37    m_flags (),
38    m_addr_range ()
39{
40}
41
42Symbol::Symbol
43(
44    uint32_t symID,
45    const char *name,
46    bool name_is_mangled,
47    SymbolType type,
48    bool external,
49    bool is_debug,
50    bool is_trampoline,
51    bool is_artificial,
52    const lldb::SectionSP &section_sp,
53    addr_t offset,
54    uint32_t size,
55    uint32_t flags
56) :
57    SymbolContextScope (),
58    m_uid (symID),
59    m_mangled (ConstString(name), name_is_mangled),
60    m_type_data (0),
61    m_type_data_resolved (false),
62    m_is_synthetic (is_artificial),
63    m_is_debug (is_debug),
64    m_is_external (external),
65    m_size_is_sibling (false),
66    m_size_is_synthesized (false),
67    m_calculated_size (size > 0),
68    m_type (type),
69    m_flags (flags),
70    m_addr_range (section_sp, offset, size)
71{
72}
73
74Symbol::Symbol
75(
76    uint32_t symID,
77    const char *name,
78    bool name_is_mangled,
79    SymbolType type,
80    bool external,
81    bool is_debug,
82    bool is_trampoline,
83    bool is_artificial,
84    const AddressRange &range,
85    uint32_t flags
86) :
87    SymbolContextScope (),
88    m_uid (symID),
89    m_mangled (ConstString(name), name_is_mangled),
90    m_type_data (0),
91    m_type_data_resolved (false),
92    m_is_synthetic (is_artificial),
93    m_is_debug (is_debug),
94    m_is_external (external),
95    m_size_is_sibling (false),
96    m_size_is_synthesized (false),
97    m_calculated_size (range.GetByteSize() > 0),
98    m_type (type),
99    m_flags (flags),
100    m_addr_range (range)
101{
102}
103
104Symbol::Symbol(const Symbol& rhs):
105    SymbolContextScope (rhs),
106    m_uid (rhs.m_uid),
107    m_mangled (rhs.m_mangled),
108    m_type_data (rhs.m_type_data),
109    m_type_data_resolved (rhs.m_type_data_resolved),
110    m_is_synthetic (rhs.m_is_synthetic),
111    m_is_debug (rhs.m_is_debug),
112    m_is_external (rhs.m_is_external),
113    m_size_is_sibling (rhs.m_size_is_sibling),
114    m_size_is_synthesized (false),
115    m_calculated_size (rhs.m_calculated_size),
116    m_type (rhs.m_type),
117    m_flags (rhs.m_flags),
118    m_addr_range (rhs.m_addr_range)
119{
120}
121
122const Symbol&
123Symbol::operator= (const Symbol& rhs)
124{
125    if (this != &rhs)
126    {
127        SymbolContextScope::operator= (rhs);
128        m_uid = rhs.m_uid;
129        m_mangled = rhs.m_mangled;
130        m_type_data = rhs.m_type_data;
131        m_type_data_resolved = rhs.m_type_data_resolved;
132        m_is_synthetic = rhs.m_is_synthetic;
133        m_is_debug = rhs.m_is_debug;
134        m_is_external = rhs.m_is_external;
135        m_size_is_sibling = rhs.m_size_is_sibling;
136        m_size_is_synthesized = rhs.m_size_is_sibling;
137        m_calculated_size = rhs.m_calculated_size;
138        m_type = rhs.m_type;
139        m_flags = rhs.m_flags;
140        m_addr_range = rhs.m_addr_range;
141    }
142    return *this;
143}
144
145void
146Symbol::Clear()
147{
148    m_uid = UINT32_MAX;
149    m_mangled.Clear();
150    m_type_data = 0;
151    m_type_data_resolved = false;
152    m_is_synthetic = false;
153    m_is_debug = false;
154    m_is_external = false;
155    m_size_is_sibling = false;
156    m_size_is_synthesized = false;
157    m_calculated_size = false;
158    m_type = eSymbolTypeInvalid;
159    m_flags = 0;
160    m_addr_range.Clear();
161}
162
163bool
164Symbol::ValueIsAddress() const
165{
166    return m_addr_range.GetBaseAddress().GetSection().get() != NULL;
167}
168
169uint32_t
170Symbol::GetSiblingIndex() const
171{
172    return m_size_is_sibling ? m_addr_range.GetByteSize() : 0;
173}
174
175bool
176Symbol::IsTrampoline () const
177{
178    return m_type == eSymbolTypeTrampoline;
179}
180
181void
182Symbol::GetDescription (Stream *s, lldb::DescriptionLevel level, Target *target) const
183{
184    s->Printf("id = {0x%8.8x}", m_uid);
185
186    if (m_addr_range.GetBaseAddress().GetSection())
187    {
188        if (ValueIsAddress())
189        {
190            const lldb::addr_t byte_size = GetByteSize();
191            if (byte_size > 0)
192            {
193                s->PutCString (", range = ");
194                m_addr_range.Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
195            }
196            else
197            {
198                s->PutCString (", address = ");
199                m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
200            }
201        }
202        else
203            s->Printf (", value = 0x%16.16llx", m_addr_range.GetBaseAddress().GetOffset());
204    }
205    else
206    {
207        if (m_size_is_sibling)
208            s->Printf (", sibling = %5llu", m_addr_range.GetBaseAddress().GetOffset());
209        else
210            s->Printf (", value = 0x%16.16llx", m_addr_range.GetBaseAddress().GetOffset());
211    }
212    if (m_mangled.GetDemangledName())
213        s->Printf(", name=\"%s\"", m_mangled.GetDemangledName().AsCString());
214    if (m_mangled.GetMangledName())
215        s->Printf(", mangled=\"%s\"", m_mangled.GetMangledName().AsCString());
216
217}
218
219void
220Symbol::Dump(Stream *s, Target *target, uint32_t index) const
221{
222//  s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
223//  s->Indent();
224//  s->Printf("Symbol[%5u] %6u %c%c %-12s ",
225    s->Printf("[%5u] %6u %c%c%c %-12s ",
226              index,
227              GetID(),
228              m_is_debug ? 'D' : ' ',
229              m_is_synthetic ? 'S' : ' ',
230              m_is_external ? 'X' : ' ',
231              GetTypeAsString());
232
233    // Make sure the size of the symbol is up to date before dumping
234    GetByteSize();
235
236    if (ValueIsAddress())
237    {
238        if (!m_addr_range.GetBaseAddress().Dump(s, NULL, Address::DumpStyleFileAddress))
239            s->Printf("%*s", 18, "");
240
241        s->PutChar(' ');
242
243        if (!m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress))
244            s->Printf("%*s", 18, "");
245
246        const char *format = m_size_is_sibling ?
247                            " Sibling -> [%5llu] 0x%8.8x %s\n":
248                            " 0x%16.16llx 0x%8.8x %s\n";
249        s->Printf(  format,
250                    GetByteSize(),
251                    m_flags,
252                    m_mangled.GetName().AsCString(""));
253    }
254    else
255    {
256        const char *format = m_size_is_sibling ?
257                            "0x%16.16llx                    Sibling -> [%5llu] 0x%8.8x %s\n":
258                            "0x%16.16llx                    0x%16.16llx 0x%8.8x %s\n";
259        s->Printf(  format,
260                    m_addr_range.GetBaseAddress().GetOffset(),
261                    GetByteSize(),
262                    m_flags,
263                    m_mangled.GetName().AsCString(""));
264    }
265}
266
267uint32_t
268Symbol::GetPrologueByteSize ()
269{
270    if (m_type == eSymbolTypeCode)
271    {
272        if (!m_type_data_resolved)
273        {
274            m_type_data_resolved = true;
275            ModuleSP module_sp (m_addr_range.GetBaseAddress().GetModule());
276            SymbolContext sc;
277            if (module_sp && module_sp->ResolveSymbolContextForAddress (m_addr_range.GetBaseAddress(),
278                                                                        eSymbolContextLineEntry,
279                                                                        sc))
280            {
281                m_type_data = sc.line_entry.range.GetByteSize();
282                // Sanity check - this may be a function in the middle of code that has debug information, but
283                // not for this symbol.  So the line entries surrounding us won't lie inside our function.
284                // In that case, the line entry will be bigger than we are, so we do that quick check and
285                // if that is true, we just return 0.
286                if (m_type_data >= m_addr_range.GetByteSize())
287                    m_type_data = 0;
288            }
289            else
290            {
291                // TODO: expose something in Process to figure out the
292                // size of a function prologue.
293            }
294        }
295        return m_type_data;
296    }
297    return 0;
298}
299
300bool
301Symbol::Compare(const ConstString& name, SymbolType type) const
302{
303    if (type == eSymbolTypeAny || m_type == type)
304        return m_mangled.GetMangledName() == name || m_mangled.GetDemangledName() == name;
305    return false;
306}
307
308#define ENUM_TO_CSTRING(x)  case eSymbolType##x: return #x;
309
310const char *
311Symbol::GetTypeAsString() const
312{
313    switch (m_type)
314    {
315    ENUM_TO_CSTRING(Invalid);
316    ENUM_TO_CSTRING(Absolute);
317    ENUM_TO_CSTRING(Code);
318    ENUM_TO_CSTRING(Data);
319    ENUM_TO_CSTRING(Trampoline);
320    ENUM_TO_CSTRING(Runtime);
321    ENUM_TO_CSTRING(Exception);
322    ENUM_TO_CSTRING(SourceFile);
323    ENUM_TO_CSTRING(HeaderFile);
324    ENUM_TO_CSTRING(ObjectFile);
325    ENUM_TO_CSTRING(CommonBlock);
326    ENUM_TO_CSTRING(Block);
327    ENUM_TO_CSTRING(Local);
328    ENUM_TO_CSTRING(Param);
329    ENUM_TO_CSTRING(Variable);
330    ENUM_TO_CSTRING(VariableType);
331    ENUM_TO_CSTRING(LineEntry);
332    ENUM_TO_CSTRING(LineHeader);
333    ENUM_TO_CSTRING(ScopeBegin);
334    ENUM_TO_CSTRING(ScopeEnd);
335    ENUM_TO_CSTRING(Additional);
336    ENUM_TO_CSTRING(Compiler);
337    ENUM_TO_CSTRING(Instrumentation);
338    ENUM_TO_CSTRING(Undefined);
339    ENUM_TO_CSTRING(ObjCClass);
340    ENUM_TO_CSTRING(ObjCMetaClass);
341    ENUM_TO_CSTRING(ObjCIVar);
342    default:
343        break;
344    }
345    return "<unknown SymbolType>";
346}
347
348
349void
350Symbol::CalculateSymbolContext (SymbolContext *sc)
351{
352    // Symbols can reconstruct the symbol and the module in the symbol context
353    sc->symbol = this;
354    if (ValueIsAddress())
355        sc->module_sp = GetAddress().GetModule();
356    else
357        sc->module_sp.reset();
358}
359
360ModuleSP
361Symbol::CalculateSymbolContextModule ()
362{
363    if (ValueIsAddress())
364        return GetAddress().GetModule();
365    return ModuleSP();
366}
367
368Symbol *
369Symbol::CalculateSymbolContextSymbol ()
370{
371    return this;
372}
373
374
375void
376Symbol::DumpSymbolContext (Stream *s)
377{
378    bool dumped_module = false;
379    if (ValueIsAddress())
380    {
381        ModuleSP module_sp (GetAddress().GetModule());
382        if (module_sp)
383        {
384            dumped_module = true;
385            module_sp->DumpSymbolContext(s);
386        }
387    }
388    if (dumped_module)
389        s->PutCString(", ");
390
391    s->Printf("Symbol{0x%8.8x}", GetID());
392}
393
394
395lldb::addr_t
396Symbol::GetByteSize () const
397{
398    addr_t byte_size = m_addr_range.GetByteSize();
399    if (byte_size == 0 && !m_calculated_size)
400    {
401        const_cast<Symbol*>(this)->m_calculated_size = true;
402        if (ValueIsAddress())
403        {
404            ModuleSP module_sp (GetAddress().GetModule());
405            if (module_sp)
406            {
407                ObjectFile *objfile = module_sp->GetObjectFile();
408                if (objfile)
409                {
410                    Symtab *symtab = objfile->GetSymtab();
411                    if (symtab)
412                    {
413                        const_cast<Symbol*>(this)->SetByteSize (symtab->CalculateSymbolSize (const_cast<Symbol *>(this)));
414                        byte_size = m_addr_range.GetByteSize();
415                    }
416                }
417            }
418        }
419    }
420    return byte_size;
421}
422
423