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 16*5082c5fdSGreg Clayton #include "lldb/Core/StreamFile.h" 1712daf946SGreg Clayton #include "lldb/Symbol/Block.h" 1812daf946SGreg Clayton #include "lldb/Symbol/Function.h" 1912daf946SGreg Clayton #include "lldb/Target/RegisterContext.h" 2030fdc8d8SChris Lattner #include "lldb/Target/StackFrame.h" 2112daf946SGreg Clayton #include "lldb/Target/Thread.h" 2212daf946SGreg Clayton #include "lldb/Target/Unwind.h" 2330fdc8d8SChris Lattner 24*5082c5fdSGreg Clayton //#define DEBUG_STACK_FRAMES 1 25*5082c5fdSGreg Clayton 2630fdc8d8SChris Lattner using namespace lldb; 2730fdc8d8SChris Lattner using namespace lldb_private; 2830fdc8d8SChris Lattner 2930fdc8d8SChris Lattner //---------------------------------------------------------------------- 3030fdc8d8SChris Lattner // StackFrameList constructor 3130fdc8d8SChris Lattner //---------------------------------------------------------------------- 320445d8f4SGreg Clayton StackFrameList::StackFrameList(Thread &thread, StackFrameList *prev_frames, bool show_inline_frames) : 3312daf946SGreg Clayton m_thread (thread), 340445d8f4SGreg Clayton m_prev_frames_ap (prev_frames), 3512daf946SGreg Clayton m_show_inlined_frames (show_inline_frames), 3630fdc8d8SChris Lattner m_mutex (Mutex::eMutexTypeRecursive), 37*5082c5fdSGreg Clayton m_frames (), 382976d00aSJim Ingham m_selected_frame_idx (0) 3930fdc8d8SChris Lattner { 4030fdc8d8SChris Lattner } 4130fdc8d8SChris Lattner 4230fdc8d8SChris Lattner //---------------------------------------------------------------------- 4330fdc8d8SChris Lattner // Destructor 4430fdc8d8SChris Lattner //---------------------------------------------------------------------- 4530fdc8d8SChris Lattner StackFrameList::~StackFrameList() 4630fdc8d8SChris Lattner { 4730fdc8d8SChris Lattner } 4830fdc8d8SChris Lattner 4930fdc8d8SChris Lattner 5030fdc8d8SChris Lattner uint32_t 5112daf946SGreg Clayton StackFrameList::GetNumFrames() 5230fdc8d8SChris Lattner { 5330fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 5412daf946SGreg Clayton 55*5082c5fdSGreg Clayton if (m_frames.size() <= 1) 56*5082c5fdSGreg Clayton { 5712daf946SGreg Clayton if (m_show_inlined_frames) 5812daf946SGreg Clayton { 59*5082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES) 60*5082c5fdSGreg Clayton StreamFile s(stdout); 61*5082c5fdSGreg Clayton #endif 6212daf946SGreg Clayton Unwind *unwinder = m_thread.GetUnwinder (); 63*5082c5fdSGreg Clayton addr_t pc, cfa; 64*5082c5fdSGreg Clayton 6512daf946SGreg Clayton // If we are going to show inlined stack frames as actual frames, 6612daf946SGreg Clayton // we need to calculate all concrete frames first, then iterate 6712daf946SGreg Clayton // through all of them and count up how many inlined functions are 68*5082c5fdSGreg Clayton // in each frame. 69*5082c5fdSGreg Clayton const uint32_t unwind_frame_count = unwinder->GetFrameCount(); 7012daf946SGreg Clayton 71*5082c5fdSGreg Clayton StackFrameSP unwind_frame_sp; 72*5082c5fdSGreg Clayton for (uint32_t idx=0; idx<unwind_frame_count; ++idx) 7312daf946SGreg Clayton { 7412daf946SGreg Clayton if (idx == 0) 7512daf946SGreg Clayton { 76*5082c5fdSGreg Clayton // We might have already created frame zero, only create it 77*5082c5fdSGreg Clayton // if we need to 78*5082c5fdSGreg Clayton if (m_frames.empty()) 79*5082c5fdSGreg Clayton { 8012daf946SGreg Clayton m_thread.GetRegisterContext(); 81*5082c5fdSGreg Clayton unwind_frame_sp.reset (new StackFrame (m_frames.size(), 82*5082c5fdSGreg Clayton idx, 8312daf946SGreg Clayton m_thread, 8412daf946SGreg Clayton m_thread.m_reg_context_sp, 8512daf946SGreg Clayton m_thread.m_reg_context_sp->GetSP(), 8612daf946SGreg Clayton m_thread.m_reg_context_sp->GetPC(), 8712daf946SGreg Clayton NULL)); 88*5082c5fdSGreg Clayton m_frames.push_back (unwind_frame_sp); 89*5082c5fdSGreg Clayton } 90*5082c5fdSGreg Clayton else 91*5082c5fdSGreg Clayton { 92*5082c5fdSGreg Clayton unwind_frame_sp = m_frames.front(); 93*5082c5fdSGreg Clayton } 9412daf946SGreg Clayton } 9512daf946SGreg Clayton else 9612daf946SGreg Clayton { 9712daf946SGreg Clayton const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc); 9812daf946SGreg Clayton assert (success); 99*5082c5fdSGreg Clayton unwind_frame_sp.reset (new StackFrame (m_frames.size(), idx, m_thread, cfa, pc, NULL)); 100*5082c5fdSGreg Clayton m_frames.push_back (unwind_frame_sp); 10112daf946SGreg Clayton } 10212daf946SGreg Clayton 103*5082c5fdSGreg Clayton Block *block = unwind_frame_sp->GetSymbolContext (eSymbolContextBlock).block; 10412daf946SGreg Clayton 10512daf946SGreg Clayton if (block) 10612daf946SGreg Clayton { 107*5082c5fdSGreg Clayton for (block = block->GetContainingInlinedBlock(); block != NULL; block = block->GetInlinedParent ()) 1080445d8f4SGreg Clayton { 109*5082c5fdSGreg Clayton SymbolContext inline_sc; 110*5082c5fdSGreg Clayton Block *parent_block = block->GetInlinedParent(); 11112daf946SGreg Clayton 112*5082c5fdSGreg Clayton const bool is_inlined_frame = parent_block != NULL; 113*5082c5fdSGreg Clayton 114*5082c5fdSGreg Clayton if (parent_block == NULL) 115*5082c5fdSGreg Clayton parent_block = block->GetParent(); 116*5082c5fdSGreg Clayton 117*5082c5fdSGreg Clayton parent_block->CalculateSymbolContext (&inline_sc); 118*5082c5fdSGreg Clayton 119*5082c5fdSGreg Clayton Address previous_frame_lookup_addr (m_frames.back()->GetFrameCodeAddress()); 120*5082c5fdSGreg Clayton if (unwind_frame_sp->GetFrameIndex() > 0 && m_frames.back().get() == unwind_frame_sp.get()) 121*5082c5fdSGreg Clayton previous_frame_lookup_addr.Slide (-1); 122*5082c5fdSGreg Clayton 123*5082c5fdSGreg Clayton AddressRange range; 124*5082c5fdSGreg Clayton block->GetRangeContainingAddress (previous_frame_lookup_addr, range); 125*5082c5fdSGreg Clayton 126*5082c5fdSGreg Clayton const InlineFunctionInfo* inline_info = block->InlinedFunctionInfo(); 127*5082c5fdSGreg Clayton assert (inline_info); 128*5082c5fdSGreg Clayton inline_sc.line_entry.range.GetBaseAddress() = m_frames.back()->GetFrameCodeAddress(); 129*5082c5fdSGreg Clayton inline_sc.line_entry.file = inline_info->GetCallSite().GetFile(); 130*5082c5fdSGreg Clayton inline_sc.line_entry.line = inline_info->GetCallSite().GetLine(); 131*5082c5fdSGreg Clayton inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn(); 132*5082c5fdSGreg Clayton 133*5082c5fdSGreg Clayton StackFrameSP frame_sp(new StackFrame (m_frames.size(), 134*5082c5fdSGreg Clayton idx, 135*5082c5fdSGreg Clayton m_thread, 136*5082c5fdSGreg Clayton unwind_frame_sp->GetRegisterContextSP (), 137*5082c5fdSGreg Clayton unwind_frame_sp->GetStackID().GetCallFrameAddress(), // CFA 138*5082c5fdSGreg Clayton range.GetBaseAddress(), 139*5082c5fdSGreg Clayton &inline_sc)); // The symbol context for this inline frame 140*5082c5fdSGreg Clayton 141*5082c5fdSGreg Clayton if (is_inlined_frame) 142*5082c5fdSGreg Clayton frame_sp->SetInlineBlockID (block->GetID()); 143*5082c5fdSGreg Clayton 144*5082c5fdSGreg Clayton m_frames.push_back (frame_sp); 145*5082c5fdSGreg Clayton } 146*5082c5fdSGreg Clayton } 147*5082c5fdSGreg Clayton } 148*5082c5fdSGreg Clayton StackFrameList *prev_frames = m_prev_frames_ap.get(); 149*5082c5fdSGreg Clayton if (prev_frames) 15012daf946SGreg Clayton { 151*5082c5fdSGreg Clayton StackFrameList *curr_frames = this; 152*5082c5fdSGreg Clayton 153*5082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES) 154*5082c5fdSGreg Clayton s.PutCString("prev_frames:\n"); 155*5082c5fdSGreg Clayton prev_frames->Dump (&s); 156*5082c5fdSGreg Clayton s.PutCString("curr_frames:\n"); 157*5082c5fdSGreg Clayton curr_frames->Dump (&s); 158*5082c5fdSGreg Clayton s.EOL(); 159*5082c5fdSGreg Clayton #endif 160*5082c5fdSGreg Clayton size_t curr_frame_num, prev_frame_num; 161*5082c5fdSGreg Clayton 162*5082c5fdSGreg Clayton for (curr_frame_num = curr_frames->m_frames.size(), prev_frame_num = prev_frames->m_frames.size(); 163*5082c5fdSGreg Clayton curr_frame_num > 0 && prev_frame_num > 0; 164*5082c5fdSGreg Clayton --curr_frame_num, --prev_frame_num) 165*5082c5fdSGreg Clayton { 166*5082c5fdSGreg Clayton const size_t curr_frame_idx = curr_frame_num-1; 167*5082c5fdSGreg Clayton const size_t prev_frame_idx = prev_frame_num-1; 168*5082c5fdSGreg Clayton StackFrameSP curr_frame_sp (curr_frames->m_frames[curr_frame_idx]); 169*5082c5fdSGreg Clayton StackFrameSP prev_frame_sp (prev_frames->m_frames[prev_frame_idx]); 170*5082c5fdSGreg Clayton 171*5082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES) 172*5082c5fdSGreg Clayton s.Printf("\nCurrent frame #%u ", curr_frame_idx); 173*5082c5fdSGreg Clayton if (curr_frame_sp) 174*5082c5fdSGreg Clayton curr_frame_sp->Dump (&s, true); 175*5082c5fdSGreg Clayton else 176*5082c5fdSGreg Clayton s.PutCString("NULL"); 177*5082c5fdSGreg Clayton s.Printf("\nPrevious frame #%u ", prev_frame_idx); 178*5082c5fdSGreg Clayton if (prev_frame_sp) 179*5082c5fdSGreg Clayton prev_frame_sp->Dump (&s, true); 180*5082c5fdSGreg Clayton else 181*5082c5fdSGreg Clayton s.PutCString("NULL"); 182*5082c5fdSGreg Clayton s.EOL(); 183*5082c5fdSGreg Clayton #endif 184*5082c5fdSGreg Clayton 185*5082c5fdSGreg Clayton StackFrame *curr_frame = curr_frame_sp.get(); 186*5082c5fdSGreg Clayton StackFrame *prev_frame = prev_frame_sp.get(); 187*5082c5fdSGreg Clayton 188*5082c5fdSGreg Clayton if (curr_frame == NULL || prev_frame == NULL) 189*5082c5fdSGreg Clayton break; 190*5082c5fdSGreg Clayton 191*5082c5fdSGreg Clayton // Do a quick sanity check to see if the CFA values are the same. 192*5082c5fdSGreg Clayton if (curr_frame->m_id.GetCallFrameAddress() != prev_frame->m_id.GetCallFrameAddress()) 193*5082c5fdSGreg Clayton break; 194*5082c5fdSGreg Clayton 195*5082c5fdSGreg Clayton // Now check our function or symbol 196*5082c5fdSGreg Clayton SymbolContext curr_sc (curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol)); 197*5082c5fdSGreg Clayton SymbolContext prev_sc (prev_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol)); 198*5082c5fdSGreg Clayton if (curr_sc.function && curr_sc.function == prev_sc.function) 199*5082c5fdSGreg Clayton { 200*5082c5fdSGreg Clayton // Same function 201*5082c5fdSGreg Clayton if (curr_sc.block != prev_sc.block) 202*5082c5fdSGreg Clayton { 203*5082c5fdSGreg Clayton // Same function different block 204*5082c5fdSGreg Clayton if (m_show_inlined_frames) 205*5082c5fdSGreg Clayton break; 206*5082c5fdSGreg Clayton else 207*5082c5fdSGreg Clayton prev_frame->SetSymbolContext (curr_frame->m_sc); 20812daf946SGreg Clayton } 20912daf946SGreg Clayton } 210*5082c5fdSGreg Clayton else if (curr_sc.symbol && curr_sc.symbol == prev_sc.symbol) 211*5082c5fdSGreg Clayton { 212*5082c5fdSGreg Clayton // Same symbol 21312daf946SGreg Clayton } 214*5082c5fdSGreg Clayton else if (curr_frame->GetFrameCodeAddress() != prev_frame->GetFrameCodeAddress()) 215*5082c5fdSGreg Clayton { 216*5082c5fdSGreg Clayton // No symbols for this frame and the PC was different 217*5082c5fdSGreg Clayton break; 21812daf946SGreg Clayton } 219*5082c5fdSGreg Clayton 220*5082c5fdSGreg Clayton if (curr_frame->GetFrameCodeAddress() != prev_frame->GetFrameCodeAddress()) 221*5082c5fdSGreg Clayton { 222*5082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES) 223*5082c5fdSGreg Clayton s.Printf("\nUpdating frame code address and symbol context in previous frame #%u to current frame #%u", prev_frame_idx, curr_frame_idx); 224*5082c5fdSGreg Clayton #endif 225*5082c5fdSGreg Clayton // We have a different code frame address, we might need to copy 226*5082c5fdSGreg Clayton // some stuff in prev_frame, yet update the code address... 227*5082c5fdSGreg Clayton prev_frame->SetFrameCodeAddress (curr_frame->GetFrameCodeAddress()); 228*5082c5fdSGreg Clayton prev_frame->SetSymbolContext (curr_frame->m_sc); 2290445d8f4SGreg Clayton } 230*5082c5fdSGreg Clayton 231*5082c5fdSGreg Clayton curr_frames->m_frames[curr_frame_idx] = prev_frames->m_frames[prev_frame_idx]; 232*5082c5fdSGreg Clayton 233*5082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES) 234*5082c5fdSGreg Clayton s.Printf("\nCopying previous frame #%u to current frame #%u", prev_frame_idx, curr_frame_idx); 235*5082c5fdSGreg Clayton #endif 236*5082c5fdSGreg Clayton } 237*5082c5fdSGreg Clayton // We are done with the old stack frame list, we can release it now 238*5082c5fdSGreg Clayton m_prev_frames_ap.release(); 239*5082c5fdSGreg Clayton prev_frames = NULL; 240*5082c5fdSGreg Clayton } 24112daf946SGreg Clayton } 24212daf946SGreg Clayton else 24312daf946SGreg Clayton { 244*5082c5fdSGreg Clayton m_frames.resize(m_thread.GetUnwinder()->GetFrameCount()); 24512daf946SGreg Clayton } 246*5082c5fdSGreg Clayton } 247*5082c5fdSGreg Clayton return m_frames.size(); 24830fdc8d8SChris Lattner } 24930fdc8d8SChris Lattner 250*5082c5fdSGreg Clayton void 251*5082c5fdSGreg Clayton StackFrameList::Dump (Stream *s) 25230fdc8d8SChris Lattner { 253*5082c5fdSGreg Clayton if (s == NULL) 254*5082c5fdSGreg Clayton return; 255*5082c5fdSGreg Clayton Mutex::Locker locker (m_mutex); 25630fdc8d8SChris Lattner 257*5082c5fdSGreg Clayton const_iterator pos, begin = m_frames.begin(), end = m_frames.end(); 258*5082c5fdSGreg Clayton for (pos = begin; pos != end; ++pos) 25912daf946SGreg Clayton { 260*5082c5fdSGreg Clayton StackFrame *frame = (*pos).get(); 261*5082c5fdSGreg Clayton s->Printf("%p: ", frame); 262*5082c5fdSGreg Clayton if (frame) 263*5082c5fdSGreg Clayton frame->Dump(s, true); 264*5082c5fdSGreg Clayton else 265*5082c5fdSGreg Clayton s->Printf("frame #%u", std::distance (begin, pos)); 266*5082c5fdSGreg Clayton s->EOL(); 26712daf946SGreg Clayton } 268*5082c5fdSGreg Clayton s->EOL(); 269*5082c5fdSGreg Clayton } 27012daf946SGreg Clayton 27130fdc8d8SChris Lattner StackFrameSP 27212daf946SGreg Clayton StackFrameList::GetFrameAtIndex (uint32_t idx) 27330fdc8d8SChris Lattner { 27430fdc8d8SChris Lattner StackFrameSP frame_sp; 27530fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 276*5082c5fdSGreg Clayton if (idx < m_frames.size()) 277*5082c5fdSGreg Clayton frame_sp = m_frames[idx]; 27812daf946SGreg Clayton 279*5082c5fdSGreg Clayton if (frame_sp) 28012daf946SGreg Clayton return frame_sp; 28112daf946SGreg Clayton 28212daf946SGreg Clayton // Special case the first frame (idx == 0) so that we don't need to 28312daf946SGreg Clayton // know how many stack frames there are to get it. If we need any other 28412daf946SGreg Clayton // frames, then we do need to know if "idx" is a valid index. 28512daf946SGreg Clayton if (idx == 0) 28612daf946SGreg Clayton { 28712daf946SGreg Clayton // If this is the first frame, we want to share the thread register 28812daf946SGreg Clayton // context with the stack frame at index zero. 28912daf946SGreg Clayton m_thread.GetRegisterContext(); 29012daf946SGreg Clayton assert (m_thread.m_reg_context_sp.get()); 29112daf946SGreg Clayton frame_sp.reset (new StackFrame (0, 29212daf946SGreg Clayton 0, 29312daf946SGreg Clayton m_thread, 29412daf946SGreg Clayton m_thread.m_reg_context_sp, 29512daf946SGreg Clayton m_thread.m_reg_context_sp->GetSP(), 29612daf946SGreg Clayton m_thread.m_reg_context_sp->GetPC(), 29712daf946SGreg Clayton NULL)); 2980445d8f4SGreg Clayton 299*5082c5fdSGreg Clayton if (m_show_inlined_frames) 3000445d8f4SGreg Clayton { 301*5082c5fdSGreg Clayton Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block; 3020445d8f4SGreg Clayton 303*5082c5fdSGreg Clayton if (block) 304*5082c5fdSGreg Clayton { 305*5082c5fdSGreg Clayton Block *inline_block = block->GetContainingInlinedBlock(); 306*5082c5fdSGreg Clayton if (inline_block) 307*5082c5fdSGreg Clayton frame_sp->SetInlineBlockID (inline_block->GetID()); 308*5082c5fdSGreg Clayton } 309*5082c5fdSGreg Clayton } 310*5082c5fdSGreg Clayton SetFrameAtIndex(idx, frame_sp); 31112daf946SGreg Clayton } 31212daf946SGreg Clayton else if (idx < GetNumFrames()) 31312daf946SGreg Clayton { 31412daf946SGreg Clayton if (m_show_inlined_frames) 31512daf946SGreg Clayton { 316*5082c5fdSGreg Clayton // When inline frames are enabled we cache up all frames in GetNumFrames() 317*5082c5fdSGreg Clayton frame_sp = m_frames[idx]; 31812daf946SGreg Clayton } 31912daf946SGreg Clayton else 32012daf946SGreg Clayton { 32112daf946SGreg Clayton Unwind *unwinder = m_thread.GetUnwinder (); 32212daf946SGreg Clayton if (unwinder) 32312daf946SGreg Clayton { 32412daf946SGreg Clayton addr_t pc, cfa; 32512daf946SGreg Clayton if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) 326*5082c5fdSGreg Clayton { 3270445d8f4SGreg Clayton frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL)); 328*5082c5fdSGreg Clayton SetFrameAtIndex(idx, frame_sp); 32912daf946SGreg Clayton } 33012daf946SGreg Clayton } 33112daf946SGreg Clayton } 3320445d8f4SGreg Clayton 33330fdc8d8SChris Lattner } 33430fdc8d8SChris Lattner return frame_sp; 33530fdc8d8SChris Lattner } 33630fdc8d8SChris Lattner 33712daf946SGreg Clayton 33812daf946SGreg Clayton bool 339*5082c5fdSGreg Clayton StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp) 34012daf946SGreg Clayton { 341*5082c5fdSGreg Clayton if (idx >= m_frames.size()) 342*5082c5fdSGreg Clayton m_frames.resize(idx + 1); 34312daf946SGreg Clayton // Make sure allocation succeeded by checking bounds again 344*5082c5fdSGreg Clayton if (idx < m_frames.size()) 34512daf946SGreg Clayton { 346*5082c5fdSGreg Clayton m_frames[idx] = frame_sp; 34730fdc8d8SChris Lattner return true; 34830fdc8d8SChris Lattner } 34930fdc8d8SChris Lattner return false; // resize failed, out of memory? 35030fdc8d8SChris Lattner } 35130fdc8d8SChris Lattner 35230fdc8d8SChris Lattner uint32_t 3532976d00aSJim Ingham StackFrameList::GetSelectedFrameIndex () const 35430fdc8d8SChris Lattner { 35530fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 3562976d00aSJim Ingham return m_selected_frame_idx; 35730fdc8d8SChris Lattner } 35830fdc8d8SChris Lattner 35930fdc8d8SChris Lattner 36030fdc8d8SChris Lattner uint32_t 3612976d00aSJim Ingham StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame) 36230fdc8d8SChris Lattner { 36330fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 36412daf946SGreg Clayton const_iterator pos; 365*5082c5fdSGreg Clayton const_iterator begin = m_frames.begin(); 366*5082c5fdSGreg Clayton const_iterator end = m_frames.end(); 36730fdc8d8SChris Lattner for (pos = begin; pos != end; ++pos) 36830fdc8d8SChris Lattner { 36930fdc8d8SChris Lattner if (pos->get() == frame) 37030fdc8d8SChris Lattner { 3712976d00aSJim Ingham m_selected_frame_idx = std::distance (begin, pos); 3722976d00aSJim Ingham return m_selected_frame_idx; 37330fdc8d8SChris Lattner } 37430fdc8d8SChris Lattner } 3752976d00aSJim Ingham m_selected_frame_idx = 0; 3762976d00aSJim Ingham return m_selected_frame_idx; 37730fdc8d8SChris Lattner } 37830fdc8d8SChris Lattner 37930fdc8d8SChris Lattner // Mark a stack frame as the current frame using the frame index 38030fdc8d8SChris Lattner void 3812976d00aSJim Ingham StackFrameList::SetSelectedFrameByIndex (uint32_t idx) 38230fdc8d8SChris Lattner { 38330fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 3842976d00aSJim Ingham m_selected_frame_idx = idx; 38530fdc8d8SChris Lattner } 38630fdc8d8SChris Lattner 38730fdc8d8SChris Lattner // The thread has been run, reset the number stack frames to zero so we can 38830fdc8d8SChris Lattner // determine how many frames we have lazily. 38930fdc8d8SChris Lattner void 39030fdc8d8SChris Lattner StackFrameList::Clear () 39130fdc8d8SChris Lattner { 39230fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 393*5082c5fdSGreg Clayton m_frames.clear(); 39430fdc8d8SChris Lattner } 39530fdc8d8SChris Lattner 39630fdc8d8SChris Lattner void 39730fdc8d8SChris Lattner StackFrameList::InvalidateFrames (uint32_t start_idx) 39830fdc8d8SChris Lattner { 39930fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 40012daf946SGreg Clayton if (m_show_inlined_frames) 40112daf946SGreg Clayton { 40212daf946SGreg Clayton Clear(); 40312daf946SGreg Clayton } 40412daf946SGreg Clayton else 40512daf946SGreg Clayton { 406*5082c5fdSGreg Clayton const size_t num_frames = m_frames.size(); 40730fdc8d8SChris Lattner while (start_idx < num_frames) 40830fdc8d8SChris Lattner { 409*5082c5fdSGreg Clayton m_frames[start_idx].reset(); 41030fdc8d8SChris Lattner ++start_idx; 41130fdc8d8SChris Lattner } 41230fdc8d8SChris Lattner } 41312daf946SGreg Clayton } 414