4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* $Id$ */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * DBGF - Debugger Facility, Breakpoint Management.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Copyright (C) 2006-2013 Oracle Corporation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * available from http://www.virtualbox.org. This file is free software;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * you can redistribute it and/or modify it under the terms of the GNU
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * General Public License (GPL) as published by the Free Software
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*******************************************************************************
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync* Header Files *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*******************************************************************************/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define LOG_GROUP LOG_GROUP_DBGF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/vmm/dbgf.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/vmm/selm.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef VBOX_WITH_REM
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync# include <VBox/vmm/rem.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync# include <VBox/vmm/iem.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/vmm/mm.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "DBGFInternal.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/vmm/vm.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/vmm/uvm.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/err.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/log.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/assert.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/string.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*******************************************************************************
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync* Internal Functions *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*******************************************************************************/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncRT_C_DECLS_BEGIN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int dbgfR3BpRegArm(PVM pVM, PDBGFBP pBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int dbgfR3BpInt3Arm(PUVM pUVM, PDBGFBP pBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncRT_C_DECLS_END
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Initialize the breakpoint stuff.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VINF_SUCCESS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pVM Pointer to the VM.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncint dbgfR3BpInit(PVM pVM)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Init structures.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync unsigned i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); i++)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVM->dbgf.s.aHwBreakpoints[i].iBp = i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVM->dbgf.s.aHwBreakpoints[i].enmType = DBGFBPTYPE_FREE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVM->dbgf.s.aHwBreakpoints[i].u.Reg.iReg = i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); i++)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVM->dbgf.s.aBreakpoints[i].iBp = i + RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVM->dbgf.s.aBreakpoints[i].enmType = DBGFBPTYPE_FREE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVMCPU pVCpu = &pVM->aCpus[idCpu];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVCpu->dbgf.s.iActiveBp = ~0U;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Register saved state.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /** @todo */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Allocate a breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns Pointer to the allocated breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns NULL if we're out of breakpoints.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pVM Pointer to the VM.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param enmType The type to allocate.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic PDBGFBP dbgfR3BpAlloc(PVM pVM, DBGFBPTYPE enmType)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Determine which array to search.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync unsigned cBps;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t *pcBpsCur;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PDBGFBP paBps;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (enmType)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_REG:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cBps = RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync paBps = &pVM->dbgf.s.aHwBreakpoints[0];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pcBpsCur = &pVM->dbgf.s.cHwBreakpoints;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_INT3:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_REM:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cBps = RT_ELEMENTS(pVM->dbgf.s.aBreakpoints);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync paBps = &pVM->dbgf.s.aBreakpoints[0];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pcBpsCur = &pVM->dbgf.s.cBreakpoints;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("enmType=%d\n", enmType));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Search.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (unsigned iBp = 0; iBp < cBps; iBp++)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (paBps[iBp].enmType == DBGFBPTYPE_FREE)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ++*pcBpsCur;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync paBps[iBp].cHits = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync paBps[iBp].enmType = enmType;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return &paBps[iBp];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LogFlow(("dbgfR3BpAlloc: returns NULL - we're out of breakpoint slots! %u/%u\n", *pcBpsCur, cBps));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Get a breakpoint give by breakpoint id.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns Pointer to the allocated breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns NULL if the breakpoint is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pVM Pointer to the VM.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param iBp The breakpoint id.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic PDBGFBP dbgfR3BpGet(PVM pVM, uint32_t iBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Find it. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PDBGFBP pBp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (iBp < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp = &pVM->dbgf.s.aHwBreakpoints[iBp];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync iBp -= RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (iBp >= RT_ELEMENTS(pVM->dbgf.s.aBreakpoints))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp = &pVM->dbgf.s.aBreakpoints[iBp];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* check if it's valid. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (pBp->enmType)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_FREE:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_REG:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_INT3:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_REM:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("Invalid enmType=%d!\n", pBp->enmType));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return pBp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Get a breakpoint give by address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns Pointer to the allocated breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns NULL if the breakpoint is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pVM Pointer to the VM.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param enmType The breakpoint type.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param GCPtr The breakpoint address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic PDBGFBP dbgfR3BpGetByAddr(PVM pVM, DBGFBPTYPE enmType, RTGCUINTPTR GCPtr)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Determine which array to search.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync unsigned cBps;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PDBGFBP paBps;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (enmType)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_REG:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cBps = RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync paBps = &pVM->dbgf.s.aHwBreakpoints[0];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_INT3:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_REM:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cBps = RT_ELEMENTS(pVM->dbgf.s.aBreakpoints);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync paBps = &pVM->dbgf.s.aBreakpoints[0];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("enmType=%d\n", enmType));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Search.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (unsigned iBp = 0; iBp < cBps; iBp++)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ( paBps[iBp].enmType == enmType
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && paBps[iBp].GCPtr == GCPtr)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return &paBps[iBp];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Frees a breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pVM Pointer to the VM.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pBp The breakpoint to free.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void dbgfR3BpFree(PVM pVM, PDBGFBP pBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (pBp->enmType)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_FREE:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("Already freed!\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_REG:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pVM->dbgf.s.cHwBreakpoints > 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVM->dbgf.s.cHwBreakpoints--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_INT3:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_REM:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pVM->dbgf.s.cBreakpoints > 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pVM->dbgf.s.cBreakpoints--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("Invalid enmType=%d!\n", pBp->enmType));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->enmType = DBGFBPTYPE_FREE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Sets a breakpoint (int 3 based).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VBox status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pUVM The user mode VM handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pAddress The address of the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param piHitTrigger The hit count at which the breakpoint start triggering.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Use 0 (or 1) if it's gonna trigger at once.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param piHitDisable The hit count which disables the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Use ~(uint64_t) if it's never gonna be disabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param piBp Where to store the breakpoint id. (optional)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @thread Any thread.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(int) dbgfR3BpSetInt3(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t *piHitTrigger,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint64_t *piHitDisable, uint32_t *piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Validate input.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVM pVM = pUVM->pVM;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!DBGFR3AddrIsValid(pUVM, pAddress))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*piHitTrigger > *piHitDisable)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgReturn(!piBp || VALID_PTR(piBp), ("piBp=%p\n", piBp), VERR_INVALID_POINTER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *piBp = ~0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Check if the breakpoint already exists.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PDBGFBP pBp = dbgfR3BpGetByAddr(pVM, DBGFBPTYPE_INT3, pAddress->FlatPtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pBp->fEnabled)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = dbgfR3BpInt3Arm(pUVM, pBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = VINF_DBGF_BP_ALREADY_EXIST;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *piBp = pBp->iBp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Allocate and initialize the bp.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp = dbgfR3BpAlloc(pVM, DBGFBPTYPE_INT3);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_DBGF_NO_MORE_BP_SLOTS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->GCPtr = pAddress->FlatPtr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->iHitTrigger = *piHitTrigger;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->iHitDisable = *piHitDisable;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->fEnabled = true;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Now ask REM to set the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = dbgfR3BpInt3Arm(pUVM, pBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *piBp = pBp->iBp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dbgfR3BpFree(pVM, pBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Sets a breakpoint (int 3 based).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VBox status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pUVM The user mode VM handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pAddress The address of the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param iHitTrigger The hit count at which the breakpoint start triggering.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Use 0 (or 1) if it's gonna trigger at once.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param iHitDisable The hit count which disables the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Use ~(uint64_t) if it's never gonna be disabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param piBp Where to store the breakpoint id. (optional)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @thread Any thread.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVMMR3DECL(int) DBGFR3BpSet(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This must be done on EMT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /** @todo SMP? */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetInt3, 5,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pUVM, pAddress, &iHitTrigger, &iHitDisable, piBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LogFlow(("DBGFR3BpSet: returns %Rrc\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Arms an int 3 breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This is used to implement both DBGFR3BpSetReg() and DBGFR3BpEnable().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VBox status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pUVM The user mode VM handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pBp The breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int dbgfR3BpInt3Arm(PUVM pUVM, PDBGFBP pBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /** @todo should actually use physical address here! */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /** @todo SMP support! */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VMCPUID idCpu = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Save current byte and write int3 instruction.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DBGFADDRESS Addr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DBGFR3AddrFromFlat(pUVM, &Addr, pBp->GCPtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = DBGFR3MemRead(pUVM, idCpu, &Addr, &pBp->u.Int3.bOrg, 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync static const uint8_t s_bInt3 = 0xcc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = DBGFR3MemWrite(pUVM, idCpu, &Addr, &s_bInt3, 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Disarms an int 3 breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This is used to implement both DBGFR3BpClear() and DBGFR3BpDisable().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VBox status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pUVM The user mode VM handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pBp The breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int dbgfR3BpInt3Disarm(PUVM pUVM, PDBGFBP pBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* @todo SMP support! */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VMCPUID idCpu = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Check that the current byte is the int3 instruction, and restore the original one.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * We currently ignore invalid bytes.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DBGFADDRESS Addr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DBGFR3AddrFromFlat(pUVM, &Addr, pBp->GCPtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint8_t bCurrent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = DBGFR3MemRead(pUVM, idCpu, &Addr, &bCurrent, 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (bCurrent == 0xcc)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = DBGFR3MemWrite(pUVM, idCpu, &Addr, &pBp->u.Int3.bOrg, 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Sets a register breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VBox status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pUVM The user mode VM handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pAddress The address of the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param piHitTrigger The hit count at which the breakpoint start triggering.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Use 0 (or 1) if it's gonna trigger at once.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param piHitDisable The hit count which disables the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Use ~(uint64_t) if it's never gonna be disabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param fType The access type (one of the X86_DR7_RW_* defines).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param cb The access size - 1,2,4 or 8 (the latter is AMD64 long mode only.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Must be 1 if fType is X86_DR7_RW_EO.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param piBp Where to store the breakpoint id. (optional)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @thread EMT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @internal
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(int) dbgfR3BpSetReg(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t *piHitTrigger, uint64_t *piHitDisable,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint8_t fType, uint8_t cb, uint32_t *piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Validate input.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVM pVM = pUVM->pVM;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!DBGFR3AddrIsValid(pUVM, pAddress))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*piHitTrigger > *piHitDisable)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgReturn(!piBp || VALID_PTR(piBp), ("piBp=%p\n", piBp), VERR_INVALID_POINTER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *piBp = ~0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (fType)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case X86_DR7_RW_EO:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cb == 1)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("fType=%#x cb=%d != 1\n", fType, cb));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case X86_DR7_RW_IO:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case X86_DR7_RW_RW:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case X86_DR7_RW_WO:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("fType=%#x\n", fType));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (cb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case 1:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case 2:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case 4:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailed(("cb=%#x\n", cb));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Check if the breakpoint already exists.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PDBGFBP pBp = dbgfR3BpGetByAddr(pVM, DBGFBPTYPE_REG, pAddress->FlatPtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ( pBp
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && pBp->u.Reg.cb == cb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && pBp->u.Reg.fType == fType)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pBp->fEnabled)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = dbgfR3BpRegArm(pVM, pBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = VINF_DBGF_BP_ALREADY_EXIST;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *piBp = pBp->iBp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Allocate and initialize the bp.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp = dbgfR3BpAlloc(pVM, DBGFBPTYPE_REG);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_DBGF_NO_MORE_BP_SLOTS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->GCPtr = pAddress->FlatPtr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->iHitTrigger = *piHitTrigger;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->iHitDisable = *piHitDisable;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->fEnabled = true;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pBp->iBp == pBp->u.Reg.iReg);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->u.Reg.fType = fType;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->u.Reg.cb = cb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Arm the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = dbgfR3BpRegArm(pVM, pBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *piBp = pBp->iBp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dbgfR3BpFree(pVM, pBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Sets a register breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VBox status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pUVM The user mode VM handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pAddress The address of the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param iHitTrigger The hit count at which the breakpoint start triggering.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Use 0 (or 1) if it's gonna trigger at once.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param iHitDisable The hit count which disables the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Use ~(uint64_t) if it's never gonna be disabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param fType The access type (one of the X86_DR7_RW_* defines).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param cb The access size - 1,2,4 or 8 (the latter is AMD64 long mode only.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Must be 1 if fType is X86_DR7_RW_EO.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param piBp Where to store the breakpoint id. (optional)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @thread Any thread.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVMMR3DECL(int) DBGFR3BpSetReg(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint8_t fType, uint8_t cb, uint32_t *piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This must be done on EMT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetReg, 7,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pUVM, pAddress, &iHitTrigger, &iHitDisable, fType, cb, piBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LogFlow(("DBGFR3BpSetReg: returns %Rrc\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @callback_method_impl{FNVMMEMTRENDEZVOUS} */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLCALLBACK(VBOXSTRICTRC) dbgfR3BpRegRecalcOnCpu(PVM pVM, PVMCPU pVCpu, void *pvUser)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NOREF(pVM); NOREF(pvUser);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return CPUMRecalcHyperDRx(pVCpu, UINT8_MAX, false);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Arms a debug register breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This is used to implement both DBGFR3BpSetReg() and DBGFR3BpEnable().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VBox status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pUVM The user mode VM handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pBp The breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int dbgfR3BpRegArm(PVM pVM, PDBGFBP pBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(pBp->fEnabled);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3BpRegRecalcOnCpu, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Disarms a debug register breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This is used to implement both DBGFR3BpClear() and DBGFR3BpDisable().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VBox status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pUVM The user mode VM handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pBp The breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int dbgfR3BpRegDisarm(PVM pVM, PDBGFBP pBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Assert(!pBp->fEnabled);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3BpRegRecalcOnCpu, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * EMT worker for DBGFR3BpSetREM().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VBox status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pUVM The user mode VM handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pAddress The address of the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param piHitTrigger The hit count at which the breakpoint start triggering.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Use 0 (or 1) if it's gonna trigger at once.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param piHitDisable The hit count which disables the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Use ~(uint64_t) if it's never gonna be disabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param piBp Where to store the breakpoint id. (optional)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @thread EMT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @internal
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(int) dbgfR3BpSetREM(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t *piHitTrigger,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint64_t *piHitDisable, uint32_t *piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Validate input.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVM pVM = pUVM->pVM;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!DBGFR3AddrIsValid(pUVM, pAddress))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*piHitTrigger > *piHitDisable)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgReturn(!piBp || VALID_PTR(piBp), ("piBp=%p\n", piBp), VERR_INVALID_POINTER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *piBp = ~0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Check if the breakpoint already exists.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PDBGFBP pBp = dbgfR3BpGetByAddr(pVM, DBGFBPTYPE_REM, pAddress->FlatPtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pBp->fEnabled)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef VBOX_WITH_REM
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = REMR3BreakpointSet(pVM, pBp->GCPtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = IEMBreakpointSet(pVM, pBp->GCPtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = VINF_DBGF_BP_ALREADY_EXIST;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *piBp = pBp->iBp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Allocate and initialize the bp.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp = dbgfR3BpAlloc(pVM, DBGFBPTYPE_REM);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_DBGF_NO_MORE_BP_SLOTS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->GCPtr = pAddress->FlatPtr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->iHitTrigger = *piHitTrigger;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->iHitDisable = *piHitDisable;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->fEnabled = true;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Now ask REM to set the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef VBOX_WITH_REM
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = REMR3BreakpointSet(pVM, pAddress->FlatPtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = IEMBreakpointSet(pVM, pAddress->FlatPtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_SUCCESS(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *piBp = pBp->iBp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dbgfR3BpFree(pVM, pBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Sets a recompiler breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VBox status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pUVM The user mode VM handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pAddress The address of the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param iHitTrigger The hit count at which the breakpoint start triggering.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Use 0 (or 1) if it's gonna trigger at once.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param iHitDisable The hit count which disables the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Use ~(uint64_t) if it's never gonna be disabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param piBp Where to store the breakpoint id. (optional)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @thread Any thread.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVMMR3DECL(int) DBGFR3BpSetREM(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This must be done on EMT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetREM, 5,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pUVM, pAddress, &iHitTrigger, &iHitDisable, piBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LogFlow(("DBGFR3BpSetREM: returns %Rrc\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * EMT worker for DBGFR3BpClear().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VBox status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pUVM The user mode VM handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param iBp The id of the breakpoint which should be removed (cleared).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @thread EMT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @internal
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(int) dbgfR3BpClear(PUVM pUVM, uint32_t iBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Validate input.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVM pVM = pUVM->pVM;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PDBGFBP pBp = dbgfR3BpGet(pVM, iBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_DBGF_BP_NOT_FOUND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Disarm the breakpoint if it's enabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pBp->fEnabled)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->fEnabled = false;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (pBp->enmType)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_REG:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = dbgfR3BpRegDisarm(pVM, pBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_INT3:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = dbgfR3BpInt3Disarm(pUVM, pBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_REM:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef VBOX_WITH_REM
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = REMR3BreakpointClear(pVM, pBp->GCPtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = IEMBreakpointClear(pVM, pBp->GCPtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailedReturn(("Invalid enmType=%d!\n", pBp->enmType), VERR_IPE_NOT_REACHED_DEFAULT_CASE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertRCReturn(rc, rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Free the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dbgfR3BpFree(pVM, pBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Clears a breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VBox status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pUVM The user mode VM handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param iBp The id of the breakpoint which should be removed (cleared).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @thread Any thread.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVMMR3DECL(int) DBGFR3BpClear(PUVM pUVM, uint32_t iBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This must be done on EMT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpClear, 2, pUVM, iBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LogFlow(("DBGFR3BpClear: returns %Rrc\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * EMT worker for DBGFR3BpEnable().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VBox status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pUVM The user mode VM handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param iBp The id of the breakpoint which should be enabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @thread EMT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @internal
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(int) dbgfR3BpEnable(PUVM pUVM, uint32_t iBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Validate input.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PVM pVM = pUVM->pVM;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PDBGFBP pBp = dbgfR3BpGet(pVM, iBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!pBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VERR_DBGF_BP_NOT_FOUND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Already enabled?
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (pBp->fEnabled)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return VINF_DBGF_BP_ALREADY_ENABLED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Remove the breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->fEnabled = true;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (pBp->enmType)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_REG:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = dbgfR3BpRegArm(pVM, pBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_INT3:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = dbgfR3BpInt3Arm(pUVM, pBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DBGFBPTYPE_REM:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef VBOX_WITH_REM
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = REMR3BreakpointSet(pVM, pBp->GCPtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = IEMBreakpointSet(pVM, pBp->GCPtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AssertMsgFailedReturn(("Invalid enmType=%d!\n", pBp->enmType), VERR_IPE_NOT_REACHED_DEFAULT_CASE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RT_FAILURE(rc))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pBp->fEnabled = false;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Enables a breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @returns VBox status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pUVM The user mode VM handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param iBp The id of the breakpoint which should be enabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @thread Any thread.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVMMR3DECL(int) DBGFR3BpEnable(PUVM pUVM, uint32_t iBp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This must be done on EMT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpEnable, 2, pUVM, iBp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LogFlow(("DBGFR3BpEnable: returns %Rrc\n", rc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * EMT worker for DBGFR3BpDisable().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @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
*/
static DECLCALLBACK(int) dbgfR3BpDisable(PUVM pUVM, uint32_t iBp)
{
/*
* Validate input.
*/
PVM pVM = pUVM->pVM;
VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
PDBGFBP pBp = dbgfR3BpGet(pVM, iBp);
if (!pBp)
return VERR_DBGF_BP_NOT_FOUND;
/*
* Already enabled?
*/
if (!pBp->fEnabled)
return VINF_DBGF_BP_ALREADY_DISABLED;
/*
* Remove the breakpoint.
*/
pBp->fEnabled = false;
int rc;
switch (pBp->enmType)
{
case DBGFBPTYPE_REG:
rc = dbgfR3BpRegDisarm(pVM, pBp);
break;
case DBGFBPTYPE_INT3:
rc = dbgfR3BpInt3Disarm(pUVM, pBp);
break;
case DBGFBPTYPE_REM:
#ifdef VBOX_WITH_REM
rc = REMR3BreakpointClear(pVM, pBp->GCPtr);
#else
rc = IEMBreakpointClear(pVM, pBp->GCPtr);
#endif
break;
default:
AssertMsgFailedReturn(("Invalid enmType=%d!\n", pBp->enmType), VERR_IPE_NOT_REACHED_DEFAULT_CASE);
}
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.
*/
VMMR3DECL(int) DBGFR3BpDisable(PUVM pUVM, uint32_t iBp)
{
/*
* This must be done on EMT.
*/
int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpDisable, 2, pUVM, iBp);
LogFlow(("DBGFR3BpDisable: returns %Rrc\n", rc));
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
*/
static DECLCALLBACK(int) dbgfR3BpEnum(PUVM pUVM, PFNDBGFBPENUM pfnCallback, void *pvUser)
{
/*
* Validate input.
*/
PVM pVM = pUVM->pVM;
VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
/*
* Enumerate the hardware breakpoints.
*/
unsigned i;
for (i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); i++)
if (pVM->dbgf.s.aHwBreakpoints[i].enmType != DBGFBPTYPE_FREE)
{
int rc = pfnCallback(pUVM, pvUser, &pVM->dbgf.s.aHwBreakpoints[i]);
if (RT_FAILURE(rc))
return rc;
}
/*
* Enumerate the other breakpoints.
*/
for (i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); i++)
if (pVM->dbgf.s.aBreakpoints[i].enmType != DBGFBPTYPE_FREE)
{
int rc = pfnCallback(pUVM, pvUser, &pVM->dbgf.s.aBreakpoints[i]);
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.
*/
VMMR3DECL(int) DBGFR3BpEnum(PUVM pUVM, PFNDBGFBPENUM pfnCallback, void *pvUser)
{
/*
* This must be done on EMT.
*/
int rc = VMR3ReqPriorityCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpEnum, 3, pUVM, pfnCallback, pvUser);
LogFlow(("DBGFR3BpClear: returns %Rrc\n", rc));
return rc;
}