//===-- 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/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Host/Debug.h"

#include "lldb/Host/common/NativeProcessProtocol.h"

using namespace lldb_private;

// -------------------------------------------------------------------
// static members
// -------------------------------------------------------------------

Error
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 Error ("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;
    Error 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 Error ("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 %lu trapcode bytes, max size is %lu", __FUNCTION__, bp_opcode_size, MAX_TRAP_OPCODE_SIZE);
        return Error ("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() returned too many trap opcode bytes: requires %lu but we only support a max of %lu", 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 Error ("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 Error ();
}

Error
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;

    Error 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 %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)bytes_read);
        return Error ("SoftwareBreakpoint::%s failed to read memory while attempting to set breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)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 %lu bytes but only wrote %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)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 %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)verify_bytes_read);
        return Error ("SoftwareBreakpoint::%s failed to read memory while attempting to verify breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, (uint64_t)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 Error ("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 Error ();
}

// -------------------------------------------------------------------
// 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);
}

Error
SoftwareBreakpoint::DoEnable ()
{
    return EnableSoftwareBreakpoint (m_process, m_addr, m_opcode_size, m_trap_opcodes, m_saved_opcodes);
}

Error
SoftwareBreakpoint::DoDisable ()
{
    Error 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 %lu bytes but only read %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, (uint64_t)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 %lu bytes but only wrote %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, (uint64_t)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 %lu verification bytes but only read %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, (uint64_t)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;
}

