summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp')
-rw-r--r--lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp141
1 files changed, 141 insertions, 0 deletions
diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
new file mode 100644
index 00000000000..6d4c345e28e
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -0,0 +1,141 @@
+//===-- UnwindLLDB.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/FuncUnwinders.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Utility/ArchDefaultUnwindPlan.h"
+#include "UnwindLLDB.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Core/Log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+UnwindLLDB::UnwindLLDB (Thread &thread) :
+ Unwind (thread),
+ m_frames()
+{
+}
+
+uint32_t
+UnwindLLDB::GetFrameCount()
+{
+ Log *log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND);
+ if (m_frames.empty())
+ {
+ // First, set up the 0th (initial) frame
+ Cursor first_cursor;
+ RegisterContextSP no_frame; // an empty shared pointer
+ RegisterContextLLDB *first_register_ctx = new RegisterContextLLDB(m_thread, no_frame, first_cursor.sctx, 0);
+ if (!first_register_ctx->IsValid())
+ {
+ delete first_register_ctx;
+ return 0;
+ }
+ if (!first_register_ctx->GetCFA (first_cursor.cfa))
+ {
+ delete first_register_ctx;
+ return 0;
+ }
+ if (!first_register_ctx->GetPC (first_cursor.start_pc))
+ {
+ delete first_register_ctx;
+ return 0;
+ }
+ // Reuse the StackFrame provided by the processor native machine context for the first frame
+ first_register_ctx->SetStackFrame (m_thread.GetStackFrameAtIndex(0).get());
+ RegisterContextSP temp_rcs(first_register_ctx);
+ first_cursor.reg_ctx = temp_rcs;
+ m_frames.push_back (first_cursor);
+
+ // Now walk up the rest of the stack
+ while (1)
+ {
+ Cursor cursor;
+ RegisterContextLLDB *register_ctx;
+ int cur_idx = m_frames.size ();
+ register_ctx = new RegisterContextLLDB (m_thread, m_frames[cur_idx - 1].reg_ctx, cursor.sctx, cur_idx);
+ if (!register_ctx->IsValid())
+ {
+ delete register_ctx;
+ if (log)
+ {
+ log->Printf("%*sThread %u Frame %d invalid RegisterContext for this frame, stopping stack walk",
+ cur_idx, "", m_thread.GetIndexID(), cur_idx);
+ }
+ break;
+ }
+ if (!register_ctx->GetCFA (cursor.cfa))
+ {
+ delete register_ctx;
+ if (log)
+ {
+ log->Printf("%*sThread %u Frame %d did not get CFA for this frame, stopping stack walk",
+ cur_idx, "", m_thread.GetIndexID(), cur_idx);
+ }
+ break;
+ }
+ if (!register_ctx->GetPC (cursor.start_pc))
+ {
+ delete register_ctx;
+ if (log)
+ {
+ log->Printf("%*sThread %u Frame %d did not get PC for this frame, stopping stack walk",
+ cur_idx, "", m_thread.GetIndexID(), cur_idx);
+ }
+ break;
+ }
+ RegisterContextSP temp_rcs(register_ctx);
+ StackFrame *frame = new StackFrame(cur_idx, cur_idx, m_thread, temp_rcs, cursor.cfa, cursor.start_pc, &cursor.sctx);
+ register_ctx->SetStackFrame (frame);
+ cursor.reg_ctx = temp_rcs;
+ m_frames.push_back (cursor);
+ }
+ }
+ return m_frames.size ();
+}
+
+bool
+UnwindLLDB::GetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
+{
+ // FIXME don't get the entire stack if it isn't needed.
+ if (m_frames.size() == 0)
+ GetFrameCount();
+
+ if (idx < m_frames.size ())
+ {
+ cfa = m_frames[idx].cfa;
+ pc = m_frames[idx].start_pc;
+ return true;
+ }
+ return false;
+}
+
+RegisterContext *
+UnwindLLDB::CreateRegisterContextForFrame (StackFrame *frame)
+{
+ uint32_t idx = frame->GetFrameIndex ();
+
+ // FIXME don't get the entire stack if it isn't needed.
+ if (m_frames.size() == 0)
+ GetFrameCount();
+
+ if (idx == 0)
+ {
+ return m_thread.GetRegisterContext();
+ }
+ if (idx < m_frames.size ())
+ return m_frames[idx].reg_ctx.get();
+ return NULL;
+}
OpenPOWER on IntegriCloud