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 #include "lldb/Symbol/Function.h" 12 #include "lldb/Core/Module.h" 13 #include "lldb/Core/Section.h" 14 #include "lldb/Symbol/SymbolVendor.h" 15 #include "lldb/Symbol/VariableList.h" 16 17 using namespace lldb; 18 using namespace lldb_private; 19 20 Block::Block(user_id_t uid, uint32_t depth, BlockList* blocks) : 21 UserID(uid), 22 m_block_list(blocks), 23 m_depth(depth), 24 m_ranges(), 25 m_inlineInfoSP(), 26 m_variables() 27 { 28 } 29 30 Block::Block(const Block& rhs) : 31 UserID(rhs), 32 m_block_list(rhs.m_block_list), 33 m_depth(rhs.m_depth), 34 m_ranges(rhs.m_ranges), 35 m_inlineInfoSP(rhs.m_inlineInfoSP), 36 m_variables(rhs.m_variables) 37 { 38 } 39 40 const Block& 41 Block::operator= (const Block& rhs) 42 { 43 if (this != &rhs) 44 { 45 UserID::operator= (rhs); 46 m_block_list = rhs.m_block_list; 47 m_depth = rhs.m_depth; 48 m_ranges = rhs.m_ranges; 49 m_inlineInfoSP = rhs.m_inlineInfoSP; 50 m_variables = rhs.m_variables; 51 } 52 return *this; 53 } 54 55 Block::~Block () 56 { 57 } 58 59 void 60 Block::GetDescription(Stream *s, lldb::DescriptionLevel level, Process *process) const 61 { 62 size_t num_ranges = m_ranges.size(); 63 if (num_ranges) 64 { 65 66 addr_t base_addr = LLDB_INVALID_ADDRESS; 67 if (process) 68 base_addr = m_block_list->GetAddressRange().GetBaseAddress().GetLoadAddress(process); 69 if (base_addr == LLDB_INVALID_ADDRESS) 70 base_addr = m_block_list->GetAddressRange().GetBaseAddress().GetFileAddress(); 71 72 s->Printf("range%s = ", num_ranges > 1 ? "s" : ""); 73 std::vector<VMRange>::const_iterator pos, end = m_ranges.end(); 74 for (pos = m_ranges.begin(); pos != end; ++pos) 75 pos->Dump(s, base_addr, 4); 76 } 77 *s << ", id = " << ((const UserID&)*this); 78 79 if (m_inlineInfoSP.get() != NULL) 80 m_inlineInfoSP->Dump(s); 81 } 82 83 void 84 Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const 85 { 86 if (depth < 0) 87 { 88 // We have a depth that is less than zero, print our parent blocks 89 // first 90 m_block_list->Dump(s, GetParentUID(), depth + 1, show_context); 91 } 92 93 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 94 s->Indent(); 95 *s << "Block" << ((const UserID&)*this); 96 const Block* parent_block = GetParent(); 97 if (parent_block) 98 { 99 s->Printf(", parent = {0x%8.8x}", parent_block->GetID()); 100 } 101 if (m_inlineInfoSP.get() != NULL) 102 m_inlineInfoSP->Dump(s); 103 104 if (!m_ranges.empty()) 105 { 106 *s << ", ranges ="; 107 std::vector<VMRange>::const_iterator pos; 108 std::vector<VMRange>::const_iterator end = m_ranges.end(); 109 for (pos = m_ranges.begin(); pos != end; ++pos) 110 { 111 if (parent_block != NULL && parent_block->Contains(*pos) == false) 112 *s << '!'; 113 else 114 *s << ' '; 115 pos->Dump(s, base_addr); 116 } 117 } 118 s->EOL(); 119 120 if (depth > 0) 121 { 122 s->IndentMore(); 123 124 if (m_variables.get()) 125 { 126 m_variables->Dump(s, show_context); 127 } 128 129 uint32_t blockID = m_block_list->GetFirstChild(GetID()); 130 while (blockID != Block::InvalidID) 131 { 132 m_block_list->Dump(s, blockID, depth - 1, show_context); 133 134 blockID = m_block_list->GetSibling(blockID); 135 } 136 137 s->IndentLess(); 138 } 139 140 } 141 142 143 void 144 Block::CalculateSymbolContext(SymbolContext* sc) 145 { 146 sc->block = this; 147 m_block_list->GetFunction()->CalculateSymbolContext(sc); 148 } 149 150 void 151 Block::DumpStopContext (Stream *s, const SymbolContext *sc) 152 { 153 Block* parent_block = GetParent(); 154 155 InlineFunctionInfo* inline_info = InlinedFunctionInfo (); 156 if (inline_info) 157 { 158 const Declaration &call_site = inline_info->GetCallSite(); 159 if (sc) 160 { 161 // First frame, dump the first inline call site 162 // if (call_site.IsValid()) 163 // { 164 // s->PutCString(" at "); 165 // call_site.DumpStopContext (s); 166 // } 167 s->PutCString (" [inlined]"); 168 } 169 s->EOL(); 170 inline_info->DumpStopContext (s); 171 if (sc == NULL) 172 { 173 if (call_site.IsValid()) 174 { 175 s->PutCString(" at "); 176 call_site.DumpStopContext (s); 177 } 178 } 179 } 180 181 if (sc) 182 { 183 // If we have any inlined functions, this will be the deepest most 184 // inlined location 185 if (sc->line_entry.IsValid()) 186 { 187 s->PutCString(" at "); 188 sc->line_entry.DumpStopContext (s); 189 } 190 } 191 if (parent_block) 192 parent_block->Block::DumpStopContext (s, NULL); 193 } 194 195 196 void 197 Block::DumpSymbolContext(Stream *s) 198 { 199 m_block_list->GetFunction()->DumpSymbolContext(s); 200 s->Printf(", Block{0x%8.8x}", GetID()); 201 } 202 203 bool 204 Block::Contains (addr_t range_offset) const 205 { 206 return VMRange::ContainsValue(m_ranges, range_offset); 207 } 208 209 bool 210 Block::Contains (const VMRange& range) const 211 { 212 return VMRange::ContainsRange(m_ranges, range); 213 } 214 215 216 217 bool 218 BlockList::BlockContainsBlockWithID (const user_id_t block_id, const user_id_t find_block_id) const 219 { 220 if (block_id == Block::InvalidID) 221 return false; 222 223 if (block_id == find_block_id) 224 return true; 225 else 226 { 227 user_id_t child_block_id = GetFirstChild(block_id); 228 while (child_block_id != Block::InvalidID) 229 { 230 if (BlockContainsBlockWithID (child_block_id, find_block_id)) 231 return true; 232 child_block_id = GetSibling(child_block_id); 233 } 234 } 235 236 return false; 237 } 238 239 bool 240 Block::ContainsBlockWithID (user_id_t block_id) const 241 { 242 return m_block_list->BlockContainsBlockWithID (GetID(), block_id); 243 } 244 245 246 void 247 Block::AddRange(addr_t start_offset, addr_t end_offset) 248 { 249 m_ranges.resize(m_ranges.size()+1); 250 m_ranges.back().Reset(start_offset, end_offset); 251 } 252 253 InlineFunctionInfo* 254 Block::InlinedFunctionInfo () 255 { 256 return m_inlineInfoSP.get(); 257 } 258 259 const InlineFunctionInfo* 260 Block::InlinedFunctionInfo () const 261 { 262 return m_inlineInfoSP.get(); 263 } 264 265 // Return the current number of bytes that this object occupies in memory 266 size_t 267 Block::MemorySize() const 268 { 269 size_t mem_size = sizeof(Block) + m_ranges.size() * sizeof(VMRange); 270 if (m_inlineInfoSP.get()) 271 mem_size += m_inlineInfoSP->MemorySize(); 272 if (m_variables.get()) 273 mem_size += m_variables->MemorySize(); 274 return mem_size; 275 276 } 277 278 Block * 279 Block::GetParent () const 280 { 281 return m_block_list->GetBlockByID (m_block_list->GetParent(GetID())); 282 } 283 284 Block * 285 Block::GetSibling () const 286 { 287 return m_block_list->GetBlockByID (m_block_list->GetSibling(GetID())); 288 } 289 290 Block * 291 Block::GetFirstChild () const 292 { 293 return m_block_list->GetBlockByID (m_block_list->GetFirstChild(GetID())); 294 } 295 296 user_id_t 297 Block::GetParentUID() const 298 { 299 return m_block_list->GetParent(GetID()); 300 } 301 302 user_id_t 303 Block::GetSiblingUID() const 304 { 305 return m_block_list->GetSibling(GetID()); 306 } 307 308 user_id_t 309 Block::GetFirstChildUID() const 310 { 311 return m_block_list->GetFirstChild(GetID()); 312 } 313 314 user_id_t 315 Block::AddChild(user_id_t userID) 316 { 317 return m_block_list->AddChild(GetID(), userID); 318 } 319 320 void 321 Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr) 322 { 323 m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr)); 324 } 325 326 BlockList::BlockList(Function *function, const AddressRange& range) : 327 m_function(function), 328 m_range(range), 329 m_blocks() 330 { 331 } 332 333 BlockList::~BlockList() 334 { 335 } 336 337 AddressRange & 338 BlockList::GetAddressRange() 339 { 340 return m_range; 341 } 342 343 const AddressRange & 344 BlockList::GetAddressRange() const 345 { 346 return m_range; 347 } 348 349 void 350 BlockList::Dump(Stream *s, user_id_t blockID, uint32_t depth, bool show_context) const 351 { 352 const Block* block = GetBlockByID(blockID); 353 if (block) 354 block->Dump(s, m_range.GetBaseAddress().GetFileAddress(), depth, show_context); 355 } 356 357 Function * 358 BlockList::GetFunction() 359 { 360 return m_function; 361 } 362 363 364 const Function * 365 BlockList::GetFunction() const 366 { 367 return m_function; 368 } 369 370 user_id_t 371 BlockList::GetParent(user_id_t blockID) const 372 { 373 collection::const_iterator end = m_blocks.end(); 374 collection::const_iterator begin = m_blocks.begin(); 375 collection::const_iterator pos = std::find_if(begin, end, UserID::IDMatches(blockID)); 376 377 if (pos != end && pos != begin && pos->Depth() > 0) 378 { 379 const uint32_t parent_depth = pos->Depth() - 1; 380 381 while (--pos >= begin) 382 { 383 if (pos->Depth() == parent_depth) 384 return pos->GetID(); 385 } 386 } 387 return Block::InvalidID; 388 } 389 390 user_id_t 391 BlockList::GetSibling(user_id_t blockID) const 392 { 393 collection::const_iterator end = m_blocks.end(); 394 collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID)); 395 396 if (pos != end) 397 { 398 const uint32_t sibling_depth = pos->Depth(); 399 while (++pos != end) 400 { 401 uint32_t depth = pos->Depth(); 402 if (depth == sibling_depth) 403 return pos->GetID(); 404 if (depth < sibling_depth) 405 break; 406 } 407 } 408 return Block::InvalidID; 409 } 410 411 user_id_t 412 BlockList::GetFirstChild(user_id_t blockID) const 413 { 414 if (!m_blocks.empty()) 415 { 416 if (blockID == Block::RootID) 417 { 418 return m_blocks.front().GetID(); 419 } 420 else 421 { 422 collection::const_iterator end = m_blocks.end(); 423 collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID)); 424 425 if (pos != end) 426 { 427 collection::const_iterator child_pos = pos + 1; 428 if (child_pos != end) 429 { 430 if (child_pos->Depth() == pos->Depth() + 1) 431 return child_pos->GetID(); 432 } 433 } 434 } 435 } 436 return Block::InvalidID; 437 } 438 439 440 // Return the current number of bytes that this object occupies in memory 441 size_t 442 BlockList::MemorySize() const 443 { 444 size_t mem_size = sizeof(BlockList); 445 446 collection::const_iterator pos, end = m_blocks.end(); 447 for (pos = m_blocks.begin(); pos != end; ++pos) 448 mem_size += pos->MemorySize(); // Each block can vary in size 449 450 return mem_size; 451 452 } 453 454 user_id_t 455 BlockList::AddChild (user_id_t parentID, user_id_t childID) 456 { 457 bool added = false; 458 if (parentID == Block::RootID) 459 { 460 assert(m_blocks.empty()); 461 Block block(childID, 0, this); 462 m_blocks.push_back(block); 463 added = true; 464 } 465 else 466 { 467 collection::iterator end = m_blocks.end(); 468 collection::iterator parent_pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(parentID)); 469 assert(parent_pos != end); 470 if (parent_pos != end) 471 { 472 const uint32_t parent_sibling_depth = parent_pos->Depth(); 473 474 collection::iterator insert_pos = parent_pos; 475 collection::iterator prev_sibling = end; 476 while (++insert_pos != end) 477 { 478 if (insert_pos->Depth() <= parent_sibling_depth) 479 break; 480 } 481 482 Block child_block(childID, parent_pos->Depth() + 1, this); 483 collection::iterator child_pos = m_blocks.insert(insert_pos, child_block); 484 added = true; 485 } 486 } 487 if (added) 488 return childID; 489 return Block::InvalidID; 490 } 491 492 const Block * 493 BlockList::GetBlockByID(user_id_t blockID) const 494 { 495 if (m_blocks.empty() || blockID == Block::InvalidID) 496 return NULL; 497 498 if (blockID == Block::RootID) 499 blockID = m_blocks.front().GetID(); 500 501 collection::const_iterator end = m_blocks.end(); 502 collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID)); 503 if (pos != end) 504 return &(*pos); 505 return NULL; 506 } 507 508 Block * 509 BlockList::GetBlockByID(user_id_t blockID) 510 { 511 if (m_blocks.empty() || blockID == Block::InvalidID) 512 return NULL; 513 514 if (blockID == Block::RootID) 515 blockID = m_blocks.front().GetID(); 516 517 collection::iterator end = m_blocks.end(); 518 collection::iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID)); 519 if (pos != end) 520 return &(*pos); 521 return NULL; 522 } 523 524 bool 525 BlockList::AddRange(user_id_t blockID, addr_t start_offset, addr_t end_offset) 526 { 527 Block *block = GetBlockByID(blockID); 528 529 if (block) 530 { 531 block->AddRange(start_offset, end_offset); 532 return true; 533 } 534 return false; 535 } 536 // 537 //const Block * 538 //BlockList::FindDeepestBlockForAddress (const Address &addr) 539 //{ 540 // if (m_range.Contains(addr)) 541 // { 542 // addr_t block_offset = addr.GetFileAddress() - m_range.GetBaseAddress().GetFileAddress(); 543 // collection::const_iterator pos, end = m_blocks.end(); 544 // collection::const_iterator deepest_match_pos = end; 545 // for (pos = m_blocks.begin(); pos != end; ++pos) 546 // { 547 // if (pos->Contains (block_offset)) 548 // { 549 // if (deepest_match_pos == end || deepest_match_pos->Depth() < pos->Depth()) 550 // deepest_match_pos = pos; 551 // } 552 // } 553 // if (deepest_match_pos != end) 554 // return &(*deepest_match_pos); 555 // } 556 // return NULL; 557 //} 558 // 559 bool 560 BlockList::SetInlinedFunctionInfo(user_id_t blockID, const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr) 561 { 562 Block *block = GetBlockByID(blockID); 563 564 if (block) 565 { 566 block->SetInlinedFunctionInfo(name, mangled, decl_ptr, call_decl_ptr); 567 return true; 568 } 569 return false; 570 } 571 572 VariableListSP 573 BlockList::GetVariableList(user_id_t blockID, bool get_child_variables, bool can_create) 574 { 575 VariableListSP variable_list_sp; 576 Block *block = GetBlockByID(blockID); 577 if (block) 578 variable_list_sp = block->GetVariableList(get_child_variables, can_create); 579 return variable_list_sp; 580 } 581 582 bool 583 BlockList::IsEmpty() const 584 { 585 return m_blocks.empty(); 586 } 587 588 589 590 bool 591 BlockList::SetVariableList(user_id_t blockID, VariableListSP& variables) 592 { 593 Block *block = GetBlockByID(blockID); 594 if (block) 595 { 596 block->SetVariableList(variables); 597 return true; 598 } 599 return false; 600 601 } 602 603 604 VariableListSP 605 Block::GetVariableList (bool get_child_variables, bool can_create) 606 { 607 VariableListSP variable_list_sp; 608 if (m_variables.get() == NULL && can_create) 609 { 610 SymbolContext sc; 611 CalculateSymbolContext(&sc); 612 assert(sc.module_sp); 613 sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); 614 } 615 616 if (m_variables.get()) 617 { 618 variable_list_sp.reset(new VariableList()); 619 if (variable_list_sp.get()) 620 variable_list_sp->AddVariables(m_variables.get()); 621 622 if (get_child_variables) 623 { 624 Block *child_block = GetFirstChild(); 625 while (child_block) 626 { 627 VariableListSP child_block_variable_list(child_block->GetVariableList(get_child_variables, can_create)); 628 if (child_block_variable_list.get()) 629 variable_list_sp->AddVariables(child_block_variable_list.get()); 630 child_block = child_block->GetSibling(); 631 } 632 } 633 } 634 635 return variable_list_sp; 636 } 637 638 uint32_t 639 Block::AppendVariables (bool can_create, bool get_parent_variables, VariableList *variable_list) 640 { 641 uint32_t num_variables_added = 0; 642 VariableListSP variable_list_sp(GetVariableList(false, can_create)); 643 644 if (variable_list_sp.get()) 645 { 646 num_variables_added = variable_list_sp->GetSize(); 647 variable_list->AddVariables(variable_list_sp.get()); 648 } 649 650 if (get_parent_variables) 651 { 652 Block* parent_block = GetParent(); 653 if (parent_block) 654 num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, variable_list); 655 } 656 return num_variables_added; 657 } 658 659 660 void 661 Block::SetVariableList(VariableListSP& variables) 662 { 663 m_variables = variables; 664 } 665 666 uint32_t 667 Block::Depth () const 668 { 669 return m_depth; 670 } 671 672