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),
4130fdc8d8SChris Lattner     m_mutex (Mutex::eMutexTypeRecursive),
425082c5fdSGreg Clayton     m_frames (),
4371c21d18SStephen Wilson     m_selected_frame_idx (0),
4471c21d18SStephen Wilson     m_show_inlined_frames (show_inline_frames)
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);
2630603aa9dSGreg Clayton             frame->DumpUsingSettingsFormat (s);
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 
3395ccbd294SGreg Clayton StackFrameSP
3405ccbd294SGreg Clayton StackFrameList::GetFrameWithConcreteFrameIndex (uint32_t unwind_idx)
3415ccbd294SGreg Clayton {
3425ccbd294SGreg Clayton     // First try assuming the unwind index is the same as the frame index. The
3435ccbd294SGreg Clayton     // unwind index is always greater than or equal to the frame index, so it
3445ccbd294SGreg Clayton     // is a good place to start. If we have inlined frames we might have 5
3455ccbd294SGreg Clayton     // concrete frames (frame unwind indexes go from 0-4), but we might have 15
3465ccbd294SGreg Clayton     // frames after we make all the inlined frames. Most of the time the unwind
3475ccbd294SGreg Clayton     // frame index (or the concrete frame index) is the same as the frame index.
3485ccbd294SGreg Clayton     uint32_t frame_idx = unwind_idx;
3495ccbd294SGreg Clayton     StackFrameSP frame_sp (GetFrameAtIndex (frame_idx));
3505ccbd294SGreg Clayton     while (frame_sp)
3515ccbd294SGreg Clayton     {
3525ccbd294SGreg Clayton         if (frame_sp->GetFrameIndex() == unwind_idx)
3535ccbd294SGreg Clayton             break;
3545ccbd294SGreg Clayton         frame_sp = GetFrameAtIndex (++frame_idx);
3555ccbd294SGreg Clayton     }
3565ccbd294SGreg Clayton     return frame_sp;
3575ccbd294SGreg Clayton }
3585ccbd294SGreg Clayton 
3593a195b7eSJim Ingham StackFrameSP
3603a195b7eSJim Ingham StackFrameList::GetFrameWithStackID (StackID &stack_id)
3613a195b7eSJim Ingham {
3623a195b7eSJim Ingham     uint32_t frame_idx = 0;
3633a195b7eSJim Ingham     StackFrameSP frame_sp;
3643a195b7eSJim Ingham     do
3653a195b7eSJim Ingham     {
3663a195b7eSJim Ingham         frame_sp = GetFrameAtIndex (frame_idx);
3673a195b7eSJim Ingham         if (frame_sp && frame_sp->GetStackID() == stack_id)
3683a195b7eSJim Ingham             break;
3693a195b7eSJim Ingham         frame_idx++;
3703a195b7eSJim Ingham     }
3713a195b7eSJim Ingham     while (frame_sp);
3723a195b7eSJim Ingham     return frame_sp;
3733a195b7eSJim Ingham }
3745ccbd294SGreg Clayton 
37512daf946SGreg Clayton bool
3765082c5fdSGreg Clayton StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
37712daf946SGreg Clayton {
3785082c5fdSGreg Clayton     if (idx >= m_frames.size())
3795082c5fdSGreg Clayton         m_frames.resize(idx + 1);
38012daf946SGreg Clayton     // Make sure allocation succeeded by checking bounds again
3815082c5fdSGreg Clayton     if (idx < m_frames.size())
38212daf946SGreg Clayton     {
3835082c5fdSGreg Clayton         m_frames[idx] = frame_sp;
38430fdc8d8SChris Lattner         return true;
38530fdc8d8SChris Lattner     }
38630fdc8d8SChris Lattner     return false;   // resize failed, out of memory?
38730fdc8d8SChris Lattner }
38830fdc8d8SChris Lattner 
38930fdc8d8SChris Lattner uint32_t
3902976d00aSJim Ingham StackFrameList::GetSelectedFrameIndex () const
39130fdc8d8SChris Lattner {
39230fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
3932976d00aSJim Ingham     return m_selected_frame_idx;
39430fdc8d8SChris Lattner }
39530fdc8d8SChris Lattner 
39630fdc8d8SChris Lattner 
39730fdc8d8SChris Lattner uint32_t
3982976d00aSJim Ingham StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame)
39930fdc8d8SChris Lattner {
40030fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
40112daf946SGreg Clayton     const_iterator pos;
4025082c5fdSGreg Clayton     const_iterator begin = m_frames.begin();
4035082c5fdSGreg Clayton     const_iterator end = m_frames.end();
40430fdc8d8SChris Lattner     for (pos = begin; pos != end; ++pos)
40530fdc8d8SChris Lattner     {
40630fdc8d8SChris Lattner         if (pos->get() == frame)
40730fdc8d8SChris Lattner         {
4082976d00aSJim Ingham             m_selected_frame_idx = std::distance (begin, pos);
4092976d00aSJim Ingham             return m_selected_frame_idx;
41030fdc8d8SChris Lattner         }
41130fdc8d8SChris Lattner     }
4122976d00aSJim Ingham     m_selected_frame_idx = 0;
4132976d00aSJim Ingham     return m_selected_frame_idx;
41430fdc8d8SChris Lattner }
41530fdc8d8SChris Lattner 
41630fdc8d8SChris Lattner // Mark a stack frame as the current frame using the frame index
41730fdc8d8SChris Lattner void
4182976d00aSJim Ingham StackFrameList::SetSelectedFrameByIndex (uint32_t idx)
41930fdc8d8SChris Lattner {
42030fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
4212976d00aSJim Ingham     m_selected_frame_idx = idx;
42230fdc8d8SChris Lattner }
42330fdc8d8SChris Lattner 
42430fdc8d8SChris Lattner // The thread has been run, reset the number stack frames to zero so we can
42530fdc8d8SChris Lattner // determine how many frames we have lazily.
42630fdc8d8SChris Lattner void
42730fdc8d8SChris Lattner StackFrameList::Clear ()
42830fdc8d8SChris Lattner {
42930fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
4305082c5fdSGreg Clayton     m_frames.clear();
43130fdc8d8SChris Lattner }
43230fdc8d8SChris Lattner 
43330fdc8d8SChris Lattner void
43430fdc8d8SChris Lattner StackFrameList::InvalidateFrames (uint32_t start_idx)
43530fdc8d8SChris Lattner {
43630fdc8d8SChris Lattner     Mutex::Locker locker (m_mutex);
43712daf946SGreg Clayton     if (m_show_inlined_frames)
43812daf946SGreg Clayton     {
43912daf946SGreg Clayton         Clear();
44012daf946SGreg Clayton     }
44112daf946SGreg Clayton     else
44212daf946SGreg Clayton     {
4435082c5fdSGreg Clayton         const size_t num_frames = m_frames.size();
44430fdc8d8SChris Lattner         while (start_idx < num_frames)
44530fdc8d8SChris Lattner         {
4465082c5fdSGreg Clayton             m_frames[start_idx].reset();
44730fdc8d8SChris Lattner             ++start_idx;
44830fdc8d8SChris Lattner         }
44930fdc8d8SChris Lattner     }
45012daf946SGreg Clayton }
4512cad65a5SGreg Clayton 
4522cad65a5SGreg Clayton void
4532cad65a5SGreg Clayton StackFrameList::Merge (std::auto_ptr<StackFrameList>& curr_ap, lldb::StackFrameListSP& prev_sp)
4542cad65a5SGreg Clayton {
4552cad65a5SGreg Clayton     Mutex::Locker curr_locker (curr_ap.get() ? curr_ap->m_mutex.GetMutex() : NULL);
4562cad65a5SGreg Clayton     Mutex::Locker prev_locker (prev_sp.get() ? prev_sp->m_mutex.GetMutex() : NULL);
4572cad65a5SGreg Clayton 
4582cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
4592cad65a5SGreg Clayton     StreamFile s(stdout);
4602cad65a5SGreg Clayton     s.PutCString("\n\nStackFrameList::Merge():\nPrev:\n");
4612cad65a5SGreg Clayton     if (prev_sp.get())
4622cad65a5SGreg Clayton         prev_sp->Dump (&s);
4632cad65a5SGreg Clayton     else
4642cad65a5SGreg Clayton         s.PutCString ("NULL");
4652cad65a5SGreg Clayton     s.PutCString("\nCurr:\n");
4662cad65a5SGreg Clayton     if (curr_ap.get())
4672cad65a5SGreg Clayton         curr_ap->Dump (&s);
4682cad65a5SGreg Clayton     else
4692cad65a5SGreg Clayton         s.PutCString ("NULL");
4702cad65a5SGreg Clayton     s.EOL();
4712cad65a5SGreg Clayton #endif
4722cad65a5SGreg Clayton 
4732cad65a5SGreg Clayton     if (curr_ap.get() == NULL || curr_ap->GetNumFrames (false) == 0)
4742cad65a5SGreg Clayton     {
4752cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
4762cad65a5SGreg Clayton         s.PutCString("No current frames, leave previous frames alone...\n");
4772cad65a5SGreg Clayton #endif
4782cad65a5SGreg Clayton         curr_ap.release();
4792cad65a5SGreg Clayton         return;
4802cad65a5SGreg Clayton     }
4812cad65a5SGreg Clayton 
4822cad65a5SGreg Clayton     if (prev_sp.get() == NULL || prev_sp->GetNumFrames (false) == 0)
4832cad65a5SGreg Clayton     {
4842cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
4852cad65a5SGreg Clayton         s.PutCString("No previous frames, so use current frames...\n");
4862cad65a5SGreg Clayton #endif
4872cad65a5SGreg Clayton         // We either don't have any previous frames, or since we have more than
4882cad65a5SGreg Clayton         // one current frames it means we have all the frames and can safely
4892cad65a5SGreg Clayton         // replace our previous frames.
4902cad65a5SGreg Clayton         prev_sp.reset (curr_ap.release());
4912cad65a5SGreg Clayton         return;
4922cad65a5SGreg Clayton     }
4932cad65a5SGreg Clayton 
4942cad65a5SGreg Clayton     const uint32_t num_curr_frames = curr_ap->GetNumFrames (false);
4952cad65a5SGreg Clayton 
4962cad65a5SGreg Clayton     if (num_curr_frames > 1)
4972cad65a5SGreg Clayton     {
4982cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
4992cad65a5SGreg Clayton         s.PutCString("We have more than one current frame, so use current frames...\n");
5002cad65a5SGreg Clayton #endif
5012cad65a5SGreg Clayton         // We have more than one current frames it means we have all the frames
5022cad65a5SGreg Clayton         // and can safely replace our previous frames.
5032cad65a5SGreg Clayton         prev_sp.reset (curr_ap.release());
5042cad65a5SGreg Clayton 
5052cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
5062cad65a5SGreg Clayton         s.PutCString("\nMerged:\n");
5072cad65a5SGreg Clayton         prev_sp->Dump (&s);
5082cad65a5SGreg Clayton #endif
5092cad65a5SGreg Clayton         return;
5102cad65a5SGreg Clayton     }
5112cad65a5SGreg Clayton 
5122cad65a5SGreg Clayton     StackFrameSP prev_frame_zero_sp(prev_sp->GetFrameAtIndex (0));
5132cad65a5SGreg Clayton     StackFrameSP curr_frame_zero_sp(curr_ap->GetFrameAtIndex (0));
5142cad65a5SGreg Clayton     StackID curr_stack_id (curr_frame_zero_sp->GetStackID());
5152cad65a5SGreg Clayton     StackID prev_stack_id (prev_frame_zero_sp->GetStackID());
5162cad65a5SGreg Clayton 
5172cad65a5SGreg Clayton     //const uint32_t num_prev_frames = prev_sp->GetNumFrames (false);
5182cad65a5SGreg Clayton 
5192cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
5202cad65a5SGreg Clayton     s.Printf("\n%u previous frames with one current frame\n", num_prev_frames);
5212cad65a5SGreg Clayton #endif
5222cad65a5SGreg Clayton 
5232cad65a5SGreg Clayton     // We have only a single current frame
5242cad65a5SGreg Clayton     // Our previous stack frames only had a single frame as well...
5252cad65a5SGreg Clayton     if (curr_stack_id == prev_stack_id)
5262cad65a5SGreg Clayton     {
5272cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
5282cad65a5SGreg Clayton         s.Printf("\nPrevious frame #0 is same as current frame #0, merge the cached data\n");
5292cad65a5SGreg Clayton #endif
5302cad65a5SGreg Clayton 
5312cad65a5SGreg Clayton         curr_frame_zero_sp->UpdateCurrentFrameFromPreviousFrame (*prev_frame_zero_sp);
5322cad65a5SGreg Clayton //        prev_frame_zero_sp->UpdatePreviousFrameFromCurrentFrame (*curr_frame_zero_sp);
5332cad65a5SGreg Clayton //        prev_sp->SetFrameAtIndex (0, prev_frame_zero_sp);
5342cad65a5SGreg Clayton     }
5352cad65a5SGreg Clayton     else if (curr_stack_id < prev_stack_id)
5362cad65a5SGreg Clayton     {
5372cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
5382cad65a5SGreg 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");
5392cad65a5SGreg Clayton #endif
5402cad65a5SGreg Clayton         prev_sp->m_frames.insert (prev_sp->m_frames.begin(), curr_frame_zero_sp);
5412cad65a5SGreg Clayton     }
5422cad65a5SGreg Clayton 
5432cad65a5SGreg Clayton     curr_ap.release();
5442cad65a5SGreg Clayton 
5452cad65a5SGreg Clayton #if defined (DEBUG_STACK_FRAMES)
5462cad65a5SGreg Clayton     s.PutCString("\nMerged:\n");
5472cad65a5SGreg Clayton     prev_sp->Dump (&s);
5482cad65a5SGreg Clayton #endif
5492cad65a5SGreg Clayton 
5502cad65a5SGreg Clayton 
5512cad65a5SGreg Clayton }
552e4284b71SJim Ingham 
553e4284b71SJim Ingham lldb::StackFrameSP
554e4284b71SJim Ingham StackFrameList::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
555e4284b71SJim Ingham {
556e4284b71SJim Ingham     const_iterator pos;
557e4284b71SJim Ingham     const_iterator begin = m_frames.begin();
558e4284b71SJim Ingham     const_iterator end = m_frames.end();
559e4284b71SJim Ingham     lldb::StackFrameSP ret_sp;
560e4284b71SJim Ingham 
561e4284b71SJim Ingham     for (pos = begin; pos != end; ++pos)
562e4284b71SJim Ingham     {
563e4284b71SJim Ingham         if (pos->get() == stack_frame_ptr)
564e4284b71SJim Ingham         {
565e4284b71SJim Ingham             ret_sp = (*pos);
566e4284b71SJim Ingham             break;
567e4284b71SJim Ingham         }
568e4284b71SJim Ingham     }
569e4284b71SJim Ingham     return ret_sp;
570e4284b71SJim Ingham }
571e4284b71SJim Ingham 
572*7260f620SGreg Clayton size_t
573*7260f620SGreg Clayton StackFrameList::GetStatus (Stream& strm,
574*7260f620SGreg Clayton                            uint32_t first_frame,
575*7260f620SGreg Clayton                            uint32_t num_frames,
576*7260f620SGreg Clayton                            bool show_frame_info,
577*7260f620SGreg Clayton                            uint32_t num_frames_with_source,
578*7260f620SGreg Clayton                            uint32_t source_lines_before,
579*7260f620SGreg Clayton                            uint32_t source_lines_after)
580*7260f620SGreg Clayton {
581*7260f620SGreg Clayton     size_t num_frames_displayed = 0;
582*7260f620SGreg Clayton 
583*7260f620SGreg Clayton     if (num_frames == 0)
584*7260f620SGreg Clayton         return 0;
585*7260f620SGreg Clayton 
586*7260f620SGreg Clayton     StackFrameSP frame_sp;
587*7260f620SGreg Clayton     uint32_t frame_idx = 0;
588*7260f620SGreg Clayton     uint32_t last_frame;
589*7260f620SGreg Clayton 
590*7260f620SGreg Clayton     // Don't let the last frame wrap around...
591*7260f620SGreg Clayton     if (num_frames == UINT32_MAX)
592*7260f620SGreg Clayton         last_frame = UINT32_MAX;
593*7260f620SGreg Clayton     else
594*7260f620SGreg Clayton         last_frame = first_frame + num_frames;
595*7260f620SGreg Clayton 
596*7260f620SGreg Clayton     for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx)
597*7260f620SGreg Clayton     {
598*7260f620SGreg Clayton         frame_sp = GetFrameAtIndex(frame_idx);
599*7260f620SGreg Clayton         if (frame_sp.get() == NULL)
600*7260f620SGreg Clayton             break;
601*7260f620SGreg Clayton 
602*7260f620SGreg Clayton         if (!frame_sp->GetStatus (strm,
603*7260f620SGreg Clayton                                   show_frame_info,
604*7260f620SGreg Clayton                                   num_frames_with_source > first_frame - frame_idx,
605*7260f620SGreg Clayton                                   source_lines_before,
606*7260f620SGreg Clayton                                   source_lines_after))
607*7260f620SGreg Clayton             break;
608*7260f620SGreg Clayton         ++num_frames_displayed;
609*7260f620SGreg Clayton     }
610*7260f620SGreg Clayton 
611*7260f620SGreg Clayton     strm.IndentLess();
612*7260f620SGreg Clayton     return num_frames_displayed;
613*7260f620SGreg Clayton }
614*7260f620SGreg Clayton 
615