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/Core/Log.h" 13 #include "lldb/Core/Module.h" 14 #include "lldb/Core/Section.h" 15 #include "lldb/Symbol/Function.h" 16 #include "lldb/Symbol/SymbolFile.h" 17 #include "lldb/Symbol/SymbolVendor.h" 18 #include "lldb/Symbol/VariableList.h" 19 20 using namespace lldb; 21 using namespace lldb_private; 22 23 Block::Block(lldb::user_id_t uid) : 24 UserID(uid), 25 m_parent_scope (nullptr), 26 m_children (), 27 m_ranges (), 28 m_inlineInfoSP (), 29 m_variable_list_sp (), 30 m_parsed_block_info (false), 31 m_parsed_block_variables (false), 32 m_parsed_child_blocks (false) 33 { 34 } 35 36 Block::~Block () 37 { 38 } 39 40 void 41 Block::GetDescription(Stream *s, Function *function, lldb::DescriptionLevel level, Target *target) const 42 { 43 *s << "id = " << ((const UserID&)*this); 44 45 size_t num_ranges = m_ranges.GetSize(); 46 if (num_ranges > 0) 47 { 48 49 addr_t base_addr = LLDB_INVALID_ADDRESS; 50 if (target) 51 base_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress(target); 52 if (base_addr == LLDB_INVALID_ADDRESS) 53 base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress(); 54 55 s->Printf(", range%s = ", num_ranges > 1 ? "s" : ""); 56 for (size_t i=0; i<num_ranges; ++i) 57 { 58 const Range &range = m_ranges.GetEntryRef(i); 59 s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4); 60 } 61 } 62 63 if (m_inlineInfoSP.get() != nullptr) 64 { 65 bool show_fullpaths = (level == eDescriptionLevelVerbose); 66 m_inlineInfoSP->Dump(s, show_fullpaths); 67 } 68 } 69 70 void 71 Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const 72 { 73 if (depth < 0) 74 { 75 Block *parent = GetParent(); 76 if (parent) 77 { 78 // We have a depth that is less than zero, print our parent blocks 79 // first 80 parent->Dump(s, base_addr, depth + 1, show_context); 81 } 82 } 83 84 s->Printf("%p: ", static_cast<const void*>(this)); 85 s->Indent(); 86 *s << "Block" << static_cast<const UserID&>(*this); 87 const Block* parent_block = GetParent(); 88 if (parent_block) 89 { 90 s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID()); 91 } 92 if (m_inlineInfoSP.get() != nullptr) 93 { 94 bool show_fullpaths = false; 95 m_inlineInfoSP->Dump(s, show_fullpaths); 96 } 97 98 if (!m_ranges.IsEmpty()) 99 { 100 *s << ", ranges ="; 101 102 size_t num_ranges = m_ranges.GetSize(); 103 for (size_t i=0; i<num_ranges; ++i) 104 { 105 const Range &range = m_ranges.GetEntryRef(i); 106 if (parent_block != nullptr && parent_block->Contains(range) == false) 107 *s << '!'; 108 else 109 *s << ' '; 110 s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4); 111 } 112 } 113 s->EOL(); 114 115 if (depth > 0) 116 { 117 s->IndentMore(); 118 119 if (m_variable_list_sp.get()) 120 { 121 m_variable_list_sp->Dump(s, show_context); 122 } 123 124 collection::const_iterator pos, end = m_children.end(); 125 for (pos = m_children.begin(); pos != end; ++pos) 126 (*pos)->Dump(s, base_addr, depth - 1, show_context); 127 128 s->IndentLess(); 129 } 130 131 } 132 133 134 Block * 135 Block::FindBlockByID (user_id_t block_id) 136 { 137 if (block_id == GetID()) 138 return this; 139 140 Block *matching_block = nullptr; 141 collection::const_iterator pos, end = m_children.end(); 142 for (pos = m_children.begin(); pos != end; ++pos) 143 { 144 matching_block = (*pos)->FindBlockByID (block_id); 145 if (matching_block) 146 break; 147 } 148 return matching_block; 149 } 150 151 void 152 Block::CalculateSymbolContext (SymbolContext* sc) 153 { 154 if (m_parent_scope) 155 m_parent_scope->CalculateSymbolContext(sc); 156 sc->block = this; 157 } 158 159 lldb::ModuleSP 160 Block::CalculateSymbolContextModule () 161 { 162 if (m_parent_scope) 163 return m_parent_scope->CalculateSymbolContextModule (); 164 return lldb::ModuleSP(); 165 } 166 167 CompileUnit * 168 Block::CalculateSymbolContextCompileUnit () 169 { 170 if (m_parent_scope) 171 return m_parent_scope->CalculateSymbolContextCompileUnit (); 172 return nullptr; 173 } 174 175 Function * 176 Block::CalculateSymbolContextFunction () 177 { 178 if (m_parent_scope) 179 return m_parent_scope->CalculateSymbolContextFunction (); 180 return nullptr; 181 } 182 183 Block * 184 Block::CalculateSymbolContextBlock () 185 { 186 return this; 187 } 188 189 void 190 Block::DumpSymbolContext(Stream *s) 191 { 192 Function *function = CalculateSymbolContextFunction(); 193 if (function) 194 function->DumpSymbolContext(s); 195 s->Printf(", Block{0x%8.8" PRIx64 "}", GetID()); 196 } 197 198 void 199 Block::DumpAddressRanges (Stream *s, lldb::addr_t base_addr) 200 { 201 if (!m_ranges.IsEmpty()) 202 { 203 size_t num_ranges = m_ranges.GetSize(); 204 for (size_t i=0; i<num_ranges; ++i) 205 { 206 const Range &range = m_ranges.GetEntryRef(i); 207 s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4); 208 } 209 } 210 } 211 212 bool 213 Block::Contains (addr_t range_offset) const 214 { 215 return m_ranges.FindEntryThatContains(range_offset) != nullptr; 216 } 217 218 bool 219 Block::Contains (const Block *block) const 220 { 221 if (this == block) 222 return false; // This block doesn't contain itself... 223 224 // Walk the parent chain for "block" and see if any if them match this block 225 const Block *block_parent; 226 for (block_parent = block->GetParent(); 227 block_parent != nullptr; 228 block_parent = block_parent->GetParent()) 229 { 230 if (this == block_parent) 231 return true; // One of the parents of "block" is this object! 232 } 233 return false; 234 } 235 236 bool 237 Block::Contains (const Range& range) const 238 { 239 return m_ranges.FindEntryThatContains (range) != nullptr; 240 } 241 242 Block * 243 Block::GetParent () const 244 { 245 if (m_parent_scope) 246 return m_parent_scope->CalculateSymbolContextBlock(); 247 return nullptr; 248 } 249 250 Block * 251 Block::GetContainingInlinedBlock () 252 { 253 if (GetInlinedFunctionInfo()) 254 return this; 255 return GetInlinedParent (); 256 } 257 258 Block * 259 Block::GetInlinedParent () 260 { 261 Block *parent_block = GetParent (); 262 if (parent_block) 263 { 264 if (parent_block->GetInlinedFunctionInfo()) 265 return parent_block; 266 else 267 return parent_block->GetInlinedParent(); 268 } 269 return nullptr; 270 } 271 272 273 bool 274 Block::GetRangeContainingOffset (const addr_t offset, Range &range) 275 { 276 const Range *range_ptr = m_ranges.FindEntryThatContains (offset); 277 if (range_ptr) 278 { 279 range = *range_ptr; 280 return true; 281 } 282 range.Clear(); 283 return false; 284 } 285 286 287 bool 288 Block::GetRangeContainingAddress (const Address& addr, AddressRange &range) 289 { 290 Function *function = CalculateSymbolContextFunction(); 291 if (function) 292 { 293 const AddressRange &func_range = function->GetAddressRange(); 294 if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) 295 { 296 const addr_t addr_offset = addr.GetOffset(); 297 const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); 298 if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize()) 299 { 300 addr_t offset = addr_offset - func_offset; 301 302 const Range *range_ptr = m_ranges.FindEntryThatContains (offset); 303 304 if (range_ptr) 305 { 306 range.GetBaseAddress() = func_range.GetBaseAddress(); 307 range.GetBaseAddress().SetOffset(func_offset + range_ptr->GetRangeBase()); 308 range.SetByteSize(range_ptr->GetByteSize()); 309 return true; 310 } 311 } 312 } 313 } 314 range.Clear(); 315 return false; 316 } 317 318 bool 319 Block::GetRangeContainingLoadAddress (lldb::addr_t load_addr, Target &target, AddressRange &range) 320 { 321 Address load_address; 322 load_address.SetLoadAddress(load_addr, &target); 323 AddressRange containing_range; 324 return GetRangeContainingAddress(load_address, containing_range); 325 } 326 327 328 uint32_t 329 Block::GetRangeIndexContainingAddress (const Address& addr) 330 { 331 Function *function = CalculateSymbolContextFunction(); 332 if (function) 333 { 334 const AddressRange &func_range = function->GetAddressRange(); 335 if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) 336 { 337 const addr_t addr_offset = addr.GetOffset(); 338 const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); 339 if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize()) 340 { 341 addr_t offset = addr_offset - func_offset; 342 return m_ranges.FindEntryIndexThatContains (offset); 343 } 344 } 345 } 346 return UINT32_MAX; 347 } 348 349 bool 350 Block::GetRangeAtIndex (uint32_t range_idx, AddressRange &range) 351 { 352 if (range_idx < m_ranges.GetSize()) 353 { 354 Function *function = CalculateSymbolContextFunction(); 355 if (function) 356 { 357 const Range &vm_range = m_ranges.GetEntryRef(range_idx); 358 range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress(); 359 range.GetBaseAddress().Slide(vm_range.GetRangeBase ()); 360 range.SetByteSize (vm_range.GetByteSize()); 361 return true; 362 } 363 } 364 return false; 365 } 366 367 bool 368 Block::GetStartAddress (Address &addr) 369 { 370 if (m_ranges.IsEmpty()) 371 return false; 372 373 Function *function = CalculateSymbolContextFunction(); 374 if (function) 375 { 376 addr = function->GetAddressRange().GetBaseAddress(); 377 addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase ()); 378 return true; 379 } 380 return false; 381 } 382 383 void 384 Block::FinalizeRanges () 385 { 386 m_ranges.Sort(); 387 m_ranges.CombineConsecutiveRanges (); 388 } 389 390 void 391 Block::AddRange (const Range& range) 392 { 393 Block *parent_block = GetParent (); 394 if (parent_block && !parent_block->Contains(range)) 395 { 396 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS)); 397 if (log) 398 { 399 ModuleSP module_sp (m_parent_scope->CalculateSymbolContextModule()); 400 Function *function = m_parent_scope->CalculateSymbolContextFunction(); 401 const addr_t function_file_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress(); 402 const addr_t block_start_addr = function_file_addr + range.GetRangeBase (); 403 const addr_t block_end_addr = function_file_addr + range.GetRangeEnd (); 404 Type *func_type = function->GetType(); 405 406 const Declaration &func_decl = func_type->GetDeclaration(); 407 if (func_decl.GetLine()) 408 { 409 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", 410 func_decl.GetFile().GetPath().c_str(), 411 func_decl.GetLine(), 412 GetID(), 413 (uint32_t)m_ranges.GetSize(), 414 block_start_addr, 415 block_end_addr, 416 parent_block->GetID(), 417 function->GetID(), 418 module_sp->GetFileSpec().GetPath().c_str()); 419 } 420 else 421 { 422 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", 423 GetID(), 424 (uint32_t)m_ranges.GetSize(), 425 block_start_addr, 426 block_end_addr, 427 parent_block->GetID(), 428 function->GetID(), 429 module_sp->GetFileSpec().GetPath().c_str()); 430 } 431 } 432 parent_block->AddRange (range); 433 } 434 m_ranges.Append(range); 435 } 436 437 // Return the current number of bytes that this object occupies in memory 438 size_t 439 Block::MemorySize() const 440 { 441 size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range); 442 if (m_inlineInfoSP.get()) 443 mem_size += m_inlineInfoSP->MemorySize(); 444 if (m_variable_list_sp.get()) 445 mem_size += m_variable_list_sp->MemorySize(); 446 return mem_size; 447 448 } 449 450 void 451 Block::AddChild(const BlockSP &child_block_sp) 452 { 453 if (child_block_sp) 454 { 455 child_block_sp->SetParentScope (this); 456 m_children.push_back (child_block_sp); 457 } 458 } 459 460 void 461 Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr) 462 { 463 m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr)); 464 } 465 466 467 468 VariableListSP 469 Block::GetBlockVariableList (bool can_create) 470 { 471 if (m_parsed_block_variables == false) 472 { 473 if (m_variable_list_sp.get() == nullptr && can_create) 474 { 475 m_parsed_block_variables = true; 476 SymbolContext sc; 477 CalculateSymbolContext(&sc); 478 assert(sc.module_sp); 479 sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); 480 } 481 } 482 return m_variable_list_sp; 483 } 484 485 uint32_t 486 Block::AppendBlockVariables (bool can_create, 487 bool get_child_block_variables, 488 bool stop_if_child_block_is_inlined_function, 489 VariableList *variable_list) 490 { 491 uint32_t num_variables_added = 0; 492 VariableList *block_var_list = GetBlockVariableList (can_create).get(); 493 if (block_var_list) 494 { 495 num_variables_added += block_var_list->GetSize(); 496 variable_list->AddVariables (block_var_list); 497 } 498 499 if (get_child_block_variables) 500 { 501 collection::const_iterator pos, end = m_children.end(); 502 for (pos = m_children.begin(); pos != end; ++pos) 503 { 504 Block *child_block = pos->get(); 505 if (stop_if_child_block_is_inlined_function == false || 506 child_block->GetInlinedFunctionInfo() == nullptr) 507 { 508 num_variables_added += child_block->AppendBlockVariables (can_create, 509 get_child_block_variables, 510 stop_if_child_block_is_inlined_function, 511 variable_list); 512 } 513 } 514 } 515 return num_variables_added; 516 } 517 518 uint32_t 519 Block::AppendVariables 520 ( 521 bool can_create, 522 bool get_parent_variables, 523 bool stop_if_block_is_inlined_function, 524 VariableList *variable_list 525 ) 526 { 527 uint32_t num_variables_added = 0; 528 VariableListSP variable_list_sp(GetBlockVariableList(can_create)); 529 530 bool is_inlined_function = GetInlinedFunctionInfo() != nullptr; 531 if (variable_list_sp.get()) 532 { 533 num_variables_added = variable_list_sp->GetSize(); 534 variable_list->AddVariables(variable_list_sp.get()); 535 } 536 537 if (get_parent_variables) 538 { 539 if (stop_if_block_is_inlined_function && is_inlined_function) 540 return num_variables_added; 541 542 Block* parent_block = GetParent(); 543 if (parent_block) 544 num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list); 545 } 546 return num_variables_added; 547 } 548 549 CompilerDeclContext 550 Block::GetDeclContext() 551 { 552 ModuleSP module_sp = CalculateSymbolContextModule (); 553 554 if (module_sp) 555 { 556 SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); 557 558 if (sym_vendor) 559 { 560 SymbolFile *sym_file = sym_vendor->GetSymbolFile(); 561 562 if (sym_file) 563 return sym_file->GetDeclContextForUID (GetID()); 564 } 565 } 566 return CompilerDeclContext(); 567 } 568 569 void 570 Block::SetBlockInfoHasBeenParsed (bool b, bool set_children) 571 { 572 m_parsed_block_info = b; 573 if (set_children) 574 { 575 m_parsed_child_blocks = true; 576 collection::const_iterator pos, end = m_children.end(); 577 for (pos = m_children.begin(); pos != end; ++pos) 578 (*pos)->SetBlockInfoHasBeenParsed (b, true); 579 } 580 } 581 582 void 583 Block::SetDidParseVariables (bool b, bool set_children) 584 { 585 m_parsed_block_variables = b; 586 if (set_children) 587 { 588 collection::const_iterator pos, end = m_children.end(); 589 for (pos = m_children.begin(); pos != end; ++pos) 590 (*pos)->SetDidParseVariables (b, true); 591 } 592 } 593 594 595 Block * 596 Block::GetSibling() const 597 { 598 if (m_parent_scope) 599 { 600 Block *parent_block = GetParent(); 601 if (parent_block) 602 return parent_block->GetSiblingForChild (this); 603 } 604 return nullptr; 605 } 606 // A parent of child blocks can be asked to find a sibling block given 607 // one of its child blocks 608 Block * 609 Block::GetSiblingForChild (const Block *child_block) const 610 { 611 if (!m_children.empty()) 612 { 613 collection::const_iterator pos, end = m_children.end(); 614 for (pos = m_children.begin(); pos != end; ++pos) 615 { 616 if (pos->get() == child_block) 617 { 618 if (++pos != end) 619 return pos->get(); 620 break; 621 } 622 } 623 } 624 return nullptr; 625 } 626 627