blob: d011314b09632e22d7f2c1589f16070025712400 [file] [log] [blame]
Chris Lattner30fdc8d2010-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 Clayton1f746072012-08-29 21:13:06 +000015#include "lldb/Symbol/Function.h"
16#include "lldb/Symbol/Symbol.h"
17#include "lldb/Symbol/ObjectFile.h"
Greg Clayton1ac04c32012-02-21 00:09:25 +000018#include "lldb/Target/ExecutionContext.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000019#include "lldb/Target/Process.h"
20#include "lldb/Target/Target.h"
Greg Clayton1ac04c32012-02-21 00:09:25 +000021#include "lldb/Target/Thread.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022
23#include "RegisterContextMacOSXFrameBackchain.h"
24
25using namespace lldb;
26using namespace lldb_private;
27
28UnwindMacOSXFrameBackchain::UnwindMacOSXFrameBackchain (Thread &thread) :
29 Unwind (thread),
30 m_cursors()
31{
32}
33
34uint32_t
Jim Ingham8f077162011-10-21 01:49:48 +000035UnwindMacOSXFrameBackchain::DoGetFrameCount()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036{
37 if (m_cursors.empty())
38 {
Greg Clayton1ac04c32012-02-21 00:09:25 +000039 ExecutionContext exe_ctx (m_thread.shared_from_this());
40 Target *target = exe_ctx.GetTargetPtr();
41 if (target)
42 {
43 const ArchSpec& target_arch = target->GetArchitecture ();
44 // Frame zero should always be supplied by the thread...
45 exe_ctx.SetFrameSP (m_thread.GetStackFrameAtIndex (0));
46
47 if (target_arch.GetAddressByteSize() == 8)
48 GetStackFrameData_x86_64 (exe_ctx);
49 else
50 GetStackFrameData_i386 (exe_ctx);
51 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000052 }
53 return m_cursors.size();
54}
55
56bool
Jim Ingham8f077162011-10-21 01:49:48 +000057UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000058{
59 const uint32_t frame_count = GetFrameCount();
60 if (idx < frame_count)
61 {
62 if (m_cursors[idx].pc == LLDB_INVALID_ADDRESS)
63 return false;
64 if (m_cursors[idx].fp == LLDB_INVALID_ADDRESS)
65 return false;
66
67 pc = m_cursors[idx].pc;
68 cfa = m_cursors[idx].fp;
69
70 return true;
71 }
72 return false;
73}
74
Greg Clayton5ccbd292011-01-06 22:15:06 +000075lldb::RegisterContextSP
Jason Molendab57e4a12013-11-04 09:33:30 +000076UnwindMacOSXFrameBackchain::DoCreateRegisterContextForFrame (StackFrame *frame)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000077{
Greg Clayton5ccbd292011-01-06 22:15:06 +000078 lldb::RegisterContextSP reg_ctx_sp;
79 uint32_t concrete_idx = frame->GetConcreteFrameIndex ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000080 const uint32_t frame_count = GetFrameCount();
Greg Clayton5ccbd292011-01-06 22:15:06 +000081 if (concrete_idx < frame_count)
82 reg_ctx_sp.reset (new RegisterContextMacOSXFrameBackchain (m_thread, concrete_idx, m_cursors[concrete_idx]));
83 return reg_ctx_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000084}
85
86size_t
Greg Clayton1ac04c32012-02-21 00:09:25 +000087UnwindMacOSXFrameBackchain::GetStackFrameData_i386 (const ExecutionContext &exe_ctx)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000088{
89 m_cursors.clear();
Greg Clayton1ac04c32012-02-21 00:09:25 +000090
Jason Molendab57e4a12013-11-04 09:33:30 +000091 StackFrame *first_frame = exe_ctx.GetFramePtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000092
Greg Clayton1ac04c32012-02-21 00:09:25 +000093 Process *process = exe_ctx.GetProcessPtr();
94 if (process == NULL)
95 return 0;
96
Chris Lattner30fdc8d2010-06-08 16:52:24 +000097 std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;
98
Greg Clayton69b518f2010-07-07 17:07:17 +000099 struct Frame_i386
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100 {
101 uint32_t fp;
102 uint32_t pc;
103 };
104
Greg Clayton5ccbd292011-01-06 22:15:06 +0000105 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000106 assert (reg_ctx);
107
108 Cursor cursor;
109 cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS);
110 cursor.fp = reg_ctx->GetFP (0);
111
Benjamin Kramerff461fc2012-02-21 18:37:14 +0000112 Frame_i386 frame = { static_cast<uint32_t>(cursor.fp), static_cast<uint32_t>(cursor.pc) };
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113
114 m_cursors.push_back(cursor);
115
116 const size_t k_frame_size = sizeof(frame);
117 Error error;
118 while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
119 {
120 // Read both the FP and PC (8 bytes)
Greg Clayton1ac04c32012-02-21 00:09:25 +0000121 if (process->ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000122 break;
123 if (frame.pc >= 0x1000)
124 {
125 cursor.pc = frame.pc;
126 cursor.fp = frame.fp;
127 m_cursors.push_back (cursor);
128 }
129 }
130 if (!m_cursors.empty())
131 {
132 lldb::addr_t first_frame_pc = m_cursors.front().pc;
133 if (first_frame_pc != LLDB_INVALID_ADDRESS)
134 {
135 const uint32_t resolve_scope = eSymbolContextModule |
136 eSymbolContextCompUnit |
137 eSymbolContextFunction |
138 eSymbolContextSymbol;
139
140 SymbolContext first_frame_sc (first_frame->GetSymbolContext(resolve_scope));
141 const AddressRange *addr_range_ptr = NULL;
Greg Claytone7612132012-03-07 21:03:09 +0000142 AddressRange range;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000143 if (first_frame_sc.function)
144 addr_range_ptr = &first_frame_sc.function->GetAddressRange();
145 else if (first_frame_sc.symbol)
Greg Claytone7612132012-03-07 21:03:09 +0000146 {
147 range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
148 range.SetByteSize (first_frame_sc.symbol->GetByteSize());
149 addr_range_ptr = &range;
150 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000151
152 if (addr_range_ptr)
153 {
Greg Clayton9da7bd02010-08-24 21:05:24 +0000154 if (first_frame->GetFrameCodeAddress() == addr_range_ptr->GetBaseAddress())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000155 {
156 // We are at the first instruction, so we can recover the
157 // previous PC by dereferencing the SP
158 lldb::addr_t first_frame_sp = reg_ctx->GetSP (0);
159 // Read the real second frame return address into frame.pc
Greg Clayton1ac04c32012-02-21 00:09:25 +0000160 if (first_frame_sp && process->ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000161 {
162 cursor.fp = m_cursors.front().fp;
163 cursor.pc = frame.pc; // Set the new second frame PC
164
165 // Insert the second frame
166 m_cursors.insert(m_cursors.begin()+1, cursor);
167
168 m_cursors.front().fp = first_frame_sp;
169 }
170 }
171 }
172 }
173 }
174// uint32_t i=0;
175// printf(" PC FP\n");
176// printf(" ------------------ ------------------ \n");
177// for (i=0; i<m_cursors.size(); ++i)
178// {
Daniel Malead01b2952012-11-29 21:49:15 +0000179// printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 "\n", i, m_cursors[i].pc, m_cursors[i].fp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000180// }
181 return m_cursors.size();
182}
183
184
185size_t
Greg Clayton1ac04c32012-02-21 00:09:25 +0000186UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64 (const ExecutionContext &exe_ctx)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000187{
188 m_cursors.clear();
189
Greg Clayton1ac04c32012-02-21 00:09:25 +0000190 Process *process = exe_ctx.GetProcessPtr();
191 if (process == NULL)
192 return 0;
193
Jason Molendab57e4a12013-11-04 09:33:30 +0000194 StackFrame *first_frame = exe_ctx.GetFramePtr();
Greg Clayton1ac04c32012-02-21 00:09:25 +0000195
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000196 std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;
197
Greg Clayton69b518f2010-07-07 17:07:17 +0000198 struct Frame_x86_64
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000199 {
200 uint64_t fp;
201 uint64_t pc;
202 };
203
Greg Clayton5ccbd292011-01-06 22:15:06 +0000204 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000205 assert (reg_ctx);
206
207 Cursor cursor;
208 cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS);
209 cursor.fp = reg_ctx->GetFP (0);
210
211 Frame_x86_64 frame = { cursor.fp, cursor.pc };
212
213 m_cursors.push_back(cursor);
214 Error error;
215 const size_t k_frame_size = sizeof(frame);
216 while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
217 {
218 // Read both the FP and PC (16 bytes)
Greg Clayton1ac04c32012-02-21 00:09:25 +0000219 if (process->ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000220 break;
221
222 if (frame.pc >= 0x1000)
223 {
224 cursor.pc = frame.pc;
225 cursor.fp = frame.fp;
226 m_cursors.push_back (cursor);
227 }
228 }
229 if (!m_cursors.empty())
230 {
231 lldb::addr_t first_frame_pc = m_cursors.front().pc;
232 if (first_frame_pc != LLDB_INVALID_ADDRESS)
233 {
234 const uint32_t resolve_scope = eSymbolContextModule |
235 eSymbolContextCompUnit |
236 eSymbolContextFunction |
237 eSymbolContextSymbol;
238
239 SymbolContext first_frame_sc(first_frame->GetSymbolContext(resolve_scope));
240 const AddressRange *addr_range_ptr = NULL;
Greg Claytone7612132012-03-07 21:03:09 +0000241 AddressRange range;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000242 if (first_frame_sc.function)
243 addr_range_ptr = &first_frame_sc.function->GetAddressRange();
244 else if (first_frame_sc.symbol)
Greg Claytone7612132012-03-07 21:03:09 +0000245 {
246 range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
247 range.SetByteSize (first_frame_sc.symbol->GetByteSize());
248 addr_range_ptr = &range;
249 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000250
251 if (addr_range_ptr)
252 {
Greg Clayton9da7bd02010-08-24 21:05:24 +0000253 if (first_frame->GetFrameCodeAddress() == addr_range_ptr->GetBaseAddress())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000254 {
255 // We are at the first instruction, so we can recover the
256 // previous PC by dereferencing the SP
257 lldb::addr_t first_frame_sp = reg_ctx->GetSP (0);
258 // Read the real second frame return address into frame.pc
Greg Clayton1ac04c32012-02-21 00:09:25 +0000259 if (process->ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000260 {
261 cursor.fp = m_cursors.front().fp;
262 cursor.pc = frame.pc; // Set the new second frame PC
263
264 // Insert the second frame
265 m_cursors.insert(m_cursors.begin()+1, cursor);
266
267 m_cursors.front().fp = first_frame_sp;
268 }
269 }
270 }
271 }
272 }
273 return m_cursors.size();
274}
275