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"
1912daf946SGreg Clayton #include "lldb/Target/RegisterContext.h"
2030fdc8d8SChris Lattner #include "lldb/Target/StackFrame.h"
2112daf946SGreg Clayton #include "lldb/Target/Thread.h"
2212daf946SGreg Clayton #include "lldb/Target/Unwind.h"
2330fdc8d8SChris Lattner 
245082c5fdSGreg Clayton //#define DEBUG_STACK_FRAMES 1
255082c5fdSGreg Clayton 
2630fdc8d8SChris Lattner using namespace lldb;
2730fdc8d8SChris Lattner using namespace lldb_private;
2830fdc8d8SChris Lattner 
2930fdc8d8SChris Lattner //----------------------------------------------------------------------
3030fdc8d8SChris Lattner // StackFrameList constructor
3130fdc8d8SChris Lattner //----------------------------------------------------------------------
320445d8f4SGreg Clayton StackFrameList::StackFrameList(Thread &thread, StackFrameList *prev_frames, bool show_inline_frames) :
3312daf946SGreg Clayton     m_thread (thread),
340445d8f4SGreg Clayton     m_prev_frames_ap (prev_frames),
3512daf946SGreg Clayton     m_show_inlined_frames (show_inline_frames),
3630fdc8d8SChris Lattner     m_mutex (Mutex::eMutexTypeRecursive),
375082c5fdSGreg Clayton     m_frames (),
382976d00aSJim Ingham     m_selected_frame_idx (0)
3930fdc8d8SChris Lattner {
4030fdc8d8SChris Lattner }
4130fdc8d8SChris Lattner 
4230fdc8d8SChris Lattner //----------------------------------------------------------------------
4330fdc8d8SChris Lattner // Destructor
4430fdc8d8SChris Lattner //----------------------------------------------------------------------
4530fdc8d8SChris Lattner StackFrameList::~StackFrameList()
4630fdc8d8SChris Lattner {
4730fdc8d8SChris Lattner }
4830fdc8d8SChris Lattner 
4930fdc8d8SChris Lattner 
5030fdc8d8SChris Lattner uint32_t
5112daf946SGreg Clayton StackFrameList::GetNumFrames()
5230fdc8d8SChris Lattner {
5330fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
5412daf946SGreg Clayton 
555082c5fdSGreg Clayton     if (m_frames.size() <= 1)
565082c5fdSGreg Clayton     {
5712daf946SGreg Clayton         if (m_show_inlined_frames)
5812daf946SGreg Clayton         {
595082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
605082c5fdSGreg Clayton             StreamFile s(stdout);
615082c5fdSGreg Clayton #endif
6212daf946SGreg Clayton             Unwind *unwinder = m_thread.GetUnwinder ();
635082c5fdSGreg Clayton             addr_t pc, cfa;
645082c5fdSGreg Clayton 
6512daf946SGreg Clayton             // If we are going to show inlined stack frames as actual frames,
6612daf946SGreg Clayton             // we need to calculate all concrete frames first, then iterate
6712daf946SGreg Clayton             // through all of them and count up how many inlined functions are
685082c5fdSGreg Clayton             // in each frame.
695082c5fdSGreg Clayton             const uint32_t unwind_frame_count = unwinder->GetFrameCount();
7012daf946SGreg Clayton 
715082c5fdSGreg Clayton             StackFrameSP unwind_frame_sp;
725082c5fdSGreg Clayton             for (uint32_t idx=0; idx<unwind_frame_count; ++idx)
7312daf946SGreg Clayton             {
7412daf946SGreg Clayton                 if (idx == 0)
7512daf946SGreg Clayton                 {
765082c5fdSGreg Clayton                     // We might have already created frame zero, only create it
775082c5fdSGreg Clayton                     // if we need to
785082c5fdSGreg Clayton                     if (m_frames.empty())
795082c5fdSGreg Clayton                     {
8012daf946SGreg Clayton                         m_thread.GetRegisterContext();
815082c5fdSGreg Clayton                         unwind_frame_sp.reset (new StackFrame (m_frames.size(),
825082c5fdSGreg Clayton                                                                idx,
8312daf946SGreg Clayton                                                                m_thread,
8412daf946SGreg Clayton                                                                m_thread.m_reg_context_sp,
8512daf946SGreg Clayton                                                                m_thread.m_reg_context_sp->GetSP(),
8612daf946SGreg Clayton                                                                m_thread.m_reg_context_sp->GetPC(),
8712daf946SGreg Clayton                                                                NULL));
885082c5fdSGreg Clayton                         m_frames.push_back (unwind_frame_sp);
895082c5fdSGreg Clayton                     }
905082c5fdSGreg Clayton                     else
915082c5fdSGreg Clayton                     {
925082c5fdSGreg Clayton                         unwind_frame_sp = m_frames.front();
935082c5fdSGreg Clayton                     }
9412daf946SGreg Clayton                 }
9512daf946SGreg Clayton                 else
9612daf946SGreg Clayton                 {
9712daf946SGreg Clayton                     const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
9812daf946SGreg Clayton                     assert (success);
995082c5fdSGreg Clayton                     unwind_frame_sp.reset (new StackFrame (m_frames.size(), idx, m_thread, cfa, pc, NULL));
1005082c5fdSGreg Clayton                     m_frames.push_back (unwind_frame_sp);
10112daf946SGreg Clayton                 }
10212daf946SGreg Clayton 
1035082c5fdSGreg Clayton                 Block *block = unwind_frame_sp->GetSymbolContext (eSymbolContextBlock).block;
10412daf946SGreg Clayton 
10512daf946SGreg Clayton                 if (block)
10612daf946SGreg Clayton                 {
1075082c5fdSGreg Clayton                     for (block = block->GetContainingInlinedBlock(); block != NULL; block = block->GetInlinedParent ())
1080445d8f4SGreg Clayton                     {
1095082c5fdSGreg Clayton                         SymbolContext inline_sc;
1105082c5fdSGreg Clayton                         Block *parent_block = block->GetInlinedParent();
11112daf946SGreg Clayton 
1125082c5fdSGreg Clayton                         const bool is_inlined_frame = parent_block != NULL;
1135082c5fdSGreg Clayton 
1145082c5fdSGreg Clayton                         if (parent_block == NULL)
1155082c5fdSGreg Clayton                             parent_block = block->GetParent();
1165082c5fdSGreg Clayton 
1175082c5fdSGreg Clayton                         parent_block->CalculateSymbolContext (&inline_sc);
1185082c5fdSGreg Clayton 
1195082c5fdSGreg Clayton                         Address previous_frame_lookup_addr (m_frames.back()->GetFrameCodeAddress());
1205082c5fdSGreg Clayton                         if (unwind_frame_sp->GetFrameIndex() > 0 && m_frames.back().get() == unwind_frame_sp.get())
1215082c5fdSGreg Clayton                             previous_frame_lookup_addr.Slide (-1);
1225082c5fdSGreg Clayton 
1235082c5fdSGreg Clayton                         AddressRange range;
1245082c5fdSGreg Clayton                         block->GetRangeContainingAddress (previous_frame_lookup_addr, range);
1255082c5fdSGreg Clayton 
1265082c5fdSGreg Clayton                         const InlineFunctionInfo* inline_info = block->InlinedFunctionInfo();
1275082c5fdSGreg Clayton                         assert (inline_info);
1285082c5fdSGreg Clayton                         inline_sc.line_entry.range.GetBaseAddress() = m_frames.back()->GetFrameCodeAddress();
1295082c5fdSGreg Clayton                         inline_sc.line_entry.file = inline_info->GetCallSite().GetFile();
1305082c5fdSGreg Clayton                         inline_sc.line_entry.line = inline_info->GetCallSite().GetLine();
1315082c5fdSGreg Clayton                         inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn();
1325082c5fdSGreg Clayton 
1335082c5fdSGreg Clayton                         StackFrameSP frame_sp(new StackFrame (m_frames.size(),
1345082c5fdSGreg Clayton                                                               idx,
1355082c5fdSGreg Clayton                                                               m_thread,
1365082c5fdSGreg Clayton                                                               unwind_frame_sp->GetRegisterContextSP (),
1375082c5fdSGreg Clayton                                                               unwind_frame_sp->GetStackID().GetCallFrameAddress(),  // CFA
1385082c5fdSGreg Clayton                                                               range.GetBaseAddress(),
1395082c5fdSGreg Clayton                                                               &inline_sc));                                           // The symbol context for this inline frame
1405082c5fdSGreg Clayton 
1415082c5fdSGreg Clayton                         if (is_inlined_frame)
1425082c5fdSGreg Clayton                             frame_sp->SetInlineBlockID (block->GetID());
1435082c5fdSGreg Clayton 
1445082c5fdSGreg Clayton                         m_frames.push_back (frame_sp);
1455082c5fdSGreg Clayton                     }
1465082c5fdSGreg Clayton                 }
1475082c5fdSGreg Clayton             }
1485082c5fdSGreg Clayton             StackFrameList *prev_frames = m_prev_frames_ap.get();
1495082c5fdSGreg Clayton             if (prev_frames)
15012daf946SGreg Clayton             {
1515082c5fdSGreg Clayton                 StackFrameList *curr_frames = this;
1525082c5fdSGreg Clayton 
1535082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
154*68275d5eSGreg Clayton                 s.PutCString("\nprev_frames:\n");
1555082c5fdSGreg Clayton                 prev_frames->Dump (&s);
156*68275d5eSGreg Clayton                 s.PutCString("\ncurr_frames:\n");
1575082c5fdSGreg Clayton                 curr_frames->Dump (&s);
1585082c5fdSGreg Clayton                 s.EOL();
1595082c5fdSGreg Clayton #endif
1605082c5fdSGreg Clayton                 size_t curr_frame_num, prev_frame_num;
1615082c5fdSGreg Clayton 
1625082c5fdSGreg Clayton                 for (curr_frame_num = curr_frames->m_frames.size(), prev_frame_num = prev_frames->m_frames.size();
1635082c5fdSGreg Clayton                      curr_frame_num > 0 && prev_frame_num > 0;
1645082c5fdSGreg Clayton                      --curr_frame_num, --prev_frame_num)
1655082c5fdSGreg Clayton                 {
1665082c5fdSGreg Clayton                     const size_t curr_frame_idx = curr_frame_num-1;
1675082c5fdSGreg Clayton                     const size_t prev_frame_idx = prev_frame_num-1;
1685082c5fdSGreg Clayton                     StackFrameSP curr_frame_sp (curr_frames->m_frames[curr_frame_idx]);
1695082c5fdSGreg Clayton                     StackFrameSP prev_frame_sp (prev_frames->m_frames[prev_frame_idx]);
1705082c5fdSGreg Clayton 
1715082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
1725082c5fdSGreg Clayton                     s.Printf("\nCurrent frame #%u ", curr_frame_idx);
1735082c5fdSGreg Clayton                     if (curr_frame_sp)
1745082c5fdSGreg Clayton                         curr_frame_sp->Dump (&s, true);
1755082c5fdSGreg Clayton                     else
1765082c5fdSGreg Clayton                         s.PutCString("NULL");
1775082c5fdSGreg Clayton                     s.Printf("\nPrevious frame #%u ", prev_frame_idx);
1785082c5fdSGreg Clayton                     if (prev_frame_sp)
1795082c5fdSGreg Clayton                         prev_frame_sp->Dump (&s, true);
1805082c5fdSGreg Clayton                     else
1815082c5fdSGreg Clayton                         s.PutCString("NULL");
1825082c5fdSGreg Clayton                     s.EOL();
1835082c5fdSGreg Clayton #endif
1845082c5fdSGreg Clayton 
1855082c5fdSGreg Clayton                     StackFrame *curr_frame = curr_frame_sp.get();
1865082c5fdSGreg Clayton                     StackFrame *prev_frame = prev_frame_sp.get();
1875082c5fdSGreg Clayton 
1885082c5fdSGreg Clayton                     if (curr_frame == NULL || prev_frame == NULL)
1895082c5fdSGreg Clayton                         break;
1905082c5fdSGreg Clayton 
1915082c5fdSGreg Clayton                     // Do a quick sanity check to see if the CFA values are the same.
1925082c5fdSGreg Clayton                     if (curr_frame->m_id.GetCallFrameAddress() != prev_frame->m_id.GetCallFrameAddress())
1935082c5fdSGreg Clayton                         break;
1945082c5fdSGreg Clayton 
1955082c5fdSGreg Clayton                     // Now check our function or symbol
1965082c5fdSGreg Clayton                     SymbolContext curr_sc (curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol));
1975082c5fdSGreg Clayton                     SymbolContext prev_sc (prev_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol));
1985082c5fdSGreg Clayton                     if (curr_sc.function && curr_sc.function == prev_sc.function)
1995082c5fdSGreg Clayton                     {
2005082c5fdSGreg Clayton                         // Same function
2015082c5fdSGreg Clayton                         if (curr_sc.block != prev_sc.block)
2025082c5fdSGreg Clayton                         {
2035082c5fdSGreg Clayton                             // Same function different block
2045082c5fdSGreg Clayton                             if (m_show_inlined_frames)
2055082c5fdSGreg Clayton                                 break;
20612daf946SGreg Clayton                         }
20712daf946SGreg Clayton                     }
2085082c5fdSGreg Clayton                     else if (curr_sc.symbol && curr_sc.symbol == prev_sc.symbol)
2095082c5fdSGreg Clayton                     {
2105082c5fdSGreg Clayton                         // Same symbol
21112daf946SGreg Clayton                     }
2125082c5fdSGreg Clayton                     else if (curr_frame->GetFrameCodeAddress() != prev_frame->GetFrameCodeAddress())
2135082c5fdSGreg Clayton                     {
2145082c5fdSGreg Clayton                         // No symbols for this frame and the PC was different
2155082c5fdSGreg Clayton                         break;
21612daf946SGreg Clayton                     }
2175082c5fdSGreg Clayton 
218*68275d5eSGreg Clayton                     curr_frame->UpdateCurrentFrameFromPreviousFrame (*prev_frame);
2195082c5fdSGreg Clayton 
2205082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
221*68275d5eSGreg Clayton                     s.Printf("\n    Copying previous frame to current frame");
2225082c5fdSGreg Clayton #endif
2235082c5fdSGreg Clayton                 }
2245082c5fdSGreg Clayton                 // We are done with the old stack frame list, we can release it now
2255082c5fdSGreg Clayton                 m_prev_frames_ap.release();
2265082c5fdSGreg Clayton                 prev_frames = NULL;
2275082c5fdSGreg Clayton             }
228*68275d5eSGreg Clayton 
229*68275d5eSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
230*68275d5eSGreg Clayton                 s.PutCString("\n\nNew frames:\n");
231*68275d5eSGreg Clayton                 Dump (&s);
232*68275d5eSGreg Clayton                 s.EOL();
233*68275d5eSGreg Clayton #endif
23412daf946SGreg Clayton         }
23512daf946SGreg Clayton         else
23612daf946SGreg Clayton         {
2375082c5fdSGreg Clayton             m_frames.resize(m_thread.GetUnwinder()->GetFrameCount());
23812daf946SGreg Clayton         }
2395082c5fdSGreg Clayton     }
2405082c5fdSGreg Clayton     return m_frames.size();
24130fdc8d8SChris Lattner }
24230fdc8d8SChris Lattner 
2435082c5fdSGreg Clayton void
2445082c5fdSGreg Clayton StackFrameList::Dump (Stream *s)
24530fdc8d8SChris Lattner {
2465082c5fdSGreg Clayton     if (s == NULL)
2475082c5fdSGreg Clayton         return;
2485082c5fdSGreg Clayton     Mutex::Locker locker (m_mutex);
24930fdc8d8SChris Lattner 
2505082c5fdSGreg Clayton     const_iterator pos, begin = m_frames.begin(), end = m_frames.end();
2515082c5fdSGreg Clayton     for (pos = begin; pos != end; ++pos)
25212daf946SGreg Clayton     {
2535082c5fdSGreg Clayton         StackFrame *frame = (*pos).get();
2545082c5fdSGreg Clayton         s->Printf("%p: ", frame);
2555082c5fdSGreg Clayton         if (frame)
2565082c5fdSGreg Clayton             frame->Dump(s, true);
2575082c5fdSGreg Clayton         else
2585082c5fdSGreg Clayton             s->Printf("frame #%u", std::distance (begin, pos));
2595082c5fdSGreg Clayton         s->EOL();
26012daf946SGreg Clayton     }
2615082c5fdSGreg Clayton     s->EOL();
2625082c5fdSGreg Clayton }
26312daf946SGreg Clayton 
26430fdc8d8SChris Lattner StackFrameSP
26512daf946SGreg Clayton StackFrameList::GetFrameAtIndex (uint32_t idx)
26630fdc8d8SChris Lattner {
26730fdc8d8SChris Lattner     StackFrameSP frame_sp;
26830fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
2695082c5fdSGreg Clayton     if (idx < m_frames.size())
2705082c5fdSGreg Clayton         frame_sp = m_frames[idx];
27112daf946SGreg Clayton 
2725082c5fdSGreg Clayton     if (frame_sp)
27312daf946SGreg Clayton         return frame_sp;
27412daf946SGreg Clayton 
27512daf946SGreg Clayton     // Special case the first frame (idx == 0) so that we don't need to
27612daf946SGreg Clayton     // know how many stack frames there are to get it. If we need any other
27712daf946SGreg Clayton     // frames, then we do need to know if "idx" is a valid index.
27812daf946SGreg Clayton     if (idx == 0)
27912daf946SGreg Clayton     {
28012daf946SGreg Clayton         // If this is the first frame, we want to share the thread register
28112daf946SGreg Clayton         // context with the stack frame at index zero.
28212daf946SGreg Clayton         m_thread.GetRegisterContext();
28312daf946SGreg Clayton         assert (m_thread.m_reg_context_sp.get());
28412daf946SGreg Clayton         frame_sp.reset (new StackFrame (0,
28512daf946SGreg Clayton                                         0,
28612daf946SGreg Clayton                                         m_thread,
28712daf946SGreg Clayton                                         m_thread.m_reg_context_sp,
28812daf946SGreg Clayton                                         m_thread.m_reg_context_sp->GetSP(),
28912daf946SGreg Clayton                                         m_thread.m_reg_context_sp->GetPC(),
29012daf946SGreg Clayton                                         NULL));
2910445d8f4SGreg Clayton 
2925082c5fdSGreg Clayton         if (m_show_inlined_frames)
2930445d8f4SGreg Clayton         {
2945082c5fdSGreg Clayton             Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block;
2950445d8f4SGreg Clayton 
2965082c5fdSGreg Clayton             if (block)
2975082c5fdSGreg Clayton             {
2985082c5fdSGreg Clayton                 Block *inline_block = block->GetContainingInlinedBlock();
2995082c5fdSGreg Clayton                 if (inline_block)
3005082c5fdSGreg Clayton                     frame_sp->SetInlineBlockID (inline_block->GetID());
3015082c5fdSGreg Clayton             }
3025082c5fdSGreg Clayton         }
3035082c5fdSGreg Clayton         SetFrameAtIndex(idx, frame_sp);
30412daf946SGreg Clayton     }
30512daf946SGreg Clayton     else if (idx < GetNumFrames())
30612daf946SGreg Clayton     {
30712daf946SGreg Clayton         if (m_show_inlined_frames)
30812daf946SGreg Clayton         {
3095082c5fdSGreg Clayton             // When inline frames are enabled we cache up all frames in GetNumFrames()
3105082c5fdSGreg Clayton             frame_sp = m_frames[idx];
31112daf946SGreg Clayton         }
31212daf946SGreg Clayton         else
31312daf946SGreg Clayton         {
31412daf946SGreg Clayton             Unwind *unwinder = m_thread.GetUnwinder ();
31512daf946SGreg Clayton             if (unwinder)
31612daf946SGreg Clayton             {
31712daf946SGreg Clayton                 addr_t pc, cfa;
31812daf946SGreg Clayton                 if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
3195082c5fdSGreg Clayton                 {
3200445d8f4SGreg Clayton                     frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL));
3215082c5fdSGreg Clayton                     SetFrameAtIndex(idx, frame_sp);
32212daf946SGreg Clayton                 }
32312daf946SGreg Clayton             }
32412daf946SGreg Clayton         }
3250445d8f4SGreg Clayton 
32630fdc8d8SChris Lattner     }
32730fdc8d8SChris Lattner     return frame_sp;
32830fdc8d8SChris Lattner }
32930fdc8d8SChris Lattner 
33012daf946SGreg Clayton 
33112daf946SGreg Clayton bool
3325082c5fdSGreg Clayton StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
33312daf946SGreg Clayton {
3345082c5fdSGreg Clayton     if (idx >= m_frames.size())
3355082c5fdSGreg Clayton         m_frames.resize(idx + 1);
33612daf946SGreg Clayton     // Make sure allocation succeeded by checking bounds again
3375082c5fdSGreg Clayton     if (idx < m_frames.size())
33812daf946SGreg Clayton     {
3395082c5fdSGreg Clayton         m_frames[idx] = frame_sp;
34030fdc8d8SChris Lattner         return true;
34130fdc8d8SChris Lattner     }
34230fdc8d8SChris Lattner     return false;   // resize failed, out of memory?
34330fdc8d8SChris Lattner }
34430fdc8d8SChris Lattner 
34530fdc8d8SChris Lattner uint32_t
3462976d00aSJim Ingham StackFrameList::GetSelectedFrameIndex () const
34730fdc8d8SChris Lattner {
34830fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
3492976d00aSJim Ingham     return m_selected_frame_idx;
35030fdc8d8SChris Lattner }
35130fdc8d8SChris Lattner 
35230fdc8d8SChris Lattner 
35330fdc8d8SChris Lattner uint32_t
3542976d00aSJim Ingham StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame)
35530fdc8d8SChris Lattner {
35630fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
35712daf946SGreg Clayton     const_iterator pos;
3585082c5fdSGreg Clayton     const_iterator begin = m_frames.begin();
3595082c5fdSGreg Clayton     const_iterator end = m_frames.end();
36030fdc8d8SChris Lattner     for (pos = begin; pos != end; ++pos)
36130fdc8d8SChris Lattner     {
36230fdc8d8SChris Lattner         if (pos->get() == frame)
36330fdc8d8SChris Lattner         {
3642976d00aSJim Ingham             m_selected_frame_idx = std::distance (begin, pos);
3652976d00aSJim Ingham             return m_selected_frame_idx;
36630fdc8d8SChris Lattner         }
36730fdc8d8SChris Lattner     }
3682976d00aSJim Ingham     m_selected_frame_idx = 0;
3692976d00aSJim Ingham     return m_selected_frame_idx;
37030fdc8d8SChris Lattner }
37130fdc8d8SChris Lattner 
37230fdc8d8SChris Lattner // Mark a stack frame as the current frame using the frame index
37330fdc8d8SChris Lattner void
3742976d00aSJim Ingham StackFrameList::SetSelectedFrameByIndex (uint32_t idx)
37530fdc8d8SChris Lattner {
37630fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
3772976d00aSJim Ingham     m_selected_frame_idx = idx;
37830fdc8d8SChris Lattner }
37930fdc8d8SChris Lattner 
38030fdc8d8SChris Lattner // The thread has been run, reset the number stack frames to zero so we can
38130fdc8d8SChris Lattner // determine how many frames we have lazily.
38230fdc8d8SChris Lattner void
38330fdc8d8SChris Lattner StackFrameList::Clear ()
38430fdc8d8SChris Lattner {
38530fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
3865082c5fdSGreg Clayton     m_frames.clear();
38730fdc8d8SChris Lattner }
38830fdc8d8SChris Lattner 
38930fdc8d8SChris Lattner void
39030fdc8d8SChris Lattner StackFrameList::InvalidateFrames (uint32_t start_idx)
39130fdc8d8SChris Lattner {
39230fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
39312daf946SGreg Clayton     if (m_show_inlined_frames)
39412daf946SGreg Clayton     {
39512daf946SGreg Clayton         Clear();
39612daf946SGreg Clayton     }
39712daf946SGreg Clayton     else
39812daf946SGreg Clayton     {
3995082c5fdSGreg Clayton         const size_t num_frames = m_frames.size();
40030fdc8d8SChris Lattner         while (start_idx < num_frames)
40130fdc8d8SChris Lattner         {
4025082c5fdSGreg Clayton             m_frames[start_idx].reset();
40330fdc8d8SChris Lattner             ++start_idx;
40430fdc8d8SChris Lattner         }
40530fdc8d8SChris Lattner     }
40612daf946SGreg Clayton }
407