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