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 22using namespace lldb; 23using namespace lldb_private; 24 25Block::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 38Block::~Block () 39{ 40} 41 42void 43Block::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 72void 73Block::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 136Block * 137Block::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 153void 154Block::CalculateSymbolContext (SymbolContext* sc) 155{ 156 if (m_parent_scope) 157 m_parent_scope->CalculateSymbolContext(sc); 158 sc->block = this; 159} 160 161lldb::ModuleSP 162Block::CalculateSymbolContextModule () 163{ 164 if (m_parent_scope) 165 return m_parent_scope->CalculateSymbolContextModule (); 166 return lldb::ModuleSP(); 167} 168 169CompileUnit * 170Block::CalculateSymbolContextCompileUnit () 171{ 172 if (m_parent_scope) 173 return m_parent_scope->CalculateSymbolContextCompileUnit (); 174 return NULL; 175} 176 177Function * 178Block::CalculateSymbolContextFunction () 179{ 180 if (m_parent_scope) 181 return m_parent_scope->CalculateSymbolContextFunction (); 182 return NULL; 183} 184 185Block * 186Block::CalculateSymbolContextBlock () 187{ 188 return this; 189} 190 191void 192Block::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 200void 201Block::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 214bool 215Block::Contains (addr_t range_offset) const 216{ 217 return m_ranges.FindEntryThatContains(range_offset) != NULL; 218} 219 220bool 221Block::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 238bool 239Block::Contains (const Range& range) const 240{ 241 return m_ranges.FindEntryThatContains (range) != NULL; 242} 243 244Block * 245Block::GetParent () const 246{ 247 if (m_parent_scope) 248 return m_parent_scope->CalculateSymbolContextBlock(); 249 return NULL; 250} 251 252Block * 253Block::GetContainingInlinedBlock () 254{ 255 if (GetInlinedFunctionInfo()) 256 return this; 257 return GetInlinedParent (); 258} 259 260Block * 261Block::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 275bool 276Block::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 289bool 290Block::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 320bool 321Block::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 330uint32_t 331Block::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 351bool 352Block::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 369bool 370Block::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 385void 386Block::FinalizeRanges () 387{ 388 m_ranges.Sort(); 389 m_ranges.CombineConsecutiveRanges (); 390} 391 392void 393Block::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 440size_t 441Block::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 452void 453Block::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 462void 463Block::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 470VariableListSP 471Block::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 487uint32_t 488Block::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 520uint32_t 521Block::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 551clang::DeclContext * 552Block::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 574void 575Block::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 587void 588Block::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 600Block * 601Block::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 613Block * 614Block::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