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 << "id = " << (const UserID&)*this << ", name = \"" << m_mangled.GetName() << '"';
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 }
215 
216 void
217 Symbol::Dump(Stream *s, Target *target, uint32_t index) const
218 {
219 //  s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
220 //  s->Indent();
221 //  s->Printf("Symbol[%5u] %6u %c%c %-12s ",
222     s->Printf("[%5u] %6u %c%c%c %-12s ",
223               index,
224               GetID(),
225               m_is_debug ? 'D' : ' ',
226               m_is_synthetic ? 'S' : ' ',
227               m_is_external ? 'X' : ' ',
228               GetTypeAsString());
229 
230     const Section *section = m_addr_range.GetBaseAddress().GetSection();
231     if (section != NULL)
232     {
233         if (!m_addr_range.GetBaseAddress().Dump(s, NULL, Address::DumpStyleFileAddress))
234             s->Printf("%*s", 18, "");
235 
236         s->PutChar(' ');
237 
238         if (!m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress))
239             s->Printf("%*s", 18, "");
240 
241         const char *format = m_size_is_sibling ?
242                             " Sibling -> [%5llu] 0x%8.8x %s\n":
243                             " 0x%16.16llx 0x%8.8x %s\n";
244         s->Printf(  format,
245                     m_addr_range.GetByteSize(),
246                     m_flags,
247                     m_mangled.GetName().AsCString(""));
248     }
249     else
250     {
251         const char *format = m_size_is_sibling ?
252                             "0x%16.16llx                    Sibling -> [%5llu] 0x%8.8x %s\n":
253                             "0x%16.16llx                    0x%16.16llx 0x%8.8x %s\n";
254         s->Printf(  format,
255                     m_addr_range.GetBaseAddress().GetOffset(),
256                     m_addr_range.GetByteSize(),
257                     m_flags,
258                     m_mangled.GetName().AsCString(""));
259     }
260 }
261 
262 uint32_t
263 Symbol::GetPrologueByteSize ()
264 {
265     if (m_type == eSymbolTypeCode)
266     {
267         if (!m_type_data_resolved)
268         {
269             m_type_data_resolved = true;
270             Module *module = m_addr_range.GetBaseAddress().GetModule();
271             SymbolContext sc;
272             if (module && module->ResolveSymbolContextForAddress (m_addr_range.GetBaseAddress(),
273                                                                   eSymbolContextLineEntry,
274                                                                   sc))
275             {
276                 m_type_data = sc.line_entry.range.GetByteSize();
277             }
278             else
279             {
280                 // TODO: expose something in Process to figure out the
281                 // size of a function prologue.
282             }
283         }
284         return m_type_data;
285     }
286     return 0;
287 }
288 
289 void
290 Symbol::SetValue(addr_t value)
291 {
292     m_addr_range.GetBaseAddress().SetSection(NULL);
293     m_addr_range.GetBaseAddress().SetOffset(value);
294 }
295 
296 
297 bool
298 Symbol::Compare(const ConstString& name, SymbolType type) const
299 {
300     if (type == eSymbolTypeAny || m_type == type)
301         return m_mangled.GetMangledName() == name || m_mangled.GetDemangledName() == name;
302     return false;
303 }
304 
305 #define ENUM_TO_CSTRING(x)  case eSymbolType##x: return #x;
306 
307 const char *
308 Symbol::GetTypeAsString() const
309 {
310     switch (m_type)
311     {
312     ENUM_TO_CSTRING(Invalid);
313     ENUM_TO_CSTRING(Absolute);
314     ENUM_TO_CSTRING(Code);
315     ENUM_TO_CSTRING(Data);
316     ENUM_TO_CSTRING(Trampoline);
317     ENUM_TO_CSTRING(Runtime);
318     ENUM_TO_CSTRING(Exception);
319     ENUM_TO_CSTRING(SourceFile);
320     ENUM_TO_CSTRING(HeaderFile);
321     ENUM_TO_CSTRING(ObjectFile);
322     ENUM_TO_CSTRING(CommonBlock);
323     ENUM_TO_CSTRING(Block);
324     ENUM_TO_CSTRING(Local);
325     ENUM_TO_CSTRING(Param);
326     ENUM_TO_CSTRING(Variable);
327     ENUM_TO_CSTRING(VariableType);
328     ENUM_TO_CSTRING(LineEntry);
329     ENUM_TO_CSTRING(LineHeader);
330     ENUM_TO_CSTRING(ScopeBegin);
331     ENUM_TO_CSTRING(ScopeEnd);
332     ENUM_TO_CSTRING(Additional);
333     ENUM_TO_CSTRING(Compiler);
334     ENUM_TO_CSTRING(Instrumentation);
335     ENUM_TO_CSTRING(Undefined);
336     ENUM_TO_CSTRING(ObjCClass);
337     ENUM_TO_CSTRING(ObjCMetaClass);
338     ENUM_TO_CSTRING(ObjCIVar);
339     default:
340         break;
341     }
342     return "<unknown SymbolType>";
343 }
344 
345 
346 void
347 Symbol::CalculateSymbolContext (SymbolContext *sc)
348 {
349     // Symbols can reconstruct the symbol and the module in the symbol context
350     sc->symbol = this;
351     const AddressRange *range = GetAddressRangePtr();
352     if (range)
353     {
354         Module *module = range->GetBaseAddress().GetModule ();
355         if (module)
356         {
357             sc->module_sp = module;
358             return;
359         }
360     }
361     sc->module_sp.reset();
362 }
363 
364 Module *
365 Symbol::CalculateSymbolContextModule ()
366 {
367     const AddressRange *range = GetAddressRangePtr();
368     if (range)
369         return range->GetBaseAddress().GetModule ();
370     return NULL;
371 }
372 
373 Symbol *
374 Symbol::CalculateSymbolContextSymbol ()
375 {
376     return this;
377 }
378 
379 
380 void
381 Symbol::DumpSymbolContext (Stream *s)
382 {
383     bool dumped_module = false;
384     const AddressRange *range = GetAddressRangePtr();
385     if (range)
386     {
387         Module *module = range->GetBaseAddress().GetModule ();
388         if (module)
389         {
390             dumped_module = true;
391             module->DumpSymbolContext(s);
392         }
393     }
394     if (dumped_module)
395         s->PutCString(", ");
396 
397     s->Printf("Symbol{0x%8.8x}", GetID());
398 }
399 
400 
401