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_type (eSymbolTypeInvalid),
37     m_flags (),
38     m_addr_range ()
39 {
40 }
41 
42 Symbol::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 
74 Symbol::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 
104 Symbol::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 
122 const Symbol&
123 Symbol::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 
145 void
146 Symbol::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 
163 bool
164 Symbol::ValueIsAddress() const
165 {
166     return m_addr_range.GetBaseAddress().GetSection().get() != NULL;
167 }
168 
169 uint32_t
170 Symbol::GetSiblingIndex() const
171 {
172     return m_size_is_sibling ? m_addr_range.GetByteSize() : 0;
173 }
174 
175 bool
176 Symbol::IsTrampoline () const
177 {
178     return m_type == eSymbolTypeTrampoline;
179 }
180 
181 void
182 Symbol::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 
219 void
220 Symbol::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 
267 uint32_t
268 Symbol::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 
300 bool
301 Symbol::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 
310 const char *
311 Symbol::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 
349 void
350 Symbol::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 
360 ModuleSP
361 Symbol::CalculateSymbolContextModule ()
362 {
363     if (ValueIsAddress())
364         return GetAddress().GetModule();
365     return ModuleSP();
366 }
367 
368 Symbol *
369 Symbol::CalculateSymbolContextSymbol ()
370 {
371     return this;
372 }
373 
374 
375 void
376 Symbol::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 
395 lldb::addr_t
396 Symbol::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