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 10*12daf946SGreg Clayton #include "lldb/Target/StackFrameList.h" 11*12daf946SGreg Clayton 1230fdc8d8SChris Lattner // C Includes 1330fdc8d8SChris Lattner // C++ Includes 1430fdc8d8SChris Lattner // Other libraries and framework includes 1530fdc8d8SChris Lattner // Project includes 16*12daf946SGreg Clayton #include "lldb/Symbol/Block.h" 17*12daf946SGreg Clayton #include "lldb/Symbol/Function.h" 18*12daf946SGreg Clayton #include "lldb/Target/RegisterContext.h" 1930fdc8d8SChris Lattner #include "lldb/Target/StackFrame.h" 20*12daf946SGreg Clayton #include "lldb/Target/Thread.h" 21*12daf946SGreg 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 //---------------------------------------------------------------------- 29*12daf946SGreg Clayton StackFrameList::StackFrameList(Thread &thread, bool show_inline_frames) : 30*12daf946SGreg Clayton m_thread (thread), 31*12daf946SGreg Clayton m_show_inlined_frames (show_inline_frames), 3230fdc8d8SChris Lattner m_mutex (Mutex::eMutexTypeRecursive), 33*12daf946SGreg Clayton m_actual_frames (), 34*12daf946SGreg Clayton m_inline_frames (), 3530fdc8d8SChris Lattner m_current_frame_idx (0) 3630fdc8d8SChris Lattner { 3730fdc8d8SChris Lattner } 3830fdc8d8SChris Lattner 3930fdc8d8SChris Lattner //---------------------------------------------------------------------- 4030fdc8d8SChris Lattner // Destructor 4130fdc8d8SChris Lattner //---------------------------------------------------------------------- 4230fdc8d8SChris Lattner StackFrameList::~StackFrameList() 4330fdc8d8SChris Lattner { 4430fdc8d8SChris Lattner } 4530fdc8d8SChris Lattner 4630fdc8d8SChris Lattner 4730fdc8d8SChris Lattner uint32_t 48*12daf946SGreg Clayton StackFrameList::GetNumFrames() 4930fdc8d8SChris Lattner { 5030fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 51*12daf946SGreg Clayton 52*12daf946SGreg Clayton if (m_show_inlined_frames) 53*12daf946SGreg Clayton { 54*12daf946SGreg Clayton if (m_inlined_frame_info.empty()) 55*12daf946SGreg Clayton { 56*12daf946SGreg Clayton Unwind *unwinder = m_thread.GetUnwinder (); 57*12daf946SGreg Clayton // If we are going to show inlined stack frames as actual frames, 58*12daf946SGreg Clayton // we need to calculate all concrete frames first, then iterate 59*12daf946SGreg Clayton // through all of them and count up how many inlined functions are 60*12daf946SGreg Clayton // in each frame. We can then fill in m_inlined_frame_info with 61*12daf946SGreg Clayton // the concrete frame index and inlined depth 62*12daf946SGreg Clayton const uint32_t concrete_frame_count = unwinder->GetFrameCount(); 63*12daf946SGreg Clayton 64*12daf946SGreg Clayton addr_t pc, cfa; 65*12daf946SGreg Clayton InlinedFrameInfo inlined_frame_info; 66*12daf946SGreg Clayton 67*12daf946SGreg Clayton StackFrameSP frame_sp; 68*12daf946SGreg Clayton for (uint32_t idx=0; idx<concrete_frame_count; ++idx) 69*12daf946SGreg Clayton { 70*12daf946SGreg Clayton if (idx == 0) 71*12daf946SGreg Clayton { 72*12daf946SGreg Clayton m_thread.GetRegisterContext(); 73*12daf946SGreg Clayton frame_sp.reset (new StackFrame (0, 74*12daf946SGreg Clayton 0, 75*12daf946SGreg Clayton m_thread, 76*12daf946SGreg Clayton m_thread.m_reg_context_sp, 77*12daf946SGreg Clayton m_thread.m_reg_context_sp->GetSP(), 78*12daf946SGreg Clayton 0, 79*12daf946SGreg Clayton m_thread.m_reg_context_sp->GetPC(), 80*12daf946SGreg Clayton NULL)); 81*12daf946SGreg Clayton } 82*12daf946SGreg Clayton else 83*12daf946SGreg Clayton { 84*12daf946SGreg Clayton const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc); 85*12daf946SGreg Clayton assert (success); 86*12daf946SGreg Clayton frame_sp.reset (new StackFrame (m_inlined_frame_info.size(), idx, m_thread, cfa, 0, pc, NULL)); 87*12daf946SGreg Clayton } 88*12daf946SGreg Clayton SetActualFrameAtIndex (idx, frame_sp); 89*12daf946SGreg Clayton Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block; 90*12daf946SGreg Clayton 91*12daf946SGreg Clayton inlined_frame_info.concrete_frame_index = idx; 92*12daf946SGreg Clayton inlined_frame_info.inline_height = 0; 93*12daf946SGreg Clayton inlined_frame_info.block = block; 94*12daf946SGreg Clayton m_inlined_frame_info.push_back (inlined_frame_info); 95*12daf946SGreg Clayton 96*12daf946SGreg Clayton if (block) 97*12daf946SGreg Clayton { 98*12daf946SGreg Clayton Block *inlined_block; 99*12daf946SGreg Clayton if (block->InlinedFunctionInfo()) 100*12daf946SGreg Clayton inlined_block = block; 101*12daf946SGreg Clayton else 102*12daf946SGreg Clayton inlined_block = block->GetInlinedParent (); 103*12daf946SGreg Clayton 104*12daf946SGreg Clayton while (inlined_block) 105*12daf946SGreg Clayton { 106*12daf946SGreg Clayton inlined_frame_info.block = inlined_block; 107*12daf946SGreg Clayton inlined_frame_info.inline_height++; 108*12daf946SGreg Clayton m_inlined_frame_info.push_back (inlined_frame_info); 109*12daf946SGreg Clayton inlined_block = inlined_block->GetInlinedParent (); 110*12daf946SGreg Clayton } 111*12daf946SGreg Clayton } 112*12daf946SGreg Clayton } 113*12daf946SGreg Clayton } 114*12daf946SGreg Clayton return m_inlined_frame_info.size(); 115*12daf946SGreg Clayton } 116*12daf946SGreg Clayton else 117*12daf946SGreg Clayton { 118*12daf946SGreg Clayton if (m_actual_frames.empty()) 119*12daf946SGreg Clayton m_actual_frames.resize(m_thread.GetUnwinder()->GetFrameCount()); 120*12daf946SGreg Clayton 121*12daf946SGreg Clayton return m_actual_frames.size(); 122*12daf946SGreg Clayton } 123*12daf946SGreg Clayton return 0; 12430fdc8d8SChris Lattner } 12530fdc8d8SChris Lattner 126*12daf946SGreg Clayton lldb::StackFrameSP 127*12daf946SGreg Clayton StackFrameList::GetActualFrameAtIndex (uint32_t idx) const 12830fdc8d8SChris Lattner { 129*12daf946SGreg Clayton StackFrameSP frame_sp; 130*12daf946SGreg Clayton if (idx < m_actual_frames.size()) 131*12daf946SGreg Clayton frame_sp = m_actual_frames[idx]; 132*12daf946SGreg Clayton return frame_sp; 13330fdc8d8SChris Lattner } 13430fdc8d8SChris Lattner 135*12daf946SGreg Clayton lldb::StackFrameSP 136*12daf946SGreg Clayton StackFrameList::GetInlineFrameAtIndex (uint32_t idx) const 137*12daf946SGreg Clayton { 138*12daf946SGreg Clayton StackFrameSP frame_sp; 139*12daf946SGreg Clayton if (idx < m_inline_frames.size()) 140*12daf946SGreg Clayton frame_sp = m_inline_frames[idx]; 141*12daf946SGreg Clayton return frame_sp; 142*12daf946SGreg Clayton } 143*12daf946SGreg Clayton 144*12daf946SGreg Clayton 14530fdc8d8SChris Lattner StackFrameSP 146*12daf946SGreg Clayton StackFrameList::GetFrameAtIndex (uint32_t idx) 14730fdc8d8SChris Lattner { 14830fdc8d8SChris Lattner StackFrameSP frame_sp; 14930fdc8d8SChris Lattner { 15030fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 151*12daf946SGreg Clayton 152*12daf946SGreg Clayton if (m_show_inlined_frames) 153*12daf946SGreg Clayton { 154*12daf946SGreg Clayton frame_sp = GetInlineFrameAtIndex (idx); 155*12daf946SGreg Clayton } 156*12daf946SGreg Clayton else 157*12daf946SGreg Clayton { 158*12daf946SGreg Clayton frame_sp = GetActualFrameAtIndex (idx); 159*12daf946SGreg Clayton } 160*12daf946SGreg Clayton 161*12daf946SGreg Clayton if (frame_sp.get()) 162*12daf946SGreg Clayton return frame_sp; 163*12daf946SGreg Clayton 164*12daf946SGreg Clayton // Special case the first frame (idx == 0) so that we don't need to 165*12daf946SGreg Clayton // know how many stack frames there are to get it. If we need any other 166*12daf946SGreg Clayton // frames, then we do need to know if "idx" is a valid index. 167*12daf946SGreg Clayton if (idx == 0) 168*12daf946SGreg Clayton { 169*12daf946SGreg Clayton // If this is the first frame, we want to share the thread register 170*12daf946SGreg Clayton // context with the stack frame at index zero. 171*12daf946SGreg Clayton m_thread.GetRegisterContext(); 172*12daf946SGreg Clayton assert (m_thread.m_reg_context_sp.get()); 173*12daf946SGreg Clayton frame_sp.reset (new StackFrame (0, 174*12daf946SGreg Clayton 0, 175*12daf946SGreg Clayton m_thread, 176*12daf946SGreg Clayton m_thread.m_reg_context_sp, 177*12daf946SGreg Clayton m_thread.m_reg_context_sp->GetSP(), 178*12daf946SGreg Clayton 0, 179*12daf946SGreg Clayton m_thread.m_reg_context_sp->GetPC(), 180*12daf946SGreg Clayton NULL)); 181*12daf946SGreg Clayton } 182*12daf946SGreg Clayton else if (idx < GetNumFrames()) 183*12daf946SGreg Clayton { 184*12daf946SGreg Clayton if (m_show_inlined_frames) 185*12daf946SGreg Clayton { 186*12daf946SGreg Clayton if (m_inlined_frame_info[idx].inline_height == 0) 187*12daf946SGreg Clayton { 188*12daf946SGreg Clayton // Same as the concrete stack frame if block is NULL 189*12daf946SGreg Clayton assert (m_inlined_frame_info[idx].concrete_frame_index < m_actual_frames.size()); 190*12daf946SGreg Clayton frame_sp = GetActualFrameAtIndex (m_inlined_frame_info[idx].concrete_frame_index); 191*12daf946SGreg Clayton } 192*12daf946SGreg Clayton else 193*12daf946SGreg Clayton { 194*12daf946SGreg Clayton // We have blocks that were above an inlined function. Inlined 195*12daf946SGreg Clayton // functions are represented as blocks with non-NULL inline 196*12daf946SGreg Clayton // function info. Here we must reconstruct a frame by looking 197*12daf946SGreg Clayton // at the block 198*12daf946SGreg Clayton StackFrameSP previous_frame_sp (m_thread.GetStackFrameAtIndex (idx-1)); 199*12daf946SGreg Clayton 200*12daf946SGreg Clayton SymbolContext inline_sc; 201*12daf946SGreg Clayton 202*12daf946SGreg Clayton Block *inlined_parent_block = m_inlined_frame_info[idx].block->GetInlinedParent(); 203*12daf946SGreg Clayton 204*12daf946SGreg Clayton if (inlined_parent_block) 205*12daf946SGreg Clayton inlined_parent_block->CalculateSymbolContext (&inline_sc); 206*12daf946SGreg Clayton else 207*12daf946SGreg Clayton { 208*12daf946SGreg Clayton Block *parent_block = m_inlined_frame_info[idx].block->GetParent(); 209*12daf946SGreg Clayton parent_block->CalculateSymbolContext(&inline_sc); 210*12daf946SGreg Clayton } 211*12daf946SGreg Clayton 212*12daf946SGreg Clayton Address previous_frame_lookup_addr (previous_frame_sp->GetFrameCodeAddress()); 213*12daf946SGreg Clayton if (previous_frame_sp->IsConcrete () && previous_frame_sp->GetFrameIndex() > 0) 214*12daf946SGreg Clayton previous_frame_lookup_addr.Slide (-1); 215*12daf946SGreg Clayton 216*12daf946SGreg Clayton AddressRange range; 217*12daf946SGreg Clayton m_inlined_frame_info[idx].block->GetRangeContainingAddress (previous_frame_lookup_addr, range); 218*12daf946SGreg Clayton 219*12daf946SGreg Clayton const InlineFunctionInfo* inline_info = m_inlined_frame_info[idx].block->InlinedFunctionInfo(); 220*12daf946SGreg Clayton assert (inline_info); 221*12daf946SGreg Clayton inline_sc.line_entry.range.GetBaseAddress() = previous_frame_sp->GetFrameCodeAddress(); 222*12daf946SGreg Clayton inline_sc.line_entry.file = inline_info->GetCallSite().GetFile(); 223*12daf946SGreg Clayton inline_sc.line_entry.line = inline_info->GetCallSite().GetLine(); 224*12daf946SGreg Clayton inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn(); 225*12daf946SGreg Clayton 226*12daf946SGreg Clayton StackFrameSP concrete_frame_sp (GetActualFrameAtIndex (m_inlined_frame_info[idx].concrete_frame_index)); 227*12daf946SGreg Clayton assert (previous_frame_sp.get()); 228*12daf946SGreg Clayton 229*12daf946SGreg Clayton frame_sp.reset (new StackFrame (idx, 230*12daf946SGreg Clayton m_inlined_frame_info[idx].concrete_frame_index, 231*12daf946SGreg Clayton m_thread, 232*12daf946SGreg Clayton concrete_frame_sp->GetRegisterContextSP (), 233*12daf946SGreg Clayton concrete_frame_sp->GetStackID().GetCallFrameAddress(), // CFA 234*12daf946SGreg Clayton m_inlined_frame_info[idx].inline_height, // Inline height 235*12daf946SGreg Clayton range.GetBaseAddress(), 236*12daf946SGreg Clayton &inline_sc)); // The symbol context for this inline frame 237*12daf946SGreg Clayton 238*12daf946SGreg Clayton } 239*12daf946SGreg Clayton } 240*12daf946SGreg Clayton else 241*12daf946SGreg Clayton { 242*12daf946SGreg Clayton Unwind *unwinder = m_thread.GetUnwinder (); 243*12daf946SGreg Clayton if (unwinder) 244*12daf946SGreg Clayton { 245*12daf946SGreg Clayton addr_t pc, cfa; 246*12daf946SGreg Clayton if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) 247*12daf946SGreg Clayton frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, 0, pc, NULL)); 248*12daf946SGreg Clayton } 249*12daf946SGreg Clayton } 250*12daf946SGreg Clayton } 251*12daf946SGreg Clayton if (m_show_inlined_frames) 252*12daf946SGreg Clayton SetInlineFrameAtIndex(idx, frame_sp); 253*12daf946SGreg Clayton else 254*12daf946SGreg Clayton SetActualFrameAtIndex(idx, frame_sp); 255*12daf946SGreg Clayton return frame_sp; 256*12daf946SGreg Clayton 25730fdc8d8SChris Lattner } 25830fdc8d8SChris Lattner return frame_sp; 25930fdc8d8SChris Lattner } 26030fdc8d8SChris Lattner 26130fdc8d8SChris Lattner bool 262*12daf946SGreg Clayton StackFrameList::SetActualFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp) 26330fdc8d8SChris Lattner { 264*12daf946SGreg Clayton if (idx >= m_actual_frames.size()) 265*12daf946SGreg Clayton m_actual_frames.resize(idx + 1); 26630fdc8d8SChris Lattner // Make sure allocation succeeded by checking bounds again 267*12daf946SGreg Clayton if (idx < m_actual_frames.size()) 26830fdc8d8SChris Lattner { 269*12daf946SGreg Clayton m_actual_frames[idx] = frame_sp; 270*12daf946SGreg Clayton return true; 271*12daf946SGreg Clayton } 272*12daf946SGreg Clayton return false; // resize failed, out of memory? 273*12daf946SGreg Clayton } 274*12daf946SGreg Clayton 275*12daf946SGreg Clayton bool 276*12daf946SGreg Clayton StackFrameList::SetInlineFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp) 277*12daf946SGreg Clayton { 278*12daf946SGreg Clayton if (idx >= m_inline_frames.size()) 279*12daf946SGreg Clayton m_inline_frames.resize(idx + 1); 280*12daf946SGreg Clayton // Make sure allocation succeeded by checking bounds again 281*12daf946SGreg Clayton if (idx < m_inline_frames.size()) 282*12daf946SGreg Clayton { 283*12daf946SGreg Clayton m_inline_frames[idx] = frame_sp; 28430fdc8d8SChris Lattner return true; 28530fdc8d8SChris Lattner } 28630fdc8d8SChris Lattner return false; // resize failed, out of memory? 28730fdc8d8SChris Lattner } 28830fdc8d8SChris Lattner 28930fdc8d8SChris Lattner uint32_t 29030fdc8d8SChris Lattner StackFrameList::GetCurrentFrameIndex () const 29130fdc8d8SChris Lattner { 29230fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 29330fdc8d8SChris Lattner return m_current_frame_idx; 29430fdc8d8SChris Lattner } 29530fdc8d8SChris Lattner 29630fdc8d8SChris Lattner 29730fdc8d8SChris Lattner uint32_t 29830fdc8d8SChris Lattner StackFrameList::SetCurrentFrame (lldb_private::StackFrame *frame) 29930fdc8d8SChris Lattner { 30030fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 301*12daf946SGreg Clayton const_iterator pos; 302*12daf946SGreg Clayton const_iterator begin = m_show_inlined_frames ? m_inline_frames.begin() : m_actual_frames.begin(); 303*12daf946SGreg Clayton const_iterator end = m_show_inlined_frames ? m_inline_frames.end() : m_actual_frames.end(); 30430fdc8d8SChris Lattner for (pos = begin; pos != end; ++pos) 30530fdc8d8SChris Lattner { 30630fdc8d8SChris Lattner if (pos->get() == frame) 30730fdc8d8SChris Lattner { 30830fdc8d8SChris Lattner m_current_frame_idx = std::distance (begin, pos); 30930fdc8d8SChris Lattner return m_current_frame_idx; 31030fdc8d8SChris Lattner } 31130fdc8d8SChris Lattner } 31230fdc8d8SChris Lattner m_current_frame_idx = 0; 31330fdc8d8SChris Lattner return m_current_frame_idx; 31430fdc8d8SChris Lattner } 31530fdc8d8SChris Lattner 31630fdc8d8SChris Lattner // Mark a stack frame as the current frame using the frame index 31730fdc8d8SChris Lattner void 31830fdc8d8SChris Lattner StackFrameList::SetCurrentFrameByIndex (uint32_t idx) 31930fdc8d8SChris Lattner { 32030fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 32130fdc8d8SChris Lattner m_current_frame_idx = idx; 32230fdc8d8SChris Lattner } 32330fdc8d8SChris Lattner 32430fdc8d8SChris Lattner // The thread has been run, reset the number stack frames to zero so we can 32530fdc8d8SChris Lattner // determine how many frames we have lazily. 32630fdc8d8SChris Lattner void 32730fdc8d8SChris Lattner StackFrameList::Clear () 32830fdc8d8SChris Lattner { 32930fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 330*12daf946SGreg Clayton m_actual_frames.clear(); 331*12daf946SGreg Clayton m_inline_frames.clear(); 332*12daf946SGreg Clayton m_inlined_frame_info.clear(); 33330fdc8d8SChris Lattner } 33430fdc8d8SChris Lattner 33530fdc8d8SChris Lattner void 33630fdc8d8SChris Lattner StackFrameList::InvalidateFrames (uint32_t start_idx) 33730fdc8d8SChris Lattner { 33830fdc8d8SChris Lattner Mutex::Locker locker (m_mutex); 339*12daf946SGreg Clayton if (m_show_inlined_frames) 340*12daf946SGreg Clayton { 341*12daf946SGreg Clayton Clear(); 342*12daf946SGreg Clayton } 343*12daf946SGreg Clayton else 344*12daf946SGreg Clayton { 345*12daf946SGreg Clayton const size_t num_frames = m_actual_frames.size(); 34630fdc8d8SChris Lattner while (start_idx < num_frames) 34730fdc8d8SChris Lattner { 348*12daf946SGreg Clayton m_actual_frames[start_idx].reset(); 34930fdc8d8SChris Lattner ++start_idx; 35030fdc8d8SChris Lattner } 35130fdc8d8SChris Lattner } 352*12daf946SGreg Clayton } 353