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
1612daf946SGreg Clayton #include "lldb/Symbol/Block.h"
1712daf946SGreg Clayton #include "lldb/Symbol/Function.h"
1812daf946SGreg Clayton #include "lldb/Target/RegisterContext.h"
1930fdc8d8SChris Lattner #include "lldb/Target/StackFrame.h"
2012daf946SGreg Clayton #include "lldb/Target/Thread.h"
2112daf946SGreg 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 //----------------------------------------------------------------------
290445d8f4SGreg Clayton StackFrameList::StackFrameList(Thread &thread, StackFrameList *prev_frames, bool show_inline_frames) :
3012daf946SGreg Clayton     m_thread (thread),
310445d8f4SGreg Clayton     m_prev_frames_ap (prev_frames),
3212daf946SGreg Clayton     m_show_inlined_frames (show_inline_frames),
3330fdc8d8SChris Lattner     m_mutex (Mutex::eMutexTypeRecursive),
340445d8f4SGreg Clayton     m_unwind_frames (),
3512daf946SGreg Clayton     m_inline_frames (),
36*2976d00aSJim Ingham     m_selected_frame_idx (0)
3730fdc8d8SChris Lattner {
3830fdc8d8SChris Lattner }
3930fdc8d8SChris Lattner 
4030fdc8d8SChris Lattner //----------------------------------------------------------------------
4130fdc8d8SChris Lattner // Destructor
4230fdc8d8SChris Lattner //----------------------------------------------------------------------
4330fdc8d8SChris Lattner StackFrameList::~StackFrameList()
4430fdc8d8SChris Lattner {
4530fdc8d8SChris Lattner }
4630fdc8d8SChris Lattner 
4730fdc8d8SChris Lattner 
4830fdc8d8SChris Lattner uint32_t
4912daf946SGreg Clayton StackFrameList::GetNumFrames()
5030fdc8d8SChris Lattner {
5130fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
5212daf946SGreg Clayton 
5312daf946SGreg Clayton     if (m_show_inlined_frames)
5412daf946SGreg Clayton     {
550445d8f4SGreg Clayton         if (m_inlined_info.empty())
5612daf946SGreg Clayton         {
5712daf946SGreg Clayton             Unwind *unwinder = m_thread.GetUnwinder ();
5812daf946SGreg Clayton             // If we are going to show inlined stack frames as actual frames,
5912daf946SGreg Clayton             // we need to calculate all concrete frames first, then iterate
6012daf946SGreg Clayton             // through all of them and count up how many inlined functions are
610445d8f4SGreg Clayton             // in each frame. We can then fill in m_inlined_info with
6212daf946SGreg Clayton             // the concrete frame index and inlined depth
6312daf946SGreg Clayton             const uint32_t concrete_frame_count = unwinder->GetFrameCount();
6412daf946SGreg Clayton 
6512daf946SGreg Clayton             addr_t pc, cfa;
6612daf946SGreg Clayton             InlinedFrameInfo inlined_frame_info;
6712daf946SGreg Clayton 
6812daf946SGreg Clayton             StackFrameSP frame_sp;
6912daf946SGreg Clayton             for (uint32_t idx=0; idx<concrete_frame_count; ++idx)
7012daf946SGreg Clayton             {
7112daf946SGreg Clayton                 if (idx == 0)
7212daf946SGreg Clayton                 {
7312daf946SGreg Clayton                     m_thread.GetRegisterContext();
7412daf946SGreg Clayton                     frame_sp.reset (new StackFrame (0,
7512daf946SGreg Clayton                                                     0,
7612daf946SGreg Clayton                                                     m_thread,
7712daf946SGreg Clayton                                                     m_thread.m_reg_context_sp,
7812daf946SGreg Clayton                                                     m_thread.m_reg_context_sp->GetSP(),
7912daf946SGreg Clayton                                                     m_thread.m_reg_context_sp->GetPC(),
8012daf946SGreg Clayton                                                     NULL));
8112daf946SGreg Clayton                 }
8212daf946SGreg Clayton                 else
8312daf946SGreg Clayton                 {
8412daf946SGreg Clayton                     const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
8512daf946SGreg Clayton                     assert (success);
860445d8f4SGreg Clayton                     frame_sp.reset (new StackFrame (m_inlined_info.size(), idx, m_thread, cfa, pc, NULL));
8712daf946SGreg Clayton                 }
880445d8f4SGreg Clayton                 SetUnwindFrameAtIndex (idx, frame_sp);
8912daf946SGreg Clayton                 Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block;
9012daf946SGreg Clayton 
910445d8f4SGreg Clayton                 inlined_frame_info.unwind_frame_index = idx;
920445d8f4SGreg Clayton                 inlined_frame_info.block = NULL;
930445d8f4SGreg Clayton                 m_inlined_info.push_back (inlined_frame_info);
9412daf946SGreg Clayton 
9512daf946SGreg Clayton                 if (block)
9612daf946SGreg Clayton                 {
970445d8f4SGreg Clayton                     Block *inlined_block = block->GetContainingInlinedBlock();
980445d8f4SGreg Clayton 
990445d8f4SGreg Clayton                     if (inlined_block)
1000445d8f4SGreg Clayton                     {
1010445d8f4SGreg Clayton                         frame_sp->SetInlineBlockID (inlined_block->GetID());
10212daf946SGreg Clayton 
10312daf946SGreg Clayton                         while (inlined_block)
10412daf946SGreg Clayton                         {
10512daf946SGreg Clayton                             inlined_frame_info.block = inlined_block;
1060445d8f4SGreg Clayton                             m_inlined_info.push_back (inlined_frame_info);
10712daf946SGreg Clayton                             inlined_block = inlined_block->GetInlinedParent ();
10812daf946SGreg Clayton                         }
10912daf946SGreg Clayton                     }
11012daf946SGreg Clayton                 }
11112daf946SGreg Clayton             }
1120445d8f4SGreg Clayton         }
1130445d8f4SGreg Clayton         return m_inlined_info.size();
11412daf946SGreg Clayton     }
11512daf946SGreg Clayton     else
11612daf946SGreg Clayton     {
1170445d8f4SGreg Clayton         if (m_unwind_frames.empty())
1180445d8f4SGreg Clayton             m_unwind_frames.resize(m_thread.GetUnwinder()->GetFrameCount());
11912daf946SGreg Clayton 
1200445d8f4SGreg Clayton         return m_unwind_frames.size();
12112daf946SGreg Clayton     }
12212daf946SGreg Clayton     return 0;
12330fdc8d8SChris Lattner }
12430fdc8d8SChris Lattner 
12512daf946SGreg Clayton lldb::StackFrameSP
1260445d8f4SGreg Clayton StackFrameList::GetUnwindFrameAtIndex (uint32_t idx) const
12730fdc8d8SChris Lattner {
12812daf946SGreg Clayton     StackFrameSP frame_sp;
1290445d8f4SGreg Clayton         if (idx < m_unwind_frames.size())
1300445d8f4SGreg Clayton             frame_sp = m_unwind_frames[idx];
13112daf946SGreg Clayton     return frame_sp;
13230fdc8d8SChris Lattner }
13330fdc8d8SChris Lattner 
13412daf946SGreg Clayton lldb::StackFrameSP
13512daf946SGreg Clayton StackFrameList::GetInlineFrameAtIndex (uint32_t idx) const
13612daf946SGreg Clayton {
13712daf946SGreg Clayton     StackFrameSP frame_sp;
13812daf946SGreg Clayton     if (idx < m_inline_frames.size())
13912daf946SGreg Clayton         frame_sp = m_inline_frames[idx];
14012daf946SGreg Clayton     return frame_sp;
14112daf946SGreg Clayton }
14212daf946SGreg Clayton 
14312daf946SGreg Clayton 
14430fdc8d8SChris Lattner StackFrameSP
14512daf946SGreg Clayton StackFrameList::GetFrameAtIndex (uint32_t idx)
14630fdc8d8SChris Lattner {
14730fdc8d8SChris Lattner     StackFrameSP frame_sp;
14830fdc8d8SChris Lattner     {
14930fdc8d8SChris Lattner         Mutex::Locker locker (m_mutex);
15012daf946SGreg Clayton 
15112daf946SGreg Clayton         if (m_show_inlined_frames)
15212daf946SGreg Clayton         {
15312daf946SGreg Clayton             frame_sp = GetInlineFrameAtIndex (idx);
15412daf946SGreg Clayton         }
15512daf946SGreg Clayton         else
15612daf946SGreg Clayton         {
1570445d8f4SGreg Clayton             frame_sp = GetUnwindFrameAtIndex (idx);
15812daf946SGreg Clayton         }
15912daf946SGreg Clayton 
16012daf946SGreg Clayton         if (frame_sp.get())
16112daf946SGreg Clayton             return frame_sp;
16212daf946SGreg Clayton 
16312daf946SGreg Clayton         // Special case the first frame (idx == 0) so that we don't need to
16412daf946SGreg Clayton         // know how many stack frames there are to get it. If we need any other
16512daf946SGreg Clayton         // frames, then we do need to know if "idx" is a valid index.
16612daf946SGreg Clayton         if (idx == 0)
16712daf946SGreg Clayton         {
16812daf946SGreg Clayton             // If this is the first frame, we want to share the thread register
16912daf946SGreg Clayton             // context with the stack frame at index zero.
17012daf946SGreg Clayton             m_thread.GetRegisterContext();
17112daf946SGreg Clayton             assert (m_thread.m_reg_context_sp.get());
17212daf946SGreg Clayton             frame_sp.reset (new StackFrame (0,
17312daf946SGreg Clayton                                             0,
17412daf946SGreg Clayton                                             m_thread,
17512daf946SGreg Clayton                                             m_thread.m_reg_context_sp,
17612daf946SGreg Clayton                                             m_thread.m_reg_context_sp->GetSP(),
17712daf946SGreg Clayton                                             m_thread.m_reg_context_sp->GetPC(),
17812daf946SGreg Clayton                                             NULL));
1790445d8f4SGreg Clayton 
1800445d8f4SGreg Clayton             if (m_show_inlined_frames && idx + 1 < m_inlined_info.size())
1810445d8f4SGreg Clayton             {
1820445d8f4SGreg Clayton                 if (m_inlined_info[idx].unwind_frame_index == m_inlined_info[idx+1].unwind_frame_index)
1830445d8f4SGreg Clayton                     frame_sp->SetInlineBlockID (frame_sp->GetSymbolContext (eSymbolContextBlock).block->GetID());
1840445d8f4SGreg Clayton             }
1850445d8f4SGreg Clayton 
18612daf946SGreg Clayton         }
18712daf946SGreg Clayton         else if (idx < GetNumFrames())
18812daf946SGreg Clayton         {
18912daf946SGreg Clayton             if (m_show_inlined_frames)
19012daf946SGreg Clayton             {
1910445d8f4SGreg Clayton                 if (m_inlined_info[idx].block == NULL)
19212daf946SGreg Clayton                 {
19312daf946SGreg Clayton                     // Same as the concrete stack frame if block is NULL
1940445d8f4SGreg Clayton                     assert (m_inlined_info[idx].unwind_frame_index < m_unwind_frames.size());
1950445d8f4SGreg Clayton                     frame_sp = GetUnwindFrameAtIndex (m_inlined_info[idx].unwind_frame_index);
1960445d8f4SGreg Clayton                     if (idx + 1 < m_inlined_info.size())
1970445d8f4SGreg Clayton                     {
1980445d8f4SGreg Clayton                         if (m_inlined_info[idx].unwind_frame_index == m_inlined_info[idx+1].unwind_frame_index)
1990445d8f4SGreg Clayton                             frame_sp->SetInlineBlockID (frame_sp->GetSymbolContext (eSymbolContextBlock).block->GetID());
2000445d8f4SGreg Clayton                     }
20112daf946SGreg Clayton                 }
20212daf946SGreg Clayton                 else
20312daf946SGreg Clayton                 {
20412daf946SGreg Clayton                     // We have blocks that were above an inlined function. Inlined
20512daf946SGreg Clayton                     // functions are represented as blocks with non-NULL inline
20612daf946SGreg Clayton                     // function info. Here we must reconstruct a frame by looking
20712daf946SGreg Clayton                     // at the block
20812daf946SGreg Clayton                     StackFrameSP previous_frame_sp (m_thread.GetStackFrameAtIndex (idx-1));
20912daf946SGreg Clayton 
21012daf946SGreg Clayton                     SymbolContext inline_sc;
21112daf946SGreg Clayton 
2120445d8f4SGreg Clayton                     Block *inlined_parent_block = m_inlined_info[idx].block->GetInlinedParent();
21312daf946SGreg Clayton 
21412daf946SGreg Clayton                     if (inlined_parent_block)
21512daf946SGreg Clayton                         inlined_parent_block->CalculateSymbolContext (&inline_sc);
21612daf946SGreg Clayton                     else
21712daf946SGreg Clayton                     {
2180445d8f4SGreg Clayton                         Block *parent_block = m_inlined_info[idx].block->GetParent();
21912daf946SGreg Clayton                         parent_block->CalculateSymbolContext(&inline_sc);
22012daf946SGreg Clayton                     }
22112daf946SGreg Clayton 
22212daf946SGreg Clayton                     Address previous_frame_lookup_addr (previous_frame_sp->GetFrameCodeAddress());
2230445d8f4SGreg Clayton                     if (previous_frame_sp->GetFrameIndex() > 0 && m_inlined_info[idx-1].block == NULL)
22412daf946SGreg Clayton                         previous_frame_lookup_addr.Slide (-1);
22512daf946SGreg Clayton 
22612daf946SGreg Clayton                     AddressRange range;
2270445d8f4SGreg Clayton                     m_inlined_info[idx].block->GetRangeContainingAddress (previous_frame_lookup_addr, range);
22812daf946SGreg Clayton 
2290445d8f4SGreg Clayton                     const InlineFunctionInfo* inline_info = m_inlined_info[idx].block->InlinedFunctionInfo();
23012daf946SGreg Clayton                     assert (inline_info);
23112daf946SGreg Clayton                     inline_sc.line_entry.range.GetBaseAddress() = previous_frame_sp->GetFrameCodeAddress();
23212daf946SGreg Clayton                     inline_sc.line_entry.file = inline_info->GetCallSite().GetFile();
23312daf946SGreg Clayton                     inline_sc.line_entry.line = inline_info->GetCallSite().GetLine();
23412daf946SGreg Clayton                     inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn();
23512daf946SGreg Clayton 
2360445d8f4SGreg Clayton                     StackFrameSP concrete_frame_sp (GetUnwindFrameAtIndex (m_inlined_info[idx].unwind_frame_index));
23712daf946SGreg Clayton                     assert (previous_frame_sp.get());
23812daf946SGreg Clayton 
23912daf946SGreg Clayton                     frame_sp.reset (new StackFrame (idx,
2400445d8f4SGreg Clayton                                                     m_inlined_info[idx].unwind_frame_index,
24112daf946SGreg Clayton                                                     m_thread,
24212daf946SGreg Clayton                                                     concrete_frame_sp->GetRegisterContextSP (),
24312daf946SGreg Clayton                                                     concrete_frame_sp->GetStackID().GetCallFrameAddress(),  // CFA
24412daf946SGreg Clayton                                                     range.GetBaseAddress(),
24512daf946SGreg Clayton                                                     &inline_sc));                                           // The symbol context for this inline frame
24612daf946SGreg Clayton 
2470445d8f4SGreg Clayton                     if (idx + 1 < m_inlined_info.size())
2480445d8f4SGreg Clayton                     {
2490445d8f4SGreg Clayton                         if (m_inlined_info[idx].unwind_frame_index == m_inlined_info[idx+1].unwind_frame_index)
2500445d8f4SGreg Clayton                             frame_sp->SetInlineBlockID (m_inlined_info[idx].block->GetID());
2510445d8f4SGreg Clayton                     }
25212daf946SGreg Clayton                 }
25312daf946SGreg Clayton             }
25412daf946SGreg Clayton             else
25512daf946SGreg Clayton             {
25612daf946SGreg Clayton                 Unwind *unwinder = m_thread.GetUnwinder ();
25712daf946SGreg Clayton                 if (unwinder)
25812daf946SGreg Clayton                 {
25912daf946SGreg Clayton                     addr_t pc, cfa;
26012daf946SGreg Clayton                     if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
2610445d8f4SGreg Clayton                         frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL));
26212daf946SGreg Clayton                 }
26312daf946SGreg Clayton             }
26412daf946SGreg Clayton         }
2650445d8f4SGreg Clayton 
26612daf946SGreg Clayton         if (m_show_inlined_frames)
2670445d8f4SGreg Clayton         {
26812daf946SGreg Clayton             SetInlineFrameAtIndex(idx, frame_sp);
2690445d8f4SGreg Clayton         }
27012daf946SGreg Clayton         else
2710445d8f4SGreg Clayton         {
2720445d8f4SGreg Clayton             SetUnwindFrameAtIndex(idx, frame_sp);
2730445d8f4SGreg Clayton         }
27412daf946SGreg Clayton         return frame_sp;
27512daf946SGreg Clayton 
27630fdc8d8SChris Lattner     }
27730fdc8d8SChris Lattner     return frame_sp;
27830fdc8d8SChris Lattner }
27930fdc8d8SChris Lattner 
28030fdc8d8SChris Lattner bool
2810445d8f4SGreg Clayton StackFrameList::SetUnwindFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
28230fdc8d8SChris Lattner {
2830445d8f4SGreg Clayton     if (idx >= m_unwind_frames.size())
2840445d8f4SGreg Clayton         m_unwind_frames.resize(idx + 1);
28530fdc8d8SChris Lattner     // Make sure allocation succeeded by checking bounds again
2860445d8f4SGreg Clayton     if (idx < m_unwind_frames.size())
28730fdc8d8SChris Lattner     {
2880445d8f4SGreg Clayton         m_unwind_frames[idx] = frame_sp;
28912daf946SGreg Clayton         return true;
29012daf946SGreg Clayton     }
29112daf946SGreg Clayton     return false;   // resize failed, out of memory?
29212daf946SGreg Clayton }
29312daf946SGreg Clayton 
29412daf946SGreg Clayton bool
29512daf946SGreg Clayton StackFrameList::SetInlineFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
29612daf946SGreg Clayton {
29712daf946SGreg Clayton     if (idx >= m_inline_frames.size())
29812daf946SGreg Clayton         m_inline_frames.resize(idx + 1);
29912daf946SGreg Clayton     // Make sure allocation succeeded by checking bounds again
30012daf946SGreg Clayton     if (idx < m_inline_frames.size())
30112daf946SGreg Clayton     {
30212daf946SGreg Clayton         m_inline_frames[idx] = frame_sp;
30330fdc8d8SChris Lattner         return true;
30430fdc8d8SChris Lattner     }
30530fdc8d8SChris Lattner     return false;   // resize failed, out of memory?
30630fdc8d8SChris Lattner }
30730fdc8d8SChris Lattner 
30830fdc8d8SChris Lattner uint32_t
309*2976d00aSJim Ingham StackFrameList::GetSelectedFrameIndex () const
31030fdc8d8SChris Lattner {
31130fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
312*2976d00aSJim Ingham     return m_selected_frame_idx;
31330fdc8d8SChris Lattner }
31430fdc8d8SChris Lattner 
31530fdc8d8SChris Lattner 
31630fdc8d8SChris Lattner uint32_t
317*2976d00aSJim Ingham StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame)
31830fdc8d8SChris Lattner {
31930fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
32012daf946SGreg Clayton     const_iterator pos;
3210445d8f4SGreg Clayton     const_iterator begin = m_show_inlined_frames ? m_inline_frames.begin() : m_unwind_frames.begin();
3220445d8f4SGreg Clayton     const_iterator end   = m_show_inlined_frames ? m_inline_frames.end()   : m_unwind_frames.end();
32330fdc8d8SChris Lattner     for (pos = begin; pos != end; ++pos)
32430fdc8d8SChris Lattner     {
32530fdc8d8SChris Lattner         if (pos->get() == frame)
32630fdc8d8SChris Lattner         {
327*2976d00aSJim Ingham             m_selected_frame_idx = std::distance (begin, pos);
328*2976d00aSJim Ingham             return m_selected_frame_idx;
32930fdc8d8SChris Lattner         }
33030fdc8d8SChris Lattner     }
331*2976d00aSJim Ingham     m_selected_frame_idx = 0;
332*2976d00aSJim Ingham     return m_selected_frame_idx;
33330fdc8d8SChris Lattner }
33430fdc8d8SChris Lattner 
33530fdc8d8SChris Lattner // Mark a stack frame as the current frame using the frame index
33630fdc8d8SChris Lattner void
337*2976d00aSJim Ingham StackFrameList::SetSelectedFrameByIndex (uint32_t idx)
33830fdc8d8SChris Lattner {
33930fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
340*2976d00aSJim Ingham     m_selected_frame_idx = idx;
34130fdc8d8SChris Lattner }
34230fdc8d8SChris Lattner 
34330fdc8d8SChris Lattner // The thread has been run, reset the number stack frames to zero so we can
34430fdc8d8SChris Lattner // determine how many frames we have lazily.
34530fdc8d8SChris Lattner void
34630fdc8d8SChris Lattner StackFrameList::Clear ()
34730fdc8d8SChris Lattner {
34830fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
3490445d8f4SGreg Clayton     m_unwind_frames.clear();
35012daf946SGreg Clayton     m_inline_frames.clear();
3510445d8f4SGreg Clayton     m_inlined_info.clear();
35230fdc8d8SChris Lattner }
35330fdc8d8SChris Lattner 
35430fdc8d8SChris Lattner void
35530fdc8d8SChris Lattner StackFrameList::InvalidateFrames (uint32_t start_idx)
35630fdc8d8SChris Lattner {
35730fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
35812daf946SGreg Clayton     if (m_show_inlined_frames)
35912daf946SGreg Clayton     {
36012daf946SGreg Clayton         Clear();
36112daf946SGreg Clayton     }
36212daf946SGreg Clayton     else
36312daf946SGreg Clayton     {
3640445d8f4SGreg Clayton         const size_t num_frames = m_unwind_frames.size();
36530fdc8d8SChris Lattner         while (start_idx < num_frames)
36630fdc8d8SChris Lattner         {
3670445d8f4SGreg Clayton             m_unwind_frames[start_idx].reset();
36830fdc8d8SChris Lattner             ++start_idx;
36930fdc8d8SChris Lattner         }
37030fdc8d8SChris Lattner     }
37112daf946SGreg Clayton }
372