1 //===-- UnwindMacOSXFrameBackchain.cpp --------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
12 // Other libraries and framework includes
14 #include "lldb/Core/ArchSpec.h"
15 #include "lldb/Symbol/Function.h"
16 #include "lldb/Symbol/Symbol.h"
17 #include "lldb/Symbol/ObjectFile.h"
18 #include "lldb/Target/ExecutionContext.h"
19 #include "lldb/Target/Process.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Target/Thread.h"
23 #include "RegisterContextMacOSXFrameBackchain.h"
26 using namespace lldb_private;
28 UnwindMacOSXFrameBackchain::UnwindMacOSXFrameBackchain (Thread &thread) :
35 UnwindMacOSXFrameBackchain::DoGetFrameCount()
37 if (m_cursors.empty())
39 ExecutionContext exe_ctx (m_thread.shared_from_this());
40 Target *target = exe_ctx.GetTargetPtr();
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));
47 if (target_arch.GetAddressByteSize() == 8)
48 GetStackFrameData_x86_64 (exe_ctx);
50 GetStackFrameData_i386 (exe_ctx);
53 return m_cursors.size();
57 UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
59 const uint32_t frame_count = GetFrameCount();
60 if (idx < frame_count)
62 if (m_cursors[idx].pc == LLDB_INVALID_ADDRESS)
64 if (m_cursors[idx].fp == LLDB_INVALID_ADDRESS)
67 pc = m_cursors[idx].pc;
68 cfa = m_cursors[idx].fp;
75 lldb::RegisterContextSP
76 UnwindMacOSXFrameBackchain::DoCreateRegisterContextForFrame (StackFrame *frame)
78 lldb::RegisterContextSP reg_ctx_sp;
79 uint32_t concrete_idx = frame->GetConcreteFrameIndex ();
80 const uint32_t frame_count = GetFrameCount();
81 if (concrete_idx < frame_count)
82 reg_ctx_sp.reset (new RegisterContextMacOSXFrameBackchain (m_thread, concrete_idx, m_cursors[concrete_idx]));
87 UnwindMacOSXFrameBackchain::GetStackFrameData_i386 (const ExecutionContext &exe_ctx)
91 StackFrame *first_frame = exe_ctx.GetFramePtr();
93 Process *process = exe_ctx.GetProcessPtr();
97 std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;
105 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
109 cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS);
110 cursor.fp = reg_ctx->GetFP (0);
112 Frame_i386 frame = { static_cast<uint32_t>(cursor.fp), static_cast<uint32_t>(cursor.pc) };
114 m_cursors.push_back(cursor);
116 const size_t k_frame_size = sizeof(frame);
118 while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
120 // Read both the FP and PC (8 bytes)
121 if (process->ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
123 if (frame.pc >= 0x1000)
125 cursor.pc = frame.pc;
126 cursor.fp = frame.fp;
127 m_cursors.push_back (cursor);
130 if (!m_cursors.empty())
132 lldb::addr_t first_frame_pc = m_cursors.front().pc;
133 if (first_frame_pc != LLDB_INVALID_ADDRESS)
135 const uint32_t resolve_scope = eSymbolContextModule |
136 eSymbolContextCompUnit |
137 eSymbolContextFunction |
138 eSymbolContextSymbol;
140 SymbolContext first_frame_sc (first_frame->GetSymbolContext(resolve_scope));
141 const AddressRange *addr_range_ptr = NULL;
143 if (first_frame_sc.function)
144 addr_range_ptr = &first_frame_sc.function->GetAddressRange();
145 else if (first_frame_sc.symbol)
147 range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
148 range.SetByteSize (first_frame_sc.symbol->GetByteSize());
149 addr_range_ptr = ⦥
154 if (first_frame->GetFrameCodeAddress() == addr_range_ptr->GetBaseAddress())
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
160 if (first_frame_sp && process->ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
162 cursor.fp = m_cursors.front().fp;
163 cursor.pc = frame.pc; // Set the new second frame PC
165 // Insert the second frame
166 m_cursors.insert(m_cursors.begin()+1, cursor);
168 m_cursors.front().fp = first_frame_sp;
175 // printf(" PC FP\n");
176 // printf(" ------------------ ------------------ \n");
177 // for (i=0; i<m_cursors.size(); ++i)
179 // printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 "\n", i, m_cursors[i].pc, m_cursors[i].fp);
181 return m_cursors.size();
186 UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64 (const ExecutionContext &exe_ctx)
190 Process *process = exe_ctx.GetProcessPtr();
194 StackFrame *first_frame = exe_ctx.GetFramePtr();
196 std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;
204 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
208 cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS);
209 cursor.fp = reg_ctx->GetFP (0);
211 Frame_x86_64 frame = { cursor.fp, cursor.pc };
213 m_cursors.push_back(cursor);
215 const size_t k_frame_size = sizeof(frame);
216 while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
218 // Read both the FP and PC (16 bytes)
219 if (process->ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
222 if (frame.pc >= 0x1000)
224 cursor.pc = frame.pc;
225 cursor.fp = frame.fp;
226 m_cursors.push_back (cursor);
229 if (!m_cursors.empty())
231 lldb::addr_t first_frame_pc = m_cursors.front().pc;
232 if (first_frame_pc != LLDB_INVALID_ADDRESS)
234 const uint32_t resolve_scope = eSymbolContextModule |
235 eSymbolContextCompUnit |
236 eSymbolContextFunction |
237 eSymbolContextSymbol;
239 SymbolContext first_frame_sc(first_frame->GetSymbolContext(resolve_scope));
240 const AddressRange *addr_range_ptr = NULL;
242 if (first_frame_sc.function)
243 addr_range_ptr = &first_frame_sc.function->GetAddressRange();
244 else if (first_frame_sc.symbol)
246 range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
247 range.SetByteSize (first_frame_sc.symbol->GetByteSize());
248 addr_range_ptr = ⦥
253 if (first_frame->GetFrameCodeAddress() == addr_range_ptr->GetBaseAddress())
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
259 if (process->ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
261 cursor.fp = m_cursors.front().fp;
262 cursor.pc = frame.pc; // Set the new second frame PC
264 // Insert the second frame
265 m_cursors.insert(m_cursors.begin()+1, cursor);
267 m_cursors.front().fp = first_frame_sp;
273 return m_cursors.size();