bool RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointVacant(uint32_t hw_index) { bool is_vacant = false; RegisterValue value; assert(hw_index < NumSupportedHardwareWatchpoints()); if (m_watchpoints_initialized == false) { // Reset the debug status and debug control registers RegisterValue zero_bits = RegisterValue(uint64_t(0)); if (!WriteRegister(dr6, zero_bits) || !WriteRegister(dr7, zero_bits)) assert(false && "Could not initialize watchpoint registers"); m_watchpoints_initialized = true; } if (ReadRegister(dr7, value)) { uint64_t val = value.GetAsUInt64(); is_vacant = (val & (3 << 2*hw_index)) == 0; } return is_vacant; }
uint64_t RegisterContext::ReadRegisterAsUnsigned(const RegisterInfo *reg_info, uint64_t fail_value) { if (reg_info) { RegisterValue value; if (ReadRegister(reg_info, value)) return value.GetAsUInt64(); } return fail_value; }
static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton, const EmulateInstruction::Context &context, const RegisterInfo *reg_info, const RegisterValue ®_value) { if (reg_info->kinds[lldb::eRegisterKindDWARF] == dwarf_bad_mips64) { EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); emulator_baton->m_watch_hit_addr = reg_value.GetAsUInt64(); } return true; }
Error NativeRegisterContextLinux::DoWriteRegisterValue(uint32_t offset, const char* reg_name, const RegisterValue &value) { Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); void* buf = reinterpret_cast<void *>(value.GetAsUInt64()); if (log) log->Printf ("NativeRegisterContextLinux::%s() reg %s: %p", __FUNCTION__, reg_name, buf); return NativeProcessLinux::PtraceWrapper( PTRACE_POKEUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), buf); }
bool RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister( const RegisterInfo *reg_info, const RegisterValue &value) { const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; if (IsGPR(reg)) { return WriteRegister(reg, value); } else if (IsFPR(reg)) { assert(reg_info->byte_offset < sizeof(m_fpr_powerpc)); uint8_t *dst = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset; *(uint64_t *)dst = value.GetAsUInt64(); return WriteFPR(); } return false; }
addr_t RegisterContextPOSIXProcessMonitor_x86_64::GetWatchpointAddress(uint32_t hw_index) { addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS; if (hw_index < NumSupportedHardwareWatchpoints()) { if (!IsWatchpointVacant(hw_index)) { RegisterValue value; if (ReadRegister(dr0 + hw_index, value)) wp_monitor_addr = value.GetAsUInt64(); } } return wp_monitor_addr; }
bool UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, const EmulateInstruction::Context &context, const RegisterInfo *reg_info, const RegisterValue ®_value) { Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); if (log && log->GetVerbose ()) { StreamString strm; strm.Printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ", reg_info->name); reg_value.Dump(&strm, reg_info, false, false, eFormatDefault); strm.PutCString (", context = "); context.Dump(strm, instruction); log->PutCString(strm.GetData()); } if (!instruction->IsInstructionConditional()) SetRegisterValue (*reg_info, reg_value); switch (context.type) { case EmulateInstruction::eContextInvalid: case EmulateInstruction::eContextReadOpcode: case EmulateInstruction::eContextImmediate: case EmulateInstruction::eContextAdjustBaseRegister: case EmulateInstruction::eContextRegisterPlusOffset: case EmulateInstruction::eContextAdjustPC: case EmulateInstruction::eContextRegisterStore: case EmulateInstruction::eContextSupervisorCall: case EmulateInstruction::eContextTableBranchReadMemory: case EmulateInstruction::eContextWriteRegisterRandomBits: case EmulateInstruction::eContextWriteMemoryRandomBits: case EmulateInstruction::eContextArithmetic: case EmulateInstruction::eContextAdvancePC: case EmulateInstruction::eContextReturnFromException: case EmulateInstruction::eContextPushRegisterOnStack: case EmulateInstruction::eContextRegisterLoad: // { // const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; // if (reg_num != LLDB_INVALID_REGNUM) // { // const bool can_replace_only_if_unspecified = true; // // m_curr_row.SetRegisterLocationToUndefined (reg_num, // can_replace_only_if_unspecified, // can_replace_only_if_unspecified); // m_curr_row_modified = true; // } // } break; case EmulateInstruction::eContextAbsoluteBranchRegister: case EmulateInstruction::eContextRelativeBranchImmediate: { if (context.info_type == EmulateInstruction::eInfoTypeISAAndImmediate && context.info.ISAAndImmediate.unsigned_data32 > 0) { m_forward_branch_offset = context.info.ISAAndImmediateSigned.signed_data32; } else if (context.info_type == EmulateInstruction::eInfoTypeISAAndImmediateSigned && context.info.ISAAndImmediateSigned.signed_data32 > 0) { m_forward_branch_offset = context.info.ISAAndImmediate.unsigned_data32; } else if (context.info_type == EmulateInstruction::eInfoTypeImmediate && context.info.unsigned_immediate > 0) { m_forward_branch_offset = context.info.unsigned_immediate; } else if (context.info_type == EmulateInstruction::eInfoTypeImmediateSigned && context.info.signed_immediate > 0) { m_forward_branch_offset = context.info.signed_immediate; } } break; case EmulateInstruction::eContextPopRegisterOffStack: { if (!instruction->IsInstructionConditional()) { const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric]; if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP) { switch (context.info_type) { case EmulateInstruction::eInfoTypeAddress: if (m_pushed_regs.find(reg_num) != m_pushed_regs.end() && context.info.address == m_pushed_regs[reg_num]) { m_curr_row->SetRegisterLocationToSame(reg_num, false /*must_replace*/); m_curr_row_modified = true; } break; case EmulateInstruction::eInfoTypeISA: assert((generic_regnum == LLDB_REGNUM_GENERIC_PC || generic_regnum == LLDB_REGNUM_GENERIC_FLAGS) && "eInfoTypeISA used for poping a register other the the PC/FLAGS"); if (generic_regnum != LLDB_REGNUM_GENERIC_FLAGS) { m_curr_row->SetRegisterLocationToSame(reg_num, false /*must_replace*/); m_curr_row_modified = true; } break; default: assert(false && "unhandled case, add code to handle this!"); break; } } } } break; case EmulateInstruction::eContextSetFramePointer: if (!m_fp_is_cfa && !instruction->IsInstructionConditional()) { m_fp_is_cfa = true; m_cfa_reg_info = *reg_info; const uint32_t cfa_reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; assert (cfa_reg_num != LLDB_INVALID_REGNUM); m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(cfa_reg_num, m_initial_sp - reg_value.GetAsUInt64()); m_curr_row_modified = true; } break; case EmulateInstruction::eContextAdjustStackPointer: // If we have created a frame using the frame pointer, don't follow // subsequent adjustments to the stack pointer. if (!m_fp_is_cfa && !instruction->IsInstructionConditional()) { m_curr_row->GetCFAValue().SetIsRegisterPlusOffset( m_curr_row->GetCFAValue().GetRegisterNumber(), m_initial_sp - reg_value.GetAsUInt64()); m_curr_row_modified = true; } break; } return true; }
bool RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) { const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; if (IsGPR(reg)) return WriteRegister(reg, value); if (IsFPR(reg, GetFPRType())) { switch (reg) { default: if (reg_info->encoding != eEncodingVector) return false; if (reg >= fpu_stmm0 && reg <= fpu_stmm7) ::memcpy (m_fpr.xstate.fxsave.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize()); if (reg >= fpu_xmm0 && reg <= fpu_xmm15) ::memcpy (m_fpr.xstate.fxsave.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), value.GetByteSize()); if (reg >= fpu_ymm0 && reg <= fpu_ymm15) { if (GetFPRType() != eXSAVE) return false; // the target processor does not support AVX // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes ::memcpy (m_ymm_set.ymm[reg - fpu_ymm0].bytes, value.GetBytes(), value.GetByteSize()); if (false == CopyYMMtoXSTATE(reg, GetByteOrder())) return false; } break; case fpu_dp: m_fpr.xstate.fxsave.dp = value.GetAsUInt64(); break; case fpu_fcw: m_fpr.xstate.fxsave.fcw = value.GetAsUInt16(); break; case fpu_fsw: m_fpr.xstate.fxsave.fsw = value.GetAsUInt16(); break; case fpu_ip: m_fpr.xstate.fxsave.ip = value.GetAsUInt64(); break; case fpu_fop: m_fpr.xstate.fxsave.fop = value.GetAsUInt16(); break; case fpu_ftw: m_fpr.xstate.fxsave.ftw = value.GetAsUInt16(); break; case fpu_mxcsr: m_fpr.xstate.fxsave.mxcsr = value.GetAsUInt32(); break; case fpu_mxcsrmask: m_fpr.xstate.fxsave.mxcsrmask = value.GetAsUInt32(); break; } if (WriteFPR()) { if (IsAVX(reg)) return CopyYMMtoXSTATE(reg, GetByteOrder()); return true; } } return false; }
bool RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) { // Since we cannot only write a single register value to the inferior, we need to make sure // our cached copy of the register values are fresh. Otherwise when writing EAX, for example, // we may also overwrite some other register with a stale value. if (!CacheAllRegisterValues()) return false; switch (reg_info->kinds[eRegisterKindLLDB]) { case lldb_rax_x86_64: m_context.Rax = reg_value.GetAsUInt64(); break; case lldb_rbx_x86_64: m_context.Rbx = reg_value.GetAsUInt64(); break; case lldb_rcx_x86_64: m_context.Rcx = reg_value.GetAsUInt64(); break; case lldb_rdx_x86_64: m_context.Rdx = reg_value.GetAsUInt64(); break; case lldb_rdi_x86_64: m_context.Rdi = reg_value.GetAsUInt64(); break; case lldb_rsi_x86_64: m_context.Rsi = reg_value.GetAsUInt64(); break; case lldb_r8_x86_64: m_context.R8 = reg_value.GetAsUInt64(); break; case lldb_r9_x86_64: m_context.R9 = reg_value.GetAsUInt64(); break; case lldb_r10_x86_64: m_context.R10 = reg_value.GetAsUInt64(); break; case lldb_r11_x86_64: m_context.R11 = reg_value.GetAsUInt64(); break; case lldb_r12_x86_64: m_context.R12 = reg_value.GetAsUInt64(); break; case lldb_r13_x86_64: m_context.R13 = reg_value.GetAsUInt64(); break; case lldb_r14_x86_64: m_context.R14 = reg_value.GetAsUInt64(); break; case lldb_r15_x86_64: m_context.R15 = reg_value.GetAsUInt64(); break; case lldb_rbp_x86_64: m_context.Rbp = reg_value.GetAsUInt64(); break; case lldb_rsp_x86_64: m_context.Rsp = reg_value.GetAsUInt64(); break; case lldb_rip_x86_64: m_context.Rip = reg_value.GetAsUInt64(); break; case lldb_rflags_x86_64: m_context.EFlags = reg_value.GetAsUInt64(); break; } // Physically update the registers in the target process. TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); return ::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); }
bool RegisterContextDarwin_arm64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) { const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; int set = GetSetForNativeRegNum(reg); if (set == -1) return false; if (ReadRegisterSet(set, false) != KERN_SUCCESS) return false; switch (reg) { case gpr_x0: case gpr_x1: case gpr_x2: case gpr_x3: case gpr_x4: case gpr_x5: case gpr_x6: case gpr_x7: case gpr_x8: case gpr_x9: case gpr_x10: case gpr_x11: case gpr_x12: case gpr_x13: case gpr_x14: case gpr_x15: case gpr_x16: case gpr_x17: case gpr_x18: case gpr_x19: case gpr_x20: case gpr_x21: case gpr_x22: case gpr_x23: case gpr_x24: case gpr_x25: case gpr_x26: case gpr_x27: case gpr_x28: case gpr_fp: case gpr_sp: case gpr_lr: case gpr_pc: case gpr_cpsr: gpr.x[reg - gpr_x0] = value.GetAsUInt64(); break; case fpu_v0: case fpu_v1: case fpu_v2: case fpu_v3: case fpu_v4: case fpu_v5: case fpu_v6: case fpu_v7: case fpu_v8: case fpu_v9: case fpu_v10: case fpu_v11: case fpu_v12: case fpu_v13: case fpu_v14: case fpu_v15: case fpu_v16: case fpu_v17: case fpu_v18: case fpu_v19: case fpu_v20: case fpu_v21: case fpu_v22: case fpu_v23: case fpu_v24: case fpu_v25: case fpu_v26: case fpu_v27: case fpu_v28: case fpu_v29: case fpu_v30: case fpu_v31: ::memcpy(fpu.v[reg].bytes, value.GetBytes(), value.GetByteSize()); break; case fpu_fpsr: fpu.fpsr = value.GetAsUInt32(); break; case fpu_fpcr: fpu.fpcr = value.GetAsUInt32(); break; case exc_exception: exc.exception = value.GetAsUInt32(); break; case exc_esr: exc.esr = value.GetAsUInt32(); break; case exc_far: exc.far = value.GetAsUInt64(); break; default: return false; } return WriteRegisterSet(set) == KERN_SUCCESS; }
Status NativeRegisterContextLinux_s390x::WriteRegister( const RegisterInfo *reg_info, const RegisterValue ®_value) { if (!reg_info) return Status("reg_info NULL"); const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; if (reg == LLDB_INVALID_REGNUM) return Status("register \"%s\" is an internal-only lldb register, cannot " "write directly", reg_info->name); if (IsGPR(reg)) { s390_regs regs; Status error = DoReadGPR(®s, sizeof(regs)); if (error.Fail()) return error; uint8_t *dst = (uint8_t *)®s + reg_info->byte_offset; assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); switch (reg_info->byte_size) { case 4: *(uint32_t *)dst = reg_value.GetAsUInt32(); break; case 8: *(uint64_t *)dst = reg_value.GetAsUInt64(); break; default: assert(false && "Unhandled data size."); return Status("unhandled byte size: %" PRIu32, reg_info->byte_size); } return DoWriteGPR(®s, sizeof(regs)); } if (IsFPR(reg)) { s390_fp_regs fp_regs; Status error = DoReadFPR(&fp_regs, sizeof(fp_regs)); if (error.Fail()) return error; // byte_offset is just the offset within fp_regs, not the whole user area. uint8_t *dst = (uint8_t *)&fp_regs + reg_info->byte_offset; assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); switch (reg_info->byte_size) { case 4: *(uint32_t *)dst = reg_value.GetAsUInt32(); break; case 8: *(uint64_t *)dst = reg_value.GetAsUInt64(); break; default: assert(false && "Unhandled data size."); return Status("unhandled byte size: %" PRIu32, reg_info->byte_size); } return DoWriteFPR(&fp_regs, sizeof(fp_regs)); } if (reg == lldb_last_break_s390x) { return Status("The last break address is read-only"); } if (reg == lldb_system_call_s390x) { uint32_t system_call = reg_value.GetAsUInt32(); return DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); } return Status("failed - register wasn't recognized"); }
lldb_private::Error NativeRegisterContextLinux_mips64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) { Error error; assert (reg_info && "reg_info is null"); const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; if (reg_index == LLDB_INVALID_REGNUM) return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>"); if (IsMSA(reg_index) && !IsMSAAvailable()) { error.SetErrorString ("MSA not available on this processor"); return error; } if (IsFPR(reg_index) || IsMSA(reg_index)) { uint8_t *dst; uint64_t *src; // Initialise the FP and MSA buffers by reading all co-processor 1 registers ReadCP1(); if (IsFPR(reg_index)) { assert (reg_info->byte_offset < sizeof(UserArea)); dst = (uint8_t *)&m_fpr + reg_info->byte_offset - (sizeof(m_gpr)); } else { assert (reg_info->byte_offset < sizeof(UserArea)); dst = (uint8_t *)&m_msa + reg_info->byte_offset - (sizeof(m_gpr) + sizeof(m_fpr)); } switch (reg_info->byte_size) { case 4: *(uint32_t *)dst = reg_value.GetAsUInt32(); break; case 8: *(uint64_t *)dst = reg_value.GetAsUInt64(); break; case 16: src = (uint64_t *)reg_value.GetBytes(); *(uint64_t *)dst = *src; *(uint64_t *)(dst + 8) = *(src + 1); break; default: assert(false && "Unhandled data size."); error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size); break; } error = WriteCP1(); if (!error.Success()) { error.SetErrorString ("failed to write co-processor 1 register"); return error; } } else { error = WriteRegisterRaw(reg_index, reg_value); } return error; }
bool RegisterContextDarwin_x86_64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &value) { const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; int set = RegisterContextDarwin_x86_64::GetSetForNativeRegNum (reg); if (set == -1) return false; if (ReadRegisterSet(set, false) != 0) return false; switch (reg) { case gpr_rax: case gpr_rbx: case gpr_rcx: case gpr_rdx: case gpr_rdi: case gpr_rsi: case gpr_rbp: case gpr_rsp: case gpr_r8: case gpr_r9: case gpr_r10: case gpr_r11: case gpr_r12: case gpr_r13: case gpr_r14: case gpr_r15: case gpr_rip: case gpr_rflags: case gpr_cs: case gpr_fs: case gpr_gs: (&gpr.rax)[reg - gpr_rax] = value.GetAsUInt64(); break; case fpu_fcw: fpu.fcw = value.GetAsUInt16(); break; case fpu_fsw: fpu.fsw = value.GetAsUInt16(); break; case fpu_ftw: fpu.ftw = value.GetAsUInt8(); break; case fpu_fop: fpu.fop = value.GetAsUInt16(); break; case fpu_ip: fpu.ip = value.GetAsUInt32(); break; case fpu_cs: fpu.cs = value.GetAsUInt16(); break; case fpu_dp: fpu.dp = value.GetAsUInt32(); break; case fpu_ds: fpu.ds = value.GetAsUInt16(); break; case fpu_mxcsr: fpu.mxcsr = value.GetAsUInt32(); break; case fpu_mxcsrmask: fpu.mxcsrmask = value.GetAsUInt32(); break; case fpu_stmm0: case fpu_stmm1: case fpu_stmm2: case fpu_stmm3: case fpu_stmm4: case fpu_stmm5: case fpu_stmm6: case fpu_stmm7: ::memcpy (fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize()); break; case fpu_xmm0: case fpu_xmm1: case fpu_xmm2: case fpu_xmm3: case fpu_xmm4: case fpu_xmm5: case fpu_xmm6: case fpu_xmm7: case fpu_xmm8: case fpu_xmm9: case fpu_xmm10: case fpu_xmm11: case fpu_xmm12: case fpu_xmm13: case fpu_xmm14: case fpu_xmm15: ::memcpy (fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), value.GetByteSize()); return false; case exc_trapno: exc.trapno = value.GetAsUInt32(); break; case exc_err: exc.err = value.GetAsUInt32(); break; case exc_faultvaddr: exc.faultvaddr = value.GetAsUInt64(); break; default: return false; } return WriteRegisterSet(set) == 0; }
bool UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, const EmulateInstruction::Context &context, const RegisterInfo *reg_info, const RegisterValue ®_value) { LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); if (log && log->GetVerbose ()) { StreamString strm; strm.Printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ", reg_info->name); reg_value.Dump(&strm, reg_info, false, false, eFormatDefault); strm.PutCString (", context = "); context.Dump(strm, instruction); log->PutCString(strm.GetData()); } const bool must_replace = true; SetRegisterValue (*reg_info, reg_value); switch (context.type) { default: case EmulateInstruction::eContextInvalid: case EmulateInstruction::eContextReadOpcode: case EmulateInstruction::eContextImmediate: case EmulateInstruction::eContextAdjustBaseRegister: case EmulateInstruction::eContextRegisterPlusOffset: case EmulateInstruction::eContextAdjustPC: case EmulateInstruction::eContextRegisterStore: case EmulateInstruction::eContextRegisterLoad: case EmulateInstruction::eContextRelativeBranchImmediate: case EmulateInstruction::eContextAbsoluteBranchRegister: case EmulateInstruction::eContextSupervisorCall: case EmulateInstruction::eContextTableBranchReadMemory: case EmulateInstruction::eContextWriteRegisterRandomBits: case EmulateInstruction::eContextWriteMemoryRandomBits: case EmulateInstruction::eContextArithmetic: case EmulateInstruction::eContextAdvancePC: case EmulateInstruction::eContextReturnFromException: case EmulateInstruction::eContextPushRegisterOnStack: // { // const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; // if (reg_num != LLDB_INVALID_REGNUM) // { // const bool can_replace_only_if_unspecified = true; // // m_curr_row.SetRegisterLocationToUndefined (reg_num, // can_replace_only_if_unspecified, // can_replace_only_if_unspecified); // } // } break; case EmulateInstruction::eContextPopRegisterOffStack: { const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; if (reg_num != LLDB_INVALID_REGNUM) { m_curr_row.SetRegisterLocationToSame (reg_num, must_replace); } } break; case EmulateInstruction::eContextSetFramePointer: if (!m_fp_is_cfa) { m_fp_is_cfa = true; m_cfa_reg_info = *reg_info; const uint32_t cfa_reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; assert (cfa_reg_num != LLDB_INVALID_REGNUM); m_curr_row.SetCFARegister(cfa_reg_num); m_curr_row.SetCFAOffset(m_initial_sp - reg_value.GetAsUInt64()); } break; case EmulateInstruction::eContextAdjustStackPointer: // If we have created a frame using the frame pointer, don't follow // subsequent adjustments to the stack pointer. if (!m_fp_is_cfa) { m_curr_row.SetCFAOffset (m_initial_sp - reg_value.GetAsUInt64()); } break; } return true; }