summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
diff options
context:
space:
mode:
authorJason Molenda <jmolenda@apple.com>2010-10-25 11:12:07 +0000
committerJason Molenda <jmolenda@apple.com>2010-10-25 11:12:07 +0000
commitab4f1924db7175fd04c78034684ff854d3b58255 (patch)
tree56ee59a62fe3eadb6ab70ea9e989950a0045f10d /lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
parent829b21fb02948e73a08bb3938153e0884a5f0b6d (diff)
downloadbcm5719-llvm-ab4f1924db7175fd04c78034684ff854d3b58255.tar.gz
bcm5719-llvm-ab4f1924db7175fd04c78034684ff854d3b58255.zip
Check in the native lldb unwinder.
Not yet enabled as the default unwinder but there are no known backtrace problems with the code at this point. Added 'log enable lldb unwind' to help diagnose backtrace problems; this output needs a little refining but it's a good first step. eh_frame information is currently read unconditionally - the code is structured to allow this to be delayed until it's actually needed. There is a performance hit when you have to parse the eh_frame information for any largeish executable/library so it's necessary to avoid if possible. It's confusing having both the UnwindPlan::RegisterLocation struct and the RegisterConextLLDB::RegisterLocation struct, I need to rename one of them. The writing of registers isn't done in the RegisterConextLLDB subclass yet; neither is the running of complex DWARF expressions from eh_frame (e.g. used for _sigtramp on Mac OS X). llvm-svn: 117256
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