| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "garnet/bin/debug_agent/arch.h" |
| |
| namespace debug_agent { |
| namespace arch { |
| |
| const BreakInstructionType kBreakInstruction = 0xCC; |
| |
| uint64_t BreakpointInstructionForExceptionAddress(uint64_t exception_addr) { |
| // An X86 exception is 1 byte and a breakpoint exception is triggered with |
| // RIP pointing to the following instruction. |
| return exception_addr - 1; |
| } |
| |
| uint64_t NextInstructionForSoftwareExceptionAddress(uint64_t exception_addr) { |
| // Exception address is the one following the instruction that caused it, |
| // so nothing needs to be done. |
| return exception_addr; |
| } |
| |
| bool IsBreakpointInstruction(zx::process& process, uint64_t address) { |
| uint8_t data; |
| size_t actual_read = 0; |
| if (process.read_memory(address, &data, 1, &actual_read) != ZX_OK || |
| actual_read != 1) |
| return false; |
| |
| // This handles the normal encoding of debug breakpoints (0xCC). It's also |
| // possible to cause an interrupt 3 to happen using the opcode sequence |
| // 0xCD 0x03 but this has slightly different semantics and no assemblers emit |
| // this. We can't easily check for that here since the computation for the |
| // instruction address that is passed in assumes a 1-byte instruction. It |
| // should be OK to ignore this case in practice. |
| return data == kBreakInstruction; |
| } |
| |
| uint64_t* IPInRegs(zx_thread_state_general_regs* regs) { |
| return ®s->rip; |
| } |
| uint64_t* SPInRegs(zx_thread_state_general_regs* regs) { |
| return ®s->rsp; |
| } |
| |
| ::debug_ipc::Arch GetArch() { |
| return ::debug_ipc::Arch::kX64; |
| } |
| |
| |
| } // namespace arch |
| } // namespace debug_agent |