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 LogSP 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/%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/%s", 412 func_decl.GetFile().GetDirectory().GetCString(), 413 func_decl.GetFile().GetFilename().GetCString(), 414 func_decl.GetLine(), 415 GetID(), 416 (uint32_t)m_ranges.GetSize(), 417 block_start_addr, 418 block_end_addr, 419 parent_block->GetID(), 420 function->GetID(), 421 module_sp->GetFileSpec().GetDirectory().GetCString(), 422 module_sp->GetFileSpec().GetFilename().GetCString()); 423 } 424 else 425 { 426 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/%s", 427 GetID(), 428 (uint32_t)m_ranges.GetSize(), 429 block_start_addr, 430 block_end_addr, 431 parent_block->GetID(), 432 function->GetID(), 433 module_sp->GetFileSpec().GetDirectory().GetCString(), 434 module_sp->GetFileSpec().GetFilename().GetCString()); 435 } 436 } 437 parent_block->AddRange (range); 438 } 439 m_ranges.Append(range); 440 } 441 442 // Return the current number of bytes that this object occupies in memory 443 size_t 444 Block::MemorySize() const 445 { 446 size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range); 447 if (m_inlineInfoSP.get()) 448 mem_size += m_inlineInfoSP->MemorySize(); 449 if (m_variable_list_sp.get()) 450 mem_size += m_variable_list_sp->MemorySize(); 451 return mem_size; 452 453 } 454 455 void 456 Block::AddChild(const BlockSP &child_block_sp) 457 { 458 if (child_block_sp) 459 { 460 child_block_sp->SetParentScope (this); 461 m_children.push_back (child_block_sp); 462 } 463 } 464 465 void 466 Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr) 467 { 468 m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr)); 469 } 470 471 472 473 VariableListSP 474 Block::GetBlockVariableList (bool can_create) 475 { 476 if (m_parsed_block_variables == false) 477 { 478 if (m_variable_list_sp.get() == NULL && can_create) 479 { 480 m_parsed_block_variables = true; 481 SymbolContext sc; 482 CalculateSymbolContext(&sc); 483 assert(sc.module_sp); 484 sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); 485 } 486 } 487 return m_variable_list_sp; 488 } 489 490 uint32_t 491 Block::AppendBlockVariables (bool can_create, 492 bool get_child_block_variables, 493 bool stop_if_child_block_is_inlined_function, 494 VariableList *variable_list) 495 { 496 uint32_t num_variables_added = 0; 497 VariableList *block_var_list = GetBlockVariableList (can_create).get(); 498 if (block_var_list) 499 { 500 num_variables_added += block_var_list->GetSize(); 501 variable_list->AddVariables (block_var_list); 502 } 503 504 if (get_child_block_variables) 505 { 506 collection::const_iterator pos, end = m_children.end(); 507 for (pos = m_children.begin(); pos != end; ++pos) 508 { 509 Block *child_block = pos->get(); 510 if (stop_if_child_block_is_inlined_function == false || 511 child_block->GetInlinedFunctionInfo() == NULL) 512 { 513 num_variables_added += child_block->AppendBlockVariables (can_create, 514 get_child_block_variables, 515 stop_if_child_block_is_inlined_function, 516 variable_list); 517 } 518 } 519 } 520 return num_variables_added; 521 } 522 523 uint32_t 524 Block::AppendVariables 525 ( 526 bool can_create, 527 bool get_parent_variables, 528 bool stop_if_block_is_inlined_function, 529 VariableList *variable_list 530 ) 531 { 532 uint32_t num_variables_added = 0; 533 VariableListSP variable_list_sp(GetBlockVariableList(can_create)); 534 535 bool is_inlined_function = GetInlinedFunctionInfo() != NULL; 536 if (variable_list_sp.get()) 537 { 538 num_variables_added = variable_list_sp->GetSize(); 539 variable_list->AddVariables(variable_list_sp.get()); 540 } 541 542 if (get_parent_variables) 543 { 544 if (stop_if_block_is_inlined_function && is_inlined_function) 545 return num_variables_added; 546 547 Block* parent_block = GetParent(); 548 if (parent_block) 549 num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list); 550 } 551 return num_variables_added; 552 } 553 554 clang::DeclContext * 555 Block::GetClangDeclContext() 556 { 557 SymbolContext sc; 558 559 CalculateSymbolContext (&sc); 560 561 if (!sc.module_sp) 562 return NULL; 563 564 SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor(); 565 566 if (!sym_vendor) 567 return NULL; 568 569 SymbolFile *sym_file = sym_vendor->GetSymbolFile(); 570 571 if (!sym_file) 572 return NULL; 573 574 return sym_file->GetClangDeclContextForTypeUID (sc, m_uid); 575 } 576 577 void 578 Block::SetBlockInfoHasBeenParsed (bool b, bool set_children) 579 { 580 m_parsed_block_info = b; 581 if (set_children) 582 { 583 m_parsed_child_blocks = true; 584 collection::const_iterator pos, end = m_children.end(); 585 for (pos = m_children.begin(); pos != end; ++pos) 586 (*pos)->SetBlockInfoHasBeenParsed (b, true); 587 } 588 } 589 590 void 591 Block::SetDidParseVariables (bool b, bool set_children) 592 { 593 m_parsed_block_variables = b; 594 if (set_children) 595 { 596 collection::const_iterator pos, end = m_children.end(); 597 for (pos = m_children.begin(); pos != end; ++pos) 598 (*pos)->SetDidParseVariables (b, true); 599 } 600 } 601 602 603 Block * 604 Block::GetSibling() const 605 { 606 if (m_parent_scope) 607 { 608 Block *parent_block = GetParent(); 609 if (parent_block) 610 return parent_block->GetSiblingForChild (this); 611 } 612 return NULL; 613 } 614 // A parent of child blocks can be asked to find a sibling block given 615 // one of its child blocks 616 Block * 617 Block::GetSiblingForChild (const Block *child_block) const 618 { 619 if (!m_children.empty()) 620 { 621 collection::const_iterator pos, end = m_children.end(); 622 for (pos = m_children.begin(); pos != end; ++pos) 623 { 624 if (pos->get() == child_block) 625 { 626 if (++pos != end) 627 return pos->get(); 628 break; 629 } 630 } 631 } 632 return NULL; 633 } 634 635