1 //===-- 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" 15 #include "lldb/Symbol/Function.h" 16 #include "lldb/Symbol/ObjectFile.h" 17 #include "lldb/Symbol/Symbol.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" 22 23 #include "RegisterContextMacOSXFrameBackchain.h" 24 25 using namespace lldb; 26 using namespace lldb_private; 27 28 UnwindMacOSXFrameBackchain::UnwindMacOSXFrameBackchain(Thread &thread) 29 : Unwind(thread), m_cursors() {} 30 31 uint32_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); 44 } 45 } 46 return m_cursors.size(); 47 } 48 49 bool 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; 58 59 pc = m_cursors[idx].pc; 60 cfa = m_cursors[idx].fp; 61 62 return true; 63 } 64 return false; 65 } 66 67 lldb::RegisterContextSP 68 UnwindMacOSXFrameBackchain::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; 76 } 77 78 size_t UnwindMacOSXFrameBackchain::GetStackFrameData_i386( 79 const ExecutionContext &exe_ctx) { 80 m_cursors.clear(); 81 82 StackFrame *first_frame = exe_ctx.GetFramePtr(); 83 84 Process *process = exe_ctx.GetProcessPtr(); 85 if (process == NULL) 86 return 0; 87 88 std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair; 89 90 struct Frame_i386 { 91 uint32_t fp; 92 uint32_t pc; 93 }; 94 95 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 96 assert(reg_ctx); 97 98 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); 118 } 119 } 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; 126 127 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 = ⦥ 137 } 138 139 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 151 152 // Insert the second frame 153 m_cursors.insert(m_cursors.begin() + 1, cursor); 154 155 m_cursors.front().fp = first_frame_sp; 156 } 157 } 158 } 159 } 160 } 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(); 170 } 171 172 size_t UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64( 173 const ExecutionContext &exe_ctx) { 174 m_cursors.clear(); 175 176 Process *process = exe_ctx.GetProcessPtr(); 177 if (process == NULL) 178 return 0; 179 180 StackFrame *first_frame = exe_ctx.GetFramePtr(); 181 182 std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair; 183 184 struct Frame_x86_64 { 185 uint64_t fp; 186 uint64_t pc; 187 }; 188 189 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 190 assert(reg_ctx); 191 192 Cursor cursor; 193 cursor.pc = reg_ctx->GetPC(LLDB_INVALID_ADDRESS); 194 cursor.fp = reg_ctx->GetFP(0); 195 196 Frame_x86_64 frame = {cursor.fp, cursor.pc}; 197 198 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); 211 } 212 } 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; 219 220 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 = ⦥ 230 } 231 232 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 243 244 // Insert the second frame 245 m_cursors.insert(m_cursors.begin() + 1, cursor); 246 247 m_cursors.front().fp = first_frame_sp; 248 } 249 } 250 } 251 } 252 } 253 return m_cursors.size(); 254 } 255