blob: 1f5be8c2e3ad46c63516796f6fbf53f9e3074b86 [file] [log] [blame]
// 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 &regs->rip;
}
uint64_t* SPInRegs(zx_thread_state_general_regs* regs) {
return &regs->rsp;
}
::debug_ipc::Arch GetArch() {
return ::debug_ipc::Arch::kX64;
}
} // namespace arch
} // namespace debug_agent