1 //===-- StackFrame.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 // C Includes 11 // C++ Includes 12 // Other libraries and framework includes 13 // Project includes 14 #include "lldb/Target/StackFrame.h" 15 #include "lldb/Core/Debugger.h" 16 #include "lldb/Core/Disassembler.h" 17 #include "lldb/Core/FormatEntity.h" 18 #include "lldb/Core/Mangled.h" 19 #include "lldb/Core/Module.h" 20 #include "lldb/Core/Value.h" 21 #include "lldb/Core/ValueObjectConstResult.h" 22 #include "lldb/Core/ValueObjectMemory.h" 23 #include "lldb/Core/ValueObjectVariable.h" 24 #include "lldb/Symbol/CompileUnit.h" 25 #include "lldb/Symbol/Function.h" 26 #include "lldb/Symbol/Symbol.h" 27 #include "lldb/Symbol/SymbolContextScope.h" 28 #include "lldb/Symbol/Type.h" 29 #include "lldb/Symbol/VariableList.h" 30 #include "lldb/Target/ABI.h" 31 #include "lldb/Target/ExecutionContext.h" 32 #include "lldb/Target/Process.h" 33 #include "lldb/Target/RegisterContext.h" 34 #include "lldb/Target/Target.h" 35 #include "lldb/Target/Thread.h" 36 37 using namespace lldb; 38 using namespace lldb_private; 39 40 // The first bits in the flags are reserved for the SymbolContext::Scope bits 41 // so we know if we have tried to look up information in our internal symbol 42 // context (m_sc) already. 43 #define RESOLVED_FRAME_CODE_ADDR (uint32_t(eSymbolContextEverything + 1)) 44 #define RESOLVED_FRAME_ID_SYMBOL_SCOPE (RESOLVED_FRAME_CODE_ADDR << 1) 45 #define GOT_FRAME_BASE (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1) 46 #define RESOLVED_VARIABLES (GOT_FRAME_BASE << 1) 47 #define RESOLVED_GLOBAL_VARIABLES (RESOLVED_VARIABLES << 1) 48 49 StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 50 user_id_t unwind_frame_index, addr_t cfa, 51 bool cfa_is_valid, addr_t pc, uint32_t stop_id, 52 bool stop_id_is_valid, bool is_history_frame, 53 const SymbolContext *sc_ptr) 54 : m_thread_wp(thread_sp), m_frame_index(frame_idx), 55 m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(), 56 m_id(pc, cfa, nullptr), m_frame_code_addr(pc), m_sc(), m_flags(), 57 m_frame_base(), m_frame_base_error(), m_cfa_is_valid(cfa_is_valid), 58 m_stop_id(stop_id), m_stop_id_is_valid(stop_id_is_valid), 59 m_is_history_frame(is_history_frame), m_variable_list_sp(), 60 m_variable_list_value_objects(), m_disassembly(), m_mutex() { 61 // If we don't have a CFA value, use the frame index for our StackID so that 62 // recursive 63 // functions properly aren't confused with one another on a history stack. 64 if (m_is_history_frame && !m_cfa_is_valid) { 65 m_id.SetCFA(m_frame_index); 66 } 67 68 if (sc_ptr != nullptr) { 69 m_sc = *sc_ptr; 70 m_flags.Set(m_sc.GetResolvedMask()); 71 } 72 } 73 74 StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 75 user_id_t unwind_frame_index, 76 const RegisterContextSP ®_context_sp, addr_t cfa, 77 addr_t pc, const SymbolContext *sc_ptr) 78 : m_thread_wp(thread_sp), m_frame_index(frame_idx), 79 m_concrete_frame_index(unwind_frame_index), 80 m_reg_context_sp(reg_context_sp), m_id(pc, cfa, nullptr), 81 m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(), 82 m_frame_base_error(), m_cfa_is_valid(true), m_stop_id(0), 83 m_stop_id_is_valid(false), m_is_history_frame(false), 84 m_variable_list_sp(), m_variable_list_value_objects(), m_disassembly(), 85 m_mutex() { 86 if (sc_ptr != nullptr) { 87 m_sc = *sc_ptr; 88 m_flags.Set(m_sc.GetResolvedMask()); 89 } 90 91 if (reg_context_sp && !m_sc.target_sp) { 92 m_sc.target_sp = reg_context_sp->CalculateTarget(); 93 if (m_sc.target_sp) 94 m_flags.Set(eSymbolContextTarget); 95 } 96 } 97 98 StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, 99 user_id_t unwind_frame_index, 100 const RegisterContextSP ®_context_sp, addr_t cfa, 101 const Address &pc_addr, const SymbolContext *sc_ptr) 102 : m_thread_wp(thread_sp), m_frame_index(frame_idx), 103 m_concrete_frame_index(unwind_frame_index), 104 m_reg_context_sp(reg_context_sp), 105 m_id(pc_addr.GetLoadAddress(thread_sp->CalculateTarget().get()), cfa, 106 nullptr), 107 m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(), 108 m_frame_base_error(), m_cfa_is_valid(true), m_stop_id(0), 109 m_stop_id_is_valid(false), m_is_history_frame(false), 110 m_variable_list_sp(), m_variable_list_value_objects(), m_disassembly(), 111 m_mutex() { 112 if (sc_ptr != nullptr) { 113 m_sc = *sc_ptr; 114 m_flags.Set(m_sc.GetResolvedMask()); 115 } 116 117 if (!m_sc.target_sp && reg_context_sp) { 118 m_sc.target_sp = reg_context_sp->CalculateTarget(); 119 if (m_sc.target_sp) 120 m_flags.Set(eSymbolContextTarget); 121 } 122 123 ModuleSP pc_module_sp(pc_addr.GetModule()); 124 if (!m_sc.module_sp || m_sc.module_sp != pc_module_sp) { 125 if (pc_module_sp) { 126 m_sc.module_sp = pc_module_sp; 127 m_flags.Set(eSymbolContextModule); 128 } else { 129 m_sc.module_sp.reset(); 130 } 131 } 132 } 133 134 StackFrame::~StackFrame() = default; 135 136 StackID &StackFrame::GetStackID() { 137 std::lock_guard<std::recursive_mutex> guard(m_mutex); 138 // Make sure we have resolved the StackID object's symbol context scope if 139 // we already haven't looked it up. 140 141 if (m_flags.IsClear(RESOLVED_FRAME_ID_SYMBOL_SCOPE)) { 142 if (m_id.GetSymbolContextScope()) { 143 // We already have a symbol context scope, we just don't have our 144 // flag bit set. 145 m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE); 146 } else { 147 // Calculate the frame block and use this for the stack ID symbol 148 // context scope if we have one. 149 SymbolContextScope *scope = GetFrameBlock(); 150 if (scope == nullptr) { 151 // We don't have a block, so use the symbol 152 if (m_flags.IsClear(eSymbolContextSymbol)) 153 GetSymbolContext(eSymbolContextSymbol); 154 155 // It is ok if m_sc.symbol is nullptr here 156 scope = m_sc.symbol; 157 } 158 // Set the symbol context scope (the accessor will set the 159 // RESOLVED_FRAME_ID_SYMBOL_SCOPE bit in m_flags). 160 SetSymbolContextScope(scope); 161 } 162 } 163 return m_id; 164 } 165 166 uint32_t StackFrame::GetFrameIndex() const { 167 ThreadSP thread_sp = GetThread(); 168 if (thread_sp) 169 return thread_sp->GetStackFrameList()->GetVisibleStackFrameIndex( 170 m_frame_index); 171 else 172 return m_frame_index; 173 } 174 175 void StackFrame::SetSymbolContextScope(SymbolContextScope *symbol_scope) { 176 std::lock_guard<std::recursive_mutex> guard(m_mutex); 177 m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE); 178 m_id.SetSymbolContextScope(symbol_scope); 179 } 180 181 const Address &StackFrame::GetFrameCodeAddress() { 182 std::lock_guard<std::recursive_mutex> guard(m_mutex); 183 if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) && 184 !m_frame_code_addr.IsSectionOffset()) { 185 m_flags.Set(RESOLVED_FRAME_CODE_ADDR); 186 187 // Resolve the PC into a temporary address because if ResolveLoadAddress 188 // fails to resolve the address, it will clear the address object... 189 ThreadSP thread_sp(GetThread()); 190 if (thread_sp) { 191 TargetSP target_sp(thread_sp->CalculateTarget()); 192 if (target_sp) { 193 if (m_frame_code_addr.SetOpcodeLoadAddress( 194 m_frame_code_addr.GetOffset(), target_sp.get(), 195 eAddressClassCode)) { 196 ModuleSP module_sp(m_frame_code_addr.GetModule()); 197 if (module_sp) { 198 m_sc.module_sp = module_sp; 199 m_flags.Set(eSymbolContextModule); 200 } 201 } 202 } 203 } 204 } 205 return m_frame_code_addr; 206 } 207 208 bool StackFrame::ChangePC(addr_t pc) { 209 std::lock_guard<std::recursive_mutex> guard(m_mutex); 210 // We can't change the pc value of a history stack frame - it is immutable. 211 if (m_is_history_frame) 212 return false; 213 m_frame_code_addr.SetRawAddress(pc); 214 m_sc.Clear(false); 215 m_flags.Reset(0); 216 ThreadSP thread_sp(GetThread()); 217 if (thread_sp) 218 thread_sp->ClearStackFrames(); 219 return true; 220 } 221 222 const char *StackFrame::Disassemble() { 223 std::lock_guard<std::recursive_mutex> guard(m_mutex); 224 if (m_disassembly.Empty()) 225 return nullptr; 226 227 ExecutionContext exe_ctx(shared_from_this()); 228 Target *target = exe_ctx.GetTargetPtr(); 229 if (target) { 230 const char *plugin_name = nullptr; 231 const char *flavor = nullptr; 232 Disassembler::Disassemble(target->GetDebugger(), target->GetArchitecture(), 233 plugin_name, flavor, exe_ctx, 0, false, 0, 0, 234 m_disassembly); 235 } 236 return m_disassembly.GetData(); 237 } 238 239 Block *StackFrame::GetFrameBlock() { 240 if (m_sc.block == nullptr && m_flags.IsClear(eSymbolContextBlock)) 241 GetSymbolContext(eSymbolContextBlock); 242 243 if (m_sc.block) { 244 Block *inline_block = m_sc.block->GetContainingInlinedBlock(); 245 if (inline_block) { 246 // Use the block with the inlined function info 247 // as the frame block we want this frame to have only the variables 248 // for the inlined function and its non-inlined block child blocks. 249 return inline_block; 250 } else { 251 // This block is not contained within any inlined function blocks 252 // with so we want to use the top most function block. 253 return &m_sc.function->GetBlock(false); 254 } 255 } 256 return nullptr; 257 } 258 259 //---------------------------------------------------------------------- 260 // Get the symbol context if we already haven't done so by resolving the 261 // PC address as much as possible. This way when we pass around a 262 // StackFrame object, everyone will have as much information as 263 // possible and no one will ever have to look things up manually. 264 //---------------------------------------------------------------------- 265 const SymbolContext &StackFrame::GetSymbolContext(uint32_t resolve_scope) { 266 std::lock_guard<std::recursive_mutex> guard(m_mutex); 267 // Copy our internal symbol context into "sc". 268 if ((m_flags.Get() & resolve_scope) != resolve_scope) { 269 uint32_t resolved = 0; 270 271 // If the target was requested add that: 272 if (!m_sc.target_sp) { 273 m_sc.target_sp = CalculateTarget(); 274 if (m_sc.target_sp) 275 resolved |= eSymbolContextTarget; 276 } 277 278 // Resolve our PC to section offset if we haven't already done so 279 // and if we don't have a module. The resolved address section will 280 // contain the module to which it belongs 281 if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR)) 282 GetFrameCodeAddress(); 283 284 // If this is not frame zero, then we need to subtract 1 from the PC 285 // value when doing address lookups since the PC will be on the 286 // instruction following the function call instruction... 287 288 Address lookup_addr(GetFrameCodeAddress()); 289 if (m_frame_index > 0 && lookup_addr.IsValid()) { 290 addr_t offset = lookup_addr.GetOffset(); 291 if (offset > 0) { 292 lookup_addr.SetOffset(offset - 1); 293 294 } else { 295 // lookup_addr is the start of a section. We need 296 // do the math on the actual load address and re-compute 297 // the section. We're working with a 'noreturn' function 298 // at the end of a section. 299 ThreadSP thread_sp(GetThread()); 300 if (thread_sp) { 301 TargetSP target_sp(thread_sp->CalculateTarget()); 302 if (target_sp) { 303 addr_t addr_minus_one = 304 lookup_addr.GetLoadAddress(target_sp.get()) - 1; 305 lookup_addr.SetLoadAddress(addr_minus_one, target_sp.get()); 306 } else { 307 lookup_addr.SetOffset(offset - 1); 308 } 309 } 310 } 311 } 312 313 if (m_sc.module_sp) { 314 // We have something in our stack frame symbol context, lets check 315 // if we haven't already tried to lookup one of those things. If we 316 // haven't then we will do the query. 317 318 uint32_t actual_resolve_scope = 0; 319 320 if (resolve_scope & eSymbolContextCompUnit) { 321 if (m_flags.IsClear(eSymbolContextCompUnit)) { 322 if (m_sc.comp_unit) 323 resolved |= eSymbolContextCompUnit; 324 else 325 actual_resolve_scope |= eSymbolContextCompUnit; 326 } 327 } 328 329 if (resolve_scope & eSymbolContextFunction) { 330 if (m_flags.IsClear(eSymbolContextFunction)) { 331 if (m_sc.function) 332 resolved |= eSymbolContextFunction; 333 else 334 actual_resolve_scope |= eSymbolContextFunction; 335 } 336 } 337 338 if (resolve_scope & eSymbolContextBlock) { 339 if (m_flags.IsClear(eSymbolContextBlock)) { 340 if (m_sc.block) 341 resolved |= eSymbolContextBlock; 342 else 343 actual_resolve_scope |= eSymbolContextBlock; 344 } 345 } 346 347 if (resolve_scope & eSymbolContextSymbol) { 348 if (m_flags.IsClear(eSymbolContextSymbol)) { 349 if (m_sc.symbol) 350 resolved |= eSymbolContextSymbol; 351 else 352 actual_resolve_scope |= eSymbolContextSymbol; 353 } 354 } 355 356 if (resolve_scope & eSymbolContextLineEntry) { 357 if (m_flags.IsClear(eSymbolContextLineEntry)) { 358 if (m_sc.line_entry.IsValid()) 359 resolved |= eSymbolContextLineEntry; 360 else 361 actual_resolve_scope |= eSymbolContextLineEntry; 362 } 363 } 364 365 if (actual_resolve_scope) { 366 // We might be resolving less information than what is already 367 // in our current symbol context so resolve into a temporary 368 // symbol context "sc" so we don't clear out data we have 369 // already found in "m_sc" 370 SymbolContext sc; 371 // Set flags that indicate what we have tried to resolve 372 resolved |= m_sc.module_sp->ResolveSymbolContextForAddress( 373 lookup_addr, actual_resolve_scope, sc); 374 // Only replace what we didn't already have as we may have 375 // information for an inlined function scope that won't match 376 // what a standard lookup by address would match 377 if ((resolved & eSymbolContextCompUnit) && m_sc.comp_unit == nullptr) 378 m_sc.comp_unit = sc.comp_unit; 379 if ((resolved & eSymbolContextFunction) && m_sc.function == nullptr) 380 m_sc.function = sc.function; 381 if ((resolved & eSymbolContextBlock) && m_sc.block == nullptr) 382 m_sc.block = sc.block; 383 if ((resolved & eSymbolContextSymbol) && m_sc.symbol == nullptr) 384 m_sc.symbol = sc.symbol; 385 if ((resolved & eSymbolContextLineEntry) && 386 !m_sc.line_entry.IsValid()) { 387 m_sc.line_entry = sc.line_entry; 388 m_sc.line_entry.ApplyFileMappings(m_sc.target_sp); 389 } 390 } 391 } else { 392 // If we don't have a module, then we can't have the compile unit, 393 // function, block, line entry or symbol, so we can safely call 394 // ResolveSymbolContextForAddress with our symbol context member m_sc. 395 if (m_sc.target_sp) { 396 resolved |= m_sc.target_sp->GetImages().ResolveSymbolContextForAddress( 397 lookup_addr, resolve_scope, m_sc); 398 } 399 } 400 401 // Update our internal flags so we remember what we have tried to locate so 402 // we don't have to keep trying when more calls to this function are made. 403 // We might have dug up more information that was requested (for example 404 // if we were asked to only get the block, we will have gotten the 405 // compile unit, and function) so set any additional bits that we resolved 406 m_flags.Set(resolve_scope | resolved); 407 } 408 409 // Return the symbol context with everything that was possible to resolve 410 // resolved. 411 return m_sc; 412 } 413 414 VariableList *StackFrame::GetVariableList(bool get_file_globals) { 415 std::lock_guard<std::recursive_mutex> guard(m_mutex); 416 if (m_flags.IsClear(RESOLVED_VARIABLES)) { 417 m_flags.Set(RESOLVED_VARIABLES); 418 419 Block *frame_block = GetFrameBlock(); 420 421 if (frame_block) { 422 const bool get_child_variables = true; 423 const bool can_create = true; 424 const bool stop_if_child_block_is_inlined_function = true; 425 m_variable_list_sp.reset(new VariableList()); 426 frame_block->AppendBlockVariables(can_create, get_child_variables, 427 stop_if_child_block_is_inlined_function, 428 [this](Variable *v) { return true; }, 429 m_variable_list_sp.get()); 430 } 431 } 432 433 if (m_flags.IsClear(RESOLVED_GLOBAL_VARIABLES) && get_file_globals) { 434 m_flags.Set(RESOLVED_GLOBAL_VARIABLES); 435 436 if (m_flags.IsClear(eSymbolContextCompUnit)) 437 GetSymbolContext(eSymbolContextCompUnit); 438 439 if (m_sc.comp_unit) { 440 VariableListSP global_variable_list_sp( 441 m_sc.comp_unit->GetVariableList(true)); 442 if (m_variable_list_sp) 443 m_variable_list_sp->AddVariables(global_variable_list_sp.get()); 444 else 445 m_variable_list_sp = global_variable_list_sp; 446 } 447 } 448 449 return m_variable_list_sp.get(); 450 } 451 452 VariableListSP 453 StackFrame::GetInScopeVariableList(bool get_file_globals, 454 bool must_have_valid_location) { 455 std::lock_guard<std::recursive_mutex> guard(m_mutex); 456 // We can't fetch variable information for a history stack frame. 457 if (m_is_history_frame) 458 return VariableListSP(); 459 460 VariableListSP var_list_sp(new VariableList); 461 GetSymbolContext(eSymbolContextCompUnit | eSymbolContextBlock); 462 463 if (m_sc.block) { 464 const bool can_create = true; 465 const bool get_parent_variables = true; 466 const bool stop_if_block_is_inlined_function = true; 467 m_sc.block->AppendVariables( 468 can_create, get_parent_variables, stop_if_block_is_inlined_function, 469 [this, must_have_valid_location](Variable *v) { 470 return v->IsInScope(this) && (!must_have_valid_location || 471 v->LocationIsValidForFrame(this)); 472 }, 473 var_list_sp.get()); 474 } 475 476 if (m_sc.comp_unit && get_file_globals) { 477 VariableListSP global_variable_list_sp( 478 m_sc.comp_unit->GetVariableList(true)); 479 if (global_variable_list_sp) 480 var_list_sp->AddVariables(global_variable_list_sp.get()); 481 } 482 483 return var_list_sp; 484 } 485 486 ValueObjectSP StackFrame::GetValueForVariableExpressionPath( 487 llvm::StringRef var_expr_cstr, DynamicValueType use_dynamic, 488 uint32_t options, VariableSP &var_sp, Error &error) { 489 // We can't fetch variable information for a history stack frame. 490 if (m_is_history_frame) 491 return ValueObjectSP(); 492 493 if (var_expr_cstr.empty()) { 494 error.SetErrorStringWithFormat("invalid variable path '%s'", var_expr_cstr); 495 return ValueObjectSP(); 496 } 497 498 const bool check_ptr_vs_member = 499 (options & eExpressionPathOptionCheckPtrVsMember) != 0; 500 const bool no_fragile_ivar = 501 (options & eExpressionPathOptionsNoFragileObjcIvar) != 0; 502 const bool no_synth_child = 503 (options & eExpressionPathOptionsNoSyntheticChildren) != 0; 504 // const bool no_synth_array = (options & 505 // eExpressionPathOptionsNoSyntheticArrayRange) != 0; 506 error.Clear(); 507 bool deref = false; 508 bool address_of = false; 509 ValueObjectSP valobj_sp; 510 const bool get_file_globals = true; 511 // When looking up a variable for an expression, we need only consider the 512 // variables that are in scope. 513 VariableListSP var_list_sp(GetInScopeVariableList(get_file_globals)); 514 VariableList *variable_list = var_list_sp.get(); 515 516 if (!variable_list) 517 return ValueObjectSP(); 518 519 // If first character is a '*', then show pointer contents 520 llvm::StringRef var_expr = var_expr_cstr; 521 std::string var_expr_storage; 522 if (var_expr[0] == '*') { 523 deref = true; 524 var_expr = var_expr.drop_front(); // Skip the '*' 525 } else if (var_expr[0] == '&') { 526 address_of = true; 527 var_expr = var_expr.drop_front(); // Skip the '&' 528 } 529 530 size_t separator_idx = var_expr.find_first_of(".-[=+~|&^%#@!/?,<>{}"); 531 StreamString var_expr_path_strm; 532 533 ConstString name_const_string(var_expr.substr(0, separator_idx)); 534 535 var_sp = variable_list->FindVariable(name_const_string, false); 536 537 bool synthetically_added_instance_object = false; 538 539 if (var_sp) { 540 var_expr = var_expr.drop_front(name_const_string.GetLength()); 541 } 542 543 if (!var_sp && (options & eExpressionPathOptionsAllowDirectIVarAccess)) { 544 // Check for direct ivars access which helps us with implicit 545 // access to ivars with the "this->" or "self->" 546 GetSymbolContext(eSymbolContextFunction | eSymbolContextBlock); 547 lldb::LanguageType method_language = eLanguageTypeUnknown; 548 bool is_instance_method = false; 549 ConstString method_object_name; 550 if (m_sc.GetFunctionMethodInfo(method_language, is_instance_method, 551 method_object_name)) { 552 if (is_instance_method && method_object_name) { 553 var_sp = variable_list->FindVariable(method_object_name); 554 if (var_sp) { 555 separator_idx = 0; 556 var_expr_storage = "->"; 557 var_expr_storage += var_expr; 558 var_expr = var_expr_storage; 559 synthetically_added_instance_object = true; 560 } 561 } 562 } 563 } 564 565 if (!var_sp && (options & eExpressionPathOptionsInspectAnonymousUnions)) { 566 // Check if any anonymous unions are there which contain a variable with 567 // the name we need 568 for (size_t i = 0; i < variable_list->GetSize(); i++) { 569 VariableSP variable_sp = variable_list->GetVariableAtIndex(i); 570 if (!variable_sp) 571 continue; 572 if (!variable_sp->GetName().IsEmpty()) 573 continue; 574 575 Type *var_type = variable_sp->GetType(); 576 if (!var_type) 577 continue; 578 579 if (!var_type->GetForwardCompilerType().IsAnonymousType()) 580 continue; 581 valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic); 582 if (!valobj_sp) 583 return valobj_sp; 584 valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string, true); 585 if (valobj_sp) 586 break; 587 } 588 } 589 590 if (var_sp && !valobj_sp) { 591 valobj_sp = GetValueObjectForFrameVariable(var_sp, use_dynamic); 592 if (!valobj_sp) 593 return valobj_sp; 594 } 595 if (!valobj_sp) { 596 error.SetErrorStringWithFormat("no variable named '%s' found in this frame", 597 name_const_string.GetCString()); 598 return ValueObjectSP(); 599 } 600 601 // We are dumping at least one child 602 while (separator_idx != std::string::npos) { 603 // Calculate the next separator index ahead of time 604 ValueObjectSP child_valobj_sp; 605 const char separator_type = var_expr[0]; 606 switch (separator_type) { 607 case '-': 608 if (var_expr.size() >= 2 && var_expr[1] != '>') 609 return ValueObjectSP(); 610 611 if (no_fragile_ivar) { 612 // Make sure we aren't trying to deref an objective 613 // C ivar if this is not allowed 614 const uint32_t pointer_type_flags = 615 valobj_sp->GetCompilerType().GetTypeInfo(nullptr); 616 if ((pointer_type_flags & eTypeIsObjC) && 617 (pointer_type_flags & eTypeIsPointer)) { 618 // This was an objective C object pointer and 619 // it was requested we skip any fragile ivars 620 // so return nothing here 621 return ValueObjectSP(); 622 } 623 } 624 var_expr = var_expr.drop_front(); // Remove the '-' 625 LLVM_FALLTHROUGH; 626 case '.': { 627 const bool expr_is_ptr = var_expr[0] == '>'; 628 629 var_expr = var_expr.drop_front(); // Remove the '.' or '>' 630 separator_idx = var_expr.find_first_of(".-["); 631 ConstString child_name(var_expr.substr(0, var_expr.find_first_of(".-["))); 632 633 if (check_ptr_vs_member) { 634 // We either have a pointer type and need to verify 635 // valobj_sp is a pointer, or we have a member of a 636 // class/union/struct being accessed with the . syntax 637 // and need to verify we don't have a pointer. 638 const bool actual_is_ptr = valobj_sp->IsPointerType(); 639 640 if (actual_is_ptr != expr_is_ptr) { 641 // Incorrect use of "." with a pointer, or "->" with 642 // a class/union/struct instance or reference. 643 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 644 if (actual_is_ptr) 645 error.SetErrorStringWithFormat( 646 "\"%s\" is a pointer and . was used to attempt to access " 647 "\"%s\". Did you mean \"%s->%s\"?", 648 var_expr_path_strm.GetData(), child_name.GetCString(), 649 var_expr_path_strm.GetData(), var_expr.str().c_str()); 650 else 651 error.SetErrorStringWithFormat( 652 "\"%s\" is not a pointer and -> was used to attempt to " 653 "access \"%s\". Did you mean \"%s.%s\"?", 654 var_expr_path_strm.GetData(), child_name.GetCString(), 655 var_expr_path_strm.GetData(), var_expr.str().c_str()); 656 return ValueObjectSP(); 657 } 658 } 659 child_valobj_sp = valobj_sp->GetChildMemberWithName(child_name, true); 660 if (!child_valobj_sp) { 661 if (!no_synth_child) { 662 child_valobj_sp = valobj_sp->GetSyntheticValue(); 663 if (child_valobj_sp) 664 child_valobj_sp = 665 child_valobj_sp->GetChildMemberWithName(child_name, true); 666 } 667 668 if (no_synth_child || !child_valobj_sp) { 669 // No child member with name "child_name" 670 if (synthetically_added_instance_object) { 671 // We added a "this->" or "self->" to the beginning of the 672 // expression 673 // and this is the first pointer ivar access, so just return 674 // the normal 675 // error 676 error.SetErrorStringWithFormat( 677 "no variable or instance variable named '%s' found in " 678 "this frame", 679 name_const_string.GetCString()); 680 } else { 681 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 682 if (child_name) { 683 error.SetErrorStringWithFormat( 684 "\"%s\" is not a member of \"(%s) %s\"", 685 child_name.GetCString(), 686 valobj_sp->GetTypeName().AsCString("<invalid type>"), 687 var_expr_path_strm.GetData()); 688 } else { 689 error.SetErrorStringWithFormat( 690 "incomplete expression path after \"%s\" in \"%s\"", 691 var_expr_path_strm.GetData(), var_expr_cstr); 692 } 693 } 694 return ValueObjectSP(); 695 } 696 } 697 synthetically_added_instance_object = false; 698 // Remove the child name from the path 699 var_expr = var_expr.drop_front(child_name.GetLength()); 700 if (use_dynamic != eNoDynamicValues) { 701 ValueObjectSP dynamic_value_sp( 702 child_valobj_sp->GetDynamicValue(use_dynamic)); 703 if (dynamic_value_sp) 704 child_valobj_sp = dynamic_value_sp; 705 } 706 } break; 707 708 case '[': { 709 // Array member access, or treating pointer as an array 710 // Need at least two brackets and a number 711 if (var_expr.size() <= 2) { 712 error.SetErrorStringWithFormat( 713 "invalid square bracket encountered after \"%s\" in \"%s\"", 714 var_expr_path_strm.GetData(), var_expr.str().c_str()); 715 return ValueObjectSP(); 716 } 717 718 // Drop the open brace. 719 var_expr = var_expr.drop_front(); 720 long child_index = 0; 721 722 // If there's no closing brace, this is an invalid expression. 723 size_t end_pos = var_expr.find_first_of(']'); 724 if (end_pos == llvm::StringRef::npos) { 725 error.SetErrorStringWithFormat( 726 "missing closing square bracket in expression \"%s\"", 727 var_expr_path_strm.GetData()); 728 return ValueObjectSP(); 729 } 730 llvm::StringRef index_expr = var_expr.take_front(end_pos); 731 llvm::StringRef original_index_expr = index_expr; 732 // Drop all of "[index_expr]" 733 var_expr = var_expr.drop_front(end_pos + 1); 734 735 if (index_expr.consumeInteger(0, child_index)) { 736 // If there was no integer anywhere in the index expression, this is 737 // erroneous expression. 738 error.SetErrorStringWithFormat("invalid index expression \"%s\"", 739 index_expr.str().c_str()); 740 return ValueObjectSP(); 741 } 742 743 if (index_expr.empty()) { 744 // The entire index expression was a single integer. 745 746 if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) { 747 // what we have is *ptr[low]. the most similar C++ syntax is to deref 748 // ptr and extract bit low out of it. reading array item low would be 749 // done by saying ptr[low], without a deref * sign 750 Error error; 751 ValueObjectSP temp(valobj_sp->Dereference(error)); 752 if (error.Fail()) { 753 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 754 error.SetErrorStringWithFormat( 755 "could not dereference \"(%s) %s\"", 756 valobj_sp->GetTypeName().AsCString("<invalid type>"), 757 var_expr_path_strm.GetData()); 758 return ValueObjectSP(); 759 } 760 valobj_sp = temp; 761 deref = false; 762 } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && 763 deref) { 764 // what we have is *arr[low]. the most similar C++ syntax is 765 // to get arr[0] 766 // (an operation that is equivalent to deref-ing arr) 767 // and extract bit low out of it. reading array item low 768 // would be done by saying arr[low], without a deref * sign 769 Error error; 770 ValueObjectSP temp(valobj_sp->GetChildAtIndex(0, true)); 771 if (error.Fail()) { 772 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 773 error.SetErrorStringWithFormat( 774 "could not get item 0 for \"(%s) %s\"", 775 valobj_sp->GetTypeName().AsCString("<invalid type>"), 776 var_expr_path_strm.GetData()); 777 return ValueObjectSP(); 778 } 779 valobj_sp = temp; 780 deref = false; 781 } 782 783 bool is_incomplete_array = false; 784 if (valobj_sp->IsPointerType()) { 785 bool is_objc_pointer = true; 786 787 if (valobj_sp->GetCompilerType().GetMinimumLanguage() != 788 eLanguageTypeObjC) 789 is_objc_pointer = false; 790 else if (!valobj_sp->GetCompilerType().IsPointerType()) 791 is_objc_pointer = false; 792 793 if (no_synth_child && is_objc_pointer) { 794 error.SetErrorStringWithFormat( 795 "\"(%s) %s\" is an Objective-C pointer, and cannot be " 796 "subscripted", 797 valobj_sp->GetTypeName().AsCString("<invalid type>"), 798 var_expr_path_strm.GetData()); 799 800 return ValueObjectSP(); 801 } else if (is_objc_pointer) { 802 // dereferencing ObjC variables is not valid.. so let's try 803 // and recur to synthetic children 804 ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(); 805 if (!synthetic /* no synthetic */ 806 || synthetic == valobj_sp) /* synthetic is the same as 807 the original object */ 808 { 809 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 810 error.SetErrorStringWithFormat( 811 "\"(%s) %s\" is not an array type", 812 valobj_sp->GetTypeName().AsCString("<invalid type>"), 813 var_expr_path_strm.GetData()); 814 } else if ( 815 static_cast<uint32_t>(child_index) >= 816 synthetic 817 ->GetNumChildren() /* synthetic does not have that many values */) { 818 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 819 error.SetErrorStringWithFormat( 820 "array index %ld is not valid for \"(%s) %s\"", child_index, 821 valobj_sp->GetTypeName().AsCString("<invalid type>"), 822 var_expr_path_strm.GetData()); 823 } else { 824 child_valobj_sp = synthetic->GetChildAtIndex(child_index, true); 825 if (!child_valobj_sp) { 826 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 827 error.SetErrorStringWithFormat( 828 "array index %ld is not valid for \"(%s) %s\"", child_index, 829 valobj_sp->GetTypeName().AsCString("<invalid type>"), 830 var_expr_path_strm.GetData()); 831 } 832 } 833 } else { 834 child_valobj_sp = 835 valobj_sp->GetSyntheticArrayMember(child_index, true); 836 if (!child_valobj_sp) { 837 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 838 error.SetErrorStringWithFormat( 839 "failed to use pointer as array for index %ld for " 840 "\"(%s) %s\"", 841 child_index, 842 valobj_sp->GetTypeName().AsCString("<invalid type>"), 843 var_expr_path_strm.GetData()); 844 } 845 } 846 } else if (valobj_sp->GetCompilerType().IsArrayType( 847 nullptr, nullptr, &is_incomplete_array)) { 848 // Pass false to dynamic_value here so we can tell the 849 // difference between 850 // no dynamic value and no member of this type... 851 child_valobj_sp = valobj_sp->GetChildAtIndex(child_index, true); 852 if (!child_valobj_sp && (is_incomplete_array || !no_synth_child)) 853 child_valobj_sp = 854 valobj_sp->GetSyntheticArrayMember(child_index, true); 855 856 if (!child_valobj_sp) { 857 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 858 error.SetErrorStringWithFormat( 859 "array index %ld is not valid for \"(%s) %s\"", child_index, 860 valobj_sp->GetTypeName().AsCString("<invalid type>"), 861 var_expr_path_strm.GetData()); 862 } 863 } else if (valobj_sp->GetCompilerType().IsScalarType()) { 864 // this is a bitfield asking to display just one bit 865 child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild( 866 child_index, child_index, true); 867 if (!child_valobj_sp) { 868 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 869 error.SetErrorStringWithFormat( 870 "bitfield range %ld-%ld is not valid for \"(%s) %s\"", 871 child_index, child_index, 872 valobj_sp->GetTypeName().AsCString("<invalid type>"), 873 var_expr_path_strm.GetData()); 874 } 875 } else { 876 ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(); 877 if (no_synth_child /* synthetic is forbidden */ || 878 !synthetic /* no synthetic */ 879 || synthetic == valobj_sp) /* synthetic is the same as the 880 original object */ 881 { 882 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 883 error.SetErrorStringWithFormat( 884 "\"(%s) %s\" is not an array type", 885 valobj_sp->GetTypeName().AsCString("<invalid type>"), 886 var_expr_path_strm.GetData()); 887 } else if ( 888 static_cast<uint32_t>(child_index) >= 889 synthetic 890 ->GetNumChildren() /* synthetic does not have that many values */) { 891 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 892 error.SetErrorStringWithFormat( 893 "array index %ld is not valid for \"(%s) %s\"", child_index, 894 valobj_sp->GetTypeName().AsCString("<invalid type>"), 895 var_expr_path_strm.GetData()); 896 } else { 897 child_valobj_sp = synthetic->GetChildAtIndex(child_index, true); 898 if (!child_valobj_sp) { 899 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 900 error.SetErrorStringWithFormat( 901 "array index %ld is not valid for \"(%s) %s\"", child_index, 902 valobj_sp->GetTypeName().AsCString("<invalid type>"), 903 var_expr_path_strm.GetData()); 904 } 905 } 906 } 907 908 if (!child_valobj_sp) { 909 // Invalid array index... 910 return ValueObjectSP(); 911 } 912 913 separator_idx = var_expr.find_first_of(".-["); 914 if (use_dynamic != eNoDynamicValues) { 915 ValueObjectSP dynamic_value_sp( 916 child_valobj_sp->GetDynamicValue(use_dynamic)); 917 if (dynamic_value_sp) 918 child_valobj_sp = dynamic_value_sp; 919 } 920 // Break out early from the switch since we were able to find the child 921 // member 922 break; 923 } 924 925 // this is most probably a BitField, let's take a look 926 if (index_expr.front() != '-') { 927 error.SetErrorStringWithFormat("invalid range expression \"'%s'\"", 928 original_index_expr.str().c_str()); 929 return ValueObjectSP(); 930 } 931 932 index_expr.drop_front(); 933 long final_index = 0; 934 if (index_expr.getAsInteger(0, final_index)) { 935 error.SetErrorStringWithFormat("invalid range expression \"'%s'\"", 936 original_index_expr.str().c_str()); 937 return ValueObjectSP(); 938 } 939 940 // if the format given is [high-low], swap range 941 if (child_index > final_index) { 942 long temp = child_index; 943 child_index = final_index; 944 final_index = temp; 945 } 946 947 if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) { 948 // what we have is *ptr[low-high]. the most similar C++ syntax is to 949 // deref ptr and extract bits low thru high out of it. reading array 950 // items low thru high would be done by saying ptr[low-high], without 951 // a deref * sign 952 Error error; 953 ValueObjectSP temp(valobj_sp->Dereference(error)); 954 if (error.Fail()) { 955 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 956 error.SetErrorStringWithFormat( 957 "could not dereference \"(%s) %s\"", 958 valobj_sp->GetTypeName().AsCString("<invalid type>"), 959 var_expr_path_strm.GetData()); 960 return ValueObjectSP(); 961 } 962 valobj_sp = temp; 963 deref = false; 964 } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && deref) { 965 // what we have is *arr[low-high]. the most similar C++ syntax is to get 966 // arr[0] (an operation that is equivalent to deref-ing arr) and extract 967 // bits low thru high out of it. reading array items low thru high would 968 // be done by saying arr[low-high], without a deref * sign 969 Error error; 970 ValueObjectSP temp(valobj_sp->GetChildAtIndex(0, true)); 971 if (error.Fail()) { 972 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 973 error.SetErrorStringWithFormat( 974 "could not get item 0 for \"(%s) %s\"", 975 valobj_sp->GetTypeName().AsCString("<invalid type>"), 976 var_expr_path_strm.GetData()); 977 return ValueObjectSP(); 978 } 979 valobj_sp = temp; 980 deref = false; 981 } 982 983 child_valobj_sp = 984 valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true); 985 if (!child_valobj_sp) { 986 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 987 error.SetErrorStringWithFormat( 988 "bitfield range %ld-%ld is not valid for \"(%s) %s\"", child_index, 989 final_index, valobj_sp->GetTypeName().AsCString("<invalid type>"), 990 var_expr_path_strm.GetData()); 991 } 992 993 if (!child_valobj_sp) { 994 // Invalid bitfield range... 995 return ValueObjectSP(); 996 } 997 998 separator_idx = var_expr.find_first_of(".-["); 999 if (use_dynamic != eNoDynamicValues) { 1000 ValueObjectSP dynamic_value_sp( 1001 child_valobj_sp->GetDynamicValue(use_dynamic)); 1002 if (dynamic_value_sp) 1003 child_valobj_sp = dynamic_value_sp; 1004 } 1005 // Break out early from the switch since we were able to find the child 1006 // member 1007 break; 1008 } 1009 default: 1010 // Failure... 1011 { 1012 valobj_sp->GetExpressionPath(var_expr_path_strm, false); 1013 error.SetErrorStringWithFormat( 1014 "unexpected char '%c' encountered after \"%s\" in \"%s\"", 1015 separator_type, var_expr_path_strm.GetData(), 1016 var_expr.str().c_str()); 1017 1018 return ValueObjectSP(); 1019 } 1020 } 1021 1022 if (child_valobj_sp) 1023 valobj_sp = child_valobj_sp; 1024 1025 if (var_expr.empty()) 1026 break; 1027 } 1028 if (valobj_sp) { 1029 if (deref) { 1030 ValueObjectSP deref_valobj_sp(valobj_sp->Dereference(error)); 1031 valobj_sp = deref_valobj_sp; 1032 } else if (address_of) { 1033 ValueObjectSP address_of_valobj_sp(valobj_sp->AddressOf(error)); 1034 valobj_sp = address_of_valobj_sp; 1035 } 1036 } 1037 return valobj_sp; 1038 } 1039 1040 bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Error *error_ptr) { 1041 std::lock_guard<std::recursive_mutex> guard(m_mutex); 1042 if (!m_cfa_is_valid) { 1043 m_frame_base_error.SetErrorString( 1044 "No frame base available for this historical stack frame."); 1045 return false; 1046 } 1047 1048 if (m_flags.IsClear(GOT_FRAME_BASE)) { 1049 if (m_sc.function) { 1050 m_frame_base.Clear(); 1051 m_frame_base_error.Clear(); 1052 1053 m_flags.Set(GOT_FRAME_BASE); 1054 ExecutionContext exe_ctx(shared_from_this()); 1055 Value expr_value; 1056 addr_t loclist_base_addr = LLDB_INVALID_ADDRESS; 1057 if (m_sc.function->GetFrameBaseExpression().IsLocationList()) 1058 loclist_base_addr = 1059 m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress( 1060 exe_ctx.GetTargetPtr()); 1061 1062 if (m_sc.function->GetFrameBaseExpression().Evaluate( 1063 &exe_ctx, nullptr, nullptr, nullptr, loclist_base_addr, nullptr, 1064 nullptr, expr_value, &m_frame_base_error) == false) { 1065 // We should really have an error if evaluate returns, but in case 1066 // we don't, lets set the error to something at least. 1067 if (m_frame_base_error.Success()) 1068 m_frame_base_error.SetErrorString( 1069 "Evaluation of the frame base expression failed."); 1070 } else { 1071 m_frame_base = expr_value.ResolveValue(&exe_ctx); 1072 } 1073 } else { 1074 m_frame_base_error.SetErrorString("No function in symbol context."); 1075 } 1076 } 1077 1078 if (m_frame_base_error.Success()) 1079 frame_base = m_frame_base; 1080 1081 if (error_ptr) 1082 *error_ptr = m_frame_base_error; 1083 return m_frame_base_error.Success(); 1084 } 1085 1086 DWARFExpression *StackFrame::GetFrameBaseExpression(Error *error_ptr) { 1087 if (!m_sc.function) { 1088 if (error_ptr) { 1089 error_ptr->SetErrorString("No function in symbol context."); 1090 } 1091 return nullptr; 1092 } 1093 1094 return &m_sc.function->GetFrameBaseExpression(); 1095 } 1096 1097 RegisterContextSP StackFrame::GetRegisterContext() { 1098 std::lock_guard<std::recursive_mutex> guard(m_mutex); 1099 if (!m_reg_context_sp) { 1100 ThreadSP thread_sp(GetThread()); 1101 if (thread_sp) 1102 m_reg_context_sp = thread_sp->CreateRegisterContextForFrame(this); 1103 } 1104 return m_reg_context_sp; 1105 } 1106 1107 bool StackFrame::HasDebugInformation() { 1108 GetSymbolContext(eSymbolContextLineEntry); 1109 return m_sc.line_entry.IsValid(); 1110 } 1111 1112 ValueObjectSP 1113 StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp, 1114 DynamicValueType use_dynamic) { 1115 std::lock_guard<std::recursive_mutex> guard(m_mutex); 1116 ValueObjectSP valobj_sp; 1117 if (m_is_history_frame) { 1118 return valobj_sp; 1119 } 1120 VariableList *var_list = GetVariableList(true); 1121 if (var_list) { 1122 // Make sure the variable is a frame variable 1123 const uint32_t var_idx = var_list->FindIndexForVariable(variable_sp.get()); 1124 const uint32_t num_variables = var_list->GetSize(); 1125 if (var_idx < num_variables) { 1126 valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex(var_idx); 1127 if (!valobj_sp) { 1128 if (m_variable_list_value_objects.GetSize() < num_variables) 1129 m_variable_list_value_objects.Resize(num_variables); 1130 valobj_sp = ValueObjectVariable::Create(this, variable_sp); 1131 m_variable_list_value_objects.SetValueObjectAtIndex(var_idx, valobj_sp); 1132 } 1133 } 1134 } 1135 if (use_dynamic != eNoDynamicValues && valobj_sp) { 1136 ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue(use_dynamic); 1137 if (dynamic_sp) 1138 return dynamic_sp; 1139 } 1140 return valobj_sp; 1141 } 1142 1143 ValueObjectSP StackFrame::TrackGlobalVariable(const VariableSP &variable_sp, 1144 DynamicValueType use_dynamic) { 1145 std::lock_guard<std::recursive_mutex> guard(m_mutex); 1146 if (m_is_history_frame) 1147 return ValueObjectSP(); 1148 1149 // Check to make sure we aren't already tracking this variable? 1150 ValueObjectSP valobj_sp( 1151 GetValueObjectForFrameVariable(variable_sp, use_dynamic)); 1152 if (!valobj_sp) { 1153 // We aren't already tracking this global 1154 VariableList *var_list = GetVariableList(true); 1155 // If this frame has no variables, create a new list 1156 if (var_list == nullptr) 1157 m_variable_list_sp.reset(new VariableList()); 1158 1159 // Add the global/static variable to this frame 1160 m_variable_list_sp->AddVariable(variable_sp); 1161 1162 // Now make a value object for it so we can track its changes 1163 valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic); 1164 } 1165 return valobj_sp; 1166 } 1167 1168 bool StackFrame::IsInlined() { 1169 if (m_sc.block == nullptr) 1170 GetSymbolContext(eSymbolContextBlock); 1171 if (m_sc.block) 1172 return m_sc.block->GetContainingInlinedBlock() != nullptr; 1173 return false; 1174 } 1175 1176 lldb::LanguageType StackFrame::GetLanguage() { 1177 CompileUnit *cu = GetSymbolContext(eSymbolContextCompUnit).comp_unit; 1178 if (cu) 1179 return cu->GetLanguage(); 1180 return lldb::eLanguageTypeUnknown; 1181 } 1182 1183 lldb::LanguageType StackFrame::GuessLanguage() { 1184 LanguageType lang_type = GetLanguage(); 1185 1186 if (lang_type == eLanguageTypeUnknown) { 1187 Function *f = GetSymbolContext(eSymbolContextFunction).function; 1188 if (f) { 1189 lang_type = f->GetMangled().GuessLanguage(); 1190 } 1191 } 1192 1193 return lang_type; 1194 } 1195 1196 namespace { 1197 std::pair<const Instruction::Operand *, int64_t> 1198 GetBaseExplainingValue(const Instruction::Operand &operand, 1199 RegisterContext ®ister_context, lldb::addr_t value) { 1200 switch (operand.m_type) { 1201 case Instruction::Operand::Type::Dereference: 1202 case Instruction::Operand::Type::Immediate: 1203 case Instruction::Operand::Type::Invalid: 1204 case Instruction::Operand::Type::Product: 1205 // These are not currently interesting 1206 return std::make_pair(nullptr, 0); 1207 case Instruction::Operand::Type::Sum: { 1208 const Instruction::Operand *immediate_child = nullptr; 1209 const Instruction::Operand *variable_child = nullptr; 1210 if (operand.m_children[0].m_type == Instruction::Operand::Type::Immediate) { 1211 immediate_child = &operand.m_children[0]; 1212 variable_child = &operand.m_children[1]; 1213 } else if (operand.m_children[1].m_type == 1214 Instruction::Operand::Type::Immediate) { 1215 immediate_child = &operand.m_children[1]; 1216 variable_child = &operand.m_children[0]; 1217 } 1218 if (!immediate_child) { 1219 return std::make_pair(nullptr, 0); 1220 } 1221 lldb::addr_t adjusted_value = value; 1222 if (immediate_child->m_negative) { 1223 adjusted_value += immediate_child->m_immediate; 1224 } else { 1225 adjusted_value -= immediate_child->m_immediate; 1226 } 1227 std::pair<const Instruction::Operand *, int64_t> base_and_offset = 1228 GetBaseExplainingValue(*variable_child, register_context, 1229 adjusted_value); 1230 if (!base_and_offset.first) { 1231 return std::make_pair(nullptr, 0); 1232 } 1233 if (immediate_child->m_negative) { 1234 base_and_offset.second -= immediate_child->m_immediate; 1235 } else { 1236 base_and_offset.second += immediate_child->m_immediate; 1237 } 1238 return base_and_offset; 1239 } 1240 case Instruction::Operand::Type::Register: { 1241 const RegisterInfo *info = 1242 register_context.GetRegisterInfoByName(operand.m_register.AsCString()); 1243 if (!info) { 1244 return std::make_pair(nullptr, 0); 1245 } 1246 RegisterValue reg_value; 1247 if (!register_context.ReadRegister(info, reg_value)) { 1248 return std::make_pair(nullptr, 0); 1249 } 1250 if (reg_value.GetAsUInt64() == value) { 1251 return std::make_pair(&operand, 0); 1252 } else { 1253 return std::make_pair(nullptr, 0); 1254 } 1255 } 1256 } 1257 return std::make_pair(nullptr, 0); 1258 } 1259 1260 std::pair<const Instruction::Operand *, int64_t> 1261 GetBaseExplainingDereference(const Instruction::Operand &operand, 1262 RegisterContext ®ister_context, 1263 lldb::addr_t addr) { 1264 if (operand.m_type == Instruction::Operand::Type::Dereference) { 1265 return GetBaseExplainingValue(operand.m_children[0], register_context, 1266 addr); 1267 } 1268 return std::make_pair(nullptr, 0); 1269 } 1270 } 1271 1272 lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) { 1273 TargetSP target_sp = CalculateTarget(); 1274 1275 const ArchSpec &target_arch = target_sp->GetArchitecture(); 1276 1277 AddressRange pc_range; 1278 pc_range.GetBaseAddress() = GetFrameCodeAddress(); 1279 pc_range.SetByteSize(target_arch.GetMaximumOpcodeByteSize()); 1280 1281 ExecutionContext exe_ctx(shared_from_this()); 1282 1283 const char *plugin_name = nullptr; 1284 const char *flavor = nullptr; 1285 const bool prefer_file_cache = false; 1286 1287 DisassemblerSP disassembler_sp = Disassembler::DisassembleRange( 1288 target_arch, plugin_name, flavor, exe_ctx, pc_range, prefer_file_cache); 1289 1290 if (!disassembler_sp->GetInstructionList().GetSize()) { 1291 return ValueObjectSP(); 1292 } 1293 1294 InstructionSP instruction_sp = 1295 disassembler_sp->GetInstructionList().GetInstructionAtIndex(0); 1296 1297 llvm::SmallVector<Instruction::Operand, 3> operands; 1298 1299 if (!instruction_sp->ParseOperands(operands)) { 1300 return ValueObjectSP(); 1301 } 1302 1303 RegisterContextSP register_context_sp = GetRegisterContext(); 1304 1305 if (!register_context_sp) { 1306 return ValueObjectSP(); 1307 } 1308 1309 for (const Instruction::Operand &operand : operands) { 1310 std::pair<const Instruction::Operand *, int64_t> base_and_offset = 1311 GetBaseExplainingDereference(operand, *register_context_sp, addr); 1312 1313 if (!base_and_offset.first) { 1314 continue; 1315 } 1316 1317 switch (base_and_offset.first->m_type) { 1318 case Instruction::Operand::Type::Immediate: { 1319 lldb_private::Address addr; 1320 if (target_sp->ResolveLoadAddress(base_and_offset.first->m_immediate + 1321 base_and_offset.second, 1322 addr)) { 1323 TypeSystem *c_type_system = 1324 target_sp->GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC); 1325 if (!c_type_system) { 1326 return ValueObjectSP(); 1327 } else { 1328 CompilerType void_ptr_type = 1329 c_type_system 1330 ->GetBasicTypeFromAST(lldb::BasicType::eBasicTypeChar) 1331 .GetPointerType(); 1332 return ValueObjectMemory::Create(this, "", addr, void_ptr_type); 1333 } 1334 } else { 1335 return ValueObjectSP(); 1336 } 1337 break; 1338 } 1339 case Instruction::Operand::Type::Register: { 1340 return GuessValueForRegisterAndOffset(base_and_offset.first->m_register, 1341 base_and_offset.second); 1342 } 1343 default: 1344 return ValueObjectSP(); 1345 } 1346 } 1347 1348 return ValueObjectSP(); 1349 } 1350 1351 namespace { 1352 ValueObjectSP GetValueForOffset(StackFrame &frame, ValueObjectSP &parent, 1353 int64_t offset) { 1354 if (offset < 0 || uint64_t(offset) >= parent->GetByteSize()) { 1355 return ValueObjectSP(); 1356 } 1357 1358 if (parent->IsPointerOrReferenceType()) { 1359 return parent; 1360 } 1361 1362 for (int ci = 0, ce = parent->GetNumChildren(); ci != ce; ++ci) { 1363 const bool can_create = true; 1364 ValueObjectSP child_sp = parent->GetChildAtIndex(ci, can_create); 1365 1366 if (!child_sp) { 1367 return ValueObjectSP(); 1368 } 1369 1370 int64_t child_offset = child_sp->GetByteOffset(); 1371 int64_t child_size = child_sp->GetByteSize(); 1372 1373 if (offset >= child_offset && offset < (child_offset + child_size)) { 1374 return GetValueForOffset(frame, child_sp, offset - child_offset); 1375 } 1376 } 1377 1378 if (offset == 0) { 1379 return parent; 1380 } else { 1381 return ValueObjectSP(); 1382 } 1383 } 1384 1385 ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame, 1386 ValueObjectSP &base, 1387 int64_t offset) { 1388 // base is a pointer to something 1389 // offset is the thing to add to the pointer 1390 // We return the most sensible ValueObject for the result of *(base+offset) 1391 1392 if (!base->IsPointerOrReferenceType()) { 1393 return ValueObjectSP(); 1394 } 1395 1396 Error error; 1397 ValueObjectSP pointee = base->Dereference(error); 1398 1399 if (!pointee) { 1400 return ValueObjectSP(); 1401 } 1402 1403 if (offset >= 0 && uint64_t(offset) >= pointee->GetByteSize()) { 1404 int64_t index = offset / pointee->GetByteSize(); 1405 offset = offset % pointee->GetByteSize(); 1406 const bool can_create = true; 1407 pointee = base->GetSyntheticArrayMember(index, can_create); 1408 } 1409 1410 if (!pointee || error.Fail()) { 1411 return ValueObjectSP(); 1412 } 1413 1414 return GetValueForOffset(frame, pointee, offset); 1415 } 1416 1417 //------------------------------------------------------------------ 1418 /// Attempt to reconstruct the ValueObject for the address contained in a 1419 /// given register plus an offset. 1420 /// 1421 /// @params [in] frame 1422 /// The current stack frame. 1423 /// 1424 /// @params [in] reg 1425 /// The register. 1426 /// 1427 /// @params [in] offset 1428 /// The offset from the register. 1429 /// 1430 /// @param [in] disassembler 1431 /// A disassembler containing instructions valid up to the current PC. 1432 /// 1433 /// @param [in] variables 1434 /// The variable list from the current frame, 1435 /// 1436 /// @param [in] pc 1437 /// The program counter for the instruction considered the 'user'. 1438 /// 1439 /// @return 1440 /// A string describing the base for the ExpressionPath. This could be a 1441 /// variable, a register value, an argument, or a function return value. 1442 /// The ValueObject if found. If valid, it has a valid ExpressionPath. 1443 //------------------------------------------------------------------ 1444 lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg, 1445 int64_t offset, Disassembler &disassembler, 1446 VariableList &variables, const Address &pc) { 1447 // Example of operation for Intel: 1448 // 1449 // +14: movq -0x8(%rbp), %rdi 1450 // +18: movq 0x8(%rdi), %rdi 1451 // +22: addl 0x4(%rdi), %eax 1452 // 1453 // f, a pointer to a struct, is known to be at -0x8(%rbp). 1454 // 1455 // DoGuessValueAt(frame, rdi, 4, dis, vars, 0x22) finds the instruction at +18 1456 // that assigns to rdi, and calls itself recursively for that dereference 1457 // DoGuessValueAt(frame, rdi, 8, dis, vars, 0x18) finds the instruction at 1458 // +14 that assigns to rdi, and calls itself recursively for that 1459 // derefernece 1460 // DoGuessValueAt(frame, rbp, -8, dis, vars, 0x14) finds "f" in the 1461 // variable list. 1462 // Returns a ValueObject for f. (That's what was stored at rbp-8 at +14) 1463 // Returns a ValueObject for *(f+8) or f->b (That's what was stored at rdi+8 1464 // at +18) 1465 // Returns a ValueObject for *(f->b+4) or f->b->a (That's what was stored at 1466 // rdi+4 at +22) 1467 1468 // First, check the variable list to see if anything is at the specified 1469 // location. 1470 1471 using namespace OperandMatchers; 1472 1473 const RegisterInfo *reg_info = 1474 frame.GetRegisterContext()->GetRegisterInfoByName(reg.AsCString()); 1475 if (!reg_info) { 1476 return ValueObjectSP(); 1477 } 1478 1479 Instruction::Operand op = 1480 offset ? Instruction::Operand::BuildDereference( 1481 Instruction::Operand::BuildSum( 1482 Instruction::Operand::BuildRegister(reg), 1483 Instruction::Operand::BuildImmediate(offset))) 1484 : Instruction::Operand::BuildDereference( 1485 Instruction::Operand::BuildRegister(reg)); 1486 1487 for (size_t vi = 0, ve = variables.GetSize(); vi != ve; ++vi) { 1488 VariableSP var_sp = variables.GetVariableAtIndex(vi); 1489 if (var_sp->LocationExpression().MatchesOperand(frame, op)) { 1490 return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues); 1491 } 1492 } 1493 1494 const uint32_t current_inst = 1495 disassembler.GetInstructionList().GetIndexOfInstructionAtAddress(pc); 1496 if (current_inst == UINT32_MAX) { 1497 return ValueObjectSP(); 1498 } 1499 1500 for (uint32_t ii = current_inst - 1; ii != (uint32_t)-1; --ii) { 1501 // This is not an exact algorithm, and it sacrifices accuracy for 1502 // generality. Recognizing "mov" and "ld" instructions –– and which are 1503 // their source and destination operands -- is something the disassembler 1504 // should do for us. 1505 InstructionSP instruction_sp = 1506 disassembler.GetInstructionList().GetInstructionAtIndex(ii); 1507 1508 if (instruction_sp->IsCall()) { 1509 ABISP abi_sp = frame.CalculateProcess()->GetABI(); 1510 if (!abi_sp) { 1511 continue; 1512 } 1513 1514 const char *return_register_name; 1515 if (!abi_sp->GetPointerReturnRegister(return_register_name)) { 1516 continue; 1517 } 1518 1519 const RegisterInfo *return_register_info = 1520 frame.GetRegisterContext()->GetRegisterInfoByName( 1521 return_register_name); 1522 if (!return_register_info) { 1523 continue; 1524 } 1525 1526 int64_t offset = 0; 1527 1528 if (!MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference), 1529 MatchRegOp(*return_register_info))(op) && 1530 !MatchUnaryOp( 1531 MatchOpType(Instruction::Operand::Type::Dereference), 1532 MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), 1533 MatchRegOp(*return_register_info), 1534 FetchImmOp(offset)))(op)) { 1535 continue; 1536 } 1537 1538 llvm::SmallVector<Instruction::Operand, 1> operands; 1539 if (!instruction_sp->ParseOperands(operands) || operands.size() != 1) { 1540 continue; 1541 } 1542 1543 switch (operands[0].m_type) { 1544 default: 1545 break; 1546 case Instruction::Operand::Type::Immediate: { 1547 SymbolContext sc; 1548 Address load_address; 1549 if (!frame.CalculateTarget()->ResolveLoadAddress( 1550 operands[0].m_immediate, load_address)) { 1551 break; 1552 } 1553 frame.CalculateTarget()->GetImages().ResolveSymbolContextForAddress( 1554 load_address, eSymbolContextFunction, sc); 1555 if (!sc.function) { 1556 break; 1557 } 1558 CompilerType function_type = sc.function->GetCompilerType(); 1559 if (!function_type.IsFunctionType()) { 1560 break; 1561 } 1562 CompilerType return_type = function_type.GetFunctionReturnType(); 1563 RegisterValue return_value; 1564 if (!frame.GetRegisterContext()->ReadRegister(return_register_info, 1565 return_value)) { 1566 break; 1567 } 1568 std::string name_str( 1569 sc.function->GetName().AsCString("<unknown function>")); 1570 name_str.append("()"); 1571 Address return_value_address(return_value.GetAsUInt64()); 1572 ValueObjectSP return_value_sp = ValueObjectMemory::Create( 1573 &frame, name_str, return_value_address, return_type); 1574 return GetValueForDereferincingOffset(frame, return_value_sp, offset); 1575 } 1576 } 1577 1578 continue; 1579 } 1580 1581 llvm::SmallVector<Instruction::Operand, 2> operands; 1582 if (!instruction_sp->ParseOperands(operands) || operands.size() != 2) { 1583 continue; 1584 } 1585 1586 Instruction::Operand *origin_operand = nullptr; 1587 auto clobbered_reg_matcher = [reg_info](const Instruction::Operand &op) { 1588 return MatchRegOp(*reg_info)(op) && op.m_clobbered; 1589 }; 1590 1591 if (clobbered_reg_matcher(operands[0])) { 1592 origin_operand = &operands[1]; 1593 } 1594 else if (clobbered_reg_matcher(operands[1])) { 1595 origin_operand = &operands[0]; 1596 } 1597 else { 1598 continue; 1599 } 1600 1601 // We have an origin operand. Can we track its value down? 1602 ValueObjectSP source_path; 1603 ConstString origin_register; 1604 int64_t origin_offset = 0; 1605 1606 if (FetchRegOp(origin_register)(*origin_operand)) { 1607 source_path = DoGuessValueAt(frame, origin_register, 0, disassembler, 1608 variables, instruction_sp->GetAddress()); 1609 } else if (MatchUnaryOp( 1610 MatchOpType(Instruction::Operand::Type::Dereference), 1611 FetchRegOp(origin_register))(*origin_operand) || 1612 MatchUnaryOp( 1613 MatchOpType(Instruction::Operand::Type::Dereference), 1614 MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), 1615 FetchRegOp(origin_register), 1616 FetchImmOp(origin_offset)))(*origin_operand)) { 1617 source_path = 1618 DoGuessValueAt(frame, origin_register, origin_offset, disassembler, 1619 variables, instruction_sp->GetAddress()); 1620 if (!source_path) { 1621 continue; 1622 } 1623 source_path = 1624 GetValueForDereferincingOffset(frame, source_path, offset); 1625 } 1626 1627 if (source_path) { 1628 return source_path; 1629 } 1630 } 1631 1632 return ValueObjectSP(); 1633 } 1634 } 1635 1636 lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg, 1637 int64_t offset) { 1638 TargetSP target_sp = CalculateTarget(); 1639 1640 const ArchSpec &target_arch = target_sp->GetArchitecture(); 1641 1642 Block *frame_block = GetFrameBlock(); 1643 1644 if (!frame_block) { 1645 return ValueObjectSP(); 1646 } 1647 1648 Function *function = frame_block->CalculateSymbolContextFunction(); 1649 if (!function) { 1650 return ValueObjectSP(); 1651 } 1652 1653 AddressRange pc_range = function->GetAddressRange(); 1654 1655 if (GetFrameCodeAddress().GetFileAddress() < 1656 pc_range.GetBaseAddress().GetFileAddress() || 1657 GetFrameCodeAddress().GetFileAddress() - 1658 pc_range.GetBaseAddress().GetFileAddress() >= 1659 pc_range.GetByteSize()) { 1660 return ValueObjectSP(); 1661 } 1662 1663 ExecutionContext exe_ctx(shared_from_this()); 1664 1665 const char *plugin_name = nullptr; 1666 const char *flavor = nullptr; 1667 const bool prefer_file_cache = false; 1668 DisassemblerSP disassembler_sp = Disassembler::DisassembleRange( 1669 target_arch, plugin_name, flavor, exe_ctx, pc_range, prefer_file_cache); 1670 1671 if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) { 1672 return ValueObjectSP(); 1673 } 1674 1675 const bool get_file_globals = false; 1676 VariableList *variables = GetVariableList(get_file_globals); 1677 1678 if (!variables) { 1679 return ValueObjectSP(); 1680 } 1681 1682 return DoGuessValueAt(*this, reg, offset, *disassembler_sp, *variables, 1683 GetFrameCodeAddress()); 1684 } 1685 1686 TargetSP StackFrame::CalculateTarget() { 1687 TargetSP target_sp; 1688 ThreadSP thread_sp(GetThread()); 1689 if (thread_sp) { 1690 ProcessSP process_sp(thread_sp->CalculateProcess()); 1691 if (process_sp) 1692 target_sp = process_sp->CalculateTarget(); 1693 } 1694 return target_sp; 1695 } 1696 1697 ProcessSP StackFrame::CalculateProcess() { 1698 ProcessSP process_sp; 1699 ThreadSP thread_sp(GetThread()); 1700 if (thread_sp) 1701 process_sp = thread_sp->CalculateProcess(); 1702 return process_sp; 1703 } 1704 1705 ThreadSP StackFrame::CalculateThread() { return GetThread(); } 1706 1707 StackFrameSP StackFrame::CalculateStackFrame() { return shared_from_this(); } 1708 1709 void StackFrame::CalculateExecutionContext(ExecutionContext &exe_ctx) { 1710 exe_ctx.SetContext(shared_from_this()); 1711 } 1712 1713 void StackFrame::DumpUsingSettingsFormat(Stream *strm, 1714 const char *frame_marker) { 1715 if (strm == nullptr) 1716 return; 1717 1718 GetSymbolContext(eSymbolContextEverything); 1719 ExecutionContext exe_ctx(shared_from_this()); 1720 StreamString s; 1721 1722 if (frame_marker) 1723 s.PutCString(frame_marker); 1724 1725 const FormatEntity::Entry *frame_format = nullptr; 1726 Target *target = exe_ctx.GetTargetPtr(); 1727 if (target) 1728 frame_format = target->GetDebugger().GetFrameFormat(); 1729 if (frame_format && FormatEntity::Format(*frame_format, s, &m_sc, &exe_ctx, 1730 nullptr, nullptr, false, false)) { 1731 strm->PutCString(s.GetString()); 1732 } else { 1733 Dump(strm, true, false); 1734 strm->EOL(); 1735 } 1736 } 1737 1738 void StackFrame::Dump(Stream *strm, bool show_frame_index, 1739 bool show_fullpaths) { 1740 if (strm == nullptr) 1741 return; 1742 1743 if (show_frame_index) 1744 strm->Printf("frame #%u: ", m_frame_index); 1745 ExecutionContext exe_ctx(shared_from_this()); 1746 Target *target = exe_ctx.GetTargetPtr(); 1747 strm->Printf("0x%0*" PRIx64 " ", 1748 target ? (target->GetArchitecture().GetAddressByteSize() * 2) 1749 : 16, 1750 GetFrameCodeAddress().GetLoadAddress(target)); 1751 GetSymbolContext(eSymbolContextEverything); 1752 const bool show_module = true; 1753 const bool show_inline = true; 1754 const bool show_function_arguments = true; 1755 const bool show_function_name = true; 1756 m_sc.DumpStopContext(strm, exe_ctx.GetBestExecutionContextScope(), 1757 GetFrameCodeAddress(), show_fullpaths, show_module, 1758 show_inline, show_function_arguments, 1759 show_function_name); 1760 } 1761 1762 void StackFrame::UpdateCurrentFrameFromPreviousFrame(StackFrame &prev_frame) { 1763 std::lock_guard<std::recursive_mutex> guard(m_mutex); 1764 assert(GetStackID() == 1765 prev_frame.GetStackID()); // TODO: remove this after some testing 1766 m_variable_list_sp = prev_frame.m_variable_list_sp; 1767 m_variable_list_value_objects.Swap(prev_frame.m_variable_list_value_objects); 1768 if (!m_disassembly.GetString().empty()) { 1769 m_disassembly.Clear(); 1770 m_disassembly.PutCString(prev_frame.m_disassembly.GetString()); 1771 } 1772 } 1773 1774 void StackFrame::UpdatePreviousFrameFromCurrentFrame(StackFrame &curr_frame) { 1775 std::lock_guard<std::recursive_mutex> guard(m_mutex); 1776 assert(GetStackID() == 1777 curr_frame.GetStackID()); // TODO: remove this after some testing 1778 m_id.SetPC(curr_frame.m_id.GetPC()); // Update the Stack ID PC value 1779 assert(GetThread() == curr_frame.GetThread()); 1780 m_frame_index = curr_frame.m_frame_index; 1781 m_concrete_frame_index = curr_frame.m_concrete_frame_index; 1782 m_reg_context_sp = curr_frame.m_reg_context_sp; 1783 m_frame_code_addr = curr_frame.m_frame_code_addr; 1784 assert(!m_sc.target_sp || !curr_frame.m_sc.target_sp || 1785 m_sc.target_sp.get() == curr_frame.m_sc.target_sp.get()); 1786 assert(!m_sc.module_sp || !curr_frame.m_sc.module_sp || 1787 m_sc.module_sp.get() == curr_frame.m_sc.module_sp.get()); 1788 assert(m_sc.comp_unit == nullptr || curr_frame.m_sc.comp_unit == nullptr || 1789 m_sc.comp_unit == curr_frame.m_sc.comp_unit); 1790 assert(m_sc.function == nullptr || curr_frame.m_sc.function == nullptr || 1791 m_sc.function == curr_frame.m_sc.function); 1792 m_sc = curr_frame.m_sc; 1793 m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything); 1794 m_flags.Set(m_sc.GetResolvedMask()); 1795 m_frame_base.Clear(); 1796 m_frame_base_error.Clear(); 1797 } 1798 1799 bool StackFrame::HasCachedData() const { 1800 if (m_variable_list_sp) 1801 return true; 1802 if (m_variable_list_value_objects.GetSize() > 0) 1803 return true; 1804 if (!m_disassembly.GetString().empty()) 1805 return true; 1806 return false; 1807 } 1808 1809 bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source, 1810 const char *frame_marker) { 1811 1812 if (show_frame_info) { 1813 strm.Indent(); 1814 DumpUsingSettingsFormat(&strm, frame_marker); 1815 } 1816 1817 if (show_source) { 1818 ExecutionContext exe_ctx(shared_from_this()); 1819 bool have_source = false, have_debuginfo = false; 1820 Debugger::StopDisassemblyType disasm_display = 1821 Debugger::eStopDisassemblyTypeNever; 1822 Target *target = exe_ctx.GetTargetPtr(); 1823 if (target) { 1824 Debugger &debugger = target->GetDebugger(); 1825 const uint32_t source_lines_before = 1826 debugger.GetStopSourceLineCount(true); 1827 const uint32_t source_lines_after = 1828 debugger.GetStopSourceLineCount(false); 1829 disasm_display = debugger.GetStopDisassemblyDisplay(); 1830 1831 GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry); 1832 if (m_sc.comp_unit && m_sc.line_entry.IsValid()) { 1833 have_debuginfo = true; 1834 if (source_lines_before > 0 || source_lines_after > 0) { 1835 size_t num_lines = 1836 target->GetSourceManager().DisplaySourceLinesWithLineNumbers( 1837 m_sc.line_entry.file, m_sc.line_entry.line, 1838 m_sc.line_entry.column, source_lines_before, 1839 source_lines_after, "->", &strm); 1840 if (num_lines != 0) 1841 have_source = true; 1842 // TODO: Give here a one time warning if source file is missing. 1843 } 1844 } 1845 switch (disasm_display) { 1846 case Debugger::eStopDisassemblyTypeNever: 1847 break; 1848 1849 case Debugger::eStopDisassemblyTypeNoDebugInfo: 1850 if (have_debuginfo) 1851 break; 1852 LLVM_FALLTHROUGH; 1853 1854 case Debugger::eStopDisassemblyTypeNoSource: 1855 if (have_source) 1856 break; 1857 LLVM_FALLTHROUGH; 1858 1859 case Debugger::eStopDisassemblyTypeAlways: 1860 if (target) { 1861 const uint32_t disasm_lines = debugger.GetDisassemblyLineCount(); 1862 if (disasm_lines > 0) { 1863 const ArchSpec &target_arch = target->GetArchitecture(); 1864 AddressRange pc_range; 1865 pc_range.GetBaseAddress() = GetFrameCodeAddress(); 1866 pc_range.SetByteSize(disasm_lines * 1867 target_arch.GetMaximumOpcodeByteSize()); 1868 const char *plugin_name = nullptr; 1869 const char *flavor = nullptr; 1870 const bool mixed_source_and_assembly = false; 1871 Disassembler::Disassemble( 1872 target->GetDebugger(), target_arch, plugin_name, flavor, 1873 exe_ctx, pc_range, disasm_lines, mixed_source_and_assembly, 0, 1874 Disassembler::eOptionMarkPCAddress, strm); 1875 } 1876 } 1877 break; 1878 } 1879 } 1880 } 1881 return true; 1882 } 1883