1
/* $Id: DBGFBp.cpp $ */
3
* DBGF - Debugger Facility, Breakpoint Management.
7
* Copyright (C) 2006-2007 Oracle Corporation
9
* This file is part of VirtualBox Open Source Edition (OSE), as
10
* available from http://www.virtualbox.org. This file is free software;
11
* you can redistribute it and/or modify it under the terms of the GNU
12
* General Public License (GPL) as published by the Free Software
13
* Foundation, in version 2 as it comes in the "COPYING" file of the
14
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19
/*******************************************************************************
21
*******************************************************************************/
22
#define LOG_GROUP LOG_GROUP_DBGF
23
#include <VBox/dbgf.h>
24
#include <VBox/selm.h>
26
#include "DBGFInternal.h"
31
#include <iprt/assert.h>
32
#include <iprt/string.h>
35
/*******************************************************************************
36
* Internal Functions *
37
*******************************************************************************/
39
static DECLCALLBACK(int) dbgfR3BpSetReg(PVM pVM, PCDBGFADDRESS pAddress, uint64_t *piHitTrigger, uint64_t *piHitDisable,
40
uint8_t u8Type, uint8_t cb, PRTUINT piBp);
41
static DECLCALLBACK(int) dbgfR3BpSetInt3(PVM pVM, PCDBGFADDRESS pAddress, uint64_t *piHitTrigger, uint64_t *piHitDisable, PRTUINT piBp);
42
static DECLCALLBACK(int) dbgfR3BpSetREM(PVM pVM, PCDBGFADDRESS pAddress, uint64_t *piHitTrigger, uint64_t *piHitDisable, PRTUINT piBp);
43
static DECLCALLBACK(int) dbgfR3BpClear(PVM pVM, RTUINT iBp);
44
static DECLCALLBACK(int) dbgfR3BpEnable(PVM pVM, RTUINT iBp);
45
static DECLCALLBACK(int) dbgfR3BpDisable(PVM pVM, RTUINT iBp);
46
static DECLCALLBACK(int) dbgfR3BpEnum(PVM pVM, PFNDBGFBPENUM pfnCallback, void *pvUser);
47
static int dbgfR3BpRegArm(PVM pVM, PDBGFBP pBp);
48
static int dbgfR3BpRegDisarm(PVM pVM, PDBGFBP pBp);
49
static int dbgfR3BpInt3Arm(PVM pVM, PDBGFBP pBp);
50
static int dbgfR3BpInt3Disarm(PVM pVM, PDBGFBP pBp);
56
* Initialize the breakpoint stuff.
58
* @returns VINF_SUCCESS
59
* @param pVM The VM handle.
61
int dbgfR3BpInit(PVM pVM)
67
for (i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); i++)
69
pVM->dbgf.s.aHwBreakpoints[i].iBp = i;
70
pVM->dbgf.s.aHwBreakpoints[i].enmType = DBGFBPTYPE_FREE;
71
pVM->dbgf.s.aHwBreakpoints[i].u.Reg.iReg = i;
74
for (i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); i++)
76
pVM->dbgf.s.aBreakpoints[i].iBp = i + RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints);
77
pVM->dbgf.s.aBreakpoints[i].enmType = DBGFBPTYPE_FREE;
81
* Register saved state.
91
* Allocate a breakpoint.
93
* @returns Pointer to the allocated breakpoint.
94
* @returns NULL if we're out of breakpoints.
95
* @param pVM The VM handle.
96
* @param enmType The type to allocate.
98
static PDBGFBP dbgfR3BpAlloc(PVM pVM, DBGFBPTYPE enmType)
101
* Determin which array to search.
109
cBps = RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints);
110
paBps = &pVM->dbgf.s.aHwBreakpoints[0];
111
pcBpsCur = &pVM->dbgf.s.cHwBreakpoints;
114
case DBGFBPTYPE_INT3:
116
cBps = RT_ELEMENTS(pVM->dbgf.s.aBreakpoints);
117
paBps = &pVM->dbgf.s.aBreakpoints[0];
118
pcBpsCur = &pVM->dbgf.s.cBreakpoints;
122
AssertMsgFailed(("enmType=%d\n", enmType));
129
for (unsigned iBp = 0; iBp < cBps; iBp++)
130
if (paBps[iBp].enmType == DBGFBPTYPE_FREE)
133
paBps[iBp].cHits = 0;
134
paBps[iBp].enmType = enmType;
138
LogFlow(("dbgfR3BpAlloc: returns NULL - we're out of breakpoint slots! %u/%u\n", *pcBpsCur, cBps));
144
* Get a breakpoint give by breakpoint id.
146
* @returns Pointer to the allocated breakpoint.
147
* @returns NULL if the breakpoint is invalid.
148
* @param pVM The VM handle.
149
* @param iBp The breakpoint id.
151
static PDBGFBP dbgfR3BpGet(PVM pVM, RTUINT iBp)
155
if (iBp < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints))
156
pBp = &pVM->dbgf.s.aHwBreakpoints[iBp];
159
iBp -= RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints);
160
if (iBp >= RT_ELEMENTS(pVM->dbgf.s.aBreakpoints))
162
pBp = &pVM->dbgf.s.aBreakpoints[iBp];
165
/* check if it's valid. */
166
switch (pBp->enmType)
168
case DBGFBPTYPE_FREE:
172
case DBGFBPTYPE_INT3:
177
AssertMsgFailed(("Invalid enmType=%d!\n", pBp->enmType));
186
* Get a breakpoint give by address.
188
* @returns Pointer to the allocated breakpoint.
189
* @returns NULL if the breakpoint is invalid.
190
* @param pVM The VM handle.
191
* @param enmType The breakpoint type.
192
* @param GCPtr The breakpoint address.
194
static PDBGFBP dbgfR3BpGetByAddr(PVM pVM, DBGFBPTYPE enmType, RTGCUINTPTR GCPtr)
197
* Determin which array to search.
204
cBps = RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints);
205
paBps = &pVM->dbgf.s.aHwBreakpoints[0];
208
case DBGFBPTYPE_INT3:
210
cBps = RT_ELEMENTS(pVM->dbgf.s.aBreakpoints);
211
paBps = &pVM->dbgf.s.aBreakpoints[0];
215
AssertMsgFailed(("enmType=%d\n", enmType));
222
for (unsigned iBp = 0; iBp < cBps; iBp++)
224
if ( paBps[iBp].enmType == enmType
225
&& paBps[iBp].GCPtr == GCPtr)
234
* Frees a breakpoint.
236
* @param pVM The VM handle.
237
* @param pBp The breakpoint to free.
239
static void dbgfR3BpFree(PVM pVM, PDBGFBP pBp)
241
switch (pBp->enmType)
243
case DBGFBPTYPE_FREE:
244
AssertMsgFailed(("Already freed!\n"));
248
Assert(pVM->dbgf.s.cHwBreakpoints > 0);
249
pVM->dbgf.s.cHwBreakpoints--;
252
case DBGFBPTYPE_INT3:
254
Assert(pVM->dbgf.s.cBreakpoints > 0);
255
pVM->dbgf.s.cBreakpoints--;
259
AssertMsgFailed(("Invalid enmType=%d!\n", pBp->enmType));
263
pBp->enmType = DBGFBPTYPE_FREE;
268
* Sets a breakpoint (int 3 based).
270
* @returns VBox status code.
271
* @param pVM The VM handle.
272
* @param pAddress The address of the breakpoint.
273
* @param iHitTrigger The hit count at which the breakpoint start triggering.
274
* Use 0 (or 1) if it's gonna trigger at once.
275
* @param iHitDisable The hit count which disables the breakpoint.
276
* Use ~(uint64_t) if it's never gonna be disabled.
277
* @param piBp Where to store the breakpoint id. (optional)
278
* @thread Any thread.
280
VMMR3DECL(int) DBGFR3BpSet(PVM pVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, PRTUINT piBp)
283
* This must be done in EMT.
286
int rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetInt3, 5, pVM, pAddress, &iHitTrigger, &iHitDisable, piBp);
287
LogFlow(("DBGFR3BpSet: returns %Rrc\n", rc));
293
* Sets a breakpoint (int 3 based).
295
* @returns VBox status code.
296
* @param pVM The VM handle.
297
* @param pAddress The address of the breakpoint.
298
* @param piHitTrigger The hit count at which the breakpoint start triggering.
299
* Use 0 (or 1) if it's gonna trigger at once.
300
* @param piHitDisable The hit count which disables the breakpoint.
301
* Use ~(uint64_t) if it's never gonna be disabled.
302
* @param piBp Where to store the breakpoint id. (optional)
303
* @thread Any thread.
305
static DECLCALLBACK(int) dbgfR3BpSetInt3(PVM pVM, PCDBGFADDRESS pAddress, uint64_t *piHitTrigger, uint64_t *piHitDisable, PRTUINT piBp)
310
if (!DBGFR3AddrIsValid(pVM, pAddress))
311
return VERR_INVALID_PARAMETER;
312
if (*piHitTrigger > *piHitDisable)
313
return VERR_INVALID_PARAMETER;
314
AssertMsgReturn(!piBp || VALID_PTR(piBp), ("piBp=%p\n", piBp), VERR_INVALID_POINTER);
319
* Check if the breakpoint already exists.
321
PDBGFBP pBp = dbgfR3BpGetByAddr(pVM, DBGFBPTYPE_INT3, pAddress->FlatPtr);
324
int rc = VINF_SUCCESS;
326
rc = dbgfR3BpInt3Arm(pVM, pBp);
329
rc = VINF_DBGF_BP_ALREADY_EXIST;
337
* Allocate and initialize the bp.
339
pBp = dbgfR3BpAlloc(pVM, DBGFBPTYPE_INT3);
341
return VERR_DBGF_NO_MORE_BP_SLOTS;
342
pBp->GCPtr = pAddress->FlatPtr;
343
pBp->iHitTrigger = *piHitTrigger;
344
pBp->iHitDisable = *piHitDisable;
345
pBp->fEnabled = true;
348
* Now ask REM to set the breakpoint.
350
int rc = dbgfR3BpInt3Arm(pVM, pBp);
357
dbgfR3BpFree(pVM, pBp);
364
* Arms an int 3 breakpoint.
365
* This is used to implement both DBGFR3BpSetReg() and DBGFR3BpEnable().
367
* @returns VBox status code.
368
* @param pVM The VM handle.
369
* @param pBp The breakpoint.
371
static int dbgfR3BpInt3Arm(PVM pVM, PDBGFBP pBp)
373
/** @todo should actually use physical address here! */
375
/* @todo SMP support! */
379
* Save current byte and write int3 instruction.
382
DBGFR3AddrFromFlat(pVM, &Addr, pBp->GCPtr);
383
int rc = DBGFR3MemRead(pVM, idCpu, &Addr, &pBp->u.Int3.bOrg, 1);
386
static const uint8_t s_bInt3 = 0xcc;
387
rc = DBGFR3MemWrite(pVM, idCpu, &Addr, &s_bInt3, 1);
394
* Disarms an int 3 breakpoint.
395
* This is used to implement both DBGFR3BpClear() and DBGFR3BpDisable().
397
* @returns VBox status code.
398
* @param pVM The VM handle.
399
* @param pBp The breakpoint.
401
static int dbgfR3BpInt3Disarm(PVM pVM, PDBGFBP pBp)
403
/* @todo SMP support! */
407
* Check that the current byte is the int3 instruction, and restore the original one.
408
* We currently ignore invalid bytes.
411
DBGFR3AddrFromFlat(pVM, &Addr, pBp->GCPtr);
413
int rc = DBGFR3MemRead(pVM, idCpu, &Addr, &bCurrent, 1);
414
if (bCurrent == 0xcc)
415
rc = DBGFR3MemWrite(pVM, idCpu, &Addr, &pBp->u.Int3.bOrg, 1);
421
* Sets a register breakpoint.
423
* @returns VBox status code.
424
* @param pVM The VM handle.
425
* @param pAddress The address of the breakpoint.
426
* @param iHitTrigger The hit count at which the breakpoint start triggering.
427
* Use 0 (or 1) if it's gonna trigger at once.
428
* @param iHitDisable The hit count which disables the breakpoint.
429
* Use ~(uint64_t) if it's never gonna be disabled.
430
* @param fType The access type (one of the X86_DR7_RW_* defines).
431
* @param cb The access size - 1,2,4 or 8 (the latter is AMD64 long mode only.
432
* Must be 1 if fType is X86_DR7_RW_EO.
433
* @param piBp Where to store the breakpoint id. (optional)
434
* @thread Any thread.
436
VMMR3DECL(int) DBGFR3BpSetReg(PVM pVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable,
437
uint8_t fType, uint8_t cb, PRTUINT piBp)
439
/** @todo SMP - broadcast, VT-x/AMD-V. */
441
* This must be done in EMT.
443
int rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetReg, 7, pVM, pAddress, &iHitTrigger, &iHitDisable, fType, cb, piBp);
444
LogFlow(("DBGFR3BpSetReg: returns %Rrc\n", rc));
451
* Sets a register breakpoint.
453
* @returns VBox status code.
454
* @param pVM The VM handle.
455
* @param pAddress The address of the breakpoint.
456
* @param piHitTrigger The hit count at which the breakpoint start triggering.
457
* Use 0 (or 1) if it's gonna trigger at once.
458
* @param piHitDisable The hit count which disables the breakpoint.
459
* Use ~(uint64_t) if it's never gonna be disabled.
460
* @param fType The access type (one of the X86_DR7_RW_* defines).
461
* @param cb The access size - 1,2,4 or 8 (the latter is AMD64 long mode only.
462
* Must be 1 if fType is X86_DR7_RW_EO.
463
* @param piBp Where to store the breakpoint id. (optional)
467
static DECLCALLBACK(int) dbgfR3BpSetReg(PVM pVM, PCDBGFADDRESS pAddress, uint64_t *piHitTrigger, uint64_t *piHitDisable,
468
uint8_t fType, uint8_t cb, PRTUINT piBp)
473
if (!DBGFR3AddrIsValid(pVM, pAddress))
474
return VERR_INVALID_PARAMETER;
475
if (*piHitTrigger > *piHitDisable)
476
return VERR_INVALID_PARAMETER;
477
AssertMsgReturn(!piBp || VALID_PTR(piBp), ("piBp=%p\n", piBp), VERR_INVALID_POINTER);
485
AssertMsgFailed(("fType=%#x cb=%d != 1\n", fType, cb));
486
return VERR_INVALID_PARAMETER;
492
AssertMsgFailed(("fType=%#x\n", fType));
493
return VERR_INVALID_PARAMETER;
502
AssertMsgFailed(("cb=%#x\n", cb));
503
return VERR_INVALID_PARAMETER;
507
* Check if the breakpoint already exists.
509
PDBGFBP pBp = dbgfR3BpGetByAddr(pVM, DBGFBPTYPE_REG, pAddress->FlatPtr);
511
&& pBp->u.Reg.cb == cb
512
&& pBp->u.Reg.fType == fType)
514
int rc = VINF_SUCCESS;
516
rc = dbgfR3BpRegArm(pVM, pBp);
519
rc = VINF_DBGF_BP_ALREADY_EXIST;
527
* Allocate and initialize the bp.
529
pBp = dbgfR3BpAlloc(pVM, DBGFBPTYPE_REG);
531
return VERR_DBGF_NO_MORE_BP_SLOTS;
532
pBp->GCPtr = pAddress->FlatPtr;
533
pBp->iHitTrigger = *piHitTrigger;
534
pBp->iHitDisable = *piHitDisable;
535
pBp->fEnabled = true;
536
Assert(pBp->iBp == pBp->u.Reg.iReg);
537
pBp->u.Reg.fType = fType;
541
* Arm the breakpoint.
543
int rc = dbgfR3BpRegArm(pVM, pBp);
550
dbgfR3BpFree(pVM, pBp);
557
* Arms a debug register breakpoint.
558
* This is used to implement both DBGFR3BpSetReg() and DBGFR3BpEnable().
560
* @returns VBox status code.
561
* @param pVM The VM handle.
562
* @param pBp The breakpoint.
564
static int dbgfR3BpRegArm(PVM pVM, PDBGFBP pBp)
566
/* @todo SMP support! */
567
PVMCPU pVCpu = &pVM->aCpus[0];
569
Assert(pBp->fEnabled);
570
return CPUMRecalcHyperDRx(pVCpu);
575
* Disarms a debug register breakpoint.
576
* This is used to implement both DBGFR3BpClear() and DBGFR3BpDisable().
578
* @returns VBox status code.
579
* @param pVM The VM handle.
580
* @param pBp The breakpoint.
582
static int dbgfR3BpRegDisarm(PVM pVM, PDBGFBP pBp)
584
/** @todo SMP support! */
585
PVMCPU pVCpu = &pVM->aCpus[0];
587
Assert(!pBp->fEnabled);
588
return CPUMRecalcHyperDRx(pVCpu);
593
* Sets a recompiler breakpoint.
595
* @returns VBox status code.
596
* @param pVM The VM handle.
597
* @param pAddress The address of the breakpoint.
598
* @param iHitTrigger The hit count at which the breakpoint start triggering.
599
* Use 0 (or 1) if it's gonna trigger at once.
600
* @param iHitDisable The hit count which disables the breakpoint.
601
* Use ~(uint64_t) if it's never gonna be disabled.
602
* @param piBp Where to store the breakpoint id. (optional)
603
* @thread Any thread.
605
VMMR3DECL(int) DBGFR3BpSetREM(PVM pVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, PRTUINT piBp)
608
* This must be done in EMT.
610
int rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetREM, 5, pVM, pAddress, &iHitTrigger, &iHitDisable, piBp);
611
LogFlow(("DBGFR3BpSetREM: returns %Rrc\n", rc));
617
* EMT worker for DBGFR3BpSetREM().
619
* @returns VBox status code.
620
* @param pVM The VM handle.
621
* @param pAddress The address of the breakpoint.
622
* @param piHitTrigger The hit count at which the breakpoint start triggering.
623
* Use 0 (or 1) if it's gonna trigger at once.
624
* @param piHitDisable The hit count which disables the breakpoint.
625
* Use ~(uint64_t) if it's never gonna be disabled.
626
* @param piBp Where to store the breakpoint id. (optional)
630
static DECLCALLBACK(int) dbgfR3BpSetREM(PVM pVM, PCDBGFADDRESS pAddress, uint64_t *piHitTrigger, uint64_t *piHitDisable, PRTUINT piBp)
635
if (!DBGFR3AddrIsValid(pVM, pAddress))
636
return VERR_INVALID_PARAMETER;
637
if (*piHitTrigger > *piHitDisable)
638
return VERR_INVALID_PARAMETER;
639
AssertMsgReturn(!piBp || VALID_PTR(piBp), ("piBp=%p\n", piBp), VERR_INVALID_POINTER);
645
* Check if the breakpoint already exists.
647
PDBGFBP pBp = dbgfR3BpGetByAddr(pVM, DBGFBPTYPE_REM, pAddress->FlatPtr);
650
int rc = VINF_SUCCESS;
652
rc = REMR3BreakpointSet(pVM, pBp->GCPtr);
655
rc = VINF_DBGF_BP_ALREADY_EXIST;
663
* Allocate and initialize the bp.
665
pBp = dbgfR3BpAlloc(pVM, DBGFBPTYPE_REM);
667
return VERR_DBGF_NO_MORE_BP_SLOTS;
668
pBp->GCPtr = pAddress->FlatPtr;
669
pBp->iHitTrigger = *piHitTrigger;
670
pBp->iHitDisable = *piHitDisable;
671
pBp->fEnabled = true;
674
* Now ask REM to set the breakpoint.
676
int rc = REMR3BreakpointSet(pVM, pAddress->FlatPtr);
683
dbgfR3BpFree(pVM, pBp);
690
* Clears a breakpoint.
692
* @returns VBox status code.
693
* @param pVM The VM handle.
694
* @param iBp The id of the breakpoint which should be removed (cleared).
695
* @thread Any thread.
697
VMMR3DECL(int) DBGFR3BpClear(PVM pVM, RTUINT iBp)
700
* This must be done in EMT.
702
int rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)dbgfR3BpClear, 2, pVM, iBp);
703
LogFlow(("DBGFR3BpClear: returns %Rrc\n", rc));
709
* EMT worker for DBGFR3BpClear().
711
* @returns VBox status code.
712
* @param pVM The VM handle.
713
* @param iBp The id of the breakpoint which should be removed (cleared).
717
static DECLCALLBACK(int) dbgfR3BpClear(PVM pVM, RTUINT iBp)
722
PDBGFBP pBp = dbgfR3BpGet(pVM, iBp);
724
return VERR_DBGF_BP_NOT_FOUND;
727
* Disarm the breakpoint if it's enabled.
731
pBp->fEnabled = false;
733
switch (pBp->enmType)
736
rc = dbgfR3BpRegDisarm(pVM, pBp);
739
case DBGFBPTYPE_INT3:
740
rc = dbgfR3BpInt3Disarm(pVM, pBp);
744
rc = REMR3BreakpointClear(pVM, pBp->GCPtr);
748
AssertMsgFailed(("Invalid enmType=%d!\n", pBp->enmType));
749
return VERR_INTERNAL_ERROR;
751
AssertRCReturn(rc, rc);
755
* Free the breakpoint.
757
dbgfR3BpFree(pVM, pBp);
763
* Enables a breakpoint.
765
* @returns VBox status code.
766
* @param pVM The VM handle.
767
* @param iBp The id of the breakpoint which should be enabled.
768
* @thread Any thread.
770
VMMR3DECL(int) DBGFR3BpEnable(PVM pVM, RTUINT iBp)
773
* This must be done in EMT.
775
int rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)dbgfR3BpEnable, 2, pVM, iBp);
776
LogFlow(("DBGFR3BpEnable: returns %Rrc\n", rc));
782
* EMT worker for DBGFR3BpEnable().
784
* @returns VBox status code.
785
* @param pVM The VM handle.
786
* @param iBp The id of the breakpoint which should be enabled.
790
static DECLCALLBACK(int) dbgfR3BpEnable(PVM pVM, RTUINT iBp)
795
PDBGFBP pBp = dbgfR3BpGet(pVM, iBp);
797
return VERR_DBGF_BP_NOT_FOUND;
803
return VINF_DBGF_BP_ALREADY_ENABLED;
806
* Remove the breakpoint.
809
pBp->fEnabled = true;
810
switch (pBp->enmType)
813
rc = dbgfR3BpRegArm(pVM, pBp);
816
case DBGFBPTYPE_INT3:
817
rc = dbgfR3BpInt3Arm(pVM, pBp);
821
rc = REMR3BreakpointSet(pVM, pBp->GCPtr);
825
AssertMsgFailed(("Invalid enmType=%d!\n", pBp->enmType));
826
return VERR_INTERNAL_ERROR;
829
pBp->fEnabled = false;
836
* Disables a breakpoint.
838
* @returns VBox status code.
839
* @param pVM The VM handle.
840
* @param iBp The id of the breakpoint which should be disabled.
841
* @thread Any thread.
843
VMMR3DECL(int) DBGFR3BpDisable(PVM pVM, RTUINT iBp)
846
* This must be done in EMT.
848
int rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)dbgfR3BpDisable, 2, pVM, iBp);
849
LogFlow(("DBGFR3BpDisable: returns %Rrc\n", rc));
855
* EMT worker for DBGFR3BpDisable().
857
* @returns VBox status code.
858
* @param pVM The VM handle.
859
* @param iBp The id of the breakpoint which should be disabled.
863
static DECLCALLBACK(int) dbgfR3BpDisable(PVM pVM, RTUINT iBp)
868
PDBGFBP pBp = dbgfR3BpGet(pVM, iBp);
870
return VERR_DBGF_BP_NOT_FOUND;
876
return VINF_DBGF_BP_ALREADY_DISABLED;
879
* Remove the breakpoint.
881
pBp->fEnabled = false;
883
switch (pBp->enmType)
886
rc = dbgfR3BpRegDisarm(pVM, pBp);
889
case DBGFBPTYPE_INT3:
890
rc = dbgfR3BpInt3Disarm(pVM, pBp);
894
rc = REMR3BreakpointClear(pVM, pBp->GCPtr);
898
AssertMsgFailed(("Invalid enmType=%d!\n", pBp->enmType));
899
return VERR_INTERNAL_ERROR;
907
* Enumerate the breakpoints.
909
* @returns VBox status code.
910
* @param pVM The VM handle.
911
* @param pfnCallback The callback function.
912
* @param pvUser The user argument to pass to the callback.
913
* @thread Any thread but the callback will be called from EMT.
915
VMMR3DECL(int) DBGFR3BpEnum(PVM pVM, PFNDBGFBPENUM pfnCallback, void *pvUser)
918
* This must be done in EMT.
920
int rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)dbgfR3BpEnum, 3, pVM, pfnCallback, pvUser);
921
LogFlow(("DBGFR3BpClear: returns %Rrc\n", rc));
927
* EMT worker for DBGFR3BpEnum().
929
* @returns VBox status code.
930
* @param pVM The VM handle.
931
* @param pfnCallback The callback function.
932
* @param pvUser The user argument to pass to the callback.
936
static DECLCALLBACK(int) dbgfR3BpEnum(PVM pVM, PFNDBGFBPENUM pfnCallback, void *pvUser)
941
AssertMsgReturn(VALID_PTR(pfnCallback), ("pfnCallback=%p\n", pfnCallback), VERR_INVALID_POINTER);
944
* Enumerate the hardware breakpoints.
947
for (i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); i++)
948
if (pVM->dbgf.s.aHwBreakpoints[i].enmType != DBGFBPTYPE_FREE)
950
int rc = pfnCallback(pVM, pvUser, &pVM->dbgf.s.aHwBreakpoints[i]);
956
* Enumerate the other breakpoints.
958
for (i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); i++)
959
if (pVM->dbgf.s.aBreakpoints[i].enmType != DBGFBPTYPE_FREE)
961
int rc = pfnCallback(pVM, pvUser, &pVM->dbgf.s.aBreakpoints[i]);