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/Target/Process.h"
16 #include "lldb/Target/Target.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 
22 Symbol::Symbol() :
23     SymbolContextScope (),
24     m_uid (UINT32_MAX),
25     m_mangled (),
26     m_type_data (0),
27     m_type_data_resolved (false),
28     m_is_synthetic (false),
29     m_is_debug (false),
30     m_is_external (false),
31     m_size_is_sibling (false),
32     m_size_is_synthesized (false),
33     m_type (eSymbolTypeInvalid),
34     m_flags (),
35     m_addr_range ()
36 {
37 }
38 
39 Symbol::Symbol
40 (
41     uint32_t symID,
42     const char *name,
43     bool name_is_mangled,
44     SymbolType type,
45     bool external,
46     bool is_debug,
47     bool is_trampoline,
48     bool is_artificial,
49     const Section* section,
50     addr_t offset,
51     uint32_t size,
52     uint32_t flags
53 ) :
54     SymbolContextScope (),
55     m_uid (symID),
56     m_mangled (name, name_is_mangled),
57     m_type_data (0),
58     m_type_data_resolved (false),
59     m_is_synthetic (is_artificial),
60     m_is_debug (is_debug),
61     m_is_external (external),
62     m_size_is_sibling (false),
63     m_size_is_synthesized (false),
64     m_type (type),
65     m_flags (flags),
66     m_addr_range (section, offset, size)
67 {
68 }
69 
70 Symbol::Symbol
71 (
72     uint32_t symID,
73     const char *name,
74     bool name_is_mangled,
75     SymbolType type,
76     bool external,
77     bool is_debug,
78     bool is_trampoline,
79     bool is_artificial,
80     const AddressRange &range,
81     uint32_t flags
82 ) :
83     SymbolContextScope (),
84     m_uid (symID),
85     m_mangled (name, name_is_mangled),
86     m_type_data (0),
87     m_type_data_resolved (false),
88     m_is_synthetic (is_artificial),
89     m_is_debug (is_debug),
90     m_is_external (external),
91     m_size_is_sibling (false),
92     m_size_is_synthesized (false),
93     m_type (type),
94     m_flags (flags),
95     m_addr_range (range)
96 {
97 }
98 
99 Symbol::Symbol(const Symbol& rhs):
100     SymbolContextScope (rhs),
101     m_uid (rhs.m_uid),
102     m_mangled (rhs.m_mangled),
103     m_type_data (rhs.m_type_data),
104     m_type_data_resolved (rhs.m_type_data_resolved),
105     m_is_synthetic (rhs.m_is_synthetic),
106     m_is_debug (rhs.m_is_debug),
107     m_is_external (rhs.m_is_external),
108     m_size_is_sibling (rhs.m_size_is_sibling),
109     m_size_is_synthesized (false),
110     m_type (rhs.m_type),
111     m_flags (rhs.m_flags),
112     m_addr_range (rhs.m_addr_range)
113 {
114 }
115 
116 const Symbol&
117 Symbol::operator= (const Symbol& rhs)
118 {
119     if (this != &rhs)
120     {
121         SymbolContextScope::operator= (rhs);
122         m_uid = rhs.m_uid;
123         m_mangled = rhs.m_mangled;
124         m_type_data = rhs.m_type_data;
125         m_type_data_resolved = rhs.m_type_data_resolved;
126         m_is_synthetic = rhs.m_is_synthetic;
127         m_is_debug = rhs.m_is_debug;
128         m_is_external = rhs.m_is_external;
129         m_size_is_sibling = rhs.m_size_is_sibling;
130         m_size_is_synthesized = rhs.m_size_is_sibling;
131         m_type = rhs.m_type;
132         m_flags = rhs.m_flags;
133         m_addr_range = rhs.m_addr_range;
134     }
135     return *this;
136 }
137 
138 void
139 Symbol::Clear()
140 {
141     m_uid = UINT32_MAX;
142     m_mangled.Clear();
143     m_type_data = 0;
144     m_type_data_resolved = false;
145     m_is_synthetic = false;
146     m_is_debug = false;
147     m_is_external = false;
148     m_size_is_sibling = false;
149     m_size_is_synthesized = false;
150     m_type = eSymbolTypeInvalid;
151     m_flags = 0;
152     m_addr_range.Clear();
153 }
154 
155 AddressRange *
156 Symbol::GetAddressRangePtr()
157 {
158     if (m_addr_range.GetBaseAddress().GetSection())
159         return &m_addr_range;
160     return NULL;
161 }
162 
163 const AddressRange *
164 Symbol::GetAddressRangePtr() const
165 {
166     if (m_addr_range.GetBaseAddress().GetSection())
167         return &m_addr_range;
168     return NULL;
169 }
170 
171 uint32_t
172 Symbol::GetSiblingIndex() const
173 {
174     return m_size_is_sibling ? m_addr_range.GetByteSize() : 0;
175 }
176 
177 bool
178 Symbol::IsTrampoline () const
179 {
180     return m_type == eSymbolTypeTrampoline;
181 }
182 
183 void
184 Symbol::GetDescription (Stream *s, lldb::DescriptionLevel level, Target *target) const
185 {
186     s->Printf("uid={%6u}", m_uid);
187 
188     const Section *section = m_addr_range.GetBaseAddress().GetSection();
189     if (section != NULL)
190     {
191         if (m_addr_range.GetBaseAddress().IsSectionOffset())
192         {
193             if (m_addr_range.GetByteSize() > 0)
194             {
195                 s->PutCString (", range = ");
196                 m_addr_range.Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
197             }
198             else
199             {
200                 s->PutCString (", address = ");
201                 m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
202             }
203         }
204         else
205             s->Printf (", value = 0x%16.16llx", m_addr_range.GetBaseAddress().GetOffset());
206     }
207     else
208     {
209         if (m_size_is_sibling)
210             s->Printf (", sibling = %5llu", m_addr_range.GetBaseAddress().GetOffset());
211         else
212             s->Printf (", value = 0x%16.16llx", m_addr_range.GetBaseAddress().GetOffset());
213     }
214     if (m_mangled.GetDemangledName())
215         s->Printf(", name=\"%s\"", m_mangled.GetDemangledName().AsCString());
216     if (m_mangled.GetMangledName())
217         s->Printf(", mangled=\"%s\"", m_mangled.GetMangledName().AsCString());
218 
219 }
220 
221 void
222 Symbol::Dump(Stream *s, Target *target, uint32_t index) const
223 {
224 //  s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
225 //  s->Indent();
226 //  s->Printf("Symbol[%5u] %6u %c%c %-12s ",
227     s->Printf("[%5u] %6u %c%c%c %-12s ",
228               index,
229               GetID(),
230               m_is_debug ? 'D' : ' ',
231               m_is_synthetic ? 'S' : ' ',
232               m_is_external ? 'X' : ' ',
233               GetTypeAsString());
234 
235     const Section *section = m_addr_range.GetBaseAddress().GetSection();
236     if (section != NULL)
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                     m_addr_range.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                     m_addr_range.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             Module *module = m_addr_range.GetBaseAddress().GetModulePtr();
276             SymbolContext sc;
277             if (module && module->ResolveSymbolContextForAddress (m_addr_range.GetBaseAddress(),
278                                                                   eSymbolContextLineEntry,
279                                                                   sc))
280             {
281                 m_type_data = sc.line_entry.range.GetByteSize();
282             }
283             else
284             {
285                 // TODO: expose something in Process to figure out the
286                 // size of a function prologue.
287             }
288         }
289         return m_type_data;
290     }
291     return 0;
292 }
293 
294 void
295 Symbol::SetValue(addr_t value)
296 {
297     m_addr_range.GetBaseAddress().SetSection(NULL);
298     m_addr_range.GetBaseAddress().SetOffset(value);
299 }
300 
301 
302 bool
303 Symbol::Compare(const ConstString& name, SymbolType type) const
304 {
305     if (type == eSymbolTypeAny || m_type == type)
306         return m_mangled.GetMangledName() == name || m_mangled.GetDemangledName() == name;
307     return false;
308 }
309 
310 #define ENUM_TO_CSTRING(x)  case eSymbolType##x: return #x;
311 
312 const char *
313 Symbol::GetTypeAsString() const
314 {
315     switch (m_type)
316     {
317     ENUM_TO_CSTRING(Invalid);
318     ENUM_TO_CSTRING(Absolute);
319     ENUM_TO_CSTRING(Code);
320     ENUM_TO_CSTRING(Data);
321     ENUM_TO_CSTRING(Trampoline);
322     ENUM_TO_CSTRING(Runtime);
323     ENUM_TO_CSTRING(Exception);
324     ENUM_TO_CSTRING(SourceFile);
325     ENUM_TO_CSTRING(HeaderFile);
326     ENUM_TO_CSTRING(ObjectFile);
327     ENUM_TO_CSTRING(CommonBlock);
328     ENUM_TO_CSTRING(Block);
329     ENUM_TO_CSTRING(Local);
330     ENUM_TO_CSTRING(Param);
331     ENUM_TO_CSTRING(Variable);
332     ENUM_TO_CSTRING(VariableType);
333     ENUM_TO_CSTRING(LineEntry);
334     ENUM_TO_CSTRING(LineHeader);
335     ENUM_TO_CSTRING(ScopeBegin);
336     ENUM_TO_CSTRING(ScopeEnd);
337     ENUM_TO_CSTRING(Additional);
338     ENUM_TO_CSTRING(Compiler);
339     ENUM_TO_CSTRING(Instrumentation);
340     ENUM_TO_CSTRING(Undefined);
341     ENUM_TO_CSTRING(ObjCClass);
342     ENUM_TO_CSTRING(ObjCMetaClass);
343     ENUM_TO_CSTRING(ObjCIVar);
344     default:
345         break;
346     }
347     return "<unknown SymbolType>";
348 }
349 
350 
351 void
352 Symbol::CalculateSymbolContext (SymbolContext *sc)
353 {
354     // Symbols can reconstruct the symbol and the module in the symbol context
355     sc->symbol = this;
356     const AddressRange *range = GetAddressRangePtr();
357     if (range)
358         sc->module_sp = range->GetBaseAddress().GetModuleSP ();
359     else
360         sc->module_sp.reset();
361 }
362 
363 Module *
364 Symbol::CalculateSymbolContextModule ()
365 {
366     const AddressRange *range = GetAddressRangePtr();
367     if (range)
368         return range->GetBaseAddress().GetModulePtr ();
369     return NULL;
370 }
371 
372 Symbol *
373 Symbol::CalculateSymbolContextSymbol ()
374 {
375     return this;
376 }
377 
378 
379 void
380 Symbol::DumpSymbolContext (Stream *s)
381 {
382     bool dumped_module = false;
383     const AddressRange *range = GetAddressRangePtr();
384     if (range)
385     {
386         Module *module = range->GetBaseAddress().GetModulePtr ();
387         if (module)
388         {
389             dumped_module = true;
390             module->DumpSymbolContext(s);
391         }
392     }
393     if (dumped_module)
394         s->PutCString(", ");
395 
396     s->Printf("Symbol{0x%8.8x}", GetID());
397 }
398 
399 
400