blob: 5847718d4e2e355dde9cf346d2a0a51ded9901c1 [file] [log] [blame]
Jason Molenda8280cbe2010-10-25 11:12:07 +00001//===-- UnwindLLDB.cpp -------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Target/Thread.h"
11#include "lldb/Target/Target.h"
12#include "lldb/Target/Process.h"
13#include "lldb/Target/RegisterContext.h"
14#include "lldb/Core/Module.h"
15#include "lldb/Symbol/FuncUnwinders.h"
16#include "lldb/Symbol/Function.h"
17#include "lldb/Utility/ArchDefaultUnwindPlan.h"
18#include "UnwindLLDB.h"
19#include "lldb/Symbol/UnwindPlan.h"
20#include "lldb/Core/Log.h"
21
22using namespace lldb;
23using namespace lldb_private;
24
25UnwindLLDB::UnwindLLDB (Thread &thread) :
26 Unwind (thread),
27 m_frames()
28{
29}
30
31uint32_t
32UnwindLLDB::GetFrameCount()
33{
Greg Claytone005f2c2010-11-06 01:53:30 +000034 LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
Jason Molenda8280cbe2010-10-25 11:12:07 +000035 if (m_frames.empty())
36 {
37 // First, set up the 0th (initial) frame
Jason Molendaa6b71de2010-11-04 09:40:56 +000038 CursorSP first_cursor_sp(new Cursor ());
Jason Molenda8280cbe2010-10-25 11:12:07 +000039 RegisterContextSP no_frame; // an empty shared pointer
Jason Molenda800d11d2010-11-04 00:53:20 +000040 RegisterContextLLDB *first_register_ctx = new RegisterContextLLDB(m_thread, no_frame, first_cursor_sp->sctx, 0);
Jason Molenda8280cbe2010-10-25 11:12:07 +000041 if (!first_register_ctx->IsValid())
42 {
43 delete first_register_ctx;
44 return 0;
45 }
Jason Molenda800d11d2010-11-04 00:53:20 +000046 if (!first_register_ctx->GetCFA (first_cursor_sp->cfa))
Jason Molenda8280cbe2010-10-25 11:12:07 +000047 {
48 delete first_register_ctx;
49 return 0;
50 }
Jason Molenda800d11d2010-11-04 00:53:20 +000051 if (!first_register_ctx->GetPC (first_cursor_sp->start_pc))
Jason Molenda8280cbe2010-10-25 11:12:07 +000052 {
53 delete first_register_ctx;
54 return 0;
55 }
56 // Reuse the StackFrame provided by the processor native machine context for the first frame
57 first_register_ctx->SetStackFrame (m_thread.GetStackFrameAtIndex(0).get());
Jason Molendaa6b71de2010-11-04 09:40:56 +000058 RegisterContextSP first_register_ctx_sp(first_register_ctx);
59 first_cursor_sp->reg_ctx = first_register_ctx_sp;
Jason Molenda800d11d2010-11-04 00:53:20 +000060 m_frames.push_back (first_cursor_sp);
Jason Molenda8280cbe2010-10-25 11:12:07 +000061
62 // Now walk up the rest of the stack
63 while (1)
64 {
Jason Molendaa6b71de2010-11-04 09:40:56 +000065 CursorSP cursor_sp(new Cursor ());
Jason Molenda8280cbe2010-10-25 11:12:07 +000066 RegisterContextLLDB *register_ctx;
Jason Molendaa6b71de2010-11-04 09:40:56 +000067 uint32_t cur_idx = m_frames.size ();
Jason Molenda800d11d2010-11-04 00:53:20 +000068 register_ctx = new RegisterContextLLDB (m_thread, m_frames[cur_idx - 1]->reg_ctx, cursor_sp->sctx, cur_idx);
Jason Molenda8280cbe2010-10-25 11:12:07 +000069 if (!register_ctx->IsValid())
70 {
71 delete register_ctx;
72 if (log)
73 {
Jason Molendaa2c269c2010-10-26 00:47:17 +000074 log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk",
Jason Molenda2e2ba542010-10-26 04:14:12 +000075 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
Jason Molenda8280cbe2010-10-25 11:12:07 +000076 }
77 break;
78 }
Jason Molenda800d11d2010-11-04 00:53:20 +000079 if (!register_ctx->GetCFA (cursor_sp->cfa))
Jason Molenda8280cbe2010-10-25 11:12:07 +000080 {
81 delete register_ctx;
82 if (log)
83 {
Jason Molendaa2c269c2010-10-26 00:47:17 +000084 log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk",
Jason Molenda2e2ba542010-10-26 04:14:12 +000085 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
Jason Molendaa2c269c2010-10-26 00:47:17 +000086 }
87 break;
88 }
Jason Molenda800d11d2010-11-04 00:53:20 +000089 if (cursor_sp->cfa == (addr_t) -1 || cursor_sp->cfa == 1 || cursor_sp->cfa == 0)
Jason Molendaa2c269c2010-10-26 00:47:17 +000090 {
91 delete register_ctx;
92 if (log)
93 {
94 log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
Jason Molenda2e2ba542010-10-26 04:14:12 +000095 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
Jason Molenda8280cbe2010-10-25 11:12:07 +000096 }
97 break;
98 }
Jason Molenda800d11d2010-11-04 00:53:20 +000099 if (!register_ctx->GetPC (cursor_sp->start_pc))
Jason Molenda8280cbe2010-10-25 11:12:07 +0000100 {
101 delete register_ctx;
102 if (log)
103 {
Jason Molendaa2c269c2010-10-26 00:47:17 +0000104 log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk",
Jason Molenda2e2ba542010-10-26 04:14:12 +0000105 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
Jason Molenda8280cbe2010-10-25 11:12:07 +0000106 }
107 break;
108 }
Jason Molendaa6b71de2010-11-04 09:40:56 +0000109 RegisterContextSP register_ctx_sp(register_ctx);
110 StackFrame *frame = new StackFrame(cur_idx, cur_idx, m_thread, register_ctx_sp, cursor_sp->cfa, cursor_sp->start_pc, &(cursor_sp->sctx));
Jason Molenda8280cbe2010-10-25 11:12:07 +0000111 register_ctx->SetStackFrame (frame);
Jason Molendaa6b71de2010-11-04 09:40:56 +0000112 cursor_sp->reg_ctx = register_ctx_sp;
Jason Molenda800d11d2010-11-04 00:53:20 +0000113 m_frames.push_back (cursor_sp);
Jason Molenda8280cbe2010-10-25 11:12:07 +0000114 }
115 }
116 return m_frames.size ();
117}
118
119bool
120UnwindLLDB::GetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
121{
122 // FIXME don't get the entire stack if it isn't needed.
123 if (m_frames.size() == 0)
124 GetFrameCount();
125
126 if (idx < m_frames.size ())
127 {
Jason Molenda800d11d2010-11-04 00:53:20 +0000128 cfa = m_frames[idx]->cfa;
129 pc = m_frames[idx]->start_pc;
Jason Molenda8280cbe2010-10-25 11:12:07 +0000130 return true;
131 }
132 return false;
133}
134
135RegisterContext *
136UnwindLLDB::CreateRegisterContextForFrame (StackFrame *frame)
137{
138 uint32_t idx = frame->GetFrameIndex ();
139
140 // FIXME don't get the entire stack if it isn't needed.
141 if (m_frames.size() == 0)
142 GetFrameCount();
143
144 if (idx == 0)
145 {
146 return m_thread.GetRegisterContext();
147 }
148 if (idx < m_frames.size ())
Jason Molenda800d11d2010-11-04 00:53:20 +0000149 return m_frames[idx]->reg_ctx.get();
Jason Molenda8280cbe2010-10-25 11:12:07 +0000150 return NULL;
151}