diff options
| -rw-r--r-- | lldb/include/lldb/Target/StackFrame.h | 8 | ||||
| -rw-r--r-- | lldb/include/lldb/Target/StackFrameList.h | 27 | ||||
| -rw-r--r-- | lldb/source/Target/StackFrame.cpp | 8 | ||||
| -rw-r--r-- | lldb/source/Target/StackFrameList.cpp | 438 | ||||
| -rw-r--r-- | lldb/source/Target/Thread.cpp | 3 |
5 files changed, 264 insertions, 220 deletions
diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h index 5e3c4f14c7f..075de243bd9 100644 --- a/lldb/include/lldb/Target/StackFrame.h +++ b/lldb/include/lldb/Target/StackFrame.h @@ -129,7 +129,15 @@ protected: { m_id.SetInlineBlockID(inline_block_id); } + + void + SetFrameCodeAddress(const Address& frame_code_addr) + { + m_frame_code_addr = frame_code_addr; + } + void + SetSymbolContext (const SymbolContext& sc); private: //------------------------------------------------------------------ // For StackFrame only diff --git a/lldb/include/lldb/Target/StackFrameList.h b/lldb/include/lldb/Target/StackFrameList.h index 1ffd1043582..2822f951c7d 100644 --- a/lldb/include/lldb/Target/StackFrameList.h +++ b/lldb/include/lldb/Target/StackFrameList.h @@ -55,27 +55,14 @@ public: void InvalidateFrames (uint32_t start_idx); -protected: + + void + Dump (Stream *s); - bool - SetUnwindFrameAtIndex (uint32_t idx, lldb::StackFrameSP &frame_sp); +protected: bool - SetInlineFrameAtIndex (uint32_t idx, lldb::StackFrameSP &frame_sp); - - - lldb::StackFrameSP - GetUnwindFrameAtIndex (uint32_t idx) const; - - lldb::StackFrameSP - GetInlineFrameAtIndex (uint32_t idx) const; - - typedef struct InlinedFrameInfo - { - uint32_t unwind_frame_index; - Block *block; - } InlinedFrameInfo; - typedef std::vector<InlinedFrameInfo> InlinedFrameInfoCollection; + SetFrameAtIndex (uint32_t idx, lldb::StackFrameSP &frame_sp); //------------------------------------------------------------------ // Classes that inherit from StackFrameList can see and modify these @@ -87,9 +74,7 @@ protected: Thread &m_thread; std::auto_ptr<StackFrameList> m_prev_frames_ap; mutable Mutex m_mutex; - collection m_unwind_frames; - collection m_inline_frames; - InlinedFrameInfoCollection m_inlined_info; + collection m_frames; uint32_t m_selected_frame_idx; bool m_show_inlined_frames; diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 9c9fe99d7df..972c19a2175 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -531,3 +531,11 @@ StackFrame::Dump (Stream *strm, bool show_frame_index) m_sc.DumpStopContext(strm, &m_thread.GetProcess(), GetFrameCodeAddress(), show_module, show_inline); } + +void +StackFrame::SetSymbolContext (const SymbolContext& sc) +{ + m_sc = sc; + m_flags.Clear(eSymbolContextEverything); + m_flags.Set(m_sc.GetResolvedMask ()); +} diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp index b82e756310e..249100ab2ff 100644 --- a/lldb/source/Target/StackFrameList.cpp +++ b/lldb/source/Target/StackFrameList.cpp @@ -13,6 +13,7 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Core/StreamFile.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Function.h" #include "lldb/Target/RegisterContext.h" @@ -20,6 +21,8 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/Unwind.h" +//#define DEBUG_STACK_FRAMES 1 + using namespace lldb; using namespace lldb_private; @@ -31,8 +34,7 @@ StackFrameList::StackFrameList(Thread &thread, StackFrameList *prev_frames, bool m_prev_frames_ap (prev_frames), m_show_inlined_frames (show_inline_frames), m_mutex (Mutex::eMutexTypeRecursive), - m_unwind_frames (), - m_inline_frames (), + m_frames (), m_selected_frame_idx (0) { } @@ -50,256 +52,298 @@ StackFrameList::GetNumFrames() { Mutex::Locker locker (m_mutex); - if (m_show_inlined_frames) + if (m_frames.size() <= 1) { - if (m_inlined_info.empty()) + if (m_show_inlined_frames) { +#if defined (DEBUG_STACK_FRAMES) + StreamFile s(stdout); +#endif Unwind *unwinder = m_thread.GetUnwinder (); + addr_t pc, cfa; + // If we are going to show inlined stack frames as actual frames, // we need to calculate all concrete frames first, then iterate // through all of them and count up how many inlined functions are - // in each frame. We can then fill in m_inlined_info with - // the concrete frame index and inlined depth - const uint32_t concrete_frame_count = unwinder->GetFrameCount(); + // in each frame. + const uint32_t unwind_frame_count = unwinder->GetFrameCount(); - addr_t pc, cfa; - InlinedFrameInfo inlined_frame_info; - - StackFrameSP frame_sp; - for (uint32_t idx=0; idx<concrete_frame_count; ++idx) + StackFrameSP unwind_frame_sp; + for (uint32_t idx=0; idx<unwind_frame_count; ++idx) { if (idx == 0) { - m_thread.GetRegisterContext(); - frame_sp.reset (new StackFrame (0, - 0, - m_thread, - m_thread.m_reg_context_sp, - m_thread.m_reg_context_sp->GetSP(), - m_thread.m_reg_context_sp->GetPC(), - NULL)); + // We might have already created frame zero, only create it + // if we need to + if (m_frames.empty()) + { + m_thread.GetRegisterContext(); + unwind_frame_sp.reset (new StackFrame (m_frames.size(), + idx, + m_thread, + m_thread.m_reg_context_sp, + m_thread.m_reg_context_sp->GetSP(), + m_thread.m_reg_context_sp->GetPC(), + NULL)); + m_frames.push_back (unwind_frame_sp); + } + else + { + unwind_frame_sp = m_frames.front(); + } } else { const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc); assert (success); - frame_sp.reset (new StackFrame (m_inlined_info.size(), idx, m_thread, cfa, pc, NULL)); + unwind_frame_sp.reset (new StackFrame (m_frames.size(), idx, m_thread, cfa, pc, NULL)); + m_frames.push_back (unwind_frame_sp); } - SetUnwindFrameAtIndex (idx, frame_sp); - Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block; - - inlined_frame_info.unwind_frame_index = idx; - inlined_frame_info.block = NULL; - m_inlined_info.push_back (inlined_frame_info); + Block *block = unwind_frame_sp->GetSymbolContext (eSymbolContextBlock).block; + if (block) { - Block *inlined_block = block->GetContainingInlinedBlock(); - - if (inlined_block) + for (block = block->GetContainingInlinedBlock(); block != NULL; block = block->GetInlinedParent ()) { - frame_sp->SetInlineBlockID (inlined_block->GetID()); + SymbolContext inline_sc; + Block *parent_block = block->GetInlinedParent(); + + const bool is_inlined_frame = parent_block != NULL; + + if (parent_block == NULL) + parent_block = block->GetParent(); + + parent_block->CalculateSymbolContext (&inline_sc); + + Address previous_frame_lookup_addr (m_frames.back()->GetFrameCodeAddress()); + if (unwind_frame_sp->GetFrameIndex() > 0 && m_frames.back().get() == unwind_frame_sp.get()) + previous_frame_lookup_addr.Slide (-1); + + AddressRange range; + block->GetRangeContainingAddress (previous_frame_lookup_addr, range); + + const InlineFunctionInfo* inline_info = block->InlinedFunctionInfo(); + assert (inline_info); + inline_sc.line_entry.range.GetBaseAddress() = m_frames.back()->GetFrameCodeAddress(); + inline_sc.line_entry.file = inline_info->GetCallSite().GetFile(); + inline_sc.line_entry.line = inline_info->GetCallSite().GetLine(); + inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn(); + + StackFrameSP frame_sp(new StackFrame (m_frames.size(), + idx, + m_thread, + unwind_frame_sp->GetRegisterContextSP (), + unwind_frame_sp->GetStackID().GetCallFrameAddress(), // CFA + range.GetBaseAddress(), + &inline_sc)); // The symbol context for this inline frame + + if (is_inlined_frame) + frame_sp->SetInlineBlockID (block->GetID()); + + m_frames.push_back (frame_sp); + } + } + } + StackFrameList *prev_frames = m_prev_frames_ap.get(); + if (prev_frames) + { + StackFrameList *curr_frames = this; + +#if defined (DEBUG_STACK_FRAMES) + s.PutCString("prev_frames:\n"); + prev_frames->Dump (&s); + s.PutCString("curr_frames:\n"); + curr_frames->Dump (&s); + s.EOL(); +#endif + size_t curr_frame_num, prev_frame_num; + + for (curr_frame_num = curr_frames->m_frames.size(), prev_frame_num = prev_frames->m_frames.size(); + curr_frame_num > 0 && prev_frame_num > 0; + --curr_frame_num, --prev_frame_num) + { + const size_t curr_frame_idx = curr_frame_num-1; + const size_t prev_frame_idx = prev_frame_num-1; + StackFrameSP curr_frame_sp (curr_frames->m_frames[curr_frame_idx]); + StackFrameSP prev_frame_sp (prev_frames->m_frames[prev_frame_idx]); + +#if defined (DEBUG_STACK_FRAMES) + s.Printf("\nCurrent frame #%u ", curr_frame_idx); + if (curr_frame_sp) + curr_frame_sp->Dump (&s, true); + else + s.PutCString("NULL"); + s.Printf("\nPrevious frame #%u ", prev_frame_idx); + if (prev_frame_sp) + prev_frame_sp->Dump (&s, true); + else + s.PutCString("NULL"); + s.EOL(); +#endif + + StackFrame *curr_frame = curr_frame_sp.get(); + StackFrame *prev_frame = prev_frame_sp.get(); + + if (curr_frame == NULL || prev_frame == NULL) + break; - while (inlined_block) + // Do a quick sanity check to see if the CFA values are the same. + if (curr_frame->m_id.GetCallFrameAddress() != prev_frame->m_id.GetCallFrameAddress()) + break; + + // Now check our function or symbol + SymbolContext curr_sc (curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol)); + SymbolContext prev_sc (prev_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol)); + if (curr_sc.function && curr_sc.function == prev_sc.function) + { + // Same function + if (curr_sc.block != prev_sc.block) { - inlined_frame_info.block = inlined_block; - m_inlined_info.push_back (inlined_frame_info); - inlined_block = inlined_block->GetInlinedParent (); + // Same function different block + if (m_show_inlined_frames) + break; + else + prev_frame->SetSymbolContext (curr_frame->m_sc); } } + else if (curr_sc.symbol && curr_sc.symbol == prev_sc.symbol) + { + // Same symbol + } + else if (curr_frame->GetFrameCodeAddress() != prev_frame->GetFrameCodeAddress()) + { + // No symbols for this frame and the PC was different + break; + } + + if (curr_frame->GetFrameCodeAddress() != prev_frame->GetFrameCodeAddress()) + { +#if defined (DEBUG_STACK_FRAMES) + s.Printf("\nUpdating frame code address and symbol context in previous frame #%u to current frame #%u", prev_frame_idx, curr_frame_idx); +#endif + // We have a different code frame address, we might need to copy + // some stuff in prev_frame, yet update the code address... + prev_frame->SetFrameCodeAddress (curr_frame->GetFrameCodeAddress()); + prev_frame->SetSymbolContext (curr_frame->m_sc); + } + + curr_frames->m_frames[curr_frame_idx] = prev_frames->m_frames[prev_frame_idx]; + +#if defined (DEBUG_STACK_FRAMES) + s.Printf("\nCopying previous frame #%u to current frame #%u", prev_frame_idx, curr_frame_idx); +#endif } + // We are done with the old stack frame list, we can release it now + m_prev_frames_ap.release(); + prev_frames = NULL; } } - return m_inlined_info.size(); - } - else - { - if (m_unwind_frames.empty()) - m_unwind_frames.resize(m_thread.GetUnwinder()->GetFrameCount()); - - return m_unwind_frames.size(); + else + { + m_frames.resize(m_thread.GetUnwinder()->GetFrameCount()); + } } - return 0; + return m_frames.size(); } -lldb::StackFrameSP -StackFrameList::GetUnwindFrameAtIndex (uint32_t idx) const +void +StackFrameList::Dump (Stream *s) { - StackFrameSP frame_sp; - if (idx < m_unwind_frames.size()) - frame_sp = m_unwind_frames[idx]; - return frame_sp; -} + if (s == NULL) + return; + Mutex::Locker locker (m_mutex); -lldb::StackFrameSP -StackFrameList::GetInlineFrameAtIndex (uint32_t idx) const -{ - StackFrameSP frame_sp; - if (idx < m_inline_frames.size()) - frame_sp = m_inline_frames[idx]; - return frame_sp; + const_iterator pos, begin = m_frames.begin(), end = m_frames.end(); + for (pos = begin; pos != end; ++pos) + { + StackFrame *frame = (*pos).get(); + s->Printf("%p: ", frame); + if (frame) + frame->Dump(s, true); + else + s->Printf("frame #%u", std::distance (begin, pos)); + s->EOL(); + } + s->EOL(); } - StackFrameSP StackFrameList::GetFrameAtIndex (uint32_t idx) { StackFrameSP frame_sp; - { - Mutex::Locker locker (m_mutex); - - if (m_show_inlined_frames) - { - frame_sp = GetInlineFrameAtIndex (idx); - } - else - { - frame_sp = GetUnwindFrameAtIndex (idx); - } + Mutex::Locker locker (m_mutex); + if (idx < m_frames.size()) + frame_sp = m_frames[idx]; - if (frame_sp.get()) - return frame_sp; + if (frame_sp) + return frame_sp; - // Special case the first frame (idx == 0) so that we don't need to - // know how many stack frames there are to get it. If we need any other - // frames, then we do need to know if "idx" is a valid index. - if (idx == 0) + // Special case the first frame (idx == 0) so that we don't need to + // know how many stack frames there are to get it. If we need any other + // frames, then we do need to know if "idx" is a valid index. + if (idx == 0) + { + // If this is the first frame, we want to share the thread register + // context with the stack frame at index zero. + m_thread.GetRegisterContext(); + assert (m_thread.m_reg_context_sp.get()); + frame_sp.reset (new StackFrame (0, + 0, + m_thread, + m_thread.m_reg_context_sp, + m_thread.m_reg_context_sp->GetSP(), + m_thread.m_reg_context_sp->GetPC(), + NULL)); + + if (m_show_inlined_frames) { - // If this is the first frame, we want to share the thread register - // context with the stack frame at index zero. - m_thread.GetRegisterContext(); - assert (m_thread.m_reg_context_sp.get()); - frame_sp.reset (new StackFrame (0, - 0, - m_thread, - m_thread.m_reg_context_sp, - m_thread.m_reg_context_sp->GetSP(), - m_thread.m_reg_context_sp->GetPC(), - NULL)); + Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block; - if (m_show_inlined_frames && idx + 1 < m_inlined_info.size()) + if (block) { - if (m_inlined_info[idx].unwind_frame_index == m_inlined_info[idx+1].unwind_frame_index) - frame_sp->SetInlineBlockID (frame_sp->GetSymbolContext (eSymbolContextBlock).block->GetID()); + Block *inline_block = block->GetContainingInlinedBlock(); + if (inline_block) + frame_sp->SetInlineBlockID (inline_block->GetID()); } - } - else if (idx < GetNumFrames()) - { - if (m_show_inlined_frames) - { - if (m_inlined_info[idx].block == NULL) - { - // Same as the concrete stack frame if block is NULL - assert (m_inlined_info[idx].unwind_frame_index < m_unwind_frames.size()); - frame_sp = GetUnwindFrameAtIndex (m_inlined_info[idx].unwind_frame_index); - if (idx + 1 < m_inlined_info.size()) - { - if (m_inlined_info[idx].unwind_frame_index == m_inlined_info[idx+1].unwind_frame_index) - frame_sp->SetInlineBlockID (frame_sp->GetSymbolContext (eSymbolContextBlock).block->GetID()); - } - } - else - { - // We have blocks that were above an inlined function. Inlined - // functions are represented as blocks with non-NULL inline - // function info. Here we must reconstruct a frame by looking - // at the block - StackFrameSP previous_frame_sp (m_thread.GetStackFrameAtIndex (idx-1)); - - SymbolContext inline_sc; - - Block *inlined_parent_block = m_inlined_info[idx].block->GetInlinedParent(); - - if (inlined_parent_block) - inlined_parent_block->CalculateSymbolContext (&inline_sc); - else - { - Block *parent_block = m_inlined_info[idx].block->GetParent(); - parent_block->CalculateSymbolContext(&inline_sc); - } - - Address previous_frame_lookup_addr (previous_frame_sp->GetFrameCodeAddress()); - if (previous_frame_sp->GetFrameIndex() > 0 && m_inlined_info[idx-1].block == NULL) - previous_frame_lookup_addr.Slide (-1); - - AddressRange range; - m_inlined_info[idx].block->GetRangeContainingAddress (previous_frame_lookup_addr, range); - - const InlineFunctionInfo* inline_info = m_inlined_info[idx].block->InlinedFunctionInfo(); - assert (inline_info); - inline_sc.line_entry.range.GetBaseAddress() = previous_frame_sp->GetFrameCodeAddress(); - inline_sc.line_entry.file = inline_info->GetCallSite().GetFile(); - inline_sc.line_entry.line = inline_info->GetCallSite().GetLine(); - inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn(); - - StackFrameSP concrete_frame_sp (GetUnwindFrameAtIndex (m_inlined_info[idx].unwind_frame_index)); - assert (previous_frame_sp.get()); - - frame_sp.reset (new StackFrame (idx, - m_inlined_info[idx].unwind_frame_index, - m_thread, - concrete_frame_sp->GetRegisterContextSP (), - concrete_frame_sp->GetStackID().GetCallFrameAddress(), // CFA - range.GetBaseAddress(), - &inline_sc)); // The symbol context for this inline frame - - if (idx + 1 < m_inlined_info.size()) - { - if (m_inlined_info[idx].unwind_frame_index == m_inlined_info[idx+1].unwind_frame_index) - frame_sp->SetInlineBlockID (m_inlined_info[idx].block->GetID()); - } - } - } - else - { - Unwind *unwinder = m_thread.GetUnwinder (); - if (unwinder) - { - addr_t pc, cfa; - if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) - frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL)); - } - } - } - + SetFrameAtIndex(idx, frame_sp); + } + else if (idx < GetNumFrames()) + { if (m_show_inlined_frames) { - SetInlineFrameAtIndex(idx, frame_sp); + // When inline frames are enabled we cache up all frames in GetNumFrames() + frame_sp = m_frames[idx]; } else { - SetUnwindFrameAtIndex(idx, frame_sp); + Unwind *unwinder = m_thread.GetUnwinder (); + if (unwinder) + { + addr_t pc, cfa; + if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) + { + frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL)); + SetFrameAtIndex(idx, frame_sp); + } + } } - return frame_sp; } return frame_sp; } -bool -StackFrameList::SetUnwindFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp) -{ - if (idx >= m_unwind_frames.size()) - m_unwind_frames.resize(idx + 1); - // Make sure allocation succeeded by checking bounds again - if (idx < m_unwind_frames.size()) - { - m_unwind_frames[idx] = frame_sp; - return true; - } - return false; // resize failed, out of memory? -} bool -StackFrameList::SetInlineFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp) +StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp) { - if (idx >= m_inline_frames.size()) - m_inline_frames.resize(idx + 1); + if (idx >= m_frames.size()) + m_frames.resize(idx + 1); // Make sure allocation succeeded by checking bounds again - if (idx < m_inline_frames.size()) + if (idx < m_frames.size()) { - m_inline_frames[idx] = frame_sp; + m_frames[idx] = frame_sp; return true; } return false; // resize failed, out of memory? @@ -318,8 +362,8 @@ StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame) { Mutex::Locker locker (m_mutex); const_iterator pos; - const_iterator begin = m_show_inlined_frames ? m_inline_frames.begin() : m_unwind_frames.begin(); - const_iterator end = m_show_inlined_frames ? m_inline_frames.end() : m_unwind_frames.end(); + const_iterator begin = m_frames.begin(); + const_iterator end = m_frames.end(); for (pos = begin; pos != end; ++pos) { if (pos->get() == frame) @@ -346,9 +390,7 @@ void StackFrameList::Clear () { Mutex::Locker locker (m_mutex); - m_unwind_frames.clear(); - m_inline_frames.clear(); - m_inlined_info.clear(); + m_frames.clear(); } void @@ -361,10 +403,10 @@ StackFrameList::InvalidateFrames (uint32_t start_idx) } else { - const size_t num_frames = m_unwind_frames.size(); + const size_t num_frames = m_frames.size(); while (start_idx < num_frames) { - m_unwind_frames[start_idx].reset(); + m_frames[start_idx].reset(); ++start_idx; } } diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index 73d2dbaa42e..5a1e1ddde88 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -813,7 +813,8 @@ Thread::GetStackFrameCount() void Thread::ClearStackFrames () { - m_prev_frames_ap = m_curr_frames_ap; + if (m_curr_frames_ap.get()) + m_prev_frames_ap = m_curr_frames_ap; } lldb::StackFrameSP |

