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.8x}", 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 Module * 162 Block::CalculateSymbolContextModule () 163 { 164 if (m_parent_scope) 165 return m_parent_scope->CalculateSymbolContextModule (); 166 return NULL; 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.8x}", 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 uint32_t 321 Block::GetRangeIndexContainingAddress (const Address& addr) 322 { 323 Function *function = CalculateSymbolContextFunction(); 324 if (function) 325 { 326 const AddressRange &func_range = function->GetAddressRange(); 327 if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) 328 { 329 const addr_t addr_offset = addr.GetOffset(); 330 const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); 331 if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize()) 332 { 333 addr_t offset = addr_offset - func_offset; 334 return m_ranges.FindEntryIndexThatContains (offset); 335 } 336 } 337 } 338 return UINT32_MAX; 339 } 340 341 bool 342 Block::GetRangeAtIndex (uint32_t range_idx, AddressRange &range) 343 { 344 if (range_idx < m_ranges.GetSize()) 345 { 346 Function *function = CalculateSymbolContextFunction(); 347 if (function) 348 { 349 const Range &vm_range = m_ranges.GetEntryRef(range_idx); 350 range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress(); 351 range.GetBaseAddress().Slide(vm_range.GetRangeBase ()); 352 range.SetByteSize (vm_range.GetByteSize()); 353 return true; 354 } 355 } 356 return false; 357 } 358 359 bool 360 Block::GetStartAddress (Address &addr) 361 { 362 if (m_ranges.IsEmpty()) 363 return false; 364 365 Function *function = CalculateSymbolContextFunction(); 366 if (function) 367 { 368 addr = function->GetAddressRange().GetBaseAddress(); 369 addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase ()); 370 return true; 371 } 372 return false; 373 } 374 375 void 376 Block::FinalizeRanges () 377 { 378 m_ranges.Sort(); 379 m_ranges.CombineConsecutiveRanges (); 380 } 381 382 void 383 Block::AddRange (const Range& range) 384 { 385 Block *parent_block = GetParent (); 386 if (parent_block && !parent_block->Contains(range)) 387 { 388 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS)); 389 if (log) 390 { 391 Module *module = m_parent_scope->CalculateSymbolContextModule(); 392 Function *function = m_parent_scope->CalculateSymbolContextFunction(); 393 const addr_t function_file_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress(); 394 const addr_t block_start_addr = function_file_addr + range.GetRangeBase (); 395 const addr_t block_end_addr = function_file_addr + range.GetRangeEnd (); 396 Type *func_type = function->GetType(); 397 398 const Declaration &func_decl = func_type->GetDeclaration(); 399 if (func_decl.GetLine()) 400 { 401 log->Printf ("warning: %s/%s:%u block {0x%8.8x} has range[%u] [0x%llx - 0x%llx) which is not contained in parent block {0x%8.8x} in function {0x%8.8x} from %s/%s", 402 func_decl.GetFile().GetDirectory().GetCString(), 403 func_decl.GetFile().GetFilename().GetCString(), 404 func_decl.GetLine(), 405 GetID(), 406 (uint32_t)m_ranges.GetSize(), 407 block_start_addr, 408 block_end_addr, 409 parent_block->GetID(), 410 function->GetID(), 411 module->GetFileSpec().GetDirectory().GetCString(), 412 module->GetFileSpec().GetFilename().GetCString()); 413 } 414 else 415 { 416 log->Printf ("warning: block {0x%8.8x} has range[%u] [0x%llx - 0x%llx) which is not contained in parent block {0x%8.8x} in function {0x%8.8x} from %s/%s", 417 GetID(), 418 (uint32_t)m_ranges.GetSize(), 419 block_start_addr, 420 block_end_addr, 421 parent_block->GetID(), 422 function->GetID(), 423 module->GetFileSpec().GetDirectory().GetCString(), 424 module->GetFileSpec().GetFilename().GetCString()); 425 } 426 } 427 parent_block->AddRange (range); 428 } 429 m_ranges.Append(range); 430 } 431 432 // Return the current number of bytes that this object occupies in memory 433 size_t 434 Block::MemorySize() const 435 { 436 size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range); 437 if (m_inlineInfoSP.get()) 438 mem_size += m_inlineInfoSP->MemorySize(); 439 if (m_variable_list_sp.get()) 440 mem_size += m_variable_list_sp->MemorySize(); 441 return mem_size; 442 443 } 444 445 void 446 Block::AddChild(const BlockSP &child_block_sp) 447 { 448 if (child_block_sp) 449 { 450 child_block_sp->SetParentScope (this); 451 m_children.push_back (child_block_sp); 452 } 453 } 454 455 void 456 Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr) 457 { 458 m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr)); 459 } 460 461 462 463 VariableListSP 464 Block::GetBlockVariableList (bool can_create) 465 { 466 if (m_parsed_block_variables == false) 467 { 468 if (m_variable_list_sp.get() == NULL && can_create) 469 { 470 m_parsed_block_variables = true; 471 SymbolContext sc; 472 CalculateSymbolContext(&sc); 473 assert(sc.module_sp); 474 sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); 475 } 476 } 477 return m_variable_list_sp; 478 } 479 480 uint32_t 481 Block::AppendBlockVariables (bool can_create, 482 bool get_child_block_variables, 483 bool stop_if_child_block_is_inlined_function, 484 VariableList *variable_list) 485 { 486 uint32_t num_variables_added = 0; 487 VariableList *block_var_list = GetBlockVariableList (can_create).get(); 488 if (block_var_list) 489 { 490 num_variables_added += block_var_list->GetSize(); 491 variable_list->AddVariables (block_var_list); 492 } 493 494 if (get_child_block_variables) 495 { 496 collection::const_iterator pos, end = m_children.end(); 497 for (pos = m_children.begin(); pos != end; ++pos) 498 { 499 Block *child_block = pos->get(); 500 if (stop_if_child_block_is_inlined_function == false || 501 child_block->GetInlinedFunctionInfo() == NULL) 502 { 503 num_variables_added += child_block->AppendBlockVariables (can_create, 504 get_child_block_variables, 505 stop_if_child_block_is_inlined_function, 506 variable_list); 507 } 508 } 509 } 510 return num_variables_added; 511 } 512 513 uint32_t 514 Block::AppendVariables 515 ( 516 bool can_create, 517 bool get_parent_variables, 518 bool stop_if_block_is_inlined_function, 519 VariableList *variable_list 520 ) 521 { 522 uint32_t num_variables_added = 0; 523 VariableListSP variable_list_sp(GetBlockVariableList(can_create)); 524 525 bool is_inlined_function = GetInlinedFunctionInfo() != NULL; 526 if (variable_list_sp.get()) 527 { 528 num_variables_added = variable_list_sp->GetSize(); 529 variable_list->AddVariables(variable_list_sp.get()); 530 } 531 532 if (get_parent_variables) 533 { 534 if (stop_if_block_is_inlined_function && is_inlined_function) 535 return num_variables_added; 536 537 Block* parent_block = GetParent(); 538 if (parent_block) 539 num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list); 540 } 541 return num_variables_added; 542 } 543 544 clang::DeclContext * 545 Block::GetClangDeclContextForInlinedFunction() 546 { 547 SymbolContext sc; 548 549 CalculateSymbolContext (&sc); 550 551 if (!sc.module_sp) 552 return NULL; 553 554 SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor(); 555 556 if (!sym_vendor) 557 return NULL; 558 559 SymbolFile *sym_file = sym_vendor->GetSymbolFile(); 560 561 if (!sym_file) 562 return NULL; 563 564 return sym_file->GetClangDeclContextForTypeUID (sc, m_uid); 565 } 566 567 void 568 Block::SetBlockInfoHasBeenParsed (bool b, bool set_children) 569 { 570 m_parsed_block_info = b; 571 if (set_children) 572 { 573 m_parsed_child_blocks = true; 574 collection::const_iterator pos, end = m_children.end(); 575 for (pos = m_children.begin(); pos != end; ++pos) 576 (*pos)->SetBlockInfoHasBeenParsed (b, true); 577 } 578 } 579 580 void 581 Block::SetDidParseVariables (bool b, bool set_children) 582 { 583 m_parsed_block_variables = b; 584 if (set_children) 585 { 586 collection::const_iterator pos, end = m_children.end(); 587 for (pos = m_children.begin(); pos != end; ++pos) 588 (*pos)->SetDidParseVariables (b, true); 589 } 590 } 591 592 593 Block * 594 Block::GetSibling() const 595 { 596 if (m_parent_scope) 597 { 598 Block *parent_block = GetParent(); 599 if (parent_block) 600 return parent_block->GetSiblingForChild (this); 601 } 602 return NULL; 603 } 604 // A parent of child blocks can be asked to find a sibling block given 605 // one of its child blocks 606 Block * 607 Block::GetSiblingForChild (const Block *child_block) const 608 { 609 if (!m_children.empty()) 610 { 611 collection::const_iterator pos, end = m_children.end(); 612 for (pos = m_children.begin(); pos != end; ++pos) 613 { 614 if (pos->get() == child_block) 615 { 616 if (++pos != end) 617 return pos->get(); 618 break; 619 } 620 } 621 } 622 return NULL; 623 } 624 625