blob: 4ed69e853879d23725bc0bf3a903fec8ee742064 [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
Greg Clayton97eecb12011-04-25 18:36:36 +000010#include "lldb/Core/Module.h"
11#include "lldb/Core/Log.h"
12#include "lldb/Symbol/FuncUnwinders.h"
13#include "lldb/Symbol/Function.h"
14#include "lldb/Symbol/UnwindPlan.h"
Jason Molenda8280cbe2010-10-25 11:12:07 +000015#include "lldb/Target/Thread.h"
16#include "lldb/Target/Target.h"
17#include "lldb/Target/Process.h"
18#include "lldb/Target/RegisterContext.h"
Jason Molenda8280cbe2010-10-25 11:12:07 +000019
Greg Claytonc3c46612011-02-15 00:19:15 +000020#include "UnwindLLDB.h"
21#include "RegisterContextLLDB.h"
22
Jason Molenda8280cbe2010-10-25 11:12:07 +000023using namespace lldb;
24using namespace lldb_private;
25
26UnwindLLDB::UnwindLLDB (Thread &thread) :
27 Unwind (thread),
28 m_frames()
29{
30}
31
32uint32_t
33UnwindLLDB::GetFrameCount()
34{
Jason Molenda8280cbe2010-10-25 11:12:07 +000035 if (m_frames.empty())
36 {
Greg Claytonfd119992011-01-07 06:08:19 +000037//#define DEBUG_FRAME_SPEED 1
38#if DEBUG_FRAME_SPEED
Greg Claytona875b642011-01-09 21:07:35 +000039#define FRAME_COUNT 10000
Greg Claytonfd119992011-01-07 06:08:19 +000040 TimeValue time_value (TimeValue::Now());
41#endif
Jason Molenda1da513b2010-11-09 02:31:21 +000042 if (!AddFirstFrame ())
Jason Molenda8280cbe2010-10-25 11:12:07 +000043 return 0;
Greg Clayton54b38412011-05-24 23:06:02 +000044
45 ABI *abi = m_thread.GetProcess().GetABI().get();
46
47 while (AddOneMoreFrame (abi))
Greg Claytonfd119992011-01-07 06:08:19 +000048 {
49#if DEBUG_FRAME_SPEED
Greg Claytona875b642011-01-09 21:07:35 +000050 if ((m_frames.size() % FRAME_COUNT) == 0)
Greg Claytonfd119992011-01-07 06:08:19 +000051 {
52 TimeValue now(TimeValue::Now());
53 uint64_t delta_t = now - time_value;
Greg Claytona875b642011-01-09 21:07:35 +000054 printf ("%u frames in %llu.%09llu ms (%g frames/sec)\n",
55 FRAME_COUNT,
Peter Collingbourne20fe30c2011-06-18 23:52:14 +000056 delta_t / TimeValue::NanoSecPerSec,
57 delta_t % TimeValue::NanoSecPerSec,
58 (float)FRAME_COUNT / ((float)delta_t / (float)TimeValue::NanoSecPerSec));
Greg Claytonfd119992011-01-07 06:08:19 +000059 time_value = now;
60 }
61#endif
62 }
Jason Molenda8280cbe2010-10-25 11:12:07 +000063 }
64 return m_frames.size ();
65}
66
67bool
Jason Molenda1da513b2010-11-09 02:31:21 +000068UnwindLLDB::AddFirstFrame ()
69{
70 // First, set up the 0th (initial) frame
71 CursorSP first_cursor_sp(new Cursor ());
Greg Clayton54b38412011-05-24 23:06:02 +000072 RegisterContextLLDB::SharedPtr reg_ctx_sp (new RegisterContextLLDB (m_thread,
73 RegisterContextLLDB::SharedPtr(),
74 first_cursor_sp->sctx,
75 0));
76 if (reg_ctx_sp.get() == NULL)
Jason Molenda1da513b2010-11-09 02:31:21 +000077 return false;
Greg Clayton08d7d3a2011-01-06 22:15:06 +000078
Greg Clayton54b38412011-05-24 23:06:02 +000079 if (!reg_ctx_sp->IsValid())
Jason Molenda1da513b2010-11-09 02:31:21 +000080 return false;
Greg Clayton08d7d3a2011-01-06 22:15:06 +000081
Greg Clayton54b38412011-05-24 23:06:02 +000082 if (!reg_ctx_sp->GetCFA (first_cursor_sp->cfa))
Jason Molenda1da513b2010-11-09 02:31:21 +000083 return false;
Greg Clayton08d7d3a2011-01-06 22:15:06 +000084
Greg Clayton54b38412011-05-24 23:06:02 +000085 if (!reg_ctx_sp->ReadPC (first_cursor_sp->start_pc))
Greg Clayton08d7d3a2011-01-06 22:15:06 +000086 return false;
87
88 // Everything checks out, so release the auto pointer value and let the
89 // cursor own it in its shared pointer
Greg Clayton54b38412011-05-24 23:06:02 +000090 first_cursor_sp->reg_ctx = reg_ctx_sp;
Jason Molenda1da513b2010-11-09 02:31:21 +000091 m_frames.push_back (first_cursor_sp);
92 return true;
93}
94
95// For adding a non-zero stack frame to m_frames.
96bool
Greg Clayton54b38412011-05-24 23:06:02 +000097UnwindLLDB::AddOneMoreFrame (ABI *abi)
Jason Molenda1da513b2010-11-09 02:31:21 +000098{
99 LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
100 CursorSP cursor_sp(new Cursor ());
Jason Molenda1da513b2010-11-09 02:31:21 +0000101
102 // Frame zero is a little different
103 if (m_frames.size() == 0)
104 return false;
105
106 uint32_t cur_idx = m_frames.size ();
Greg Clayton54b38412011-05-24 23:06:02 +0000107 RegisterContextLLDB::SharedPtr reg_ctx_sp(new RegisterContextLLDB (m_thread,
108 m_frames[cur_idx - 1]->reg_ctx,
109 cursor_sp->sctx,
110 cur_idx));
111 if (reg_ctx_sp.get() == NULL)
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000112 return false;
Jason Molenda1da513b2010-11-09 02:31:21 +0000113
Greg Clayton54b38412011-05-24 23:06:02 +0000114 if (!reg_ctx_sp->IsValid())
Jason Molenda1da513b2010-11-09 02:31:21 +0000115 {
Jason Molenda1da513b2010-11-09 02:31:21 +0000116 if (log)
117 {
118 log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk",
119 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
120 }
121 return false;
122 }
Greg Clayton54b38412011-05-24 23:06:02 +0000123 if (!reg_ctx_sp->GetCFA (cursor_sp->cfa))
Jason Molenda1da513b2010-11-09 02:31:21 +0000124 {
Jason Molenda1da513b2010-11-09 02:31:21 +0000125 if (log)
126 {
127 log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk",
128 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
129 }
130 return false;
131 }
Greg Clayton54b38412011-05-24 23:06:02 +0000132 if (abi && !abi->CallFrameAddressIsValid(cursor_sp->cfa))
Jason Molenda1da513b2010-11-09 02:31:21 +0000133 {
Jason Molenda1da513b2010-11-09 02:31:21 +0000134 if (log)
135 {
136 log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
137 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
138 }
139 return false;
140 }
Greg Clayton54b38412011-05-24 23:06:02 +0000141 if (!reg_ctx_sp->ReadPC (cursor_sp->start_pc))
Jason Molenda1da513b2010-11-09 02:31:21 +0000142 {
Jason Molenda1da513b2010-11-09 02:31:21 +0000143 if (log)
144 {
145 log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk",
146 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
147 }
148 return false;
149 }
Greg Clayton54b38412011-05-24 23:06:02 +0000150 if (abi && !abi->CodeAddressIsValid (cursor_sp->start_pc))
151 {
152 if (log)
153 {
154 log->Printf("%*sFrame %d did not get a valid PC, stopping stack walk",
155 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
156 }
157 return false;
158 }
Greg Clayton1724dec2011-01-17 21:03:33 +0000159 if (!m_frames.empty())
160 {
Greg Clayton54b38412011-05-24 23:06:02 +0000161 if (m_frames.back()->start_pc == cursor_sp->start_pc)
Greg Clayton1724dec2011-01-17 21:03:33 +0000162 {
Greg Clayton54b38412011-05-24 23:06:02 +0000163 if (m_frames.back()->cfa == cursor_sp->cfa)
164 return false; // Infinite loop where the current cursor is the same as the previous one...
165 else if (abi->StackUsesFrames())
166 {
Greg Clayton19552cb2011-05-25 17:56:20 +0000167 // We might have a CFA that is not using the frame pointer and
168 // we want to validate that the frame pointer is valid.
Greg Clayton54b38412011-05-24 23:06:02 +0000169 if (reg_ctx_sp->GetFP() == 0)
170 return false;
171 }
Greg Clayton1724dec2011-01-17 21:03:33 +0000172 }
173 }
Greg Claytonc3c46612011-02-15 00:19:15 +0000174 cursor_sp->reg_ctx = reg_ctx_sp;
Jason Molenda1da513b2010-11-09 02:31:21 +0000175 m_frames.push_back (cursor_sp);
176 return true;
177}
178
179bool
Jason Molenda8280cbe2010-10-25 11:12:07 +0000180UnwindLLDB::GetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
181{
Jason Molenda8280cbe2010-10-25 11:12:07 +0000182 if (m_frames.size() == 0)
Jason Molenda1da513b2010-11-09 02:31:21 +0000183 {
184 if (!AddFirstFrame())
185 return false;
186 }
187
Greg Clayton54b38412011-05-24 23:06:02 +0000188 ABI *abi = m_thread.GetProcess().GetABI().get();
189
190 while (idx >= m_frames.size() && AddOneMoreFrame (abi))
Jason Molenda1da513b2010-11-09 02:31:21 +0000191 ;
Jason Molenda8280cbe2010-10-25 11:12:07 +0000192
193 if (idx < m_frames.size ())
194 {
Jason Molenda800d11d2010-11-04 00:53:20 +0000195 cfa = m_frames[idx]->cfa;
196 pc = m_frames[idx]->start_pc;
Jason Molenda8280cbe2010-10-25 11:12:07 +0000197 return true;
198 }
199 return false;
200}
201
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000202lldb::RegisterContextSP
Jason Molenda8280cbe2010-10-25 11:12:07 +0000203UnwindLLDB::CreateRegisterContextForFrame (StackFrame *frame)
204{
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000205 lldb::RegisterContextSP reg_ctx_sp;
Greg Clayton869efc22011-01-08 01:53:06 +0000206 uint32_t idx = frame->GetConcreteFrameIndex ();
Jason Molenda1da513b2010-11-09 02:31:21 +0000207
Jason Molenda8280cbe2010-10-25 11:12:07 +0000208 if (idx == 0)
209 {
210 return m_thread.GetRegisterContext();
211 }
Jason Molenda1da513b2010-11-09 02:31:21 +0000212
213 if (m_frames.size() == 0)
214 {
215 if (!AddFirstFrame())
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000216 return reg_ctx_sp;
Jason Molenda1da513b2010-11-09 02:31:21 +0000217 }
218
Greg Clayton54b38412011-05-24 23:06:02 +0000219 ABI *abi = m_thread.GetProcess().GetABI().get();
220
221 while (idx >= m_frames.size() && AddOneMoreFrame (abi))
Jason Molenda1da513b2010-11-09 02:31:21 +0000222 ;
223
Jason Molenda8280cbe2010-10-25 11:12:07 +0000224 if (idx < m_frames.size ())
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000225 reg_ctx_sp = m_frames[idx]->reg_ctx;
226 return reg_ctx_sp;
Jason Molenda8280cbe2010-10-25 11:12:07 +0000227}