130fdc8d8SChris Lattner //===-- StackFrameList.cpp --------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1012daf946SGreg Clayton #include "lldb/Target/StackFrameList.h"
1112daf946SGreg Clayton 
1230fdc8d8SChris Lattner // C Includes
1330fdc8d8SChris Lattner // C++ Includes
1430fdc8d8SChris Lattner // Other libraries and framework includes
1530fdc8d8SChris Lattner // Project includes
165082c5fdSGreg Clayton #include "lldb/Core/StreamFile.h"
1712daf946SGreg Clayton #include "lldb/Symbol/Block.h"
1812daf946SGreg Clayton #include "lldb/Symbol/Function.h"
1959e8fc1cSGreg Clayton #include "lldb/Symbol/Symbol.h"
2012daf946SGreg Clayton #include "lldb/Target/RegisterContext.h"
2130fdc8d8SChris Lattner #include "lldb/Target/StackFrame.h"
2212daf946SGreg Clayton #include "lldb/Target/Thread.h"
2312daf946SGreg Clayton #include "lldb/Target/Unwind.h"
2430fdc8d8SChris Lattner 
255082c5fdSGreg Clayton //#define DEBUG_STACK_FRAMES 1
265082c5fdSGreg Clayton 
2730fdc8d8SChris Lattner using namespace lldb;
2830fdc8d8SChris Lattner using namespace lldb_private;
2930fdc8d8SChris Lattner 
3030fdc8d8SChris Lattner //----------------------------------------------------------------------
3130fdc8d8SChris Lattner // StackFrameList constructor
3230fdc8d8SChris Lattner //----------------------------------------------------------------------
332cad65a5SGreg Clayton StackFrameList::StackFrameList
342cad65a5SGreg Clayton (
352cad65a5SGreg Clayton     Thread &thread,
362cad65a5SGreg Clayton     const lldb::StackFrameListSP &prev_frames_sp,
372cad65a5SGreg Clayton     bool show_inline_frames
382cad65a5SGreg Clayton ) :
3912daf946SGreg Clayton     m_thread (thread),
402cad65a5SGreg Clayton     m_prev_frames_sp (prev_frames_sp),
4112daf946SGreg Clayton     m_show_inlined_frames (show_inline_frames),
4230fdc8d8SChris Lattner     m_mutex (Mutex::eMutexTypeRecursive),
435082c5fdSGreg Clayton     m_frames (),
442976d00aSJim Ingham     m_selected_frame_idx (0)
4530fdc8d8SChris Lattner {
4630fdc8d8SChris Lattner }
4730fdc8d8SChris Lattner 
4830fdc8d8SChris Lattner //----------------------------------------------------------------------
4930fdc8d8SChris Lattner // Destructor
5030fdc8d8SChris Lattner //----------------------------------------------------------------------
5130fdc8d8SChris Lattner StackFrameList::~StackFrameList()
5230fdc8d8SChris Lattner {
5330fdc8d8SChris Lattner }
5430fdc8d8SChris Lattner 
5530fdc8d8SChris Lattner 
5630fdc8d8SChris Lattner uint32_t
572cad65a5SGreg Clayton StackFrameList::GetNumFrames (bool can_create)
5830fdc8d8SChris Lattner {
5930fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
6012daf946SGreg Clayton 
612cad65a5SGreg Clayton     if (can_create && m_frames.size() <= 1)
625082c5fdSGreg Clayton     {
6312daf946SGreg Clayton         if (m_show_inlined_frames)
6412daf946SGreg Clayton         {
655082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
665082c5fdSGreg Clayton             StreamFile s(stdout);
675082c5fdSGreg Clayton #endif
6812daf946SGreg Clayton             Unwind *unwinder = m_thread.GetUnwinder ();
6959e8fc1cSGreg Clayton             addr_t pc = LLDB_INVALID_ADDRESS;
7059e8fc1cSGreg Clayton             addr_t cfa = LLDB_INVALID_ADDRESS;
715082c5fdSGreg Clayton 
7212daf946SGreg Clayton             // If we are going to show inlined stack frames as actual frames,
7312daf946SGreg Clayton             // we need to calculate all concrete frames first, then iterate
7412daf946SGreg Clayton             // through all of them and count up how many inlined functions are
755082c5fdSGreg Clayton             // in each frame.
765082c5fdSGreg Clayton             const uint32_t unwind_frame_count = unwinder->GetFrameCount();
7712daf946SGreg Clayton 
785082c5fdSGreg Clayton             StackFrameSP unwind_frame_sp;
795082c5fdSGreg Clayton             for (uint32_t idx=0; idx<unwind_frame_count; ++idx)
8012daf946SGreg Clayton             {
8112daf946SGreg Clayton                 if (idx == 0)
8212daf946SGreg Clayton                 {
835082c5fdSGreg Clayton                     // We might have already created frame zero, only create it
845082c5fdSGreg Clayton                     // if we need to
855082c5fdSGreg Clayton                     if (m_frames.empty())
865082c5fdSGreg Clayton                     {
8759e8fc1cSGreg Clayton                         cfa = m_thread.m_reg_context_sp->GetSP();
8812daf946SGreg Clayton                         m_thread.GetRegisterContext();
895082c5fdSGreg Clayton                         unwind_frame_sp.reset (new StackFrame (m_frames.size(),
905082c5fdSGreg Clayton                                                                idx,
9112daf946SGreg Clayton                                                                m_thread,
9212daf946SGreg Clayton                                                                m_thread.m_reg_context_sp,
9359e8fc1cSGreg Clayton                                                                cfa,
9412daf946SGreg Clayton                                                                m_thread.m_reg_context_sp->GetPC(),
9512daf946SGreg Clayton                                                                NULL));
965082c5fdSGreg Clayton                         m_frames.push_back (unwind_frame_sp);
975082c5fdSGreg Clayton                     }
985082c5fdSGreg Clayton                     else
995082c5fdSGreg Clayton                     {
1005082c5fdSGreg Clayton                         unwind_frame_sp = m_frames.front();
10159e8fc1cSGreg Clayton                         cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
1025082c5fdSGreg Clayton                     }
10312daf946SGreg Clayton                 }
10412daf946SGreg Clayton                 else
10512daf946SGreg Clayton                 {
10612daf946SGreg Clayton                     const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
10712daf946SGreg Clayton                     assert (success);
1085082c5fdSGreg Clayton                     unwind_frame_sp.reset (new StackFrame (m_frames.size(), idx, m_thread, cfa, pc, NULL));
1095082c5fdSGreg Clayton                     m_frames.push_back (unwind_frame_sp);
11012daf946SGreg Clayton                 }
11112daf946SGreg Clayton 
11259e8fc1cSGreg Clayton                 Block *unwind_block = unwind_frame_sp->GetSymbolContext (eSymbolContextBlock).block;
11312daf946SGreg Clayton 
11459e8fc1cSGreg Clayton                 if (unwind_block)
11512daf946SGreg Clayton                 {
11659e8fc1cSGreg Clayton                     Block *inlined_block = unwind_block->GetContainingInlinedBlock();
11759e8fc1cSGreg Clayton                     if (inlined_block)
11859e8fc1cSGreg Clayton                     {
11959e8fc1cSGreg Clayton                         for (; inlined_block != NULL; inlined_block = inlined_block->GetInlinedParent ())
1200445d8f4SGreg Clayton                         {
1215082c5fdSGreg Clayton                             SymbolContext inline_sc;
12259e8fc1cSGreg Clayton                             Block *parent_block = inlined_block->GetInlinedParent();
12312daf946SGreg Clayton 
1245082c5fdSGreg Clayton                             const bool is_inlined_frame = parent_block != NULL;
1255082c5fdSGreg Clayton 
1265082c5fdSGreg Clayton                             if (parent_block == NULL)
12759e8fc1cSGreg Clayton                                 parent_block = inlined_block->GetParent();
1285082c5fdSGreg Clayton 
1295082c5fdSGreg Clayton                             parent_block->CalculateSymbolContext (&inline_sc);
1305082c5fdSGreg Clayton 
1315082c5fdSGreg Clayton                             Address previous_frame_lookup_addr (m_frames.back()->GetFrameCodeAddress());
1325082c5fdSGreg Clayton                             if (unwind_frame_sp->GetFrameIndex() > 0 && m_frames.back().get() == unwind_frame_sp.get())
1335082c5fdSGreg Clayton                                 previous_frame_lookup_addr.Slide (-1);
1345082c5fdSGreg Clayton 
1355082c5fdSGreg Clayton                             AddressRange range;
13659e8fc1cSGreg Clayton                             inlined_block->GetRangeContainingAddress (previous_frame_lookup_addr, range);
1375082c5fdSGreg Clayton 
13895897c6aSGreg Clayton                             const InlineFunctionInfo* inline_info = inlined_block->GetInlinedFunctionInfo();
1395082c5fdSGreg Clayton                             assert (inline_info);
1405082c5fdSGreg Clayton                             inline_sc.line_entry.range.GetBaseAddress() = m_frames.back()->GetFrameCodeAddress();
1415082c5fdSGreg Clayton                             inline_sc.line_entry.file = inline_info->GetCallSite().GetFile();
1425082c5fdSGreg Clayton                             inline_sc.line_entry.line = inline_info->GetCallSite().GetLine();
1435082c5fdSGreg Clayton                             inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn();
1445082c5fdSGreg Clayton 
1455082c5fdSGreg Clayton                             StackFrameSP frame_sp(new StackFrame (m_frames.size(),
1465082c5fdSGreg Clayton                                                                   idx,
1475082c5fdSGreg Clayton                                                                   m_thread,
1485082c5fdSGreg Clayton                                                                   unwind_frame_sp->GetRegisterContextSP (),
14959e8fc1cSGreg Clayton                                                                   cfa,
1505082c5fdSGreg Clayton                                                                   range.GetBaseAddress(),
1515082c5fdSGreg Clayton                                                                   &inline_sc));                                           // The symbol context for this inline frame
1525082c5fdSGreg Clayton 
1535082c5fdSGreg Clayton                             if (is_inlined_frame)
15459e8fc1cSGreg Clayton                             {
15559e8fc1cSGreg Clayton                                 // Use the block with the inlined function info
15659e8fc1cSGreg Clayton                                 // as the symbol context since we want this frame
15759e8fc1cSGreg Clayton                                 // to have only the variables for the inlined function
15859e8fc1cSGreg Clayton                                 frame_sp->SetSymbolContextScope (parent_block);
15959e8fc1cSGreg Clayton                             }
16059e8fc1cSGreg Clayton                             else
16159e8fc1cSGreg Clayton                             {
16259e8fc1cSGreg Clayton                                 // This block is not inlined with means it has no
16359e8fc1cSGreg Clayton                                 // inlined parents either, so we want to use the top
16459e8fc1cSGreg Clayton                                 // most function block.
16559e8fc1cSGreg Clayton                                 frame_sp->SetSymbolContextScope (&unwind_frame_sp->GetSymbolContext (eSymbolContextFunction).function->GetBlock(false));
16659e8fc1cSGreg Clayton                             }
1675082c5fdSGreg Clayton 
1685082c5fdSGreg Clayton                             m_frames.push_back (frame_sp);
1695082c5fdSGreg Clayton                         }
1705082c5fdSGreg Clayton                     }
1715082c5fdSGreg Clayton                 }
17259e8fc1cSGreg Clayton             }
1732cad65a5SGreg Clayton 
1742cad65a5SGreg Clayton             if (m_prev_frames_sp)
17512daf946SGreg Clayton             {
1762cad65a5SGreg Clayton                 StackFrameList *prev_frames = m_prev_frames_sp.get();
1775082c5fdSGreg Clayton                 StackFrameList *curr_frames = this;
1785082c5fdSGreg Clayton 
1795082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
18068275d5eSGreg Clayton                 s.PutCString("\nprev_frames:\n");
1815082c5fdSGreg Clayton                 prev_frames->Dump (&s);
18268275d5eSGreg Clayton                 s.PutCString("\ncurr_frames:\n");
1835082c5fdSGreg Clayton                 curr_frames->Dump (&s);
1845082c5fdSGreg Clayton                 s.EOL();
1855082c5fdSGreg Clayton #endif
1865082c5fdSGreg Clayton                 size_t curr_frame_num, prev_frame_num;
1875082c5fdSGreg Clayton 
1885082c5fdSGreg Clayton                 for (curr_frame_num = curr_frames->m_frames.size(), prev_frame_num = prev_frames->m_frames.size();
1895082c5fdSGreg Clayton                      curr_frame_num > 0 && prev_frame_num > 0;
1905082c5fdSGreg Clayton                      --curr_frame_num, --prev_frame_num)
1915082c5fdSGreg Clayton                 {
1925082c5fdSGreg Clayton                     const size_t curr_frame_idx = curr_frame_num-1;
1935082c5fdSGreg Clayton                     const size_t prev_frame_idx = prev_frame_num-1;
1945082c5fdSGreg Clayton                     StackFrameSP curr_frame_sp (curr_frames->m_frames[curr_frame_idx]);
1955082c5fdSGreg Clayton                     StackFrameSP prev_frame_sp (prev_frames->m_frames[prev_frame_idx]);
1965082c5fdSGreg Clayton 
1975082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
1982cad65a5SGreg Clayton                     s.Printf("\n\nCurr frame #%u ", curr_frame_idx);
1995082c5fdSGreg Clayton                     if (curr_frame_sp)
2002cad65a5SGreg Clayton                         curr_frame_sp->Dump (&s, true, false);
2015082c5fdSGreg Clayton                     else
2025082c5fdSGreg Clayton                         s.PutCString("NULL");
2032cad65a5SGreg Clayton                     s.Printf("\nPrev frame #%u ", prev_frame_idx);
2045082c5fdSGreg Clayton                     if (prev_frame_sp)
2052cad65a5SGreg Clayton                         prev_frame_sp->Dump (&s, true, false);
2065082c5fdSGreg Clayton                     else
2075082c5fdSGreg Clayton                         s.PutCString("NULL");
2085082c5fdSGreg Clayton #endif
2095082c5fdSGreg Clayton 
2105082c5fdSGreg Clayton                     StackFrame *curr_frame = curr_frame_sp.get();
2115082c5fdSGreg Clayton                     StackFrame *prev_frame = prev_frame_sp.get();
2125082c5fdSGreg Clayton 
2135082c5fdSGreg Clayton                     if (curr_frame == NULL || prev_frame == NULL)
2145082c5fdSGreg Clayton                         break;
2155082c5fdSGreg Clayton 
21659e8fc1cSGreg Clayton                     // Check the stack ID to make sure they are equal
21759e8fc1cSGreg Clayton                     if (curr_frame->GetStackID() != prev_frame->GetStackID())
2185082c5fdSGreg Clayton                         break;
2195082c5fdSGreg Clayton 
22059e8fc1cSGreg Clayton                     prev_frame->UpdatePreviousFrameFromCurrentFrame (*curr_frame);
22159e8fc1cSGreg Clayton                     // Now copy the fixed up previous frame into the current frames
22259e8fc1cSGreg Clayton                     // so the pointer doesn't change
22359e8fc1cSGreg Clayton                     m_frames[curr_frame_idx] = prev_frame_sp;
22459e8fc1cSGreg Clayton                     //curr_frame->UpdateCurrentFrameFromPreviousFrame (*prev_frame);
2255082c5fdSGreg Clayton 
2265082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
22768275d5eSGreg Clayton                     s.Printf("\n    Copying previous frame to current frame");
2285082c5fdSGreg Clayton #endif
2295082c5fdSGreg Clayton                 }
2305082c5fdSGreg Clayton                 // We are done with the old stack frame list, we can release it now
2312cad65a5SGreg Clayton                 m_prev_frames_sp.reset();
2325082c5fdSGreg Clayton             }
23368275d5eSGreg Clayton 
23468275d5eSGreg Clayton #if defined (DEBUG_STACK_FRAMES)
23568275d5eSGreg Clayton                 s.PutCString("\n\nNew frames:\n");
23668275d5eSGreg Clayton                 Dump (&s);
23768275d5eSGreg Clayton                 s.EOL();
23868275d5eSGreg Clayton #endif
23912daf946SGreg Clayton         }
24012daf946SGreg Clayton         else
24112daf946SGreg Clayton         {
2425082c5fdSGreg Clayton             m_frames.resize(m_thread.GetUnwinder()->GetFrameCount());
24312daf946SGreg Clayton         }
2445082c5fdSGreg Clayton     }
2455082c5fdSGreg Clayton     return m_frames.size();
24630fdc8d8SChris Lattner }
24730fdc8d8SChris Lattner 
2485082c5fdSGreg Clayton void
2495082c5fdSGreg Clayton StackFrameList::Dump (Stream *s)
25030fdc8d8SChris Lattner {
2515082c5fdSGreg Clayton     if (s == NULL)
2525082c5fdSGreg Clayton         return;
2535082c5fdSGreg Clayton     Mutex::Locker locker (m_mutex);
25430fdc8d8SChris Lattner 
2555082c5fdSGreg Clayton     const_iterator pos, begin = m_frames.begin(), end = m_frames.end();
2565082c5fdSGreg Clayton     for (pos = begin; pos != end; ++pos)
25712daf946SGreg Clayton     {
2585082c5fdSGreg Clayton         StackFrame *frame = (*pos).get();
2595082c5fdSGreg Clayton         s->Printf("%p: ", frame);
2605082c5fdSGreg Clayton         if (frame)
26159e8fc1cSGreg Clayton         {
26259e8fc1cSGreg Clayton             frame->GetStackID().Dump (s);
2636dadd508SGreg Clayton             frame->Dump(s, true, false);
26459e8fc1cSGreg Clayton         }
2655082c5fdSGreg Clayton         else
2665082c5fdSGreg Clayton             s->Printf("frame #%u", std::distance (begin, pos));
2675082c5fdSGreg Clayton         s->EOL();
26812daf946SGreg Clayton     }
2695082c5fdSGreg Clayton     s->EOL();
2705082c5fdSGreg Clayton }
27112daf946SGreg Clayton 
27230fdc8d8SChris Lattner StackFrameSP
27312daf946SGreg Clayton StackFrameList::GetFrameAtIndex (uint32_t idx)
27430fdc8d8SChris Lattner {
27530fdc8d8SChris Lattner     StackFrameSP frame_sp;
27630fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
2775082c5fdSGreg Clayton     if (idx < m_frames.size())
2785082c5fdSGreg Clayton         frame_sp = m_frames[idx];
27912daf946SGreg Clayton 
2805082c5fdSGreg Clayton     if (frame_sp)
28112daf946SGreg Clayton         return frame_sp;
28212daf946SGreg Clayton 
28312daf946SGreg Clayton     // Special case the first frame (idx == 0) so that we don't need to
28412daf946SGreg Clayton     // know how many stack frames there are to get it. If we need any other
28512daf946SGreg Clayton     // frames, then we do need to know if "idx" is a valid index.
28612daf946SGreg Clayton     if (idx == 0)
28712daf946SGreg Clayton     {
28812daf946SGreg Clayton         // If this is the first frame, we want to share the thread register
28912daf946SGreg Clayton         // context with the stack frame at index zero.
29012daf946SGreg Clayton         m_thread.GetRegisterContext();
29112daf946SGreg Clayton         assert (m_thread.m_reg_context_sp.get());
29212daf946SGreg Clayton         frame_sp.reset (new StackFrame (0,
29312daf946SGreg Clayton                                         0,
29412daf946SGreg Clayton                                         m_thread,
29512daf946SGreg Clayton                                         m_thread.m_reg_context_sp,
29612daf946SGreg Clayton                                         m_thread.m_reg_context_sp->GetSP(),
29712daf946SGreg Clayton                                         m_thread.m_reg_context_sp->GetPC(),
29812daf946SGreg Clayton                                         NULL));
2990445d8f4SGreg Clayton 
3005082c5fdSGreg Clayton         SetFrameAtIndex(idx, frame_sp);
30112daf946SGreg Clayton     }
30212daf946SGreg Clayton     else if (idx < GetNumFrames())
30312daf946SGreg Clayton     {
30412daf946SGreg Clayton         if (m_show_inlined_frames)
30512daf946SGreg Clayton         {
3065082c5fdSGreg Clayton             // When inline frames are enabled we cache up all frames in GetNumFrames()
3075082c5fdSGreg Clayton             frame_sp = m_frames[idx];
30812daf946SGreg Clayton         }
30912daf946SGreg Clayton         else
31012daf946SGreg Clayton         {
31112daf946SGreg Clayton             Unwind *unwinder = m_thread.GetUnwinder ();
31212daf946SGreg Clayton             if (unwinder)
31312daf946SGreg Clayton             {
31412daf946SGreg Clayton                 addr_t pc, cfa;
31512daf946SGreg Clayton                 if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
3165082c5fdSGreg Clayton                 {
3170445d8f4SGreg Clayton                     frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL));
31859e8fc1cSGreg Clayton 
31959e8fc1cSGreg Clayton                     Function *function = frame_sp->GetSymbolContext (eSymbolContextFunction).function;
32059e8fc1cSGreg Clayton                     if (function)
32159e8fc1cSGreg Clayton                     {
32259e8fc1cSGreg Clayton                         // When we aren't showing inline functions we always use
32359e8fc1cSGreg Clayton                         // the top most function block as the scope.
32459e8fc1cSGreg Clayton                         frame_sp->SetSymbolContextScope (&function->GetBlock(false));
32559e8fc1cSGreg Clayton                     }
32659e8fc1cSGreg Clayton                     else
32759e8fc1cSGreg Clayton                     {
32859e8fc1cSGreg Clayton                         // Set the symbol scope from the symbol regardless if it is NULL or valid.
32959e8fc1cSGreg Clayton                         frame_sp->SetSymbolContextScope (frame_sp->GetSymbolContext (eSymbolContextSymbol).symbol);
33059e8fc1cSGreg Clayton                     }
3315082c5fdSGreg Clayton                     SetFrameAtIndex(idx, frame_sp);
33212daf946SGreg Clayton                 }
33312daf946SGreg Clayton             }
33412daf946SGreg Clayton         }
33530fdc8d8SChris Lattner     }
33630fdc8d8SChris Lattner     return frame_sp;
33730fdc8d8SChris Lattner }
33830fdc8d8SChris Lattner 
33912daf946SGreg Clayton bool
3405082c5fdSGreg Clayton StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
34112daf946SGreg Clayton {
3425082c5fdSGreg Clayton     if (idx >= m_frames.size())
3435082c5fdSGreg Clayton         m_frames.resize(idx + 1);
34412daf946SGreg Clayton     // Make sure allocation succeeded by checking bounds again
3455082c5fdSGreg Clayton     if (idx < m_frames.size())
34612daf946SGreg Clayton     {
3475082c5fdSGreg Clayton         m_frames[idx] = frame_sp;
34830fdc8d8SChris Lattner         return true;
34930fdc8d8SChris Lattner     }
35030fdc8d8SChris Lattner     return false;   // resize failed, out of memory?
35130fdc8d8SChris Lattner }
35230fdc8d8SChris Lattner 
35330fdc8d8SChris Lattner uint32_t
3542976d00aSJim Ingham StackFrameList::GetSelectedFrameIndex () const
35530fdc8d8SChris Lattner {
35630fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
3572976d00aSJim Ingham     return m_selected_frame_idx;
35830fdc8d8SChris Lattner }
35930fdc8d8SChris Lattner 
36030fdc8d8SChris Lattner 
36130fdc8d8SChris Lattner uint32_t
3622976d00aSJim Ingham StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame)
36330fdc8d8SChris Lattner {
36430fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
36512daf946SGreg Clayton     const_iterator pos;
3665082c5fdSGreg Clayton     const_iterator begin = m_frames.begin();
3675082c5fdSGreg Clayton     const_iterator end = m_frames.end();
36830fdc8d8SChris Lattner     for (pos = begin; pos != end; ++pos)
36930fdc8d8SChris Lattner     {
37030fdc8d8SChris Lattner         if (pos->get() == frame)
37130fdc8d8SChris Lattner         {
3722976d00aSJim Ingham             m_selected_frame_idx = std::distance (begin, pos);
3732976d00aSJim Ingham             return m_selected_frame_idx;
37430fdc8d8SChris Lattner         }
37530fdc8d8SChris Lattner     }
3762976d00aSJim Ingham     m_selected_frame_idx = 0;
3772976d00aSJim Ingham     return m_selected_frame_idx;
37830fdc8d8SChris Lattner }
37930fdc8d8SChris Lattner 
38030fdc8d8SChris Lattner // Mark a stack frame as the current frame using the frame index
38130fdc8d8SChris Lattner void
3822976d00aSJim Ingham StackFrameList::SetSelectedFrameByIndex (uint32_t idx)
38330fdc8d8SChris Lattner {
38430fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
3852976d00aSJim Ingham     m_selected_frame_idx = idx;
38630fdc8d8SChris Lattner }
38730fdc8d8SChris Lattner 
38830fdc8d8SChris Lattner // The thread has been run, reset the number stack frames to zero so we can
38930fdc8d8SChris Lattner // determine how many frames we have lazily.
39030fdc8d8SChris Lattner void
39130fdc8d8SChris Lattner StackFrameList::Clear ()
39230fdc8d8SChris Lattner {
39330fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
3945082c5fdSGreg Clayton     m_frames.clear();
39530fdc8d8SChris Lattner }
39630fdc8d8SChris Lattner 
39730fdc8d8SChris Lattner void
39830fdc8d8SChris Lattner StackFrameList::InvalidateFrames (uint32_t start_idx)
39930fdc8d8SChris Lattner {
40030fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
40112daf946SGreg Clayton     if (m_show_inlined_frames)
40212daf946SGreg Clayton     {
40312daf946SGreg Clayton         Clear();
40412daf946SGreg Clayton     }
40512daf946SGreg Clayton     else
40612daf946SGreg Clayton     {
4075082c5fdSGreg Clayton         const size_t num_frames = m_frames.size();
40830fdc8d8SChris Lattner         while (start_idx < num_frames)
40930fdc8d8SChris Lattner         {
4105082c5fdSGreg Clayton             m_frames[start_idx].reset();
41130fdc8d8SChris Lattner             ++start_idx;
41230fdc8d8SChris Lattner         }
41330fdc8d8SChris Lattner     }
41412daf946SGreg Clayton }
4152cad65a5SGreg Clayton 
4162cad65a5SGreg Clayton void
4172cad65a5SGreg Clayton StackFrameList::Merge (std::auto_ptr<StackFrameList>& curr_ap, lldb::StackFrameListSP& prev_sp)
4182cad65a5SGreg Clayton {
4192cad65a5SGreg Clayton     Mutex::Locker curr_locker (curr_ap.get() ? curr_ap->m_mutex.GetMutex() : NULL);
4202cad65a5SGreg Clayton     Mutex::Locker prev_locker (prev_sp.get() ? prev_sp->m_mutex.GetMutex() : NULL);
4212cad65a5SGreg Clayton 
4222cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
4232cad65a5SGreg Clayton     StreamFile s(stdout);
4242cad65a5SGreg Clayton     s.PutCString("\n\nStackFrameList::Merge():\nPrev:\n");
4252cad65a5SGreg Clayton     if (prev_sp.get())
4262cad65a5SGreg Clayton         prev_sp->Dump (&s);
4272cad65a5SGreg Clayton     else
4282cad65a5SGreg Clayton         s.PutCString ("NULL");
4292cad65a5SGreg Clayton     s.PutCString("\nCurr:\n");
4302cad65a5SGreg Clayton     if (curr_ap.get())
4312cad65a5SGreg Clayton         curr_ap->Dump (&s);
4322cad65a5SGreg Clayton     else
4332cad65a5SGreg Clayton         s.PutCString ("NULL");
4342cad65a5SGreg Clayton     s.EOL();
4352cad65a5SGreg Clayton #endif
4362cad65a5SGreg Clayton 
4372cad65a5SGreg Clayton     if (curr_ap.get() == NULL || curr_ap->GetNumFrames (false) == 0)
4382cad65a5SGreg Clayton     {
4392cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
4402cad65a5SGreg Clayton         s.PutCString("No current frames, leave previous frames alone...\n");
4412cad65a5SGreg Clayton #endif
4422cad65a5SGreg Clayton         curr_ap.release();
4432cad65a5SGreg Clayton         return;
4442cad65a5SGreg Clayton     }
4452cad65a5SGreg Clayton 
4462cad65a5SGreg Clayton     if (prev_sp.get() == NULL || prev_sp->GetNumFrames (false) == 0)
4472cad65a5SGreg Clayton     {
4482cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
4492cad65a5SGreg Clayton         s.PutCString("No previous frames, so use current frames...\n");
4502cad65a5SGreg Clayton #endif
4512cad65a5SGreg Clayton         // We either don't have any previous frames, or since we have more than
4522cad65a5SGreg Clayton         // one current frames it means we have all the frames and can safely
4532cad65a5SGreg Clayton         // replace our previous frames.
4542cad65a5SGreg Clayton         prev_sp.reset (curr_ap.release());
4552cad65a5SGreg Clayton         return;
4562cad65a5SGreg Clayton     }
4572cad65a5SGreg Clayton 
4582cad65a5SGreg Clayton     const uint32_t num_curr_frames = curr_ap->GetNumFrames (false);
4592cad65a5SGreg Clayton 
4602cad65a5SGreg Clayton     if (num_curr_frames > 1)
4612cad65a5SGreg Clayton     {
4622cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
4632cad65a5SGreg Clayton         s.PutCString("We have more than one current frame, so use current frames...\n");
4642cad65a5SGreg Clayton #endif
4652cad65a5SGreg Clayton         // We have more than one current frames it means we have all the frames
4662cad65a5SGreg Clayton         // and can safely replace our previous frames.
4672cad65a5SGreg Clayton         prev_sp.reset (curr_ap.release());
4682cad65a5SGreg Clayton 
4692cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
4702cad65a5SGreg Clayton         s.PutCString("\nMerged:\n");
4712cad65a5SGreg Clayton         prev_sp->Dump (&s);
4722cad65a5SGreg Clayton #endif
4732cad65a5SGreg Clayton         return;
4742cad65a5SGreg Clayton     }
4752cad65a5SGreg Clayton 
4762cad65a5SGreg Clayton     StackFrameSP prev_frame_zero_sp(prev_sp->GetFrameAtIndex (0));
4772cad65a5SGreg Clayton     StackFrameSP curr_frame_zero_sp(curr_ap->GetFrameAtIndex (0));
4782cad65a5SGreg Clayton     StackID curr_stack_id (curr_frame_zero_sp->GetStackID());
4792cad65a5SGreg Clayton     StackID prev_stack_id (prev_frame_zero_sp->GetStackID());
4802cad65a5SGreg Clayton 
4812cad65a5SGreg Clayton     //const uint32_t num_prev_frames = prev_sp->GetNumFrames (false);
4822cad65a5SGreg Clayton 
4832cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
4842cad65a5SGreg Clayton     s.Printf("\n%u previous frames with one current frame\n", num_prev_frames);
4852cad65a5SGreg Clayton #endif
4862cad65a5SGreg Clayton 
4872cad65a5SGreg Clayton     // We have only a single current frame
4882cad65a5SGreg Clayton     // Our previous stack frames only had a single frame as well...
4892cad65a5SGreg Clayton     if (curr_stack_id == prev_stack_id)
4902cad65a5SGreg Clayton     {
4912cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
4922cad65a5SGreg Clayton         s.Printf("\nPrevious frame #0 is same as current frame #0, merge the cached data\n");
4932cad65a5SGreg Clayton #endif
4942cad65a5SGreg Clayton 
4952cad65a5SGreg Clayton         curr_frame_zero_sp->UpdateCurrentFrameFromPreviousFrame (*prev_frame_zero_sp);
4962cad65a5SGreg Clayton //        prev_frame_zero_sp->UpdatePreviousFrameFromCurrentFrame (*curr_frame_zero_sp);
4972cad65a5SGreg Clayton //        prev_sp->SetFrameAtIndex (0, prev_frame_zero_sp);
4982cad65a5SGreg Clayton     }
4992cad65a5SGreg Clayton     else if (curr_stack_id < prev_stack_id)
5002cad65a5SGreg Clayton     {
5012cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
5022cad65a5SGreg Clayton         s.Printf("\nCurrent frame #0 has a stack ID that is less than the previous frame #0, insert current frame zero in front of previous\n");
5032cad65a5SGreg Clayton #endif
5042cad65a5SGreg Clayton         prev_sp->m_frames.insert (prev_sp->m_frames.begin(), curr_frame_zero_sp);
5052cad65a5SGreg Clayton     }
5062cad65a5SGreg Clayton 
5072cad65a5SGreg Clayton     curr_ap.release();
5082cad65a5SGreg Clayton 
5092cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
5102cad65a5SGreg Clayton     s.PutCString("\nMerged:\n");
5112cad65a5SGreg Clayton     prev_sp->Dump (&s);
5122cad65a5SGreg Clayton #endif
5132cad65a5SGreg Clayton 
5142cad65a5SGreg Clayton 
5152cad65a5SGreg Clayton }
516*e4284b71SJim Ingham 
517*e4284b71SJim Ingham lldb::StackFrameSP
518*e4284b71SJim Ingham StackFrameList::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
519*e4284b71SJim Ingham {
520*e4284b71SJim Ingham     const_iterator pos;
521*e4284b71SJim Ingham     const_iterator begin = m_frames.begin();
522*e4284b71SJim Ingham     const_iterator end = m_frames.end();
523*e4284b71SJim Ingham     lldb::StackFrameSP ret_sp;
524*e4284b71SJim Ingham 
525*e4284b71SJim Ingham     for (pos = begin; pos != end; ++pos)
526*e4284b71SJim Ingham     {
527*e4284b71SJim Ingham         if (pos->get() == stack_frame_ptr)
528*e4284b71SJim Ingham         {
529*e4284b71SJim Ingham             ret_sp = (*pos);
530*e4284b71SJim Ingham             break;
531*e4284b71SJim Ingham         }
532*e4284b71SJim Ingham     }
533*e4284b71SJim Ingham     return ret_sp;
534*e4284b71SJim Ingham }
535*e4284b71SJim Ingham 
536