1 //===-- StackFrameList.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/StackFrameList.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/StreamFile.h" 17 #include "lldb/Core/SourceManager.h" 18 #include "lldb/Symbol/Block.h" 19 #include "lldb/Symbol/Function.h" 20 #include "lldb/Symbol/Symbol.h" 21 #include "lldb/Target/Process.h" 22 #include "lldb/Target/RegisterContext.h" 23 #include "lldb/Target/StackFrame.h" 24 #include "lldb/Target/StopInfo.h" 25 #include "lldb/Target/Target.h" 26 #include "lldb/Target/Thread.h" 27 #include "lldb/Target/Unwind.h" 28 29 //#define DEBUG_STACK_FRAMES 1 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 //---------------------------------------------------------------------- 35 // StackFrameList constructor 36 //---------------------------------------------------------------------- 37 StackFrameList::StackFrameList 38 ( 39 Thread &thread, 40 const lldb::StackFrameListSP &prev_frames_sp, 41 bool show_inline_frames 42 ) : 43 m_thread (thread), 44 m_prev_frames_sp (prev_frames_sp), 45 m_mutex (Mutex::eMutexTypeRecursive), 46 m_frames (), 47 m_selected_frame_idx (0), 48 m_concrete_frames_fetched (0), 49 m_current_inlined_depth (UINT32_MAX), 50 m_current_inlined_pc (LLDB_INVALID_ADDRESS), 51 m_show_inlined_frames (show_inline_frames) 52 { 53 if (prev_frames_sp) 54 { 55 m_current_inlined_depth = prev_frames_sp->m_current_inlined_depth; 56 m_current_inlined_pc = prev_frames_sp->m_current_inlined_pc; 57 } 58 } 59 60 //---------------------------------------------------------------------- 61 // Destructor 62 //---------------------------------------------------------------------- 63 StackFrameList::~StackFrameList() 64 { 65 } 66 67 void 68 StackFrameList::CalculateCurrentInlinedDepth() 69 { 70 uint32_t cur_inlined_depth = GetCurrentInlinedDepth(); 71 if (cur_inlined_depth == UINT32_MAX) 72 { 73 ResetCurrentInlinedDepth(); 74 } 75 } 76 77 uint32_t 78 StackFrameList::GetCurrentInlinedDepth () 79 { 80 if (m_show_inlined_frames) 81 { 82 lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC(); 83 if (cur_pc != m_current_inlined_pc) 84 { 85 m_current_inlined_pc = LLDB_INVALID_ADDRESS; 86 m_current_inlined_depth = UINT32_MAX; 87 } 88 return m_current_inlined_depth; 89 } 90 else 91 { 92 return UINT32_MAX; 93 } 94 } 95 96 static const bool LLDB_FANCY_INLINED_STEPPING = false; 97 98 void 99 StackFrameList::ResetCurrentInlinedDepth () 100 { 101 if (LLDB_FANCY_INLINED_STEPPING && m_show_inlined_frames) 102 { 103 GetFramesUpTo(0); 104 if (!m_frames[0]->IsInlined()) 105 { 106 m_current_inlined_depth = UINT32_MAX; 107 m_current_inlined_pc = LLDB_INVALID_ADDRESS; 108 } 109 else 110 { 111 // We only need to do something special about inlined blocks when we 112 // are at the beginning of an inlined function: 113 // FIXME: We probably also have to do something special if the PC is at the END 114 // of an inlined function, which coincides with the end of either its containing 115 // function or another inlined function. 116 117 lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC(); 118 Block *block_ptr = m_frames[0]->GetFrameBlock(); 119 if (block_ptr) 120 { 121 Address pc_as_address; 122 pc_as_address.SetLoadAddress(curr_pc, &(m_thread.GetProcess()->GetTarget())); 123 AddressRange containing_range; 124 if (block_ptr->GetRangeContainingAddress(pc_as_address, containing_range)) 125 { 126 if (pc_as_address == containing_range.GetBaseAddress()) 127 { 128 // If we got here because of a breakpoint hit, then set the inlined depth depending on where 129 // the breakpoint was set. 130 // If we got here because of a crash, then set the inlined depth to the deepest most block. 131 // Otherwise, we stopped here naturally as the result of a step, so set ourselves in the 132 // containing frame of the whole set of nested inlines, so the user can then "virtually" 133 // step into the frames one by one, or next over the whole mess. 134 // Note: We don't have to handle being somewhere in the middle of the stack here, since 135 // ResetCurrentInlinedDepth doesn't get called if there is a valid inlined depth set. 136 StopInfoSP stop_info_sp = m_thread.GetStopInfo(); 137 if (stop_info_sp) 138 { 139 switch (stop_info_sp->GetStopReason()) 140 { 141 case eStopReasonBreakpoint: 142 { 143 144 } 145 break; 146 case eStopReasonWatchpoint: 147 case eStopReasonException: 148 case eStopReasonSignal: 149 // In all these cases we want to stop in the deepest most frame. 150 m_current_inlined_pc = curr_pc; 151 m_current_inlined_depth = 0; 152 break; 153 default: 154 { 155 // Otherwise, we should set ourselves at the container of the inlining, so that the 156 // user can descend into them. 157 // So first we check whether we have more than one inlined block sharing this PC: 158 int num_inlined_functions = 0; 159 160 for (Block *container_ptr = block_ptr->GetInlinedParent(); 161 container_ptr != NULL; 162 container_ptr = container_ptr->GetInlinedParent()) 163 { 164 if (!container_ptr->GetRangeContainingAddress(pc_as_address, containing_range)) 165 break; 166 if (pc_as_address != containing_range.GetBaseAddress()) 167 break; 168 169 num_inlined_functions++; 170 } 171 m_current_inlined_pc = curr_pc; 172 m_current_inlined_depth = num_inlined_functions + 1; 173 174 } 175 break; 176 } 177 } 178 } 179 } 180 } 181 } 182 } 183 } 184 185 bool 186 StackFrameList::DecrementCurrentInlinedDepth () 187 { 188 if (m_show_inlined_frames) 189 { 190 uint32_t current_inlined_depth = GetCurrentInlinedDepth(); 191 if (current_inlined_depth != UINT32_MAX) 192 { 193 if (current_inlined_depth > 0) 194 m_current_inlined_depth--; 195 return true; 196 } 197 } 198 return false; 199 } 200 201 void 202 StackFrameList::GetFramesUpTo(uint32_t end_idx) 203 { 204 // We've already gotten more frames than asked for, or we've already finished unwinding, return. 205 if (m_frames.size() > end_idx || GetAllFramesFetched()) 206 return; 207 208 Unwind *unwinder = m_thread.GetUnwinder (); 209 210 if (m_show_inlined_frames) 211 { 212 #if defined (DEBUG_STACK_FRAMES) 213 StreamFile s(stdout, false); 214 #endif 215 // If we are hiding some frames from the outside world, we need to add those onto the total count of 216 // frames to fetch. However, we don't need ot do that if end_idx is 0 since in that case we always 217 // get the first concrete frame and all the inlined frames below it... 218 219 uint32_t inlined_depth = 0; 220 if (end_idx > 0) 221 { 222 inlined_depth = GetCurrentInlinedDepth(); 223 if (inlined_depth != UINT32_MAX) 224 { 225 if (end_idx > 0) 226 end_idx += inlined_depth; 227 } 228 else 229 inlined_depth = 0; 230 } 231 232 StackFrameSP unwind_frame_sp; 233 do 234 { 235 uint32_t idx = m_concrete_frames_fetched++; 236 lldb::addr_t pc; 237 lldb::addr_t cfa; 238 if (idx == 0) 239 { 240 // We might have already created frame zero, only create it 241 // if we need to 242 if (m_frames.empty()) 243 { 244 m_thread.GetRegisterContext(); 245 assert (m_thread.m_reg_context_sp.get()); 246 247 const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc); 248 // There shouldn't be any way not to get the frame info for frame 0. 249 // But if the unwinder can't make one, lets make one by hand with the 250 // SP as the CFA and see if that gets any further. 251 if (!success) 252 { 253 cfa = m_thread.GetRegisterContext()->GetSP(); 254 pc = m_thread.GetRegisterContext()->GetPC(); 255 } 256 257 unwind_frame_sp.reset (new StackFrame (m_thread.shared_from_this(), 258 m_frames.size(), 259 idx, 260 m_thread.m_reg_context_sp, 261 cfa, 262 pc, 263 NULL)); 264 m_frames.push_back (unwind_frame_sp); 265 } 266 else 267 { 268 unwind_frame_sp = m_frames.front(); 269 cfa = unwind_frame_sp->m_id.GetCallFrameAddress(); 270 } 271 } 272 else 273 { 274 const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc); 275 if (!success) 276 { 277 // We've gotten to the end of the stack. 278 SetAllFramesFetched(); 279 break; 280 } 281 unwind_frame_sp.reset (new StackFrame (m_thread.shared_from_this(), m_frames.size(), idx, cfa, pc, NULL)); 282 m_frames.push_back (unwind_frame_sp); 283 } 284 285 SymbolContext unwind_sc = unwind_frame_sp->GetSymbolContext (eSymbolContextBlock | eSymbolContextFunction); 286 Block *unwind_block = unwind_sc.block; 287 if (unwind_block) 288 { 289 Address curr_frame_address (unwind_frame_sp->GetFrameCodeAddress()); 290 // Be sure to adjust the frame address to match the address 291 // that was used to lookup the symbol context above. If we are 292 // in the first concrete frame, then we lookup using the current 293 // address, else we decrement the address by one to get the correct 294 // location. 295 if (idx > 0) 296 curr_frame_address.Slide(-1); 297 298 SymbolContext next_frame_sc; 299 Address next_frame_address; 300 301 while (unwind_sc.GetParentOfInlinedScope(curr_frame_address, next_frame_sc, next_frame_address)) 302 { 303 StackFrameSP frame_sp(new StackFrame (m_thread.shared_from_this(), 304 m_frames.size(), 305 idx, 306 unwind_frame_sp->GetRegisterContextSP (), 307 cfa, 308 next_frame_address, 309 &next_frame_sc)); 310 311 m_frames.push_back (frame_sp); 312 unwind_sc = next_frame_sc; 313 curr_frame_address = next_frame_address; 314 } 315 } 316 } while (m_frames.size() - 1 < end_idx); 317 318 // Don't try to merge till you've calculated all the frames in this stack. 319 if (GetAllFramesFetched() && m_prev_frames_sp) 320 { 321 StackFrameList *prev_frames = m_prev_frames_sp.get(); 322 StackFrameList *curr_frames = this; 323 324 #if defined (DEBUG_STACK_FRAMES) 325 s.PutCString("\nprev_frames:\n"); 326 prev_frames->Dump (&s); 327 s.PutCString("\ncurr_frames:\n"); 328 curr_frames->Dump (&s); 329 s.EOL(); 330 #endif 331 size_t curr_frame_num, prev_frame_num; 332 333 for (curr_frame_num = curr_frames->m_frames.size(), prev_frame_num = prev_frames->m_frames.size(); 334 curr_frame_num > 0 && prev_frame_num > 0; 335 --curr_frame_num, --prev_frame_num) 336 { 337 const size_t curr_frame_idx = curr_frame_num-1; 338 const size_t prev_frame_idx = prev_frame_num-1; 339 StackFrameSP curr_frame_sp (curr_frames->m_frames[curr_frame_idx]); 340 StackFrameSP prev_frame_sp (prev_frames->m_frames[prev_frame_idx]); 341 342 #if defined (DEBUG_STACK_FRAMES) 343 s.Printf("\n\nCurr frame #%u ", curr_frame_idx); 344 if (curr_frame_sp) 345 curr_frame_sp->Dump (&s, true, false); 346 else 347 s.PutCString("NULL"); 348 s.Printf("\nPrev frame #%u ", prev_frame_idx); 349 if (prev_frame_sp) 350 prev_frame_sp->Dump (&s, true, false); 351 else 352 s.PutCString("NULL"); 353 #endif 354 355 StackFrame *curr_frame = curr_frame_sp.get(); 356 StackFrame *prev_frame = prev_frame_sp.get(); 357 358 if (curr_frame == NULL || prev_frame == NULL) 359 break; 360 361 // Check the stack ID to make sure they are equal 362 if (curr_frame->GetStackID() != prev_frame->GetStackID()) 363 break; 364 365 prev_frame->UpdatePreviousFrameFromCurrentFrame (*curr_frame); 366 // Now copy the fixed up previous frame into the current frames 367 // so the pointer doesn't change 368 m_frames[curr_frame_idx] = prev_frame_sp; 369 //curr_frame->UpdateCurrentFrameFromPreviousFrame (*prev_frame); 370 371 #if defined (DEBUG_STACK_FRAMES) 372 s.Printf("\n Copying previous frame to current frame"); 373 #endif 374 } 375 // We are done with the old stack frame list, we can release it now 376 m_prev_frames_sp.reset(); 377 } 378 379 #if defined (DEBUG_STACK_FRAMES) 380 s.PutCString("\n\nNew frames:\n"); 381 Dump (&s); 382 s.EOL(); 383 #endif 384 } 385 else 386 { 387 if (end_idx < m_concrete_frames_fetched) 388 return; 389 390 uint32_t num_frames = unwinder->GetFramesUpTo(end_idx); 391 if (num_frames <= end_idx + 1) 392 { 393 //Done unwinding. 394 m_concrete_frames_fetched = UINT32_MAX; 395 } 396 m_frames.resize(num_frames); 397 } 398 } 399 400 uint32_t 401 StackFrameList::GetNumFrames (bool can_create) 402 { 403 Mutex::Locker locker (m_mutex); 404 405 if (can_create) 406 GetFramesUpTo (UINT32_MAX); 407 408 uint32_t inlined_depth = GetCurrentInlinedDepth(); 409 if (inlined_depth == UINT32_MAX) 410 return m_frames.size(); 411 else 412 return m_frames.size() - inlined_depth; 413 } 414 415 void 416 StackFrameList::Dump (Stream *s) 417 { 418 if (s == NULL) 419 return; 420 Mutex::Locker locker (m_mutex); 421 422 const_iterator pos, begin = m_frames.begin(), end = m_frames.end(); 423 for (pos = begin; pos != end; ++pos) 424 { 425 StackFrame *frame = (*pos).get(); 426 s->Printf("%p: ", frame); 427 if (frame) 428 { 429 frame->GetStackID().Dump (s); 430 frame->DumpUsingSettingsFormat (s); 431 } 432 else 433 s->Printf("frame #%u", (uint32_t)std::distance (begin, pos)); 434 s->EOL(); 435 } 436 s->EOL(); 437 } 438 439 StackFrameSP 440 StackFrameList::GetFrameAtIndex (uint32_t idx) 441 { 442 StackFrameSP frame_sp; 443 Mutex::Locker locker (m_mutex); 444 uint32_t inlined_depth = GetCurrentInlinedDepth(); 445 if (inlined_depth != UINT32_MAX) 446 idx += inlined_depth; 447 448 if (idx < m_frames.size()) 449 frame_sp = m_frames[idx]; 450 451 if (frame_sp) 452 return frame_sp; 453 454 // GetFramesUpTo will fill m_frames with as many frames as you asked for, 455 // if there are that many. If there weren't then you asked for too many 456 // frames. 457 GetFramesUpTo (idx); 458 if (idx < m_frames.size()) 459 { 460 if (m_show_inlined_frames) 461 { 462 // When inline frames are enabled we actually create all the frames in GetFramesUpTo. 463 frame_sp = m_frames[idx]; 464 } 465 else 466 { 467 Unwind *unwinder = m_thread.GetUnwinder (); 468 if (unwinder) 469 { 470 addr_t pc, cfa; 471 if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) 472 { 473 frame_sp.reset (new StackFrame (m_thread.shared_from_this(), idx, idx, cfa, pc, NULL)); 474 475 Function *function = frame_sp->GetSymbolContext (eSymbolContextFunction).function; 476 if (function) 477 { 478 // When we aren't showing inline functions we always use 479 // the top most function block as the scope. 480 frame_sp->SetSymbolContextScope (&function->GetBlock(false)); 481 } 482 else 483 { 484 // Set the symbol scope from the symbol regardless if it is NULL or valid. 485 frame_sp->SetSymbolContextScope (frame_sp->GetSymbolContext (eSymbolContextSymbol).symbol); 486 } 487 SetFrameAtIndex(idx, frame_sp); 488 } 489 } 490 } 491 } 492 return frame_sp; 493 } 494 495 StackFrameSP 496 StackFrameList::GetFrameWithConcreteFrameIndex (uint32_t unwind_idx) 497 { 498 // First try assuming the unwind index is the same as the frame index. The 499 // unwind index is always greater than or equal to the frame index, so it 500 // is a good place to start. If we have inlined frames we might have 5 501 // concrete frames (frame unwind indexes go from 0-4), but we might have 15 502 // frames after we make all the inlined frames. Most of the time the unwind 503 // frame index (or the concrete frame index) is the same as the frame index. 504 uint32_t frame_idx = unwind_idx; 505 StackFrameSP frame_sp (GetFrameAtIndex (frame_idx)); 506 while (frame_sp) 507 { 508 if (frame_sp->GetFrameIndex() == unwind_idx) 509 break; 510 frame_sp = GetFrameAtIndex (++frame_idx); 511 } 512 return frame_sp; 513 } 514 515 StackFrameSP 516 StackFrameList::GetFrameWithStackID (const StackID &stack_id) 517 { 518 uint32_t frame_idx = 0; 519 StackFrameSP frame_sp; 520 do 521 { 522 frame_sp = GetFrameAtIndex (frame_idx); 523 if (frame_sp && frame_sp->GetStackID() == stack_id) 524 break; 525 frame_idx++; 526 } 527 while (frame_sp); 528 return frame_sp; 529 } 530 531 bool 532 StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp) 533 { 534 if (idx >= m_frames.size()) 535 m_frames.resize(idx + 1); 536 // Make sure allocation succeeded by checking bounds again 537 if (idx < m_frames.size()) 538 { 539 m_frames[idx] = frame_sp; 540 return true; 541 } 542 return false; // resize failed, out of memory? 543 } 544 545 uint32_t 546 StackFrameList::GetSelectedFrameIndex () const 547 { 548 Mutex::Locker locker (m_mutex); 549 return m_selected_frame_idx; 550 } 551 552 553 uint32_t 554 StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame) 555 { 556 Mutex::Locker locker (m_mutex); 557 const_iterator pos; 558 const_iterator begin = m_frames.begin(); 559 const_iterator end = m_frames.end(); 560 m_selected_frame_idx = 0; 561 for (pos = begin; pos != end; ++pos) 562 { 563 if (pos->get() == frame) 564 { 565 m_selected_frame_idx = std::distance (begin, pos); 566 uint32_t inlined_depth = GetCurrentInlinedDepth(); 567 if (inlined_depth != UINT32_MAX) 568 m_selected_frame_idx -= inlined_depth; 569 break; 570 } 571 } 572 SetDefaultFileAndLineToSelectedFrame(); 573 return m_selected_frame_idx; 574 } 575 576 // Mark a stack frame as the current frame using the frame index 577 bool 578 StackFrameList::SetSelectedFrameByIndex (uint32_t idx) 579 { 580 Mutex::Locker locker (m_mutex); 581 StackFrameSP frame_sp (GetFrameAtIndex (idx)); 582 if (frame_sp) 583 { 584 SetSelectedFrame(frame_sp.get()); 585 return true; 586 } 587 else 588 return false; 589 } 590 591 void 592 StackFrameList::SetDefaultFileAndLineToSelectedFrame() 593 { 594 if (m_thread.GetID() == m_thread.GetProcess()->GetThreadList().GetSelectedThread()->GetID()) 595 { 596 StackFrameSP frame_sp (GetFrameAtIndex (GetSelectedFrameIndex())); 597 if (frame_sp) 598 { 599 SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextLineEntry); 600 if (sc.line_entry.file) 601 m_thread.CalculateTarget()->GetSourceManager().SetDefaultFileAndLine (sc.line_entry.file, 602 sc.line_entry.line); 603 } 604 } 605 } 606 607 // The thread has been run, reset the number stack frames to zero so we can 608 // determine how many frames we have lazily. 609 void 610 StackFrameList::Clear () 611 { 612 Mutex::Locker locker (m_mutex); 613 m_frames.clear(); 614 m_concrete_frames_fetched = 0; 615 } 616 617 void 618 StackFrameList::InvalidateFrames (uint32_t start_idx) 619 { 620 Mutex::Locker locker (m_mutex); 621 if (m_show_inlined_frames) 622 { 623 Clear(); 624 } 625 else 626 { 627 const size_t num_frames = m_frames.size(); 628 while (start_idx < num_frames) 629 { 630 m_frames[start_idx].reset(); 631 ++start_idx; 632 } 633 } 634 } 635 636 void 637 StackFrameList::Merge (std::auto_ptr<StackFrameList>& curr_ap, lldb::StackFrameListSP& prev_sp) 638 { 639 Mutex::Locker curr_locker (curr_ap.get() ? &curr_ap->m_mutex : NULL); 640 Mutex::Locker prev_locker (prev_sp.get() ? &prev_sp->m_mutex : NULL); 641 642 #if defined (DEBUG_STACK_FRAMES) 643 StreamFile s(stdout, false); 644 s.PutCString("\n\nStackFrameList::Merge():\nPrev:\n"); 645 if (prev_sp.get()) 646 prev_sp->Dump (&s); 647 else 648 s.PutCString ("NULL"); 649 s.PutCString("\nCurr:\n"); 650 if (curr_ap.get()) 651 curr_ap->Dump (&s); 652 else 653 s.PutCString ("NULL"); 654 s.EOL(); 655 #endif 656 657 if (curr_ap.get() == NULL || curr_ap->GetNumFrames (false) == 0) 658 { 659 #if defined (DEBUG_STACK_FRAMES) 660 s.PutCString("No current frames, leave previous frames alone...\n"); 661 #endif 662 curr_ap.release(); 663 return; 664 } 665 666 if (prev_sp.get() == NULL || prev_sp->GetNumFrames (false) == 0) 667 { 668 #if defined (DEBUG_STACK_FRAMES) 669 s.PutCString("No previous frames, so use current frames...\n"); 670 #endif 671 // We either don't have any previous frames, or since we have more than 672 // one current frames it means we have all the frames and can safely 673 // replace our previous frames. 674 prev_sp.reset (curr_ap.release()); 675 return; 676 } 677 678 const uint32_t num_curr_frames = curr_ap->GetNumFrames (false); 679 680 if (num_curr_frames > 1) 681 { 682 #if defined (DEBUG_STACK_FRAMES) 683 s.PutCString("We have more than one current frame, so use current frames...\n"); 684 #endif 685 // We have more than one current frames it means we have all the frames 686 // and can safely replace our previous frames. 687 prev_sp.reset (curr_ap.release()); 688 689 #if defined (DEBUG_STACK_FRAMES) 690 s.PutCString("\nMerged:\n"); 691 prev_sp->Dump (&s); 692 #endif 693 return; 694 } 695 696 StackFrameSP prev_frame_zero_sp(prev_sp->GetFrameAtIndex (0)); 697 StackFrameSP curr_frame_zero_sp(curr_ap->GetFrameAtIndex (0)); 698 StackID curr_stack_id (curr_frame_zero_sp->GetStackID()); 699 StackID prev_stack_id (prev_frame_zero_sp->GetStackID()); 700 701 #if defined (DEBUG_STACK_FRAMES) 702 const uint32_t num_prev_frames = prev_sp->GetNumFrames (false); 703 s.Printf("\n%u previous frames with one current frame\n", num_prev_frames); 704 #endif 705 706 // We have only a single current frame 707 // Our previous stack frames only had a single frame as well... 708 if (curr_stack_id == prev_stack_id) 709 { 710 #if defined (DEBUG_STACK_FRAMES) 711 s.Printf("\nPrevious frame #0 is same as current frame #0, merge the cached data\n"); 712 #endif 713 714 curr_frame_zero_sp->UpdateCurrentFrameFromPreviousFrame (*prev_frame_zero_sp); 715 // prev_frame_zero_sp->UpdatePreviousFrameFromCurrentFrame (*curr_frame_zero_sp); 716 // prev_sp->SetFrameAtIndex (0, prev_frame_zero_sp); 717 } 718 else if (curr_stack_id < prev_stack_id) 719 { 720 #if defined (DEBUG_STACK_FRAMES) 721 s.Printf("\nCurrent frame #0 has a stack ID that is less than the previous frame #0, insert current frame zero in front of previous\n"); 722 #endif 723 prev_sp->m_frames.insert (prev_sp->m_frames.begin(), curr_frame_zero_sp); 724 } 725 726 curr_ap.release(); 727 728 #if defined (DEBUG_STACK_FRAMES) 729 s.PutCString("\nMerged:\n"); 730 prev_sp->Dump (&s); 731 #endif 732 733 734 } 735 736 lldb::StackFrameSP 737 StackFrameList::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr) 738 { 739 const_iterator pos; 740 const_iterator begin = m_frames.begin(); 741 const_iterator end = m_frames.end(); 742 lldb::StackFrameSP ret_sp; 743 744 for (pos = begin; pos != end; ++pos) 745 { 746 if (pos->get() == stack_frame_ptr) 747 { 748 ret_sp = (*pos); 749 break; 750 } 751 } 752 return ret_sp; 753 } 754 755 size_t 756 StackFrameList::GetStatus (Stream& strm, 757 uint32_t first_frame, 758 uint32_t num_frames, 759 bool show_frame_info, 760 uint32_t num_frames_with_source) 761 { 762 size_t num_frames_displayed = 0; 763 764 if (num_frames == 0) 765 return 0; 766 767 StackFrameSP frame_sp; 768 uint32_t frame_idx = 0; 769 uint32_t last_frame; 770 771 // Don't let the last frame wrap around... 772 if (num_frames == UINT32_MAX) 773 last_frame = UINT32_MAX; 774 else 775 last_frame = first_frame + num_frames; 776 777 for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx) 778 { 779 frame_sp = GetFrameAtIndex(frame_idx); 780 if (frame_sp.get() == NULL) 781 break; 782 783 if (!frame_sp->GetStatus (strm, 784 show_frame_info, 785 num_frames_with_source > (first_frame - frame_idx))) 786 break; 787 ++num_frames_displayed; 788 } 789 790 strm.IndentLess(); 791 return num_frames_displayed; 792 } 793 794