Cleaned up the inline backtrace code even more by moving all stack backtracing
functionality into StackFrameList. This will allow us to copy the previous
stack backtrace from the previous stop into another variable so we can re-use
as much as possible from the previous stack backtrace.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@112007 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Target/StackFrameList.cpp b/source/Target/StackFrameList.cpp
index 8615f71..1ebe8a4 100644
--- a/source/Target/StackFrameList.cpp
+++ b/source/Target/StackFrameList.cpp
@@ -7,12 +7,18 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/Target/StackFrameList.h"
+
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/Target/StackFrameList.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/Unwind.h"
using namespace lldb;
using namespace lldb_private;
@@ -20,9 +26,12 @@
//----------------------------------------------------------------------
// StackFrameList constructor
//----------------------------------------------------------------------
-StackFrameList::StackFrameList() :
+StackFrameList::StackFrameList(Thread &thread, bool show_inline_frames) :
+ m_thread (thread),
+ m_show_inlined_frames (show_inline_frames),
m_mutex (Mutex::eMutexTypeRecursive),
- m_frames (),
+ m_actual_frames (),
+ m_inline_frames (),
m_current_frame_idx (0)
{
}
@@ -36,43 +45,242 @@
uint32_t
-StackFrameList::GetNumFrames() const
+StackFrameList::GetNumFrames()
{
Mutex::Locker locker (m_mutex);
- return m_frames.size();
+
+ if (m_show_inlined_frames)
+ {
+ if (m_inlined_frame_info.empty())
+ {
+ Unwind *unwinder = m_thread.GetUnwinder ();
+ // 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_frame_info with
+ // the concrete frame index and inlined depth
+ const uint32_t concrete_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)
+ {
+ 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(),
+ 0,
+ m_thread.m_reg_context_sp->GetPC(),
+ NULL));
+ }
+ else
+ {
+ const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
+ assert (success);
+ frame_sp.reset (new StackFrame (m_inlined_frame_info.size(), idx, m_thread, cfa, 0, pc, NULL));
+ }
+ SetActualFrameAtIndex (idx, frame_sp);
+ Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block;
+
+ inlined_frame_info.concrete_frame_index = idx;
+ inlined_frame_info.inline_height = 0;
+ inlined_frame_info.block = block;
+ m_inlined_frame_info.push_back (inlined_frame_info);
+
+ if (block)
+ {
+ Block *inlined_block;
+ if (block->InlinedFunctionInfo())
+ inlined_block = block;
+ else
+ inlined_block = block->GetInlinedParent ();
+
+ while (inlined_block)
+ {
+ inlined_frame_info.block = inlined_block;
+ inlined_frame_info.inline_height++;
+ m_inlined_frame_info.push_back (inlined_frame_info);
+ inlined_block = inlined_block->GetInlinedParent ();
+ }
+ }
+ }
+ }
+ return m_inlined_frame_info.size();
+ }
+ else
+ {
+ if (m_actual_frames.empty())
+ m_actual_frames.resize(m_thread.GetUnwinder()->GetFrameCount());
+
+ return m_actual_frames.size();
+ }
+ return 0;
}
-// After we have determined the number of frames, we can set the count here
-// and have the frame info be generated on demand.
-void
-StackFrameList::SetNumFrames(uint32_t count)
+lldb::StackFrameSP
+StackFrameList::GetActualFrameAtIndex (uint32_t idx) const
{
- Mutex::Locker locker (m_mutex);
- return m_frames.resize(count);
+ StackFrameSP frame_sp;
+ if (idx < m_actual_frames.size())
+ frame_sp = m_actual_frames[idx];
+ return frame_sp;
}
+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;
+}
+
+
StackFrameSP
-StackFrameList::GetFrameAtIndex (uint32_t idx) const
+StackFrameList::GetFrameAtIndex (uint32_t idx)
{
StackFrameSP frame_sp;
{
Mutex::Locker locker (m_mutex);
- if (idx < m_frames.size())
- frame_sp = m_frames[idx];
+
+ if (m_show_inlined_frames)
+ {
+ frame_sp = GetInlineFrameAtIndex (idx);
+ }
+ else
+ {
+ frame_sp = GetActualFrameAtIndex (idx);
+ }
+
+ if (frame_sp.get())
+ 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)
+ {
+ // 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(),
+ 0,
+ m_thread.m_reg_context_sp->GetPC(),
+ NULL));
+ }
+ else if (idx < GetNumFrames())
+ {
+ if (m_show_inlined_frames)
+ {
+ if (m_inlined_frame_info[idx].inline_height == 0)
+ {
+ // Same as the concrete stack frame if block is NULL
+ assert (m_inlined_frame_info[idx].concrete_frame_index < m_actual_frames.size());
+ frame_sp = GetActualFrameAtIndex (m_inlined_frame_info[idx].concrete_frame_index);
+ }
+ 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_frame_info[idx].block->GetInlinedParent();
+
+ if (inlined_parent_block)
+ inlined_parent_block->CalculateSymbolContext (&inline_sc);
+ else
+ {
+ Block *parent_block = m_inlined_frame_info[idx].block->GetParent();
+ parent_block->CalculateSymbolContext(&inline_sc);
+ }
+
+ Address previous_frame_lookup_addr (previous_frame_sp->GetFrameCodeAddress());
+ if (previous_frame_sp->IsConcrete () && previous_frame_sp->GetFrameIndex() > 0)
+ previous_frame_lookup_addr.Slide (-1);
+
+ AddressRange range;
+ m_inlined_frame_info[idx].block->GetRangeContainingAddress (previous_frame_lookup_addr, range);
+
+ const InlineFunctionInfo* inline_info = m_inlined_frame_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 (GetActualFrameAtIndex (m_inlined_frame_info[idx].concrete_frame_index));
+ assert (previous_frame_sp.get());
+
+ frame_sp.reset (new StackFrame (idx,
+ m_inlined_frame_info[idx].concrete_frame_index,
+ m_thread,
+ concrete_frame_sp->GetRegisterContextSP (),
+ concrete_frame_sp->GetStackID().GetCallFrameAddress(), // CFA
+ m_inlined_frame_info[idx].inline_height, // Inline height
+ range.GetBaseAddress(),
+ &inline_sc)); // The symbol context for this inline frame
+
+ }
+ }
+ 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, 0, pc, NULL));
+ }
+ }
+ }
+ if (m_show_inlined_frames)
+ SetInlineFrameAtIndex(idx, frame_sp);
+ else
+ SetActualFrameAtIndex(idx, frame_sp);
+ return frame_sp;
+
}
return frame_sp;
}
bool
-StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
+StackFrameList::SetActualFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
{
- Mutex::Locker locker (m_mutex);
- if (idx >= m_frames.size())
- m_frames.resize(idx + 1);
+ if (idx >= m_actual_frames.size())
+ m_actual_frames.resize(idx + 1);
// Make sure allocation succeeded by checking bounds again
- if (idx < m_frames.size())
+ if (idx < m_actual_frames.size())
{
- m_frames[idx] = frame_sp;
+ m_actual_frames[idx] = frame_sp;
+ return true;
+ }
+ return false; // resize failed, out of memory?
+}
+
+bool
+StackFrameList::SetInlineFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
+{
+ if (idx >= m_inline_frames.size())
+ m_inline_frames.resize(idx + 1);
+ // Make sure allocation succeeded by checking bounds again
+ if (idx < m_inline_frames.size())
+ {
+ m_inline_frames[idx] = frame_sp;
return true;
}
return false; // resize failed, out of memory?
@@ -90,9 +298,9 @@
StackFrameList::SetCurrentFrame (lldb_private::StackFrame *frame)
{
Mutex::Locker locker (m_mutex);
- const_iterator pos,
- begin = m_frames.begin(),
- end = m_frames.end();
+ const_iterator pos;
+ const_iterator begin = m_show_inlined_frames ? m_inline_frames.begin() : m_actual_frames.begin();
+ const_iterator end = m_show_inlined_frames ? m_inline_frames.end() : m_actual_frames.end();
for (pos = begin; pos != end; ++pos)
{
if (pos->get() == frame)
@@ -119,17 +327,26 @@
StackFrameList::Clear ()
{
Mutex::Locker locker (m_mutex);
- m_frames.clear();
+ m_actual_frames.clear();
+ m_inline_frames.clear();
+ m_inlined_frame_info.clear();
}
void
StackFrameList::InvalidateFrames (uint32_t start_idx)
{
Mutex::Locker locker (m_mutex);
- size_t num_frames = m_frames.size();
- while (start_idx < num_frames)
+ if (m_show_inlined_frames)
{
- m_frames[start_idx].reset();
- ++start_idx;
+ Clear();
+ }
+ else
+ {
+ const size_t num_frames = m_actual_frames.size();
+ while (start_idx < num_frames)
+ {
+ m_actual_frames[start_idx].reset();
+ ++start_idx;
+ }
}
}
diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp
index 1f70ada..97dd52f 100644
--- a/source/Target/Thread.cpp
+++ b/source/Target/Thread.cpp
@@ -45,14 +45,11 @@
m_index_id (process.GetNextThreadIndexID ()),
m_reg_context_sp (),
m_state (eStateUnloaded),
+ m_state_mutex (Mutex::eMutexTypeRecursive),
m_plan_stack (),
m_immediate_plan_stack(),
m_completed_plan_stack(),
- m_state_mutex (Mutex::eMutexTypeRecursive),
- m_concrete_frames (),
- m_inlined_frames (),
- m_inlined_frame_info (),
- m_show_inlined_frames (true),
+ m_frames_sp (),
m_resume_signal (LLDB_INVALID_SIGNAL_NUMBER),
m_resume_state (eStateRunning),
m_unwinder_ap ()
@@ -795,200 +792,53 @@
exe_ctx.frame = NULL;
}
+
+StackFrameList &
+Thread::GetStackFrameList ()
+{
+ if (m_frames_sp.get() == NULL)
+ m_frames_sp.reset (new StackFrameList (*this, true));
+ return *m_frames_sp;
+}
+
+
+
uint32_t
Thread::GetStackFrameCount()
{
- Unwind *unwinder = GetUnwinder ();
- if (unwinder)
- {
- if (m_show_inlined_frames)
- {
- if (m_inlined_frame_info.empty())
- {
- // 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_frame_info with
- // the concrete frame index and inlined depth
- const uint32_t concrete_frame_count = unwinder->GetFrameCount();
-
- addr_t pc, cfa;
- InlinedFrameInfo inlined_frame_info;
+ return GetStackFrameList().GetNumFrames();
+}
- StackFrameSP frame_sp;
- for (uint32_t idx=0; idx<concrete_frame_count; ++idx)
- {
- if (idx == 0)
- {
- GetRegisterContext();
- assert (m_reg_context_sp.get());
- frame_sp.reset (new StackFrame (0, 0, *this, m_reg_context_sp, m_reg_context_sp->GetSP(), 0, m_reg_context_sp->GetPC(), NULL));
- }
- else
- {
- const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
- assert (success);
- frame_sp.reset (new StackFrame (m_inlined_frame_info.size(), idx, *this, cfa, 0, pc, NULL));
- }
- m_concrete_frames.SetFrameAtIndex(idx, frame_sp);
- Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block;
- inlined_frame_info.concrete_frame_index = idx;
- inlined_frame_info.inline_height = 0;
- inlined_frame_info.block = block;
- m_inlined_frame_info.push_back (inlined_frame_info);
-
- if (block)
- {
- Block *inlined_block;
- if (block->InlinedFunctionInfo())
- inlined_block = block;
- else
- inlined_block = block->GetInlinedParent ();
-
- while (inlined_block)
- {
- inlined_frame_info.block = inlined_block;
- inlined_frame_info.inline_height++;
- m_inlined_frame_info.push_back (inlined_frame_info);
- inlined_block = inlined_block->GetInlinedParent ();
- }
- }
- }
- }
- return m_inlined_frame_info.size();
- }
- else
- {
- return unwinder->GetFrameCount();
- }
- }
- return 0;
+void
+Thread::ClearStackFrames ()
+{
+ if (m_frames_sp)
+ m_frames_sp->Clear();
}
lldb::StackFrameSP
Thread::GetStackFrameAtIndex (uint32_t idx)
{
-
- StackFrameSP frame_sp;
-
- if (m_show_inlined_frames)
- frame_sp = m_inlined_frames.GetFrameAtIndex(idx);
- else
- frame_sp = m_concrete_frames.GetFrameAtIndex(idx);
-
- if (frame_sp.get())
- return frame_sp;
-
- // Don't try and fetch a frame while process is running
-// FIXME: This check isn't right because IsRunning checks the Public state, but this
-// is work you need to do - for instance in ShouldStop & friends - before the public
-// state has been changed.
-// if (m_process.IsRunning())
-// 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)
- {
- // If this is the first frame, we want to share the thread register
- // context with the stack frame at index zero.
- GetRegisterContext();
- assert (m_reg_context_sp.get());
- frame_sp.reset (new StackFrame (0, 0, *this, m_reg_context_sp, m_reg_context_sp->GetSP(), 0, m_reg_context_sp->GetPC(), NULL));
- }
- else if (idx < GetStackFrameCount())
- {
- if (m_show_inlined_frames)
- {
- if (m_inlined_frame_info[idx].inline_height == 0)
- {
- // Same as the concrete stack frame if block is NULL
- frame_sp = m_concrete_frames.GetFrameAtIndex (m_inlined_frame_info[idx].concrete_frame_index);
- }
- 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 (GetStackFrameAtIndex (idx-1));
-
- SymbolContext inline_sc;
-
- Block *inlined_parent_block = m_inlined_frame_info[idx].block->GetInlinedParent();
-
- if (inlined_parent_block)
- inlined_parent_block->CalculateSymbolContext (&inline_sc);
- else
- {
- Block *parent_block = m_inlined_frame_info[idx].block->GetParent();
- parent_block->CalculateSymbolContext(&inline_sc);
- }
-
- Address previous_frame_lookup_addr (previous_frame_sp->GetFrameCodeAddress());
- if (previous_frame_sp->IsConcrete () && previous_frame_sp->GetFrameIndex() > 0)
- previous_frame_lookup_addr.Slide (-1);
-
- AddressRange range;
- m_inlined_frame_info[idx].block->GetRangeContainingAddress (previous_frame_lookup_addr, range);
-
- const InlineFunctionInfo* inline_info = m_inlined_frame_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 (m_concrete_frames.GetFrameAtIndex (m_inlined_frame_info[idx].concrete_frame_index));
- assert (previous_frame_sp.get());
-
- frame_sp.reset (new StackFrame (idx,
- m_inlined_frame_info[idx].concrete_frame_index,
- *this,
- concrete_frame_sp->GetRegisterContextSP (),
- concrete_frame_sp->GetStackID().GetCallFrameAddress(), // CFA
- m_inlined_frame_info[idx].inline_height, // Inline height
- range.GetBaseAddress(),
- &inline_sc)); // The symbol context for this inline frame
-
- }
- }
- else
- {
- Unwind *unwinder = GetUnwinder ();
- if (unwinder)
- {
- addr_t pc, cfa;
- if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
- frame_sp.reset (new StackFrame (idx, idx, *this, cfa, 0, pc, NULL));
- }
- }
- }
- if (m_show_inlined_frames)
- m_inlined_frames.SetFrameAtIndex(idx, frame_sp);
- else
- m_concrete_frames.SetFrameAtIndex(idx, frame_sp);
- return frame_sp;
+ return StackFrameSP (GetStackFrameList().GetFrameAtIndex(idx));
}
lldb::StackFrameSP
Thread::GetCurrentFrame ()
{
- return GetStackFrameAtIndex (m_concrete_frames.GetCurrentFrameIndex());
+ return GetStackFrameAtIndex (GetStackFrameList().GetCurrentFrameIndex());
}
uint32_t
Thread::SetCurrentFrame (lldb_private::StackFrame *frame)
{
- return m_concrete_frames.SetCurrentFrame(frame);
+ return GetStackFrameList().SetCurrentFrame(frame);
}
void
Thread::SetCurrentFrameByIndex (uint32_t idx)
{
- m_concrete_frames.SetCurrentFrameByIndex(idx);
+ GetStackFrameList().SetCurrentFrameByIndex(idx);
}
void