blob: 90913b961d5fe4e41a2c2bdfb06fc68bc2b6534a [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- UnwindMacOSXFrameBackchain.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// C Includes
11// C++ Includes
12// Other libraries and framework includes
13// Project includes
14#include "lldb/Core/ArchSpec.h"
Greg Claytonf4124de2012-02-21 00:09:25 +000015#include "lldb/Target/ExecutionContext.h"
Chris Lattner24943d22010-06-08 16:52:24 +000016#include "lldb/Target/Process.h"
17#include "lldb/Target/Target.h"
Greg Claytonf4124de2012-02-21 00:09:25 +000018#include "lldb/Target/Thread.h"
Chris Lattner24943d22010-06-08 16:52:24 +000019
20#include "RegisterContextMacOSXFrameBackchain.h"
21
22using namespace lldb;
23using namespace lldb_private;
24
25UnwindMacOSXFrameBackchain::UnwindMacOSXFrameBackchain (Thread &thread) :
26 Unwind (thread),
27 m_cursors()
28{
29}
30
31uint32_t
Jim Ingham591cf152011-10-21 01:49:48 +000032UnwindMacOSXFrameBackchain::DoGetFrameCount()
Chris Lattner24943d22010-06-08 16:52:24 +000033{
34 if (m_cursors.empty())
35 {
Greg Claytonf4124de2012-02-21 00:09:25 +000036 ExecutionContext exe_ctx (m_thread.shared_from_this());
37 Target *target = exe_ctx.GetTargetPtr();
38 if (target)
39 {
40 const ArchSpec& target_arch = target->GetArchitecture ();
41 // Frame zero should always be supplied by the thread...
42 exe_ctx.SetFrameSP (m_thread.GetStackFrameAtIndex (0));
43
44 if (target_arch.GetAddressByteSize() == 8)
45 GetStackFrameData_x86_64 (exe_ctx);
46 else
47 GetStackFrameData_i386 (exe_ctx);
48 }
Chris Lattner24943d22010-06-08 16:52:24 +000049 }
50 return m_cursors.size();
51}
52
53bool
Jim Ingham591cf152011-10-21 01:49:48 +000054UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
Chris Lattner24943d22010-06-08 16:52:24 +000055{
56 const uint32_t frame_count = GetFrameCount();
57 if (idx < frame_count)
58 {
59 if (m_cursors[idx].pc == LLDB_INVALID_ADDRESS)
60 return false;
61 if (m_cursors[idx].fp == LLDB_INVALID_ADDRESS)
62 return false;
63
64 pc = m_cursors[idx].pc;
65 cfa = m_cursors[idx].fp;
66
67 return true;
68 }
69 return false;
70}
71
Greg Clayton08d7d3a2011-01-06 22:15:06 +000072lldb::RegisterContextSP
Jim Ingham591cf152011-10-21 01:49:48 +000073UnwindMacOSXFrameBackchain::DoCreateRegisterContextForFrame (StackFrame *frame)
Chris Lattner24943d22010-06-08 16:52:24 +000074{
Greg Clayton08d7d3a2011-01-06 22:15:06 +000075 lldb::RegisterContextSP reg_ctx_sp;
76 uint32_t concrete_idx = frame->GetConcreteFrameIndex ();
Chris Lattner24943d22010-06-08 16:52:24 +000077 const uint32_t frame_count = GetFrameCount();
Greg Clayton08d7d3a2011-01-06 22:15:06 +000078 if (concrete_idx < frame_count)
79 reg_ctx_sp.reset (new RegisterContextMacOSXFrameBackchain (m_thread, concrete_idx, m_cursors[concrete_idx]));
80 return reg_ctx_sp;
Chris Lattner24943d22010-06-08 16:52:24 +000081}
82
83size_t
Greg Claytonf4124de2012-02-21 00:09:25 +000084UnwindMacOSXFrameBackchain::GetStackFrameData_i386 (const ExecutionContext &exe_ctx)
Chris Lattner24943d22010-06-08 16:52:24 +000085{
86 m_cursors.clear();
Greg Claytonf4124de2012-02-21 00:09:25 +000087
88 StackFrame *first_frame = exe_ctx.GetFramePtr();
Chris Lattner24943d22010-06-08 16:52:24 +000089
Greg Claytonf4124de2012-02-21 00:09:25 +000090 Process *process = exe_ctx.GetProcessPtr();
91 if (process == NULL)
92 return 0;
93
Chris Lattner24943d22010-06-08 16:52:24 +000094 std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;
95
Greg Claytonc0418152010-07-07 17:07:17 +000096 struct Frame_i386
Chris Lattner24943d22010-06-08 16:52:24 +000097 {
98 uint32_t fp;
99 uint32_t pc;
100 };
101
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000102 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000103 assert (reg_ctx);
104
105 Cursor cursor;
106 cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS);
107 cursor.fp = reg_ctx->GetFP (0);
108
Benjamin Kramer137e5232012-02-21 18:37:14 +0000109 Frame_i386 frame = { static_cast<uint32_t>(cursor.fp), static_cast<uint32_t>(cursor.pc) };
Chris Lattner24943d22010-06-08 16:52:24 +0000110
111 m_cursors.push_back(cursor);
112
113 const size_t k_frame_size = sizeof(frame);
114 Error error;
115 while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
116 {
117 // Read both the FP and PC (8 bytes)
Greg Claytonf4124de2012-02-21 00:09:25 +0000118 if (process->ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
Chris Lattner24943d22010-06-08 16:52:24 +0000119 break;
120 if (frame.pc >= 0x1000)
121 {
122 cursor.pc = frame.pc;
123 cursor.fp = frame.fp;
124 m_cursors.push_back (cursor);
125 }
126 }
127 if (!m_cursors.empty())
128 {
129 lldb::addr_t first_frame_pc = m_cursors.front().pc;
130 if (first_frame_pc != LLDB_INVALID_ADDRESS)
131 {
132 const uint32_t resolve_scope = eSymbolContextModule |
133 eSymbolContextCompUnit |
134 eSymbolContextFunction |
135 eSymbolContextSymbol;
136
137 SymbolContext first_frame_sc (first_frame->GetSymbolContext(resolve_scope));
138 const AddressRange *addr_range_ptr = NULL;
Greg Clayton0c31d3d2012-03-07 21:03:09 +0000139 AddressRange range;
Chris Lattner24943d22010-06-08 16:52:24 +0000140 if (first_frame_sc.function)
141 addr_range_ptr = &first_frame_sc.function->GetAddressRange();
142 else if (first_frame_sc.symbol)
Greg Clayton0c31d3d2012-03-07 21:03:09 +0000143 {
144 range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
145 range.SetByteSize (first_frame_sc.symbol->GetByteSize());
146 addr_range_ptr = &range;
147 }
Chris Lattner24943d22010-06-08 16:52:24 +0000148
149 if (addr_range_ptr)
150 {
Greg Claytonb04e7a82010-08-24 21:05:24 +0000151 if (first_frame->GetFrameCodeAddress() == addr_range_ptr->GetBaseAddress())
Chris Lattner24943d22010-06-08 16:52:24 +0000152 {
153 // We are at the first instruction, so we can recover the
154 // previous PC by dereferencing the SP
155 lldb::addr_t first_frame_sp = reg_ctx->GetSP (0);
156 // Read the real second frame return address into frame.pc
Greg Claytonf4124de2012-02-21 00:09:25 +0000157 if (first_frame_sp && process->ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
Chris Lattner24943d22010-06-08 16:52:24 +0000158 {
159 cursor.fp = m_cursors.front().fp;
160 cursor.pc = frame.pc; // Set the new second frame PC
161
162 // Insert the second frame
163 m_cursors.insert(m_cursors.begin()+1, cursor);
164
165 m_cursors.front().fp = first_frame_sp;
166 }
167 }
168 }
169 }
170 }
171// uint32_t i=0;
172// printf(" PC FP\n");
173// printf(" ------------------ ------------------ \n");
174// for (i=0; i<m_cursors.size(); ++i)
175// {
176// printf("[%3u] 0x%16.16llx 0x%16.16llx\n", i, m_cursors[i].pc, m_cursors[i].fp);
177// }
178 return m_cursors.size();
179}
180
181
182size_t
Greg Claytonf4124de2012-02-21 00:09:25 +0000183UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64 (const ExecutionContext &exe_ctx)
Chris Lattner24943d22010-06-08 16:52:24 +0000184{
185 m_cursors.clear();
186
Greg Claytonf4124de2012-02-21 00:09:25 +0000187 Process *process = exe_ctx.GetProcessPtr();
188 if (process == NULL)
189 return 0;
190
191 StackFrame *first_frame = exe_ctx.GetFramePtr();
192
Chris Lattner24943d22010-06-08 16:52:24 +0000193 std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;
194
Greg Claytonc0418152010-07-07 17:07:17 +0000195 struct Frame_x86_64
Chris Lattner24943d22010-06-08 16:52:24 +0000196 {
197 uint64_t fp;
198 uint64_t pc;
199 };
200
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000201 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000202 assert (reg_ctx);
203
204 Cursor cursor;
205 cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS);
206 cursor.fp = reg_ctx->GetFP (0);
207
208 Frame_x86_64 frame = { cursor.fp, cursor.pc };
209
210 m_cursors.push_back(cursor);
211 Error error;
212 const size_t k_frame_size = sizeof(frame);
213 while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
214 {
215 // Read both the FP and PC (16 bytes)
Greg Claytonf4124de2012-02-21 00:09:25 +0000216 if (process->ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
Chris Lattner24943d22010-06-08 16:52:24 +0000217 break;
218
219 if (frame.pc >= 0x1000)
220 {
221 cursor.pc = frame.pc;
222 cursor.fp = frame.fp;
223 m_cursors.push_back (cursor);
224 }
225 }
226 if (!m_cursors.empty())
227 {
228 lldb::addr_t first_frame_pc = m_cursors.front().pc;
229 if (first_frame_pc != LLDB_INVALID_ADDRESS)
230 {
231 const uint32_t resolve_scope = eSymbolContextModule |
232 eSymbolContextCompUnit |
233 eSymbolContextFunction |
234 eSymbolContextSymbol;
235
236 SymbolContext first_frame_sc(first_frame->GetSymbolContext(resolve_scope));
237 const AddressRange *addr_range_ptr = NULL;
Greg Clayton0c31d3d2012-03-07 21:03:09 +0000238 AddressRange range;
Chris Lattner24943d22010-06-08 16:52:24 +0000239 if (first_frame_sc.function)
240 addr_range_ptr = &first_frame_sc.function->GetAddressRange();
241 else if (first_frame_sc.symbol)
Greg Clayton0c31d3d2012-03-07 21:03:09 +0000242 {
243 range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
244 range.SetByteSize (first_frame_sc.symbol->GetByteSize());
245 addr_range_ptr = &range;
246 }
Chris Lattner24943d22010-06-08 16:52:24 +0000247
248 if (addr_range_ptr)
249 {
Greg Claytonb04e7a82010-08-24 21:05:24 +0000250 if (first_frame->GetFrameCodeAddress() == addr_range_ptr->GetBaseAddress())
Chris Lattner24943d22010-06-08 16:52:24 +0000251 {
252 // We are at the first instruction, so we can recover the
253 // previous PC by dereferencing the SP
254 lldb::addr_t first_frame_sp = reg_ctx->GetSP (0);
255 // Read the real second frame return address into frame.pc
Greg Claytonf4124de2012-02-21 00:09:25 +0000256 if (process->ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
Chris Lattner24943d22010-06-08 16:52:24 +0000257 {
258 cursor.fp = m_cursors.front().fp;
259 cursor.pc = frame.pc; // Set the new second frame PC
260
261 // Insert the second frame
262 m_cursors.insert(m_cursors.begin()+1, cursor);
263
264 m_cursors.front().fp = first_frame_sp;
265 }
266 }
267 }
268 }
269 }
270 return m_cursors.size();
271}
272