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