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