Home | History | Annotate | Download | only in Target
      1 //===-- StackFrameList.cpp --------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "lldb/Target/StackFrameList.h"
     11 
     12 // C Includes
     13 // C++ Includes
     14 // Other libraries and framework includes
     15 // Project includes
     16 #include "lldb/Breakpoint/BreakpointLocation.h"
     17 #include "lldb/Breakpoint/Breakpoint.h"
     18 #include "lldb/Core/Log.h"
     19 #include "lldb/Core/StreamFile.h"
     20 #include "lldb/Core/SourceManager.h"
     21 #include "lldb/Symbol/Block.h"
     22 #include "lldb/Symbol/Function.h"
     23 #include "lldb/Symbol/Symbol.h"
     24 #include "lldb/Target/Process.h"
     25 #include "lldb/Target/RegisterContext.h"
     26 #include "lldb/Target/StackFrame.h"
     27 #include "lldb/Target/StopInfo.h"
     28 #include "lldb/Target/Target.h"
     29 #include "lldb/Target/Thread.h"
     30 #include "lldb/Target/Unwind.h"
     31 
     32 //#define DEBUG_STACK_FRAMES 1
     33 
     34 using namespace lldb;
     35 using namespace lldb_private;
     36 
     37 //----------------------------------------------------------------------
     38 // StackFrameList constructor
     39 //----------------------------------------------------------------------
     40 StackFrameList::StackFrameList
     41 (
     42     Thread &thread,
     43     const lldb::StackFrameListSP &prev_frames_sp,
     44     bool show_inline_frames
     45 ) :
     46     m_thread (thread),
     47     m_prev_frames_sp (prev_frames_sp),
     48     m_mutex (Mutex::eMutexTypeRecursive),
     49     m_frames (),
     50     m_selected_frame_idx (0),
     51     m_concrete_frames_fetched (0),
     52     m_current_inlined_depth (UINT32_MAX),
     53     m_current_inlined_pc (LLDB_INVALID_ADDRESS),
     54     m_show_inlined_frames (show_inline_frames)
     55 {
     56     if (prev_frames_sp)
     57     {
     58         m_current_inlined_depth = prev_frames_sp->m_current_inlined_depth;
     59         m_current_inlined_pc =    prev_frames_sp->m_current_inlined_pc;
     60     }
     61 }
     62 
     63 //----------------------------------------------------------------------
     64 // Destructor
     65 //----------------------------------------------------------------------
     66 StackFrameList::~StackFrameList()
     67 {
     68     // Call clear since this takes a lock and clears the stack frame list
     69     // in case another thread is currently using this stack frame list
     70     Clear();
     71 }
     72 
     73 void
     74 StackFrameList::CalculateCurrentInlinedDepth()
     75 {
     76     uint32_t cur_inlined_depth = GetCurrentInlinedDepth();
     77     if (cur_inlined_depth == UINT32_MAX)
     78     {
     79         ResetCurrentInlinedDepth();
     80     }
     81 }
     82 
     83 uint32_t
     84 StackFrameList::GetCurrentInlinedDepth ()
     85 {
     86     if (m_show_inlined_frames && m_current_inlined_pc != LLDB_INVALID_ADDRESS)
     87     {
     88         lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC();
     89         if (cur_pc != m_current_inlined_pc)
     90         {
     91             m_current_inlined_pc = LLDB_INVALID_ADDRESS;
     92             m_current_inlined_depth = UINT32_MAX;
     93             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
     94             if (log && log->GetVerbose())
     95                 log->Printf ("GetCurrentInlinedDepth: invalidating current inlined depth.\n");
     96         }
     97         return m_current_inlined_depth;
     98     }
     99     else
    100     {
    101         return UINT32_MAX;
    102     }
    103 }
    104 
    105 void
    106 StackFrameList::ResetCurrentInlinedDepth ()
    107 {
    108     if (m_show_inlined_frames)
    109     {
    110         GetFramesUpTo(0);
    111         if (!m_frames[0]->IsInlined())
    112         {
    113             m_current_inlined_depth = UINT32_MAX;
    114             m_current_inlined_pc = LLDB_INVALID_ADDRESS;
    115             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    116             if (log && log->GetVerbose())
    117                 log->Printf ("ResetCurrentInlinedDepth: Invalidating current inlined depth.\n");
    118         }
    119         else
    120         {
    121             // We only need to do something special about inlined blocks when we
    122             // are at the beginning of an inlined function:
    123             // FIXME: We probably also have to do something special if the PC is at the END
    124             // of an inlined function, which coincides with the end of either its containing
    125             // function or another inlined function.
    126 
    127             lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
    128             Block *block_ptr = m_frames[0]->GetFrameBlock();
    129             if (block_ptr)
    130             {
    131                 Address pc_as_address;
    132                 pc_as_address.SetLoadAddress(curr_pc, &(m_thread.GetProcess()->GetTarget()));
    133                 AddressRange containing_range;
    134                 if (block_ptr->GetRangeContainingAddress(pc_as_address, containing_range))
    135                 {
    136                     if (pc_as_address == containing_range.GetBaseAddress())
    137                     {
    138                         // If we got here because of a breakpoint hit, then set the inlined depth depending on where
    139                         // the breakpoint was set.
    140                         // If we got here because of a crash, then set the inlined depth to the deepest most block.
    141                         // Otherwise, we stopped here naturally as the result of a step, so set ourselves in the
    142                         // containing frame of the whole set of nested inlines, so the user can then "virtually"
    143                         // step into the frames one by one, or next over the whole mess.
    144                         // Note: We don't have to handle being somewhere in the middle of the stack here, since
    145                         // ResetCurrentInlinedDepth doesn't get called if there is a valid inlined depth set.
    146                         StopInfoSP stop_info_sp = m_thread.GetStopInfo();
    147                         if (stop_info_sp)
    148                         {
    149                             switch (stop_info_sp->GetStopReason())
    150                             {
    151                             case eStopReasonWatchpoint:
    152                             case eStopReasonException:
    153                             case eStopReasonExec:
    154                             case eStopReasonSignal:
    155                                 // In all these cases we want to stop in the deepest most frame.
    156                                 m_current_inlined_pc = curr_pc;
    157                                 m_current_inlined_depth = 0;
    158                                 break;
    159                             case eStopReasonBreakpoint:
    160                                 {
    161                                     // FIXME: Figure out what this break point is doing, and set the inline depth
    162                                     // appropriately.  Be careful to take into account breakpoints that implement
    163                                     // step over prologue, since that should do the default calculation.
    164                                     // For now, if the breakpoints corresponding to this hit are all internal,
    165                                     // I set the stop location to the top of the inlined stack, since that will make
    166                                     // things like stepping over prologues work right.  But if there are any non-internal
    167                                     // breakpoints I do to the bottom of the stack, since that was the old behavior.
    168                                     uint32_t bp_site_id = stop_info_sp->GetValue();
    169                                     BreakpointSiteSP bp_site_sp(m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id));
    170                                     bool all_internal = true;
    171                                     if (bp_site_sp)
    172                                     {
    173                                         uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
    174                                         for (uint32_t i = 0; i < num_owners; i++)
    175                                         {
    176                                             Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
    177                                             if (!bp_ref.IsInternal())
    178                                             {
    179                                                 all_internal = false;
    180                                             }
    181                                         }
    182                                     }
    183                                     if (!all_internal)
    184                                     {
    185                                         m_current_inlined_pc = curr_pc;
    186                                         m_current_inlined_depth = 0;
    187                                         break;
    188                                     }
    189                                 }
    190                             default:
    191                                 {
    192                                     // Otherwise, we should set ourselves at the container of the inlining, so that the
    193                                     // user can descend into them.
    194                                     // So first we check whether we have more than one inlined block sharing this PC:
    195                                     int num_inlined_functions = 0;
    196 
    197                                     for  (Block *container_ptr = block_ptr->GetInlinedParent();
    198                                               container_ptr != NULL;
    199                                               container_ptr = container_ptr->GetInlinedParent())
    200                                     {
    201                                         if (!container_ptr->GetRangeContainingAddress(pc_as_address, containing_range))
    202                                             break;
    203                                         if (pc_as_address != containing_range.GetBaseAddress())
    204                                             break;
    205 
    206                                         num_inlined_functions++;
    207                                     }
    208                                     m_current_inlined_pc = curr_pc;
    209                                     m_current_inlined_depth = num_inlined_functions + 1;
    210                                     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    211                                     if (log && log->GetVerbose())
    212                                         log->Printf ("ResetCurrentInlinedDepth: setting inlined depth: %d 0x%" PRIx64 ".\n", m_current_inlined_depth, curr_pc);
    213 
    214                                 }
    215                                 break;
    216                             }
    217                         }
    218                     }
    219                 }
    220             }
    221         }
    222     }
    223 }
    224 
    225 bool
    226 StackFrameList::DecrementCurrentInlinedDepth ()
    227 {
    228     if (m_show_inlined_frames)
    229     {
    230         uint32_t current_inlined_depth = GetCurrentInlinedDepth();
    231         if (current_inlined_depth != UINT32_MAX)
    232         {
    233             if (current_inlined_depth > 0)
    234             {
    235                 m_current_inlined_depth--;
    236                 return true;
    237             }
    238         }
    239     }
    240     return false;
    241 }
    242 
    243 void
    244 StackFrameList::SetCurrentInlinedDepth (uint32_t new_depth)
    245 {
    246     m_current_inlined_depth = new_depth;
    247     if (new_depth == UINT32_MAX)
    248         m_current_inlined_pc = LLDB_INVALID_ADDRESS;
    249     else
    250         m_current_inlined_pc = m_thread.GetRegisterContext()->GetPC();
    251 }
    252 
    253 void
    254 StackFrameList::GetFramesUpTo(uint32_t end_idx)
    255 {
    256     // this makes sure we do not fetch frames for an invalid thread
    257     if (m_thread.IsValid() == false)
    258         return;
    259 
    260     // We've already gotten more frames than asked for, or we've already finished unwinding, return.
    261     if (m_frames.size() > end_idx || GetAllFramesFetched())
    262         return;
    263 
    264     Unwind *unwinder = m_thread.GetUnwinder ();
    265 
    266     if (m_show_inlined_frames)
    267     {
    268 #if defined (DEBUG_STACK_FRAMES)
    269         StreamFile s(stdout, false);
    270 #endif
    271         // If we are hiding some frames from the outside world, we need to add those onto the total count of
    272         // frames to fetch.  However, we don't need ot do that if end_idx is 0 since in that case we always
    273         // get the first concrete frame and all the inlined frames below it...  And of course, if end_idx is
    274         // UINT32_MAX that means get all, so just do that...
    275 
    276         uint32_t inlined_depth = 0;
    277         if (end_idx > 0 && end_idx != UINT32_MAX)
    278         {
    279             inlined_depth = GetCurrentInlinedDepth();
    280             if (inlined_depth != UINT32_MAX)
    281             {
    282                 if (end_idx > 0)
    283                     end_idx += inlined_depth;
    284             }
    285         }
    286 
    287         StackFrameSP unwind_frame_sp;
    288         do
    289         {
    290             uint32_t idx = m_concrete_frames_fetched++;
    291             lldb::addr_t pc;
    292             lldb::addr_t cfa;
    293             if (idx == 0)
    294             {
    295                 // We might have already created frame zero, only create it
    296                 // if we need to
    297                 if (m_frames.empty())
    298                 {
    299                     RegisterContextSP reg_ctx_sp (m_thread.GetRegisterContext());
    300 
    301                     if (reg_ctx_sp)
    302                     {
    303 
    304                         const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
    305                         // There shouldn't be any way not to get the frame info for frame 0.
    306                         // But if the unwinder can't make one, lets make one by hand with the
    307                         // SP as the CFA and see if that gets any further.
    308                         if (!success)
    309                         {
    310                             cfa = reg_ctx_sp->GetSP();
    311                             pc = reg_ctx_sp->GetPC();
    312                         }
    313 
    314                         unwind_frame_sp.reset (new StackFrame (m_thread.shared_from_this(),
    315                                                                m_frames.size(),
    316                                                                idx,
    317                                                                reg_ctx_sp,
    318                                                                cfa,
    319                                                                pc,
    320                                                                NULL));
    321                         m_frames.push_back (unwind_frame_sp);
    322                     }
    323                 }
    324                 else
    325                 {
    326                     unwind_frame_sp = m_frames.front();
    327                     cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
    328                 }
    329             }
    330             else
    331             {
    332                 const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
    333                 if (!success)
    334                 {
    335                     // We've gotten to the end of the stack.
    336                     SetAllFramesFetched();
    337                     break;
    338                 }
    339                 unwind_frame_sp.reset (new StackFrame (m_thread.shared_from_this(), m_frames.size(), idx, cfa, pc, NULL));
    340                 m_frames.push_back (unwind_frame_sp);
    341             }
    342 
    343             SymbolContext unwind_sc = unwind_frame_sp->GetSymbolContext (eSymbolContextBlock | eSymbolContextFunction);
    344             Block *unwind_block = unwind_sc.block;
    345             if (unwind_block)
    346             {
    347                 Address curr_frame_address (unwind_frame_sp->GetFrameCodeAddress());
    348                 // Be sure to adjust the frame address to match the address
    349                 // that was used to lookup the symbol context above. If we are
    350                 // in the first concrete frame, then we lookup using the current
    351                 // address, else we decrement the address by one to get the correct
    352                 // location.
    353                 if (idx > 0)
    354                     curr_frame_address.Slide(-1);
    355 
    356                 SymbolContext next_frame_sc;
    357                 Address next_frame_address;
    358 
    359                 while (unwind_sc.GetParentOfInlinedScope(curr_frame_address, next_frame_sc, next_frame_address))
    360                 {
    361                         StackFrameSP frame_sp(new StackFrame (m_thread.shared_from_this(),
    362                                                               m_frames.size(),
    363                                                               idx,
    364                                                               unwind_frame_sp->GetRegisterContextSP (),
    365                                                               cfa,
    366                                                               next_frame_address,
    367                                                               &next_frame_sc));
    368 
    369                         m_frames.push_back (frame_sp);
    370                         unwind_sc = next_frame_sc;
    371                         curr_frame_address = next_frame_address;
    372                 }
    373             }
    374         } while (m_frames.size() - 1 < end_idx);
    375 
    376         // Don't try to merge till you've calculated all the frames in this stack.
    377         if (GetAllFramesFetched() && m_prev_frames_sp)
    378         {
    379             StackFrameList *prev_frames = m_prev_frames_sp.get();
    380             StackFrameList *curr_frames = this;
    381 
    382             //curr_frames->m_current_inlined_depth = prev_frames->m_current_inlined_depth;
    383             //curr_frames->m_current_inlined_pc = prev_frames->m_current_inlined_pc;
    384             //printf ("GetFramesUpTo: Copying current inlined depth: %d 0x%" PRIx64 ".\n", curr_frames->m_current_inlined_depth, curr_frames->m_current_inlined_pc);
    385 
    386 #if defined (DEBUG_STACK_FRAMES)
    387             s.PutCString("\nprev_frames:\n");
    388             prev_frames->Dump (&s);
    389             s.PutCString("\ncurr_frames:\n");
    390             curr_frames->Dump (&s);
    391             s.EOL();
    392 #endif
    393             size_t curr_frame_num, prev_frame_num;
    394 
    395             for (curr_frame_num = curr_frames->m_frames.size(), prev_frame_num = prev_frames->m_frames.size();
    396                  curr_frame_num > 0 && prev_frame_num > 0;
    397                  --curr_frame_num, --prev_frame_num)
    398             {
    399                 const size_t curr_frame_idx = curr_frame_num-1;
    400                 const size_t prev_frame_idx = prev_frame_num-1;
    401                 StackFrameSP curr_frame_sp (curr_frames->m_frames[curr_frame_idx]);
    402                 StackFrameSP prev_frame_sp (prev_frames->m_frames[prev_frame_idx]);
    403 
    404 #if defined (DEBUG_STACK_FRAMES)
    405                 s.Printf("\n\nCurr frame #%u ", curr_frame_idx);
    406                 if (curr_frame_sp)
    407                     curr_frame_sp->Dump (&s, true, false);
    408                 else
    409                     s.PutCString("NULL");
    410                 s.Printf("\nPrev frame #%u ", prev_frame_idx);
    411                 if (prev_frame_sp)
    412                     prev_frame_sp->Dump (&s, true, false);
    413                 else
    414                     s.PutCString("NULL");
    415 #endif
    416 
    417                 StackFrame *curr_frame = curr_frame_sp.get();
    418                 StackFrame *prev_frame = prev_frame_sp.get();
    419 
    420                 if (curr_frame == NULL || prev_frame == NULL)
    421                     break;
    422 
    423                 // Check the stack ID to make sure they are equal
    424                 if (curr_frame->GetStackID() != prev_frame->GetStackID())
    425                     break;
    426 
    427                 prev_frame->UpdatePreviousFrameFromCurrentFrame (*curr_frame);
    428                 // Now copy the fixed up previous frame into the current frames
    429                 // so the pointer doesn't change
    430                 m_frames[curr_frame_idx] = prev_frame_sp;
    431                 //curr_frame->UpdateCurrentFrameFromPreviousFrame (*prev_frame);
    432 
    433 #if defined (DEBUG_STACK_FRAMES)
    434                 s.Printf("\n    Copying previous frame to current frame");
    435 #endif
    436             }
    437             // We are done with the old stack frame list, we can release it now
    438             m_prev_frames_sp.reset();
    439         }
    440 
    441 #if defined (DEBUG_STACK_FRAMES)
    442             s.PutCString("\n\nNew frames:\n");
    443             Dump (&s);
    444             s.EOL();
    445 #endif
    446     }
    447     else
    448     {
    449         if (end_idx < m_concrete_frames_fetched)
    450             return;
    451 
    452         uint32_t num_frames = unwinder->GetFramesUpTo(end_idx);
    453         if (num_frames <= end_idx + 1)
    454         {
    455             //Done unwinding.
    456             m_concrete_frames_fetched = UINT32_MAX;
    457         }
    458         m_frames.resize(num_frames);
    459     }
    460 }
    461 
    462 uint32_t
    463 StackFrameList::GetNumFrames (bool can_create)
    464 {
    465     Mutex::Locker locker (m_mutex);
    466 
    467     if (can_create)
    468         GetFramesUpTo (UINT32_MAX);
    469 
    470     uint32_t inlined_depth = GetCurrentInlinedDepth();
    471     if (inlined_depth == UINT32_MAX)
    472         return m_frames.size();
    473     else
    474         return m_frames.size() - inlined_depth;
    475 }
    476 
    477 void
    478 StackFrameList::Dump (Stream *s)
    479 {
    480     if (s == NULL)
    481         return;
    482     Mutex::Locker locker (m_mutex);
    483 
    484     const_iterator pos, begin = m_frames.begin(), end = m_frames.end();
    485     for (pos = begin; pos != end; ++pos)
    486     {
    487         StackFrame *frame = (*pos).get();
    488         s->Printf("%p: ", frame);
    489         if (frame)
    490         {
    491             frame->GetStackID().Dump (s);
    492             frame->DumpUsingSettingsFormat (s);
    493         }
    494         else
    495             s->Printf("frame #%u", (uint32_t)std::distance (begin, pos));
    496         s->EOL();
    497     }
    498     s->EOL();
    499 }
    500 
    501 StackFrameSP
    502 StackFrameList::GetFrameAtIndex (uint32_t idx)
    503 {
    504     StackFrameSP frame_sp;
    505     Mutex::Locker locker (m_mutex);
    506     uint32_t original_idx = idx;
    507 
    508     uint32_t inlined_depth = GetCurrentInlinedDepth();
    509     if (inlined_depth != UINT32_MAX)
    510         idx += inlined_depth;
    511 
    512     if (idx < m_frames.size())
    513         frame_sp = m_frames[idx];
    514 
    515     if (frame_sp)
    516         return frame_sp;
    517 
    518     // GetFramesUpTo will fill m_frames with as many frames as you asked for,
    519     // if there are that many.  If there weren't then you asked for too many
    520     // frames.
    521     GetFramesUpTo (idx);
    522     if (idx < m_frames.size())
    523     {
    524         if (m_show_inlined_frames)
    525         {
    526             // When inline frames are enabled we actually create all the frames in GetFramesUpTo.
    527             frame_sp = m_frames[idx];
    528         }
    529         else
    530         {
    531             Unwind *unwinder = m_thread.GetUnwinder ();
    532             if (unwinder)
    533             {
    534                 addr_t pc, cfa;
    535                 if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
    536                 {
    537                     frame_sp.reset (new StackFrame (m_thread.shared_from_this(), idx, idx, cfa, pc, NULL));
    538 
    539                     Function *function = frame_sp->GetSymbolContext (eSymbolContextFunction).function;
    540                     if (function)
    541                     {
    542                         // When we aren't showing inline functions we always use
    543                         // the top most function block as the scope.
    544                         frame_sp->SetSymbolContextScope (&function->GetBlock(false));
    545                     }
    546                     else
    547                     {
    548                         // Set the symbol scope from the symbol regardless if it is NULL or valid.
    549                         frame_sp->SetSymbolContextScope (frame_sp->GetSymbolContext (eSymbolContextSymbol).symbol);
    550                     }
    551                     SetFrameAtIndex(idx, frame_sp);
    552                 }
    553             }
    554         }
    555     }
    556     else if (original_idx == 0)
    557     {
    558         // There should ALWAYS be a frame at index 0.  If something went wrong with the CurrentInlinedDepth such that
    559         // there weren't as many frames as we thought taking that into account, then reset the current inlined depth
    560         // and return the real zeroth frame.
    561         if (m_frames.size() > 0)
    562         {
    563             ResetCurrentInlinedDepth();
    564             frame_sp = m_frames[original_idx];
    565         }
    566         else
    567         {
    568             // Why do we have a thread with zero frames, that should not ever happen...
    569             if (m_thread.IsValid())
    570                 assert ("A valid thread has no frames.");
    571 
    572         }
    573     }
    574 
    575     return frame_sp;
    576 }
    577 
    578 StackFrameSP
    579 StackFrameList::GetFrameWithConcreteFrameIndex (uint32_t unwind_idx)
    580 {
    581     // First try assuming the unwind index is the same as the frame index. The
    582     // unwind index is always greater than or equal to the frame index, so it
    583     // is a good place to start. If we have inlined frames we might have 5
    584     // concrete frames (frame unwind indexes go from 0-4), but we might have 15
    585     // frames after we make all the inlined frames. Most of the time the unwind
    586     // frame index (or the concrete frame index) is the same as the frame index.
    587     uint32_t frame_idx = unwind_idx;
    588     StackFrameSP frame_sp (GetFrameAtIndex (frame_idx));
    589     while (frame_sp)
    590     {
    591         if (frame_sp->GetFrameIndex() == unwind_idx)
    592             break;
    593         frame_sp = GetFrameAtIndex (++frame_idx);
    594     }
    595     return frame_sp;
    596 }
    597 
    598 static bool
    599 CompareStackID (const StackFrameSP &stack_sp, const StackID &stack_id)
    600 {
    601     return stack_sp->GetStackID() < stack_id;
    602 }
    603 
    604 StackFrameSP
    605 StackFrameList::GetFrameWithStackID (const StackID &stack_id)
    606 {
    607     StackFrameSP frame_sp;
    608 
    609     if (stack_id.IsValid())
    610     {
    611         Mutex::Locker locker (m_mutex);
    612         uint32_t frame_idx = 0;
    613         // Do a binary search in case the stack frame is already in our cache
    614         collection::const_iterator begin = m_frames.begin();
    615         collection::const_iterator end = m_frames.end();
    616         if (begin != end)
    617         {
    618             collection::const_iterator pos = std::lower_bound (begin, end, stack_id, CompareStackID);
    619             if (pos != end && (*pos)->GetStackID() == stack_id)
    620                 return *pos;
    621 
    622             if (m_frames.back()->GetStackID() < stack_id)
    623                 frame_idx = m_frames.size();
    624         }
    625         do
    626         {
    627             frame_sp = GetFrameAtIndex (frame_idx);
    628             if (frame_sp && frame_sp->GetStackID() == stack_id)
    629                 break;
    630             frame_idx++;
    631         }
    632         while (frame_sp);
    633     }
    634     return frame_sp;
    635 }
    636 
    637 bool
    638 StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
    639 {
    640     if (idx >= m_frames.size())
    641         m_frames.resize(idx + 1);
    642     // Make sure allocation succeeded by checking bounds again
    643     if (idx < m_frames.size())
    644     {
    645         m_frames[idx] = frame_sp;
    646         return true;
    647     }
    648     return false;   // resize failed, out of memory?
    649 }
    650 
    651 uint32_t
    652 StackFrameList::GetSelectedFrameIndex () const
    653 {
    654     Mutex::Locker locker (m_mutex);
    655     return m_selected_frame_idx;
    656 }
    657 
    658 
    659 uint32_t
    660 StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame)
    661 {
    662     Mutex::Locker locker (m_mutex);
    663     const_iterator pos;
    664     const_iterator begin = m_frames.begin();
    665     const_iterator end = m_frames.end();
    666     m_selected_frame_idx = 0;
    667     for (pos = begin; pos != end; ++pos)
    668     {
    669         if (pos->get() == frame)
    670         {
    671             m_selected_frame_idx = std::distance (begin, pos);
    672             uint32_t inlined_depth = GetCurrentInlinedDepth();
    673             if (inlined_depth != UINT32_MAX)
    674                 m_selected_frame_idx -= inlined_depth;
    675             break;
    676         }
    677     }
    678     SetDefaultFileAndLineToSelectedFrame();
    679     return m_selected_frame_idx;
    680 }
    681 
    682 // Mark a stack frame as the current frame using the frame index
    683 bool
    684 StackFrameList::SetSelectedFrameByIndex (uint32_t idx)
    685 {
    686     Mutex::Locker locker (m_mutex);
    687     StackFrameSP frame_sp (GetFrameAtIndex (idx));
    688     if (frame_sp)
    689     {
    690         SetSelectedFrame(frame_sp.get());
    691         return true;
    692     }
    693     else
    694         return false;
    695 }
    696 
    697 void
    698 StackFrameList::SetDefaultFileAndLineToSelectedFrame()
    699 {
    700     if (m_thread.GetID() == m_thread.GetProcess()->GetThreadList().GetSelectedThread()->GetID())
    701     {
    702         StackFrameSP frame_sp (GetFrameAtIndex (GetSelectedFrameIndex()));
    703         if (frame_sp)
    704         {
    705             SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextLineEntry);
    706             if (sc.line_entry.file)
    707                 m_thread.CalculateTarget()->GetSourceManager().SetDefaultFileAndLine (sc.line_entry.file,
    708                                                                                             sc.line_entry.line);
    709         }
    710     }
    711 }
    712 
    713 // The thread has been run, reset the number stack frames to zero so we can
    714 // determine how many frames we have lazily.
    715 void
    716 StackFrameList::Clear ()
    717 {
    718     Mutex::Locker locker (m_mutex);
    719     m_frames.clear();
    720     m_concrete_frames_fetched = 0;
    721 }
    722 
    723 void
    724 StackFrameList::InvalidateFrames (uint32_t start_idx)
    725 {
    726     Mutex::Locker locker (m_mutex);
    727     if (m_show_inlined_frames)
    728     {
    729         Clear();
    730     }
    731     else
    732     {
    733         const size_t num_frames = m_frames.size();
    734         while (start_idx < num_frames)
    735         {
    736             m_frames[start_idx].reset();
    737             ++start_idx;
    738         }
    739     }
    740 }
    741 
    742 void
    743 StackFrameList::Merge (std::unique_ptr<StackFrameList>& curr_ap, lldb::StackFrameListSP& prev_sp)
    744 {
    745     Mutex::Locker curr_locker (curr_ap.get() ? &curr_ap->m_mutex : NULL);
    746     Mutex::Locker prev_locker (prev_sp.get() ? &prev_sp->m_mutex : NULL);
    747 
    748 #if defined (DEBUG_STACK_FRAMES)
    749     StreamFile s(stdout, false);
    750     s.PutCString("\n\nStackFrameList::Merge():\nPrev:\n");
    751     if (prev_sp.get())
    752         prev_sp->Dump (&s);
    753     else
    754         s.PutCString ("NULL");
    755     s.PutCString("\nCurr:\n");
    756     if (curr_ap.get())
    757         curr_ap->Dump (&s);
    758     else
    759         s.PutCString ("NULL");
    760     s.EOL();
    761 #endif
    762 
    763     if (curr_ap.get() == NULL || curr_ap->GetNumFrames (false) == 0)
    764     {
    765 #if defined (DEBUG_STACK_FRAMES)
    766         s.PutCString("No current frames, leave previous frames alone...\n");
    767 #endif
    768         curr_ap.release();
    769         return;
    770     }
    771 
    772     if (prev_sp.get() == NULL || prev_sp->GetNumFrames (false) == 0)
    773     {
    774 #if defined (DEBUG_STACK_FRAMES)
    775         s.PutCString("No previous frames, so use current frames...\n");
    776 #endif
    777         // We either don't have any previous frames, or since we have more than
    778         // one current frames it means we have all the frames and can safely
    779         // replace our previous frames.
    780         prev_sp.reset (curr_ap.release());
    781         return;
    782     }
    783 
    784     const uint32_t num_curr_frames = curr_ap->GetNumFrames (false);
    785 
    786     if (num_curr_frames > 1)
    787     {
    788 #if defined (DEBUG_STACK_FRAMES)
    789         s.PutCString("We have more than one current frame, so use current frames...\n");
    790 #endif
    791         // We have more than one current frames it means we have all the frames
    792         // and can safely replace our previous frames.
    793         prev_sp.reset (curr_ap.release());
    794 
    795 #if defined (DEBUG_STACK_FRAMES)
    796         s.PutCString("\nMerged:\n");
    797         prev_sp->Dump (&s);
    798 #endif
    799         return;
    800     }
    801 
    802     StackFrameSP prev_frame_zero_sp(prev_sp->GetFrameAtIndex (0));
    803     StackFrameSP curr_frame_zero_sp(curr_ap->GetFrameAtIndex (0));
    804     StackID curr_stack_id (curr_frame_zero_sp->GetStackID());
    805     StackID prev_stack_id (prev_frame_zero_sp->GetStackID());
    806 
    807 #if defined (DEBUG_STACK_FRAMES)
    808     const uint32_t num_prev_frames = prev_sp->GetNumFrames (false);
    809     s.Printf("\n%u previous frames with one current frame\n", num_prev_frames);
    810 #endif
    811 
    812     // We have only a single current frame
    813     // Our previous stack frames only had a single frame as well...
    814     if (curr_stack_id == prev_stack_id)
    815     {
    816 #if defined (DEBUG_STACK_FRAMES)
    817         s.Printf("\nPrevious frame #0 is same as current frame #0, merge the cached data\n");
    818 #endif
    819 
    820         curr_frame_zero_sp->UpdateCurrentFrameFromPreviousFrame (*prev_frame_zero_sp);
    821 //        prev_frame_zero_sp->UpdatePreviousFrameFromCurrentFrame (*curr_frame_zero_sp);
    822 //        prev_sp->SetFrameAtIndex (0, prev_frame_zero_sp);
    823     }
    824     else if (curr_stack_id < prev_stack_id)
    825     {
    826 #if defined (DEBUG_STACK_FRAMES)
    827         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");
    828 #endif
    829         prev_sp->m_frames.insert (prev_sp->m_frames.begin(), curr_frame_zero_sp);
    830     }
    831 
    832     curr_ap.release();
    833 
    834 #if defined (DEBUG_STACK_FRAMES)
    835     s.PutCString("\nMerged:\n");
    836     prev_sp->Dump (&s);
    837 #endif
    838 
    839 
    840 }
    841 
    842 lldb::StackFrameSP
    843 StackFrameList::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
    844 {
    845     const_iterator pos;
    846     const_iterator begin = m_frames.begin();
    847     const_iterator end = m_frames.end();
    848     lldb::StackFrameSP ret_sp;
    849 
    850     for (pos = begin; pos != end; ++pos)
    851     {
    852         if (pos->get() == stack_frame_ptr)
    853         {
    854             ret_sp = (*pos);
    855             break;
    856         }
    857     }
    858     return ret_sp;
    859 }
    860 
    861 size_t
    862 StackFrameList::GetStatus (Stream& strm,
    863                            uint32_t first_frame,
    864                            uint32_t num_frames,
    865                            bool show_frame_info,
    866                            uint32_t num_frames_with_source)
    867 {
    868     size_t num_frames_displayed = 0;
    869 
    870     if (num_frames == 0)
    871         return 0;
    872 
    873     StackFrameSP frame_sp;
    874     uint32_t frame_idx = 0;
    875     uint32_t last_frame;
    876 
    877     // Don't let the last frame wrap around...
    878     if (num_frames == UINT32_MAX)
    879         last_frame = UINT32_MAX;
    880     else
    881         last_frame = first_frame + num_frames;
    882 
    883     for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx)
    884     {
    885         frame_sp = GetFrameAtIndex(frame_idx);
    886         if (frame_sp.get() == NULL)
    887             break;
    888 
    889         if (!frame_sp->GetStatus (strm,
    890                                   show_frame_info,
    891                                   num_frames_with_source > (first_frame - frame_idx)))
    892             break;
    893         ++num_frames_displayed;
    894     }
    895 
    896     strm.IndentLess();
    897     return num_frames_displayed;
    898 }
    899 
    900