StackFrame.cpp revision be9875dc16a839be592110d9de6dc2c9285c5b61
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#include "lldb/Target/StackFrame.h" 11 12// C Includes 13// C++ Includes 14// Other libraries and framework includes 15// Project includes 16#include "lldb/Core/Module.h" 17#include "lldb/Core/Debugger.h" 18#include "lldb/Core/Disassembler.h" 19#include "lldb/Core/Value.h" 20#include "lldb/Core/ValueObjectVariable.h" 21#include "lldb/Core/ValueObjectConstResult.h" 22#include "lldb/Symbol/Function.h" 23#include "lldb/Symbol/VariableList.h" 24#include "lldb/Target/ExecutionContext.h" 25#include "lldb/Target/Process.h" 26#include "lldb/Target/RegisterContext.h" 27#include "lldb/Target/Target.h" 28#include "lldb/Target/Thread.h" 29 30using namespace lldb; 31using namespace lldb_private; 32 33// The first bits in the flags are reserved for the SymbolContext::Scope bits 34// so we know if we have tried to look up information in our internal symbol 35// context (m_sc) already. 36#define RESOLVED_FRAME_CODE_ADDR (uint32_t(eSymbolContextEverything + 1)) 37#define RESOLVED_FRAME_ID_SYMBOL_SCOPE (RESOLVED_FRAME_CODE_ADDR << 1) 38#define GOT_FRAME_BASE (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1) 39#define RESOLVED_VARIABLES (GOT_FRAME_BASE << 1) 40#define RESOLVED_GLOBAL_VARIABLES (RESOLVED_VARIABLES << 1) 41 42StackFrame::StackFrame (user_id_t frame_idx, 43 user_id_t unwind_frame_index, 44 Thread &thread, 45 addr_t cfa, 46 addr_t pc, 47 const SymbolContext *sc_ptr) : 48 m_thread (thread), 49 m_frame_index (frame_idx), 50 m_concrete_frame_index (unwind_frame_index), 51 m_reg_context_sp (), 52 m_id (pc, cfa, NULL), 53 m_frame_code_addr (NULL, pc), 54 m_sc (), 55 m_flags (), 56 m_frame_base (), 57 m_frame_base_error (), 58 m_variable_list_sp (), 59 m_variable_list_value_objects (), 60 m_disassembly () 61{ 62 if (sc_ptr != NULL) 63 { 64 m_sc = *sc_ptr; 65 m_flags.Set(m_sc.GetResolvedMask ()); 66 } 67} 68 69StackFrame::StackFrame (user_id_t frame_idx, 70 user_id_t unwind_frame_index, 71 Thread &thread, 72 const RegisterContextSP ®_context_sp, 73 addr_t cfa, 74 addr_t pc, 75 const SymbolContext *sc_ptr) : 76 m_thread (thread), 77 m_frame_index (frame_idx), 78 m_concrete_frame_index (unwind_frame_index), 79 m_reg_context_sp (reg_context_sp), 80 m_id (pc, cfa, NULL), 81 m_frame_code_addr (NULL, pc), 82 m_sc (), 83 m_flags (), 84 m_frame_base (), 85 m_frame_base_error (), 86 m_variable_list_sp (), 87 m_variable_list_value_objects (), 88 m_disassembly () 89{ 90 if (sc_ptr != NULL) 91 { 92 m_sc = *sc_ptr; 93 m_flags.Set(m_sc.GetResolvedMask ()); 94 } 95 96 if (reg_context_sp && !m_sc.target_sp) 97 { 98 m_sc.target_sp = reg_context_sp->GetThread().GetProcess().GetTarget().GetSP(); 99 m_flags.Set (eSymbolContextTarget); 100 } 101} 102 103StackFrame::StackFrame (user_id_t frame_idx, 104 user_id_t unwind_frame_index, 105 Thread &thread, 106 const RegisterContextSP ®_context_sp, 107 addr_t cfa, 108 const Address& pc_addr, 109 const SymbolContext *sc_ptr) : 110 m_thread (thread), 111 m_frame_index (frame_idx), 112 m_concrete_frame_index (unwind_frame_index), 113 m_reg_context_sp (reg_context_sp), 114 m_id (pc_addr.GetLoadAddress (&thread.GetProcess().GetTarget()), cfa, NULL), 115 m_frame_code_addr (pc_addr), 116 m_sc (), 117 m_flags (), 118 m_frame_base (), 119 m_frame_base_error (), 120 m_variable_list_sp (), 121 m_variable_list_value_objects (), 122 m_disassembly () 123{ 124 if (sc_ptr != NULL) 125 { 126 m_sc = *sc_ptr; 127 m_flags.Set(m_sc.GetResolvedMask ()); 128 } 129 130 if (m_sc.target_sp.get() == NULL && reg_context_sp) 131 { 132 m_sc.target_sp = reg_context_sp->GetThread().GetProcess().GetTarget().GetSP(); 133 m_flags.Set (eSymbolContextTarget); 134 } 135 136 Module *pc_module = pc_addr.GetModule(); 137 if (m_sc.module_sp.get() == NULL || m_sc.module_sp.get() != pc_module) 138 { 139 if (pc_module) 140 { 141 m_sc.module_sp = pc_module; 142 m_flags.Set (eSymbolContextModule); 143 } 144 else 145 { 146 m_sc.module_sp.reset(); 147 } 148 149 } 150} 151 152 153//---------------------------------------------------------------------- 154// Destructor 155//---------------------------------------------------------------------- 156StackFrame::~StackFrame() 157{ 158} 159 160StackID& 161StackFrame::GetStackID() 162{ 163 // Make sure we have resolved the StackID object's symbol context scope if 164 // we already haven't looked it up. 165 166 if (m_flags.IsClear (RESOLVED_FRAME_ID_SYMBOL_SCOPE)) 167 { 168 if (m_id.GetSymbolContextScope ()) 169 { 170 // We already have a symbol context scope, we just don't have our 171 // flag bit set. 172 m_flags.Set (RESOLVED_FRAME_ID_SYMBOL_SCOPE); 173 } 174 else 175 { 176 // Calculate the frame block and use this for the stack ID symbol 177 // context scope if we have one. 178 SymbolContextScope *scope = GetFrameBlock (); 179 if (scope == NULL) 180 { 181 // We don't have a block, so use the symbol 182 if (m_flags.IsClear (eSymbolContextSymbol)) 183 GetSymbolContext (eSymbolContextSymbol); 184 185 // It is ok if m_sc.symbol is NULL here 186 scope = m_sc.symbol; 187 } 188 // Set the symbol context scope (the accessor will set the 189 // RESOLVED_FRAME_ID_SYMBOL_SCOPE bit in m_flags). 190 SetSymbolContextScope (scope); 191 } 192 } 193 return m_id; 194} 195 196void 197StackFrame::SetSymbolContextScope (SymbolContextScope *symbol_scope) 198{ 199 m_flags.Set (RESOLVED_FRAME_ID_SYMBOL_SCOPE); 200 m_id.SetSymbolContextScope (symbol_scope); 201} 202 203const Address& 204StackFrame::GetFrameCodeAddress() 205{ 206 if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) && !m_frame_code_addr.IsSectionOffset()) 207 { 208 m_flags.Set (RESOLVED_FRAME_CODE_ADDR); 209 210 // Resolve the PC into a temporary address because if ResolveLoadAddress 211 // fails to resolve the address, it will clear the address object... 212 213 if (m_frame_code_addr.SetOpcodeLoadAddress (m_frame_code_addr.GetOffset(), &m_thread.GetProcess().GetTarget())) 214 { 215 const Section *section = m_frame_code_addr.GetSection(); 216 if (section) 217 { 218 Module *module = section->GetModule(); 219 if (module) 220 { 221 m_sc.module_sp = module; 222 if (m_sc.module_sp) 223 m_flags.Set(eSymbolContextModule); 224 } 225 } 226 } 227 } 228 return m_frame_code_addr; 229} 230 231void 232StackFrame::ChangePC (addr_t pc) 233{ 234 m_frame_code_addr.SetOffset(pc); 235 m_frame_code_addr.SetSection(NULL); 236 m_sc.Clear(); 237 m_flags.Reset(0); 238 m_thread.ClearStackFrames (); 239} 240 241const char * 242StackFrame::Disassemble () 243{ 244 if (m_disassembly.GetSize() == 0) 245 { 246 ExecutionContext exe_ctx; 247 CalculateExecutionContext(exe_ctx); 248 Target &target = m_thread.GetProcess().GetTarget(); 249 Disassembler::Disassemble (target.GetDebugger(), 250 target.GetArchitecture(), 251 NULL, 252 exe_ctx, 253 0, 254 0, 255 0, 256 m_disassembly); 257 if (m_disassembly.GetSize() == 0) 258 return NULL; 259 } 260 return m_disassembly.GetData(); 261} 262 263Block * 264StackFrame::GetFrameBlock () 265{ 266 if (m_sc.block == NULL && m_flags.IsClear (eSymbolContextBlock)) 267 GetSymbolContext (eSymbolContextBlock); 268 269 if (m_sc.block) 270 { 271 Block *inline_block = m_sc.block->GetContainingInlinedBlock(); 272 if (inline_block) 273 { 274 // Use the block with the inlined function info 275 // as the frame block we want this frame to have only the variables 276 // for the inlined function and its non-inlined block child blocks. 277 return inline_block; 278 } 279 else 280 { 281 // This block is not contained withing any inlined function blocks 282 // with so we want to use the top most function block. 283 return &m_sc.function->GetBlock (false); 284 } 285 } 286 return NULL; 287} 288 289//---------------------------------------------------------------------- 290// Get the symbol context if we already haven't done so by resolving the 291// PC address as much as possible. This way when we pass around a 292// StackFrame object, everyone will have as much information as 293// possible and no one will ever have to look things up manually. 294//---------------------------------------------------------------------- 295const SymbolContext& 296StackFrame::GetSymbolContext (uint32_t resolve_scope) 297{ 298 // Copy our internal symbol context into "sc". 299 if ((m_flags.Get() & resolve_scope) != resolve_scope) 300 { 301 // Resolve our PC to section offset if we haven't alreday done so 302 // and if we don't have a module. The resolved address section will 303 // contain the module to which it belongs 304 if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR)) 305 GetFrameCodeAddress(); 306 307 // If this is not frame zero, then we need to subtract 1 from the PC 308 // value when doing address lookups since the PC will be on the 309 // instruction following the function call instruction... 310 311 Address lookup_addr(GetFrameCodeAddress()); 312 if (m_frame_index > 0 && lookup_addr.IsValid()) 313 { 314 addr_t offset = lookup_addr.GetOffset(); 315 if (offset > 0) 316 lookup_addr.SetOffset(offset - 1); 317 } 318 319 320 uint32_t resolved = 0; 321 if (m_sc.module_sp) 322 { 323 // We have something in our stack frame symbol context, lets check 324 // if we haven't already tried to lookup one of those things. If we 325 // haven't then we will do the query. 326 327 uint32_t actual_resolve_scope = 0; 328 329 if (resolve_scope & eSymbolContextCompUnit) 330 { 331 if (m_flags.IsClear (eSymbolContextCompUnit)) 332 { 333 if (m_sc.comp_unit) 334 resolved |= eSymbolContextCompUnit; 335 else 336 actual_resolve_scope |= eSymbolContextCompUnit; 337 } 338 } 339 340 if (resolve_scope & eSymbolContextFunction) 341 { 342 if (m_flags.IsClear (eSymbolContextFunction)) 343 { 344 if (m_sc.function) 345 resolved |= eSymbolContextFunction; 346 else 347 actual_resolve_scope |= eSymbolContextFunction; 348 } 349 } 350 351 if (resolve_scope & eSymbolContextBlock) 352 { 353 if (m_flags.IsClear (eSymbolContextBlock)) 354 { 355 if (m_sc.block) 356 resolved |= eSymbolContextBlock; 357 else 358 actual_resolve_scope |= eSymbolContextBlock; 359 } 360 } 361 362 if (resolve_scope & eSymbolContextSymbol) 363 { 364 if (m_flags.IsClear (eSymbolContextSymbol)) 365 { 366 if (m_sc.symbol) 367 resolved |= eSymbolContextSymbol; 368 else 369 actual_resolve_scope |= eSymbolContextSymbol; 370 } 371 } 372 373 if (resolve_scope & eSymbolContextLineEntry) 374 { 375 if (m_flags.IsClear (eSymbolContextLineEntry)) 376 { 377 if (m_sc.line_entry.IsValid()) 378 resolved |= eSymbolContextLineEntry; 379 else 380 actual_resolve_scope |= eSymbolContextLineEntry; 381 } 382 } 383 384 if (actual_resolve_scope) 385 { 386 // We might be resolving less information than what is already 387 // in our current symbol context so resolve into a temporary 388 // symbol context "sc" so we don't clear out data we have 389 // already found in "m_sc" 390 SymbolContext sc; 391 // Set flags that indicate what we have tried to resolve 392 resolved |= m_sc.module_sp->ResolveSymbolContextForAddress (lookup_addr, actual_resolve_scope, sc); 393 // Only replace what we didn't already have as we may have 394 // information for an inlined function scope that won't match 395 // what a standard lookup by address would match 396 if ((resolved & eSymbolContextCompUnit) && m_sc.comp_unit == NULL) 397 m_sc.comp_unit = sc.comp_unit; 398 if ((resolved & eSymbolContextFunction) && m_sc.function == NULL) 399 m_sc.function = sc.function; 400 if ((resolved & eSymbolContextBlock) && m_sc.block == NULL) 401 m_sc.block = sc.block; 402 if ((resolved & eSymbolContextSymbol) && m_sc.symbol == NULL) 403 m_sc.symbol = sc.symbol; 404 if ((resolved & eSymbolContextLineEntry) && !m_sc.line_entry.IsValid()) 405 m_sc.line_entry = sc.line_entry; 406 407 } 408 } 409 else 410 { 411 // If we don't have a module, then we can't have the compile unit, 412 // function, block, line entry or symbol, so we can safely call 413 // ResolveSymbolContextForAddress with our symbol context member m_sc. 414 resolved |= m_thread.GetProcess().GetTarget().GetImages().ResolveSymbolContextForAddress (lookup_addr, resolve_scope, m_sc); 415 } 416 417 // If the target was requested add that: 418 if (m_sc.target_sp.get() == NULL) 419 { 420 m_sc.target_sp = CalculateProcess()->GetTarget().GetSP(); 421 if (m_sc.target_sp) 422 resolved |= eSymbolContextTarget; 423 } 424 425 // Update our internal flags so we remember what we have tried to locate so 426 // we don't have to keep trying when more calls to this function are made. 427 // We might have dug up more information that was requested (for example 428 // if we were asked to only get the block, we will have gotten the 429 // compile unit, and function) so set any additional bits that we resolved 430 m_flags.Set (resolve_scope | resolved); 431 } 432 433 // Return the symbol context with everything that was possible to resolve 434 // resolved. 435 return m_sc; 436} 437 438 439VariableList * 440StackFrame::GetVariableList (bool get_file_globals) 441{ 442 if (m_flags.IsClear(RESOLVED_VARIABLES)) 443 { 444 m_flags.Set(RESOLVED_VARIABLES); 445 446 Block *frame_block = GetFrameBlock(); 447 448 if (frame_block) 449 { 450 const bool get_child_variables = true; 451 const bool can_create = true; 452 const bool stop_if_child_block_is_inlined_function = true; 453 m_variable_list_sp.reset(new VariableList()); 454 frame_block->AppendBlockVariables(can_create, get_child_variables, stop_if_child_block_is_inlined_function, m_variable_list_sp.get()); 455 } 456 } 457 458 if (m_flags.IsClear(RESOLVED_GLOBAL_VARIABLES) && 459 get_file_globals) 460 { 461 m_flags.Set(RESOLVED_GLOBAL_VARIABLES); 462 463 if (m_flags.IsClear (eSymbolContextCompUnit)) 464 GetSymbolContext (eSymbolContextCompUnit); 465 466 if (m_sc.comp_unit) 467 { 468 VariableListSP global_variable_list_sp (m_sc.comp_unit->GetVariableList(true)); 469 if (m_variable_list_sp) 470 m_variable_list_sp->AddVariables (global_variable_list_sp.get()); 471 else 472 m_variable_list_sp = global_variable_list_sp; 473 } 474 } 475 476 return m_variable_list_sp.get(); 477} 478 479VariableListSP 480StackFrame::GetInScopeVariableList (bool get_file_globals) 481{ 482 VariableListSP var_list_sp(new VariableList); 483 GetSymbolContext (eSymbolContextCompUnit | eSymbolContextBlock); 484 485 if (m_sc.block) 486 { 487 const bool can_create = true; 488 const bool get_parent_variables = true; 489 const bool stop_if_block_is_inlined_function = true; 490 m_sc.block->AppendVariables (can_create, 491 get_parent_variables, 492 stop_if_block_is_inlined_function, 493 var_list_sp.get()); 494 } 495 496 if (m_sc.comp_unit) 497 { 498 VariableListSP global_variable_list_sp (m_sc.comp_unit->GetVariableList(true)); 499 if (global_variable_list_sp) 500 var_list_sp->AddVariables (global_variable_list_sp.get()); 501 } 502 503 return var_list_sp; 504} 505 506 507ValueObjectSP 508StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr, 509 DynamicValueType use_dynamic, 510 uint32_t options, 511 VariableSP &var_sp, 512 Error &error) 513{ 514 515 if (var_expr_cstr && var_expr_cstr[0]) 516 { 517 const bool check_ptr_vs_member = (options & eExpressionPathOptionCheckPtrVsMember) != 0; 518 const bool no_fragile_ivar = (options & eExpressionPathOptionsNoFragileObjcIvar) != 0; 519 const bool no_synth_child = (options & eExpressionPathOptionsNoSyntheticChildren) != 0; 520 //const bool no_synth_array = (options & eExpressionPathOptionsNoSyntheticArrayRange) != 0; 521 error.Clear(); 522 bool deref = false; 523 bool address_of = false; 524 ValueObjectSP valobj_sp; 525 const bool get_file_globals = true; 526 // When looking up a variable for an expression, we need only consider the 527 // variables that are in scope. 528 VariableListSP var_list_sp (GetInScopeVariableList (get_file_globals)); 529 VariableList *variable_list = var_list_sp.get(); 530 531 if (variable_list) 532 { 533 // If first character is a '*', then show pointer contents 534 const char *var_expr = var_expr_cstr; 535 if (var_expr[0] == '*') 536 { 537 deref = true; 538 var_expr++; // Skip the '*' 539 } 540 else if (var_expr[0] == '&') 541 { 542 address_of = true; 543 var_expr++; // Skip the '&' 544 } 545 546 std::string var_path (var_expr); 547 size_t separator_idx = var_path.find_first_of(".-[=+~|&^%#@!/?,<>{}"); 548 StreamString var_expr_path_strm; 549 550 ConstString name_const_string; 551 if (separator_idx == std::string::npos) 552 name_const_string.SetCString (var_path.c_str()); 553 else 554 name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx); 555 556 var_sp = variable_list->FindVariable(name_const_string); 557 if (var_sp) 558 { 559 valobj_sp = GetValueObjectForFrameVariable (var_sp, use_dynamic); 560 if (!valobj_sp) 561 return valobj_sp; 562 563 var_path.erase (0, name_const_string.GetLength ()); 564 // We are dumping at least one child 565 while (separator_idx != std::string::npos) 566 { 567 // Calculate the next separator index ahead of time 568 ValueObjectSP child_valobj_sp; 569 const char separator_type = var_path[0]; 570 switch (separator_type) 571 { 572 573 case '-': 574 if (var_path.size() >= 2 && var_path[1] != '>') 575 return ValueObjectSP(); 576 577 if (no_fragile_ivar) 578 { 579 // Make sure we aren't trying to deref an objective 580 // C ivar if this is not allowed 581 const uint32_t pointer_type_flags = ClangASTContext::GetTypeInfo (valobj_sp->GetClangType(), NULL, NULL); 582 if ((pointer_type_flags & ClangASTContext::eTypeIsObjC) && 583 (pointer_type_flags & ClangASTContext::eTypeIsPointer)) 584 { 585 // This was an objective C object pointer and 586 // it was requested we skip any fragile ivars 587 // so return nothing here 588 return ValueObjectSP(); 589 } 590 } 591 var_path.erase (0, 1); // Remove the '-' 592 // Fall through 593 case '.': 594 { 595 const bool expr_is_ptr = var_path[0] == '>'; 596 597 var_path.erase (0, 1); // Remove the '.' or '>' 598 separator_idx = var_path.find_first_of(".-["); 599 ConstString child_name; 600 if (separator_idx == std::string::npos) 601 child_name.SetCString (var_path.c_str()); 602 else 603 child_name.SetCStringWithLength(var_path.c_str(), separator_idx); 604 605 if (check_ptr_vs_member) 606 { 607 // We either have a pointer type and need to verify 608 // valobj_sp is a pointer, or we have a member of a 609 // class/union/struct being accessed with the . syntax 610 // and need to verify we don't have a pointer. 611 const bool actual_is_ptr = valobj_sp->IsPointerType (); 612 613 if (actual_is_ptr != expr_is_ptr) 614 { 615 // Incorrect use of "." with a pointer, or "->" with 616 // a class/union/struct instance or reference. 617 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 618 if (actual_is_ptr) 619 error.SetErrorStringWithFormat ("\"%s\" is a pointer and . was used to attempt to access \"%s\". Did you mean \"%s->%s\"?", 620 var_expr_path_strm.GetString().c_str(), 621 child_name.GetCString(), 622 var_expr_path_strm.GetString().c_str(), 623 var_path.c_str()); 624 else 625 error.SetErrorStringWithFormat ("\"%s\" is not a pointer and -> was used to attempt to access \"%s\". Did you mean \"%s.%s\"?", 626 var_expr_path_strm.GetString().c_str(), 627 child_name.GetCString(), 628 var_expr_path_strm.GetString().c_str(), 629 var_path.c_str()); 630 return ValueObjectSP(); 631 } 632 } 633 child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true); 634 if (!child_valobj_sp) 635 { 636 if (no_synth_child == false) 637 child_valobj_sp = valobj_sp->GetSyntheticValue(eUseSyntheticFilter)->GetChildMemberWithName (child_name, true); 638 639 if (no_synth_child || !child_valobj_sp) 640 { 641 // No child member with name "child_name" 642 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 643 if (child_name) 644 { 645 error.SetErrorStringWithFormat ("\"%s\" is not a member of \"(%s) %s\"", 646 child_name.GetCString(), 647 valobj_sp->GetTypeName().AsCString("<invalid type>"), 648 var_expr_path_strm.GetString().c_str()); 649 } 650 else 651 { 652 error.SetErrorStringWithFormat ("incomplete expression path after \"%s\" in \"%s\"", 653 var_expr_path_strm.GetString().c_str(), 654 var_expr_cstr); 655 } 656 return ValueObjectSP(); 657 } 658 } 659 // Remove the child name from the path 660 var_path.erase(0, child_name.GetLength()); 661 if (use_dynamic != eNoDynamicValues) 662 { 663 ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(use_dynamic)); 664 if (dynamic_value_sp) 665 child_valobj_sp = dynamic_value_sp; 666 } 667 } 668 break; 669 670 case '[': 671 // Array member access, or treating pointer as an array 672 if (var_path.size() > 2) // Need at least two brackets and a number 673 { 674 char *end = NULL; 675 long child_index = ::strtol (&var_path[1], &end, 0); 676 if (end && *end == ']' 677 && *(end-1) != '[') // this code forces an error in the case of arr[]. as bitfield[] is not a good syntax we're good to go 678 { 679 if (ClangASTContext::IsPointerToScalarType(valobj_sp->GetClangType()) && deref) 680 { 681 // what we have is *ptr[low]. the most similar C++ syntax is to deref ptr 682 // and extract bit low out of it. reading array item low 683 // would be done by saying ptr[low], without a deref * sign 684 Error error; 685 ValueObjectSP temp(valobj_sp->Dereference(error)); 686 if (error.Fail()) 687 { 688 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 689 error.SetErrorStringWithFormat ("could not dereference \"(%s) %s\"", 690 valobj_sp->GetTypeName().AsCString("<invalid type>"), 691 var_expr_path_strm.GetString().c_str()); 692 return ValueObjectSP(); 693 } 694 valobj_sp = temp; 695 deref = false; 696 } 697 else if (ClangASTContext::IsArrayOfScalarType(valobj_sp->GetClangType()) && deref) 698 { 699 // what we have is *arr[low]. the most similar C++ syntax is to get arr[0] 700 // (an operation that is equivalent to deref-ing arr) 701 // and extract bit low out of it. reading array item low 702 // would be done by saying arr[low], without a deref * sign 703 Error error; 704 ValueObjectSP temp(valobj_sp->GetChildAtIndex (0, true)); 705 if (error.Fail()) 706 { 707 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 708 error.SetErrorStringWithFormat ("could not get item 0 for \"(%s) %s\"", 709 valobj_sp->GetTypeName().AsCString("<invalid type>"), 710 var_expr_path_strm.GetString().c_str()); 711 return ValueObjectSP(); 712 } 713 valobj_sp = temp; 714 deref = false; 715 } 716 717 if (valobj_sp->IsPointerType ()) 718 { 719 if (no_synth_child == false 720 && 721 ClangASTType::GetMinimumLanguage(valobj_sp->GetClangAST(), 722 valobj_sp->GetClangType()) == eLanguageTypeObjC /* is ObjC pointer */ 723 && 724 ClangASTContext::IsPointerType(ClangASTType::GetPointeeType(valobj_sp->GetClangType())) == false /* is not double-ptr */) 725 { 726 // dereferencing ObjC variables is not valid.. so let's try and recur to synthetic children 727 ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(eUseSyntheticFilter); 728 if (synthetic.get() == NULL /* no synthetic */ 729 || synthetic == valobj_sp) /* synthetic is the same as the original object */ 730 { 731 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 732 error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type", 733 valobj_sp->GetTypeName().AsCString("<invalid type>"), 734 var_expr_path_strm.GetString().c_str()); 735 } 736 else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */) 737 { 738 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 739 error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"", 740 child_index, 741 valobj_sp->GetTypeName().AsCString("<invalid type>"), 742 var_expr_path_strm.GetString().c_str()); 743 } 744 else 745 { 746 child_valobj_sp = synthetic->GetChildAtIndex(child_index, true); 747 if (!child_valobj_sp) 748 { 749 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 750 error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"", 751 child_index, 752 valobj_sp->GetTypeName().AsCString("<invalid type>"), 753 var_expr_path_strm.GetString().c_str()); 754 } 755 } 756 } 757 else 758 { 759 child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true); 760 if (!child_valobj_sp) 761 { 762 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 763 error.SetErrorStringWithFormat ("failed to use pointer as array for index %ld for \"(%s) %s\"", 764 child_index, 765 valobj_sp->GetTypeName().AsCString("<invalid type>"), 766 var_expr_path_strm.GetString().c_str()); 767 } 768 } 769 } 770 else if (ClangASTContext::IsArrayType (valobj_sp->GetClangType(), NULL, NULL)) 771 { 772 // Pass false to dynamic_value here so we can tell the difference between 773 // no dynamic value and no member of this type... 774 child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true); 775 if (!child_valobj_sp) 776 { 777 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 778 error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"", 779 child_index, 780 valobj_sp->GetTypeName().AsCString("<invalid type>"), 781 var_expr_path_strm.GetString().c_str()); 782 } 783 } 784 else if (ClangASTContext::IsScalarType(valobj_sp->GetClangType())) 785 { 786 // this is a bitfield asking to display just one bit 787 child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, child_index, true); 788 if (!child_valobj_sp) 789 { 790 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 791 error.SetErrorStringWithFormat ("bitfield range %ld-%ld is not valid for \"(%s) %s\"", 792 child_index, child_index, 793 valobj_sp->GetTypeName().AsCString("<invalid type>"), 794 var_expr_path_strm.GetString().c_str()); 795 } 796 } 797 else 798 { 799 ValueObjectSP synthetic = valobj_sp->GetSyntheticValue(eUseSyntheticFilter); 800 if (no_synth_child /* synthetic is forbidden */ || 801 synthetic.get() == NULL /* no synthetic */ 802 || synthetic == valobj_sp) /* synthetic is the same as the original object */ 803 { 804 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 805 error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type", 806 valobj_sp->GetTypeName().AsCString("<invalid type>"), 807 var_expr_path_strm.GetString().c_str()); 808 } 809 else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */) 810 { 811 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 812 error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"", 813 child_index, 814 valobj_sp->GetTypeName().AsCString("<invalid type>"), 815 var_expr_path_strm.GetString().c_str()); 816 } 817 else 818 { 819 child_valobj_sp = synthetic->GetChildAtIndex(child_index, true); 820 if (!child_valobj_sp) 821 { 822 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 823 error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"", 824 child_index, 825 valobj_sp->GetTypeName().AsCString("<invalid type>"), 826 var_expr_path_strm.GetString().c_str()); 827 } 828 } 829 } 830 831 if (!child_valobj_sp) 832 { 833 // Invalid array index... 834 return ValueObjectSP(); 835 } 836 837 // Erase the array member specification '[%i]' where 838 // %i is the array index 839 var_path.erase(0, (end - var_path.c_str()) + 1); 840 separator_idx = var_path.find_first_of(".-["); 841 if (use_dynamic != eNoDynamicValues) 842 { 843 ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(use_dynamic)); 844 if (dynamic_value_sp) 845 child_valobj_sp = dynamic_value_sp; 846 } 847 // Break out early from the switch since we were 848 // able to find the child member 849 break; 850 } 851 else if (end && *end == '-') 852 { 853 // this is most probably a BitField, let's take a look 854 char *real_end = NULL; 855 long final_index = ::strtol (end+1, &real_end, 0); 856 bool expand_bitfield = true; 857 if (real_end && *real_end == ']') 858 { 859 // if the format given is [high-low], swap range 860 if (child_index > final_index) 861 { 862 long temp = child_index; 863 child_index = final_index; 864 final_index = temp; 865 } 866 867 if (ClangASTContext::IsPointerToScalarType(valobj_sp->GetClangType()) && deref) 868 { 869 // what we have is *ptr[low-high]. the most similar C++ syntax is to deref ptr 870 // and extract bits low thru high out of it. reading array items low thru high 871 // would be done by saying ptr[low-high], without a deref * sign 872 Error error; 873 ValueObjectSP temp(valobj_sp->Dereference(error)); 874 if (error.Fail()) 875 { 876 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 877 error.SetErrorStringWithFormat ("could not dereference \"(%s) %s\"", 878 valobj_sp->GetTypeName().AsCString("<invalid type>"), 879 var_expr_path_strm.GetString().c_str()); 880 return ValueObjectSP(); 881 } 882 valobj_sp = temp; 883 deref = false; 884 } 885 else if (ClangASTContext::IsArrayOfScalarType(valobj_sp->GetClangType()) && deref) 886 { 887 // what we have is *arr[low-high]. the most similar C++ syntax is to get arr[0] 888 // (an operation that is equivalent to deref-ing arr) 889 // and extract bits low thru high out of it. reading array items low thru high 890 // would be done by saying arr[low-high], without a deref * sign 891 Error error; 892 ValueObjectSP temp(valobj_sp->GetChildAtIndex (0, true)); 893 if (error.Fail()) 894 { 895 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 896 error.SetErrorStringWithFormat ("could not get item 0 for \"(%s) %s\"", 897 valobj_sp->GetTypeName().AsCString("<invalid type>"), 898 var_expr_path_strm.GetString().c_str()); 899 return ValueObjectSP(); 900 } 901 valobj_sp = temp; 902 deref = false; 903 } 904 /*else if (valobj_sp->IsArrayType() || valobj_sp->IsPointerType()) 905 { 906 child_valobj_sp = valobj_sp->GetSyntheticArrayRangeChild(child_index, final_index, true); 907 expand_bitfield = false; 908 if (!child_valobj_sp) 909 { 910 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 911 error.SetErrorStringWithFormat ("array range %i-%i is not valid for \"(%s) %s\"", 912 child_index, final_index, 913 valobj_sp->GetTypeName().AsCString("<invalid type>"), 914 var_expr_path_strm.GetString().c_str()); 915 } 916 }*/ 917 918 if (expand_bitfield) 919 { 920 child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true); 921 if (!child_valobj_sp) 922 { 923 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 924 error.SetErrorStringWithFormat ("bitfield range %ld-%ld is not valid for \"(%s) %s\"", 925 child_index, final_index, 926 valobj_sp->GetTypeName().AsCString("<invalid type>"), 927 var_expr_path_strm.GetString().c_str()); 928 } 929 } 930 } 931 932 if (!child_valobj_sp) 933 { 934 // Invalid bitfield range... 935 return ValueObjectSP(); 936 } 937 938 // Erase the bitfield member specification '[%i-%i]' where 939 // %i is the index 940 var_path.erase(0, (real_end - var_path.c_str()) + 1); 941 separator_idx = var_path.find_first_of(".-["); 942 if (use_dynamic != eNoDynamicValues) 943 { 944 ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(use_dynamic)); 945 if (dynamic_value_sp) 946 child_valobj_sp = dynamic_value_sp; 947 } 948 // Break out early from the switch since we were 949 // able to find the child member 950 break; 951 952 } 953 } 954 else 955 { 956 error.SetErrorStringWithFormat("invalid square bracket encountered after \"%s\" in \"%s\"", 957 var_expr_path_strm.GetString().c_str(), 958 var_path.c_str()); 959 } 960 return ValueObjectSP(); 961 962 default: 963 // Failure... 964 { 965 valobj_sp->GetExpressionPath (var_expr_path_strm, false); 966 error.SetErrorStringWithFormat ("unexpected char '%c' encountered after \"%s\" in \"%s\"", 967 separator_type, 968 var_expr_path_strm.GetString().c_str(), 969 var_path.c_str()); 970 971 return ValueObjectSP(); 972 } 973 } 974 975 if (child_valobj_sp) 976 valobj_sp = child_valobj_sp; 977 978 if (var_path.empty()) 979 break; 980 981 } 982 if (valobj_sp) 983 { 984 if (deref) 985 { 986 ValueObjectSP deref_valobj_sp (valobj_sp->Dereference(error)); 987 valobj_sp = deref_valobj_sp; 988 } 989 else if (address_of) 990 { 991 ValueObjectSP address_of_valobj_sp (valobj_sp->AddressOf(error)); 992 valobj_sp = address_of_valobj_sp; 993 } 994 } 995 return valobj_sp; 996 } 997 else 998 { 999 error.SetErrorStringWithFormat("no variable named '%s' found in this frame", 1000 name_const_string.GetCString()); 1001 } 1002 } 1003 } 1004 else 1005 { 1006 error.SetErrorStringWithFormat("invalid variable path '%s'", var_expr_cstr); 1007 } 1008 return ValueObjectSP(); 1009} 1010 1011bool 1012StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr) 1013{ 1014 if (m_flags.IsClear(GOT_FRAME_BASE)) 1015 { 1016 if (m_sc.function) 1017 { 1018 m_frame_base.Clear(); 1019 m_frame_base_error.Clear(); 1020 1021 m_flags.Set(GOT_FRAME_BASE); 1022 ExecutionContext exe_ctx (&m_thread.GetProcess(), &m_thread, this); 1023 Value expr_value; 1024 addr_t loclist_base_addr = LLDB_INVALID_ADDRESS; 1025 if (m_sc.function->GetFrameBaseExpression().IsLocationList()) 1026 loclist_base_addr = m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (&m_thread.GetProcess().GetTarget()); 1027 1028 if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, NULL, NULL, NULL, loclist_base_addr, NULL, expr_value, &m_frame_base_error) == false) 1029 { 1030 // We should really have an error if evaluate returns, but in case 1031 // we don't, lets set the error to something at least. 1032 if (m_frame_base_error.Success()) 1033 m_frame_base_error.SetErrorString("Evaluation of the frame base expression failed."); 1034 } 1035 else 1036 { 1037 m_frame_base = expr_value.ResolveValue(&exe_ctx, NULL); 1038 } 1039 } 1040 else 1041 { 1042 m_frame_base_error.SetErrorString ("No function in symbol context."); 1043 } 1044 } 1045 1046 if (m_frame_base_error.Success()) 1047 frame_base = m_frame_base; 1048 1049 if (error_ptr) 1050 *error_ptr = m_frame_base_error; 1051 return m_frame_base_error.Success(); 1052} 1053 1054RegisterContextSP 1055StackFrame::GetRegisterContext () 1056{ 1057 if (!m_reg_context_sp) 1058 m_reg_context_sp = m_thread.CreateRegisterContextForFrame (this); 1059 return m_reg_context_sp; 1060} 1061 1062bool 1063StackFrame::HasDebugInformation () 1064{ 1065 GetSymbolContext (eSymbolContextLineEntry); 1066 return m_sc.line_entry.IsValid(); 1067} 1068 1069 1070ValueObjectSP 1071StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic) 1072{ 1073 ValueObjectSP valobj_sp; 1074 VariableList *var_list = GetVariableList (true); 1075 if (var_list) 1076 { 1077 // Make sure the variable is a frame variable 1078 const uint32_t var_idx = var_list->FindIndexForVariable (variable_sp.get()); 1079 const uint32_t num_variables = var_list->GetSize(); 1080 if (var_idx < num_variables) 1081 { 1082 valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex (var_idx); 1083 if (valobj_sp.get() == NULL) 1084 { 1085 if (m_variable_list_value_objects.GetSize() < num_variables) 1086 m_variable_list_value_objects.Resize(num_variables); 1087 valobj_sp = ValueObjectVariable::Create (this, variable_sp); 1088 m_variable_list_value_objects.SetValueObjectAtIndex (var_idx, valobj_sp); 1089 } 1090 } 1091 } 1092 if (use_dynamic != eNoDynamicValues && valobj_sp) 1093 { 1094 ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue (use_dynamic); 1095 if (dynamic_sp) 1096 return dynamic_sp; 1097 } 1098 return valobj_sp; 1099} 1100 1101ValueObjectSP 1102StackFrame::TrackGlobalVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic) 1103{ 1104 // Check to make sure we aren't already tracking this variable? 1105 ValueObjectSP valobj_sp (GetValueObjectForFrameVariable (variable_sp, use_dynamic)); 1106 if (!valobj_sp) 1107 { 1108 // We aren't already tracking this global 1109 VariableList *var_list = GetVariableList (true); 1110 // If this frame has no variables, create a new list 1111 if (var_list == NULL) 1112 m_variable_list_sp.reset (new VariableList()); 1113 1114 // Add the global/static variable to this frame 1115 m_variable_list_sp->AddVariable (variable_sp); 1116 1117 // Now make a value object for it so we can track its changes 1118 valobj_sp = GetValueObjectForFrameVariable (variable_sp, use_dynamic); 1119 } 1120 return valobj_sp; 1121} 1122 1123bool 1124StackFrame::IsInlined () 1125{ 1126 if (m_sc.block == NULL) 1127 GetSymbolContext (eSymbolContextBlock); 1128 if (m_sc.block) 1129 return m_sc.block->GetContainingInlinedBlock() != NULL; 1130 return false; 1131} 1132 1133Target * 1134StackFrame::CalculateTarget () 1135{ 1136 return m_thread.CalculateTarget(); 1137} 1138 1139Process * 1140StackFrame::CalculateProcess () 1141{ 1142 return m_thread.CalculateProcess(); 1143} 1144 1145Thread * 1146StackFrame::CalculateThread () 1147{ 1148 return &m_thread; 1149} 1150 1151StackFrame * 1152StackFrame::CalculateStackFrame () 1153{ 1154 return this; 1155} 1156 1157 1158void 1159StackFrame::CalculateExecutionContext (ExecutionContext &exe_ctx) 1160{ 1161 m_thread.CalculateExecutionContext (exe_ctx); 1162 exe_ctx.SetFramePtr(this); 1163} 1164 1165void 1166StackFrame::DumpUsingSettingsFormat (Stream *strm) 1167{ 1168 if (strm == NULL) 1169 return; 1170 1171 GetSymbolContext(eSymbolContextEverything); 1172 ExecutionContext exe_ctx; 1173 CalculateExecutionContext(exe_ctx); 1174 const char *end = NULL; 1175 StreamString s; 1176 const char *frame_format = m_thread.GetProcess().GetTarget().GetDebugger().GetFrameFormat(); 1177 if (frame_format && Debugger::FormatPrompt (frame_format, &m_sc, &exe_ctx, NULL, s, &end)) 1178 { 1179 strm->Write(s.GetData(), s.GetSize()); 1180 } 1181 else 1182 { 1183 Dump (strm, true, false); 1184 strm->EOL(); 1185 } 1186} 1187 1188void 1189StackFrame::Dump (Stream *strm, bool show_frame_index, bool show_fullpaths) 1190{ 1191 if (strm == NULL) 1192 return; 1193 1194 if (show_frame_index) 1195 strm->Printf("frame #%u: ", m_frame_index); 1196 strm->Printf("0x%0*llx ", m_thread.GetProcess().GetTarget().GetArchitecture().GetAddressByteSize() * 2, GetFrameCodeAddress().GetLoadAddress(&m_thread.GetProcess().GetTarget())); 1197 GetSymbolContext(eSymbolContextEverything); 1198 const bool show_module = true; 1199 const bool show_inline = true; 1200 m_sc.DumpStopContext(strm, &m_thread.GetProcess(), GetFrameCodeAddress(), show_fullpaths, show_module, show_inline); 1201} 1202 1203void 1204StackFrame::UpdateCurrentFrameFromPreviousFrame (StackFrame &prev_frame) 1205{ 1206 assert (GetStackID() == prev_frame.GetStackID()); // TODO: remove this after some testing 1207 m_variable_list_sp = prev_frame.m_variable_list_sp; 1208 m_variable_list_value_objects.Swap (prev_frame.m_variable_list_value_objects); 1209 if (!m_disassembly.GetString().empty()) 1210 m_disassembly.GetString().swap (m_disassembly.GetString()); 1211} 1212 1213 1214void 1215StackFrame::UpdatePreviousFrameFromCurrentFrame (StackFrame &curr_frame) 1216{ 1217 assert (GetStackID() == curr_frame.GetStackID()); // TODO: remove this after some testing 1218 m_id.SetPC (curr_frame.m_id.GetPC()); // Update the Stack ID PC value 1219 assert (&m_thread == &curr_frame.m_thread); 1220 m_frame_index = curr_frame.m_frame_index; 1221 m_concrete_frame_index = curr_frame.m_concrete_frame_index; 1222 m_reg_context_sp = curr_frame.m_reg_context_sp; 1223 m_frame_code_addr = curr_frame.m_frame_code_addr; 1224 assert (m_sc.target_sp.get() == NULL || curr_frame.m_sc.target_sp.get() == NULL || m_sc.target_sp.get() == curr_frame.m_sc.target_sp.get()); 1225 assert (m_sc.module_sp.get() == NULL || curr_frame.m_sc.module_sp.get() == NULL || m_sc.module_sp.get() == curr_frame.m_sc.module_sp.get()); 1226 assert (m_sc.comp_unit == NULL || curr_frame.m_sc.comp_unit == NULL || m_sc.comp_unit == curr_frame.m_sc.comp_unit); 1227 assert (m_sc.function == NULL || curr_frame.m_sc.function == NULL || m_sc.function == curr_frame.m_sc.function); 1228 m_sc = curr_frame.m_sc; 1229 m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything); 1230 m_flags.Set (m_sc.GetResolvedMask()); 1231 m_frame_base.Clear(); 1232 m_frame_base_error.Clear(); 1233} 1234 1235 1236bool 1237StackFrame::HasCachedData () const 1238{ 1239 if (m_variable_list_sp.get()) 1240 return true; 1241 if (m_variable_list_value_objects.GetSize() > 0) 1242 return true; 1243 if (!m_disassembly.GetString().empty()) 1244 return true; 1245 return false; 1246} 1247 1248StackFrameSP 1249StackFrame::GetSP () 1250{ 1251 // This object contains an instrusive ref count base class so we can 1252 // easily make a shared pointer to this object 1253 return StackFrameSP (this); 1254} 1255 1256 1257 1258bool 1259StackFrame::GetStatus (Stream& strm, 1260 bool show_frame_info, 1261 bool show_source, 1262 uint32_t source_lines_before, 1263 uint32_t source_lines_after) 1264{ 1265 if (show_frame_info) 1266 { 1267 strm.Indent(); 1268 DumpUsingSettingsFormat (&strm); 1269 } 1270 1271 if (show_source) 1272 { 1273 Target &target = GetThread().GetProcess().GetTarget(); 1274 Debugger &debugger = target.GetDebugger(); 1275 const uint32_t source_before = debugger.GetStopSourceLineCount(true); 1276 const uint32_t source_after = debugger.GetStopSourceLineCount(false); 1277 bool have_source = false; 1278 if (source_before || source_after) 1279 { 1280 GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry); 1281 1282 if (m_sc.comp_unit && m_sc.line_entry.IsValid()) 1283 { 1284 if (target.GetSourceManager().DisplaySourceLinesWithLineNumbers (m_sc.line_entry.file, 1285 m_sc.line_entry.line, 1286 source_before, 1287 source_after, 1288 "->", 1289 &strm)) 1290 { 1291 have_source = true; 1292 } 1293 } 1294 } 1295 DebuggerInstanceSettings::StopDisassemblyType disasm_display = debugger.GetStopDisassemblyDisplay (); 1296 1297 switch (disasm_display) 1298 { 1299 case DebuggerInstanceSettings::eStopDisassemblyTypeNever: 1300 break; 1301 1302 case DebuggerInstanceSettings::eStopDisassemblyTypeNoSource: 1303 if (have_source) 1304 break; 1305 // Fall through to next case 1306 case DebuggerInstanceSettings::eStopDisassemblyTypeAlways: 1307 { 1308 const uint32_t disasm_lines = debugger.GetDisassemblyLineCount(); 1309 if (disasm_lines > 0) 1310 { 1311 const ArchSpec &target_arch = target.GetArchitecture(); 1312 AddressRange pc_range; 1313 pc_range.GetBaseAddress() = GetFrameCodeAddress(); 1314 pc_range.SetByteSize(disasm_lines * target_arch.GetMaximumOpcodeByteSize()); 1315 ExecutionContext exe_ctx; 1316 CalculateExecutionContext(exe_ctx); 1317 Disassembler::Disassemble (debugger, 1318 target_arch, 1319 NULL, 1320 exe_ctx, 1321 pc_range, 1322 disasm_lines, 1323 0, 1324 Disassembler::eOptionMarkPCAddress, 1325 strm); 1326 } 1327 } 1328 break; 1329 } 1330 } 1331 return true; 1332} 1333 1334