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