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 void 362 Block::AddRange(addr_t start_offset, addr_t end_offset) 363 { 364 m_ranges.resize(m_ranges.size()+1); 365 m_ranges.back().Reset(start_offset, end_offset); 366 } 367 368 // Return the current number of bytes that this object occupies in memory 369 size_t 370 Block::MemorySize() const 371 { 372 size_t mem_size = sizeof(Block) + m_ranges.size() * sizeof(VMRange); 373 if (m_inlineInfoSP.get()) 374 mem_size += m_inlineInfoSP->MemorySize(); 375 if (m_variable_list_sp.get()) 376 mem_size += m_variable_list_sp->MemorySize(); 377 return mem_size; 378 379 } 380 381 void 382 Block::AddChild(const BlockSP &child_block_sp) 383 { 384 if (child_block_sp) 385 { 386 Block *block_needs_sibling = NULL; 387 388 if (!m_children.empty()) 389 block_needs_sibling = m_children.back().get(); 390 391 child_block_sp->SetParentScope (this); 392 m_children.push_back (child_block_sp); 393 394 if (block_needs_sibling) 395 block_needs_sibling->SetSibling (child_block_sp.get()); 396 } 397 } 398 399 void 400 Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr) 401 { 402 m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr)); 403 } 404 405 406 407 VariableListSP 408 Block::GetVariableList (bool get_child_variables, bool can_create) 409 { 410 VariableListSP variable_list_sp; 411 if (m_parsed_block_variables == false) 412 { 413 if (m_variable_list_sp.get() == NULL && can_create) 414 { 415 m_parsed_block_variables = true; 416 SymbolContext sc; 417 CalculateSymbolContext(&sc); 418 assert(sc.module_sp); 419 sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); 420 } 421 } 422 423 if (m_variable_list_sp.get()) 424 { 425 variable_list_sp.reset(new VariableList()); 426 if (variable_list_sp.get()) 427 variable_list_sp->AddVariables(m_variable_list_sp.get()); 428 429 if (get_child_variables) 430 { 431 for (Block *child_block = GetFirstChild(); 432 child_block != NULL; 433 child_block = child_block->GetSibling()) 434 { 435 if (child_block->GetInlinedFunctionInfo() == NULL) 436 { 437 VariableListSP child_block_variable_list(child_block->GetVariableList(get_child_variables, can_create)); 438 if (child_block_variable_list.get()) 439 variable_list_sp->AddVariables(child_block_variable_list.get()); 440 } 441 442 } 443 } 444 } 445 446 return variable_list_sp; 447 } 448 449 uint32_t 450 Block::AppendVariables 451 ( 452 bool can_create, 453 bool get_parent_variables, 454 bool stop_if_block_is_inlined_function, 455 VariableList *variable_list 456 ) 457 { 458 uint32_t num_variables_added = 0; 459 VariableListSP variable_list_sp(GetVariableList(false, can_create)); 460 461 bool is_inlined_function = GetInlinedFunctionInfo() != NULL; 462 if (variable_list_sp.get()) 463 { 464 num_variables_added = variable_list_sp->GetSize(); 465 variable_list->AddVariables(variable_list_sp.get()); 466 } 467 468 if (get_parent_variables) 469 { 470 if (stop_if_block_is_inlined_function && is_inlined_function) 471 return num_variables_added; 472 473 Block* parent_block = GetParent(); 474 if (parent_block) 475 num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list); 476 } 477 return num_variables_added; 478 } 479 480 void 481 Block::SetBlockInfoHasBeenParsed (bool b, bool set_children) 482 { 483 m_parsed_block_info = b; 484 if (set_children) 485 { 486 m_parsed_child_blocks = true; 487 for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling()) 488 child_block->SetBlockInfoHasBeenParsed (b, true); 489 } 490 } 491