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