blob: ae0b9fb0a5269e53ea4ae21720b525b20bfdd33d [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
Greg Clayton1f746072012-08-29 21:13:06 +000010#include "lldb/Symbol/Function.h"
Greg Clayton1f746072012-08-29 21:13:06 +000011#include "lldb/Symbol/ObjectFile.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000012#include "lldb/Symbol/Symbol.h"
Greg Clayton1ac04c32012-02-21 00:09:25 +000013#include "lldb/Target/ExecutionContext.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000014#include "lldb/Target/Process.h"
15#include "lldb/Target/Target.h"
Greg Clayton1ac04c32012-02-21 00:09:25 +000016#include "lldb/Target/Thread.h"
Pavel Labath5f19b902017-11-13 16:16:33 +000017#include "lldb/Utility/ArchSpec.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018
19#include "RegisterContextMacOSXFrameBackchain.h"
20
21using namespace lldb;
22using namespace lldb_private;
23
Kate Stoneb9c1b512016-09-06 20:57:50 +000024UnwindMacOSXFrameBackchain::UnwindMacOSXFrameBackchain(Thread &thread)
25 : Unwind(thread), m_cursors() {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000026
Kate Stoneb9c1b512016-09-06 20:57:50 +000027uint32_t UnwindMacOSXFrameBackchain::DoGetFrameCount() {
28 if (m_cursors.empty()) {
29 ExecutionContext exe_ctx(m_thread.shared_from_this());
30 Target *target = exe_ctx.GetTargetPtr();
31 if (target) {
32 const ArchSpec &target_arch = target->GetArchitecture();
33 // Frame zero should always be supplied by the thread...
34 exe_ctx.SetFrameSP(m_thread.GetStackFrameAtIndex(0));
35
36 if (target_arch.GetAddressByteSize() == 8)
37 GetStackFrameData_x86_64(exe_ctx);
38 else
39 GetStackFrameData_i386(exe_ctx);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000040 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000041 }
42 return m_cursors.size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043}
44
Kate Stoneb9c1b512016-09-06 20:57:50 +000045bool UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex(uint32_t idx,
46 addr_t &cfa,
47 addr_t &pc) {
48 const uint32_t frame_count = GetFrameCount();
49 if (idx < frame_count) {
50 if (m_cursors[idx].pc == LLDB_INVALID_ADDRESS)
51 return false;
52 if (m_cursors[idx].fp == LLDB_INVALID_ADDRESS)
53 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000054
Kate Stoneb9c1b512016-09-06 20:57:50 +000055 pc = m_cursors[idx].pc;
56 cfa = m_cursors[idx].fp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000057
Kate Stoneb9c1b512016-09-06 20:57:50 +000058 return true;
59 }
60 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000061}
Kate Stoneb9c1b512016-09-06 20:57:50 +000062
Greg Clayton5ccbd292011-01-06 22:15:06 +000063lldb::RegisterContextSP
Kate Stoneb9c1b512016-09-06 20:57:50 +000064UnwindMacOSXFrameBackchain::DoCreateRegisterContextForFrame(StackFrame *frame) {
65 lldb::RegisterContextSP reg_ctx_sp;
66 uint32_t concrete_idx = frame->GetConcreteFrameIndex();
67 const uint32_t frame_count = GetFrameCount();
68 if (concrete_idx < frame_count)
69 reg_ctx_sp.reset(new RegisterContextMacOSXFrameBackchain(
70 m_thread, concrete_idx, m_cursors[concrete_idx]));
71 return reg_ctx_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000072}
73
Kate Stoneb9c1b512016-09-06 20:57:50 +000074size_t UnwindMacOSXFrameBackchain::GetStackFrameData_i386(
75 const ExecutionContext &exe_ctx) {
76 m_cursors.clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000077
Kate Stoneb9c1b512016-09-06 20:57:50 +000078 StackFrame *first_frame = exe_ctx.GetFramePtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000079
Kate Stoneb9c1b512016-09-06 20:57:50 +000080 Process *process = exe_ctx.GetProcessPtr();
81 if (process == NULL)
82 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000083
Kate Stoneb9c1b512016-09-06 20:57:50 +000084 struct Frame_i386 {
85 uint32_t fp;
86 uint32_t pc;
87 };
Chris Lattner30fdc8d2010-06-08 16:52:24 +000088
Kate Stoneb9c1b512016-09-06 20:57:50 +000089 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
90 assert(reg_ctx);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000091
Kate Stoneb9c1b512016-09-06 20:57:50 +000092 Cursor cursor;
93 cursor.pc = reg_ctx->GetPC(LLDB_INVALID_ADDRESS);
94 cursor.fp = reg_ctx->GetFP(0);
95
96 Frame_i386 frame = {static_cast<uint32_t>(cursor.fp),
97 static_cast<uint32_t>(cursor.pc)};
98
99 m_cursors.push_back(cursor);
100
101 const size_t k_frame_size = sizeof(frame);
Zachary Turner97206d52017-05-12 04:51:55 +0000102 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000103 while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0)) {
104 // Read both the FP and PC (8 bytes)
105 if (process->ReadMemory(frame.fp, &frame.fp, k_frame_size, error) !=
106 k_frame_size)
107 break;
108 if (frame.pc >= 0x1000) {
109 cursor.pc = frame.pc;
110 cursor.fp = frame.fp;
111 m_cursors.push_back(cursor);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000112 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000113 }
114 if (!m_cursors.empty()) {
115 lldb::addr_t first_frame_pc = m_cursors.front().pc;
116 if (first_frame_pc != LLDB_INVALID_ADDRESS) {
Zachary Turner991e4452018-10-25 20:45:19 +0000117 const SymbolContextItem resolve_scope =
Kate Stoneb9c1b512016-09-06 20:57:50 +0000118 eSymbolContextModule | eSymbolContextCompUnit |
119 eSymbolContextFunction | eSymbolContextSymbol;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000120
Kate Stoneb9c1b512016-09-06 20:57:50 +0000121 SymbolContext first_frame_sc(
122 first_frame->GetSymbolContext(resolve_scope));
123 const AddressRange *addr_range_ptr = NULL;
124 AddressRange range;
125 if (first_frame_sc.function)
126 addr_range_ptr = &first_frame_sc.function->GetAddressRange();
127 else if (first_frame_sc.symbol) {
128 range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
129 range.SetByteSize(first_frame_sc.symbol->GetByteSize());
130 addr_range_ptr = &range;
131 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000132
Kate Stoneb9c1b512016-09-06 20:57:50 +0000133 if (addr_range_ptr) {
134 if (first_frame->GetFrameCodeAddress() ==
135 addr_range_ptr->GetBaseAddress()) {
Adrian Prantl05097242018-04-30 16:49:04 +0000136 // We are at the first instruction, so we can recover the previous PC
137 // by dereferencing the SP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000138 lldb::addr_t first_frame_sp = reg_ctx->GetSP(0);
139 // Read the real second frame return address into frame.pc
140 if (first_frame_sp &&
141 process->ReadMemory(first_frame_sp, &frame.pc, sizeof(frame.pc),
142 error) == sizeof(frame.pc)) {
143 cursor.fp = m_cursors.front().fp;
144 cursor.pc = frame.pc; // Set the new second frame PC
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000145
Kate Stoneb9c1b512016-09-06 20:57:50 +0000146 // Insert the second frame
147 m_cursors.insert(m_cursors.begin() + 1, cursor);
148
149 m_cursors.front().fp = first_frame_sp;
150 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000151 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000152 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000153 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000154 }
155 // uint32_t i=0;
156 // printf(" PC FP\n");
157 // printf(" ------------------ ------------------ \n");
158 // for (i=0; i<m_cursors.size(); ++i)
159 // {
160 // printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 "\n", i,
161 // m_cursors[i].pc, m_cursors[i].fp);
162 // }
163 return m_cursors.size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000164}
165
Kate Stoneb9c1b512016-09-06 20:57:50 +0000166size_t UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64(
167 const ExecutionContext &exe_ctx) {
168 m_cursors.clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000169
Kate Stoneb9c1b512016-09-06 20:57:50 +0000170 Process *process = exe_ctx.GetProcessPtr();
171 if (process == NULL)
172 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173
Kate Stoneb9c1b512016-09-06 20:57:50 +0000174 StackFrame *first_frame = exe_ctx.GetFramePtr();
Greg Clayton1ac04c32012-02-21 00:09:25 +0000175
Kate Stoneb9c1b512016-09-06 20:57:50 +0000176 struct Frame_x86_64 {
177 uint64_t fp;
178 uint64_t pc;
179 };
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000180
Kate Stoneb9c1b512016-09-06 20:57:50 +0000181 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
182 assert(reg_ctx);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000183
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184 Cursor cursor;
185 cursor.pc = reg_ctx->GetPC(LLDB_INVALID_ADDRESS);
186 cursor.fp = reg_ctx->GetFP(0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000187
Kate Stoneb9c1b512016-09-06 20:57:50 +0000188 Frame_x86_64 frame = {cursor.fp, cursor.pc};
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000189
Kate Stoneb9c1b512016-09-06 20:57:50 +0000190 m_cursors.push_back(cursor);
Zachary Turner97206d52017-05-12 04:51:55 +0000191 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000192 const size_t k_frame_size = sizeof(frame);
193 while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0)) {
194 // Read both the FP and PC (16 bytes)
195 if (process->ReadMemory(frame.fp, &frame.fp, k_frame_size, error) !=
196 k_frame_size)
197 break;
198
199 if (frame.pc >= 0x1000) {
200 cursor.pc = frame.pc;
201 cursor.fp = frame.fp;
202 m_cursors.push_back(cursor);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000203 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000204 }
205 if (!m_cursors.empty()) {
206 lldb::addr_t first_frame_pc = m_cursors.front().pc;
207 if (first_frame_pc != LLDB_INVALID_ADDRESS) {
Zachary Turner991e4452018-10-25 20:45:19 +0000208 const SymbolContextItem resolve_scope =
Kate Stoneb9c1b512016-09-06 20:57:50 +0000209 eSymbolContextModule | eSymbolContextCompUnit |
210 eSymbolContextFunction | eSymbolContextSymbol;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000211
Kate Stoneb9c1b512016-09-06 20:57:50 +0000212 SymbolContext first_frame_sc(
213 first_frame->GetSymbolContext(resolve_scope));
214 const AddressRange *addr_range_ptr = NULL;
215 AddressRange range;
216 if (first_frame_sc.function)
217 addr_range_ptr = &first_frame_sc.function->GetAddressRange();
218 else if (first_frame_sc.symbol) {
219 range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
220 range.SetByteSize(first_frame_sc.symbol->GetByteSize());
221 addr_range_ptr = &range;
222 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000223
Kate Stoneb9c1b512016-09-06 20:57:50 +0000224 if (addr_range_ptr) {
225 if (first_frame->GetFrameCodeAddress() ==
226 addr_range_ptr->GetBaseAddress()) {
Adrian Prantl05097242018-04-30 16:49:04 +0000227 // We are at the first instruction, so we can recover the previous PC
228 // by dereferencing the SP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000229 lldb::addr_t first_frame_sp = reg_ctx->GetSP(0);
230 // Read the real second frame return address into frame.pc
231 if (process->ReadMemory(first_frame_sp, &frame.pc, sizeof(frame.pc),
232 error) == sizeof(frame.pc)) {
233 cursor.fp = m_cursors.front().fp;
234 cursor.pc = frame.pc; // Set the new second frame PC
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000235
Kate Stoneb9c1b512016-09-06 20:57:50 +0000236 // Insert the second frame
237 m_cursors.insert(m_cursors.begin() + 1, cursor);
238
239 m_cursors.front().fp = first_frame_sp;
240 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000241 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000242 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000243 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000244 }
245 return m_cursors.size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000246}