1 //===-- Block.cpp -----------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Symbol/Block.h"
12 #include "lldb/lldb-private-log.h"
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"
23 using namespace lldb_private;
25 Block::Block(lldb::user_id_t uid) :
27 m_parent_scope (NULL),
31 m_variable_list_sp (),
32 m_parsed_block_info (false),
33 m_parsed_block_variables (false),
34 m_parsed_child_blocks (false)
43 Block::GetDescription(Stream *s, Function *function, lldb::DescriptionLevel level, Target *target) const
45 *s << "id = " << ((const UserID&)*this);
47 size_t num_ranges = m_ranges.GetSize();
51 addr_t base_addr = LLDB_INVALID_ADDRESS;
53 base_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress(target);
54 if (base_addr == LLDB_INVALID_ADDRESS)
55 base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
57 s->Printf(", range%s = ", num_ranges > 1 ? "s" : "");
58 for (size_t i=0; i<num_ranges; ++i)
60 const Range &range = m_ranges.GetEntryRef(i);
61 s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4);
65 if (m_inlineInfoSP.get() != NULL)
67 bool show_fullpaths = (level == eDescriptionLevelVerbose);
68 m_inlineInfoSP->Dump(s, show_fullpaths);
73 Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const
77 Block *parent = GetParent();
80 // We have a depth that is less than zero, print our parent blocks
82 parent->Dump(s, base_addr, depth + 1, show_context);
86 s->Printf("%p: ", this);
88 *s << "Block" << ((const UserID&)*this);
89 const Block* parent_block = GetParent();
92 s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID());
94 if (m_inlineInfoSP.get() != NULL)
96 bool show_fullpaths = false;
97 m_inlineInfoSP->Dump(s, show_fullpaths);
100 if (!m_ranges.IsEmpty())
104 size_t num_ranges = m_ranges.GetSize();
105 for (size_t i=0; i<num_ranges; ++i)
107 const Range &range = m_ranges.GetEntryRef(i);
108 if (parent_block != NULL && parent_block->Contains(range) == false)
112 s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4);
121 if (m_variable_list_sp.get())
123 m_variable_list_sp->Dump(s, show_context);
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);
137 Block::FindBlockByID (user_id_t block_id)
139 if (block_id == GetID())
142 Block *matching_block = NULL;
143 collection::const_iterator pos, end = m_children.end();
144 for (pos = m_children.begin(); pos != end; ++pos)
146 matching_block = (*pos)->FindBlockByID (block_id);
150 return matching_block;
154 Block::CalculateSymbolContext (SymbolContext* sc)
157 m_parent_scope->CalculateSymbolContext(sc);
162 Block::CalculateSymbolContextModule ()
165 return m_parent_scope->CalculateSymbolContextModule ();
166 return lldb::ModuleSP();
170 Block::CalculateSymbolContextCompileUnit ()
173 return m_parent_scope->CalculateSymbolContextCompileUnit ();
178 Block::CalculateSymbolContextFunction ()
181 return m_parent_scope->CalculateSymbolContextFunction ();
186 Block::CalculateSymbolContextBlock ()
192 Block::DumpSymbolContext(Stream *s)
194 Function *function = CalculateSymbolContextFunction();
196 function->DumpSymbolContext(s);
197 s->Printf(", Block{0x%8.8" PRIx64 "}", GetID());
201 Block::DumpAddressRanges (Stream *s, lldb::addr_t base_addr)
203 if (!m_ranges.IsEmpty())
205 size_t num_ranges = m_ranges.GetSize();
206 for (size_t i=0; i<num_ranges; ++i)
208 const Range &range = m_ranges.GetEntryRef(i);
209 s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4);
215 Block::Contains (addr_t range_offset) const
217 return m_ranges.FindEntryThatContains(range_offset) != NULL;
221 Block::Contains (const Block *block) const
224 return false; // This block doesn't contain itself...
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())
232 if (this == block_parent)
233 return true; // One of the parents of "block" is this object!
239 Block::Contains (const Range& range) const
241 return m_ranges.FindEntryThatContains (range) != NULL;
245 Block::GetParent () const
248 return m_parent_scope->CalculateSymbolContextBlock();
253 Block::GetContainingInlinedBlock ()
255 if (GetInlinedFunctionInfo())
257 return GetInlinedParent ();
261 Block::GetInlinedParent ()
263 Block *parent_block = GetParent ();
266 if (parent_block->GetInlinedFunctionInfo())
269 return parent_block->GetInlinedParent();
276 Block::GetRangeContainingOffset (const addr_t offset, Range &range)
278 const Range *range_ptr = m_ranges.FindEntryThatContains (offset);
290 Block::GetRangeContainingAddress (const Address& addr, AddressRange &range)
292 Function *function = CalculateSymbolContextFunction();
295 const AddressRange &func_range = function->GetAddressRange();
296 if (addr.GetSection() == func_range.GetBaseAddress().GetSection())
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())
302 addr_t offset = addr_offset - func_offset;
304 const Range *range_ptr = m_ranges.FindEntryThatContains (offset);
308 range.GetBaseAddress() = func_range.GetBaseAddress();
309 range.GetBaseAddress().SetOffset(func_offset + range_ptr->GetRangeBase());
310 range.SetByteSize(range_ptr->GetByteSize());
321 Block::GetRangeContainingLoadAddress (lldb::addr_t load_addr, Target &target, AddressRange &range)
323 Address load_address;
324 load_address.SetLoadAddress(load_addr, &target);
325 AddressRange containing_range;
326 return GetRangeContainingAddress(load_address, containing_range);
331 Block::GetRangeIndexContainingAddress (const Address& addr)
333 Function *function = CalculateSymbolContextFunction();
336 const AddressRange &func_range = function->GetAddressRange();
337 if (addr.GetSection() == func_range.GetBaseAddress().GetSection())
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())
343 addr_t offset = addr_offset - func_offset;
344 return m_ranges.FindEntryIndexThatContains (offset);
352 Block::GetRangeAtIndex (uint32_t range_idx, AddressRange &range)
354 if (range_idx < m_ranges.GetSize())
356 Function *function = CalculateSymbolContextFunction();
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());
370 Block::GetStartAddress (Address &addr)
372 if (m_ranges.IsEmpty())
375 Function *function = CalculateSymbolContextFunction();
378 addr = function->GetAddressRange().GetBaseAddress();
379 addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase ());
386 Block::FinalizeRanges ()
389 m_ranges.CombineConsecutiveRanges ();
393 Block::AddRange (const Range& range)
395 Block *parent_block = GetParent ();
396 if (parent_block && !parent_block->Contains(range))
398 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
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();
408 const Declaration &func_decl = func_type->GetDeclaration();
409 if (func_decl.GetLine())
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(),
415 (uint32_t)m_ranges.GetSize(),
418 parent_block->GetID(),
420 module_sp->GetFileSpec().GetPath().c_str());
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",
426 (uint32_t)m_ranges.GetSize(),
429 parent_block->GetID(),
431 module_sp->GetFileSpec().GetPath().c_str());
434 parent_block->AddRange (range);
436 m_ranges.Append(range);
439 // Return the current number of bytes that this object occupies in memory
441 Block::MemorySize() const
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();
453 Block::AddChild(const BlockSP &child_block_sp)
457 child_block_sp->SetParentScope (this);
458 m_children.push_back (child_block_sp);
463 Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
465 m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr));
471 Block::GetBlockVariableList (bool can_create)
473 if (m_parsed_block_variables == false)
475 if (m_variable_list_sp.get() == NULL && can_create)
477 m_parsed_block_variables = true;
479 CalculateSymbolContext(&sc);
480 assert(sc.module_sp);
481 sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
484 return m_variable_list_sp;
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)
493 uint32_t num_variables_added = 0;
494 VariableList *block_var_list = GetBlockVariableList (can_create).get();
497 num_variables_added += block_var_list->GetSize();
498 variable_list->AddVariables (block_var_list);
501 if (get_child_block_variables)
503 collection::const_iterator pos, end = m_children.end();
504 for (pos = m_children.begin(); pos != end; ++pos)
506 Block *child_block = pos->get();
507 if (stop_if_child_block_is_inlined_function == false ||
508 child_block->GetInlinedFunctionInfo() == NULL)
510 num_variables_added += child_block->AppendBlockVariables (can_create,
511 get_child_block_variables,
512 stop_if_child_block_is_inlined_function,
517 return num_variables_added;
521 Block::AppendVariables
524 bool get_parent_variables,
525 bool stop_if_block_is_inlined_function,
526 VariableList *variable_list
529 uint32_t num_variables_added = 0;
530 VariableListSP variable_list_sp(GetBlockVariableList(can_create));
532 bool is_inlined_function = GetInlinedFunctionInfo() != NULL;
533 if (variable_list_sp.get())
535 num_variables_added = variable_list_sp->GetSize();
536 variable_list->AddVariables(variable_list_sp.get());
539 if (get_parent_variables)
541 if (stop_if_block_is_inlined_function && is_inlined_function)
542 return num_variables_added;
544 Block* parent_block = GetParent();
546 num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list);
548 return num_variables_added;
552 Block::GetClangDeclContext()
556 CalculateSymbolContext (&sc);
561 SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
566 SymbolFile *sym_file = sym_vendor->GetSymbolFile();
571 return sym_file->GetClangDeclContextForTypeUID (sc, m_uid);
575 Block::SetBlockInfoHasBeenParsed (bool b, bool set_children)
577 m_parsed_block_info = b;
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);
588 Block::SetDidParseVariables (bool b, bool set_children)
590 m_parsed_block_variables = b;
593 collection::const_iterator pos, end = m_children.end();
594 for (pos = m_children.begin(); pos != end; ++pos)
595 (*pos)->SetDidParseVariables (b, true);
601 Block::GetSibling() const
605 Block *parent_block = GetParent();
607 return parent_block->GetSiblingForChild (this);
611 // A parent of child blocks can be asked to find a sibling block given
612 // one of its child blocks
614 Block::GetSiblingForChild (const Block *child_block) const
616 if (!m_children.empty())
618 collection::const_iterator pos, end = m_children.end();
619 for (pos = m_children.begin(); pos != end; ++pos)
621 if (pos->get() == child_block)