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