DBGFBp.cpp revision eb2281916491963d4c6ae8d12910d7cd53d21015
/* $Id$ */
/** @file
* DBGF - Debugger Facility, Breakpoint Management.
*/
/*
* Copyright (C) 2006-2007 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_DBGF
#ifdef VBOX_WITH_REM
#else
#endif
#include "DBGFInternal.h"
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
/**
* Initialize the breakpoint stuff.
*
* @returns VINF_SUCCESS
* @param pVM Pointer to the VM.
*/
{
/*
* Init structures.
*/
unsigned i;
{
}
{
}
{
}
/*
* Register saved state.
*/
/** @todo */
return VINF_SUCCESS;
}
/**
* Allocate a breakpoint.
*
* @returns Pointer to the allocated breakpoint.
* @returns NULL if we're out of breakpoints.
* @param pVM Pointer to the VM.
* @param enmType The type to allocate.
*/
{
/*
* Determine which array to search.
*/
unsigned cBps;
switch (enmType)
{
case DBGFBPTYPE_REG:
break;
case DBGFBPTYPE_INT3:
case DBGFBPTYPE_REM:
break;
default:
return NULL;
}
/*
* Search.
*/
{
++*pcBpsCur;
}
return NULL;
}
/**
* Get a breakpoint give by breakpoint id.
*
* @returns Pointer to the allocated breakpoint.
* @returns NULL if the breakpoint is invalid.
* @param pVM Pointer to the VM.
* @param iBp The breakpoint id.
*/
{
/* Find it. */
else
{
return NULL;
}
/* check if it's valid. */
{
case DBGFBPTYPE_FREE:
return NULL;
case DBGFBPTYPE_REG:
case DBGFBPTYPE_INT3:
case DBGFBPTYPE_REM:
break;
default:
return NULL;
}
return pBp;
}
/**
* Get a breakpoint give by address.
*
* @returns Pointer to the allocated breakpoint.
* @returns NULL if the breakpoint is invalid.
* @param pVM Pointer to the VM.
* @param enmType The breakpoint type.
* @param GCPtr The breakpoint address.
*/
{
/*
* Determine which array to search.
*/
unsigned cBps;
switch (enmType)
{
case DBGFBPTYPE_REG:
break;
case DBGFBPTYPE_INT3:
case DBGFBPTYPE_REM:
break;
default:
return NULL;
}
/*
* Search.
*/
{
}
return NULL;
}
/**
* Frees a breakpoint.
*
* @param pVM Pointer to the VM.
* @param pBp The breakpoint to free.
*/
{
{
case DBGFBPTYPE_FREE:
AssertMsgFailed(("Already freed!\n"));
return;
case DBGFBPTYPE_REG:
break;
case DBGFBPTYPE_INT3:
case DBGFBPTYPE_REM:
break;
default:
return;
}
}
/**
* Sets a breakpoint (int 3 based).
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param pAddress The address of the breakpoint.
* @param piHitTrigger The hit count at which the breakpoint start triggering.
* Use 0 (or 1) if it's gonna trigger at once.
* @param piHitDisable The hit count which disables the breakpoint.
* Use ~(uint64_t) if it's never gonna be disabled.
* @param piBp Where to store the breakpoint id. (optional)
* @thread Any thread.
*/
{
/*
* Validate input.
*/
return VERR_INVALID_PARAMETER;
if (*piHitTrigger > *piHitDisable)
return VERR_INVALID_PARAMETER;
if (piBp)
*piBp = ~0;
/*
* Check if the breakpoint already exists.
*/
if (pBp)
{
int rc = VINF_SUCCESS;
if (RT_SUCCESS(rc))
{
if (piBp)
}
return rc;
}
/*
* Allocate and initialize the bp.
*/
if (!pBp)
return VERR_DBGF_NO_MORE_BP_SLOTS;
/*
* Now ask REM to set the breakpoint.
*/
if (RT_SUCCESS(rc))
{
if (piBp)
}
else
return rc;
}
/**
* Sets a breakpoint (int 3 based).
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param pAddress The address of the breakpoint.
* @param iHitTrigger The hit count at which the breakpoint start triggering.
* Use 0 (or 1) if it's gonna trigger at once.
* @param iHitDisable The hit count which disables the breakpoint.
* Use ~(uint64_t) if it's never gonna be disabled.
* @param piBp Where to store the breakpoint id. (optional)
* @thread Any thread.
*/
VMMR3DECL(int) DBGFR3BpSet(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp)
{
/*
* This must be done on EMT.
*/
/** @todo SMP? */
return rc;
}
/**
* Arms an int 3 breakpoint.
* This is used to implement both DBGFR3BpSetReg() and DBGFR3BpEnable().
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param pBp The breakpoint.
*/
{
/** @todo should actually use physical address here! */
/** @todo SMP support! */
/*
* Save current byte and write int3 instruction.
*/
if (RT_SUCCESS(rc))
{
}
return rc;
}
/**
* Disarms an int 3 breakpoint.
* This is used to implement both DBGFR3BpClear() and DBGFR3BpDisable().
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param pBp The breakpoint.
*/
{
/* @todo SMP support! */
/*
* Check that the current byte is the int3 instruction, and restore the original one.
* We currently ignore invalid bytes.
*/
if (bCurrent == 0xcc)
return rc;
}
/**
* Sets a register breakpoint.
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param pAddress The address of the breakpoint.
* @param piHitTrigger The hit count at which the breakpoint start triggering.
* Use 0 (or 1) if it's gonna trigger at once.
* @param piHitDisable The hit count which disables the breakpoint.
* Use ~(uint64_t) if it's never gonna be disabled.
* @param fType The access type (one of the X86_DR7_RW_* defines).
* @param cb The access size - 1,2,4 or 8 (the latter is AMD64 long mode only.
* Must be 1 if fType is X86_DR7_RW_EO.
* @param piBp Where to store the breakpoint id. (optional)
* @thread EMT
* @internal
*/
static DECLCALLBACK(int) dbgfR3BpSetReg(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t *piHitTrigger, uint64_t *piHitDisable,
{
/*
* Validate input.
*/
return VERR_INVALID_PARAMETER;
if (*piHitTrigger > *piHitDisable)
return VERR_INVALID_PARAMETER;
if (piBp)
*piBp = ~0;
switch (fType)
{
case X86_DR7_RW_EO:
if (cb == 1)
break;
return VERR_INVALID_PARAMETER;
case X86_DR7_RW_IO:
case X86_DR7_RW_RW:
case X86_DR7_RW_WO:
break;
default:
return VERR_INVALID_PARAMETER;
}
switch (cb)
{
case 1:
case 2:
case 4:
break;
default:
return VERR_INVALID_PARAMETER;
}
/*
* Check if the breakpoint already exists.
*/
if ( pBp
{
int rc = VINF_SUCCESS;
if (RT_SUCCESS(rc))
{
if (piBp)
}
return rc;
}
/*
* Allocate and initialize the bp.
*/
if (!pBp)
return VERR_DBGF_NO_MORE_BP_SLOTS;
/*
* Arm the breakpoint.
*/
if (RT_SUCCESS(rc))
{
if (piBp)
}
else
return rc;
}
/**
* Sets a register breakpoint.
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param pAddress The address of the breakpoint.
* @param iHitTrigger The hit count at which the breakpoint start triggering.
* Use 0 (or 1) if it's gonna trigger at once.
* @param iHitDisable The hit count which disables the breakpoint.
* Use ~(uint64_t) if it's never gonna be disabled.
* @param fType The access type (one of the X86_DR7_RW_* defines).
* @param cb The access size - 1,2,4 or 8 (the latter is AMD64 long mode only.
* Must be 1 if fType is X86_DR7_RW_EO.
* @param piBp Where to store the breakpoint id. (optional)
* @thread Any thread.
*/
VMMR3DECL(int) DBGFR3BpSetReg(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable,
{
/*
* This must be done on EMT.
*/
return rc;
}
/** @callback_method_impl{FNVMMEMTRENDEZVOUS} */
{
return CPUMRecalcHyperDRx(pVCpu);
}
/**
* Arms a debug register breakpoint.
* This is used to implement both DBGFR3BpSetReg() and DBGFR3BpEnable().
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param pBp The breakpoint.
*/
{
return VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3BpRegRecalcOnCpu, NULL);
}
/**
* Disarms a debug register breakpoint.
* This is used to implement both DBGFR3BpClear() and DBGFR3BpDisable().
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param pBp The breakpoint.
*/
{
return VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3BpRegRecalcOnCpu, NULL);
}
/**
* EMT worker for DBGFR3BpSetREM().
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param pAddress The address of the breakpoint.
* @param piHitTrigger The hit count at which the breakpoint start triggering.
* Use 0 (or 1) if it's gonna trigger at once.
* @param piHitDisable The hit count which disables the breakpoint.
* Use ~(uint64_t) if it's never gonna be disabled.
* @param piBp Where to store the breakpoint id. (optional)
* @thread EMT
* @internal
*/
{
/*
* Validate input.
*/
return VERR_INVALID_PARAMETER;
if (*piHitTrigger > *piHitDisable)
return VERR_INVALID_PARAMETER;
if (piBp)
*piBp = ~0;
/*
* Check if the breakpoint already exists.
*/
if (pBp)
{
int rc = VINF_SUCCESS;
#ifdef VBOX_WITH_REM
#else
#endif
if (RT_SUCCESS(rc))
{
if (piBp)
}
return rc;
}
/*
* Allocate and initialize the bp.
*/
if (!pBp)
return VERR_DBGF_NO_MORE_BP_SLOTS;
/*
* Now ask REM to set the breakpoint.
*/
#ifdef VBOX_WITH_REM
#else
#endif
if (RT_SUCCESS(rc))
{
if (piBp)
}
else
return rc;
}
/**
* Sets a recompiler breakpoint.
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param pAddress The address of the breakpoint.
* @param iHitTrigger The hit count at which the breakpoint start triggering.
* Use 0 (or 1) if it's gonna trigger at once.
* @param iHitDisable The hit count which disables the breakpoint.
* Use ~(uint64_t) if it's never gonna be disabled.
* @param piBp Where to store the breakpoint id. (optional)
* @thread Any thread.
*/
VMMR3DECL(int) DBGFR3BpSetREM(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp)
{
/*
* This must be done on EMT.
*/
return rc;
}
/**
* EMT worker for DBGFR3BpClear().
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param iBp The id of the breakpoint which should be removed (cleared).
* @thread EMT
* @internal
*/
{
/*
* Validate input.
*/
if (!pBp)
return VERR_DBGF_BP_NOT_FOUND;
/*
* Disarm the breakpoint if it's enabled.
*/
{
int rc;
{
case DBGFBPTYPE_REG:
break;
case DBGFBPTYPE_INT3:
break;
case DBGFBPTYPE_REM:
#ifdef VBOX_WITH_REM
#else
#endif
break;
default:
}
}
/*
* Free the breakpoint.
*/
return VINF_SUCCESS;
}
/**
* Clears a breakpoint.
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param iBp The id of the breakpoint which should be removed (cleared).
* @thread Any thread.
*/
{
/*
* This must be done on EMT.
*/
return rc;
}
/**
* EMT worker for DBGFR3BpEnable().
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param iBp The id of the breakpoint which should be enabled.
* @thread EMT
* @internal
*/
{
/*
* Validate input.
*/
if (!pBp)
return VERR_DBGF_BP_NOT_FOUND;
/*
* Already enabled?
*/
return VINF_DBGF_BP_ALREADY_ENABLED;
/*
* Remove the breakpoint.
*/
int rc;
{
case DBGFBPTYPE_REG:
break;
case DBGFBPTYPE_INT3:
break;
case DBGFBPTYPE_REM:
#ifdef VBOX_WITH_REM
#else
#endif
break;
default:
}
if (RT_FAILURE(rc))
return rc;
}
/**
* Enables a breakpoint.
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param iBp The id of the breakpoint which should be enabled.
* @thread Any thread.
*/
{
/*
* This must be done on EMT.
*/
return rc;
}
/**
* EMT worker for DBGFR3BpDisable().
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param iBp The id of the breakpoint which should be disabled.
* @thread EMT
* @internal
*/
{
/*
* Validate input.
*/
if (!pBp)
return VERR_DBGF_BP_NOT_FOUND;
/*
* Already enabled?
*/
return VINF_DBGF_BP_ALREADY_DISABLED;
/*
* Remove the breakpoint.
*/
int rc;
{
case DBGFBPTYPE_REG:
break;
case DBGFBPTYPE_INT3:
break;
case DBGFBPTYPE_REM:
#ifdef VBOX_WITH_REM
#else
#endif
break;
default:
}
return rc;
}
/**
* Disables a breakpoint.
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param iBp The id of the breakpoint which should be disabled.
* @thread Any thread.
*/
{
/*
* This must be done on EMT.
*/
return rc;
}
/**
* EMT worker for DBGFR3BpEnum().
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param pfnCallback The callback function.
* @param pvUser The user argument to pass to the callback.
* @thread EMT
* @internal
*/
{
/*
* Validate input.
*/
/*
* Enumerate the hardware breakpoints.
*/
unsigned i;
{
if (RT_FAILURE(rc))
return rc;
}
/*
* Enumerate the other breakpoints.
*/
{
if (RT_FAILURE(rc))
return rc;
}
return VINF_SUCCESS;
}
/**
* Enumerate the breakpoints.
*
* @returns VBox status code.
* @param pUVM The user mode VM handle.
* @param pfnCallback The callback function.
* @param pvUser The user argument to pass to the callback.
* @thread Any thread but the callback will be called from EMT.
*/
{
/*
* This must be done on EMT.
*/
int rc = VMR3ReqPriorityCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpEnum, 3, pUVM, pfnCallback, pvUser);
return rc;
}