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