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