Home | History | Annotate | Download | only in Symbol
      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/Symbol/Function.h"
     18 #include "lldb/Target/Process.h"
     19 #include "lldb/Target/Target.h"
     20 #include "lldb/Symbol/SymbolVendor.h"
     21 
     22 using namespace lldb;
     23 using namespace lldb_private;
     24 
     25 
     26 Symbol::Symbol() :
     27     SymbolContextScope (),
     28     m_uid (UINT32_MAX),
     29     m_type_data (0),
     30     m_type_data_resolved (false),
     31     m_is_synthetic (false),
     32     m_is_debug (false),
     33     m_is_external (false),
     34     m_size_is_sibling (false),
     35     m_size_is_synthesized (false),
     36     m_size_is_valid (false),
     37     m_demangled_is_synthesized (false),
     38     m_type (eSymbolTypeInvalid),
     39     m_mangled (),
     40     m_addr_range (),
     41     m_flags ()
     42 {
     43 }
     44 
     45 Symbol::Symbol
     46 (
     47     uint32_t symID,
     48     const char *name,
     49     bool name_is_mangled,
     50     SymbolType type,
     51     bool external,
     52     bool is_debug,
     53     bool is_trampoline,
     54     bool is_artificial,
     55     const lldb::SectionSP &section_sp,
     56     addr_t offset,
     57     addr_t size,
     58     bool size_is_valid,
     59     uint32_t flags
     60 ) :
     61     SymbolContextScope (),
     62     m_uid (symID),
     63     m_type_data (0),
     64     m_type_data_resolved (false),
     65     m_is_synthetic (is_artificial),
     66     m_is_debug (is_debug),
     67     m_is_external (external),
     68     m_size_is_sibling (false),
     69     m_size_is_synthesized (false),
     70     m_size_is_valid (size_is_valid || size > 0),
     71     m_demangled_is_synthesized (false),
     72     m_type (type),
     73     m_mangled (ConstString(name), name_is_mangled),
     74     m_addr_range (section_sp, offset, size),
     75     m_flags (flags)
     76 {
     77 }
     78 
     79 Symbol::Symbol
     80 (
     81     uint32_t symID,
     82     const char *name,
     83     bool name_is_mangled,
     84     SymbolType type,
     85     bool external,
     86     bool is_debug,
     87     bool is_trampoline,
     88     bool is_artificial,
     89     const AddressRange &range,
     90     bool size_is_valid,
     91     uint32_t flags
     92 ) :
     93     SymbolContextScope (),
     94     m_uid (symID),
     95     m_type_data (0),
     96     m_type_data_resolved (false),
     97     m_is_synthetic (is_artificial),
     98     m_is_debug (is_debug),
     99     m_is_external (external),
    100     m_size_is_sibling (false),
    101     m_size_is_synthesized (false),
    102     m_size_is_valid (size_is_valid || range.GetByteSize() > 0),
    103     m_demangled_is_synthesized (false),
    104     m_type (type),
    105     m_mangled (ConstString(name), name_is_mangled),
    106     m_addr_range (range),
    107     m_flags (flags)
    108 {
    109 }
    110 
    111 Symbol::Symbol(const Symbol& rhs):
    112     SymbolContextScope (rhs),
    113     m_uid (rhs.m_uid),
    114     m_type_data (rhs.m_type_data),
    115     m_type_data_resolved (rhs.m_type_data_resolved),
    116     m_is_synthetic (rhs.m_is_synthetic),
    117     m_is_debug (rhs.m_is_debug),
    118     m_is_external (rhs.m_is_external),
    119     m_size_is_sibling (rhs.m_size_is_sibling),
    120     m_size_is_synthesized (false),
    121     m_size_is_valid (rhs.m_size_is_valid),
    122     m_demangled_is_synthesized (rhs.m_demangled_is_synthesized),
    123     m_type (rhs.m_type),
    124     m_mangled (rhs.m_mangled),
    125     m_addr_range (rhs.m_addr_range),
    126     m_flags (rhs.m_flags)
    127 {
    128 }
    129 
    130 const Symbol&
    131 Symbol::operator= (const Symbol& rhs)
    132 {
    133     if (this != &rhs)
    134     {
    135         SymbolContextScope::operator= (rhs);
    136         m_uid = rhs.m_uid;
    137         m_type_data = rhs.m_type_data;
    138         m_type_data_resolved = rhs.m_type_data_resolved;
    139         m_is_synthetic = rhs.m_is_synthetic;
    140         m_is_debug = rhs.m_is_debug;
    141         m_is_external = rhs.m_is_external;
    142         m_size_is_sibling = rhs.m_size_is_sibling;
    143         m_size_is_synthesized = rhs.m_size_is_sibling;
    144         m_size_is_valid = rhs.m_size_is_valid;
    145         m_demangled_is_synthesized = rhs.m_demangled_is_synthesized;
    146         m_type = rhs.m_type;
    147         m_mangled = rhs.m_mangled;
    148         m_addr_range = rhs.m_addr_range;
    149         m_flags = rhs.m_flags;
    150     }
    151     return *this;
    152 }
    153 
    154 void
    155 Symbol::Clear()
    156 {
    157     m_uid = UINT32_MAX;
    158     m_mangled.Clear();
    159     m_type_data = 0;
    160     m_type_data_resolved = false;
    161     m_is_synthetic = false;
    162     m_is_debug = false;
    163     m_is_external = false;
    164     m_size_is_sibling = false;
    165     m_size_is_synthesized = false;
    166     m_size_is_valid = false;
    167     m_demangled_is_synthesized = false;
    168     m_type = eSymbolTypeInvalid;
    169     m_flags = 0;
    170     m_addr_range.Clear();
    171 }
    172 
    173 bool
    174 Symbol::ValueIsAddress() const
    175 {
    176     return m_addr_range.GetBaseAddress().GetSection().get() != NULL;
    177 }
    178 
    179 uint32_t
    180 Symbol::GetSiblingIndex() const
    181 {
    182     return m_size_is_sibling ? m_addr_range.GetByteSize() : 0;
    183 }
    184 
    185 bool
    186 Symbol::IsTrampoline () const
    187 {
    188     return m_type == eSymbolTypeTrampoline;
    189 }
    190 
    191 bool
    192 Symbol::IsIndirect () const
    193 {
    194     return m_type == eSymbolTypeResolver;
    195 }
    196 
    197 void
    198 Symbol::GetDescription (Stream *s, lldb::DescriptionLevel level, Target *target) const
    199 {
    200     s->Printf("id = {0x%8.8x}", m_uid);
    201 
    202     if (m_addr_range.GetBaseAddress().GetSection())
    203     {
    204         if (ValueIsAddress())
    205         {
    206             const lldb::addr_t byte_size = GetByteSize();
    207             if (byte_size > 0)
    208             {
    209                 s->PutCString (", range = ");
    210                 m_addr_range.Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
    211             }
    212             else
    213             {
    214                 s->PutCString (", address = ");
    215                 m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
    216             }
    217         }
    218         else
    219             s->Printf (", value = 0x%16.16" PRIx64, m_addr_range.GetBaseAddress().GetOffset());
    220     }
    221     else
    222     {
    223         if (m_size_is_sibling)
    224             s->Printf (", sibling = %5" PRIu64, m_addr_range.GetBaseAddress().GetOffset());
    225         else
    226             s->Printf (", value = 0x%16.16" PRIx64, m_addr_range.GetBaseAddress().GetOffset());
    227     }
    228     if (m_mangled.GetDemangledName())
    229         s->Printf(", name=\"%s\"", m_mangled.GetDemangledName().AsCString());
    230     if (m_mangled.GetMangledName())
    231         s->Printf(", mangled=\"%s\"", m_mangled.GetMangledName().AsCString());
    232 
    233 }
    234 
    235 void
    236 Symbol::Dump(Stream *s, Target *target, uint32_t index) const
    237 {
    238 //  s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
    239 //  s->Indent();
    240 //  s->Printf("Symbol[%5u] %6u %c%c %-12s ",
    241     s->Printf("[%5u] %6u %c%c%c %-12s ",
    242               index,
    243               GetID(),
    244               m_is_debug ? 'D' : ' ',
    245               m_is_synthetic ? 'S' : ' ',
    246               m_is_external ? 'X' : ' ',
    247               GetTypeAsString());
    248 
    249     // Make sure the size of the symbol is up to date before dumping
    250     GetByteSize();
    251 
    252     if (ValueIsAddress())
    253     {
    254         if (!m_addr_range.GetBaseAddress().Dump(s, NULL, Address::DumpStyleFileAddress))
    255             s->Printf("%*s", 18, "");
    256 
    257         s->PutChar(' ');
    258 
    259         if (!m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress))
    260             s->Printf("%*s", 18, "");
    261 
    262         const char *format = m_size_is_sibling ?
    263                             " Sibling -> [%5llu] 0x%8.8x %s\n":
    264                             " 0x%16.16" PRIx64 " 0x%8.8x %s\n";
    265         s->Printf(  format,
    266                     GetByteSize(),
    267                     m_flags,
    268                     m_mangled.GetName().AsCString(""));
    269     }
    270     else
    271     {
    272         const char *format = m_size_is_sibling ?
    273                             "0x%16.16" PRIx64 "                    Sibling -> [%5llu] 0x%8.8x %s\n":
    274                             "0x%16.16" PRIx64 "                    0x%16.16" PRIx64 " 0x%8.8x %s\n";
    275         s->Printf(  format,
    276                     m_addr_range.GetBaseAddress().GetOffset(),
    277                     GetByteSize(),
    278                     m_flags,
    279                     m_mangled.GetName().AsCString(""));
    280     }
    281 }
    282 
    283 uint32_t
    284 Symbol::GetPrologueByteSize ()
    285 {
    286     if (m_type == eSymbolTypeCode || m_type == eSymbolTypeResolver)
    287     {
    288         if (!m_type_data_resolved)
    289         {
    290             m_type_data_resolved = true;
    291 
    292             const Address &base_address = m_addr_range.GetBaseAddress();
    293             Function *function = base_address.CalculateSymbolContextFunction();
    294             if (function)
    295             {
    296                 // Functions have line entries which can also potentially have end of prologue information.
    297                 // So if this symbol points to a function, use the prologue information from there.
    298                 m_type_data = function->GetPrologueByteSize();
    299             }
    300             else
    301             {
    302                 ModuleSP module_sp (base_address.GetModule());
    303                 SymbolContext sc;
    304                 if (module_sp)
    305                 {
    306                     uint32_t resolved_flags = module_sp->ResolveSymbolContextForAddress (base_address,
    307                                                                                          eSymbolContextLineEntry,
    308                                                                                          sc);
    309                     if (resolved_flags & eSymbolContextLineEntry)
    310                     {
    311                         // Default to the end of the first line entry.
    312                         m_type_data = sc.line_entry.range.GetByteSize();
    313 
    314                         // Set address for next line.
    315                         Address addr (base_address);
    316                         addr.Slide (m_type_data);
    317 
    318                         // Check the first few instructions and look for one that has a line number that is
    319                         // different than the first entry. This is also done in Function::GetPrologueByteSize().
    320                         uint16_t total_offset = m_type_data;
    321                         for (int idx = 0; idx < 6; ++idx)
    322                         {
    323                             SymbolContext sc_temp;
    324                             resolved_flags = module_sp->ResolveSymbolContextForAddress (addr, eSymbolContextLineEntry, sc_temp);
    325                             // Make sure we got line number information...
    326                             if (!(resolved_flags & eSymbolContextLineEntry))
    327                                 break;
    328 
    329                             // If this line number is different than our first one, use it and we're done.
    330                             if (sc_temp.line_entry.line != sc.line_entry.line)
    331                             {
    332                                 m_type_data = total_offset;
    333                                 break;
    334                             }
    335 
    336                             // Slide addr up to the next line address.
    337                             addr.Slide (sc_temp.line_entry.range.GetByteSize());
    338                             total_offset += sc_temp.line_entry.range.GetByteSize();
    339                             // If we've gone too far, bail out.
    340                             if (total_offset >= m_addr_range.GetByteSize())
    341                                 break;
    342                         }
    343 
    344                         // Sanity check - this may be a function in the middle of code that has debug information, but
    345                         // not for this symbol.  So the line entries surrounding us won't lie inside our function.
    346                         // In that case, the line entry will be bigger than we are, so we do that quick check and
    347                         // if that is true, we just return 0.
    348                         if (m_type_data >= m_addr_range.GetByteSize())
    349                             m_type_data = 0;
    350                     }
    351                     else
    352                     {
    353                         // TODO: expose something in Process to figure out the
    354                         // size of a function prologue.
    355                         m_type_data = 0;
    356                     }
    357                 }
    358             }
    359         }
    360         return m_type_data;
    361     }
    362     return 0;
    363 }
    364 
    365 bool
    366 Symbol::Compare(const ConstString& name, SymbolType type) const
    367 {
    368     if (type == eSymbolTypeAny || m_type == type)
    369         return m_mangled.GetMangledName() == name || m_mangled.GetDemangledName() == name;
    370     return false;
    371 }
    372 
    373 #define ENUM_TO_CSTRING(x)  case eSymbolType##x: return #x;
    374 
    375 const char *
    376 Symbol::GetTypeAsString() const
    377 {
    378     switch (m_type)
    379     {
    380     ENUM_TO_CSTRING(Invalid);
    381     ENUM_TO_CSTRING(Absolute);
    382     ENUM_TO_CSTRING(Code);
    383     ENUM_TO_CSTRING(Data);
    384     ENUM_TO_CSTRING(Trampoline);
    385     ENUM_TO_CSTRING(Runtime);
    386     ENUM_TO_CSTRING(Exception);
    387     ENUM_TO_CSTRING(SourceFile);
    388     ENUM_TO_CSTRING(HeaderFile);
    389     ENUM_TO_CSTRING(ObjectFile);
    390     ENUM_TO_CSTRING(CommonBlock);
    391     ENUM_TO_CSTRING(Block);
    392     ENUM_TO_CSTRING(Local);
    393     ENUM_TO_CSTRING(Param);
    394     ENUM_TO_CSTRING(Variable);
    395     ENUM_TO_CSTRING(VariableType);
    396     ENUM_TO_CSTRING(LineEntry);
    397     ENUM_TO_CSTRING(LineHeader);
    398     ENUM_TO_CSTRING(ScopeBegin);
    399     ENUM_TO_CSTRING(ScopeEnd);
    400     ENUM_TO_CSTRING(Additional);
    401     ENUM_TO_CSTRING(Compiler);
    402     ENUM_TO_CSTRING(Instrumentation);
    403     ENUM_TO_CSTRING(Undefined);
    404     ENUM_TO_CSTRING(ObjCClass);
    405     ENUM_TO_CSTRING(ObjCMetaClass);
    406     ENUM_TO_CSTRING(ObjCIVar);
    407     default:
    408         break;
    409     }
    410     return "<unknown SymbolType>";
    411 }
    412 
    413 void
    414 Symbol::CalculateSymbolContext (SymbolContext *sc)
    415 {
    416     // Symbols can reconstruct the symbol and the module in the symbol context
    417     sc->symbol = this;
    418     if (ValueIsAddress())
    419         sc->module_sp = GetAddress().GetModule();
    420     else
    421         sc->module_sp.reset();
    422 }
    423 
    424 ModuleSP
    425 Symbol::CalculateSymbolContextModule ()
    426 {
    427     if (ValueIsAddress())
    428         return GetAddress().GetModule();
    429     return ModuleSP();
    430 }
    431 
    432 Symbol *
    433 Symbol::CalculateSymbolContextSymbol ()
    434 {
    435     return this;
    436 }
    437 
    438 void
    439 Symbol::DumpSymbolContext (Stream *s)
    440 {
    441     bool dumped_module = false;
    442     if (ValueIsAddress())
    443     {
    444         ModuleSP module_sp (GetAddress().GetModule());
    445         if (module_sp)
    446         {
    447             dumped_module = true;
    448             module_sp->DumpSymbolContext(s);
    449         }
    450     }
    451     if (dumped_module)
    452         s->PutCString(", ");
    453 
    454     s->Printf("Symbol{0x%8.8x}", GetID());
    455 }
    456 
    457 lldb::addr_t
    458 Symbol::GetByteSize () const
    459 {
    460     return m_addr_range.GetByteSize();
    461 }
    462 
    463