blob: e2691be603eced9c298b891bf3c0c0bab6145dcc [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"
Greg Clayton1f746072012-08-29 21:13:06 +000016#include "lldb/Symbol/ObjectFile.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000017#include "lldb/Symbol/Symbol.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
Kate Stoneb9c1b512016-09-06 20:57:50 +000028UnwindMacOSXFrameBackchain::UnwindMacOSXFrameBackchain(Thread &thread)
29 : Unwind(thread), m_cursors() {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000030
Kate Stoneb9c1b512016-09-06 20:57:50 +000031uint32_t UnwindMacOSXFrameBackchain::DoGetFrameCount() {
32 if (m_cursors.empty()) {
33 ExecutionContext exe_ctx(m_thread.shared_from_this());
34 Target *target = exe_ctx.GetTargetPtr();
35 if (target) {
36 const ArchSpec &target_arch = target->GetArchitecture();
37 // Frame zero should always be supplied by the thread...
38 exe_ctx.SetFrameSP(m_thread.GetStackFrameAtIndex(0));
39
40 if (target_arch.GetAddressByteSize() == 8)
41 GetStackFrameData_x86_64(exe_ctx);
42 else
43 GetStackFrameData_i386(exe_ctx);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000044 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000045 }
46 return m_cursors.size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000047}
48
Kate Stoneb9c1b512016-09-06 20:57:50 +000049bool UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex(uint32_t idx,
50 addr_t &cfa,
51 addr_t &pc) {
52 const uint32_t frame_count = GetFrameCount();
53 if (idx < frame_count) {
54 if (m_cursors[idx].pc == LLDB_INVALID_ADDRESS)
55 return false;
56 if (m_cursors[idx].fp == LLDB_INVALID_ADDRESS)
57 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000058
Kate Stoneb9c1b512016-09-06 20:57:50 +000059 pc = m_cursors[idx].pc;
60 cfa = m_cursors[idx].fp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000061
Kate Stoneb9c1b512016-09-06 20:57:50 +000062 return true;
63 }
64 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000065}
Kate Stoneb9c1b512016-09-06 20:57:50 +000066
Greg Clayton5ccbd292011-01-06 22:15:06 +000067lldb::RegisterContextSP
Kate Stoneb9c1b512016-09-06 20:57:50 +000068UnwindMacOSXFrameBackchain::DoCreateRegisterContextForFrame(StackFrame *frame) {
69 lldb::RegisterContextSP reg_ctx_sp;
70 uint32_t concrete_idx = frame->GetConcreteFrameIndex();
71 const uint32_t frame_count = GetFrameCount();
72 if (concrete_idx < frame_count)
73 reg_ctx_sp.reset(new RegisterContextMacOSXFrameBackchain(
74 m_thread, concrete_idx, m_cursors[concrete_idx]));
75 return reg_ctx_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000076}
77
Kate Stoneb9c1b512016-09-06 20:57:50 +000078size_t UnwindMacOSXFrameBackchain::GetStackFrameData_i386(
79 const ExecutionContext &exe_ctx) {
80 m_cursors.clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000081
Kate Stoneb9c1b512016-09-06 20:57:50 +000082 StackFrame *first_frame = exe_ctx.GetFramePtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000083
Kate Stoneb9c1b512016-09-06 20:57:50 +000084 Process *process = exe_ctx.GetProcessPtr();
85 if (process == NULL)
86 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000087
Kate Stoneb9c1b512016-09-06 20:57:50 +000088 std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000089
Kate Stoneb9c1b512016-09-06 20:57:50 +000090 struct Frame_i386 {
91 uint32_t fp;
92 uint32_t pc;
93 };
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094
Kate Stoneb9c1b512016-09-06 20:57:50 +000095 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
96 assert(reg_ctx);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000097
Kate Stoneb9c1b512016-09-06 20:57:50 +000098 Cursor cursor;
99 cursor.pc = reg_ctx->GetPC(LLDB_INVALID_ADDRESS);
100 cursor.fp = reg_ctx->GetFP(0);
101
102 Frame_i386 frame = {static_cast<uint32_t>(cursor.fp),
103 static_cast<uint32_t>(cursor.pc)};
104
105 m_cursors.push_back(cursor);
106
107 const size_t k_frame_size = sizeof(frame);
108 Error error;
109 while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0)) {
110 // Read both the FP and PC (8 bytes)
111 if (process->ReadMemory(frame.fp, &frame.fp, k_frame_size, error) !=
112 k_frame_size)
113 break;
114 if (frame.pc >= 0x1000) {
115 cursor.pc = frame.pc;
116 cursor.fp = frame.fp;
117 m_cursors.push_back(cursor);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000118 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000119 }
120 if (!m_cursors.empty()) {
121 lldb::addr_t first_frame_pc = m_cursors.front().pc;
122 if (first_frame_pc != LLDB_INVALID_ADDRESS) {
123 const uint32_t resolve_scope =
124 eSymbolContextModule | eSymbolContextCompUnit |
125 eSymbolContextFunction | eSymbolContextSymbol;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000126
Kate Stoneb9c1b512016-09-06 20:57:50 +0000127 SymbolContext first_frame_sc(
128 first_frame->GetSymbolContext(resolve_scope));
129 const AddressRange *addr_range_ptr = NULL;
130 AddressRange range;
131 if (first_frame_sc.function)
132 addr_range_ptr = &first_frame_sc.function->GetAddressRange();
133 else if (first_frame_sc.symbol) {
134 range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
135 range.SetByteSize(first_frame_sc.symbol->GetByteSize());
136 addr_range_ptr = &range;
137 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000138
Kate Stoneb9c1b512016-09-06 20:57:50 +0000139 if (addr_range_ptr) {
140 if (first_frame->GetFrameCodeAddress() ==
141 addr_range_ptr->GetBaseAddress()) {
142 // We are at the first instruction, so we can recover the
143 // previous PC by dereferencing the SP
144 lldb::addr_t first_frame_sp = reg_ctx->GetSP(0);
145 // Read the real second frame return address into frame.pc
146 if (first_frame_sp &&
147 process->ReadMemory(first_frame_sp, &frame.pc, sizeof(frame.pc),
148 error) == sizeof(frame.pc)) {
149 cursor.fp = m_cursors.front().fp;
150 cursor.pc = frame.pc; // Set the new second frame PC
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000151
Kate Stoneb9c1b512016-09-06 20:57:50 +0000152 // Insert the second frame
153 m_cursors.insert(m_cursors.begin() + 1, cursor);
154
155 m_cursors.front().fp = first_frame_sp;
156 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000157 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000158 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000159 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000160 }
161 // uint32_t i=0;
162 // printf(" PC FP\n");
163 // printf(" ------------------ ------------------ \n");
164 // for (i=0; i<m_cursors.size(); ++i)
165 // {
166 // printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 "\n", i,
167 // m_cursors[i].pc, m_cursors[i].fp);
168 // }
169 return m_cursors.size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000170}
171
Kate Stoneb9c1b512016-09-06 20:57:50 +0000172size_t UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64(
173 const ExecutionContext &exe_ctx) {
174 m_cursors.clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000175
Kate Stoneb9c1b512016-09-06 20:57:50 +0000176 Process *process = exe_ctx.GetProcessPtr();
177 if (process == NULL)
178 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000179
Kate Stoneb9c1b512016-09-06 20:57:50 +0000180 StackFrame *first_frame = exe_ctx.GetFramePtr();
Greg Clayton1ac04c32012-02-21 00:09:25 +0000181
Kate Stoneb9c1b512016-09-06 20:57:50 +0000182 std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000183
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184 struct Frame_x86_64 {
185 uint64_t fp;
186 uint64_t pc;
187 };
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000188
Kate Stoneb9c1b512016-09-06 20:57:50 +0000189 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
190 assert(reg_ctx);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000191
Kate Stoneb9c1b512016-09-06 20:57:50 +0000192 Cursor cursor;
193 cursor.pc = reg_ctx->GetPC(LLDB_INVALID_ADDRESS);
194 cursor.fp = reg_ctx->GetFP(0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000195
Kate Stoneb9c1b512016-09-06 20:57:50 +0000196 Frame_x86_64 frame = {cursor.fp, cursor.pc};
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000197
Kate Stoneb9c1b512016-09-06 20:57:50 +0000198 m_cursors.push_back(cursor);
199 Error error;
200 const size_t k_frame_size = sizeof(frame);
201 while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0)) {
202 // Read both the FP and PC (16 bytes)
203 if (process->ReadMemory(frame.fp, &frame.fp, k_frame_size, error) !=
204 k_frame_size)
205 break;
206
207 if (frame.pc >= 0x1000) {
208 cursor.pc = frame.pc;
209 cursor.fp = frame.fp;
210 m_cursors.push_back(cursor);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000211 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000212 }
213 if (!m_cursors.empty()) {
214 lldb::addr_t first_frame_pc = m_cursors.front().pc;
215 if (first_frame_pc != LLDB_INVALID_ADDRESS) {
216 const uint32_t resolve_scope =
217 eSymbolContextModule | eSymbolContextCompUnit |
218 eSymbolContextFunction | eSymbolContextSymbol;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000219
Kate Stoneb9c1b512016-09-06 20:57:50 +0000220 SymbolContext first_frame_sc(
221 first_frame->GetSymbolContext(resolve_scope));
222 const AddressRange *addr_range_ptr = NULL;
223 AddressRange range;
224 if (first_frame_sc.function)
225 addr_range_ptr = &first_frame_sc.function->GetAddressRange();
226 else if (first_frame_sc.symbol) {
227 range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
228 range.SetByteSize(first_frame_sc.symbol->GetByteSize());
229 addr_range_ptr = &range;
230 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000231
Kate Stoneb9c1b512016-09-06 20:57:50 +0000232 if (addr_range_ptr) {
233 if (first_frame->GetFrameCodeAddress() ==
234 addr_range_ptr->GetBaseAddress()) {
235 // We are at the first instruction, so we can recover the
236 // previous PC by dereferencing the SP
237 lldb::addr_t first_frame_sp = reg_ctx->GetSP(0);
238 // Read the real second frame return address into frame.pc
239 if (process->ReadMemory(first_frame_sp, &frame.pc, sizeof(frame.pc),
240 error) == sizeof(frame.pc)) {
241 cursor.fp = m_cursors.front().fp;
242 cursor.pc = frame.pc; // Set the new second frame PC
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000243
Kate Stoneb9c1b512016-09-06 20:57:50 +0000244 // Insert the second frame
245 m_cursors.insert(m_cursors.begin() + 1, cursor);
246
247 m_cursors.front().fp = first_frame_sp;
248 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000249 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000250 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000251 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000252 }
253 return m_cursors.size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000254}