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 void 156 Block::DumpStopContext 157 ( 158 Stream *s, 159 const SymbolContext *sc_ptr, 160 const Declaration *child_inline_call_site, 161 bool show_fullpaths, 162 bool show_inline_blocks) 163 { 164 const InlineFunctionInfo* inline_info = NULL; 165 Block* inlined_block; 166 if (sc_ptr) 167 inlined_block = GetContainingInlinedBlock (); 168 else 169 inlined_block = GetInlinedParent(); 170 171 if (inlined_block) 172 inline_info = inlined_block->GetInlinedFunctionInfo(); 173 const Declaration *inline_call_site = child_inline_call_site; 174 if (inline_info) 175 { 176 inline_call_site = &inline_info->GetCallSite(); 177 if (sc_ptr) 178 { 179 // First frame in a frame with inlined functions 180 s->PutCString (" [inlined]"); 181 } 182 if (show_inline_blocks && child_inline_call_site) 183 s->EOL(); 184 else 185 s->PutChar(' '); 186 187 if (sc_ptr == NULL) 188 s->Indent(); 189 190 s->PutCString(inline_info->GetName ().AsCString()); 191 192 if (child_inline_call_site && child_inline_call_site->IsValid()) 193 { 194 s->PutCString(" at "); 195 child_inline_call_site->DumpStopContext (s, show_fullpaths); 196 } 197 } 198 199 // The first call to this function from something that has a symbol 200 // context will pass in a valid sc_ptr. Subsequent calls to this function 201 // from this function for inline purposes will NULL out sc_ptr. So on the 202 // first time through we dump the line table entry (which is always at the 203 // deepest inline code block). And subsequent calls to this function we 204 // will use hte inline call site information to print line numbers. 205 if (sc_ptr) 206 { 207 // If we have any inlined functions, this will be the deepest most 208 // inlined location 209 if (sc_ptr->line_entry.IsValid()) 210 { 211 s->PutCString(" at "); 212 sc_ptr->line_entry.DumpStopContext (s, show_fullpaths); 213 } 214 } 215 216 if (show_inline_blocks) 217 { 218 if (inlined_block) 219 { 220 inlined_block->Block::DumpStopContext (s, 221 NULL, 222 inline_call_site, 223 show_fullpaths, 224 show_inline_blocks); 225 } 226 else if (child_inline_call_site) 227 { 228 SymbolContext sc; 229 CalculateSymbolContext(&sc); 230 if (sc.function) 231 { 232 s->EOL(); 233 s->Indent (sc.function->GetMangled().GetName().AsCString()); 234 if (child_inline_call_site && child_inline_call_site->IsValid()) 235 { 236 s->PutCString(" at "); 237 child_inline_call_site->DumpStopContext (s, show_fullpaths); 238 } 239 } 240 } 241 } 242 } 243 244 245 void 246 Block::DumpSymbolContext(Stream *s) 247 { 248 SymbolContext sc; 249 CalculateSymbolContext(&sc); 250 if (sc.function) 251 sc.function->DumpSymbolContext(s); 252 s->Printf(", Block{0x%8.8x}", GetID()); 253 } 254 255 void 256 Block::DumpAddressRanges (Stream *s, lldb::addr_t base_addr) 257 { 258 if (!m_ranges.empty()) 259 { 260 std::vector<VMRange>::const_iterator pos, end = m_ranges.end(); 261 for (pos = m_ranges.begin(); pos != end; ++pos) 262 pos->Dump (s, base_addr); 263 } 264 } 265 266 bool 267 Block::Contains (addr_t range_offset) const 268 { 269 return VMRange::ContainsValue(m_ranges, range_offset); 270 } 271 272 bool 273 Block::Contains (const Block *block) const 274 { 275 if (this == block) 276 return false; // This block doesn't contain itself... 277 278 // Walk the parent chain for "block" and see if any if them match this block 279 const Block *block_parent; 280 for (block_parent = block->GetParent(); 281 block_parent != NULL; 282 block_parent = block_parent->GetParent()) 283 { 284 if (this == block_parent) 285 return true; // One of the parents of "block" is this object! 286 } 287 return false; 288 } 289 290 bool 291 Block::Contains (const VMRange& range) const 292 { 293 return VMRange::ContainsRange(m_ranges, range); 294 } 295 296 Block * 297 Block::GetParent () const 298 { 299 if (m_parent_scope) 300 { 301 SymbolContext sc; 302 m_parent_scope->CalculateSymbolContext(&sc); 303 if (sc.block) 304 return sc.block; 305 } 306 return NULL; 307 } 308 309 Block * 310 Block::GetContainingInlinedBlock () 311 { 312 if (GetInlinedFunctionInfo()) 313 return this; 314 return GetInlinedParent (); 315 } 316 317 Block * 318 Block::GetInlinedParent () 319 { 320 Block *parent_block = GetParent (); 321 if (parent_block) 322 { 323 if (parent_block->GetInlinedFunctionInfo()) 324 return parent_block; 325 else 326 return parent_block->GetInlinedParent(); 327 } 328 return NULL; 329 } 330 331 332 bool 333 Block::GetRangeContainingOffset (const addr_t offset, VMRange &range) 334 { 335 uint32_t range_idx = VMRange::FindRangeIndexThatContainsValue (m_ranges, offset); 336 if (range_idx < m_ranges.size()) 337 { 338 range = m_ranges[range_idx]; 339 return true; 340 } 341 range.Clear(); 342 return false; 343 } 344 345 346 bool 347 Block::GetRangeContainingAddress (const Address& addr, AddressRange &range) 348 { 349 SymbolContext sc; 350 CalculateSymbolContext(&sc); 351 if (sc.function) 352 { 353 const AddressRange &func_range = sc.function->GetAddressRange(); 354 if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) 355 { 356 const addr_t addr_offset = addr.GetOffset(); 357 const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); 358 if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize()) 359 { 360 addr_t offset = addr_offset - func_offset; 361 362 uint32_t range_idx = VMRange::FindRangeIndexThatContainsValue (m_ranges, offset); 363 if (range_idx < m_ranges.size()) 364 { 365 range.GetBaseAddress() = func_range.GetBaseAddress(); 366 range.GetBaseAddress().SetOffset(func_offset + m_ranges[range_idx].GetBaseAddress()); 367 range.SetByteSize(m_ranges[range_idx].GetByteSize()); 368 return true; 369 } 370 } 371 } 372 } 373 range.Clear(); 374 return false; 375 } 376 377 bool 378 Block::GetRangeAtIndex (uint32_t range_idx, AddressRange &range) 379 { 380 if (range_idx < m_ranges.size()) 381 { 382 SymbolContext sc; 383 CalculateSymbolContext(&sc); 384 if (sc.function) 385 { 386 range.GetBaseAddress() = sc.function->GetAddressRange().GetBaseAddress(); 387 range.GetBaseAddress().Slide(m_ranges[range_idx].GetBaseAddress ()); 388 range.SetByteSize (m_ranges[range_idx].GetByteSize()); 389 return true; 390 } 391 } 392 return false; 393 } 394 395 bool 396 Block::GetStartAddress (Address &addr) 397 { 398 if (m_ranges.empty()) 399 return false; 400 401 SymbolContext sc; 402 CalculateSymbolContext(&sc); 403 if (sc.function) 404 { 405 addr = sc.function->GetAddressRange().GetBaseAddress(); 406 addr.Slide(m_ranges.front().GetBaseAddress ()); 407 return true; 408 } 409 return false; 410 } 411 412 void 413 Block::AddRange(addr_t start_offset, addr_t end_offset) 414 { 415 m_ranges.resize(m_ranges.size()+1); 416 m_ranges.back().Reset(start_offset, end_offset); 417 } 418 419 // Return the current number of bytes that this object occupies in memory 420 size_t 421 Block::MemorySize() const 422 { 423 size_t mem_size = sizeof(Block) + m_ranges.size() * sizeof(VMRange); 424 if (m_inlineInfoSP.get()) 425 mem_size += m_inlineInfoSP->MemorySize(); 426 if (m_variable_list_sp.get()) 427 mem_size += m_variable_list_sp->MemorySize(); 428 return mem_size; 429 430 } 431 432 void 433 Block::AddChild(const BlockSP &child_block_sp) 434 { 435 if (child_block_sp) 436 { 437 Block *block_needs_sibling = NULL; 438 439 if (!m_children.empty()) 440 block_needs_sibling = m_children.back().get(); 441 442 child_block_sp->SetParentScope (this); 443 m_children.push_back (child_block_sp); 444 445 if (block_needs_sibling) 446 block_needs_sibling->SetSibling (child_block_sp.get()); 447 } 448 } 449 450 void 451 Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr) 452 { 453 m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr)); 454 } 455 456 457 458 VariableListSP 459 Block::GetBlockVariableList (bool can_create) 460 { 461 if (m_parsed_block_variables == false) 462 { 463 if (m_variable_list_sp.get() == NULL && can_create) 464 { 465 m_parsed_block_variables = true; 466 SymbolContext sc; 467 CalculateSymbolContext(&sc); 468 assert(sc.module_sp); 469 sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); 470 } 471 } 472 return m_variable_list_sp; 473 } 474 475 uint32_t 476 Block::AppendBlockVariables (bool can_create, 477 bool get_child_block_variables, 478 bool stop_if_child_block_is_inlined_function, 479 VariableList *variable_list) 480 { 481 uint32_t num_variables_added = 0; 482 VariableList *block_var_list = GetBlockVariableList (can_create).get(); 483 if (block_var_list) 484 { 485 num_variables_added += block_var_list->GetSize(); 486 variable_list->AddVariables (block_var_list); 487 } 488 489 if (get_child_block_variables) 490 { 491 for (Block *child_block = GetFirstChild(); 492 child_block != NULL; 493 child_block = child_block->GetSibling()) 494 { 495 if (stop_if_child_block_is_inlined_function == false || 496 child_block->GetInlinedFunctionInfo() == NULL) 497 { 498 num_variables_added += child_block->AppendBlockVariables (can_create, 499 get_child_block_variables, 500 stop_if_child_block_is_inlined_function, 501 variable_list); 502 } 503 } 504 } 505 return num_variables_added; 506 } 507 508 uint32_t 509 Block::AppendVariables 510 ( 511 bool can_create, 512 bool get_parent_variables, 513 bool stop_if_block_is_inlined_function, 514 VariableList *variable_list 515 ) 516 { 517 uint32_t num_variables_added = 0; 518 VariableListSP variable_list_sp(GetBlockVariableList(can_create)); 519 520 bool is_inlined_function = GetInlinedFunctionInfo() != NULL; 521 if (variable_list_sp.get()) 522 { 523 num_variables_added = variable_list_sp->GetSize(); 524 variable_list->AddVariables(variable_list_sp.get()); 525 } 526 527 if (get_parent_variables) 528 { 529 if (stop_if_block_is_inlined_function && is_inlined_function) 530 return num_variables_added; 531 532 Block* parent_block = GetParent(); 533 if (parent_block) 534 num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list); 535 } 536 return num_variables_added; 537 } 538 539 clang::DeclContext * 540 Block::GetClangDeclContextForInlinedFunction() 541 { 542 SymbolContext sc; 543 544 CalculateSymbolContext (&sc); 545 546 if (!sc.module_sp) 547 return NULL; 548 549 SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor(); 550 551 if (!sym_vendor) 552 return NULL; 553 554 SymbolFile *sym_file = sym_vendor->GetSymbolFile(); 555 556 if (!sym_file) 557 return NULL; 558 559 return sym_file->GetClangDeclContextForTypeUID (sc, m_uid); 560 } 561 562 void 563 Block::SetBlockInfoHasBeenParsed (bool b, bool set_children) 564 { 565 m_parsed_block_info = b; 566 if (set_children) 567 { 568 m_parsed_child_blocks = true; 569 for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling()) 570 child_block->SetBlockInfoHasBeenParsed (b, true); 571 } 572 } 573 574 void 575 Block::SetDidParseVariables (bool b, bool set_children) 576 { 577 m_parsed_block_variables = b; 578 if (set_children) 579 { 580 for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling()) 581 child_block->SetDidParseVariables (b, true); 582 } 583 } 584 585