blob: 2de786f0639c7ed310a45cbd6edc063e886452aa [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;
Jason Molenda1da513b2010-11-09 02:31:21 +000044 while (AddOneMoreFrame ())
Greg Claytonfd119992011-01-07 06:08:19 +000045 {
46#if DEBUG_FRAME_SPEED
Greg Claytona875b642011-01-09 21:07:35 +000047 if ((m_frames.size() % FRAME_COUNT) == 0)
Greg Claytonfd119992011-01-07 06:08:19 +000048 {
49 TimeValue now(TimeValue::Now());
50 uint64_t delta_t = now - time_value;
Greg Claytona875b642011-01-09 21:07:35 +000051 printf ("%u frames in %llu.%09llu ms (%g frames/sec)\n",
52 FRAME_COUNT,
53 delta_t / NSEC_PER_SEC,
54 delta_t % NSEC_PER_SEC,
55 (float)FRAME_COUNT / ((float)delta_t / (float)NSEC_PER_SEC));
Greg Claytonfd119992011-01-07 06:08:19 +000056 time_value = now;
57 }
58#endif
59 }
Jason Molenda8280cbe2010-10-25 11:12:07 +000060 }
61 return m_frames.size ();
62}
63
64bool
Jason Molenda1da513b2010-11-09 02:31:21 +000065UnwindLLDB::AddFirstFrame ()
66{
67 // First, set up the 0th (initial) frame
68 CursorSP first_cursor_sp(new Cursor ());
Greg Claytonc3c46612011-02-15 00:19:15 +000069 std::auto_ptr<RegisterContextLLDB> first_register_ctx_ap (new RegisterContextLLDB (m_thread,
70 RegisterContextLLDB::SharedPtr(),
71 first_cursor_sp->sctx,
72 0));
Greg Clayton08d7d3a2011-01-06 22:15:06 +000073 if (first_register_ctx_ap.get() == NULL)
Jason Molenda1da513b2010-11-09 02:31:21 +000074 return false;
Greg Clayton08d7d3a2011-01-06 22:15:06 +000075
76 if (!first_register_ctx_ap->IsValid())
Jason Molenda1da513b2010-11-09 02:31:21 +000077 return false;
Greg Clayton08d7d3a2011-01-06 22:15:06 +000078
79 if (!first_register_ctx_ap->GetCFA (first_cursor_sp->cfa))
Jason Molenda1da513b2010-11-09 02:31:21 +000080 return false;
Greg Clayton08d7d3a2011-01-06 22:15:06 +000081
Greg Clayton1724dec2011-01-17 21:03:33 +000082 if (!first_register_ctx_ap->ReadPC (first_cursor_sp->start_pc))
Greg Clayton08d7d3a2011-01-06 22:15:06 +000083 return false;
84
85 // Everything checks out, so release the auto pointer value and let the
86 // cursor own it in its shared pointer
87 first_cursor_sp->reg_ctx.reset(first_register_ctx_ap.release());
Jason Molenda1da513b2010-11-09 02:31:21 +000088 m_frames.push_back (first_cursor_sp);
89 return true;
90}
91
92// For adding a non-zero stack frame to m_frames.
93bool
94UnwindLLDB::AddOneMoreFrame ()
95{
96 LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
97 CursorSP cursor_sp(new Cursor ());
Jason Molenda1da513b2010-11-09 02:31:21 +000098
99 // Frame zero is a little different
100 if (m_frames.size() == 0)
101 return false;
102
103 uint32_t cur_idx = m_frames.size ();
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000104 std::auto_ptr<RegisterContextLLDB> register_ctx_ap(new RegisterContextLLDB (m_thread,
105 m_frames[cur_idx - 1]->reg_ctx,
106 cursor_sp->sctx,
107 cur_idx));
108 if (register_ctx_ap.get() == NULL)
109 return false;
Jason Molenda1da513b2010-11-09 02:31:21 +0000110
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000111 if (!register_ctx_ap->IsValid())
Jason Molenda1da513b2010-11-09 02:31:21 +0000112 {
Jason Molenda1da513b2010-11-09 02:31:21 +0000113 if (log)
114 {
115 log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk",
116 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
117 }
118 return false;
119 }
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000120 if (!register_ctx_ap->GetCFA (cursor_sp->cfa))
Jason Molenda1da513b2010-11-09 02:31:21 +0000121 {
Jason Molenda1da513b2010-11-09 02:31:21 +0000122 if (log)
123 {
124 log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk",
125 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
126 }
127 return false;
128 }
129 if (cursor_sp->cfa == (addr_t) -1 || cursor_sp->cfa == 1 || cursor_sp->cfa == 0)
130 {
Jason Molenda1da513b2010-11-09 02:31:21 +0000131 if (log)
132 {
133 log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
134 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
135 }
136 return false;
137 }
Greg Clayton1724dec2011-01-17 21:03:33 +0000138 if (!register_ctx_ap->ReadPC (cursor_sp->start_pc))
Jason Molenda1da513b2010-11-09 02:31:21 +0000139 {
Jason Molenda1da513b2010-11-09 02:31:21 +0000140 if (log)
141 {
142 log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk",
143 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
144 }
145 return false;
146 }
Greg Clayton1724dec2011-01-17 21:03:33 +0000147 if (!m_frames.empty())
148 {
149 if ((m_frames.back()->start_pc == cursor_sp->start_pc) &&
150 (m_frames.back()->cfa == cursor_sp->cfa))
151 {
152 // Infinite loop where the current cursor is the same as the previous one...
153 return false;
154 }
155 }
Greg Claytonc3c46612011-02-15 00:19:15 +0000156 RegisterContextLLDB::SharedPtr reg_ctx_sp(register_ctx_ap.release());
157 cursor_sp->reg_ctx = reg_ctx_sp;
Jason Molenda1da513b2010-11-09 02:31:21 +0000158 m_frames.push_back (cursor_sp);
159 return true;
160}
161
162bool
Jason Molenda8280cbe2010-10-25 11:12:07 +0000163UnwindLLDB::GetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
164{
Jason Molenda8280cbe2010-10-25 11:12:07 +0000165 if (m_frames.size() == 0)
Jason Molenda1da513b2010-11-09 02:31:21 +0000166 {
167 if (!AddFirstFrame())
168 return false;
169 }
170
171 while (idx >= m_frames.size() && AddOneMoreFrame ())
172 ;
Jason Molenda8280cbe2010-10-25 11:12:07 +0000173
174 if (idx < m_frames.size ())
175 {
Jason Molenda800d11d2010-11-04 00:53:20 +0000176 cfa = m_frames[idx]->cfa;
177 pc = m_frames[idx]->start_pc;
Jason Molenda8280cbe2010-10-25 11:12:07 +0000178 return true;
179 }
180 return false;
181}
182
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000183lldb::RegisterContextSP
Jason Molenda8280cbe2010-10-25 11:12:07 +0000184UnwindLLDB::CreateRegisterContextForFrame (StackFrame *frame)
185{
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000186 lldb::RegisterContextSP reg_ctx_sp;
Greg Clayton869efc22011-01-08 01:53:06 +0000187 uint32_t idx = frame->GetConcreteFrameIndex ();
Jason Molenda1da513b2010-11-09 02:31:21 +0000188
Jason Molenda8280cbe2010-10-25 11:12:07 +0000189 if (idx == 0)
190 {
191 return m_thread.GetRegisterContext();
192 }
Jason Molenda1da513b2010-11-09 02:31:21 +0000193
194 if (m_frames.size() == 0)
195 {
196 if (!AddFirstFrame())
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000197 return reg_ctx_sp;
Jason Molenda1da513b2010-11-09 02:31:21 +0000198 }
199
200 while (idx >= m_frames.size() && AddOneMoreFrame ())
201 ;
202
Jason Molenda8280cbe2010-10-25 11:12:07 +0000203 if (idx < m_frames.size ())
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000204 reg_ctx_sp = m_frames[idx]->reg_ctx;
205 return reg_ctx_sp;
Jason Molenda8280cbe2010-10-25 11:12:07 +0000206}