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     addr_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 bool
188 Symbol::IsIndirect () const
189 {
190     return m_type == eSymbolTypeResolver;
191 }
192 
193 void
194 Symbol::GetDescription (Stream *s, lldb::DescriptionLevel level, Target *target) const
195 {
196     s->Printf("id = {0x%8.8x}", m_uid);
197 
198     if (m_addr_range.GetBaseAddress().GetSection())
199     {
200         if (ValueIsAddress())
201         {
202             const lldb::addr_t byte_size = GetByteSize();
203             if (byte_size > 0)
204             {
205                 s->PutCString (", range = ");
206                 m_addr_range.Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
207             }
208             else
209             {
210                 s->PutCString (", address = ");
211                 m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
212             }
213         }
214         else
215             s->Printf (", value = 0x%16.16" PRIx64, m_addr_range.GetBaseAddress().GetOffset());
216     }
217     else
218     {
219         if (m_size_is_sibling)
220             s->Printf (", sibling = %5" PRIu64, m_addr_range.GetBaseAddress().GetOffset());
221         else
222             s->Printf (", value = 0x%16.16" PRIx64, m_addr_range.GetBaseAddress().GetOffset());
223     }
224     if (m_mangled.GetDemangledName())
225         s->Printf(", name=\"%s\"", m_mangled.GetDemangledName().AsCString());
226     if (m_mangled.GetMangledName())
227         s->Printf(", mangled=\"%s\"", m_mangled.GetMangledName().AsCString());
228 
229 }
230 
231 void
232 Symbol::Dump(Stream *s, Target *target, uint32_t index) const
233 {
234 //  s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
235 //  s->Indent();
236 //  s->Printf("Symbol[%5u] %6u %c%c %-12s ",
237     s->Printf("[%5u] %6u %c%c%c %-12s ",
238               index,
239               GetID(),
240               m_is_debug ? 'D' : ' ',
241               m_is_synthetic ? 'S' : ' ',
242               m_is_external ? 'X' : ' ',
243               GetTypeAsString());
244 
245     // Make sure the size of the symbol is up to date before dumping
246     GetByteSize();
247 
248     if (ValueIsAddress())
249     {
250         if (!m_addr_range.GetBaseAddress().Dump(s, NULL, Address::DumpStyleFileAddress))
251             s->Printf("%*s", 18, "");
252 
253         s->PutChar(' ');
254 
255         if (!m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress))
256             s->Printf("%*s", 18, "");
257 
258         const char *format = m_size_is_sibling ?
259                             " Sibling -> [%5llu] 0x%8.8x %s\n":
260                             " 0x%16.16" PRIx64 " 0x%8.8x %s\n";
261         s->Printf(  format,
262                     GetByteSize(),
263                     m_flags,
264                     m_mangled.GetName().AsCString(""));
265     }
266     else
267     {
268         const char *format = m_size_is_sibling ?
269                             "0x%16.16" PRIx64 "                    Sibling -> [%5llu] 0x%8.8x %s\n":
270                             "0x%16.16" PRIx64 "                    0x%16.16" PRIx64 " 0x%8.8x %s\n";
271         s->Printf(  format,
272                     m_addr_range.GetBaseAddress().GetOffset(),
273                     GetByteSize(),
274                     m_flags,
275                     m_mangled.GetName().AsCString(""));
276     }
277 }
278 
279 uint32_t
280 Symbol::GetPrologueByteSize ()
281 {
282     if (m_type == eSymbolTypeCode || m_type == eSymbolTypeResolver)
283     {
284         if (!m_type_data_resolved)
285         {
286             m_type_data_resolved = true;
287             ModuleSP module_sp (m_addr_range.GetBaseAddress().GetModule());
288             SymbolContext sc;
289             if (module_sp && module_sp->ResolveSymbolContextForAddress (m_addr_range.GetBaseAddress(),
290                                                                         eSymbolContextLineEntry,
291                                                                         sc))
292             {
293                 m_type_data = sc.line_entry.range.GetByteSize();
294                 // Sanity check - this may be a function in the middle of code that has debug information, but
295                 // not for this symbol.  So the line entries surrounding us won't lie inside our function.
296                 // In that case, the line entry will be bigger than we are, so we do that quick check and
297                 // if that is true, we just return 0.
298                 if (m_type_data >= m_addr_range.GetByteSize())
299                     m_type_data = 0;
300             }
301             else
302             {
303                 // TODO: expose something in Process to figure out the
304                 // size of a function prologue.
305             }
306         }
307         return m_type_data;
308     }
309     return 0;
310 }
311 
312 bool
313 Symbol::Compare(const ConstString& name, SymbolType type) const
314 {
315     if (type == eSymbolTypeAny || m_type == type)
316         return m_mangled.GetMangledName() == name || m_mangled.GetDemangledName() == name;
317     return false;
318 }
319 
320 #define ENUM_TO_CSTRING(x)  case eSymbolType##x: return #x;
321 
322 const char *
323 Symbol::GetTypeAsString() const
324 {
325     switch (m_type)
326     {
327     ENUM_TO_CSTRING(Invalid);
328     ENUM_TO_CSTRING(Absolute);
329     ENUM_TO_CSTRING(Code);
330     ENUM_TO_CSTRING(Data);
331     ENUM_TO_CSTRING(Trampoline);
332     ENUM_TO_CSTRING(Runtime);
333     ENUM_TO_CSTRING(Exception);
334     ENUM_TO_CSTRING(SourceFile);
335     ENUM_TO_CSTRING(HeaderFile);
336     ENUM_TO_CSTRING(ObjectFile);
337     ENUM_TO_CSTRING(CommonBlock);
338     ENUM_TO_CSTRING(Block);
339     ENUM_TO_CSTRING(Local);
340     ENUM_TO_CSTRING(Param);
341     ENUM_TO_CSTRING(Variable);
342     ENUM_TO_CSTRING(VariableType);
343     ENUM_TO_CSTRING(LineEntry);
344     ENUM_TO_CSTRING(LineHeader);
345     ENUM_TO_CSTRING(ScopeBegin);
346     ENUM_TO_CSTRING(ScopeEnd);
347     ENUM_TO_CSTRING(Additional);
348     ENUM_TO_CSTRING(Compiler);
349     ENUM_TO_CSTRING(Instrumentation);
350     ENUM_TO_CSTRING(Undefined);
351     ENUM_TO_CSTRING(ObjCClass);
352     ENUM_TO_CSTRING(ObjCMetaClass);
353     ENUM_TO_CSTRING(ObjCIVar);
354     default:
355         break;
356     }
357     return "<unknown SymbolType>";
358 }
359 
360 
361 void
362 Symbol::CalculateSymbolContext (SymbolContext *sc)
363 {
364     // Symbols can reconstruct the symbol and the module in the symbol context
365     sc->symbol = this;
366     if (ValueIsAddress())
367         sc->module_sp = GetAddress().GetModule();
368     else
369         sc->module_sp.reset();
370 }
371 
372 ModuleSP
373 Symbol::CalculateSymbolContextModule ()
374 {
375     if (ValueIsAddress())
376         return GetAddress().GetModule();
377     return ModuleSP();
378 }
379 
380 Symbol *
381 Symbol::CalculateSymbolContextSymbol ()
382 {
383     return this;
384 }
385 
386 
387 void
388 Symbol::DumpSymbolContext (Stream *s)
389 {
390     bool dumped_module = false;
391     if (ValueIsAddress())
392     {
393         ModuleSP module_sp (GetAddress().GetModule());
394         if (module_sp)
395         {
396             dumped_module = true;
397             module_sp->DumpSymbolContext(s);
398         }
399     }
400     if (dumped_module)
401         s->PutCString(", ");
402 
403     s->Printf("Symbol{0x%8.8x}", GetID());
404 }
405 
406 
407 lldb::addr_t
408 Symbol::GetByteSize () const
409 {
410     addr_t byte_size = m_addr_range.GetByteSize();
411     if (byte_size == 0 && !m_calculated_size)
412     {
413         const_cast<Symbol*>(this)->m_calculated_size = true;
414         if (ValueIsAddress())
415         {
416             ModuleSP module_sp (GetAddress().GetModule());
417             if (module_sp)
418             {
419                 ObjectFile *objfile = module_sp->GetObjectFile();
420                 if (objfile)
421                 {
422                     Symtab *symtab = objfile->GetSymtab();
423                     if (symtab)
424                     {
425                         const_cast<Symbol*>(this)->SetByteSize (symtab->CalculateSymbolSize (const_cast<Symbol *>(this)));
426                         byte_size = m_addr_range.GetByteSize();
427                     }
428                 }
429             }
430         }
431     }
432     return byte_size;
433 }
434 
435