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" 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 245082c5fdSGreg Clayton //#define DEBUG_STACK_FRAMES 1 255082c5fdSGreg 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), 375082c5fdSGreg 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 555082c5fdSGreg Clayton if (m_frames.size() <= 1) 565082c5fdSGreg Clayton { 5712daf946SGreg Clayton if (m_show_inlined_frames) 5812daf946SGreg Clayton { 595082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES) 605082c5fdSGreg Clayton StreamFile s(stdout); 615082c5fdSGreg Clayton #endif 6212daf946SGreg Clayton Unwind *unwinder = m_thread.GetUnwinder (); 635082c5fdSGreg Clayton addr_t pc, cfa; 645082c5fdSGreg 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 685082c5fdSGreg Clayton // in each frame. 695082c5fdSGreg Clayton const uint32_t unwind_frame_count = unwinder->GetFrameCount(); 7012daf946SGreg Clayton 715082c5fdSGreg Clayton StackFrameSP unwind_frame_sp; 725082c5fdSGreg Clayton for (uint32_t idx=0; idx<unwind_frame_count; ++idx) 7312daf946SGreg Clayton { 7412daf946SGreg Clayton if (idx == 0) 7512daf946SGreg Clayton { 765082c5fdSGreg Clayton // We might have already created frame zero, only create it 775082c5fdSGreg Clayton // if we need to 785082c5fdSGreg Clayton if (m_frames.empty()) 795082c5fdSGreg Clayton { 8012daf946SGreg Clayton m_thread.GetRegisterContext(); 815082c5fdSGreg Clayton unwind_frame_sp.reset (new StackFrame (m_frames.size(), 825082c5fdSGreg 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)); 885082c5fdSGreg Clayton m_frames.push_back (unwind_frame_sp); 895082c5fdSGreg Clayton } 905082c5fdSGreg Clayton else 915082c5fdSGreg Clayton { 925082c5fdSGreg Clayton unwind_frame_sp = m_frames.front(); 935082c5fdSGreg Clayton } 9412daf946SGreg Clayton } 9512daf946SGreg Clayton else 9612daf946SGreg Clayton { 9712daf946SGreg Clayton const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc); 9812daf946SGreg Clayton assert (success); 995082c5fdSGreg Clayton unwind_frame_sp.reset (new StackFrame (m_frames.size(), idx, m_thread, cfa, pc, NULL)); 1005082c5fdSGreg Clayton m_frames.push_back (unwind_frame_sp); 10112daf946SGreg Clayton } 10212daf946SGreg Clayton 1035082c5fdSGreg Clayton Block *block = unwind_frame_sp->GetSymbolContext (eSymbolContextBlock).block; 10412daf946SGreg Clayton 10512daf946SGreg Clayton if (block) 10612daf946SGreg Clayton { 1075082c5fdSGreg Clayton for (block = block->GetContainingInlinedBlock(); block != NULL; block = block->GetInlinedParent ()) 1080445d8f4SGreg Clayton { 1095082c5fdSGreg Clayton SymbolContext inline_sc; 1105082c5fdSGreg Clayton Block *parent_block = block->GetInlinedParent(); 11112daf946SGreg Clayton 1125082c5fdSGreg Clayton const bool is_inlined_frame = parent_block != NULL; 1135082c5fdSGreg Clayton 1145082c5fdSGreg Clayton if (parent_block == NULL) 1155082c5fdSGreg Clayton parent_block = block->GetParent(); 1165082c5fdSGreg Clayton 1175082c5fdSGreg Clayton parent_block->CalculateSymbolContext (&inline_sc); 1185082c5fdSGreg Clayton 1195082c5fdSGreg Clayton Address previous_frame_lookup_addr (m_frames.back()->GetFrameCodeAddress()); 1205082c5fdSGreg Clayton if (unwind_frame_sp->GetFrameIndex() > 0 && m_frames.back().get() == unwind_frame_sp.get()) 1215082c5fdSGreg Clayton previous_frame_lookup_addr.Slide (-1); 1225082c5fdSGreg Clayton 1235082c5fdSGreg Clayton AddressRange range; 1245082c5fdSGreg Clayton block->GetRangeContainingAddress (previous_frame_lookup_addr, range); 1255082c5fdSGreg Clayton 1265082c5fdSGreg Clayton const InlineFunctionInfo* inline_info = block->InlinedFunctionInfo(); 1275082c5fdSGreg Clayton assert (inline_info); 1285082c5fdSGreg Clayton inline_sc.line_entry.range.GetBaseAddress() = m_frames.back()->GetFrameCodeAddress(); 1295082c5fdSGreg Clayton inline_sc.line_entry.file = inline_info->GetCallSite().GetFile(); 1305082c5fdSGreg Clayton inline_sc.line_entry.line = inline_info->GetCallSite().GetLine(); 1315082c5fdSGreg Clayton inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn(); 1325082c5fdSGreg Clayton 1335082c5fdSGreg Clayton StackFrameSP frame_sp(new StackFrame (m_frames.size(), 1345082c5fdSGreg Clayton idx, 1355082c5fdSGreg Clayton m_thread, 1365082c5fdSGreg Clayton unwind_frame_sp->GetRegisterContextSP (), 1375082c5fdSGreg Clayton unwind_frame_sp->GetStackID().GetCallFrameAddress(), // CFA 1385082c5fdSGreg Clayton range.GetBaseAddress(), 1395082c5fdSGreg Clayton &inline_sc)); // The symbol context for this inline frame 1405082c5fdSGreg Clayton 1415082c5fdSGreg Clayton if (is_inlined_frame) 1425082c5fdSGreg Clayton frame_sp->SetInlineBlockID (block->GetID()); 1435082c5fdSGreg Clayton 1445082c5fdSGreg Clayton m_frames.push_back (frame_sp); 1455082c5fdSGreg Clayton } 1465082c5fdSGreg Clayton } 1475082c5fdSGreg Clayton } 1485082c5fdSGreg Clayton StackFrameList *prev_frames = m_prev_frames_ap.get(); 1495082c5fdSGreg Clayton if (prev_frames) 15012daf946SGreg Clayton { 1515082c5fdSGreg Clayton StackFrameList *curr_frames = this; 1525082c5fdSGreg Clayton 1535082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES) 154*68275d5eSGreg Clayton s.PutCString("\nprev_frames:\n"); 1555082c5fdSGreg Clayton prev_frames->Dump (&s); 156*68275d5eSGreg Clayton s.PutCString("\ncurr_frames:\n"); 1575082c5fdSGreg Clayton curr_frames->Dump (&s); 1585082c5fdSGreg Clayton s.EOL(); 1595082c5fdSGreg Clayton #endif 1605082c5fdSGreg Clayton size_t curr_frame_num, prev_frame_num; 1615082c5fdSGreg Clayton 1625082c5fdSGreg Clayton for (curr_frame_num = curr_frames->m_frames.size(), prev_frame_num = prev_frames->m_frames.size(); 1635082c5fdSGreg Clayton curr_frame_num > 0 && prev_frame_num > 0; 1645082c5fdSGreg Clayton --curr_frame_num, --prev_frame_num) 1655082c5fdSGreg Clayton { 1665082c5fdSGreg Clayton const size_t curr_frame_idx = curr_frame_num-1; 1675082c5fdSGreg Clayton const size_t prev_frame_idx = prev_frame_num-1; 1685082c5fdSGreg Clayton StackFrameSP curr_frame_sp (curr_frames->m_frames[curr_frame_idx]); 1695082c5fdSGreg Clayton StackFrameSP prev_frame_sp (prev_frames->m_frames[prev_frame_idx]); 1705082c5fdSGreg Clayton 1715082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES) 1725082c5fdSGreg Clayton s.Printf("\nCurrent frame #%u ", curr_frame_idx); 1735082c5fdSGreg Clayton if (curr_frame_sp) 1745082c5fdSGreg Clayton curr_frame_sp->Dump (&s, true); 1755082c5fdSGreg Clayton else 1765082c5fdSGreg Clayton s.PutCString("NULL"); 1775082c5fdSGreg Clayton s.Printf("\nPrevious frame #%u ", prev_frame_idx); 1785082c5fdSGreg Clayton if (prev_frame_sp) 1795082c5fdSGreg Clayton prev_frame_sp->Dump (&s, true); 1805082c5fdSGreg Clayton else 1815082c5fdSGreg Clayton s.PutCString("NULL"); 1825082c5fdSGreg Clayton s.EOL(); 1835082c5fdSGreg Clayton #endif 1845082c5fdSGreg Clayton 1855082c5fdSGreg Clayton StackFrame *curr_frame = curr_frame_sp.get(); 1865082c5fdSGreg Clayton StackFrame *prev_frame = prev_frame_sp.get(); 1875082c5fdSGreg Clayton 1885082c5fdSGreg Clayton if (curr_frame == NULL || prev_frame == NULL) 1895082c5fdSGreg Clayton break; 1905082c5fdSGreg Clayton 1915082c5fdSGreg Clayton // Do a quick sanity check to see if the CFA values are the same. 1925082c5fdSGreg Clayton if (curr_frame->m_id.GetCallFrameAddress() != prev_frame->m_id.GetCallFrameAddress()) 1935082c5fdSGreg Clayton break; 1945082c5fdSGreg Clayton 1955082c5fdSGreg Clayton // Now check our function or symbol 1965082c5fdSGreg Clayton SymbolContext curr_sc (curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol)); 1975082c5fdSGreg Clayton SymbolContext prev_sc (prev_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol)); 1985082c5fdSGreg Clayton if (curr_sc.function && curr_sc.function == prev_sc.function) 1995082c5fdSGreg Clayton { 2005082c5fdSGreg Clayton // Same function 2015082c5fdSGreg Clayton if (curr_sc.block != prev_sc.block) 2025082c5fdSGreg Clayton { 2035082c5fdSGreg Clayton // Same function different block 2045082c5fdSGreg Clayton if (m_show_inlined_frames) 2055082c5fdSGreg Clayton break; 20612daf946SGreg Clayton } 20712daf946SGreg Clayton } 2085082c5fdSGreg Clayton else if (curr_sc.symbol && curr_sc.symbol == prev_sc.symbol) 2095082c5fdSGreg Clayton { 2105082c5fdSGreg Clayton // Same symbol 21112daf946SGreg Clayton } 2125082c5fdSGreg Clayton else if (curr_frame->GetFrameCodeAddress() != prev_frame->GetFrameCodeAddress()) 2135082c5fdSGreg Clayton { 2145082c5fdSGreg Clayton // No symbols for this frame and the PC was different 2155082c5fdSGreg Clayton break; 21612daf946SGreg Clayton } 2175082c5fdSGreg Clayton 218*68275d5eSGreg Clayton curr_frame->UpdateCurrentFrameFromPreviousFrame (*prev_frame); 2195082c5fdSGreg Clayton 2205082c5fdSGreg Clayton #if defined (DEBUG_STACK_FRAMES) 221*68275d5eSGreg Clayton s.Printf("\n Copying previous frame to current frame"); 2225082c5fdSGreg Clayton #endif 2235082c5fdSGreg Clayton } 2245082c5fdSGreg Clayton // We are done with the old stack frame list, we can release it now 2255082c5fdSGreg Clayton m_prev_frames_ap.release(); 2265082c5fdSGreg Clayton prev_frames = NULL; 2275082c5fdSGreg Clayton } 228*68275d5eSGreg Clayton 229*68275d5eSGreg Clayton #if defined (DEBUG_STACK_FRAMES) 230*68275d5eSGreg Clayton s.PutCString("\n\nNew frames:\n"); 231*68275d5eSGreg Clayton Dump (&s); 232*68275d5eSGreg Clayton s.EOL(); 233*68275d5eSGreg Clayton #endif 23412daf946SGreg Clayton } 23512daf946SGreg Clayton else 23612daf946SGreg Clayton { 2375082c5fdSGreg Clayton m_frames.resize(m_thread.GetUnwinder()->GetFrameCount()); 23812daf946SGreg Clayton } 2395082c5fdSGreg Clayton } 2405082c5fdSGreg Clayton return m_frames.size(); 24130fdc8d8SChris Lattner } 24230fdc8d8SChris Lattner 2435082c5fdSGreg Clayton void 2445082c5fdSGreg Clayton StackFrameList::Dump (Stream *s) 24530fdc8d8SChris Lattner { 2465082c5fdSGreg Clayton if (s == NULL) 2475082c5fdSGreg Clayton return; 2485082c5fdSGreg Clayton Mutex::Locker locker (m_mutex); 24930fdc8d8SChris Lattner 2505082c5fdSGreg Clayton const_iterator pos, begin = m_frames.begin(), end = m_frames.end(); 2515082c5fdSGreg Clayton for (pos = begin; pos != end; ++pos) 25212daf946SGreg Clayton { 2535082c5fdSGreg Clayton StackFrame *frame = (*pos).get(); 2545082c5fdSGreg Clayton s->Printf("%p: ", frame); 2555082c5fdSGreg Clayton if (frame) 2565082c5fdSGreg Clayton frame->Dump(s, true); 2575082c5fdSGreg Clayton else 2585082c5fdSGreg Clayton s->Printf("frame #%u", std::distance (begin, pos)); 2595082c5fdSGreg Clayton s->EOL(); 26012daf946SGreg Clayton } 2615082c5fdSGreg Clayton s->EOL(); 2625082c5fdSGreg Clayton } 26312daf946SGreg Clayton 26430fdc8d8SChris Lattner StackFrameSP 26512daf946SGreg Clayton StackFrameList::GetFrameAtIndex (uint32_t idx) 26630fdc8d8SChris Lattner { 26730fdc8d8SChris Lattner StackFrameSP frame_sp; 26830fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 2695082c5fdSGreg Clayton if (idx < m_frames.size()) 2705082c5fdSGreg Clayton frame_sp = m_frames[idx]; 27112daf946SGreg Clayton 2725082c5fdSGreg Clayton if (frame_sp) 27312daf946SGreg Clayton return frame_sp; 27412daf946SGreg Clayton 27512daf946SGreg Clayton // Special case the first frame (idx == 0) so that we don't need to 27612daf946SGreg Clayton // know how many stack frames there are to get it. If we need any other 27712daf946SGreg Clayton // frames, then we do need to know if "idx" is a valid index. 27812daf946SGreg Clayton if (idx == 0) 27912daf946SGreg Clayton { 28012daf946SGreg Clayton // If this is the first frame, we want to share the thread register 28112daf946SGreg Clayton // context with the stack frame at index zero. 28212daf946SGreg Clayton m_thread.GetRegisterContext(); 28312daf946SGreg Clayton assert (m_thread.m_reg_context_sp.get()); 28412daf946SGreg Clayton frame_sp.reset (new StackFrame (0, 28512daf946SGreg Clayton 0, 28612daf946SGreg Clayton m_thread, 28712daf946SGreg Clayton m_thread.m_reg_context_sp, 28812daf946SGreg Clayton m_thread.m_reg_context_sp->GetSP(), 28912daf946SGreg Clayton m_thread.m_reg_context_sp->GetPC(), 29012daf946SGreg Clayton NULL)); 2910445d8f4SGreg Clayton 2925082c5fdSGreg Clayton if (m_show_inlined_frames) 2930445d8f4SGreg Clayton { 2945082c5fdSGreg Clayton Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block; 2950445d8f4SGreg Clayton 2965082c5fdSGreg Clayton if (block) 2975082c5fdSGreg Clayton { 2985082c5fdSGreg Clayton Block *inline_block = block->GetContainingInlinedBlock(); 2995082c5fdSGreg Clayton if (inline_block) 3005082c5fdSGreg Clayton frame_sp->SetInlineBlockID (inline_block->GetID()); 3015082c5fdSGreg Clayton } 3025082c5fdSGreg Clayton } 3035082c5fdSGreg Clayton SetFrameAtIndex(idx, frame_sp); 30412daf946SGreg Clayton } 30512daf946SGreg Clayton else if (idx < GetNumFrames()) 30612daf946SGreg Clayton { 30712daf946SGreg Clayton if (m_show_inlined_frames) 30812daf946SGreg Clayton { 3095082c5fdSGreg Clayton // When inline frames are enabled we cache up all frames in GetNumFrames() 3105082c5fdSGreg Clayton frame_sp = m_frames[idx]; 31112daf946SGreg Clayton } 31212daf946SGreg Clayton else 31312daf946SGreg Clayton { 31412daf946SGreg Clayton Unwind *unwinder = m_thread.GetUnwinder (); 31512daf946SGreg Clayton if (unwinder) 31612daf946SGreg Clayton { 31712daf946SGreg Clayton addr_t pc, cfa; 31812daf946SGreg Clayton if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) 3195082c5fdSGreg Clayton { 3200445d8f4SGreg Clayton frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL)); 3215082c5fdSGreg Clayton SetFrameAtIndex(idx, frame_sp); 32212daf946SGreg Clayton } 32312daf946SGreg Clayton } 32412daf946SGreg Clayton } 3250445d8f4SGreg Clayton 32630fdc8d8SChris Lattner } 32730fdc8d8SChris Lattner return frame_sp; 32830fdc8d8SChris Lattner } 32930fdc8d8SChris Lattner 33012daf946SGreg Clayton 33112daf946SGreg Clayton bool 3325082c5fdSGreg Clayton StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp) 33312daf946SGreg Clayton { 3345082c5fdSGreg Clayton if (idx >= m_frames.size()) 3355082c5fdSGreg Clayton m_frames.resize(idx + 1); 33612daf946SGreg Clayton // Make sure allocation succeeded by checking bounds again 3375082c5fdSGreg Clayton if (idx < m_frames.size()) 33812daf946SGreg Clayton { 3395082c5fdSGreg Clayton m_frames[idx] = frame_sp; 34030fdc8d8SChris Lattner return true; 34130fdc8d8SChris Lattner } 34230fdc8d8SChris Lattner return false; // resize failed, out of memory? 34330fdc8d8SChris Lattner } 34430fdc8d8SChris Lattner 34530fdc8d8SChris Lattner uint32_t 3462976d00aSJim Ingham StackFrameList::GetSelectedFrameIndex () const 34730fdc8d8SChris Lattner { 34830fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 3492976d00aSJim Ingham return m_selected_frame_idx; 35030fdc8d8SChris Lattner } 35130fdc8d8SChris Lattner 35230fdc8d8SChris Lattner 35330fdc8d8SChris Lattner uint32_t 3542976d00aSJim Ingham StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame) 35530fdc8d8SChris Lattner { 35630fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 35712daf946SGreg Clayton const_iterator pos; 3585082c5fdSGreg Clayton const_iterator begin = m_frames.begin(); 3595082c5fdSGreg Clayton const_iterator end = m_frames.end(); 36030fdc8d8SChris Lattner for (pos = begin; pos != end; ++pos) 36130fdc8d8SChris Lattner { 36230fdc8d8SChris Lattner if (pos->get() == frame) 36330fdc8d8SChris Lattner { 3642976d00aSJim Ingham m_selected_frame_idx = std::distance (begin, pos); 3652976d00aSJim Ingham return m_selected_frame_idx; 36630fdc8d8SChris Lattner } 36730fdc8d8SChris Lattner } 3682976d00aSJim Ingham m_selected_frame_idx = 0; 3692976d00aSJim Ingham return m_selected_frame_idx; 37030fdc8d8SChris Lattner } 37130fdc8d8SChris Lattner 37230fdc8d8SChris Lattner // Mark a stack frame as the current frame using the frame index 37330fdc8d8SChris Lattner void 3742976d00aSJim Ingham StackFrameList::SetSelectedFrameByIndex (uint32_t idx) 37530fdc8d8SChris Lattner { 37630fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 3772976d00aSJim Ingham m_selected_frame_idx = idx; 37830fdc8d8SChris Lattner } 37930fdc8d8SChris Lattner 38030fdc8d8SChris Lattner // The thread has been run, reset the number stack frames to zero so we can 38130fdc8d8SChris Lattner // determine how many frames we have lazily. 38230fdc8d8SChris Lattner void 38330fdc8d8SChris Lattner StackFrameList::Clear () 38430fdc8d8SChris Lattner { 38530fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 3865082c5fdSGreg Clayton m_frames.clear(); 38730fdc8d8SChris Lattner } 38830fdc8d8SChris Lattner 38930fdc8d8SChris Lattner void 39030fdc8d8SChris Lattner StackFrameList::InvalidateFrames (uint32_t start_idx) 39130fdc8d8SChris Lattner { 39230fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 39312daf946SGreg Clayton if (m_show_inlined_frames) 39412daf946SGreg Clayton { 39512daf946SGreg Clayton Clear(); 39612daf946SGreg Clayton } 39712daf946SGreg Clayton else 39812daf946SGreg Clayton { 3995082c5fdSGreg Clayton const size_t num_frames = m_frames.size(); 40030fdc8d8SChris Lattner while (start_idx < num_frames) 40130fdc8d8SChris Lattner { 4025082c5fdSGreg Clayton m_frames[start_idx].reset(); 40330fdc8d8SChris Lattner ++start_idx; 40430fdc8d8SChris Lattner } 40530fdc8d8SChris Lattner } 40612daf946SGreg Clayton } 407