diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:06:29 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:06:29 +0000 |
commit | 94994d372d014ce4c8758b9605d63fae651bd8aa (patch) | |
tree | 51c0b708bd59f205d6b35cb2a8c24d62f0c33d77 /source/Host/common/SoftwareBreakpoint.cpp | |
parent | 39be7ce23363d12ae3e49aeb1fdb2bfeb892e836 (diff) |
Notes
Diffstat (limited to 'source/Host/common/SoftwareBreakpoint.cpp')
-rw-r--r-- | source/Host/common/SoftwareBreakpoint.cpp | 350 |
1 files changed, 0 insertions, 350 deletions
diff --git a/source/Host/common/SoftwareBreakpoint.cpp b/source/Host/common/SoftwareBreakpoint.cpp deleted file mode 100644 index 353dadf6ce6d..000000000000 --- a/source/Host/common/SoftwareBreakpoint.cpp +++ /dev/null @@ -1,350 +0,0 @@ -//===-- SoftwareBreakpoint.cpp ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/common/SoftwareBreakpoint.h" - -#include "lldb/Host/Debug.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" - -#include "lldb/Host/common/NativeProcessProtocol.h" - -using namespace lldb_private; - -// ------------------------------------------------------------------- static -// members ------------------------------------------------------------------- - -Status SoftwareBreakpoint::CreateSoftwareBreakpoint( - NativeProcessProtocol &process, lldb::addr_t addr, size_t size_hint, - NativeBreakpointSP &breakpoint_sp) { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - - // Validate the address. - if (addr == LLDB_INVALID_ADDRESS) - return Status("SoftwareBreakpoint::%s invalid load address specified.", - __FUNCTION__); - - // Ask the NativeProcessProtocol subclass to fill in the correct software - // breakpoint trap for the breakpoint site. - size_t bp_opcode_size = 0; - const uint8_t *bp_opcode_bytes = NULL; - Status error = process.GetSoftwareBreakpointTrapOpcode( - size_hint, bp_opcode_size, bp_opcode_bytes); - - if (error.Fail()) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to retrieve software " - "breakpoint trap opcode: %s", - __FUNCTION__, error.AsCString()); - return error; - } - - // Validate size of trap opcode. - if (bp_opcode_size == 0) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to retrieve any trap opcodes", - __FUNCTION__); - return Status("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() " - "returned zero, unable to get breakpoint trap for address " - "0x%" PRIx64, - addr); - } - - if (bp_opcode_size > MAX_TRAP_OPCODE_SIZE) { - if (log) - log->Printf("SoftwareBreakpoint::%s cannot support %zu trapcode bytes, " - "max size is %zu", - __FUNCTION__, bp_opcode_size, MAX_TRAP_OPCODE_SIZE); - return Status("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() " - "returned too many trap opcode bytes: requires %zu but we " - "only support a max of %zu", - bp_opcode_size, MAX_TRAP_OPCODE_SIZE); - } - - // Validate that we received opcodes. - if (!bp_opcode_bytes) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to retrieve trap opcode bytes", - __FUNCTION__); - return Status("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() " - "returned NULL trap opcode bytes, unable to get breakpoint " - "trap for address 0x%" PRIx64, - addr); - } - - // Enable the breakpoint. - uint8_t saved_opcode_bytes[MAX_TRAP_OPCODE_SIZE]; - error = EnableSoftwareBreakpoint(process, addr, bp_opcode_size, - bp_opcode_bytes, saved_opcode_bytes); - if (error.Fail()) { - if (log) - log->Printf("SoftwareBreakpoint::%s: failed to enable new breakpoint at " - "0x%" PRIx64 ": %s", - __FUNCTION__, addr, error.AsCString()); - return error; - } - - if (log) - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", - __FUNCTION__, addr); - - // Set the breakpoint and verified it was written properly. Now create a - // breakpoint remover that understands how to undo this breakpoint. - breakpoint_sp.reset(new SoftwareBreakpoint(process, addr, saved_opcode_bytes, - bp_opcode_bytes, bp_opcode_size)); - return Status(); -} - -Status SoftwareBreakpoint::EnableSoftwareBreakpoint( - NativeProcessProtocol &process, lldb::addr_t addr, size_t bp_opcode_size, - const uint8_t *bp_opcode_bytes, uint8_t *saved_opcode_bytes) { - assert(bp_opcode_size <= MAX_TRAP_OPCODE_SIZE && - "bp_opcode_size out of valid range"); - assert(bp_opcode_bytes && "bp_opcode_bytes is NULL"); - assert(saved_opcode_bytes && "saved_opcode_bytes is NULL"); - - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - - // Save the original opcodes by reading them so we can restore later. - size_t bytes_read = 0; - - Status error = - process.ReadMemory(addr, saved_opcode_bytes, bp_opcode_size, bytes_read); - if (error.Fail()) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to read memory while " - "attempting to set breakpoint: %s", - __FUNCTION__, error.AsCString()); - return error; - } - - // Ensure we read as many bytes as we expected. - if (bytes_read != bp_opcode_size) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to read memory while " - "attempting to set breakpoint: attempted to read %zu bytes " - "but only read %zu", - __FUNCTION__, bp_opcode_size, bytes_read); - return Status("SoftwareBreakpoint::%s failed to read memory while " - "attempting to set breakpoint: attempted to read %zu bytes " - "but only read %zu", - __FUNCTION__, bp_opcode_size, bytes_read); - } - - // Log what we read. - if (log) { - int i = 0; - for (const uint8_t *read_byte = saved_opcode_bytes; - read_byte < saved_opcode_bytes + bp_opcode_size; ++read_byte) { - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 - " ovewriting byte index %d (was 0x%hhx)", - __FUNCTION__, addr, i++, *read_byte); - } - } - - // Write a software breakpoint in place of the original opcode. - size_t bytes_written = 0; - error = - process.WriteMemory(addr, bp_opcode_bytes, bp_opcode_size, bytes_written); - if (error.Fail()) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to write memory while " - "attempting to set breakpoint: %s", - __FUNCTION__, error.AsCString()); - return error; - } - - // Ensure we wrote as many bytes as we expected. - if (bytes_written != bp_opcode_size) { - error.SetErrorStringWithFormat( - "SoftwareBreakpoint::%s failed write memory while attempting to set " - "breakpoint: attempted to write %zu bytes but only wrote %zu", - __FUNCTION__, bp_opcode_size, bytes_written); - if (log) - log->PutCString(error.AsCString()); - return error; - } - - uint8_t verify_bp_opcode_bytes[MAX_TRAP_OPCODE_SIZE]; - size_t verify_bytes_read = 0; - error = process.ReadMemory(addr, verify_bp_opcode_bytes, bp_opcode_size, - verify_bytes_read); - if (error.Fail()) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to read memory while " - "attempting to verify the breakpoint set: %s", - __FUNCTION__, error.AsCString()); - return error; - } - - // Ensure we read as many verification bytes as we expected. - if (verify_bytes_read != bp_opcode_size) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to read memory while " - "attempting to verify breakpoint: attempted to read %zu " - "bytes but only read %zu", - __FUNCTION__, bp_opcode_size, verify_bytes_read); - return Status( - "SoftwareBreakpoint::%s failed to read memory while " - "attempting to verify breakpoint: attempted to read %zu bytes " - "but only read %zu", - __FUNCTION__, bp_opcode_size, verify_bytes_read); - } - - if (::memcmp(bp_opcode_bytes, verify_bp_opcode_bytes, bp_opcode_size) != 0) { - if (log) - log->Printf("SoftwareBreakpoint::%s: verification of software breakpoint " - "writing failed - trap opcodes not successfully read back " - "after writing when setting breakpoint at 0x%" PRIx64, - __FUNCTION__, addr); - return Status("SoftwareBreakpoint::%s: verification of software breakpoint " - "writing failed - trap opcodes not successfully read back " - "after writing when setting breakpoint at 0x%" PRIx64, - __FUNCTION__, addr); - } - - if (log) - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", - __FUNCTION__, addr); - - return Status(); -} - -// ------------------------------------------------------------------- -// instance-level members -// ------------------------------------------------------------------- - -SoftwareBreakpoint::SoftwareBreakpoint(NativeProcessProtocol &process, - lldb::addr_t addr, - const uint8_t *saved_opcodes, - const uint8_t *trap_opcodes, - size_t opcode_size) - : NativeBreakpoint(addr), m_process(process), m_saved_opcodes(), - m_trap_opcodes(), m_opcode_size(opcode_size) { - assert(opcode_size > 0 && "setting software breakpoint with no trap opcodes"); - assert(opcode_size <= MAX_TRAP_OPCODE_SIZE && "trap opcode size too large"); - - ::memcpy(m_saved_opcodes, saved_opcodes, opcode_size); - ::memcpy(m_trap_opcodes, trap_opcodes, opcode_size); -} - -Status SoftwareBreakpoint::DoEnable() { - return EnableSoftwareBreakpoint(m_process, m_addr, m_opcode_size, - m_trap_opcodes, m_saved_opcodes); -} - -Status SoftwareBreakpoint::DoDisable() { - Status error; - assert(m_addr && (m_addr != LLDB_INVALID_ADDRESS) && - "can't remove a software breakpoint for an invalid address"); - - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, - m_addr); - - assert((m_opcode_size > 0) && - "cannot restore opcodes when there are no opcodes"); - - if (m_opcode_size > 0) { - // Clear a software breakpoint instruction - uint8_t curr_break_op[MAX_TRAP_OPCODE_SIZE]; - bool break_op_found = false; - assert(m_opcode_size <= sizeof(curr_break_op)); - - // Read the breakpoint opcode - size_t bytes_read = 0; - error = - m_process.ReadMemory(m_addr, curr_break_op, m_opcode_size, bytes_read); - if (error.Success() && bytes_read < m_opcode_size) { - error.SetErrorStringWithFormat( - "SoftwareBreakpointr::%s addr=0x%" PRIx64 - ": tried to read %zu bytes but only read %zu", - __FUNCTION__, m_addr, m_opcode_size, bytes_read); - } - if (error.Success()) { - bool verify = false; - // Make sure the breakpoint opcode exists at this address - if (::memcmp(curr_break_op, m_trap_opcodes, m_opcode_size) == 0) { - break_op_found = true; - // We found a valid breakpoint opcode at this address, now restore the - // saved opcode. - size_t bytes_written = 0; - error = m_process.WriteMemory(m_addr, m_saved_opcodes, m_opcode_size, - bytes_written); - if (error.Success() && bytes_written < m_opcode_size) { - error.SetErrorStringWithFormat( - "SoftwareBreakpoint::%s addr=0x%" PRIx64 - ": tried to write %zu bytes but only wrote %zu", - __FUNCTION__, m_addr, m_opcode_size, bytes_written); - } - if (error.Success()) { - verify = true; - } - } else { - error.SetErrorString( - "Original breakpoint trap is no longer in memory."); - // Set verify to true and so we can check if the original opcode has - // already been restored - verify = true; - } - - if (verify) { - uint8_t verify_opcode[MAX_TRAP_OPCODE_SIZE]; - assert(m_opcode_size <= sizeof(verify_opcode)); - // Verify that our original opcode made it back to the inferior - - size_t verify_bytes_read = 0; - error = m_process.ReadMemory(m_addr, verify_opcode, m_opcode_size, - verify_bytes_read); - if (error.Success() && verify_bytes_read < m_opcode_size) { - error.SetErrorStringWithFormat( - "SoftwareBreakpoint::%s addr=0x%" PRIx64 - ": tried to read %zu verification bytes but only read %zu", - __FUNCTION__, m_addr, m_opcode_size, verify_bytes_read); - } - if (error.Success()) { - // compare the memory we just read with the original opcode - if (::memcmp(m_saved_opcodes, verify_opcode, m_opcode_size) == 0) { - // SUCCESS - if (log) { - int i = 0; - for (const uint8_t *verify_byte = verify_opcode; - verify_byte < verify_opcode + m_opcode_size; ++verify_byte) { - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 - " replaced byte index %d with 0x%hhx", - __FUNCTION__, m_addr, i++, *verify_byte); - } - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 - " -- SUCCESS", - __FUNCTION__, m_addr); - } - return error; - } else { - if (break_op_found) - error.SetErrorString("Failed to restore original opcode."); - } - } else - error.SetErrorString("Failed to read memory to verify that " - "breakpoint trap was restored."); - } - } - } - - if (log && error.Fail()) - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- FAILED: %s", - __FUNCTION__, m_addr, error.AsCString()); - return error; -} - -bool SoftwareBreakpoint::IsSoftwareBreakpoint() const { return true; } |