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