Home | History | Annotate | Download | only in Symbol
      1 //===-- Block.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/Block.h"
     11 
     12 #include "lldb/lldb-private-log.h"
     13 
     14 #include "lldb/Core/Log.h"
     15 #include "lldb/Core/Module.h"
     16 #include "lldb/Core/Section.h"
     17 #include "lldb/Symbol/Function.h"
     18 #include "lldb/Symbol/SymbolFile.h"
     19 #include "lldb/Symbol/SymbolVendor.h"
     20 #include "lldb/Symbol/VariableList.h"
     21 
     22 using namespace lldb;
     23 using namespace lldb_private;
     24 
     25 Block::Block(lldb::user_id_t uid) :
     26     UserID(uid),
     27     m_parent_scope (NULL),
     28     m_children (),
     29     m_ranges (),
     30     m_inlineInfoSP (),
     31     m_variable_list_sp (),
     32     m_parsed_block_info (false),
     33     m_parsed_block_variables (false),
     34     m_parsed_child_blocks (false)
     35 {
     36 }
     37 
     38 Block::~Block ()
     39 {
     40 }
     41 
     42 void
     43 Block::GetDescription(Stream *s, Function *function, lldb::DescriptionLevel level, Target *target) const
     44 {
     45     *s << "id = " << ((const UserID&)*this);
     46 
     47     size_t num_ranges = m_ranges.GetSize();
     48     if (num_ranges > 0)
     49     {
     50 
     51         addr_t base_addr = LLDB_INVALID_ADDRESS;
     52         if (target)
     53             base_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress(target);
     54         if (base_addr == LLDB_INVALID_ADDRESS)
     55             base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
     56 
     57         s->Printf(", range%s = ", num_ranges > 1 ? "s" : "");
     58         for (size_t i=0; i<num_ranges; ++i)
     59         {
     60             const Range &range = m_ranges.GetEntryRef(i);
     61             s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4);
     62         }
     63     }
     64 
     65     if (m_inlineInfoSP.get() != NULL)
     66     {
     67         bool show_fullpaths = (level == eDescriptionLevelVerbose);
     68         m_inlineInfoSP->Dump(s, show_fullpaths);
     69     }
     70 }
     71 
     72 void
     73 Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const
     74 {
     75     if (depth < 0)
     76     {
     77         Block *parent = GetParent();
     78         if (parent)
     79         {
     80             // We have a depth that is less than zero, print our parent blocks
     81             // first
     82             parent->Dump(s, base_addr, depth + 1, show_context);
     83         }
     84     }
     85 
     86     s->Printf("%p: ", this);
     87     s->Indent();
     88     *s << "Block" << ((const UserID&)*this);
     89     const Block* parent_block = GetParent();
     90     if (parent_block)
     91     {
     92         s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID());
     93     }
     94     if (m_inlineInfoSP.get() != NULL)
     95     {
     96         bool show_fullpaths = false;
     97         m_inlineInfoSP->Dump(s, show_fullpaths);
     98     }
     99 
    100     if (!m_ranges.IsEmpty())
    101     {
    102         *s << ", ranges =";
    103 
    104         size_t num_ranges = m_ranges.GetSize();
    105         for (size_t i=0; i<num_ranges; ++i)
    106         {
    107             const Range &range = m_ranges.GetEntryRef(i);
    108             if (parent_block != NULL && parent_block->Contains(range) == false)
    109                 *s << '!';
    110             else
    111                 *s << ' ';
    112             s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4);
    113         }
    114     }
    115     s->EOL();
    116 
    117     if (depth > 0)
    118     {
    119         s->IndentMore();
    120 
    121         if (m_variable_list_sp.get())
    122         {
    123             m_variable_list_sp->Dump(s, show_context);
    124         }
    125 
    126         collection::const_iterator pos, end = m_children.end();
    127         for (pos = m_children.begin(); pos != end; ++pos)
    128             (*pos)->Dump(s, base_addr, depth - 1, show_context);
    129 
    130         s->IndentLess();
    131     }
    132 
    133 }
    134 
    135 
    136 Block *
    137 Block::FindBlockByID (user_id_t block_id)
    138 {
    139     if (block_id == GetID())
    140         return this;
    141 
    142     Block *matching_block = NULL;
    143     collection::const_iterator pos, end = m_children.end();
    144     for (pos = m_children.begin(); pos != end; ++pos)
    145     {
    146         matching_block = (*pos)->FindBlockByID (block_id);
    147         if (matching_block)
    148             break;
    149     }
    150     return matching_block;
    151 }
    152 
    153 void
    154 Block::CalculateSymbolContext (SymbolContext* sc)
    155 {
    156     if (m_parent_scope)
    157         m_parent_scope->CalculateSymbolContext(sc);
    158     sc->block = this;
    159 }
    160 
    161 lldb::ModuleSP
    162 Block::CalculateSymbolContextModule ()
    163 {
    164     if (m_parent_scope)
    165         return m_parent_scope->CalculateSymbolContextModule ();
    166     return lldb::ModuleSP();
    167 }
    168 
    169 CompileUnit *
    170 Block::CalculateSymbolContextCompileUnit ()
    171 {
    172     if (m_parent_scope)
    173         return m_parent_scope->CalculateSymbolContextCompileUnit ();
    174     return NULL;
    175 }
    176 
    177 Function *
    178 Block::CalculateSymbolContextFunction ()
    179 {
    180     if (m_parent_scope)
    181         return m_parent_scope->CalculateSymbolContextFunction ();
    182     return NULL;
    183 }
    184 
    185 Block *
    186 Block::CalculateSymbolContextBlock ()
    187 {
    188     return this;
    189 }
    190 
    191 void
    192 Block::DumpSymbolContext(Stream *s)
    193 {
    194     Function *function = CalculateSymbolContextFunction();
    195     if (function)
    196         function->DumpSymbolContext(s);
    197     s->Printf(", Block{0x%8.8" PRIx64 "}", GetID());
    198 }
    199 
    200 void
    201 Block::DumpAddressRanges (Stream *s, lldb::addr_t base_addr)
    202 {
    203     if (!m_ranges.IsEmpty())
    204     {
    205         size_t num_ranges = m_ranges.GetSize();
    206         for (size_t i=0; i<num_ranges; ++i)
    207         {
    208             const Range &range = m_ranges.GetEntryRef(i);
    209             s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4);
    210         }
    211     }
    212 }
    213 
    214 bool
    215 Block::Contains (addr_t range_offset) const
    216 {
    217     return m_ranges.FindEntryThatContains(range_offset) != NULL;
    218 }
    219 
    220 bool
    221 Block::Contains (const Block *block) const
    222 {
    223     if (this == block)
    224         return false; // This block doesn't contain itself...
    225 
    226     // Walk the parent chain for "block" and see if any if them match this block
    227     const Block *block_parent;
    228     for (block_parent = block->GetParent();
    229          block_parent != NULL;
    230          block_parent = block_parent->GetParent())
    231     {
    232         if (this == block_parent)
    233             return true; // One of the parents of "block" is this object!
    234     }
    235     return false;
    236 }
    237 
    238 bool
    239 Block::Contains (const Range& range) const
    240 {
    241     return m_ranges.FindEntryThatContains (range) != NULL;
    242 }
    243 
    244 Block *
    245 Block::GetParent () const
    246 {
    247     if (m_parent_scope)
    248         return m_parent_scope->CalculateSymbolContextBlock();
    249     return NULL;
    250 }
    251 
    252 Block *
    253 Block::GetContainingInlinedBlock ()
    254 {
    255     if (GetInlinedFunctionInfo())
    256         return this;
    257     return GetInlinedParent ();
    258 }
    259 
    260 Block *
    261 Block::GetInlinedParent ()
    262 {
    263     Block *parent_block = GetParent ();
    264     if (parent_block)
    265     {
    266         if (parent_block->GetInlinedFunctionInfo())
    267             return parent_block;
    268         else
    269             return parent_block->GetInlinedParent();
    270     }
    271     return NULL;
    272 }
    273 
    274 
    275 bool
    276 Block::GetRangeContainingOffset (const addr_t offset, Range &range)
    277 {
    278     const Range *range_ptr = m_ranges.FindEntryThatContains (offset);
    279     if (range_ptr)
    280     {
    281         range = *range_ptr;
    282         return true;
    283     }
    284     range.Clear();
    285     return false;
    286 }
    287 
    288 
    289 bool
    290 Block::GetRangeContainingAddress (const Address& addr, AddressRange &range)
    291 {
    292     Function *function = CalculateSymbolContextFunction();
    293     if (function)
    294     {
    295         const AddressRange &func_range = function->GetAddressRange();
    296         if (addr.GetSection() == func_range.GetBaseAddress().GetSection())
    297         {
    298             const addr_t addr_offset = addr.GetOffset();
    299             const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
    300             if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize())
    301             {
    302                 addr_t offset = addr_offset - func_offset;
    303 
    304                 const Range *range_ptr = m_ranges.FindEntryThatContains (offset);
    305 
    306                 if (range_ptr)
    307                 {
    308                     range.GetBaseAddress() = func_range.GetBaseAddress();
    309                     range.GetBaseAddress().SetOffset(func_offset + range_ptr->GetRangeBase());
    310                     range.SetByteSize(range_ptr->GetByteSize());
    311                     return true;
    312                 }
    313             }
    314         }
    315     }
    316     range.Clear();
    317     return false;
    318 }
    319 
    320 bool
    321 Block::GetRangeContainingLoadAddress (lldb::addr_t load_addr, Target &target, AddressRange &range)
    322 {
    323     Address load_address;
    324     load_address.SetLoadAddress(load_addr, &target);
    325     AddressRange containing_range;
    326     return GetRangeContainingAddress(load_address, containing_range);
    327 }
    328 
    329 
    330 uint32_t
    331 Block::GetRangeIndexContainingAddress (const Address& addr)
    332 {
    333     Function *function = CalculateSymbolContextFunction();
    334     if (function)
    335     {
    336         const AddressRange &func_range = function->GetAddressRange();
    337         if (addr.GetSection() == func_range.GetBaseAddress().GetSection())
    338         {
    339             const addr_t addr_offset = addr.GetOffset();
    340             const addr_t func_offset = func_range.GetBaseAddress().GetOffset();
    341             if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize())
    342             {
    343                 addr_t offset = addr_offset - func_offset;
    344                 return m_ranges.FindEntryIndexThatContains (offset);
    345             }
    346         }
    347     }
    348     return UINT32_MAX;
    349 }
    350 
    351 bool
    352 Block::GetRangeAtIndex (uint32_t range_idx, AddressRange &range)
    353 {
    354     if (range_idx < m_ranges.GetSize())
    355     {
    356         Function *function = CalculateSymbolContextFunction();
    357         if (function)
    358         {
    359             const Range &vm_range = m_ranges.GetEntryRef(range_idx);
    360             range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress();
    361             range.GetBaseAddress().Slide(vm_range.GetRangeBase ());
    362             range.SetByteSize (vm_range.GetByteSize());
    363             return true;
    364         }
    365     }
    366     return false;
    367 }
    368 
    369 bool
    370 Block::GetStartAddress (Address &addr)
    371 {
    372     if (m_ranges.IsEmpty())
    373         return false;
    374 
    375     Function *function = CalculateSymbolContextFunction();
    376     if (function)
    377     {
    378         addr = function->GetAddressRange().GetBaseAddress();
    379         addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase ());
    380         return true;
    381     }
    382     return false;
    383 }
    384 
    385 void
    386 Block::FinalizeRanges ()
    387 {
    388     m_ranges.Sort();
    389     m_ranges.CombineConsecutiveRanges ();
    390 }
    391 
    392 void
    393 Block::AddRange (const Range& range)
    394 {
    395     Block *parent_block = GetParent ();
    396     if (parent_block && !parent_block->Contains(range))
    397     {
    398         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
    399         if (log)
    400         {
    401             ModuleSP module_sp (m_parent_scope->CalculateSymbolContextModule());
    402             Function *function = m_parent_scope->CalculateSymbolContextFunction();
    403             const addr_t function_file_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
    404             const addr_t block_start_addr = function_file_addr + range.GetRangeBase ();
    405             const addr_t block_end_addr = function_file_addr + range.GetRangeEnd ();
    406             Type *func_type = function->GetType();
    407 
    408             const Declaration &func_decl = func_type->GetDeclaration();
    409             if (func_decl.GetLine())
    410             {
    411                 log->Printf ("warning: %s:%u block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 ") which is not contained in parent block {0x%8.8" PRIx64 "} in function {0x%8.8" PRIx64 "} from %s",
    412                              func_decl.GetFile().GetPath().c_str(),
    413                              func_decl.GetLine(),
    414                              GetID(),
    415                              (uint32_t)m_ranges.GetSize(),
    416                              block_start_addr,
    417                              block_end_addr,
    418                              parent_block->GetID(),
    419                              function->GetID(),
    420                              module_sp->GetFileSpec().GetPath().c_str());
    421             }
    422             else
    423             {
    424                 log->Printf ("warning: block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 ") which is not contained in parent block {0x%8.8" PRIx64 "} in function {0x%8.8" PRIx64 "} from %s",
    425                              GetID(),
    426                              (uint32_t)m_ranges.GetSize(),
    427                              block_start_addr,
    428                              block_end_addr,
    429                              parent_block->GetID(),
    430                              function->GetID(),
    431                              module_sp->GetFileSpec().GetPath().c_str());
    432             }
    433         }
    434         parent_block->AddRange (range);
    435     }
    436     m_ranges.Append(range);
    437 }
    438 
    439 // Return the current number of bytes that this object occupies in memory
    440 size_t
    441 Block::MemorySize() const
    442 {
    443     size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range);
    444     if (m_inlineInfoSP.get())
    445         mem_size += m_inlineInfoSP->MemorySize();
    446     if (m_variable_list_sp.get())
    447         mem_size += m_variable_list_sp->MemorySize();
    448     return mem_size;
    449 
    450 }
    451 
    452 void
    453 Block::AddChild(const BlockSP &child_block_sp)
    454 {
    455     if (child_block_sp)
    456     {
    457         child_block_sp->SetParentScope (this);
    458         m_children.push_back (child_block_sp);
    459     }
    460 }
    461 
    462 void
    463 Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
    464 {
    465     m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr));
    466 }
    467 
    468 
    469 
    470 VariableListSP
    471 Block::GetBlockVariableList (bool can_create)
    472 {
    473     if (m_parsed_block_variables == false)
    474     {
    475         if (m_variable_list_sp.get() == NULL && can_create)
    476         {
    477             m_parsed_block_variables = true;
    478             SymbolContext sc;
    479             CalculateSymbolContext(&sc);
    480             assert(sc.module_sp);
    481             sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
    482         }
    483     }
    484     return m_variable_list_sp;
    485 }
    486 
    487 uint32_t
    488 Block::AppendBlockVariables (bool can_create,
    489                              bool get_child_block_variables,
    490                              bool stop_if_child_block_is_inlined_function,
    491                              VariableList *variable_list)
    492 {
    493     uint32_t num_variables_added = 0;
    494     VariableList *block_var_list = GetBlockVariableList (can_create).get();
    495     if (block_var_list)
    496     {
    497         num_variables_added += block_var_list->GetSize();
    498         variable_list->AddVariables (block_var_list);
    499     }
    500 
    501     if (get_child_block_variables)
    502     {
    503         collection::const_iterator pos, end = m_children.end();
    504         for (pos = m_children.begin(); pos != end; ++pos)
    505         {
    506             Block *child_block = pos->get();
    507             if (stop_if_child_block_is_inlined_function == false ||
    508                 child_block->GetInlinedFunctionInfo() == NULL)
    509             {
    510                 num_variables_added += child_block->AppendBlockVariables (can_create,
    511                                                                           get_child_block_variables,
    512                                                                           stop_if_child_block_is_inlined_function,
    513                                                                           variable_list);
    514             }
    515         }
    516     }
    517     return num_variables_added;
    518 }
    519 
    520 uint32_t
    521 Block::AppendVariables
    522 (
    523     bool can_create,
    524     bool get_parent_variables,
    525     bool stop_if_block_is_inlined_function,
    526     VariableList *variable_list
    527 )
    528 {
    529     uint32_t num_variables_added = 0;
    530     VariableListSP variable_list_sp(GetBlockVariableList(can_create));
    531 
    532     bool is_inlined_function = GetInlinedFunctionInfo() != NULL;
    533     if (variable_list_sp.get())
    534     {
    535         num_variables_added = variable_list_sp->GetSize();
    536         variable_list->AddVariables(variable_list_sp.get());
    537     }
    538 
    539     if (get_parent_variables)
    540     {
    541         if (stop_if_block_is_inlined_function && is_inlined_function)
    542             return num_variables_added;
    543 
    544         Block* parent_block = GetParent();
    545         if (parent_block)
    546             num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list);
    547     }
    548     return num_variables_added;
    549 }
    550 
    551 clang::DeclContext *
    552 Block::GetClangDeclContext()
    553 {
    554     SymbolContext sc;
    555 
    556     CalculateSymbolContext (&sc);
    557 
    558     if (!sc.module_sp)
    559         return NULL;
    560 
    561     SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
    562 
    563     if (!sym_vendor)
    564         return NULL;
    565 
    566     SymbolFile *sym_file = sym_vendor->GetSymbolFile();
    567 
    568     if (!sym_file)
    569         return NULL;
    570 
    571     return sym_file->GetClangDeclContextForTypeUID (sc, m_uid);
    572 }
    573 
    574 void
    575 Block::SetBlockInfoHasBeenParsed (bool b, bool set_children)
    576 {
    577     m_parsed_block_info = b;
    578     if (set_children)
    579     {
    580         m_parsed_child_blocks = true;
    581         collection::const_iterator pos, end = m_children.end();
    582         for (pos = m_children.begin(); pos != end; ++pos)
    583             (*pos)->SetBlockInfoHasBeenParsed (b, true);
    584     }
    585 }
    586 
    587 void
    588 Block::SetDidParseVariables (bool b, bool set_children)
    589 {
    590     m_parsed_block_variables = b;
    591     if (set_children)
    592     {
    593         collection::const_iterator pos, end = m_children.end();
    594         for (pos = m_children.begin(); pos != end; ++pos)
    595             (*pos)->SetDidParseVariables (b, true);
    596     }
    597 }
    598 
    599 
    600 Block *
    601 Block::GetSibling() const
    602 {
    603     if (m_parent_scope)
    604     {
    605         Block *parent_block = GetParent();
    606         if (parent_block)
    607             return parent_block->GetSiblingForChild (this);
    608     }
    609     return NULL;
    610 }
    611 // A parent of child blocks can be asked to find a sibling block given
    612 // one of its child blocks
    613 Block *
    614 Block::GetSiblingForChild (const Block *child_block) const
    615 {
    616     if (!m_children.empty())
    617     {
    618         collection::const_iterator pos, end = m_children.end();
    619         for (pos = m_children.begin(); pos != end; ++pos)
    620         {
    621             if (pos->get() == child_block)
    622             {
    623                 if (++pos != end)
    624                     return pos->get();
    625                 break;
    626             }
    627         }
    628     }
    629     return NULL;
    630 }
    631 
    632