blob: 38f2c46f8e8493a23800f2b26a92b322e08b9249 [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{
Jason Molenda8280cbe2010-10-25 11:12:07 +000034 if (m_frames.empty())
35 {
Jason Molenda1da513b2010-11-09 02:31:21 +000036 if (!AddFirstFrame ())
Jason Molenda8280cbe2010-10-25 11:12:07 +000037 return 0;
Jason Molenda1da513b2010-11-09 02:31:21 +000038 while (AddOneMoreFrame ())
39 ;
Jason Molenda8280cbe2010-10-25 11:12:07 +000040 }
41 return m_frames.size ();
42}
43
44bool
Jason Molenda1da513b2010-11-09 02:31:21 +000045UnwindLLDB::AddFirstFrame ()
46{
47 // First, set up the 0th (initial) frame
48 CursorSP first_cursor_sp(new Cursor ());
49 RegisterContextSP no_frame;
50 RegisterContextLLDB *first_register_ctx = new RegisterContextLLDB(m_thread, no_frame, first_cursor_sp->sctx, 0);
51 if (!first_register_ctx->IsValid())
52 {
53 delete first_register_ctx;
54 return false;
55 }
56 if (!first_register_ctx->GetCFA (first_cursor_sp->cfa))
57 {
58 delete first_register_ctx;
59 return false;
60 }
61 if (!first_register_ctx->GetPC (first_cursor_sp->start_pc))
62 {
63 delete first_register_ctx;
64 return false;
65 }
66 // Reuse the StackFrame provided by the processor native machine context for the first frame
67 first_register_ctx->SetStackFrame (m_thread.GetStackFrameAtIndex(0).get());
68 RegisterContextSP first_register_ctx_sp(first_register_ctx);
69 first_cursor_sp->reg_ctx = first_register_ctx_sp;
70 m_frames.push_back (first_cursor_sp);
71 return true;
72}
73
74// For adding a non-zero stack frame to m_frames.
75bool
76UnwindLLDB::AddOneMoreFrame ()
77{
78 LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
79 CursorSP cursor_sp(new Cursor ());
80 RegisterContextLLDB *register_ctx;
81
82 // Frame zero is a little different
83 if (m_frames.size() == 0)
84 return false;
85
86 uint32_t cur_idx = m_frames.size ();
87 register_ctx = new RegisterContextLLDB (m_thread, m_frames[cur_idx - 1]->reg_ctx, cursor_sp->sctx, cur_idx);
88
89 if (!register_ctx->IsValid())
90 {
91 delete register_ctx;
92 if (log)
93 {
94 log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk",
95 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
96 }
97 return false;
98 }
99 if (!register_ctx->GetCFA (cursor_sp->cfa))
100 {
101 delete register_ctx;
102 if (log)
103 {
104 log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk",
105 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
106 }
107 return false;
108 }
109 if (cursor_sp->cfa == (addr_t) -1 || cursor_sp->cfa == 1 || cursor_sp->cfa == 0)
110 {
111 delete register_ctx;
112 if (log)
113 {
114 log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
115 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
116 }
117 return false;
118 }
119 if (!register_ctx->GetPC (cursor_sp->start_pc))
120 {
121 delete register_ctx;
122 if (log)
123 {
124 log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk",
125 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
126 }
127 return false;
128 }
129 RegisterContextSP register_ctx_sp(register_ctx);
130 StackFrame *frame = new StackFrame(cur_idx, cur_idx, m_thread, register_ctx_sp, cursor_sp->cfa, cursor_sp->start_pc, &(cursor_sp->sctx));
131 register_ctx->SetStackFrame (frame);
132 cursor_sp->reg_ctx = register_ctx_sp;
133 m_frames.push_back (cursor_sp);
134 return true;
135}
136
137bool
Jason Molenda8280cbe2010-10-25 11:12:07 +0000138UnwindLLDB::GetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
139{
Jason Molenda8280cbe2010-10-25 11:12:07 +0000140 if (m_frames.size() == 0)
Jason Molenda1da513b2010-11-09 02:31:21 +0000141 {
142 if (!AddFirstFrame())
143 return false;
144 }
145
146 while (idx >= m_frames.size() && AddOneMoreFrame ())
147 ;
Jason Molenda8280cbe2010-10-25 11:12:07 +0000148
149 if (idx < m_frames.size ())
150 {
Jason Molenda800d11d2010-11-04 00:53:20 +0000151 cfa = m_frames[idx]->cfa;
152 pc = m_frames[idx]->start_pc;
Jason Molenda8280cbe2010-10-25 11:12:07 +0000153 return true;
154 }
155 return false;
156}
157
158RegisterContext *
159UnwindLLDB::CreateRegisterContextForFrame (StackFrame *frame)
160{
161 uint32_t idx = frame->GetFrameIndex ();
Jason Molenda1da513b2010-11-09 02:31:21 +0000162
Jason Molenda8280cbe2010-10-25 11:12:07 +0000163 if (idx == 0)
164 {
165 return m_thread.GetRegisterContext();
166 }
Jason Molenda1da513b2010-11-09 02:31:21 +0000167
168 if (m_frames.size() == 0)
169 {
170 if (!AddFirstFrame())
171 return NULL;
172 }
173
174 while (idx >= m_frames.size() && AddOneMoreFrame ())
175 ;
176
Jason Molenda8280cbe2010-10-25 11:12:07 +0000177 if (idx < m_frames.size ())
Jason Molenda800d11d2010-11-04 00:53:20 +0000178 return m_frames[idx]->reg_ctx.get();
Jason Molenda8280cbe2010-10-25 11:12:07 +0000179 return NULL;
180}