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 1612daf946SGreg Clayton #include "lldb/Symbol/Block.h" 1712daf946SGreg Clayton #include "lldb/Symbol/Function.h" 1812daf946SGreg Clayton #include "lldb/Target/RegisterContext.h" 1930fdc8d8SChris Lattner #include "lldb/Target/StackFrame.h" 2012daf946SGreg Clayton #include "lldb/Target/Thread.h" 2112daf946SGreg Clayton #include "lldb/Target/Unwind.h" 2230fdc8d8SChris Lattner 2330fdc8d8SChris Lattner using namespace lldb; 2430fdc8d8SChris Lattner using namespace lldb_private; 2530fdc8d8SChris Lattner 2630fdc8d8SChris Lattner //---------------------------------------------------------------------- 2730fdc8d8SChris Lattner // StackFrameList constructor 2830fdc8d8SChris Lattner //---------------------------------------------------------------------- 290445d8f4SGreg Clayton StackFrameList::StackFrameList(Thread &thread, StackFrameList *prev_frames, bool show_inline_frames) : 3012daf946SGreg Clayton m_thread (thread), 310445d8f4SGreg Clayton m_prev_frames_ap (prev_frames), 3212daf946SGreg Clayton m_show_inlined_frames (show_inline_frames), 3330fdc8d8SChris Lattner m_mutex (Mutex::eMutexTypeRecursive), 340445d8f4SGreg Clayton m_unwind_frames (), 3512daf946SGreg Clayton m_inline_frames (), 36*2976d00aSJim Ingham m_selected_frame_idx (0) 3730fdc8d8SChris Lattner { 3830fdc8d8SChris Lattner } 3930fdc8d8SChris Lattner 4030fdc8d8SChris Lattner //---------------------------------------------------------------------- 4130fdc8d8SChris Lattner // Destructor 4230fdc8d8SChris Lattner //---------------------------------------------------------------------- 4330fdc8d8SChris Lattner StackFrameList::~StackFrameList() 4430fdc8d8SChris Lattner { 4530fdc8d8SChris Lattner } 4630fdc8d8SChris Lattner 4730fdc8d8SChris Lattner 4830fdc8d8SChris Lattner uint32_t 4912daf946SGreg Clayton StackFrameList::GetNumFrames() 5030fdc8d8SChris Lattner { 5130fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 5212daf946SGreg Clayton 5312daf946SGreg Clayton if (m_show_inlined_frames) 5412daf946SGreg Clayton { 550445d8f4SGreg Clayton if (m_inlined_info.empty()) 5612daf946SGreg Clayton { 5712daf946SGreg Clayton Unwind *unwinder = m_thread.GetUnwinder (); 5812daf946SGreg Clayton // If we are going to show inlined stack frames as actual frames, 5912daf946SGreg Clayton // we need to calculate all concrete frames first, then iterate 6012daf946SGreg Clayton // through all of them and count up how many inlined functions are 610445d8f4SGreg Clayton // in each frame. We can then fill in m_inlined_info with 6212daf946SGreg Clayton // the concrete frame index and inlined depth 6312daf946SGreg Clayton const uint32_t concrete_frame_count = unwinder->GetFrameCount(); 6412daf946SGreg Clayton 6512daf946SGreg Clayton addr_t pc, cfa; 6612daf946SGreg Clayton InlinedFrameInfo inlined_frame_info; 6712daf946SGreg Clayton 6812daf946SGreg Clayton StackFrameSP frame_sp; 6912daf946SGreg Clayton for (uint32_t idx=0; idx<concrete_frame_count; ++idx) 7012daf946SGreg Clayton { 7112daf946SGreg Clayton if (idx == 0) 7212daf946SGreg Clayton { 7312daf946SGreg Clayton m_thread.GetRegisterContext(); 7412daf946SGreg Clayton frame_sp.reset (new StackFrame (0, 7512daf946SGreg Clayton 0, 7612daf946SGreg Clayton m_thread, 7712daf946SGreg Clayton m_thread.m_reg_context_sp, 7812daf946SGreg Clayton m_thread.m_reg_context_sp->GetSP(), 7912daf946SGreg Clayton m_thread.m_reg_context_sp->GetPC(), 8012daf946SGreg Clayton NULL)); 8112daf946SGreg Clayton } 8212daf946SGreg Clayton else 8312daf946SGreg Clayton { 8412daf946SGreg Clayton const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc); 8512daf946SGreg Clayton assert (success); 860445d8f4SGreg Clayton frame_sp.reset (new StackFrame (m_inlined_info.size(), idx, m_thread, cfa, pc, NULL)); 8712daf946SGreg Clayton } 880445d8f4SGreg Clayton SetUnwindFrameAtIndex (idx, frame_sp); 8912daf946SGreg Clayton Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block; 9012daf946SGreg Clayton 910445d8f4SGreg Clayton inlined_frame_info.unwind_frame_index = idx; 920445d8f4SGreg Clayton inlined_frame_info.block = NULL; 930445d8f4SGreg Clayton m_inlined_info.push_back (inlined_frame_info); 9412daf946SGreg Clayton 9512daf946SGreg Clayton if (block) 9612daf946SGreg Clayton { 970445d8f4SGreg Clayton Block *inlined_block = block->GetContainingInlinedBlock(); 980445d8f4SGreg Clayton 990445d8f4SGreg Clayton if (inlined_block) 1000445d8f4SGreg Clayton { 1010445d8f4SGreg Clayton frame_sp->SetInlineBlockID (inlined_block->GetID()); 10212daf946SGreg Clayton 10312daf946SGreg Clayton while (inlined_block) 10412daf946SGreg Clayton { 10512daf946SGreg Clayton inlined_frame_info.block = inlined_block; 1060445d8f4SGreg Clayton m_inlined_info.push_back (inlined_frame_info); 10712daf946SGreg Clayton inlined_block = inlined_block->GetInlinedParent (); 10812daf946SGreg Clayton } 10912daf946SGreg Clayton } 11012daf946SGreg Clayton } 11112daf946SGreg Clayton } 1120445d8f4SGreg Clayton } 1130445d8f4SGreg Clayton return m_inlined_info.size(); 11412daf946SGreg Clayton } 11512daf946SGreg Clayton else 11612daf946SGreg Clayton { 1170445d8f4SGreg Clayton if (m_unwind_frames.empty()) 1180445d8f4SGreg Clayton m_unwind_frames.resize(m_thread.GetUnwinder()->GetFrameCount()); 11912daf946SGreg Clayton 1200445d8f4SGreg Clayton return m_unwind_frames.size(); 12112daf946SGreg Clayton } 12212daf946SGreg Clayton return 0; 12330fdc8d8SChris Lattner } 12430fdc8d8SChris Lattner 12512daf946SGreg Clayton lldb::StackFrameSP 1260445d8f4SGreg Clayton StackFrameList::GetUnwindFrameAtIndex (uint32_t idx) const 12730fdc8d8SChris Lattner { 12812daf946SGreg Clayton StackFrameSP frame_sp; 1290445d8f4SGreg Clayton if (idx < m_unwind_frames.size()) 1300445d8f4SGreg Clayton frame_sp = m_unwind_frames[idx]; 13112daf946SGreg Clayton return frame_sp; 13230fdc8d8SChris Lattner } 13330fdc8d8SChris Lattner 13412daf946SGreg Clayton lldb::StackFrameSP 13512daf946SGreg Clayton StackFrameList::GetInlineFrameAtIndex (uint32_t idx) const 13612daf946SGreg Clayton { 13712daf946SGreg Clayton StackFrameSP frame_sp; 13812daf946SGreg Clayton if (idx < m_inline_frames.size()) 13912daf946SGreg Clayton frame_sp = m_inline_frames[idx]; 14012daf946SGreg Clayton return frame_sp; 14112daf946SGreg Clayton } 14212daf946SGreg Clayton 14312daf946SGreg Clayton 14430fdc8d8SChris Lattner StackFrameSP 14512daf946SGreg Clayton StackFrameList::GetFrameAtIndex (uint32_t idx) 14630fdc8d8SChris Lattner { 14730fdc8d8SChris Lattner StackFrameSP frame_sp; 14830fdc8d8SChris Lattner { 14930fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 15012daf946SGreg Clayton 15112daf946SGreg Clayton if (m_show_inlined_frames) 15212daf946SGreg Clayton { 15312daf946SGreg Clayton frame_sp = GetInlineFrameAtIndex (idx); 15412daf946SGreg Clayton } 15512daf946SGreg Clayton else 15612daf946SGreg Clayton { 1570445d8f4SGreg Clayton frame_sp = GetUnwindFrameAtIndex (idx); 15812daf946SGreg Clayton } 15912daf946SGreg Clayton 16012daf946SGreg Clayton if (frame_sp.get()) 16112daf946SGreg Clayton return frame_sp; 16212daf946SGreg Clayton 16312daf946SGreg Clayton // Special case the first frame (idx == 0) so that we don't need to 16412daf946SGreg Clayton // know how many stack frames there are to get it. If we need any other 16512daf946SGreg Clayton // frames, then we do need to know if "idx" is a valid index. 16612daf946SGreg Clayton if (idx == 0) 16712daf946SGreg Clayton { 16812daf946SGreg Clayton // If this is the first frame, we want to share the thread register 16912daf946SGreg Clayton // context with the stack frame at index zero. 17012daf946SGreg Clayton m_thread.GetRegisterContext(); 17112daf946SGreg Clayton assert (m_thread.m_reg_context_sp.get()); 17212daf946SGreg Clayton frame_sp.reset (new StackFrame (0, 17312daf946SGreg Clayton 0, 17412daf946SGreg Clayton m_thread, 17512daf946SGreg Clayton m_thread.m_reg_context_sp, 17612daf946SGreg Clayton m_thread.m_reg_context_sp->GetSP(), 17712daf946SGreg Clayton m_thread.m_reg_context_sp->GetPC(), 17812daf946SGreg Clayton NULL)); 1790445d8f4SGreg Clayton 1800445d8f4SGreg Clayton if (m_show_inlined_frames && idx + 1 < m_inlined_info.size()) 1810445d8f4SGreg Clayton { 1820445d8f4SGreg Clayton if (m_inlined_info[idx].unwind_frame_index == m_inlined_info[idx+1].unwind_frame_index) 1830445d8f4SGreg Clayton frame_sp->SetInlineBlockID (frame_sp->GetSymbolContext (eSymbolContextBlock).block->GetID()); 1840445d8f4SGreg Clayton } 1850445d8f4SGreg Clayton 18612daf946SGreg Clayton } 18712daf946SGreg Clayton else if (idx < GetNumFrames()) 18812daf946SGreg Clayton { 18912daf946SGreg Clayton if (m_show_inlined_frames) 19012daf946SGreg Clayton { 1910445d8f4SGreg Clayton if (m_inlined_info[idx].block == NULL) 19212daf946SGreg Clayton { 19312daf946SGreg Clayton // Same as the concrete stack frame if block is NULL 1940445d8f4SGreg Clayton assert (m_inlined_info[idx].unwind_frame_index < m_unwind_frames.size()); 1950445d8f4SGreg Clayton frame_sp = GetUnwindFrameAtIndex (m_inlined_info[idx].unwind_frame_index); 1960445d8f4SGreg Clayton if (idx + 1 < m_inlined_info.size()) 1970445d8f4SGreg Clayton { 1980445d8f4SGreg Clayton if (m_inlined_info[idx].unwind_frame_index == m_inlined_info[idx+1].unwind_frame_index) 1990445d8f4SGreg Clayton frame_sp->SetInlineBlockID (frame_sp->GetSymbolContext (eSymbolContextBlock).block->GetID()); 2000445d8f4SGreg Clayton } 20112daf946SGreg Clayton } 20212daf946SGreg Clayton else 20312daf946SGreg Clayton { 20412daf946SGreg Clayton // We have blocks that were above an inlined function. Inlined 20512daf946SGreg Clayton // functions are represented as blocks with non-NULL inline 20612daf946SGreg Clayton // function info. Here we must reconstruct a frame by looking 20712daf946SGreg Clayton // at the block 20812daf946SGreg Clayton StackFrameSP previous_frame_sp (m_thread.GetStackFrameAtIndex (idx-1)); 20912daf946SGreg Clayton 21012daf946SGreg Clayton SymbolContext inline_sc; 21112daf946SGreg Clayton 2120445d8f4SGreg Clayton Block *inlined_parent_block = m_inlined_info[idx].block->GetInlinedParent(); 21312daf946SGreg Clayton 21412daf946SGreg Clayton if (inlined_parent_block) 21512daf946SGreg Clayton inlined_parent_block->CalculateSymbolContext (&inline_sc); 21612daf946SGreg Clayton else 21712daf946SGreg Clayton { 2180445d8f4SGreg Clayton Block *parent_block = m_inlined_info[idx].block->GetParent(); 21912daf946SGreg Clayton parent_block->CalculateSymbolContext(&inline_sc); 22012daf946SGreg Clayton } 22112daf946SGreg Clayton 22212daf946SGreg Clayton Address previous_frame_lookup_addr (previous_frame_sp->GetFrameCodeAddress()); 2230445d8f4SGreg Clayton if (previous_frame_sp->GetFrameIndex() > 0 && m_inlined_info[idx-1].block == NULL) 22412daf946SGreg Clayton previous_frame_lookup_addr.Slide (-1); 22512daf946SGreg Clayton 22612daf946SGreg Clayton AddressRange range; 2270445d8f4SGreg Clayton m_inlined_info[idx].block->GetRangeContainingAddress (previous_frame_lookup_addr, range); 22812daf946SGreg Clayton 2290445d8f4SGreg Clayton const InlineFunctionInfo* inline_info = m_inlined_info[idx].block->InlinedFunctionInfo(); 23012daf946SGreg Clayton assert (inline_info); 23112daf946SGreg Clayton inline_sc.line_entry.range.GetBaseAddress() = previous_frame_sp->GetFrameCodeAddress(); 23212daf946SGreg Clayton inline_sc.line_entry.file = inline_info->GetCallSite().GetFile(); 23312daf946SGreg Clayton inline_sc.line_entry.line = inline_info->GetCallSite().GetLine(); 23412daf946SGreg Clayton inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn(); 23512daf946SGreg Clayton 2360445d8f4SGreg Clayton StackFrameSP concrete_frame_sp (GetUnwindFrameAtIndex (m_inlined_info[idx].unwind_frame_index)); 23712daf946SGreg Clayton assert (previous_frame_sp.get()); 23812daf946SGreg Clayton 23912daf946SGreg Clayton frame_sp.reset (new StackFrame (idx, 2400445d8f4SGreg Clayton m_inlined_info[idx].unwind_frame_index, 24112daf946SGreg Clayton m_thread, 24212daf946SGreg Clayton concrete_frame_sp->GetRegisterContextSP (), 24312daf946SGreg Clayton concrete_frame_sp->GetStackID().GetCallFrameAddress(), // CFA 24412daf946SGreg Clayton range.GetBaseAddress(), 24512daf946SGreg Clayton &inline_sc)); // The symbol context for this inline frame 24612daf946SGreg Clayton 2470445d8f4SGreg Clayton if (idx + 1 < m_inlined_info.size()) 2480445d8f4SGreg Clayton { 2490445d8f4SGreg Clayton if (m_inlined_info[idx].unwind_frame_index == m_inlined_info[idx+1].unwind_frame_index) 2500445d8f4SGreg Clayton frame_sp->SetInlineBlockID (m_inlined_info[idx].block->GetID()); 2510445d8f4SGreg Clayton } 25212daf946SGreg Clayton } 25312daf946SGreg Clayton } 25412daf946SGreg Clayton else 25512daf946SGreg Clayton { 25612daf946SGreg Clayton Unwind *unwinder = m_thread.GetUnwinder (); 25712daf946SGreg Clayton if (unwinder) 25812daf946SGreg Clayton { 25912daf946SGreg Clayton addr_t pc, cfa; 26012daf946SGreg Clayton if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) 2610445d8f4SGreg Clayton frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL)); 26212daf946SGreg Clayton } 26312daf946SGreg Clayton } 26412daf946SGreg Clayton } 2650445d8f4SGreg Clayton 26612daf946SGreg Clayton if (m_show_inlined_frames) 2670445d8f4SGreg Clayton { 26812daf946SGreg Clayton SetInlineFrameAtIndex(idx, frame_sp); 2690445d8f4SGreg Clayton } 27012daf946SGreg Clayton else 2710445d8f4SGreg Clayton { 2720445d8f4SGreg Clayton SetUnwindFrameAtIndex(idx, frame_sp); 2730445d8f4SGreg Clayton } 27412daf946SGreg Clayton return frame_sp; 27512daf946SGreg Clayton 27630fdc8d8SChris Lattner } 27730fdc8d8SChris Lattner return frame_sp; 27830fdc8d8SChris Lattner } 27930fdc8d8SChris Lattner 28030fdc8d8SChris Lattner bool 2810445d8f4SGreg Clayton StackFrameList::SetUnwindFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp) 28230fdc8d8SChris Lattner { 2830445d8f4SGreg Clayton if (idx >= m_unwind_frames.size()) 2840445d8f4SGreg Clayton m_unwind_frames.resize(idx + 1); 28530fdc8d8SChris Lattner // Make sure allocation succeeded by checking bounds again 2860445d8f4SGreg Clayton if (idx < m_unwind_frames.size()) 28730fdc8d8SChris Lattner { 2880445d8f4SGreg Clayton m_unwind_frames[idx] = frame_sp; 28912daf946SGreg Clayton return true; 29012daf946SGreg Clayton } 29112daf946SGreg Clayton return false; // resize failed, out of memory? 29212daf946SGreg Clayton } 29312daf946SGreg Clayton 29412daf946SGreg Clayton bool 29512daf946SGreg Clayton StackFrameList::SetInlineFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp) 29612daf946SGreg Clayton { 29712daf946SGreg Clayton if (idx >= m_inline_frames.size()) 29812daf946SGreg Clayton m_inline_frames.resize(idx + 1); 29912daf946SGreg Clayton // Make sure allocation succeeded by checking bounds again 30012daf946SGreg Clayton if (idx < m_inline_frames.size()) 30112daf946SGreg Clayton { 30212daf946SGreg Clayton m_inline_frames[idx] = frame_sp; 30330fdc8d8SChris Lattner return true; 30430fdc8d8SChris Lattner } 30530fdc8d8SChris Lattner return false; // resize failed, out of memory? 30630fdc8d8SChris Lattner } 30730fdc8d8SChris Lattner 30830fdc8d8SChris Lattner uint32_t 309*2976d00aSJim Ingham StackFrameList::GetSelectedFrameIndex () const 31030fdc8d8SChris Lattner { 31130fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 312*2976d00aSJim Ingham return m_selected_frame_idx; 31330fdc8d8SChris Lattner } 31430fdc8d8SChris Lattner 31530fdc8d8SChris Lattner 31630fdc8d8SChris Lattner uint32_t 317*2976d00aSJim Ingham StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame) 31830fdc8d8SChris Lattner { 31930fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 32012daf946SGreg Clayton const_iterator pos; 3210445d8f4SGreg Clayton const_iterator begin = m_show_inlined_frames ? m_inline_frames.begin() : m_unwind_frames.begin(); 3220445d8f4SGreg Clayton const_iterator end = m_show_inlined_frames ? m_inline_frames.end() : m_unwind_frames.end(); 32330fdc8d8SChris Lattner for (pos = begin; pos != end; ++pos) 32430fdc8d8SChris Lattner { 32530fdc8d8SChris Lattner if (pos->get() == frame) 32630fdc8d8SChris Lattner { 327*2976d00aSJim Ingham m_selected_frame_idx = std::distance (begin, pos); 328*2976d00aSJim Ingham return m_selected_frame_idx; 32930fdc8d8SChris Lattner } 33030fdc8d8SChris Lattner } 331*2976d00aSJim Ingham m_selected_frame_idx = 0; 332*2976d00aSJim Ingham return m_selected_frame_idx; 33330fdc8d8SChris Lattner } 33430fdc8d8SChris Lattner 33530fdc8d8SChris Lattner // Mark a stack frame as the current frame using the frame index 33630fdc8d8SChris Lattner void 337*2976d00aSJim Ingham StackFrameList::SetSelectedFrameByIndex (uint32_t idx) 33830fdc8d8SChris Lattner { 33930fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 340*2976d00aSJim Ingham m_selected_frame_idx = idx; 34130fdc8d8SChris Lattner } 34230fdc8d8SChris Lattner 34330fdc8d8SChris Lattner // The thread has been run, reset the number stack frames to zero so we can 34430fdc8d8SChris Lattner // determine how many frames we have lazily. 34530fdc8d8SChris Lattner void 34630fdc8d8SChris Lattner StackFrameList::Clear () 34730fdc8d8SChris Lattner { 34830fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 3490445d8f4SGreg Clayton m_unwind_frames.clear(); 35012daf946SGreg Clayton m_inline_frames.clear(); 3510445d8f4SGreg Clayton m_inlined_info.clear(); 35230fdc8d8SChris Lattner } 35330fdc8d8SChris Lattner 35430fdc8d8SChris Lattner void 35530fdc8d8SChris Lattner StackFrameList::InvalidateFrames (uint32_t start_idx) 35630fdc8d8SChris Lattner { 35730fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 35812daf946SGreg Clayton if (m_show_inlined_frames) 35912daf946SGreg Clayton { 36012daf946SGreg Clayton Clear(); 36112daf946SGreg Clayton } 36212daf946SGreg Clayton else 36312daf946SGreg Clayton { 3640445d8f4SGreg Clayton const size_t num_frames = m_unwind_frames.size(); 36530fdc8d8SChris Lattner while (start_idx < num_frames) 36630fdc8d8SChris Lattner { 3670445d8f4SGreg Clayton m_unwind_frames[start_idx].reset(); 36830fdc8d8SChris Lattner ++start_idx; 36930fdc8d8SChris Lattner } 37030fdc8d8SChris Lattner } 37112daf946SGreg Clayton } 372