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 
10*12daf946SGreg Clayton #include "lldb/Target/StackFrameList.h"
11*12daf946SGreg Clayton 
1230fdc8d8SChris Lattner // C Includes
1330fdc8d8SChris Lattner // C++ Includes
1430fdc8d8SChris Lattner // Other libraries and framework includes
1530fdc8d8SChris Lattner // Project includes
16*12daf946SGreg Clayton #include "lldb/Symbol/Block.h"
17*12daf946SGreg Clayton #include "lldb/Symbol/Function.h"
18*12daf946SGreg Clayton #include "lldb/Target/RegisterContext.h"
1930fdc8d8SChris Lattner #include "lldb/Target/StackFrame.h"
20*12daf946SGreg Clayton #include "lldb/Target/Thread.h"
21*12daf946SGreg Clayton #include "lldb/Target/Unwind.h"
2230fdc8d8SChris Lattner 
2330fdc8d8SChris Lattner using namespace lldb;
2430fdc8d8SChris Lattner using namespace lldb_private;
2530fdc8d8SChris Lattner 
2630fdc8d8SChris Lattner //----------------------------------------------------------------------
2730fdc8d8SChris Lattner // StackFrameList constructor
2830fdc8d8SChris Lattner //----------------------------------------------------------------------
29*12daf946SGreg Clayton StackFrameList::StackFrameList(Thread &thread, bool show_inline_frames) :
30*12daf946SGreg Clayton     m_thread (thread),
31*12daf946SGreg Clayton     m_show_inlined_frames (show_inline_frames),
3230fdc8d8SChris Lattner     m_mutex (Mutex::eMutexTypeRecursive),
33*12daf946SGreg Clayton     m_actual_frames (),
34*12daf946SGreg Clayton     m_inline_frames (),
3530fdc8d8SChris Lattner     m_current_frame_idx (0)
3630fdc8d8SChris Lattner {
3730fdc8d8SChris Lattner }
3830fdc8d8SChris Lattner 
3930fdc8d8SChris Lattner //----------------------------------------------------------------------
4030fdc8d8SChris Lattner // Destructor
4130fdc8d8SChris Lattner //----------------------------------------------------------------------
4230fdc8d8SChris Lattner StackFrameList::~StackFrameList()
4330fdc8d8SChris Lattner {
4430fdc8d8SChris Lattner }
4530fdc8d8SChris Lattner 
4630fdc8d8SChris Lattner 
4730fdc8d8SChris Lattner uint32_t
48*12daf946SGreg Clayton StackFrameList::GetNumFrames()
4930fdc8d8SChris Lattner {
5030fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
51*12daf946SGreg Clayton 
52*12daf946SGreg Clayton     if (m_show_inlined_frames)
53*12daf946SGreg Clayton     {
54*12daf946SGreg Clayton         if (m_inlined_frame_info.empty())
55*12daf946SGreg Clayton         {
56*12daf946SGreg Clayton             Unwind *unwinder = m_thread.GetUnwinder ();
57*12daf946SGreg Clayton             // If we are going to show inlined stack frames as actual frames,
58*12daf946SGreg Clayton             // we need to calculate all concrete frames first, then iterate
59*12daf946SGreg Clayton             // through all of them and count up how many inlined functions are
60*12daf946SGreg Clayton             // in each frame. We can then fill in m_inlined_frame_info with
61*12daf946SGreg Clayton             // the concrete frame index and inlined depth
62*12daf946SGreg Clayton             const uint32_t concrete_frame_count = unwinder->GetFrameCount();
63*12daf946SGreg Clayton 
64*12daf946SGreg Clayton             addr_t pc, cfa;
65*12daf946SGreg Clayton             InlinedFrameInfo inlined_frame_info;
66*12daf946SGreg Clayton 
67*12daf946SGreg Clayton             StackFrameSP frame_sp;
68*12daf946SGreg Clayton             for (uint32_t idx=0; idx<concrete_frame_count; ++idx)
69*12daf946SGreg Clayton             {
70*12daf946SGreg Clayton                 if (idx == 0)
71*12daf946SGreg Clayton                 {
72*12daf946SGreg Clayton                     m_thread.GetRegisterContext();
73*12daf946SGreg Clayton                     frame_sp.reset (new StackFrame (0,
74*12daf946SGreg Clayton                                                     0,
75*12daf946SGreg Clayton                                                     m_thread,
76*12daf946SGreg Clayton                                                     m_thread.m_reg_context_sp,
77*12daf946SGreg Clayton                                                     m_thread.m_reg_context_sp->GetSP(),
78*12daf946SGreg Clayton                                                     0,
79*12daf946SGreg Clayton                                                     m_thread.m_reg_context_sp->GetPC(),
80*12daf946SGreg Clayton                                                     NULL));
81*12daf946SGreg Clayton                 }
82*12daf946SGreg Clayton                 else
83*12daf946SGreg Clayton                 {
84*12daf946SGreg Clayton                     const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
85*12daf946SGreg Clayton                     assert (success);
86*12daf946SGreg Clayton                     frame_sp.reset (new StackFrame (m_inlined_frame_info.size(), idx, m_thread, cfa, 0, pc, NULL));
87*12daf946SGreg Clayton                 }
88*12daf946SGreg Clayton                 SetActualFrameAtIndex (idx, frame_sp);
89*12daf946SGreg Clayton                 Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block;
90*12daf946SGreg Clayton 
91*12daf946SGreg Clayton                 inlined_frame_info.concrete_frame_index = idx;
92*12daf946SGreg Clayton                 inlined_frame_info.inline_height = 0;
93*12daf946SGreg Clayton                 inlined_frame_info.block = block;
94*12daf946SGreg Clayton                 m_inlined_frame_info.push_back (inlined_frame_info);
95*12daf946SGreg Clayton 
96*12daf946SGreg Clayton                 if (block)
97*12daf946SGreg Clayton                 {
98*12daf946SGreg Clayton                     Block *inlined_block;
99*12daf946SGreg Clayton                     if (block->InlinedFunctionInfo())
100*12daf946SGreg Clayton                         inlined_block = block;
101*12daf946SGreg Clayton                     else
102*12daf946SGreg Clayton                         inlined_block = block->GetInlinedParent ();
103*12daf946SGreg Clayton 
104*12daf946SGreg Clayton                     while (inlined_block)
105*12daf946SGreg Clayton                     {
106*12daf946SGreg Clayton                         inlined_frame_info.block = inlined_block;
107*12daf946SGreg Clayton                         inlined_frame_info.inline_height++;
108*12daf946SGreg Clayton                         m_inlined_frame_info.push_back (inlined_frame_info);
109*12daf946SGreg Clayton                         inlined_block = inlined_block->GetInlinedParent ();
110*12daf946SGreg Clayton                     }
111*12daf946SGreg Clayton                 }
112*12daf946SGreg Clayton             }
113*12daf946SGreg Clayton         }
114*12daf946SGreg Clayton         return m_inlined_frame_info.size();
115*12daf946SGreg Clayton     }
116*12daf946SGreg Clayton     else
117*12daf946SGreg Clayton     {
118*12daf946SGreg Clayton         if (m_actual_frames.empty())
119*12daf946SGreg Clayton             m_actual_frames.resize(m_thread.GetUnwinder()->GetFrameCount());
120*12daf946SGreg Clayton 
121*12daf946SGreg Clayton         return m_actual_frames.size();
122*12daf946SGreg Clayton     }
123*12daf946SGreg Clayton     return 0;
12430fdc8d8SChris Lattner }
12530fdc8d8SChris Lattner 
126*12daf946SGreg Clayton lldb::StackFrameSP
127*12daf946SGreg Clayton StackFrameList::GetActualFrameAtIndex (uint32_t idx) const
12830fdc8d8SChris Lattner {
129*12daf946SGreg Clayton     StackFrameSP frame_sp;
130*12daf946SGreg Clayton         if (idx < m_actual_frames.size())
131*12daf946SGreg Clayton             frame_sp = m_actual_frames[idx];
132*12daf946SGreg Clayton     return frame_sp;
13330fdc8d8SChris Lattner }
13430fdc8d8SChris Lattner 
135*12daf946SGreg Clayton lldb::StackFrameSP
136*12daf946SGreg Clayton StackFrameList::GetInlineFrameAtIndex (uint32_t idx) const
137*12daf946SGreg Clayton {
138*12daf946SGreg Clayton     StackFrameSP frame_sp;
139*12daf946SGreg Clayton     if (idx < m_inline_frames.size())
140*12daf946SGreg Clayton         frame_sp = m_inline_frames[idx];
141*12daf946SGreg Clayton     return frame_sp;
142*12daf946SGreg Clayton }
143*12daf946SGreg Clayton 
144*12daf946SGreg Clayton 
14530fdc8d8SChris Lattner StackFrameSP
146*12daf946SGreg Clayton StackFrameList::GetFrameAtIndex (uint32_t idx)
14730fdc8d8SChris Lattner {
14830fdc8d8SChris Lattner     StackFrameSP frame_sp;
14930fdc8d8SChris Lattner     {
15030fdc8d8SChris Lattner         Mutex::Locker locker (m_mutex);
151*12daf946SGreg Clayton 
152*12daf946SGreg Clayton         if (m_show_inlined_frames)
153*12daf946SGreg Clayton         {
154*12daf946SGreg Clayton             frame_sp = GetInlineFrameAtIndex (idx);
155*12daf946SGreg Clayton         }
156*12daf946SGreg Clayton         else
157*12daf946SGreg Clayton         {
158*12daf946SGreg Clayton             frame_sp = GetActualFrameAtIndex (idx);
159*12daf946SGreg Clayton         }
160*12daf946SGreg Clayton 
161*12daf946SGreg Clayton         if (frame_sp.get())
162*12daf946SGreg Clayton         return frame_sp;
163*12daf946SGreg Clayton 
164*12daf946SGreg Clayton     // Special case the first frame (idx == 0) so that we don't need to
165*12daf946SGreg Clayton     // know how many stack frames there are to get it. If we need any other
166*12daf946SGreg Clayton     // frames, then we do need to know if "idx" is a valid index.
167*12daf946SGreg Clayton     if (idx == 0)
168*12daf946SGreg Clayton     {
169*12daf946SGreg Clayton         // If this is the first frame, we want to share the thread register
170*12daf946SGreg Clayton         // context with the stack frame at index zero.
171*12daf946SGreg Clayton         m_thread.GetRegisterContext();
172*12daf946SGreg Clayton         assert (m_thread.m_reg_context_sp.get());
173*12daf946SGreg Clayton         frame_sp.reset (new StackFrame (0,
174*12daf946SGreg Clayton                                         0,
175*12daf946SGreg Clayton                                         m_thread,
176*12daf946SGreg Clayton                                         m_thread.m_reg_context_sp,
177*12daf946SGreg Clayton                                         m_thread.m_reg_context_sp->GetSP(),
178*12daf946SGreg Clayton                                         0,
179*12daf946SGreg Clayton                                         m_thread.m_reg_context_sp->GetPC(),
180*12daf946SGreg Clayton                                         NULL));
181*12daf946SGreg Clayton     }
182*12daf946SGreg Clayton     else if (idx < GetNumFrames())
183*12daf946SGreg Clayton     {
184*12daf946SGreg Clayton         if (m_show_inlined_frames)
185*12daf946SGreg Clayton         {
186*12daf946SGreg Clayton             if (m_inlined_frame_info[idx].inline_height == 0)
187*12daf946SGreg Clayton             {
188*12daf946SGreg Clayton                 // Same as the concrete stack frame if block is NULL
189*12daf946SGreg Clayton                 assert (m_inlined_frame_info[idx].concrete_frame_index < m_actual_frames.size());
190*12daf946SGreg Clayton                 frame_sp = GetActualFrameAtIndex (m_inlined_frame_info[idx].concrete_frame_index);
191*12daf946SGreg Clayton             }
192*12daf946SGreg Clayton             else
193*12daf946SGreg Clayton             {
194*12daf946SGreg Clayton                 // We have blocks that were above an inlined function. Inlined
195*12daf946SGreg Clayton                 // functions are represented as blocks with non-NULL inline
196*12daf946SGreg Clayton                 // function info. Here we must reconstruct a frame by looking
197*12daf946SGreg Clayton                 // at the block
198*12daf946SGreg Clayton                 StackFrameSP previous_frame_sp (m_thread.GetStackFrameAtIndex (idx-1));
199*12daf946SGreg Clayton 
200*12daf946SGreg Clayton                 SymbolContext inline_sc;
201*12daf946SGreg Clayton 
202*12daf946SGreg Clayton                 Block *inlined_parent_block = m_inlined_frame_info[idx].block->GetInlinedParent();
203*12daf946SGreg Clayton 
204*12daf946SGreg Clayton                 if (inlined_parent_block)
205*12daf946SGreg Clayton                     inlined_parent_block->CalculateSymbolContext (&inline_sc);
206*12daf946SGreg Clayton                 else
207*12daf946SGreg Clayton                 {
208*12daf946SGreg Clayton                     Block *parent_block = m_inlined_frame_info[idx].block->GetParent();
209*12daf946SGreg Clayton                     parent_block->CalculateSymbolContext(&inline_sc);
210*12daf946SGreg Clayton                 }
211*12daf946SGreg Clayton 
212*12daf946SGreg Clayton                 Address previous_frame_lookup_addr (previous_frame_sp->GetFrameCodeAddress());
213*12daf946SGreg Clayton                 if (previous_frame_sp->IsConcrete () && previous_frame_sp->GetFrameIndex() > 0)
214*12daf946SGreg Clayton                     previous_frame_lookup_addr.Slide (-1);
215*12daf946SGreg Clayton 
216*12daf946SGreg Clayton                 AddressRange range;
217*12daf946SGreg Clayton                 m_inlined_frame_info[idx].block->GetRangeContainingAddress (previous_frame_lookup_addr, range);
218*12daf946SGreg Clayton 
219*12daf946SGreg Clayton                 const InlineFunctionInfo* inline_info = m_inlined_frame_info[idx].block->InlinedFunctionInfo();
220*12daf946SGreg Clayton                 assert (inline_info);
221*12daf946SGreg Clayton                 inline_sc.line_entry.range.GetBaseAddress() = previous_frame_sp->GetFrameCodeAddress();
222*12daf946SGreg Clayton                 inline_sc.line_entry.file = inline_info->GetCallSite().GetFile();
223*12daf946SGreg Clayton                 inline_sc.line_entry.line = inline_info->GetCallSite().GetLine();
224*12daf946SGreg Clayton                 inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn();
225*12daf946SGreg Clayton 
226*12daf946SGreg Clayton                 StackFrameSP concrete_frame_sp (GetActualFrameAtIndex (m_inlined_frame_info[idx].concrete_frame_index));
227*12daf946SGreg Clayton                 assert (previous_frame_sp.get());
228*12daf946SGreg Clayton 
229*12daf946SGreg Clayton                 frame_sp.reset (new StackFrame (idx,
230*12daf946SGreg Clayton                                                 m_inlined_frame_info[idx].concrete_frame_index,
231*12daf946SGreg Clayton                                                 m_thread,
232*12daf946SGreg Clayton                                                 concrete_frame_sp->GetRegisterContextSP (),
233*12daf946SGreg Clayton                                                 concrete_frame_sp->GetStackID().GetCallFrameAddress(),  // CFA
234*12daf946SGreg Clayton                                                 m_inlined_frame_info[idx].inline_height,                // Inline height
235*12daf946SGreg Clayton                                                 range.GetBaseAddress(),
236*12daf946SGreg Clayton                                                 &inline_sc));                                           // The symbol context for this inline frame
237*12daf946SGreg Clayton 
238*12daf946SGreg Clayton             }
239*12daf946SGreg Clayton         }
240*12daf946SGreg Clayton         else
241*12daf946SGreg Clayton         {
242*12daf946SGreg Clayton             Unwind *unwinder = m_thread.GetUnwinder ();
243*12daf946SGreg Clayton             if (unwinder)
244*12daf946SGreg Clayton             {
245*12daf946SGreg Clayton                 addr_t pc, cfa;
246*12daf946SGreg Clayton                 if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
247*12daf946SGreg Clayton                     frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, 0, pc, NULL));
248*12daf946SGreg Clayton             }
249*12daf946SGreg Clayton         }
250*12daf946SGreg Clayton     }
251*12daf946SGreg Clayton     if (m_show_inlined_frames)
252*12daf946SGreg Clayton         SetInlineFrameAtIndex(idx, frame_sp);
253*12daf946SGreg Clayton     else
254*12daf946SGreg Clayton         SetActualFrameAtIndex(idx, frame_sp);
255*12daf946SGreg Clayton     return frame_sp;
256*12daf946SGreg Clayton 
25730fdc8d8SChris Lattner     }
25830fdc8d8SChris Lattner     return frame_sp;
25930fdc8d8SChris Lattner }
26030fdc8d8SChris Lattner 
26130fdc8d8SChris Lattner bool
262*12daf946SGreg Clayton StackFrameList::SetActualFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
26330fdc8d8SChris Lattner {
264*12daf946SGreg Clayton     if (idx >= m_actual_frames.size())
265*12daf946SGreg Clayton         m_actual_frames.resize(idx + 1);
26630fdc8d8SChris Lattner     // Make sure allocation succeeded by checking bounds again
267*12daf946SGreg Clayton     if (idx < m_actual_frames.size())
26830fdc8d8SChris Lattner     {
269*12daf946SGreg Clayton         m_actual_frames[idx] = frame_sp;
270*12daf946SGreg Clayton         return true;
271*12daf946SGreg Clayton     }
272*12daf946SGreg Clayton     return false;   // resize failed, out of memory?
273*12daf946SGreg Clayton }
274*12daf946SGreg Clayton 
275*12daf946SGreg Clayton bool
276*12daf946SGreg Clayton StackFrameList::SetInlineFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
277*12daf946SGreg Clayton {
278*12daf946SGreg Clayton     if (idx >= m_inline_frames.size())
279*12daf946SGreg Clayton         m_inline_frames.resize(idx + 1);
280*12daf946SGreg Clayton     // Make sure allocation succeeded by checking bounds again
281*12daf946SGreg Clayton     if (idx < m_inline_frames.size())
282*12daf946SGreg Clayton     {
283*12daf946SGreg Clayton         m_inline_frames[idx] = frame_sp;
28430fdc8d8SChris Lattner         return true;
28530fdc8d8SChris Lattner     }
28630fdc8d8SChris Lattner     return false;   // resize failed, out of memory?
28730fdc8d8SChris Lattner }
28830fdc8d8SChris Lattner 
28930fdc8d8SChris Lattner uint32_t
29030fdc8d8SChris Lattner StackFrameList::GetCurrentFrameIndex () const
29130fdc8d8SChris Lattner {
29230fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
29330fdc8d8SChris Lattner     return m_current_frame_idx;
29430fdc8d8SChris Lattner }
29530fdc8d8SChris Lattner 
29630fdc8d8SChris Lattner 
29730fdc8d8SChris Lattner uint32_t
29830fdc8d8SChris Lattner StackFrameList::SetCurrentFrame (lldb_private::StackFrame *frame)
29930fdc8d8SChris Lattner {
30030fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
301*12daf946SGreg Clayton     const_iterator pos;
302*12daf946SGreg Clayton     const_iterator begin = m_show_inlined_frames ? m_inline_frames.begin() : m_actual_frames.begin();
303*12daf946SGreg Clayton     const_iterator end   = m_show_inlined_frames ? m_inline_frames.end()   : m_actual_frames.end();
30430fdc8d8SChris Lattner     for (pos = begin; pos != end; ++pos)
30530fdc8d8SChris Lattner     {
30630fdc8d8SChris Lattner         if (pos->get() == frame)
30730fdc8d8SChris Lattner         {
30830fdc8d8SChris Lattner             m_current_frame_idx = std::distance (begin, pos);
30930fdc8d8SChris Lattner             return m_current_frame_idx;
31030fdc8d8SChris Lattner         }
31130fdc8d8SChris Lattner     }
31230fdc8d8SChris Lattner     m_current_frame_idx = 0;
31330fdc8d8SChris Lattner     return m_current_frame_idx;
31430fdc8d8SChris Lattner }
31530fdc8d8SChris Lattner 
31630fdc8d8SChris Lattner // Mark a stack frame as the current frame using the frame index
31730fdc8d8SChris Lattner void
31830fdc8d8SChris Lattner StackFrameList::SetCurrentFrameByIndex (uint32_t idx)
31930fdc8d8SChris Lattner {
32030fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
32130fdc8d8SChris Lattner     m_current_frame_idx = idx;
32230fdc8d8SChris Lattner }
32330fdc8d8SChris Lattner 
32430fdc8d8SChris Lattner // The thread has been run, reset the number stack frames to zero so we can
32530fdc8d8SChris Lattner // determine how many frames we have lazily.
32630fdc8d8SChris Lattner void
32730fdc8d8SChris Lattner StackFrameList::Clear ()
32830fdc8d8SChris Lattner {
32930fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
330*12daf946SGreg Clayton     m_actual_frames.clear();
331*12daf946SGreg Clayton     m_inline_frames.clear();
332*12daf946SGreg Clayton     m_inlined_frame_info.clear();
33330fdc8d8SChris Lattner }
33430fdc8d8SChris Lattner 
33530fdc8d8SChris Lattner void
33630fdc8d8SChris Lattner StackFrameList::InvalidateFrames (uint32_t start_idx)
33730fdc8d8SChris Lattner {
33830fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
339*12daf946SGreg Clayton     if (m_show_inlined_frames)
340*12daf946SGreg Clayton     {
341*12daf946SGreg Clayton         Clear();
342*12daf946SGreg Clayton     }
343*12daf946SGreg Clayton     else
344*12daf946SGreg Clayton     {
345*12daf946SGreg Clayton         const size_t num_frames = m_actual_frames.size();
34630fdc8d8SChris Lattner         while (start_idx < num_frames)
34730fdc8d8SChris Lattner         {
348*12daf946SGreg Clayton             m_actual_frames[start_idx].reset();
34930fdc8d8SChris Lattner             ++start_idx;
35030fdc8d8SChris Lattner         }
35130fdc8d8SChris Lattner     }
352*12daf946SGreg Clayton }
353