130fdc8d8SChris Lattner //===-- StackFrameList.cpp --------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1012daf946SGreg Clayton #include "lldb/Target/StackFrameList.h"
1112daf946SGreg Clayton 
1230fdc8d8SChris Lattner // C Includes
1330fdc8d8SChris Lattner // C++ Includes
1430fdc8d8SChris Lattner // Other libraries and framework includes
1530fdc8d8SChris Lattner // Project includes
165082c5fdSGreg Clayton #include "lldb/Core/StreamFile.h"
1712daf946SGreg Clayton #include "lldb/Symbol/Block.h"
1812daf946SGreg Clayton #include "lldb/Symbol/Function.h"
1959e8fc1cSGreg Clayton #include "lldb/Symbol/Symbol.h"
2012daf946SGreg Clayton #include "lldb/Target/RegisterContext.h"
2130fdc8d8SChris Lattner #include "lldb/Target/StackFrame.h"
2212daf946SGreg Clayton #include "lldb/Target/Thread.h"
2312daf946SGreg Clayton #include "lldb/Target/Unwind.h"
2430fdc8d8SChris Lattner 
255082c5fdSGreg Clayton //#define DEBUG_STACK_FRAMES 1
265082c5fdSGreg Clayton 
2730fdc8d8SChris Lattner using namespace lldb;
2830fdc8d8SChris Lattner using namespace lldb_private;
2930fdc8d8SChris Lattner 
3030fdc8d8SChris Lattner //----------------------------------------------------------------------
3130fdc8d8SChris Lattner // StackFrameList constructor
3230fdc8d8SChris Lattner //----------------------------------------------------------------------
330445d8f4SGreg Clayton StackFrameList::StackFrameList(Thread &thread, StackFrameList *prev_frames, bool show_inline_frames) :
3412daf946SGreg Clayton     m_thread (thread),
350445d8f4SGreg Clayton     m_prev_frames_ap (prev_frames),
3612daf946SGreg Clayton     m_show_inlined_frames (show_inline_frames),
3730fdc8d8SChris Lattner     m_mutex (Mutex::eMutexTypeRecursive),
385082c5fdSGreg Clayton     m_frames (),
392976d00aSJim Ingham     m_selected_frame_idx (0)
4030fdc8d8SChris Lattner {
4130fdc8d8SChris Lattner }
4230fdc8d8SChris Lattner 
4330fdc8d8SChris Lattner //----------------------------------------------------------------------
4430fdc8d8SChris Lattner // Destructor
4530fdc8d8SChris Lattner //----------------------------------------------------------------------
4630fdc8d8SChris Lattner StackFrameList::~StackFrameList()
4730fdc8d8SChris Lattner {
4830fdc8d8SChris Lattner }
4930fdc8d8SChris Lattner 
5030fdc8d8SChris Lattner 
5130fdc8d8SChris Lattner uint32_t
5212daf946SGreg Clayton StackFrameList::GetNumFrames()
5330fdc8d8SChris Lattner {
5430fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
5512daf946SGreg Clayton 
565082c5fdSGreg Clayton     if (m_frames.size() <= 1)
575082c5fdSGreg Clayton     {
5812daf946SGreg Clayton         if (m_show_inlined_frames)
5912daf946SGreg Clayton         {
605082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
615082c5fdSGreg Clayton             StreamFile s(stdout);
625082c5fdSGreg Clayton #endif
6312daf946SGreg Clayton             Unwind *unwinder = m_thread.GetUnwinder ();
6459e8fc1cSGreg Clayton             addr_t pc = LLDB_INVALID_ADDRESS;
6559e8fc1cSGreg Clayton             addr_t cfa = LLDB_INVALID_ADDRESS;
665082c5fdSGreg Clayton 
6712daf946SGreg Clayton             // If we are going to show inlined stack frames as actual frames,
6812daf946SGreg Clayton             // we need to calculate all concrete frames first, then iterate
6912daf946SGreg Clayton             // through all of them and count up how many inlined functions are
705082c5fdSGreg Clayton             // in each frame.
715082c5fdSGreg Clayton             const uint32_t unwind_frame_count = unwinder->GetFrameCount();
7212daf946SGreg Clayton 
735082c5fdSGreg Clayton             StackFrameSP unwind_frame_sp;
745082c5fdSGreg Clayton             for (uint32_t idx=0; idx<unwind_frame_count; ++idx)
7512daf946SGreg Clayton             {
7612daf946SGreg Clayton                 if (idx == 0)
7712daf946SGreg Clayton                 {
785082c5fdSGreg Clayton                     // We might have already created frame zero, only create it
795082c5fdSGreg Clayton                     // if we need to
805082c5fdSGreg Clayton                     if (m_frames.empty())
815082c5fdSGreg Clayton                     {
8259e8fc1cSGreg Clayton                         cfa = m_thread.m_reg_context_sp->GetSP();
8312daf946SGreg Clayton                         m_thread.GetRegisterContext();
845082c5fdSGreg Clayton                         unwind_frame_sp.reset (new StackFrame (m_frames.size(),
855082c5fdSGreg Clayton                                                                idx,
8612daf946SGreg Clayton                                                                m_thread,
8712daf946SGreg Clayton                                                                m_thread.m_reg_context_sp,
8859e8fc1cSGreg Clayton                                                                cfa,
8912daf946SGreg Clayton                                                                m_thread.m_reg_context_sp->GetPC(),
9012daf946SGreg Clayton                                                                NULL));
915082c5fdSGreg Clayton                         m_frames.push_back (unwind_frame_sp);
925082c5fdSGreg Clayton                     }
935082c5fdSGreg Clayton                     else
945082c5fdSGreg Clayton                     {
955082c5fdSGreg Clayton                         unwind_frame_sp = m_frames.front();
9659e8fc1cSGreg Clayton                         cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
975082c5fdSGreg Clayton                     }
9812daf946SGreg Clayton                 }
9912daf946SGreg Clayton                 else
10012daf946SGreg Clayton                 {
10112daf946SGreg Clayton                     const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
10212daf946SGreg Clayton                     assert (success);
1035082c5fdSGreg Clayton                     unwind_frame_sp.reset (new StackFrame (m_frames.size(), idx, m_thread, cfa, pc, NULL));
1045082c5fdSGreg Clayton                     m_frames.push_back (unwind_frame_sp);
10512daf946SGreg Clayton                 }
10612daf946SGreg Clayton 
10759e8fc1cSGreg Clayton                 Block *unwind_block = unwind_frame_sp->GetSymbolContext (eSymbolContextBlock).block;
10812daf946SGreg Clayton 
10959e8fc1cSGreg Clayton                 if (unwind_block)
11012daf946SGreg Clayton                 {
11159e8fc1cSGreg Clayton                     Block *inlined_block = unwind_block->GetContainingInlinedBlock();
11259e8fc1cSGreg Clayton                     if (inlined_block)
11359e8fc1cSGreg Clayton                     {
11459e8fc1cSGreg Clayton                         for (; inlined_block != NULL; inlined_block = inlined_block->GetInlinedParent ())
1150445d8f4SGreg Clayton                         {
1165082c5fdSGreg Clayton                             SymbolContext inline_sc;
11759e8fc1cSGreg Clayton                             Block *parent_block = inlined_block->GetInlinedParent();
11812daf946SGreg Clayton 
1195082c5fdSGreg Clayton                             const bool is_inlined_frame = parent_block != NULL;
1205082c5fdSGreg Clayton 
1215082c5fdSGreg Clayton                             if (parent_block == NULL)
12259e8fc1cSGreg Clayton                                 parent_block = inlined_block->GetParent();
1235082c5fdSGreg Clayton 
1245082c5fdSGreg Clayton                             parent_block->CalculateSymbolContext (&inline_sc);
1255082c5fdSGreg Clayton 
1265082c5fdSGreg Clayton                             Address previous_frame_lookup_addr (m_frames.back()->GetFrameCodeAddress());
1275082c5fdSGreg Clayton                             if (unwind_frame_sp->GetFrameIndex() > 0 && m_frames.back().get() == unwind_frame_sp.get())
1285082c5fdSGreg Clayton                                 previous_frame_lookup_addr.Slide (-1);
1295082c5fdSGreg Clayton 
1305082c5fdSGreg Clayton                             AddressRange range;
13159e8fc1cSGreg Clayton                             inlined_block->GetRangeContainingAddress (previous_frame_lookup_addr, range);
1325082c5fdSGreg Clayton 
13359e8fc1cSGreg Clayton                             const InlineFunctionInfo* inline_info = inlined_block->InlinedFunctionInfo();
1345082c5fdSGreg Clayton                             assert (inline_info);
1355082c5fdSGreg Clayton                             inline_sc.line_entry.range.GetBaseAddress() = m_frames.back()->GetFrameCodeAddress();
1365082c5fdSGreg Clayton                             inline_sc.line_entry.file = inline_info->GetCallSite().GetFile();
1375082c5fdSGreg Clayton                             inline_sc.line_entry.line = inline_info->GetCallSite().GetLine();
1385082c5fdSGreg Clayton                             inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn();
1395082c5fdSGreg Clayton 
1405082c5fdSGreg Clayton                             StackFrameSP frame_sp(new StackFrame (m_frames.size(),
1415082c5fdSGreg Clayton                                                                   idx,
1425082c5fdSGreg Clayton                                                                   m_thread,
1435082c5fdSGreg Clayton                                                                   unwind_frame_sp->GetRegisterContextSP (),
14459e8fc1cSGreg Clayton                                                                   cfa,
1455082c5fdSGreg Clayton                                                                   range.GetBaseAddress(),
1465082c5fdSGreg Clayton                                                                   &inline_sc));                                           // The symbol context for this inline frame
1475082c5fdSGreg Clayton 
1485082c5fdSGreg Clayton                             if (is_inlined_frame)
14959e8fc1cSGreg Clayton                             {
15059e8fc1cSGreg Clayton                                 // Use the block with the inlined function info
15159e8fc1cSGreg Clayton                                 // as the symbol context since we want this frame
15259e8fc1cSGreg Clayton                                 // to have only the variables for the inlined function
15359e8fc1cSGreg Clayton                                 frame_sp->SetSymbolContextScope (parent_block);
15459e8fc1cSGreg Clayton                             }
15559e8fc1cSGreg Clayton                             else
15659e8fc1cSGreg Clayton                             {
15759e8fc1cSGreg Clayton                                 // This block is not inlined with means it has no
15859e8fc1cSGreg Clayton                                 // inlined parents either, so we want to use the top
15959e8fc1cSGreg Clayton                                 // most function block.
16059e8fc1cSGreg Clayton                                 frame_sp->SetSymbolContextScope (&unwind_frame_sp->GetSymbolContext (eSymbolContextFunction).function->GetBlock(false));
16159e8fc1cSGreg Clayton                             }
1625082c5fdSGreg Clayton 
1635082c5fdSGreg Clayton                             m_frames.push_back (frame_sp);
1645082c5fdSGreg Clayton                         }
1655082c5fdSGreg Clayton                     }
1665082c5fdSGreg Clayton                 }
16759e8fc1cSGreg Clayton             }
1685082c5fdSGreg Clayton             StackFrameList *prev_frames = m_prev_frames_ap.get();
1695082c5fdSGreg Clayton             if (prev_frames)
17012daf946SGreg Clayton             {
1715082c5fdSGreg Clayton                 StackFrameList *curr_frames = this;
1725082c5fdSGreg Clayton 
1735082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
17468275d5eSGreg Clayton                 s.PutCString("\nprev_frames:\n");
1755082c5fdSGreg Clayton                 prev_frames->Dump (&s);
17668275d5eSGreg Clayton                 s.PutCString("\ncurr_frames:\n");
1775082c5fdSGreg Clayton                 curr_frames->Dump (&s);
1785082c5fdSGreg Clayton                 s.EOL();
1795082c5fdSGreg Clayton #endif
1805082c5fdSGreg Clayton                 size_t curr_frame_num, prev_frame_num;
1815082c5fdSGreg Clayton 
1825082c5fdSGreg Clayton                 for (curr_frame_num = curr_frames->m_frames.size(), prev_frame_num = prev_frames->m_frames.size();
1835082c5fdSGreg Clayton                      curr_frame_num > 0 && prev_frame_num > 0;
1845082c5fdSGreg Clayton                      --curr_frame_num, --prev_frame_num)
1855082c5fdSGreg Clayton                 {
1865082c5fdSGreg Clayton                     const size_t curr_frame_idx = curr_frame_num-1;
1875082c5fdSGreg Clayton                     const size_t prev_frame_idx = prev_frame_num-1;
1885082c5fdSGreg Clayton                     StackFrameSP curr_frame_sp (curr_frames->m_frames[curr_frame_idx]);
1895082c5fdSGreg Clayton                     StackFrameSP prev_frame_sp (prev_frames->m_frames[prev_frame_idx]);
1905082c5fdSGreg Clayton 
1915082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
1925082c5fdSGreg Clayton                     s.Printf("\nCurrent frame #%u ", curr_frame_idx);
1935082c5fdSGreg Clayton                     if (curr_frame_sp)
1945082c5fdSGreg Clayton                         curr_frame_sp->Dump (&s, true);
1955082c5fdSGreg Clayton                     else
1965082c5fdSGreg Clayton                         s.PutCString("NULL");
1975082c5fdSGreg Clayton                     s.Printf("\nPrevious frame #%u ", prev_frame_idx);
1985082c5fdSGreg Clayton                     if (prev_frame_sp)
1995082c5fdSGreg Clayton                         prev_frame_sp->Dump (&s, true);
2005082c5fdSGreg Clayton                     else
2015082c5fdSGreg Clayton                         s.PutCString("NULL");
2025082c5fdSGreg Clayton                     s.EOL();
2035082c5fdSGreg Clayton #endif
2045082c5fdSGreg Clayton 
2055082c5fdSGreg Clayton                     StackFrame *curr_frame = curr_frame_sp.get();
2065082c5fdSGreg Clayton                     StackFrame *prev_frame = prev_frame_sp.get();
2075082c5fdSGreg Clayton 
2085082c5fdSGreg Clayton                     if (curr_frame == NULL || prev_frame == NULL)
2095082c5fdSGreg Clayton                         break;
2105082c5fdSGreg Clayton 
21159e8fc1cSGreg Clayton                     // Check the stack ID to make sure they are equal
21259e8fc1cSGreg Clayton                     if (curr_frame->GetStackID() != prev_frame->GetStackID())
2135082c5fdSGreg Clayton                         break;
2145082c5fdSGreg Clayton 
21559e8fc1cSGreg Clayton                     prev_frame->UpdatePreviousFrameFromCurrentFrame (*curr_frame);
21659e8fc1cSGreg Clayton                     // Now copy the fixed up previous frame into the current frames
21759e8fc1cSGreg Clayton                     // so the pointer doesn't change
21859e8fc1cSGreg Clayton                     m_frames[curr_frame_idx] = prev_frame_sp;
21959e8fc1cSGreg Clayton                     //curr_frame->UpdateCurrentFrameFromPreviousFrame (*prev_frame);
2205082c5fdSGreg Clayton 
2215082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
22268275d5eSGreg Clayton                     s.Printf("\n    Copying previous frame to current frame");
2235082c5fdSGreg Clayton #endif
2245082c5fdSGreg Clayton                 }
2255082c5fdSGreg Clayton                 // We are done with the old stack frame list, we can release it now
2265082c5fdSGreg Clayton                 m_prev_frames_ap.release();
2275082c5fdSGreg Clayton                 prev_frames = NULL;
2285082c5fdSGreg Clayton             }
22968275d5eSGreg Clayton 
23068275d5eSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
23168275d5eSGreg Clayton                 s.PutCString("\n\nNew frames:\n");
23268275d5eSGreg Clayton                 Dump (&s);
23368275d5eSGreg Clayton                 s.EOL();
23468275d5eSGreg Clayton #endif
23512daf946SGreg Clayton         }
23612daf946SGreg Clayton         else
23712daf946SGreg Clayton         {
2385082c5fdSGreg Clayton             m_frames.resize(m_thread.GetUnwinder()->GetFrameCount());
23912daf946SGreg Clayton         }
2405082c5fdSGreg Clayton     }
2415082c5fdSGreg Clayton     return m_frames.size();
24230fdc8d8SChris Lattner }
24330fdc8d8SChris Lattner 
2445082c5fdSGreg Clayton void
2455082c5fdSGreg Clayton StackFrameList::Dump (Stream *s)
24630fdc8d8SChris Lattner {
2475082c5fdSGreg Clayton     if (s == NULL)
2485082c5fdSGreg Clayton         return;
2495082c5fdSGreg Clayton     Mutex::Locker locker (m_mutex);
25030fdc8d8SChris Lattner 
2515082c5fdSGreg Clayton     const_iterator pos, begin = m_frames.begin(), end = m_frames.end();
2525082c5fdSGreg Clayton     for (pos = begin; pos != end; ++pos)
25312daf946SGreg Clayton     {
2545082c5fdSGreg Clayton         StackFrame *frame = (*pos).get();
2555082c5fdSGreg Clayton         s->Printf("%p: ", frame);
2565082c5fdSGreg Clayton         if (frame)
25759e8fc1cSGreg Clayton         {
25859e8fc1cSGreg Clayton             frame->GetStackID().Dump (s);
259*6dadd508SGreg Clayton             frame->Dump(s, true, false);
26059e8fc1cSGreg Clayton         }
2615082c5fdSGreg Clayton         else
2625082c5fdSGreg Clayton             s->Printf("frame #%u", std::distance (begin, pos));
2635082c5fdSGreg Clayton         s->EOL();
26412daf946SGreg Clayton     }
2655082c5fdSGreg Clayton     s->EOL();
2665082c5fdSGreg Clayton }
26712daf946SGreg Clayton 
26830fdc8d8SChris Lattner StackFrameSP
26912daf946SGreg Clayton StackFrameList::GetFrameAtIndex (uint32_t idx)
27030fdc8d8SChris Lattner {
27130fdc8d8SChris Lattner     StackFrameSP frame_sp;
27230fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
2735082c5fdSGreg Clayton     if (idx < m_frames.size())
2745082c5fdSGreg Clayton         frame_sp = m_frames[idx];
27512daf946SGreg Clayton 
2765082c5fdSGreg Clayton     if (frame_sp)
27712daf946SGreg Clayton         return frame_sp;
27812daf946SGreg Clayton 
27912daf946SGreg Clayton     // Special case the first frame (idx == 0) so that we don't need to
28012daf946SGreg Clayton     // know how many stack frames there are to get it. If we need any other
28112daf946SGreg Clayton     // frames, then we do need to know if "idx" is a valid index.
28212daf946SGreg Clayton     if (idx == 0)
28312daf946SGreg Clayton     {
28412daf946SGreg Clayton         // If this is the first frame, we want to share the thread register
28512daf946SGreg Clayton         // context with the stack frame at index zero.
28612daf946SGreg Clayton         m_thread.GetRegisterContext();
28712daf946SGreg Clayton         assert (m_thread.m_reg_context_sp.get());
28812daf946SGreg Clayton         frame_sp.reset (new StackFrame (0,
28912daf946SGreg Clayton                                         0,
29012daf946SGreg Clayton                                         m_thread,
29112daf946SGreg Clayton                                         m_thread.m_reg_context_sp,
29212daf946SGreg Clayton                                         m_thread.m_reg_context_sp->GetSP(),
29312daf946SGreg Clayton                                         m_thread.m_reg_context_sp->GetPC(),
29412daf946SGreg Clayton                                         NULL));
2950445d8f4SGreg Clayton 
2965082c5fdSGreg Clayton         SetFrameAtIndex(idx, frame_sp);
29712daf946SGreg Clayton     }
29812daf946SGreg Clayton     else if (idx < GetNumFrames())
29912daf946SGreg Clayton     {
30012daf946SGreg Clayton         if (m_show_inlined_frames)
30112daf946SGreg Clayton         {
3025082c5fdSGreg Clayton             // When inline frames are enabled we cache up all frames in GetNumFrames()
3035082c5fdSGreg Clayton             frame_sp = m_frames[idx];
30412daf946SGreg Clayton         }
30512daf946SGreg Clayton         else
30612daf946SGreg Clayton         {
30712daf946SGreg Clayton             Unwind *unwinder = m_thread.GetUnwinder ();
30812daf946SGreg Clayton             if (unwinder)
30912daf946SGreg Clayton             {
31012daf946SGreg Clayton                 addr_t pc, cfa;
31112daf946SGreg Clayton                 if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
3125082c5fdSGreg Clayton                 {
3130445d8f4SGreg Clayton                     frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL));
31459e8fc1cSGreg Clayton 
31559e8fc1cSGreg Clayton                     Function *function = frame_sp->GetSymbolContext (eSymbolContextFunction).function;
31659e8fc1cSGreg Clayton                     if (function)
31759e8fc1cSGreg Clayton                     {
31859e8fc1cSGreg Clayton                         // When we aren't showing inline functions we always use
31959e8fc1cSGreg Clayton                         // the top most function block as the scope.
32059e8fc1cSGreg Clayton                         frame_sp->SetSymbolContextScope (&function->GetBlock(false));
32159e8fc1cSGreg Clayton                     }
32259e8fc1cSGreg Clayton                     else
32359e8fc1cSGreg Clayton                     {
32459e8fc1cSGreg Clayton                         // Set the symbol scope from the symbol regardless if it is NULL or valid.
32559e8fc1cSGreg Clayton                         frame_sp->SetSymbolContextScope (frame_sp->GetSymbolContext (eSymbolContextSymbol).symbol);
32659e8fc1cSGreg Clayton                     }
3275082c5fdSGreg Clayton                     SetFrameAtIndex(idx, frame_sp);
32812daf946SGreg Clayton                 }
32912daf946SGreg Clayton             }
33012daf946SGreg Clayton         }
33130fdc8d8SChris Lattner     }
33230fdc8d8SChris Lattner     return frame_sp;
33330fdc8d8SChris Lattner }
33430fdc8d8SChris Lattner 
33512daf946SGreg Clayton 
33612daf946SGreg Clayton bool
3375082c5fdSGreg Clayton StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
33812daf946SGreg Clayton {
3395082c5fdSGreg Clayton     if (idx >= m_frames.size())
3405082c5fdSGreg Clayton         m_frames.resize(idx + 1);
34112daf946SGreg Clayton     // Make sure allocation succeeded by checking bounds again
3425082c5fdSGreg Clayton     if (idx < m_frames.size())
34312daf946SGreg Clayton     {
3445082c5fdSGreg Clayton         m_frames[idx] = frame_sp;
34530fdc8d8SChris Lattner         return true;
34630fdc8d8SChris Lattner     }
34730fdc8d8SChris Lattner     return false;   // resize failed, out of memory?
34830fdc8d8SChris Lattner }
34930fdc8d8SChris Lattner 
35030fdc8d8SChris Lattner uint32_t
3512976d00aSJim Ingham StackFrameList::GetSelectedFrameIndex () const
35230fdc8d8SChris Lattner {
35330fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
3542976d00aSJim Ingham     return m_selected_frame_idx;
35530fdc8d8SChris Lattner }
35630fdc8d8SChris Lattner 
35730fdc8d8SChris Lattner 
35830fdc8d8SChris Lattner uint32_t
3592976d00aSJim Ingham StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame)
36030fdc8d8SChris Lattner {
36130fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
36212daf946SGreg Clayton     const_iterator pos;
3635082c5fdSGreg Clayton     const_iterator begin = m_frames.begin();
3645082c5fdSGreg Clayton     const_iterator end = m_frames.end();
36530fdc8d8SChris Lattner     for (pos = begin; pos != end; ++pos)
36630fdc8d8SChris Lattner     {
36730fdc8d8SChris Lattner         if (pos->get() == frame)
36830fdc8d8SChris Lattner         {
3692976d00aSJim Ingham             m_selected_frame_idx = std::distance (begin, pos);
3702976d00aSJim Ingham             return m_selected_frame_idx;
37130fdc8d8SChris Lattner         }
37230fdc8d8SChris Lattner     }
3732976d00aSJim Ingham     m_selected_frame_idx = 0;
3742976d00aSJim Ingham     return m_selected_frame_idx;
37530fdc8d8SChris Lattner }
37630fdc8d8SChris Lattner 
37730fdc8d8SChris Lattner // Mark a stack frame as the current frame using the frame index
37830fdc8d8SChris Lattner void
3792976d00aSJim Ingham StackFrameList::SetSelectedFrameByIndex (uint32_t idx)
38030fdc8d8SChris Lattner {
38130fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
3822976d00aSJim Ingham     m_selected_frame_idx = idx;
38330fdc8d8SChris Lattner }
38430fdc8d8SChris Lattner 
38530fdc8d8SChris Lattner // The thread has been run, reset the number stack frames to zero so we can
38630fdc8d8SChris Lattner // determine how many frames we have lazily.
38730fdc8d8SChris Lattner void
38830fdc8d8SChris Lattner StackFrameList::Clear ()
38930fdc8d8SChris Lattner {
39030fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
3915082c5fdSGreg Clayton     m_frames.clear();
39230fdc8d8SChris Lattner }
39330fdc8d8SChris Lattner 
39430fdc8d8SChris Lattner void
39530fdc8d8SChris Lattner StackFrameList::InvalidateFrames (uint32_t start_idx)
39630fdc8d8SChris Lattner {
39730fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
39812daf946SGreg Clayton     if (m_show_inlined_frames)
39912daf946SGreg Clayton     {
40012daf946SGreg Clayton         Clear();
40112daf946SGreg Clayton     }
40212daf946SGreg Clayton     else
40312daf946SGreg Clayton     {
4045082c5fdSGreg Clayton         const size_t num_frames = m_frames.size();
40530fdc8d8SChris Lattner         while (start_idx < num_frames)
40630fdc8d8SChris Lattner         {
4075082c5fdSGreg Clayton             m_frames[start_idx].reset();
40830fdc8d8SChris Lattner             ++start_idx;
40930fdc8d8SChris Lattner         }
41030fdc8d8SChris Lattner     }
41112daf946SGreg Clayton }
412