blob: 565983df49408cf31ee6e76e54fd2a01c58a338c [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,
56 delta_t / NSEC_PER_SEC,
57 delta_t % NSEC_PER_SEC,
58 (float)FRAME_COUNT / ((float)delta_t / (float)NSEC_PER_SEC));
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 {
167 if (reg_ctx_sp->GetFP() == 0)
168 return false;
169 }
Greg Clayton1724dec2011-01-17 21:03:33 +0000170 }
171 }
Greg Claytonc3c46612011-02-15 00:19:15 +0000172 cursor_sp->reg_ctx = reg_ctx_sp;
Jason Molenda1da513b2010-11-09 02:31:21 +0000173 m_frames.push_back (cursor_sp);
174 return true;
175}
176
177bool
Jason Molenda8280cbe2010-10-25 11:12:07 +0000178UnwindLLDB::GetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
179{
Jason Molenda8280cbe2010-10-25 11:12:07 +0000180 if (m_frames.size() == 0)
Jason Molenda1da513b2010-11-09 02:31:21 +0000181 {
182 if (!AddFirstFrame())
183 return false;
184 }
185
Greg Clayton54b38412011-05-24 23:06:02 +0000186 ABI *abi = m_thread.GetProcess().GetABI().get();
187
188 while (idx >= m_frames.size() && AddOneMoreFrame (abi))
Jason Molenda1da513b2010-11-09 02:31:21 +0000189 ;
Jason Molenda8280cbe2010-10-25 11:12:07 +0000190
191 if (idx < m_frames.size ())
192 {
Jason Molenda800d11d2010-11-04 00:53:20 +0000193 cfa = m_frames[idx]->cfa;
194 pc = m_frames[idx]->start_pc;
Jason Molenda8280cbe2010-10-25 11:12:07 +0000195 return true;
196 }
197 return false;
198}
199
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000200lldb::RegisterContextSP
Jason Molenda8280cbe2010-10-25 11:12:07 +0000201UnwindLLDB::CreateRegisterContextForFrame (StackFrame *frame)
202{
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000203 lldb::RegisterContextSP reg_ctx_sp;
Greg Clayton869efc22011-01-08 01:53:06 +0000204 uint32_t idx = frame->GetConcreteFrameIndex ();
Jason Molenda1da513b2010-11-09 02:31:21 +0000205
Jason Molenda8280cbe2010-10-25 11:12:07 +0000206 if (idx == 0)
207 {
208 return m_thread.GetRegisterContext();
209 }
Jason Molenda1da513b2010-11-09 02:31:21 +0000210
211 if (m_frames.size() == 0)
212 {
213 if (!AddFirstFrame())
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000214 return reg_ctx_sp;
Jason Molenda1da513b2010-11-09 02:31:21 +0000215 }
216
Greg Clayton54b38412011-05-24 23:06:02 +0000217 ABI *abi = m_thread.GetProcess().GetABI().get();
218
219 while (idx >= m_frames.size() && AddOneMoreFrame (abi))
Jason Molenda1da513b2010-11-09 02:31:21 +0000220 ;
221
Jason Molenda8280cbe2010-10-25 11:12:07 +0000222 if (idx < m_frames.size ())
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000223 reg_ctx_sp = m_frames[idx]->reg_ctx;
224 return reg_ctx_sp;
Jason Molenda8280cbe2010-10-25 11:12:07 +0000225}