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     UserID (),
24     SymbolContextScope (),
25     m_mangled (),
26     m_type (eSymbolTypeInvalid),
27     m_type_data (0),
28     m_type_data_resolved (false),
29     m_is_synthetic (false),
30     m_is_debug (false),
31     m_is_external (false),
32     m_size_is_sibling (false),
33     m_size_is_synthesized (false),
34     m_searched_for_function (false),
35     m_addr_range (),
36     m_flags (),
37     m_function (NULL)
38 {
39 }
40 
41 Symbol::Symbol
42 (
43     user_id_t symID,
44     const char *name,
45     bool name_is_mangled,
46     SymbolType type,
47     bool external,
48     bool is_debug,
49     bool is_trampoline,
50     bool is_artificial,
51     const Section* section,
52     addr_t offset,
53     uint32_t size,
54     uint32_t flags
55 ) :
56     UserID (symID),
57     SymbolContextScope (),
58     m_mangled (name, name_is_mangled),
59     m_type (type),
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_searched_for_function (false),
68     m_addr_range (section, offset, size),
69     m_flags (flags),
70     m_function (NULL)
71 {
72 }
73 
74 Symbol::Symbol
75 (
76     user_id_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     UserID (symID),
88     SymbolContextScope (),
89     m_mangled (name, name_is_mangled),
90     m_type (type),
91     m_type_data (0),
92     m_type_data_resolved (false),
93     m_is_synthetic (is_artificial),
94     m_is_debug (is_debug),
95     m_is_external (external),
96     m_size_is_sibling (false),
97     m_size_is_synthesized (false),
98     m_searched_for_function (false),
99     m_addr_range (range),
100     m_flags (flags),
101     m_function (NULL)
102 {
103 }
104 
105 Symbol::Symbol(const Symbol& rhs):
106     UserID (rhs),
107     SymbolContextScope (rhs),
108     m_mangled (rhs.m_mangled),
109     m_type (rhs.m_type),
110     m_type_data (rhs.m_type_data),
111     m_type_data_resolved (rhs.m_type_data_resolved),
112     m_is_synthetic (rhs.m_is_synthetic),
113     m_is_debug (rhs.m_is_debug),
114     m_is_external (rhs.m_is_external),
115     m_size_is_sibling (rhs.m_size_is_sibling),
116     m_size_is_synthesized (false),
117     m_searched_for_function (false),
118     m_addr_range (rhs.m_addr_range),
119     m_flags (rhs.m_flags),
120     m_function (NULL)
121 {
122 }
123 
124 const Symbol&
125 Symbol::operator= (const Symbol& rhs)
126 {
127     if (this != &rhs)
128     {
129         SymbolContextScope::operator= (rhs);
130         UserID::operator= (rhs);
131         m_mangled = rhs.m_mangled;
132         m_type = rhs.m_type;
133         m_type_data = rhs.m_type_data;
134         m_type_data_resolved = rhs.m_type_data_resolved;
135         m_is_synthetic = rhs.m_is_synthetic;
136         m_is_debug = rhs.m_is_debug;
137         m_is_external = rhs.m_is_external;
138         m_size_is_sibling = rhs.m_size_is_sibling;
139         m_size_is_synthesized = rhs.m_size_is_sibling;
140         m_searched_for_function = rhs.m_searched_for_function;
141         m_addr_range = rhs.m_addr_range;
142         m_flags = rhs.m_flags;
143         m_function = rhs.m_function;
144     }
145     return *this;
146 }
147 
148 AddressRange *
149 Symbol::GetAddressRangePtr()
150 {
151     if (m_addr_range.GetBaseAddress().GetSection())
152         return &m_addr_range;
153     return NULL;
154 }
155 
156 const AddressRange *
157 Symbol::GetAddressRangePtr() const
158 {
159     if (m_addr_range.GetBaseAddress().GetSection())
160         return &m_addr_range;
161     return NULL;
162 }
163 
164 uint32_t
165 Symbol::GetSiblingIndex() const
166 {
167     return m_size_is_sibling ? m_addr_range.GetByteSize() : 0;
168 }
169 
170 bool
171 Symbol::IsTrampoline () const
172 {
173     return m_type == eSymbolTypeTrampoline;
174 }
175 
176 void
177 Symbol::GetDescription (Stream *s, lldb::DescriptionLevel level, Target *target) const
178 {
179     *s << "id = " << (const UserID&)*this << ", name = \"" << m_mangled.GetName() << '"';
180     const Section *section = m_addr_range.GetBaseAddress().GetSection();
181     if (section != NULL)
182     {
183         if (m_addr_range.GetBaseAddress().IsSectionOffset())
184         {
185             if (m_addr_range.GetByteSize() > 0)
186             {
187                 s->PutCString (", range = ");
188                 m_addr_range.Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
189             }
190             else
191             {
192                 s->PutCString (", address = ");
193                 m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
194             }
195         }
196         else
197         {
198             if (m_size_is_sibling)
199                 s->Printf (", sibling = %5llu", m_addr_range.GetBaseAddress().GetOffset());
200             else
201                 s->Printf (", value = 0x%16.16llx", m_addr_range.GetBaseAddress().GetOffset());
202         }
203     }
204 }
205 
206 void
207 Symbol::Dump(Stream *s, Target *target, uint32_t index) const
208 {
209 //  s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
210 //  s->Indent();
211 //  s->Printf("Symbol[%5u] %6u %c%c %-12s ",
212     s->Printf("[%5u] %6u %c%c%c %-12s ",
213               index,
214               GetID(),
215               m_is_debug ? 'D' : ' ',
216               m_is_synthetic ? 'S' : ' ',
217               m_is_external ? 'X' : ' ',
218               GetTypeAsString());
219 
220     const Section *section = m_addr_range.GetBaseAddress().GetSection();
221     if (section != NULL)
222     {
223         if (!m_addr_range.GetBaseAddress().Dump(s, NULL, Address::DumpStyleFileAddress))
224             s->Printf("%*s", 18, "");
225 
226         s->PutChar(' ');
227 
228         if (!m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress))
229             s->Printf("%*s", 18, "");
230 
231         const char *format = m_size_is_sibling ?
232                             " Sibling -> [%5llu] 0x%8.8x %s\n":
233                             " 0x%16.16llx 0x%8.8x %s\n";
234         s->Printf(  format,
235                     m_addr_range.GetByteSize(),
236                     m_flags,
237                     m_mangled.GetName().AsCString(""));
238     }
239     else
240     {
241         const char *format = m_size_is_sibling ?
242                             "0x%16.16llx                    Sibling -> [%5llu] 0x%8.8x %s\n":
243                             "0x%16.16llx                    0x%16.16llx 0x%8.8x %s\n";
244         s->Printf(  format,
245                     m_addr_range.GetBaseAddress().GetOffset(),
246                     m_addr_range.GetByteSize(),
247                     m_flags,
248                     m_mangled.GetName().AsCString(""));
249     }
250 }
251 
252 Function *
253 Symbol::GetFunction ()
254 {
255     if (m_function == NULL && !m_searched_for_function)
256     {
257         m_searched_for_function = true;
258         Module *module = m_addr_range.GetBaseAddress().GetModule();
259         if (module)
260         {
261             SymbolContext sc;
262             if (module->ResolveSymbolContextForAddress(m_addr_range.GetBaseAddress(), eSymbolContextFunction, sc))
263                 m_function = sc.function;
264         }
265     }
266     return m_function;
267 }
268 
269 uint32_t
270 Symbol::GetPrologueByteSize ()
271 {
272     if (m_type == eSymbolTypeCode)
273     {
274         if (!m_type_data_resolved)
275         {
276             m_type_data_resolved = true;
277             Module *module = m_addr_range.GetBaseAddress().GetModule();
278             SymbolContext sc;
279             if (module && module->ResolveSymbolContextForAddress (m_addr_range.GetBaseAddress(),
280                                                                   eSymbolContextLineEntry,
281                                                                   sc))
282             {
283                 m_type_data = sc.line_entry.range.GetByteSize();
284             }
285             else
286             {
287                 // TODO: expose something in Process to figure out the
288                 // size of a function prologue.
289             }
290         }
291         return m_type_data;
292     }
293     return 0;
294 }
295 
296 void
297 Symbol::SetValue(addr_t value)
298 {
299     m_addr_range.GetBaseAddress().SetSection(NULL);
300     m_addr_range.GetBaseAddress().SetOffset(value);
301 }
302 
303 
304 bool
305 Symbol::Compare(const ConstString& name, SymbolType type) const
306 {
307     if (m_type == eSymbolTypeAny || m_type == type)
308         return m_mangled.GetMangledName() == name || m_mangled.GetDemangledName() == name;
309     return false;
310 }
311 
312 #define ENUM_TO_CSTRING(x)  case eSymbolType##x: return #x;
313 
314 const char *
315 Symbol::GetTypeAsString() const
316 {
317     switch (m_type)
318     {
319     ENUM_TO_CSTRING(Invalid);
320     ENUM_TO_CSTRING(Absolute);
321     ENUM_TO_CSTRING(Extern);
322     ENUM_TO_CSTRING(Code);
323     ENUM_TO_CSTRING(Data);
324     ENUM_TO_CSTRING(Trampoline);
325     ENUM_TO_CSTRING(Runtime);
326     ENUM_TO_CSTRING(Exception);
327     ENUM_TO_CSTRING(SourceFile);
328     ENUM_TO_CSTRING(HeaderFile);
329     ENUM_TO_CSTRING(ObjectFile);
330     ENUM_TO_CSTRING(CommonBlock);
331     ENUM_TO_CSTRING(Block);
332     ENUM_TO_CSTRING(Local);
333     ENUM_TO_CSTRING(Param);
334     ENUM_TO_CSTRING(Variable);
335     ENUM_TO_CSTRING(VariableType);
336     ENUM_TO_CSTRING(LineEntry);
337     ENUM_TO_CSTRING(LineHeader);
338     ENUM_TO_CSTRING(ScopeBegin);
339     ENUM_TO_CSTRING(ScopeEnd);
340     ENUM_TO_CSTRING(Additional);
341     ENUM_TO_CSTRING(Compiler);
342     ENUM_TO_CSTRING(Instrumentation);
343     ENUM_TO_CSTRING(Undefined);
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     {
359         Module *module = range->GetBaseAddress().GetModule ();
360         if (module)
361         {
362             sc->module_sp = module->GetSP();
363             return;
364         }
365     }
366     sc->module_sp.reset();
367 }
368 
369 Module *
370 Symbol::CalculateSymbolContextModule ()
371 {
372     const AddressRange *range = GetAddressRangePtr();
373     if (range)
374         return range->GetBaseAddress().GetModule ();
375     return NULL;
376 }
377 
378 Symbol *
379 Symbol::CalculateSymbolContextSymbol ()
380 {
381     return this;
382 }
383 
384 
385 void
386 Symbol::DumpSymbolContext (Stream *s)
387 {
388     bool dumped_module = false;
389     const AddressRange *range = GetAddressRangePtr();
390     if (range)
391     {
392         Module *module = range->GetBaseAddress().GetModule ();
393         if (module)
394         {
395             dumped_module = true;
396             module->DumpSymbolContext(s);
397         }
398     }
399     if (dumped_module)
400         s->PutCString(", ");
401 
402     s->Printf("Symbol{0x%8.8x}", GetID());
403 }
404 
405 
406