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
16*5082c5fdSGreg 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 
24*5082c5fdSGreg Clayton //#define DEBUG_STACK_FRAMES 1
25*5082c5fdSGreg 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),
37*5082c5fdSGreg 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 
55*5082c5fdSGreg Clayton     if (m_frames.size() <= 1)
56*5082c5fdSGreg Clayton     {
5712daf946SGreg Clayton         if (m_show_inlined_frames)
5812daf946SGreg Clayton         {
59*5082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
60*5082c5fdSGreg Clayton             StreamFile s(stdout);
61*5082c5fdSGreg Clayton #endif
6212daf946SGreg Clayton             Unwind *unwinder = m_thread.GetUnwinder ();
63*5082c5fdSGreg Clayton             addr_t pc, cfa;
64*5082c5fdSGreg 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
68*5082c5fdSGreg Clayton             // in each frame.
69*5082c5fdSGreg Clayton             const uint32_t unwind_frame_count = unwinder->GetFrameCount();
7012daf946SGreg Clayton 
71*5082c5fdSGreg Clayton             StackFrameSP unwind_frame_sp;
72*5082c5fdSGreg Clayton             for (uint32_t idx=0; idx<unwind_frame_count; ++idx)
7312daf946SGreg Clayton             {
7412daf946SGreg Clayton                 if (idx == 0)
7512daf946SGreg Clayton                 {
76*5082c5fdSGreg Clayton                     // We might have already created frame zero, only create it
77*5082c5fdSGreg Clayton                     // if we need to
78*5082c5fdSGreg Clayton                     if (m_frames.empty())
79*5082c5fdSGreg Clayton                     {
8012daf946SGreg Clayton                         m_thread.GetRegisterContext();
81*5082c5fdSGreg Clayton                         unwind_frame_sp.reset (new StackFrame (m_frames.size(),
82*5082c5fdSGreg 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));
88*5082c5fdSGreg Clayton                         m_frames.push_back (unwind_frame_sp);
89*5082c5fdSGreg Clayton                     }
90*5082c5fdSGreg Clayton                     else
91*5082c5fdSGreg Clayton                     {
92*5082c5fdSGreg Clayton                         unwind_frame_sp = m_frames.front();
93*5082c5fdSGreg Clayton                     }
9412daf946SGreg Clayton                 }
9512daf946SGreg Clayton                 else
9612daf946SGreg Clayton                 {
9712daf946SGreg Clayton                     const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
9812daf946SGreg Clayton                     assert (success);
99*5082c5fdSGreg Clayton                     unwind_frame_sp.reset (new StackFrame (m_frames.size(), idx, m_thread, cfa, pc, NULL));
100*5082c5fdSGreg Clayton                     m_frames.push_back (unwind_frame_sp);
10112daf946SGreg Clayton                 }
10212daf946SGreg Clayton 
103*5082c5fdSGreg Clayton                 Block *block = unwind_frame_sp->GetSymbolContext (eSymbolContextBlock).block;
10412daf946SGreg Clayton 
10512daf946SGreg Clayton                 if (block)
10612daf946SGreg Clayton                 {
107*5082c5fdSGreg Clayton                     for (block = block->GetContainingInlinedBlock(); block != NULL; block = block->GetInlinedParent ())
1080445d8f4SGreg Clayton                     {
109*5082c5fdSGreg Clayton                         SymbolContext inline_sc;
110*5082c5fdSGreg Clayton                         Block *parent_block = block->GetInlinedParent();
11112daf946SGreg Clayton 
112*5082c5fdSGreg Clayton                         const bool is_inlined_frame = parent_block != NULL;
113*5082c5fdSGreg Clayton 
114*5082c5fdSGreg Clayton                         if (parent_block == NULL)
115*5082c5fdSGreg Clayton                             parent_block = block->GetParent();
116*5082c5fdSGreg Clayton 
117*5082c5fdSGreg Clayton                         parent_block->CalculateSymbolContext (&inline_sc);
118*5082c5fdSGreg Clayton 
119*5082c5fdSGreg Clayton                         Address previous_frame_lookup_addr (m_frames.back()->GetFrameCodeAddress());
120*5082c5fdSGreg Clayton                         if (unwind_frame_sp->GetFrameIndex() > 0 && m_frames.back().get() == unwind_frame_sp.get())
121*5082c5fdSGreg Clayton                             previous_frame_lookup_addr.Slide (-1);
122*5082c5fdSGreg Clayton 
123*5082c5fdSGreg Clayton                         AddressRange range;
124*5082c5fdSGreg Clayton                         block->GetRangeContainingAddress (previous_frame_lookup_addr, range);
125*5082c5fdSGreg Clayton 
126*5082c5fdSGreg Clayton                         const InlineFunctionInfo* inline_info = block->InlinedFunctionInfo();
127*5082c5fdSGreg Clayton                         assert (inline_info);
128*5082c5fdSGreg Clayton                         inline_sc.line_entry.range.GetBaseAddress() = m_frames.back()->GetFrameCodeAddress();
129*5082c5fdSGreg Clayton                         inline_sc.line_entry.file = inline_info->GetCallSite().GetFile();
130*5082c5fdSGreg Clayton                         inline_sc.line_entry.line = inline_info->GetCallSite().GetLine();
131*5082c5fdSGreg Clayton                         inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn();
132*5082c5fdSGreg Clayton 
133*5082c5fdSGreg Clayton                         StackFrameSP frame_sp(new StackFrame (m_frames.size(),
134*5082c5fdSGreg Clayton                                                               idx,
135*5082c5fdSGreg Clayton                                                               m_thread,
136*5082c5fdSGreg Clayton                                                               unwind_frame_sp->GetRegisterContextSP (),
137*5082c5fdSGreg Clayton                                                               unwind_frame_sp->GetStackID().GetCallFrameAddress(),  // CFA
138*5082c5fdSGreg Clayton                                                               range.GetBaseAddress(),
139*5082c5fdSGreg Clayton                                                               &inline_sc));                                           // The symbol context for this inline frame
140*5082c5fdSGreg Clayton 
141*5082c5fdSGreg Clayton                         if (is_inlined_frame)
142*5082c5fdSGreg Clayton                             frame_sp->SetInlineBlockID (block->GetID());
143*5082c5fdSGreg Clayton 
144*5082c5fdSGreg Clayton                         m_frames.push_back (frame_sp);
145*5082c5fdSGreg Clayton                     }
146*5082c5fdSGreg Clayton                 }
147*5082c5fdSGreg Clayton             }
148*5082c5fdSGreg Clayton             StackFrameList *prev_frames = m_prev_frames_ap.get();
149*5082c5fdSGreg Clayton             if (prev_frames)
15012daf946SGreg Clayton             {
151*5082c5fdSGreg Clayton                 StackFrameList *curr_frames = this;
152*5082c5fdSGreg Clayton 
153*5082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
154*5082c5fdSGreg Clayton                 s.PutCString("prev_frames:\n");
155*5082c5fdSGreg Clayton                 prev_frames->Dump (&s);
156*5082c5fdSGreg Clayton                 s.PutCString("curr_frames:\n");
157*5082c5fdSGreg Clayton                 curr_frames->Dump (&s);
158*5082c5fdSGreg Clayton                 s.EOL();
159*5082c5fdSGreg Clayton #endif
160*5082c5fdSGreg Clayton                 size_t curr_frame_num, prev_frame_num;
161*5082c5fdSGreg Clayton 
162*5082c5fdSGreg Clayton                 for (curr_frame_num = curr_frames->m_frames.size(), prev_frame_num = prev_frames->m_frames.size();
163*5082c5fdSGreg Clayton                      curr_frame_num > 0 && prev_frame_num > 0;
164*5082c5fdSGreg Clayton                      --curr_frame_num, --prev_frame_num)
165*5082c5fdSGreg Clayton                 {
166*5082c5fdSGreg Clayton                     const size_t curr_frame_idx = curr_frame_num-1;
167*5082c5fdSGreg Clayton                     const size_t prev_frame_idx = prev_frame_num-1;
168*5082c5fdSGreg Clayton                     StackFrameSP curr_frame_sp (curr_frames->m_frames[curr_frame_idx]);
169*5082c5fdSGreg Clayton                     StackFrameSP prev_frame_sp (prev_frames->m_frames[prev_frame_idx]);
170*5082c5fdSGreg Clayton 
171*5082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
172*5082c5fdSGreg Clayton                     s.Printf("\nCurrent frame #%u ", curr_frame_idx);
173*5082c5fdSGreg Clayton                     if (curr_frame_sp)
174*5082c5fdSGreg Clayton                         curr_frame_sp->Dump (&s, true);
175*5082c5fdSGreg Clayton                     else
176*5082c5fdSGreg Clayton                         s.PutCString("NULL");
177*5082c5fdSGreg Clayton                     s.Printf("\nPrevious frame #%u ", prev_frame_idx);
178*5082c5fdSGreg Clayton                     if (prev_frame_sp)
179*5082c5fdSGreg Clayton                         prev_frame_sp->Dump (&s, true);
180*5082c5fdSGreg Clayton                     else
181*5082c5fdSGreg Clayton                         s.PutCString("NULL");
182*5082c5fdSGreg Clayton                     s.EOL();
183*5082c5fdSGreg Clayton #endif
184*5082c5fdSGreg Clayton 
185*5082c5fdSGreg Clayton                     StackFrame *curr_frame = curr_frame_sp.get();
186*5082c5fdSGreg Clayton                     StackFrame *prev_frame = prev_frame_sp.get();
187*5082c5fdSGreg Clayton 
188*5082c5fdSGreg Clayton                     if (curr_frame == NULL || prev_frame == NULL)
189*5082c5fdSGreg Clayton                         break;
190*5082c5fdSGreg Clayton 
191*5082c5fdSGreg Clayton                     // Do a quick sanity check to see if the CFA values are the same.
192*5082c5fdSGreg Clayton                     if (curr_frame->m_id.GetCallFrameAddress() != prev_frame->m_id.GetCallFrameAddress())
193*5082c5fdSGreg Clayton                         break;
194*5082c5fdSGreg Clayton 
195*5082c5fdSGreg Clayton                     // Now check our function or symbol
196*5082c5fdSGreg Clayton                     SymbolContext curr_sc (curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol));
197*5082c5fdSGreg Clayton                     SymbolContext prev_sc (prev_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol));
198*5082c5fdSGreg Clayton                     if (curr_sc.function && curr_sc.function == prev_sc.function)
199*5082c5fdSGreg Clayton                     {
200*5082c5fdSGreg Clayton                         // Same function
201*5082c5fdSGreg Clayton                         if (curr_sc.block != prev_sc.block)
202*5082c5fdSGreg Clayton                         {
203*5082c5fdSGreg Clayton                             // Same function different block
204*5082c5fdSGreg Clayton                             if (m_show_inlined_frames)
205*5082c5fdSGreg Clayton                                 break;
206*5082c5fdSGreg Clayton                             else
207*5082c5fdSGreg Clayton                                 prev_frame->SetSymbolContext (curr_frame->m_sc);
20812daf946SGreg Clayton                         }
20912daf946SGreg Clayton                     }
210*5082c5fdSGreg Clayton                     else if (curr_sc.symbol && curr_sc.symbol == prev_sc.symbol)
211*5082c5fdSGreg Clayton                     {
212*5082c5fdSGreg Clayton                         // Same symbol
21312daf946SGreg Clayton                     }
214*5082c5fdSGreg Clayton                     else if (curr_frame->GetFrameCodeAddress() != prev_frame->GetFrameCodeAddress())
215*5082c5fdSGreg Clayton                     {
216*5082c5fdSGreg Clayton                         // No symbols for this frame and the PC was different
217*5082c5fdSGreg Clayton                         break;
21812daf946SGreg Clayton                     }
219*5082c5fdSGreg Clayton 
220*5082c5fdSGreg Clayton                     if (curr_frame->GetFrameCodeAddress() != prev_frame->GetFrameCodeAddress())
221*5082c5fdSGreg Clayton                     {
222*5082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
223*5082c5fdSGreg Clayton                         s.Printf("\nUpdating frame code address and symbol context in previous frame #%u to current frame #%u", prev_frame_idx, curr_frame_idx);
224*5082c5fdSGreg Clayton #endif
225*5082c5fdSGreg Clayton                         // We have a different code frame address, we might need to copy
226*5082c5fdSGreg Clayton                         // some stuff in prev_frame, yet update the code address...
227*5082c5fdSGreg Clayton                         prev_frame->SetFrameCodeAddress (curr_frame->GetFrameCodeAddress());
228*5082c5fdSGreg Clayton                         prev_frame->SetSymbolContext (curr_frame->m_sc);
2290445d8f4SGreg Clayton                     }
230*5082c5fdSGreg Clayton 
231*5082c5fdSGreg Clayton                     curr_frames->m_frames[curr_frame_idx] = prev_frames->m_frames[prev_frame_idx];
232*5082c5fdSGreg Clayton 
233*5082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
234*5082c5fdSGreg Clayton                     s.Printf("\nCopying previous frame #%u to current frame #%u", prev_frame_idx, curr_frame_idx);
235*5082c5fdSGreg Clayton #endif
236*5082c5fdSGreg Clayton                 }
237*5082c5fdSGreg Clayton                 // We are done with the old stack frame list, we can release it now
238*5082c5fdSGreg Clayton                 m_prev_frames_ap.release();
239*5082c5fdSGreg Clayton                 prev_frames = NULL;
240*5082c5fdSGreg Clayton             }
24112daf946SGreg Clayton         }
24212daf946SGreg Clayton         else
24312daf946SGreg Clayton         {
244*5082c5fdSGreg Clayton             m_frames.resize(m_thread.GetUnwinder()->GetFrameCount());
24512daf946SGreg Clayton         }
246*5082c5fdSGreg Clayton     }
247*5082c5fdSGreg Clayton     return m_frames.size();
24830fdc8d8SChris Lattner }
24930fdc8d8SChris Lattner 
250*5082c5fdSGreg Clayton void
251*5082c5fdSGreg Clayton StackFrameList::Dump (Stream *s)
25230fdc8d8SChris Lattner {
253*5082c5fdSGreg Clayton     if (s == NULL)
254*5082c5fdSGreg Clayton         return;
255*5082c5fdSGreg Clayton     Mutex::Locker locker (m_mutex);
25630fdc8d8SChris Lattner 
257*5082c5fdSGreg Clayton     const_iterator pos, begin = m_frames.begin(), end = m_frames.end();
258*5082c5fdSGreg Clayton     for (pos = begin; pos != end; ++pos)
25912daf946SGreg Clayton     {
260*5082c5fdSGreg Clayton         StackFrame *frame = (*pos).get();
261*5082c5fdSGreg Clayton         s->Printf("%p: ", frame);
262*5082c5fdSGreg Clayton         if (frame)
263*5082c5fdSGreg Clayton             frame->Dump(s, true);
264*5082c5fdSGreg Clayton         else
265*5082c5fdSGreg Clayton             s->Printf("frame #%u", std::distance (begin, pos));
266*5082c5fdSGreg Clayton         s->EOL();
26712daf946SGreg Clayton     }
268*5082c5fdSGreg Clayton     s->EOL();
269*5082c5fdSGreg Clayton }
27012daf946SGreg Clayton 
27130fdc8d8SChris Lattner StackFrameSP
27212daf946SGreg Clayton StackFrameList::GetFrameAtIndex (uint32_t idx)
27330fdc8d8SChris Lattner {
27430fdc8d8SChris Lattner     StackFrameSP frame_sp;
27530fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
276*5082c5fdSGreg Clayton     if (idx < m_frames.size())
277*5082c5fdSGreg Clayton         frame_sp = m_frames[idx];
27812daf946SGreg Clayton 
279*5082c5fdSGreg Clayton     if (frame_sp)
28012daf946SGreg Clayton         return frame_sp;
28112daf946SGreg Clayton 
28212daf946SGreg Clayton     // Special case the first frame (idx == 0) so that we don't need to
28312daf946SGreg Clayton     // know how many stack frames there are to get it. If we need any other
28412daf946SGreg Clayton     // frames, then we do need to know if "idx" is a valid index.
28512daf946SGreg Clayton     if (idx == 0)
28612daf946SGreg Clayton     {
28712daf946SGreg Clayton         // If this is the first frame, we want to share the thread register
28812daf946SGreg Clayton         // context with the stack frame at index zero.
28912daf946SGreg Clayton         m_thread.GetRegisterContext();
29012daf946SGreg Clayton         assert (m_thread.m_reg_context_sp.get());
29112daf946SGreg Clayton         frame_sp.reset (new StackFrame (0,
29212daf946SGreg Clayton                                         0,
29312daf946SGreg Clayton                                         m_thread,
29412daf946SGreg Clayton                                         m_thread.m_reg_context_sp,
29512daf946SGreg Clayton                                         m_thread.m_reg_context_sp->GetSP(),
29612daf946SGreg Clayton                                         m_thread.m_reg_context_sp->GetPC(),
29712daf946SGreg Clayton                                         NULL));
2980445d8f4SGreg Clayton 
299*5082c5fdSGreg Clayton         if (m_show_inlined_frames)
3000445d8f4SGreg Clayton         {
301*5082c5fdSGreg Clayton             Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block;
3020445d8f4SGreg Clayton 
303*5082c5fdSGreg Clayton             if (block)
304*5082c5fdSGreg Clayton             {
305*5082c5fdSGreg Clayton                 Block *inline_block = block->GetContainingInlinedBlock();
306*5082c5fdSGreg Clayton                 if (inline_block)
307*5082c5fdSGreg Clayton                     frame_sp->SetInlineBlockID (inline_block->GetID());
308*5082c5fdSGreg Clayton             }
309*5082c5fdSGreg Clayton         }
310*5082c5fdSGreg Clayton         SetFrameAtIndex(idx, frame_sp);
31112daf946SGreg Clayton     }
31212daf946SGreg Clayton     else if (idx < GetNumFrames())
31312daf946SGreg Clayton     {
31412daf946SGreg Clayton         if (m_show_inlined_frames)
31512daf946SGreg Clayton         {
316*5082c5fdSGreg Clayton             // When inline frames are enabled we cache up all frames in GetNumFrames()
317*5082c5fdSGreg Clayton             frame_sp = m_frames[idx];
31812daf946SGreg Clayton         }
31912daf946SGreg Clayton         else
32012daf946SGreg Clayton         {
32112daf946SGreg Clayton             Unwind *unwinder = m_thread.GetUnwinder ();
32212daf946SGreg Clayton             if (unwinder)
32312daf946SGreg Clayton             {
32412daf946SGreg Clayton                 addr_t pc, cfa;
32512daf946SGreg Clayton                 if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
326*5082c5fdSGreg Clayton                 {
3270445d8f4SGreg Clayton                     frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL));
328*5082c5fdSGreg Clayton                     SetFrameAtIndex(idx, frame_sp);
32912daf946SGreg Clayton                 }
33012daf946SGreg Clayton             }
33112daf946SGreg Clayton         }
3320445d8f4SGreg Clayton 
33330fdc8d8SChris Lattner     }
33430fdc8d8SChris Lattner     return frame_sp;
33530fdc8d8SChris Lattner }
33630fdc8d8SChris Lattner 
33712daf946SGreg Clayton 
33812daf946SGreg Clayton bool
339*5082c5fdSGreg Clayton StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
34012daf946SGreg Clayton {
341*5082c5fdSGreg Clayton     if (idx >= m_frames.size())
342*5082c5fdSGreg Clayton         m_frames.resize(idx + 1);
34312daf946SGreg Clayton     // Make sure allocation succeeded by checking bounds again
344*5082c5fdSGreg Clayton     if (idx < m_frames.size())
34512daf946SGreg Clayton     {
346*5082c5fdSGreg Clayton         m_frames[idx] = frame_sp;
34730fdc8d8SChris Lattner         return true;
34830fdc8d8SChris Lattner     }
34930fdc8d8SChris Lattner     return false;   // resize failed, out of memory?
35030fdc8d8SChris Lattner }
35130fdc8d8SChris Lattner 
35230fdc8d8SChris Lattner uint32_t
3532976d00aSJim Ingham StackFrameList::GetSelectedFrameIndex () const
35430fdc8d8SChris Lattner {
35530fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
3562976d00aSJim Ingham     return m_selected_frame_idx;
35730fdc8d8SChris Lattner }
35830fdc8d8SChris Lattner 
35930fdc8d8SChris Lattner 
36030fdc8d8SChris Lattner uint32_t
3612976d00aSJim Ingham StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame)
36230fdc8d8SChris Lattner {
36330fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
36412daf946SGreg Clayton     const_iterator pos;
365*5082c5fdSGreg Clayton     const_iterator begin = m_frames.begin();
366*5082c5fdSGreg Clayton     const_iterator end = m_frames.end();
36730fdc8d8SChris Lattner     for (pos = begin; pos != end; ++pos)
36830fdc8d8SChris Lattner     {
36930fdc8d8SChris Lattner         if (pos->get() == frame)
37030fdc8d8SChris Lattner         {
3712976d00aSJim Ingham             m_selected_frame_idx = std::distance (begin, pos);
3722976d00aSJim Ingham             return m_selected_frame_idx;
37330fdc8d8SChris Lattner         }
37430fdc8d8SChris Lattner     }
3752976d00aSJim Ingham     m_selected_frame_idx = 0;
3762976d00aSJim Ingham     return m_selected_frame_idx;
37730fdc8d8SChris Lattner }
37830fdc8d8SChris Lattner 
37930fdc8d8SChris Lattner // Mark a stack frame as the current frame using the frame index
38030fdc8d8SChris Lattner void
3812976d00aSJim Ingham StackFrameList::SetSelectedFrameByIndex (uint32_t idx)
38230fdc8d8SChris Lattner {
38330fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
3842976d00aSJim Ingham     m_selected_frame_idx = idx;
38530fdc8d8SChris Lattner }
38630fdc8d8SChris Lattner 
38730fdc8d8SChris Lattner // The thread has been run, reset the number stack frames to zero so we can
38830fdc8d8SChris Lattner // determine how many frames we have lazily.
38930fdc8d8SChris Lattner void
39030fdc8d8SChris Lattner StackFrameList::Clear ()
39130fdc8d8SChris Lattner {
39230fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
393*5082c5fdSGreg Clayton     m_frames.clear();
39430fdc8d8SChris Lattner }
39530fdc8d8SChris Lattner 
39630fdc8d8SChris Lattner void
39730fdc8d8SChris Lattner StackFrameList::InvalidateFrames (uint32_t start_idx)
39830fdc8d8SChris Lattner {
39930fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
40012daf946SGreg Clayton     if (m_show_inlined_frames)
40112daf946SGreg Clayton     {
40212daf946SGreg Clayton         Clear();
40312daf946SGreg Clayton     }
40412daf946SGreg Clayton     else
40512daf946SGreg Clayton     {
406*5082c5fdSGreg Clayton         const size_t num_frames = m_frames.size();
40730fdc8d8SChris Lattner         while (start_idx < num_frames)
40830fdc8d8SChris Lattner         {
409*5082c5fdSGreg Clayton             m_frames[start_idx].reset();
41030fdc8d8SChris Lattner             ++start_idx;
41130fdc8d8SChris Lattner         }
41230fdc8d8SChris Lattner     }
41312daf946SGreg Clayton }
414