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