Home | History | Annotate | Download | only in Symbol
      1 //===-- SymbolContext.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/SymbolContext.h"
     11 
     12 #include "lldb/Core/Log.h"
     13 #include "lldb/Core/Module.h"
     14 #include "lldb/Core/ModuleSpec.h"
     15 #include "lldb/Host/Host.h"
     16 #include "lldb/Interpreter/Args.h"
     17 #include "lldb/Symbol/Block.h"
     18 #include "lldb/Symbol/ClangASTContext.h"
     19 #include "lldb/Symbol/CompileUnit.h"
     20 #include "lldb/Symbol/ObjectFile.h"
     21 #include "lldb/Symbol/Symbol.h"
     22 #include "lldb/Symbol/SymbolFile.h"
     23 #include "lldb/Symbol/SymbolVendor.h"
     24 #include "lldb/Target/Target.h"
     25 
     26 using namespace lldb;
     27 using namespace lldb_private;
     28 
     29 SymbolContext::SymbolContext() :
     30     target_sp   (),
     31     module_sp   (),
     32     comp_unit   (NULL),
     33     function    (NULL),
     34     block       (NULL),
     35     line_entry  (),
     36     symbol      (NULL)
     37 {
     38 }
     39 
     40 SymbolContext::SymbolContext(const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) :
     41     target_sp   (),
     42     module_sp   (m),
     43     comp_unit   (cu),
     44     function    (f),
     45     block       (b),
     46     line_entry  (),
     47     symbol      (s)
     48 {
     49     if (le)
     50         line_entry = *le;
     51 }
     52 
     53 SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) :
     54     target_sp   (t),
     55     module_sp   (m),
     56     comp_unit   (cu),
     57     function    (f),
     58     block       (b),
     59     line_entry  (),
     60     symbol      (s)
     61 {
     62     if (le)
     63         line_entry = *le;
     64 }
     65 
     66 SymbolContext::SymbolContext(const SymbolContext& rhs) :
     67     target_sp   (rhs.target_sp),
     68     module_sp   (rhs.module_sp),
     69     comp_unit   (rhs.comp_unit),
     70     function    (rhs.function),
     71     block       (rhs.block),
     72     line_entry  (rhs.line_entry),
     73     symbol      (rhs.symbol)
     74 {
     75 }
     76 
     77 
     78 SymbolContext::SymbolContext (SymbolContextScope *sc_scope) :
     79     target_sp   (),
     80     module_sp   (),
     81     comp_unit   (NULL),
     82     function    (NULL),
     83     block       (NULL),
     84     line_entry  (),
     85     symbol      (NULL)
     86 {
     87     sc_scope->CalculateSymbolContext (this);
     88 }
     89 
     90 SymbolContext::~SymbolContext ()
     91 {
     92 }
     93 
     94 const SymbolContext&
     95 SymbolContext::operator= (const SymbolContext& rhs)
     96 {
     97     if (this != &rhs)
     98     {
     99         target_sp   = rhs.target_sp;
    100         module_sp   = rhs.module_sp;
    101         comp_unit   = rhs.comp_unit;
    102         function    = rhs.function;
    103         block       = rhs.block;
    104         line_entry  = rhs.line_entry;
    105         symbol      = rhs.symbol;
    106     }
    107     return *this;
    108 }
    109 
    110 void
    111 SymbolContext::Clear(bool clear_target)
    112 {
    113     if (clear_target)
    114         target_sp.reset();
    115     module_sp.reset();
    116     comp_unit   = NULL;
    117     function    = NULL;
    118     block       = NULL;
    119     line_entry.Clear();
    120     symbol      = NULL;
    121 }
    122 
    123 bool
    124 SymbolContext::DumpStopContext
    125 (
    126     Stream *s,
    127     ExecutionContextScope *exe_scope,
    128     const Address &addr,
    129     bool show_fullpaths,
    130     bool show_module,
    131     bool show_inlined_frames
    132 ) const
    133 {
    134     bool dumped_something = false;
    135     if (show_module && module_sp)
    136     {
    137         if (show_fullpaths)
    138             *s << module_sp->GetFileSpec();
    139         else
    140             *s << module_sp->GetFileSpec().GetFilename();
    141         s->PutChar('`');
    142         dumped_something = true;
    143     }
    144 
    145     if (function != NULL)
    146     {
    147         SymbolContext inline_parent_sc;
    148         Address inline_parent_addr;
    149         if (function->GetMangled().GetName())
    150         {
    151             dumped_something = true;
    152             function->GetMangled().GetName().Dump(s);
    153         }
    154 
    155         if (addr.IsValid())
    156         {
    157             const addr_t function_offset = addr.GetOffset() - function->GetAddressRange().GetBaseAddress().GetOffset();
    158             if (function_offset)
    159             {
    160                 dumped_something = true;
    161                 s->Printf(" + %" PRIu64, function_offset);
    162             }
    163         }
    164 
    165         if (GetParentOfInlinedScope (addr, inline_parent_sc, inline_parent_addr))
    166         {
    167             dumped_something = true;
    168             Block *inlined_block = block->GetContainingInlinedBlock();
    169             const InlineFunctionInfo* inlined_block_info = inlined_block->GetInlinedFunctionInfo();
    170             s->Printf (" [inlined] %s", inlined_block_info->GetName().GetCString());
    171 
    172             lldb_private::AddressRange block_range;
    173             if (inlined_block->GetRangeContainingAddress(addr, block_range))
    174             {
    175                 const addr_t inlined_function_offset = addr.GetOffset() - block_range.GetBaseAddress().GetOffset();
    176                 if (inlined_function_offset)
    177                 {
    178                     s->Printf(" + %" PRIu64, inlined_function_offset);
    179                 }
    180             }
    181             const Declaration &call_site = inlined_block_info->GetCallSite();
    182             if (call_site.IsValid())
    183             {
    184                 s->PutCString(" at ");
    185                 call_site.DumpStopContext (s, show_fullpaths);
    186             }
    187             if (show_inlined_frames)
    188             {
    189                 s->EOL();
    190                 s->Indent();
    191                 return inline_parent_sc.DumpStopContext (s, exe_scope, inline_parent_addr, show_fullpaths, show_module, show_inlined_frames);
    192             }
    193         }
    194         else
    195         {
    196             if (line_entry.IsValid())
    197             {
    198                 dumped_something = true;
    199                 s->PutCString(" at ");
    200                 if (line_entry.DumpStopContext(s, show_fullpaths))
    201                     dumped_something = true;
    202             }
    203         }
    204     }
    205     else if (symbol != NULL)
    206     {
    207         if (symbol->GetMangled().GetName())
    208         {
    209             dumped_something = true;
    210             if (symbol->GetType() == eSymbolTypeTrampoline)
    211                 s->PutCString("symbol stub for: ");
    212             symbol->GetMangled().GetName().Dump(s);
    213         }
    214 
    215         if (addr.IsValid() && symbol->ValueIsAddress())
    216         {
    217             const addr_t symbol_offset = addr.GetOffset() - symbol->GetAddress().GetOffset();
    218             if (symbol_offset)
    219             {
    220                 dumped_something = true;
    221                 s->Printf(" + %" PRIu64, symbol_offset);
    222             }
    223         }
    224     }
    225     else if (addr.IsValid())
    226     {
    227         addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress);
    228         dumped_something = true;
    229     }
    230     return dumped_something;
    231 }
    232 
    233 void
    234 SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target) const
    235 {
    236     if (module_sp)
    237     {
    238         s->Indent("     Module: file = \"");
    239         module_sp->GetFileSpec().Dump(s);
    240         *s << '"';
    241         if (module_sp->GetArchitecture().IsValid())
    242             s->Printf (", arch = \"%s\"", module_sp->GetArchitecture().GetArchitectureName());
    243         s->EOL();
    244     }
    245 
    246     if (comp_unit != NULL)
    247     {
    248         s->Indent("CompileUnit: ");
    249         comp_unit->GetDescription (s, level);
    250         s->EOL();
    251     }
    252 
    253     if (function != NULL)
    254     {
    255         s->Indent("   Function: ");
    256         function->GetDescription (s, level, target);
    257         s->EOL();
    258 
    259         Type *func_type = function->GetType();
    260         if (func_type)
    261         {
    262             s->Indent("   FuncType: ");
    263             func_type->GetDescription (s, level, false);
    264             s->EOL();
    265         }
    266     }
    267 
    268     if (block != NULL)
    269     {
    270         std::vector<Block *> blocks;
    271         blocks.push_back (block);
    272         Block *parent_block = block->GetParent();
    273 
    274         while (parent_block)
    275         {
    276             blocks.push_back (parent_block);
    277             parent_block = parent_block->GetParent();
    278         }
    279         std::vector<Block *>::reverse_iterator pos;
    280         std::vector<Block *>::reverse_iterator begin = blocks.rbegin();
    281         std::vector<Block *>::reverse_iterator end = blocks.rend();
    282         for (pos = begin; pos != end; ++pos)
    283         {
    284             if (pos == begin)
    285                 s->Indent("     Blocks: ");
    286             else
    287                 s->Indent("             ");
    288             (*pos)->GetDescription(s, function, level, target);
    289             s->EOL();
    290         }
    291     }
    292 
    293     if (line_entry.IsValid())
    294     {
    295         s->Indent("  LineEntry: ");
    296         line_entry.GetDescription (s, level, comp_unit, target, false);
    297         s->EOL();
    298     }
    299 
    300     if (symbol != NULL)
    301     {
    302         s->Indent("     Symbol: ");
    303         symbol->GetDescription(s, level, target);
    304         s->EOL();
    305     }
    306 }
    307 
    308 uint32_t
    309 SymbolContext::GetResolvedMask () const
    310 {
    311     uint32_t resolved_mask = 0;
    312     if (target_sp)              resolved_mask |= eSymbolContextTarget;
    313     if (module_sp)              resolved_mask |= eSymbolContextModule;
    314     if (comp_unit)              resolved_mask |= eSymbolContextCompUnit;
    315     if (function)               resolved_mask |= eSymbolContextFunction;
    316     if (block)                  resolved_mask |= eSymbolContextBlock;
    317     if (line_entry.IsValid())   resolved_mask |= eSymbolContextLineEntry;
    318     if (symbol)                 resolved_mask |= eSymbolContextSymbol;
    319     return resolved_mask;
    320 }
    321 
    322 void
    323 SymbolContext::Dump(Stream *s, Target *target) const
    324 {
    325     *s << (void *)this << ": ";
    326     s->Indent();
    327     s->PutCString("SymbolContext");
    328     s->IndentMore();
    329     s->EOL();
    330     s->IndentMore();
    331     s->Indent();
    332     *s << "Module       = " << (void *)module_sp.get() << ' ';
    333     if (module_sp)
    334         module_sp->GetFileSpec().Dump(s);
    335     s->EOL();
    336     s->Indent();
    337     *s << "CompileUnit  = " << (void *)comp_unit;
    338     if (comp_unit != NULL)
    339         *s << " {0x" << comp_unit->GetID() << "} " << *(static_cast<FileSpec*> (comp_unit));
    340     s->EOL();
    341     s->Indent();
    342     *s << "Function     = " << (void *)function;
    343     if (function != NULL)
    344     {
    345         *s << " {0x" << function->GetID() << "} " << function->GetType()->GetName() << ", address-range = ";
    346         function->GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
    347         s->EOL();
    348         s->Indent();
    349         Type* func_type = function->GetType();
    350         if (func_type)
    351         {
    352             *s << "        Type = ";
    353             func_type->Dump (s, false);
    354         }
    355     }
    356     s->EOL();
    357     s->Indent();
    358     *s << "Block        = " << (void *)block;
    359     if (block != NULL)
    360         *s << " {0x" << block->GetID() << '}';
    361     // Dump the block and pass it a negative depth to we print all the parent blocks
    362     //if (block != NULL)
    363     //  block->Dump(s, function->GetFileAddress(), INT_MIN);
    364     s->EOL();
    365     s->Indent();
    366     *s << "LineEntry    = ";
    367     line_entry.Dump (s, target, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true);
    368     s->EOL();
    369     s->Indent();
    370     *s << "Symbol       = " << (void *)symbol;
    371     if (symbol != NULL && symbol->GetMangled())
    372         *s << ' ' << symbol->GetMangled().GetName().AsCString();
    373     s->EOL();
    374     s->IndentLess();
    375     s->IndentLess();
    376 }
    377 
    378 bool
    379 lldb_private::operator== (const SymbolContext& lhs, const SymbolContext& rhs)
    380 {
    381     return  lhs.function == rhs.function
    382             && lhs.symbol == rhs.symbol
    383             && lhs.module_sp.get() == rhs.module_sp.get()
    384             && lhs.comp_unit == rhs.comp_unit
    385             && lhs.target_sp.get() == rhs.target_sp.get()
    386             && LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0;
    387 }
    388 
    389 bool
    390 lldb_private::operator!= (const SymbolContext& lhs, const SymbolContext& rhs)
    391 {
    392     return  lhs.function != rhs.function
    393             || lhs.symbol != rhs.symbol
    394             || lhs.module_sp.get() != rhs.module_sp.get()
    395             || lhs.comp_unit != rhs.comp_unit
    396             || lhs.target_sp.get() != rhs.target_sp.get()
    397             || LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0;
    398 }
    399 
    400 bool
    401 SymbolContext::GetAddressRange (uint32_t scope,
    402                                 uint32_t range_idx,
    403                                 bool use_inline_block_range,
    404                                 AddressRange &range) const
    405 {
    406     if ((scope & eSymbolContextLineEntry) && line_entry.IsValid())
    407     {
    408         range = line_entry.range;
    409         return true;
    410     }
    411 
    412     if ((scope & eSymbolContextBlock) && (block != NULL))
    413     {
    414         if (use_inline_block_range)
    415         {
    416             Block *inline_block = block->GetContainingInlinedBlock();
    417             if (inline_block)
    418                 return inline_block->GetRangeAtIndex (range_idx, range);
    419         }
    420         else
    421         {
    422             return block->GetRangeAtIndex (range_idx, range);
    423         }
    424     }
    425 
    426     if ((scope & eSymbolContextFunction) && (function != NULL))
    427     {
    428         if (range_idx == 0)
    429         {
    430             range = function->GetAddressRange();
    431             return true;
    432         }
    433     }
    434 
    435     if ((scope & eSymbolContextSymbol) && (symbol != NULL))
    436     {
    437         if (range_idx == 0)
    438         {
    439             if (symbol->ValueIsAddress())
    440             {
    441                 range.GetBaseAddress() = symbol->GetAddress();
    442                 range.SetByteSize (symbol->GetByteSize());
    443                 return true;
    444             }
    445         }
    446     }
    447     range.Clear();
    448     return false;
    449 }
    450 
    451 bool
    452 SymbolContext::GetParentOfInlinedScope (const Address &curr_frame_pc,
    453                                         SymbolContext &next_frame_sc,
    454                                         Address &next_frame_pc) const
    455 {
    456     next_frame_sc.Clear(false);
    457     next_frame_pc.Clear();
    458 
    459     if (block)
    460     {
    461         //const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress();
    462 
    463         // In order to get the parent of an inlined function we first need to
    464         // see if we are in an inlined block as "this->block" could be an
    465         // inlined block, or a parent of "block" could be. So lets check if
    466         // this block or one of this blocks parents is an inlined function.
    467         Block *curr_inlined_block = block->GetContainingInlinedBlock();
    468         if (curr_inlined_block)
    469         {
    470             // "this->block" is contained in an inline function block, so to
    471             // get the scope above the inlined block, we get the parent of the
    472             // inlined block itself
    473             Block *next_frame_block = curr_inlined_block->GetParent();
    474             // Now calculate the symbol context of the containing block
    475             next_frame_block->CalculateSymbolContext (&next_frame_sc);
    476 
    477             // If we get here we weren't able to find the return line entry using the nesting of the blocks and
    478             // the line table.  So just use the call site info from our inlined block.
    479 
    480             AddressRange range;
    481             if (curr_inlined_block->GetRangeContainingAddress (curr_frame_pc, range))
    482             {
    483                 // To see there this new frame block it, we need to look at the
    484                 // call site information from
    485                 const InlineFunctionInfo* curr_inlined_block_inlined_info = curr_inlined_block->GetInlinedFunctionInfo();
    486                 next_frame_pc = range.GetBaseAddress();
    487                 next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc;
    488                 next_frame_sc.line_entry.file = curr_inlined_block_inlined_info->GetCallSite().GetFile();
    489                 next_frame_sc.line_entry.line = curr_inlined_block_inlined_info->GetCallSite().GetLine();
    490                 next_frame_sc.line_entry.column = curr_inlined_block_inlined_info->GetCallSite().GetColumn();
    491                 return true;
    492             }
    493             else
    494             {
    495                 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
    496 
    497                 if (log)
    498                 {
    499                     log->Printf ("warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64,
    500                                  curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress());
    501                 }
    502 #ifdef LLDB_CONFIGURATION_DEBUG
    503                 else
    504                 {
    505                     ObjectFile *objfile = NULL;
    506                     if (module_sp)
    507                     {
    508                         SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
    509                         if (symbol_vendor)
    510                         {
    511                             SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
    512                             if (symbol_file)
    513                                 objfile = symbol_file->GetObjectFile();
    514                         }
    515                     }
    516                     if (objfile)
    517                     {
    518                         Host::SystemLog (Host::eSystemLogWarning,
    519                                          "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 " in %s\n",
    520                                          curr_inlined_block->GetID(),
    521                                          curr_frame_pc.GetFileAddress(),
    522                                          objfile->GetFileSpec().GetPath().c_str());
    523                     }
    524                     else
    525                     {
    526                         Host::SystemLog (Host::eSystemLogWarning,
    527                                          "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 "\n",
    528                                          curr_inlined_block->GetID(),
    529                                          curr_frame_pc.GetFileAddress());
    530                     }
    531                 }
    532 #endif
    533             }
    534         }
    535     }
    536 
    537     return false;
    538 }
    539 
    540 Block *
    541 SymbolContext::GetFunctionBlock ()
    542 {
    543     if (function)
    544     {
    545         if (block)
    546         {
    547             // If this symbol context has a block, check to see if this block
    548             // is itself, or is contained within a block with inlined function
    549             // information. If so, then the inlined block is the block that
    550             // defines the function.
    551             Block *inlined_block = block->GetContainingInlinedBlock();
    552             if (inlined_block)
    553                 return inlined_block;
    554 
    555             // The block in this symbol context is not inside an inlined
    556             // block, so the block that defines the function is the function's
    557             // top level block, which is returned below.
    558         }
    559 
    560         // There is no block information in this symbol context, so we must
    561         // assume that the block that is desired is the top level block of
    562         // the function itself.
    563         return &function->GetBlock(true);
    564     }
    565     return NULL;
    566 }
    567 
    568 bool
    569 SymbolContext::GetFunctionMethodInfo (lldb::LanguageType &language,
    570                                       bool &is_instance_method,
    571                                       ConstString &language_object_name)
    572 
    573 
    574 {
    575     Block *function_block = GetFunctionBlock ();
    576     if (function_block)
    577     {
    578         clang::DeclContext *decl_context = function_block->GetClangDeclContext();
    579 
    580         if (decl_context)
    581         {
    582             return ClangASTContext::GetClassMethodInfoForDeclContext (decl_context,
    583                                                                       language,
    584                                                                       is_instance_method,
    585                                                                       language_object_name);
    586         }
    587     }
    588     language = eLanguageTypeUnknown;
    589     is_instance_method = false;
    590     language_object_name.Clear();
    591     return false;
    592 }
    593 
    594 ConstString
    595 SymbolContext::GetFunctionName (Mangled::NamePreference preference) const
    596 {
    597     if (function)
    598     {
    599         if (block)
    600         {
    601             Block *inlined_block = block->GetContainingInlinedBlock();
    602 
    603             if (inlined_block)
    604             {
    605                 const InlineFunctionInfo *inline_info = inlined_block->GetInlinedFunctionInfo();
    606                 if (inline_info)
    607                     return inline_info->GetName();
    608             }
    609         }
    610         return function->GetMangled().GetName(preference);
    611     }
    612     else if (symbol && symbol->ValueIsAddress())
    613     {
    614         return symbol->GetMangled().GetName(preference);
    615     }
    616     else
    617     {
    618         // No function, return an empty string.
    619         return ConstString();
    620     }
    621 }
    622 
    623 LineEntry
    624 SymbolContext::GetFunctionStartLineEntry () const
    625 {
    626     LineEntry line_entry;
    627     Address start_addr;
    628     if (block)
    629     {
    630         Block *inlined_block = block->GetContainingInlinedBlock();
    631         if (inlined_block)
    632         {
    633             if (inlined_block->GetStartAddress (start_addr))
    634             {
    635                 if (start_addr.CalculateSymbolContextLineEntry (line_entry))
    636                     return line_entry;
    637             }
    638             return LineEntry();
    639         }
    640     }
    641 
    642     if (function)
    643     {
    644         if (function->GetAddressRange().GetBaseAddress().CalculateSymbolContextLineEntry(line_entry))
    645             return line_entry;
    646     }
    647     return LineEntry();
    648 }
    649 
    650 //----------------------------------------------------------------------
    651 //
    652 //  SymbolContextSpecifier
    653 //
    654 //----------------------------------------------------------------------
    655 
    656 SymbolContextSpecifier::SymbolContextSpecifier (const TargetSP &target_sp) :
    657     m_target_sp (target_sp),
    658     m_module_spec (),
    659     m_module_sp (),
    660     m_file_spec_ap (),
    661     m_start_line (0),
    662     m_end_line (0),
    663     m_function_spec (),
    664     m_class_name (),
    665     m_address_range_ap (),
    666     m_type (eNothingSpecified)
    667 {
    668 }
    669 
    670 SymbolContextSpecifier::~SymbolContextSpecifier()
    671 {
    672 }
    673 
    674 bool
    675 SymbolContextSpecifier::AddLineSpecification (uint32_t line_no, SpecificationType type)
    676 {
    677     bool return_value = true;
    678     switch (type)
    679     {
    680     case eNothingSpecified:
    681         Clear();
    682         break;
    683     case eLineStartSpecified:
    684         m_start_line = line_no;
    685         m_type |= eLineStartSpecified;
    686         break;
    687     case eLineEndSpecified:
    688         m_end_line = line_no;
    689         m_type |= eLineEndSpecified;
    690         break;
    691     default:
    692         return_value = false;
    693         break;
    694     }
    695     return return_value;
    696 }
    697 
    698 bool
    699 SymbolContextSpecifier::AddSpecification (const char *spec_string, SpecificationType type)
    700 {
    701     bool return_value = true;
    702     switch (type)
    703     {
    704     case eNothingSpecified:
    705         Clear();
    706         break;
    707     case eModuleSpecified:
    708         {
    709             // See if we can find the Module, if so stick it in the SymbolContext.
    710             FileSpec module_file_spec(spec_string, false);
    711             ModuleSpec module_spec (module_file_spec);
    712             lldb::ModuleSP module_sp (m_target_sp->GetImages().FindFirstModule (module_spec));
    713             m_type |= eModuleSpecified;
    714             if (module_sp)
    715                 m_module_sp = module_sp;
    716             else
    717                 m_module_spec.assign (spec_string);
    718         }
    719         break;
    720     case eFileSpecified:
    721         // CompUnits can't necessarily be resolved here, since an inlined function might show up in
    722         // a number of CompUnits.  Instead we just convert to a FileSpec and store it away.
    723         m_file_spec_ap.reset (new FileSpec (spec_string, false));
    724         m_type |= eFileSpecified;
    725         break;
    726     case eLineStartSpecified:
    727         m_start_line = Args::StringToSInt32(spec_string, 0, 0, &return_value);
    728         if (return_value)
    729             m_type |= eLineStartSpecified;
    730         break;
    731     case eLineEndSpecified:
    732         m_end_line = Args::StringToSInt32(spec_string, 0, 0, &return_value);
    733         if (return_value)
    734             m_type |= eLineEndSpecified;
    735         break;
    736     case eFunctionSpecified:
    737         m_function_spec.assign(spec_string);
    738         m_type |= eFunctionSpecified;
    739         break;
    740     case eClassOrNamespaceSpecified:
    741         Clear();
    742         m_class_name.assign (spec_string);
    743         m_type = eClassOrNamespaceSpecified;
    744         break;
    745     case eAddressRangeSpecified:
    746         // Not specified yet...
    747         break;
    748     }
    749 
    750     return return_value;
    751 }
    752 
    753 void
    754 SymbolContextSpecifier::Clear()
    755 {
    756     m_module_spec.clear();
    757     m_file_spec_ap.reset();
    758     m_function_spec.clear();
    759     m_class_name.clear();
    760     m_start_line = 0;
    761     m_end_line = 0;
    762     m_address_range_ap.reset();
    763 
    764     m_type = eNothingSpecified;
    765 }
    766 
    767 bool
    768 SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
    769 {
    770     if (m_type == eNothingSpecified)
    771         return true;
    772 
    773     if (m_target_sp.get() != sc.target_sp.get())
    774         return false;
    775 
    776     if (m_type & eModuleSpecified)
    777     {
    778         if (sc.module_sp)
    779         {
    780             if (m_module_sp.get() != NULL)
    781             {
    782                 if (m_module_sp.get() != sc.module_sp.get())
    783                     return false;
    784             }
    785             else
    786             {
    787                 FileSpec module_file_spec (m_module_spec.c_str(), false);
    788                 if (!FileSpec::Equal (module_file_spec, sc.module_sp->GetFileSpec(), false))
    789                     return false;
    790             }
    791         }
    792     }
    793     if (m_type & eFileSpecified)
    794     {
    795         if (m_file_spec_ap.get())
    796         {
    797             // If we don't have a block or a comp_unit, then we aren't going to match a source file.
    798             if (sc.block == NULL && sc.comp_unit == NULL)
    799                 return false;
    800 
    801             // Check if the block is present, and if so is it inlined:
    802             bool was_inlined = false;
    803             if (sc.block != NULL)
    804             {
    805                 const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
    806                 if (inline_info != NULL)
    807                 {
    808                     was_inlined = true;
    809                     if (!FileSpec::Equal (inline_info->GetDeclaration().GetFile(), *(m_file_spec_ap.get()), false))
    810                         return false;
    811                 }
    812             }
    813 
    814             // Next check the comp unit, but only if the SymbolContext was not inlined.
    815             if (!was_inlined && sc.comp_unit != NULL)
    816             {
    817                 if (!FileSpec::Equal (*(sc.comp_unit), *(m_file_spec_ap.get()), false))
    818                     return false;
    819             }
    820         }
    821     }
    822     if (m_type & eLineStartSpecified
    823         || m_type & eLineEndSpecified)
    824     {
    825         if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line)
    826             return false;
    827     }
    828 
    829     if (m_type & eFunctionSpecified)
    830     {
    831         // First check the current block, and if it is inlined, get the inlined function name:
    832         bool was_inlined = false;
    833         ConstString func_name(m_function_spec.c_str());
    834 
    835         if (sc.block != NULL)
    836         {
    837             const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
    838             if (inline_info != NULL)
    839             {
    840                 was_inlined = true;
    841                 const Mangled &name = inline_info->GetMangled();
    842                 if (!name.NameMatches (func_name))
    843                     return false;
    844             }
    845         }
    846         //  If it wasn't inlined, check the name in the function or symbol:
    847         if (!was_inlined)
    848         {
    849             if (sc.function != NULL)
    850             {
    851                 if (!sc.function->GetMangled().NameMatches(func_name))
    852                     return false;
    853             }
    854             else if (sc.symbol != NULL)
    855             {
    856                 if (!sc.symbol->GetMangled().NameMatches(func_name))
    857                     return false;
    858             }
    859         }
    860 
    861 
    862     }
    863 
    864     return true;
    865 }
    866 
    867 bool
    868 SymbolContextSpecifier::AddressMatches(lldb::addr_t addr)
    869 {
    870     if (m_type & eAddressRangeSpecified)
    871     {
    872 
    873     }
    874     else
    875     {
    876         Address match_address (addr, NULL);
    877         SymbolContext sc;
    878         m_target_sp->GetImages().ResolveSymbolContextForAddress(match_address, eSymbolContextEverything, sc);
    879         return SymbolContextMatches(sc);
    880     }
    881     return true;
    882 }
    883 
    884 void
    885 SymbolContextSpecifier::GetDescription (Stream *s, lldb::DescriptionLevel level) const
    886 {
    887     char path_str[PATH_MAX + 1];
    888 
    889     if (m_type == eNothingSpecified)
    890     {
    891         s->Printf ("Nothing specified.\n");
    892     }
    893 
    894     if (m_type == eModuleSpecified)
    895     {
    896         s->Indent();
    897         if (m_module_sp)
    898         {
    899             m_module_sp->GetFileSpec().GetPath (path_str, PATH_MAX);
    900             s->Printf ("Module: %s\n", path_str);
    901         }
    902         else
    903             s->Printf ("Module: %s\n", m_module_spec.c_str());
    904     }
    905 
    906     if (m_type == eFileSpecified  && m_file_spec_ap.get() != NULL)
    907     {
    908         m_file_spec_ap->GetPath (path_str, PATH_MAX);
    909         s->Indent();
    910         s->Printf ("File: %s", path_str);
    911         if (m_type == eLineStartSpecified)
    912         {
    913             s->Printf (" from line %lu", m_start_line);
    914             if (m_type == eLineEndSpecified)
    915                 s->Printf ("to line %lu", m_end_line);
    916             else
    917                 s->Printf ("to end");
    918         }
    919         else if (m_type == eLineEndSpecified)
    920         {
    921             s->Printf (" from start to line %ld", m_end_line);
    922         }
    923         s->Printf (".\n");
    924     }
    925 
    926     if (m_type == eLineStartSpecified)
    927     {
    928         s->Indent();
    929         s->Printf ("From line %lu", m_start_line);
    930         if (m_type == eLineEndSpecified)
    931             s->Printf ("to line %lu", m_end_line);
    932         else
    933             s->Printf ("to end");
    934         s->Printf (".\n");
    935     }
    936     else if (m_type == eLineEndSpecified)
    937     {
    938         s->Printf ("From start to line %ld.\n", m_end_line);
    939     }
    940 
    941     if (m_type == eFunctionSpecified)
    942     {
    943         s->Indent();
    944         s->Printf ("Function: %s.\n", m_function_spec.c_str());
    945     }
    946 
    947     if (m_type == eClassOrNamespaceSpecified)
    948     {
    949         s->Indent();
    950         s->Printf ("Class name: %s.\n", m_class_name.c_str());
    951     }
    952 
    953     if (m_type == eAddressRangeSpecified && m_address_range_ap.get() != NULL)
    954     {
    955         s->Indent();
    956         s->PutCString ("Address range: ");
    957         m_address_range_ap->Dump (s, m_target_sp.get(), Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
    958         s->PutCString ("\n");
    959     }
    960 }
    961 
    962 //----------------------------------------------------------------------
    963 //
    964 //  SymbolContextList
    965 //
    966 //----------------------------------------------------------------------
    967 
    968 
    969 SymbolContextList::SymbolContextList() :
    970     m_symbol_contexts()
    971 {
    972 }
    973 
    974 SymbolContextList::~SymbolContextList()
    975 {
    976 }
    977 
    978 void
    979 SymbolContextList::Append(const SymbolContext& sc)
    980 {
    981     m_symbol_contexts.push_back(sc);
    982 }
    983 
    984 void
    985 SymbolContextList::Append (const SymbolContextList& sc_list)
    986 {
    987     collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
    988     for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
    989         m_symbol_contexts.push_back (*pos);
    990 }
    991 
    992 
    993 uint32_t
    994 SymbolContextList::AppendIfUnique (const SymbolContextList& sc_list, bool merge_symbol_into_function)
    995 {
    996     uint32_t unique_sc_add_count = 0;
    997     collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
    998     for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
    999     {
   1000         if (AppendIfUnique (*pos, merge_symbol_into_function))
   1001             ++unique_sc_add_count;
   1002     }
   1003     return unique_sc_add_count;
   1004 }
   1005 
   1006 bool
   1007 SymbolContextList::AppendIfUnique (const SymbolContext& sc, bool merge_symbol_into_function)
   1008 {
   1009     collection::iterator pos, end = m_symbol_contexts.end();
   1010     for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
   1011     {
   1012         if (*pos == sc)
   1013             return false;
   1014     }
   1015     if (merge_symbol_into_function
   1016         && sc.symbol    != NULL
   1017         && sc.comp_unit == NULL
   1018         && sc.function  == NULL
   1019         && sc.block     == NULL
   1020         && sc.line_entry.IsValid() == false)
   1021     {
   1022         if (sc.symbol->ValueIsAddress())
   1023         {
   1024             for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
   1025             {
   1026                 // Don't merge symbols into inlined function symbol contexts
   1027                 if (pos->block && pos->block->GetContainingInlinedBlock())
   1028                     continue;
   1029 
   1030                 if (pos->function)
   1031                 {
   1032                     if (pos->function->GetAddressRange().GetBaseAddress() == sc.symbol->GetAddress())
   1033                     {
   1034                         // Do we already have a function with this symbol?
   1035                         if (pos->symbol == sc.symbol)
   1036                             return false;
   1037                         if (pos->symbol == NULL)
   1038                         {
   1039                             pos->symbol = sc.symbol;
   1040                             return false;
   1041                         }
   1042                     }
   1043                 }
   1044             }
   1045         }
   1046     }
   1047     m_symbol_contexts.push_back(sc);
   1048     return true;
   1049 }
   1050 
   1051 bool
   1052 SymbolContextList::MergeSymbolContextIntoFunctionContext (const SymbolContext& symbol_sc,
   1053                                                           uint32_t start_idx,
   1054                                                           uint32_t stop_idx)
   1055 {
   1056     if (symbol_sc.symbol    != NULL
   1057         && symbol_sc.comp_unit == NULL
   1058         && symbol_sc.function  == NULL
   1059         && symbol_sc.block     == NULL
   1060         && symbol_sc.line_entry.IsValid() == false)
   1061     {
   1062         if (symbol_sc.symbol->ValueIsAddress())
   1063         {
   1064             const size_t end = std::min<size_t>(m_symbol_contexts.size(), stop_idx);
   1065             for (size_t i=start_idx; i<end; ++i)
   1066             {
   1067                 const SymbolContext &function_sc = m_symbol_contexts[i];
   1068                 // Don't merge symbols into inlined function symbol contexts
   1069                 if (function_sc.block && function_sc.block->GetContainingInlinedBlock())
   1070                     continue;
   1071 
   1072                 if (function_sc.function)
   1073                 {
   1074                     if (function_sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddress())
   1075                     {
   1076                         // Do we already have a function with this symbol?
   1077                         if (function_sc.symbol == symbol_sc.symbol)
   1078                             return true; // Already have a symbol context with this symbol, return true
   1079 
   1080                         if (function_sc.symbol == NULL)
   1081                         {
   1082                             // We successfully merged this symbol into an existing symbol context
   1083                             m_symbol_contexts[i].symbol = symbol_sc.symbol;
   1084                             return true;
   1085                         }
   1086                     }
   1087                 }
   1088             }
   1089         }
   1090     }
   1091     return false;
   1092 }
   1093 
   1094 void
   1095 SymbolContextList::Clear()
   1096 {
   1097     m_symbol_contexts.clear();
   1098 }
   1099 
   1100 void
   1101 SymbolContextList::Dump(Stream *s, Target *target) const
   1102 {
   1103 
   1104     *s << (void *)this << ": ";
   1105     s->Indent();
   1106     s->PutCString("SymbolContextList");
   1107     s->EOL();
   1108     s->IndentMore();
   1109 
   1110     collection::const_iterator pos, end = m_symbol_contexts.end();
   1111     for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
   1112     {
   1113         //pos->Dump(s, target);
   1114         pos->GetDescription(s, eDescriptionLevelVerbose, target);
   1115     }
   1116     s->IndentLess();
   1117 }
   1118 
   1119 bool
   1120 SymbolContextList::GetContextAtIndex(size_t idx, SymbolContext& sc) const
   1121 {
   1122     if (idx < m_symbol_contexts.size())
   1123     {
   1124         sc = m_symbol_contexts[idx];
   1125         return true;
   1126     }
   1127     return false;
   1128 }
   1129 
   1130 bool
   1131 SymbolContextList::GetLastContext(SymbolContext& sc) const
   1132 {
   1133     if (!m_symbol_contexts.empty())
   1134     {
   1135         sc = m_symbol_contexts.back();
   1136         return true;
   1137     }
   1138     return false;
   1139 }
   1140 
   1141 bool
   1142 SymbolContextList::RemoveContextAtIndex (size_t idx)
   1143 {
   1144     if (idx < m_symbol_contexts.size())
   1145     {
   1146         m_symbol_contexts.erase(m_symbol_contexts.begin() + idx);
   1147         return true;
   1148     }
   1149     return false;
   1150 }
   1151 
   1152 uint32_t
   1153 SymbolContextList::GetSize() const
   1154 {
   1155     return m_symbol_contexts.size();
   1156 }
   1157 
   1158 uint32_t
   1159 SymbolContextList::NumLineEntriesWithLine (uint32_t line) const
   1160 {
   1161     uint32_t match_count = 0;
   1162     const size_t size = m_symbol_contexts.size();
   1163     for (size_t idx = 0; idx<size; ++idx)
   1164     {
   1165         if (m_symbol_contexts[idx].line_entry.line == line)
   1166             ++match_count;
   1167     }
   1168     return match_count;
   1169 }
   1170 
   1171 void
   1172 SymbolContextList::GetDescription(Stream *s,
   1173                                   lldb::DescriptionLevel level,
   1174                                   Target *target) const
   1175 {
   1176     const size_t size = m_symbol_contexts.size();
   1177     for (size_t idx = 0; idx<size; ++idx)
   1178         m_symbol_contexts[idx].GetDescription (s, level, target);
   1179 }
   1180 
   1181 bool
   1182 lldb_private::operator== (const SymbolContextList& lhs, const SymbolContextList& rhs)
   1183 {
   1184     const uint32_t size = lhs.GetSize();
   1185     if (size != rhs.GetSize())
   1186         return false;
   1187 
   1188     SymbolContext lhs_sc;
   1189     SymbolContext rhs_sc;
   1190     for (uint32_t i=0; i<size; ++i)
   1191     {
   1192         lhs.GetContextAtIndex(i, lhs_sc);
   1193         rhs.GetContextAtIndex(i, rhs_sc);
   1194         if (lhs_sc != rhs_sc)
   1195             return false;
   1196     }
   1197     return true;
   1198 }
   1199 
   1200 bool
   1201 lldb_private::operator!= (const SymbolContextList& lhs, const SymbolContextList& rhs)
   1202 {
   1203     return !(lhs == rhs);
   1204 }
   1205 
   1206