Changeset 35410 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Jan 5, 2011 5:21:11 PM (14 years ago)
- Location:
- trunk/src/VBox/VMM/VMMR3
- Files:
-
- 2 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/CPUMDbg.cpp
r35404 r35410 1 1 /* $Id$ */ 2 2 /** @file 3 * DBGF - Debugger Facility, Register Methods.3 * CPUM - CPU Monitor / Manager, Debugger & Debugging APIs. 4 4 */ 5 5 … … 29 29 30 30 31 /******************************************************************************* 32 * Defined Constants And Macros * 33 *******************************************************************************/ 34 /** @name Register and value sizes used by dbgfR3RegQueryWorker and 35 * dbgfR3RegSetWorker. 36 * @{ */ 37 #define R_SZ_8 RT_BIT(0) 38 #define R_SZ_16 RT_BIT(1) 39 #define R_SZ_32 RT_BIT(2) 40 #define R_SZ_64 RT_BIT(3) 41 #define R_SZ_64_16 RT_BIT(4) 42 #define R_SZ_80 RT_BIT(5) 43 #define R_SZ_128 RT_BIT(6) 44 #define R_SZ_8_TO_64 (R_SZ_8 | R_SZ_16 | R_SZ_32 | R_SZ_64) 45 #define R_SZ_16_TO_64 (R_SZ_16 | R_SZ_32 | R_SZ_64) 46 #define R_SZ_32_OR_64 (R_SZ_32 | R_SZ_64) 47 /** @} */ 48 49 50 /******************************************************************************* 51 * Structures and Typedefs * 52 *******************************************************************************/ 53 /** 54 * Register sub-field descriptor. 55 */ 56 typedef struct DBGFREGSUBFIELD 57 { 58 /** The name of the sub-field. NULL is used to terminate the array. */ 59 const char *pszName; 60 /** The index of the first bit. */ 61 uint8_t iFirstBit; 62 /** The number of bits. */ 63 uint8_t cBits; 64 /** The shift count. */ 65 int8_t cShift; 66 /** @todo getter/setter callbacks? */ 67 } DBGFREGSUBFIELD; 68 /** Pointer to a const register sub-field descriptor. */ 69 typedef DBGFREGSUBFIELD const *PCDBGFREGSUBFIELD; 70 71 /** 72 * Register alias descriptor. 73 */ 74 typedef struct DBGFREGALIAS 75 { 76 /** The alias name. NULL is used to terminate the array. */ 77 const char *pszName; 78 /** Set to a valid type if the alias has a different type. */ 79 DBGFREGVALTYPE enmType; 80 } DBGFREGALIAS; 81 /** Pointer to a const register alias descriptor. */ 82 typedef DBGFREGALIAS const *PCDBGFREGALIAS; 83 84 /** 85 * Register descriptor. 86 */ 87 typedef struct DBGFREGDESC 88 { 89 /** The normal register name. */ 90 const char *pszName; 91 /** The register identifier (same as the table index). */ 92 DBGFREG enmReg; 93 /** The default register type. */ 94 DBGFREGVALTYPE enmType; 95 /** The offset info the CPUMCTX structure. ~(size_t)0 if not applicable. */ 96 size_t offCtx; 97 /** Getter (optional). */ 98 DECLCALLBACKMEMBER(int, pfnGet)(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 99 /** Setter (optional). */ 100 DECLCALLBACKMEMBER(int, pfnSet)(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 101 /** Aliases (optional). */ 102 PCDBGFREGALIAS paAliases; 103 /** Sub fields (optional). */ 104 PCDBGFREGSUBFIELD paSubFields; 105 } DBGFREGDESC; 106 /** Pointer to a const register descriptor. */ 107 typedef DBGFREGDESC const *PCDBGFREGDESC; 108 109 110 /******************************************************************************* 111 * Internal Functions * 112 *******************************************************************************/ 113 static DECLCALLBACK(int) dbgfR3RegSet_seg(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 114 static DECLCALLBACK(int) dbgfR3RegGet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 115 static DECLCALLBACK(int) dbgfR3RegSet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 116 static DECLCALLBACK(int) dbgfR3RegGet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 117 static DECLCALLBACK(int) dbgfR3RegSet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 118 static DECLCALLBACK(int) dbgfR3RegGet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 119 static DECLCALLBACK(int) dbgfR3RegSet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 120 static DECLCALLBACK(int) dbgfR3RegGet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 121 static DECLCALLBACK(int) dbgfR3RegSet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 122 static DECLCALLBACK(int) dbgfR3RegGet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 123 static DECLCALLBACK(int) dbgfR3RegSet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 124 static DECLCALLBACK(int) dbgfR3RegGet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 125 static DECLCALLBACK(int) dbgfR3RegSet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 126 static DECLCALLBACK(int) dbgfR3RegGet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 127 static DECLCALLBACK(int) dbgfR3RegSet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 128 129 130 /******************************************************************************* 131 * Global Variables * 132 *******************************************************************************/ 31 static DECLCALLBACK(int) dbgfR3RegSet_seg(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 32 { 33 return VERR_NOT_IMPLEMENTED; 34 } 35 36 static DECLCALLBACK(int) dbgfR3RegGet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue) 37 { 38 return VERR_NOT_IMPLEMENTED; 39 } 40 41 static DECLCALLBACK(int) dbgfR3RegSet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 42 { 43 return VERR_NOT_IMPLEMENTED; 44 } 45 46 static DECLCALLBACK(int) dbgfR3RegGet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue) 47 { 48 return VERR_NOT_IMPLEMENTED; 49 } 50 51 static DECLCALLBACK(int) dbgfR3RegSet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 52 { 53 return VERR_NOT_IMPLEMENTED; 54 } 55 56 static DECLCALLBACK(int) dbgfR3RegGet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue) 57 { 58 return VERR_NOT_IMPLEMENTED; 59 } 60 61 static DECLCALLBACK(int) dbgfR3RegSet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 62 { 63 return VERR_NOT_IMPLEMENTED; 64 } 65 66 static DECLCALLBACK(int) dbgfR3RegGet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue) 67 { 68 return VERR_NOT_IMPLEMENTED; 69 } 70 71 static DECLCALLBACK(int) dbgfR3RegSet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 72 { 73 return VERR_NOT_IMPLEMENTED; 74 } 75 76 static DECLCALLBACK(int) dbgfR3RegGet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue) 77 { 78 return VERR_NOT_IMPLEMENTED; 79 } 80 81 static DECLCALLBACK(int) dbgfR3RegSet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 82 { 83 return VERR_NOT_IMPLEMENTED; 84 } 85 86 static DECLCALLBACK(int) dbgfR3RegGet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue) 87 { 88 return VERR_NOT_IMPLEMENTED; 89 } 90 91 static DECLCALLBACK(int) dbgfR3RegSet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 92 { 93 return VERR_NOT_IMPLEMENTED; 94 } 95 96 static DECLCALLBACK(int) dbgfR3RegGet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue) 97 { 98 return VERR_NOT_IMPLEMENTED; 99 } 100 101 static DECLCALLBACK(int) dbgfR3RegSet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 102 { 103 return VERR_NOT_IMPLEMENTED; 104 } 105 106 107 133 108 /* 134 109 * Set up aliases. … … 564 539 }; 565 540 566 567 static DECLCALLBACK(int) dbgfR3RegSet_seg(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)568 {569 return VERR_NOT_IMPLEMENTED;570 }571 572 static DECLCALLBACK(int) dbgfR3RegGet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)573 {574 return VERR_NOT_IMPLEMENTED;575 }576 577 static DECLCALLBACK(int) dbgfR3RegSet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)578 {579 return VERR_NOT_IMPLEMENTED;580 }581 582 static DECLCALLBACK(int) dbgfR3RegGet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)583 {584 return VERR_NOT_IMPLEMENTED;585 }586 587 static DECLCALLBACK(int) dbgfR3RegSet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)588 {589 return VERR_NOT_IMPLEMENTED;590 }591 592 static DECLCALLBACK(int) dbgfR3RegGet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)593 {594 return VERR_NOT_IMPLEMENTED;595 }596 597 static DECLCALLBACK(int) dbgfR3RegSet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)598 {599 return VERR_NOT_IMPLEMENTED;600 }601 602 static DECLCALLBACK(int) dbgfR3RegGet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)603 {604 return VERR_NOT_IMPLEMENTED;605 }606 607 static DECLCALLBACK(int) dbgfR3RegSet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)608 {609 return VERR_NOT_IMPLEMENTED;610 }611 612 static DECLCALLBACK(int) dbgfR3RegGet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)613 {614 return VERR_NOT_IMPLEMENTED;615 }616 617 static DECLCALLBACK(int) dbgfR3RegSet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)618 {619 return VERR_NOT_IMPLEMENTED;620 }621 622 static DECLCALLBACK(int) dbgfR3RegGet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)623 {624 return VERR_NOT_IMPLEMENTED;625 }626 627 static DECLCALLBACK(int) dbgfR3RegSet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)628 {629 return VERR_NOT_IMPLEMENTED;630 }631 632 static DECLCALLBACK(int) dbgfR3RegGet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue)633 {634 return VERR_NOT_IMPLEMENTED;635 }636 637 static DECLCALLBACK(int) dbgfR3RegSet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask)638 {639 return VERR_NOT_IMPLEMENTED;640 }641 642 643 644 /**645 * Wrapper around CPUMQueryGuestMsr for dbgfR3RegQueryWorker.646 *647 * @retval VINF_SUCCESS648 * @retval VERR_DBGF_INVALID_REGISTER649 *650 * @param pVCpu The current CPU.651 * @param pu64 Where to store the register value.652 * @param pfRegSizes Where to store the register sizes.653 * @param idMsr The MSR to get.654 */655 static uint64_t dbgfR3RegGetMsr(PVMCPU pVCpu, uint64_t *pu64, uint32_t *pfRegSizes, uint32_t idMsr)656 {657 *pfRegSizes = R_SZ_64;658 int rc = CPUMQueryGuestMsr(pVCpu, idMsr, pu64);659 if (RT_FAILURE(rc))660 {661 AssertMsg(rc == VERR_CPUM_RAISE_GP_0, ("%Rrc\n", rc));662 *pu64 = 0;663 }664 return VINF_SUCCESS;665 }666 667 /**668 * Worker for DBGFR3RegQueryU8, DBGFR3RegQueryU16, DBGFR3RegQueryU32 and669 * DBGFR3RegQueryU64.670 *671 * @param pVM The VM handle.672 * @param idCpu The target CPU ID.673 * @param enmReg The register that's being queried.674 * @param pu64 Where to store the register value.675 * @param pfRegSizes Where to store the register sizes.676 */677 static DECLCALLBACK(int) dbgfR3RegQueryWorker(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64, uint32_t *pfRegSizes)678 {679 /** @todo rewrite this to use the register descriptors. */680 PVMCPU pVCpu = &pVM->aCpus[idCpu];681 PCCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);682 switch (enmReg)683 {684 case DBGFREG_RAX: *pu64 = pCtx->rax; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;685 case DBGFREG_RCX: *pu64 = pCtx->rcx; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;686 case DBGFREG_RDX: *pu64 = pCtx->rdx; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;687 case DBGFREG_RBX: *pu64 = pCtx->rbx; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;688 case DBGFREG_RSP: *pu64 = pCtx->rsp; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;689 case DBGFREG_RBP: *pu64 = pCtx->rbp; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;690 case DBGFREG_RSI: *pu64 = pCtx->rsi; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;691 case DBGFREG_RDI: *pu64 = pCtx->rdi; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;692 case DBGFREG_R8: *pu64 = pCtx->r8; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;693 case DBGFREG_R9: *pu64 = pCtx->r9; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;694 case DBGFREG_R10: *pu64 = pCtx->r10; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;695 case DBGFREG_R11: *pu64 = pCtx->r11; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;696 case DBGFREG_R12: *pu64 = pCtx->r12; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;697 case DBGFREG_R13: *pu64 = pCtx->r13; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;698 case DBGFREG_R14: *pu64 = pCtx->r14; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;699 case DBGFREG_R15: *pu64 = pCtx->r15; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS;700 701 case DBGFREG_CS: *pu64 = pCtx->cs; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;702 case DBGFREG_DS: *pu64 = pCtx->ds; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;703 case DBGFREG_ES: *pu64 = pCtx->es; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;704 case DBGFREG_FS: *pu64 = pCtx->fs; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;705 case DBGFREG_GS: *pu64 = pCtx->gs; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;706 case DBGFREG_SS: *pu64 = pCtx->ss; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;707 708 case DBGFREG_CS_ATTR: *pu64 = pCtx->csHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;709 case DBGFREG_DS_ATTR: *pu64 = pCtx->dsHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;710 case DBGFREG_ES_ATTR: *pu64 = pCtx->esHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;711 case DBGFREG_FS_ATTR: *pu64 = pCtx->fsHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;712 case DBGFREG_GS_ATTR: *pu64 = pCtx->gsHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;713 case DBGFREG_SS_ATTR: *pu64 = pCtx->ssHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;714 715 case DBGFREG_CS_BASE: *pu64 = pCtx->csHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;716 case DBGFREG_DS_BASE: *pu64 = pCtx->dsHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;717 case DBGFREG_ES_BASE: *pu64 = pCtx->esHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;718 case DBGFREG_FS_BASE: *pu64 = pCtx->fsHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;719 case DBGFREG_GS_BASE: *pu64 = pCtx->gsHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;720 case DBGFREG_SS_BASE: *pu64 = pCtx->ssHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;721 722 case DBGFREG_CS_LIMIT: *pu64 = pCtx->csHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;723 case DBGFREG_DS_LIMIT: *pu64 = pCtx->dsHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;724 case DBGFREG_ES_LIMIT: *pu64 = pCtx->esHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;725 case DBGFREG_FS_LIMIT: *pu64 = pCtx->fsHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;726 case DBGFREG_GS_LIMIT: *pu64 = pCtx->gsHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;727 case DBGFREG_SS_LIMIT: *pu64 = pCtx->ssHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;728 729 case DBGFREG_RIP: *pu64 = pCtx->rip; *pfRegSizes = R_SZ_16_TO_64; return VINF_SUCCESS;730 case DBGFREG_FLAGS: *pu64 = pCtx->rflags.u; *pfRegSizes = R_SZ_16_TO_64; return VINF_SUCCESS;731 732 /** @todo check fxsave/fsave format? */733 case DBGFREG_FCW: *pu64 = pCtx->fpu.FCW; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;734 case DBGFREG_FSW: *pu64 = pCtx->fpu.FSW; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;735 case DBGFREG_FTW: *pu64 = pCtx->fpu.FTW; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;736 case DBGFREG_FOP: *pu64 = pCtx->fpu.FOP; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;737 case DBGFREG_FPUIP: *pu64 = pCtx->fpu.FPUIP; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;738 case DBGFREG_FPUCS: *pu64 = pCtx->fpu.CS; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;739 case DBGFREG_FPUDP: *pu64 = pCtx->fpu.FPUDP; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;740 case DBGFREG_FPUDS: *pu64 = pCtx->fpu.DS; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;741 case DBGFREG_MXCSR: *pu64 = pCtx->fpu.MXCSR; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;742 case DBGFREG_MXCSR_MASK:*pu64 = pCtx->fpu.MXCSR_MASK; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;743 744 case DBGFREG_ST0:745 case DBGFREG_ST1:746 case DBGFREG_ST2:747 case DBGFREG_ST3:748 case DBGFREG_ST4:749 case DBGFREG_ST5:750 case DBGFREG_ST6:751 case DBGFREG_ST7:752 {753 /** @todo check tags and fxsave/fsave format. */754 unsigned iReg = (pCtx->fpu.FSW >> 11) & 7;755 iReg += enmReg - DBGFREG_ST0;756 iReg &= 7;757 758 *pu64 = pCtx->fpu.aRegs[iReg].au64[0];759 *pfRegSizes = R_SZ_80;760 return VINF_SUCCESS;761 }762 763 case DBGFREG_MM0:764 case DBGFREG_MM1:765 case DBGFREG_MM2:766 case DBGFREG_MM3:767 case DBGFREG_MM4:768 case DBGFREG_MM5:769 case DBGFREG_MM6:770 case DBGFREG_MM7:771 *pu64 = pCtx->fpu.aRegs[enmReg - DBGFREG_MM0].mmx;772 *pfRegSizes = R_SZ_64;773 return VINF_SUCCESS;774 775 case DBGFREG_XMM0:776 case DBGFREG_XMM1:777 case DBGFREG_XMM2:778 case DBGFREG_XMM3:779 case DBGFREG_XMM4:780 case DBGFREG_XMM5:781 case DBGFREG_XMM6:782 case DBGFREG_XMM7:783 case DBGFREG_XMM8:784 case DBGFREG_XMM9:785 case DBGFREG_XMM10:786 case DBGFREG_XMM11:787 case DBGFREG_XMM12:788 case DBGFREG_XMM13:789 case DBGFREG_XMM14:790 case DBGFREG_XMM15:791 *pu64 = pCtx->fpu.aRegs[enmReg - DBGFREG_XMM0].au64[0];792 *pfRegSizes = R_SZ_128;793 return VINF_SUCCESS;794 795 case DBGFREG_GDTR_BASE: *pu64 = pCtx->gdtr.pGdt; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;796 case DBGFREG_GDTR_LIMIT: *pu64 = pCtx->gdtr.cbGdt; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;797 case DBGFREG_IDTR_BASE: *pu64 = pCtx->idtr.pIdt; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;798 case DBGFREG_IDTR_LIMIT: *pu64 = pCtx->idtr.cbIdt; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;799 case DBGFREG_LDTR: *pu64 = pCtx->ldtr; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;800 case DBGFREG_LDTR_ATTR: *pu64 = pCtx->ldtrHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;801 case DBGFREG_LDTR_BASE: *pu64 = pCtx->ldtrHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;802 case DBGFREG_LDTR_LIMIT: *pu64 = pCtx->ldtrHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;803 case DBGFREG_TR: *pu64 = pCtx->tr; *pfRegSizes = R_SZ_16; return VINF_SUCCESS;804 case DBGFREG_TR_ATTR: *pu64 = pCtx->trHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;805 case DBGFREG_TR_BASE: *pu64 = pCtx->trHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS;806 case DBGFREG_TR_LIMIT: *pu64 = pCtx->trHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS;807 808 case DBGFREG_CR0: *pu64 = CPUMGetGuestCR0(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;809 case DBGFREG_CR2: *pu64 = CPUMGetGuestCR2(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;810 case DBGFREG_CR3: *pu64 = CPUMGetGuestCR3(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;811 case DBGFREG_CR4: *pu64 = CPUMGetGuestCR4(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;812 case DBGFREG_CR8: *pu64 = CPUMGetGuestCR8(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;813 814 case DBGFREG_DR0: *pu64 = CPUMGetGuestDR0(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;815 case DBGFREG_DR1: *pu64 = CPUMGetGuestDR1(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;816 case DBGFREG_DR2: *pu64 = CPUMGetGuestDR2(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;817 case DBGFREG_DR3: *pu64 = CPUMGetGuestDR3(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;818 case DBGFREG_DR6: *pu64 = CPUMGetGuestDR6(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;819 case DBGFREG_DR7: *pu64 = CPUMGetGuestDR7(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS;820 821 case DBGFREG_MSR_IA32_APICBASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_APICBASE);822 case DBGFREG_MSR_IA32_CR_PAT: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_CR_PAT);823 case DBGFREG_MSR_IA32_PERF_STATUS: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_PERF_STATUS);824 case DBGFREG_MSR_IA32_SYSENTER_CS: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_CS);825 case DBGFREG_MSR_IA32_SYSENTER_EIP: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_EIP);826 case DBGFREG_MSR_IA32_SYSENTER_ESP: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_ESP);827 case DBGFREG_MSR_IA32_TSC: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_TSC);828 case DBGFREG_MSR_K6_EFER: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K6_EFER);829 case DBGFREG_MSR_K6_STAR: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K6_STAR);830 case DBGFREG_MSR_K8_CSTAR: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_CSTAR);831 case DBGFREG_MSR_K8_FS_BASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_FS_BASE);832 case DBGFREG_MSR_K8_GS_BASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_GS_BASE);833 case DBGFREG_MSR_K8_KERNEL_GS_BASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_KERNEL_GS_BASE);834 case DBGFREG_MSR_K8_LSTAR: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_LSTAR);835 case DBGFREG_MSR_K8_SF_MASK: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_SF_MASK);836 case DBGFREG_MSR_K8_TSC_AUX: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_TSC_AUX);837 838 case DBGFREG_AH: *pu64 = RT_BYTE2(pCtx->ax); *pfRegSizes = R_SZ_8; return VINF_SUCCESS;839 case DBGFREG_CH: *pu64 = RT_BYTE2(pCtx->cx); *pfRegSizes = R_SZ_8; return VINF_SUCCESS;840 case DBGFREG_DH: *pu64 = RT_BYTE2(pCtx->dx); *pfRegSizes = R_SZ_8; return VINF_SUCCESS;841 case DBGFREG_BH: *pu64 = RT_BYTE2(pCtx->bx); *pfRegSizes = R_SZ_8; return VINF_SUCCESS;842 case DBGFREG_GDTR: *pu64 = pCtx->gdtr.pGdt; *pfRegSizes = R_SZ_64_16; return VINF_SUCCESS;843 case DBGFREG_IDTR: *pu64 = pCtx->idtr.pIdt; *pfRegSizes = R_SZ_64_16; return VINF_SUCCESS;844 845 case DBGFREG_END:846 case DBGFREG_32BIT_HACK:847 /* no default! We want GCC warnings. */848 break;849 }850 851 AssertMsgFailed(("%d (%#x)\n", enmReg, enmReg));852 return VERR_DBGF_INVALID_REGISTER;853 }854 855 856 /**857 * Queries a 8-bit register value.858 *859 * @retval VINF_SUCCESS860 * @retval VERR_INVALID_VM_HANDLE861 * @retval VERR_INVALID_CPU_ID862 * @retval VERR_DBGF_INVALID_REGISTER863 * @retval VINF_DBGF_TRUNCATED_REGISTER864 *865 * @param pVM The VM handle.866 * @param idCpu The target CPU ID.867 * @param enmReg The register that's being queried.868 * @param pu8 Where to store the register value.869 */870 VMMR3DECL(int) DBGFR3RegQueryU8(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t *pu8)871 {872 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);873 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);874 875 uint64_t u64Value;876 uint32_t fRegSizes;877 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);878 if (RT_SUCCESS(rc))879 {880 *pu8 = (uint8_t)u64Value;881 if (R_SZ_8 & fRegSizes)882 rc = VINF_SUCCESS;883 else884 rc = VINF_DBGF_TRUNCATED_REGISTER;885 }886 else887 *pu8 = 0;888 return rc;889 }890 891 892 /**893 * Queries a 16-bit register value.894 *895 * @retval VINF_SUCCESS896 * @retval VERR_INVALID_VM_HANDLE897 * @retval VERR_INVALID_CPU_ID898 * @retval VERR_DBGF_INVALID_REGISTER899 * @retval VINF_DBGF_TRUNCATED_REGISTER900 * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER901 *902 * @param pVM The VM handle.903 * @param idCpu The target CPU ID.904 * @param enmReg The register that's being queried.905 * @param pu16 Where to store the register value.906 */907 VMMR3DECL(int) DBGFR3RegQueryU16(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t *pu16)908 {909 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);910 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);911 912 uint64_t u64Value;913 uint32_t fRegSizes;914 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);915 if (RT_SUCCESS(rc))916 {917 *pu16 = (uint16_t)u64Value;918 if (R_SZ_16 & fRegSizes)919 rc = VINF_SUCCESS;920 else if (~(R_SZ_8 | R_SZ_16) & fRegSizes)921 rc = VINF_DBGF_TRUNCATED_REGISTER;922 else923 rc = VINF_DBGF_ZERO_EXTENDED_REGISTER;924 }925 else926 *pu16 = 0;927 return rc;928 }929 930 931 /**932 * Queries a 32-bit register value.933 *934 * @retval VINF_SUCCESS935 * @retval VERR_INVALID_VM_HANDLE936 * @retval VERR_INVALID_CPU_ID937 * @retval VERR_DBGF_INVALID_REGISTER938 * @retval VINF_DBGF_TRUNCATED_REGISTER939 * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER940 *941 * @param pVM The VM handle.942 * @param idCpu The target CPU ID.943 * @param enmReg The register that's being queried.944 * @param pu32 Where to store the register value.945 */946 VMMR3DECL(int) DBGFR3RegQueryU32(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t *pu32)947 {948 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);949 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);950 951 uint64_t u64Value;952 uint32_t fRegSizes;953 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);954 if (RT_SUCCESS(rc))955 {956 *pu32 = (uint32_t)u64Value;957 if (R_SZ_32 & fRegSizes)958 rc = VINF_SUCCESS;959 else if (~(R_SZ_8 | R_SZ_16 | R_SZ_32) & fRegSizes)960 rc = VINF_DBGF_TRUNCATED_REGISTER;961 else962 rc = VINF_DBGF_ZERO_EXTENDED_REGISTER;963 }964 else965 *pu32 = 0;966 return rc;967 }968 969 970 /**971 * Queries a 64-bit register value.972 *973 * @retval VINF_SUCCESS974 * @retval VERR_INVALID_VM_HANDLE975 * @retval VERR_INVALID_CPU_ID976 * @retval VERR_DBGF_INVALID_REGISTER977 * @retval VINF_DBGF_TRUNCATED_REGISTER978 * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER979 *980 * @param pVM The VM handle.981 * @param idCpu The target CPU ID.982 * @param enmReg The register that's being queried.983 * @param pu64 Where to store the register value.984 */985 VMMR3DECL(int) DBGFR3RegQueryU64(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64)986 {987 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);988 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);989 990 uint64_t u64Value;991 uint32_t fRegSizes;992 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes);993 if (RT_SUCCESS(rc))994 {995 *pu64 = u64Value;996 if (R_SZ_64 & fRegSizes)997 rc = VINF_SUCCESS;998 else if (~(R_SZ_8 | R_SZ_16 | R_SZ_32 | R_SZ_64) & fRegSizes)999 rc = VINF_DBGF_TRUNCATED_REGISTER;1000 else1001 rc = VINF_DBGF_ZERO_EXTENDED_REGISTER;1002 }1003 else1004 *pu64 = 0;1005 return rc;1006 }1007 1008 1009 /**1010 * Wrapper around CPUMQueryGuestMsr for dbgfR3RegQueryBatchWorker.1011 *1012 * @retval VINF_SUCCESS1013 * @retval VERR_DBGF_INVALID_REGISTER1014 *1015 * @param pVCpu The current CPU.1016 * @param pReg The where to store the register value and1017 * size.1018 * @param idMsr The MSR to get.1019 */1020 static void dbgfR3RegGetMsrBatch(PVMCPU pVCpu, PDBGFREGENTRY pReg, uint32_t idMsr)1021 {1022 pReg->enmType = DBGFREGVALTYPE_U64;1023 int rc = CPUMQueryGuestMsr(pVCpu, idMsr, &pReg->Val.u64);1024 if (RT_FAILURE(rc))1025 {1026 AssertMsg(rc == VERR_CPUM_RAISE_GP_0, ("%Rrc\n", rc));1027 pReg->Val.u64 = 0;1028 }1029 }1030 1031 1032 static DECLCALLBACK(int) dbgfR3RegQueryBatchWorker(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)1033 {1034 PVMCPU pVCpu = &pVM->aCpus[idCpu];1035 PCCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);1036 1037 PDBGFREGENTRY pReg = paRegs - 1;1038 while (cRegs-- > 0)1039 {1040 pReg++;1041 pReg->Val.au64[0] = 0;1042 pReg->Val.au64[1] = 0;1043 1044 DBGFREG const enmReg = pReg->enmReg;1045 AssertMsgReturn(enmReg >= 0 && enmReg <= DBGFREG_END, ("%d (%#x)\n", enmReg, enmReg), VERR_DBGF_INVALID_REGISTER);1046 if (enmReg != DBGFREG_END)1047 {1048 PCDBGFREGDESC pDesc = &g_aDbgfRegDescs[enmReg];1049 if (!pDesc->pfnGet)1050 {1051 PCRTUINT128U pu = (PCRTUINT128U)((uintptr_t)pCtx + pDesc->offCtx);1052 pReg->enmType = pDesc->enmType;1053 switch (pDesc->enmType)1054 {1055 case DBGFREGVALTYPE_U8: pReg->Val.u8 = pu->au8[0]; break;1056 case DBGFREGVALTYPE_U16: pReg->Val.u16 = pu->au16[0]; break;1057 case DBGFREGVALTYPE_U32: pReg->Val.u32 = pu->au32[0]; break;1058 case DBGFREGVALTYPE_U64: pReg->Val.u64 = pu->au64[0]; break;1059 case DBGFREGVALTYPE_U128:1060 pReg->Val.au64[0] = pu->au64[0];1061 pReg->Val.au64[1] = pu->au64[1];1062 break;1063 case DBGFREGVALTYPE_LRD:1064 pReg->Val.au64[0] = pu->au64[0];1065 pReg->Val.au16[5] = pu->au16[5];1066 break;1067 default:1068 AssertMsgFailedReturn(("%s %d\n", pDesc->pszName, pDesc->enmType), VERR_INTERNAL_ERROR_3);1069 }1070 }1071 else1072 {1073 int rc = pDesc->pfnGet(pVCpu, pDesc, pCtx, &pReg->Val.u);1074 if (RT_FAILURE(rc))1075 return rc;1076 }1077 }1078 }1079 1080 return VINF_SUCCESS;1081 }1082 1083 1084 /**1085 * Query a batch of registers.1086 *1087 * @retval VINF_SUCCESS1088 * @retval VERR_INVALID_VM_HANDLE1089 * @retval VERR_INVALID_CPU_ID1090 * @retval VERR_DBGF_INVALID_REGISTER1091 *1092 * @param pVM The VM handle.1093 * @param idCpu The target CPU ID.1094 * @param paRegs Pointer to an array of @a cRegs elements. On1095 * input the enmReg members indicates which1096 * registers to query. On successful return the1097 * other members are set. DBGFREG_END can be used1098 * as a filler.1099 * @param cRegs The number of entries in @a paRegs.1100 */1101 VMMR3DECL(int) DBGFR3RegQueryBatch(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)1102 {1103 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);1104 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);1105 if (!cRegs)1106 return VINF_SUCCESS;1107 AssertReturn(cRegs < _1M, VERR_OUT_OF_RANGE);1108 AssertPtrReturn(paRegs, VERR_INVALID_POINTER);1109 size_t iReg = cRegs;1110 while (iReg-- > 0)1111 {1112 DBGFREG enmReg = paRegs[iReg].enmReg;1113 AssertMsgReturn(enmReg < DBGFREG_END && enmReg >= DBGFREG_AL, ("%d (%#x)", enmReg, enmReg), VERR_DBGF_INVALID_REGISTER);1114 }1115 1116 return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryBatchWorker, 4, pVM, idCpu, paRegs, cRegs);1117 }1118 1119 1120 /**1121 * Query a all registers for a Virtual CPU.1122 *1123 * @retval VINF_SUCCESS1124 * @retval VERR_INVALID_VM_HANDLE1125 * @retval VERR_INVALID_CPU_ID1126 *1127 * @param pVM The VM handle.1128 * @param idCpu The target CPU ID.1129 * @param paRegs Pointer to an array of @a cRegs elements.1130 * These will be filled with the CPU register1131 * values. Overflowing entries will be set to1132 * DBGFREG_END. The returned registers can be1133 * accessed by using the DBGFREG values as index.1134 * @param cRegs The number of entries in @a paRegs. The1135 * recommended value is DBGFREG_ALL_COUNT.1136 */1137 VMMR3DECL(int) DBGFR3RegQueryAll(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)1138 {1139 /*1140 * Validate input.1141 */1142 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);1143 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);1144 if (!cRegs)1145 return VINF_SUCCESS;1146 AssertReturn(cRegs < _1M, VERR_OUT_OF_RANGE);1147 AssertPtrReturn(paRegs, VERR_INVALID_POINTER);1148 1149 /*1150 * Convert it into a batch query (lazy bird).1151 */1152 unsigned iReg = 0;1153 while (iReg < cRegs && iReg < DBGFREG_ALL_COUNT)1154 {1155 paRegs[iReg].enmReg = (DBGFREG)iReg;1156 iReg++;1157 }1158 while (iReg < cRegs)1159 paRegs[iReg++].enmReg = DBGFREG_END;1160 1161 return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryBatchWorker, 4, pVM, idCpu, paRegs, cRegs);1162 }1163 1164 1165 1166 /**1167 * Gets the name of a register.1168 *1169 * @returns Pointer to read-only register name (lower case). NULL if the1170 * parameters are invalid.1171 * @param enmReg The register identifier.1172 * @param enmType The register type. This is for sort out1173 * aliases. Pass DBGFREGVALTYPE_INVALID to get1174 * the standard name.1175 */1176 VMMR3DECL(const char *) DBGFR3RegName(DBGFREG enmReg, DBGFREGVALTYPE enmType)1177 {1178 AssertReturn(enmReg >= DBGFREG_AL && enmReg < DBGFREG_END, NULL);1179 AssertReturn(enmType >= DBGFREGVALTYPE_INVALID && enmType < DBGFREGVALTYPE_END, NULL);1180 1181 PCDBGFREGDESC pDesc = &g_aDbgfRegDescs[enmReg];1182 PCDBGFREGALIAS pAlias = pDesc->paAliases;1183 if ( pAlias1184 && pDesc->enmType != enmType1185 && enmType != DBGFREGVALTYPE_INVALID)1186 {1187 while (pAlias->pszName)1188 {1189 if (pAlias->enmType == enmType)1190 return pAlias->pszName;1191 pAlias++;1192 }1193 }1194 1195 return pDesc->pszName;1196 }1197 -
trunk/src/VBox/VMM/VMMR3/DBGFReg.cpp
r35351 r35410 23 23 #include <VBox/vmm/dbgf.h> 24 24 #include "DBGFInternal.h" 25 #include <VBox/vmm/mm.h> 25 26 #include <VBox/vmm/vm.h> 26 27 #include <VBox/param.h> 27 28 #include <VBox/err.h> 28 29 #include <VBox/log.h> 30 #include <iprt/ctype.h> 31 #include <iprt/string.h> 29 32 30 33 … … 32 35 * Defined Constants And Macros * 33 36 *******************************************************************************/ 34 /** @name Register and value sizes used by dbgfR3RegQueryWorker and 35 * dbgfR3RegSetWorker. 36 * @{ */ 37 #define R_SZ_8 RT_BIT(0) 38 #define R_SZ_16 RT_BIT(1) 39 #define R_SZ_32 RT_BIT(2) 40 #define R_SZ_64 RT_BIT(3) 41 #define R_SZ_64_16 RT_BIT(4) 42 #define R_SZ_80 RT_BIT(5) 43 #define R_SZ_128 RT_BIT(6) 44 #define R_SZ_8_TO_64 (R_SZ_8 | R_SZ_16 | R_SZ_32 | R_SZ_64) 45 #define R_SZ_16_TO_64 (R_SZ_16 | R_SZ_32 | R_SZ_64) 46 #define R_SZ_32_OR_64 (R_SZ_32 | R_SZ_64) 47 /** @} */ 37 /** Locks the register database for writing. */ 38 #define DBGF_REG_DB_LOCK_WRITE(pVM) \ 39 do { \ 40 int rcSem = RTSemRWRequestWrite((pVM)->dbgf.s.hRegDbLock, RT_INDEFINITE_WAIT); \ 41 AssertRC(rcSem); \ 42 } while (0) 43 44 /** Unlocks the register database after writing. */ 45 #define DBGF_REG_DB_UNLOCK_WRITE(pVM) \ 46 do { \ 47 int rcSem = RTSemRWReleaseWrite((pVM)->dbgf.s.hRegDbLock); \ 48 AssertRC(rcSem); \ 49 } while (0) 50 51 /** Locks the register database for reading. */ 52 #define DBGF_REG_DB_LOCK_READ(pVM) \ 53 do { \ 54 int rcSem = RTSemRWRequestRead((pVM)->dbgf.s.hRegDbLock, RT_INDEFINITE_WAIT); \ 55 AssertRC(rcSem); \ 56 } while (0) 57 58 /** Unlocks the register database after reading. */ 59 #define DBGF_REG_DB_UNLOCK_READ(pVM) \ 60 do { \ 61 int rcSem = RTSemRWReleaseRead((pVM)->dbgf.s.hRegDbLock); \ 62 AssertRC(rcSem); \ 63 } while (0) 64 48 65 49 66 … … 52 69 *******************************************************************************/ 53 70 /** 54 * Register sub-field descriptor. 55 */ 56 typedef struct DBGFREGSUBFIELD 57 { 58 /** The name of the sub-field. NULL is used to terminate the array. */ 59 const char *pszName; 60 /** The index of the first bit. */ 61 uint8_t iFirstBit; 62 /** The number of bits. */ 63 uint8_t cBits; 64 /** The shift count. */ 65 int8_t cShift; 66 /** @todo getter/setter callbacks? */ 67 } DBGFREGSUBFIELD; 68 /** Pointer to a const register sub-field descriptor. */ 69 typedef DBGFREGSUBFIELD const *PCDBGFREGSUBFIELD; 70 71 /** 72 * Register alias descriptor. 73 */ 74 typedef struct DBGFREGALIAS 75 { 76 /** The alias name. NULL is used to terminate the array. */ 77 const char *pszName; 78 /** Set to a valid type if the alias has a different type. */ 79 DBGFREGVALTYPE enmType; 80 } DBGFREGALIAS; 81 /** Pointer to a const register alias descriptor. */ 82 typedef DBGFREGALIAS const *PCDBGFREGALIAS; 83 84 /** 85 * Register descriptor. 86 */ 87 typedef struct DBGFREGDESC 88 { 89 /** The normal register name. */ 90 const char *pszName; 91 /** The register identifier (same as the table index). */ 92 DBGFREG enmReg; 93 /** The default register type. */ 94 DBGFREGVALTYPE enmType; 95 /** The offset info the CPUMCTX structure. ~(size_t)0 if not applicable. */ 96 size_t offCtx; 97 /** Getter (optional). */ 98 DECLCALLBACKMEMBER(int, pfnGet)(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 99 /** Setter (optional). */ 100 DECLCALLBACKMEMBER(int, pfnSet)(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 101 /** Aliases (optional). */ 102 PCDBGFREGALIAS paAliases; 103 /** Sub fields (optional). */ 104 PCDBGFREGSUBFIELD paSubFields; 105 } DBGFREGDESC; 106 /** Pointer to a const register descriptor. */ 107 typedef DBGFREGDESC const *PCDBGFREGDESC; 108 109 110 /******************************************************************************* 111 * Internal Functions * 112 *******************************************************************************/ 113 static DECLCALLBACK(int) dbgfR3RegSet_seg(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 114 static DECLCALLBACK(int) dbgfR3RegGet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 115 static DECLCALLBACK(int) dbgfR3RegSet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 116 static DECLCALLBACK(int) dbgfR3RegGet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 117 static DECLCALLBACK(int) dbgfR3RegSet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 118 static DECLCALLBACK(int) dbgfR3RegGet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 119 static DECLCALLBACK(int) dbgfR3RegSet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 120 static DECLCALLBACK(int) dbgfR3RegGet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 121 static DECLCALLBACK(int) dbgfR3RegSet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 122 static DECLCALLBACK(int) dbgfR3RegGet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 123 static DECLCALLBACK(int) dbgfR3RegSet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 124 static DECLCALLBACK(int) dbgfR3RegGet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 125 static DECLCALLBACK(int) dbgfR3RegSet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 126 static DECLCALLBACK(int) dbgfR3RegGet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue); 127 static DECLCALLBACK(int) dbgfR3RegSet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask); 128 129 130 /******************************************************************************* 131 * Global Variables * 132 *******************************************************************************/ 133 /* 134 * Set up aliases. 135 */ 136 #define DBGFREGALIAS_STD(Name, psz32, psz16, psz8) \ 137 static DBGFREGALIAS const g_aDbgfRegAliases_##Name[] = \ 138 { \ 139 { psz32, DBGFREGVALTYPE_U32 }, \ 140 { psz16, DBGFREGVALTYPE_U16 }, \ 141 { psz8, DBGFREGVALTYPE_U8 }, \ 142 { NULL, DBGFREGVALTYPE_INVALID } \ 71 * Register set registration record type. 72 */ 73 typedef enum DBGFREGSETTYPE 74 { 75 /** Invalid zero value. */ 76 DBGFREGSETTYPE_INVALID = 0, 77 /** CPU record. */ 78 DBGFREGSETTYPE_CPU, 79 /** Device record. */ 80 DBGFREGSETTYPE_DEVICE, 81 /** End of valid record types. */ 82 DBGFREGSETTYPE_END 83 } DBGFREGSETTYPE; 84 85 86 /** 87 * Register set registration record. 88 */ 89 typedef struct DBGFREGSET 90 { 91 /** String space core. */ 92 RTSTRSPACECORE Core; 93 /** The registration record type. */ 94 DBGFREGSETTYPE enmType; 95 /** The user argument for the callbacks. */ 96 union 97 { 98 /** The CPU view. */ 99 PVMCPU pVCpu; 100 /** The device view. */ 101 PPDMDEVINS pDevIns; 102 /** The general view. */ 103 void *pv; 104 } uUserArg; 105 106 /** The register descriptors. */ 107 PCDBGFREGDESC paDescs; 108 /** The number of register descriptors. */ 109 size_t cDescs; 110 111 /** The register name prefix. */ 112 char szPrefix[32]; 113 } DBGFREGSET; 114 /** Pointer to a register registration record. */ 115 typedef DBGFREGSET *PDBGFREGSET; 116 117 118 /** 119 * Validates a register name. 120 * 121 * This is used for prefixes, aliases and field names. 122 * 123 * @returns true if valid, false if not. 124 * @param pszName The register name to validate. 125 */ 126 static bool dbgfR3RegIsNameValid(const char *pszName) 127 { 128 if (!RT_C_IS_ALPHA(*pszName)) 129 return false; 130 char ch; 131 while ((ch = *++pszName)) 132 if ( !RT_C_IS_LOWER(ch) 133 && !RT_C_IS_DIGIT(ch) 134 && ch != '_') 135 return false; 136 return true; 137 } 138 139 140 /** 141 * Common worker for registering a register set. 142 * 143 * @returns VBox status code. 144 * @param pVM The VM handle. 145 * @param paRegisters The register descriptors. 146 * @param enmType The set type. 147 * @param pvUserArg The user argument for the callbacks. 148 * @param pszPrefix The name prefix. 149 * @param iInstance The instance number to be appended to @a 150 * pszPrefix when creating the set name. 151 */ 152 static int dbgfR3RegRegisterCommon(PVM pVM, PCDBGFREGDESC paRegisters, DBGFREGSETTYPE enmType, void *pvUserArg, const char *pszPrefix, uint32_t iInstance) 153 { 154 /* 155 * Validate input. 156 */ 157 /* The name components. */ 158 AssertMsgReturn(dbgfR3RegIsNameValid(pszPrefix), ("%s\n", pszPrefix), VERR_INVALID_NAME); 159 const char *psz = RTStrEnd(pszPrefix, RTSTR_MAX); 160 bool const fNeedUnderscore = RT_C_IS_DIGIT(psz[-1]); 161 size_t const cchPrefix = psz - pszPrefix + fNeedUnderscore; 162 AssertMsgReturn(cchPrefix < RT_SIZEOFMEMB(DBGFREGSET, szPrefix) - 4 - 1, ("%s\n", pszPrefix), VERR_INVALID_NAME); 163 164 AssertMsgReturn(iInstance <= 9999, ("%d\n", iInstance), VERR_INVALID_NAME); 165 166 /* The descriptors. */ 167 uint32_t iDesc; 168 for (iDesc = 0; paRegisters[iDesc].pszName != NULL; iDesc++) 169 { 170 AssertMsgReturn(dbgfR3RegIsNameValid(paRegisters[iDesc].pszName), ("%s (#%u)\n", paRegisters[iDesc].pszName, iDesc), VERR_INVALID_NAME); 171 172 if (enmType == DBGFREGSETTYPE_CPU) 173 AssertMsgReturn((unsigned)paRegisters[iDesc].enmReg == iDesc && iDesc < (unsigned)DBGFREG_END, 174 ("%d iDesc=%d\n", paRegisters[iDesc].enmReg, iDesc), 175 VERR_INVALID_PARAMETER); 176 else 177 AssertReturn(paRegisters[iDesc].enmReg == DBGFREG_END, VERR_INVALID_PARAMETER); 178 AssertReturn( paRegisters[iDesc].enmType > DBGFREGVALTYPE_INVALID 179 && paRegisters[iDesc].enmType < DBGFREGVALTYPE_END, VERR_INVALID_PARAMETER); 180 AssertMsgReturn(paRegisters[iDesc].fFlags & ~DBGFREG_FLAGS_READ_ONLY, 181 ("%#x (#%u)\n", paRegisters[iDesc].fFlags, iDesc), 182 VERR_INVALID_PARAMETER); 183 AssertPtrReturn(paRegisters[iDesc].pfnGet, VERR_INVALID_PARAMETER); 184 AssertPtrReturn(paRegisters[iDesc].pfnSet, VERR_INVALID_PARAMETER); 185 186 PCDBGFREGALIAS paAliases = paRegisters[iDesc].paAliases; 187 if (paAliases) 188 { 189 AssertPtrReturn(paAliases, VERR_INVALID_PARAMETER); 190 for (uint32_t j = 0; paAliases[j].pszName; j++) 191 { 192 AssertMsgReturn(dbgfR3RegIsNameValid(paAliases[j].pszName), ("%s (%s)\n", paAliases[j].pszName, paRegisters[iDesc].pszName), VERR_INVALID_NAME); 193 AssertReturn( paAliases[j].enmType > DBGFREGVALTYPE_INVALID 194 && paAliases[j].enmType < DBGFREGVALTYPE_END, VERR_INVALID_PARAMETER); 195 } 196 } 197 198 PCDBGFREGSUBFIELD paSubFields = paRegisters[iDesc].paSubFields; 199 if (paSubFields) 200 { 201 AssertPtrReturn(paSubFields, VERR_INVALID_PARAMETER); 202 for (uint32_t j = 0; paSubFields[j].pszName; j++) 203 { 204 AssertMsgReturn(dbgfR3RegIsNameValid(paSubFields[j].pszName), ("%s (%s)\n", paSubFields[j].pszName, paRegisters[iDesc].pszName), VERR_INVALID_NAME); 205 AssertReturn(paSubFields[j].iFirstBit + paSubFields[j].cBits <= 128, VERR_INVALID_PARAMETER); 206 AssertReturn(paSubFields[j].cBits + paSubFields[j].cShift <= 128, VERR_INVALID_PARAMETER); 207 AssertPtrNullReturn(paSubFields[j].pfnGet, VERR_INVALID_POINTER); 208 AssertPtrNullReturn(paSubFields[j].pfnSet, VERR_INVALID_POINTER); 209 } 210 } 143 211 } 144 DBGFREGALIAS_STD(rax, "eax", "ax", "al"); 145 DBGFREGALIAS_STD(rcx, "ecx", "cx", "cl"); 146 DBGFREGALIAS_STD(rdx, "edx", "dx", "dl"); 147 DBGFREGALIAS_STD(rbx, "ebx", "bx", "bl"); 148 DBGFREGALIAS_STD(rsp, "esp", "sp", NULL); 149 DBGFREGALIAS_STD(rbp, "ebp", "bp", NULL); 150 DBGFREGALIAS_STD(rsi, "esi", "si", "sil"); 151 DBGFREGALIAS_STD(rdi, "edi", "di", "dil"); 152 DBGFREGALIAS_STD(r8, "r8d", "r8w", "r8b"); 153 DBGFREGALIAS_STD(r9, "r9d", "r9w", "r9b"); 154 DBGFREGALIAS_STD(r10, "r10d", "r10w", "r10b"); 155 DBGFREGALIAS_STD(r11, "r11d", "r11w", "r11b"); 156 DBGFREGALIAS_STD(r12, "r12d", "r12w", "r12b"); 157 DBGFREGALIAS_STD(r13, "r13d", "r13w", "r13b"); 158 DBGFREGALIAS_STD(r14, "r14d", "r14w", "r14b"); 159 DBGFREGALIAS_STD(r15, "r15d", "r15w", "r15b"); 160 DBGFREGALIAS_STD(rip, "eip", "ip", NULL); 161 DBGFREGALIAS_STD(rflags, "eflags", "flags", NULL); 162 #undef DBGFREGALIAS_STD 163 164 static DBGFREGALIAS const g_aDbgfRegAliases_fpuip[] = 165 { 166 { "fpuip", DBGFREGVALTYPE_U16 }, 167 { NULL, DBGFREGVALTYPE_INVALID } 168 }; 169 170 static DBGFREGALIAS const g_aDbgfRegAliases_fpudp[] = 171 { 172 { "fpudp", DBGFREGVALTYPE_U16 }, 173 { NULL, DBGFREGVALTYPE_INVALID } 174 }; 175 176 static DBGFREGALIAS const g_aDbgfRegAliases_cr0[] = 177 { 178 { "msw", DBGFREGVALTYPE_U16 }, 179 { NULL, DBGFREGVALTYPE_INVALID } 180 }; 181 182 /* 183 * Sub fields. 184 */ 185 /** Sub-fields for the (hidden) segment attribute register. */ 186 static DBGFREGSUBFIELD const g_aDbgfRegFields_seg[] = 187 { 188 { "type", 0, 4, 0 }, 189 { "s", 4, 1, 0 }, 190 { "dpl", 5, 2, 0 }, 191 { "p", 7, 1, 0 }, 192 { "avl", 12, 1, 0 }, 193 { "l", 13, 1, 0 }, 194 { "d", 14, 1, 0 }, 195 { "g", 15, 1, 0 }, 196 { NULL, 0, 0, 0 } 197 }; 198 199 /** Sub-fields for the flags register. */ 200 static DBGFREGSUBFIELD const g_aDbgfRegFields_rflags[] = 201 { 202 { "cf", 0, 1, 0 }, 203 { "pf", 2, 1, 0 }, 204 { "af", 4, 1, 0 }, 205 { "zf", 6, 1, 0 }, 206 { "sf", 7, 1, 0 }, 207 { "tf", 8, 1, 0 }, 208 { "if", 9, 1, 0 }, 209 { "df", 10, 1, 0 }, 210 { "of", 11, 1, 0 }, 211 { "iopl", 12, 2, 0 }, 212 { "nt", 14, 1, 0 }, 213 { "rf", 16, 1, 0 }, 214 { "vm", 17, 1, 0 }, 215 { "ac", 18, 1, 0 }, 216 { "vif", 19, 1, 0 }, 217 { "vip", 20, 1, 0 }, 218 { "id", 21, 1, 0 }, 219 { NULL, 0, 0, 0 } 220 }; 221 222 /** Sub-fields for the FPU control word register. */ 223 static DBGFREGSUBFIELD const g_aDbgfRegFields_fcw[] = 224 { 225 { "im", 1, 1, 0 }, 226 { "dm", 2, 1, 0 }, 227 { "zm", 3, 1, 0 }, 228 { "om", 4, 1, 0 }, 229 { "um", 5, 1, 0 }, 230 { "pm", 6, 1, 0 }, 231 { "pc", 8, 2, 0 }, 232 { "rc", 10, 2, 0 }, 233 { "x", 12, 1, 0 }, 234 { NULL, 0, 0, 0 } 235 }; 236 237 /** Sub-fields for the FPU status word register. */ 238 static DBGFREGSUBFIELD const g_aDbgfRegFields_fsw[] = 239 { 240 { "ie", 0, 1, 0 }, 241 { "de", 1, 1, 0 }, 242 { "ze", 2, 1, 0 }, 243 { "oe", 3, 1, 0 }, 244 { "ue", 4, 1, 0 }, 245 { "pe", 5, 1, 0 }, 246 { "se", 6, 1, 0 }, 247 { "es", 7, 1, 0 }, 248 { "c0", 8, 1, 0 }, 249 { "c1", 9, 1, 0 }, 250 { "c2", 10, 1, 0 }, 251 { "top", 11, 3, 0 }, 252 { "c3", 14, 1, 0 }, 253 { "b", 15, 1, 0 }, 254 { NULL, 0, 0, 0 } 255 }; 256 257 /** Sub-fields for the FPU tag word register. */ 258 static DBGFREGSUBFIELD const g_aDbgfRegFields_ftw[] = 259 { 260 { "tag0", 0, 2, 0 }, 261 { "tag1", 2, 2, 0 }, 262 { "tag2", 4, 2, 0 }, 263 { "tag3", 6, 2, 0 }, 264 { "tag4", 8, 2, 0 }, 265 { "tag5", 10, 2, 0 }, 266 { "tag6", 12, 2, 0 }, 267 { "tag7", 14, 2, 0 }, 268 { NULL, 0, 0, 0 } 269 }; 270 271 /** Sub-fields for the Multimedia Extensions Control and Status Register. */ 272 static DBGFREGSUBFIELD const g_aDbgfRegFields_mxcsr[] = 273 { 274 { "ie", 0, 1, 0 }, 275 { "de", 1, 1, 0 }, 276 { "ze", 2, 1, 0 }, 277 { "oe", 3, 1, 0 }, 278 { "ue", 4, 1, 0 }, 279 { "pe", 5, 1, 0 }, 280 { "daz", 6, 1, 0 }, 281 { "im", 7, 1, 0 }, 282 { "dm", 8, 1, 0 }, 283 { "zm", 9, 1, 0 }, 284 { "om", 10, 1, 0 }, 285 { "um", 11, 1, 0 }, 286 { "pm", 12, 1, 0 }, 287 { "rc", 13, 2, 0 }, 288 { "fz", 14, 1, 0 }, 289 { NULL, 0, 0, 0 } 290 }; 291 292 /** Sub-fields for the FPU tag word register. */ 293 static DBGFREGSUBFIELD const g_aDbgfRegFields_stN[] = 294 { 295 { "man", 0, 64, 0 }, 296 { "exp", 64, 15, 0 }, 297 { "sig", 79, 1, 0 }, 298 { NULL, 0, 0, 0 } 299 }; 300 301 /** Sub-fields for the MMX registers. */ 302 static DBGFREGSUBFIELD const g_aDbgfRegFields_mmN[] = 303 { 304 { "dw0", 0, 32, 0 }, 305 { "dw1", 32, 32, 0 }, 306 { "w0", 0, 16, 0 }, 307 { "w1", 16, 16, 0 }, 308 { "w2", 32, 16, 0 }, 309 { "w3", 48, 16, 0 }, 310 { "b0", 0, 8, 0 }, 311 { "b1", 8, 8, 0 }, 312 { "b2", 16, 8, 0 }, 313 { "b3", 24, 8, 0 }, 314 { "b4", 32, 8, 0 }, 315 { "b5", 40, 8, 0 }, 316 { "b6", 48, 8, 0 }, 317 { "b7", 56, 8, 0 }, 318 { NULL, 0, 0, 0 } 319 }; 320 321 /** Sub-fields for the XMM registers. */ 322 static DBGFREGSUBFIELD const g_aDbgfRegFields_xmmN[] = 323 { 324 { "r0", 0, 32, 0 }, 325 { "r0.man", 0+ 0, 23, 0 }, 326 { "r0.exp", 0+23, 8, 0 }, 327 { "r0.sig", 0+31, 1, 0 }, 328 { "r1", 32, 32, 0 }, 329 { "r1.man", 32+ 0, 23, 0 }, 330 { "r1.exp", 32+23, 8, 0 }, 331 { "r1.sig", 32+31, 1, 0 }, 332 { "r2", 64, 32, 0 }, 333 { "r2.man", 64+ 0, 23, 0 }, 334 { "r2.exp", 64+23, 8, 0 }, 335 { "r2.sig", 64+31, 1, 0 }, 336 { "r3", 96, 32, 0 }, 337 { "r3.man", 96+ 0, 23, 0 }, 338 { "r3.exp", 96+23, 8, 0 }, 339 { "r3.sig", 96+31, 1, 0 }, 340 { NULL, 0, 0, 0 } 341 }; 342 343 /** Sub-fields for the CR0 register. */ 344 static DBGFREGSUBFIELD const g_aDbgfRegFields_cr0[] = 345 { 346 /** @todo */ 347 { NULL, 0, 0, 0 } 348 }; 349 350 /** Sub-fields for the CR3 register. */ 351 static DBGFREGSUBFIELD const g_aDbgfRegFields_cr3[] = 352 { 353 /** @todo */ 354 { NULL, 0, 0, 0 } 355 }; 356 357 /** Sub-fields for the CR4 register. */ 358 static DBGFREGSUBFIELD const g_aDbgfRegFields_cr4[] = 359 { 360 /** @todo */ 361 { NULL, 0, 0, 0 } 362 }; 363 364 /** Sub-fields for the DR6 register. */ 365 static DBGFREGSUBFIELD const g_aDbgfRegFields_dr6[] = 366 { 367 /** @todo */ 368 { NULL, 0, 0, 0 } 369 }; 370 371 /** Sub-fields for the DR7 register. */ 372 static DBGFREGSUBFIELD const g_aDbgfRegFields_dr7[] = 373 { 374 /** @todo */ 375 { NULL, 0, 0, 0 } 376 }; 377 378 /** Sub-fields for the CR_PAT MSR. */ 379 static DBGFREGSUBFIELD const g_aDbgfRegFields_apic_base[] = 380 { 381 { "bsp", 8, 1, 0 }, 382 { "ge", 9, 1, 0 }, 383 { "base", 12, 20, 12 }, 384 { NULL, 0, 0, 0 } 385 }; 386 387 /** Sub-fields for the CR_PAT MSR. */ 388 static DBGFREGSUBFIELD const g_aDbgfRegFields_cr_pat[] = 389 { 390 /** @todo */ 391 { NULL, 0, 0, 0 } 392 }; 393 394 /** Sub-fields for the PERF_STATUS MSR. */ 395 static DBGFREGSUBFIELD const g_aDbgfRegFields_perf_status[] = 396 { 397 /** @todo */ 398 { NULL, 0, 0, 0 } 399 }; 400 401 /** Sub-fields for the EFER MSR. */ 402 static DBGFREGSUBFIELD const g_aDbgfRegFields_efer[] = 403 { 404 /** @todo */ 405 { NULL, 0, 0, 0 } 406 }; 407 408 /** Sub-fields for the STAR MSR. */ 409 static DBGFREGSUBFIELD const g_aDbgfRegFields_star[] = 410 { 411 /** @todo */ 412 { NULL, 0, 0, 0 } 413 }; 414 415 /** Sub-fields for the CSTAR MSR. */ 416 static DBGFREGSUBFIELD const g_aDbgfRegFields_cstar[] = 417 { 418 /** @todo */ 419 { NULL, 0, 0, 0 } 420 }; 421 422 /** Sub-fields for the LSTAR MSR. */ 423 static DBGFREGSUBFIELD const g_aDbgfRegFields_lstar[] = 424 { 425 /** @todo */ 426 { NULL, 0, 0, 0 } 427 }; 428 429 /** Sub-fields for the SF_MASK MSR. */ 430 static DBGFREGSUBFIELD const g_aDbgfRegFields_sf_mask[] = 431 { 432 /** @todo */ 433 { NULL, 0, 0, 0 } 434 }; 435 436 437 438 /** 439 * The register descriptors. 440 */ 441 static DBGFREGDESC const g_aDbgfRegDescs[] = 442 { 443 #define DBGFREGDESC_REG(UName, LName) \ 444 { #LName, DBGFREG_##UName, DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, LName), NULL, NULL, g_aDbgfRegAliases_##LName, NULL } 445 DBGFREGDESC_REG(RAX, rax), 446 DBGFREGDESC_REG(RCX, rcx), 447 DBGFREGDESC_REG(RDX, rdx), 448 DBGFREGDESC_REG(RSP, rsp), 449 DBGFREGDESC_REG(RBP, rbp), 450 DBGFREGDESC_REG(RSI, rsi), 451 DBGFREGDESC_REG(RDI, rdi), 452 DBGFREGDESC_REG(R8, r8), 453 DBGFREGDESC_REG(R9, r9), 454 DBGFREGDESC_REG(R10, r10), 455 DBGFREGDESC_REG(R11, r11), 456 DBGFREGDESC_REG(R12, r12), 457 DBGFREGDESC_REG(R13, r13), 458 DBGFREGDESC_REG(R14, r14), 459 DBGFREGDESC_REG(R15, r15), 460 #define DBGFREGDESC_SEG(UName, LName) \ 461 { #LName, DBGFREG_##UName, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, LName), NULL, dbgfR3RegSet_seg, NULL, NULL }, \ 462 { #LName "_attr", DBGFREG_##UName##_ATTR, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, LName##Hid.Attr.u), NULL, NULL, NULL, g_aDbgfRegFields_seg }, \ 463 { #LName "_base", DBGFREG_##UName##_ATTR, DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, LName##Hid.u64Base), NULL, NULL, NULL, NULL }, \ 464 { #LName "_lim", DBGFREG_##UName##_ATTR, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, LName##Hid.u32Limit), NULL, NULL, NULL, NULL } 465 DBGFREGDESC_SEG(CS, cs), 466 DBGFREGDESC_SEG(DS, ds), 467 DBGFREGDESC_SEG(ES, es), 468 DBGFREGDESC_SEG(FS, fs), 469 DBGFREGDESC_SEG(GS, gs), 470 DBGFREGDESC_SEG(SS, ss), 471 DBGFREGDESC_REG(RIP, rip), 472 { "rflags", DBGFREG_RFLAGS, DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, rflags), NULL, NULL, g_aDbgfRegAliases_rflags, g_aDbgfRegFields_rflags }, 473 { "fcw", DBGFREG_FCW, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.FCW), NULL, NULL, NULL, g_aDbgfRegFields_fcw }, 474 { "fsw", DBGFREG_FSW, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.FSW), NULL, NULL, NULL, g_aDbgfRegFields_fsw }, 475 { "ftw", DBGFREG_FTW, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.FTW), dbgfR3RegGet_ftw, dbgfR3RegSet_ftw, NULL, g_aDbgfRegFields_ftw }, 476 { "fop", DBGFREG_FOP, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.FOP), NULL, NULL, NULL, NULL }, 477 { "fpuip", DBGFREG_FPUIP, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, fpu.FPUIP), NULL, NULL, g_aDbgfRegAliases_fpuip, NULL }, 478 { "fpucs", DBGFREG_FPUCS, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.CS), NULL, NULL, NULL, NULL }, 479 { "fpudp", DBGFREG_FPUDP, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, fpu.FPUDP), NULL, NULL, g_aDbgfRegAliases_fpudp, NULL }, 480 { "fpuds", DBGFREG_FPUDS, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, fpu.DS), NULL, NULL, NULL, NULL }, 481 { "mxcsr", DBGFREG_MXCSR, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, fpu.MXCSR), NULL, NULL, NULL, g_aDbgfRegFields_mxcsr }, 482 { "mxcsr_mask", DBGFREG_MXCSR_MASK, DBGFREGVALTYPE_U32, RT_OFFSETOF(CPUMCTX, fpu.MXCSR_MASK), NULL, NULL, NULL, g_aDbgfRegFields_mxcsr }, 483 #define DBGFREGDESC_ST(n) \ 484 { "st" #n, DBGFREG_ST##n, DBGFREGVALTYPE_80, ~(size_t)0, dbgfR3RegGet_stN, dbgfR3RegSet_stN, NULL, g_aDbgfRegFields_stN } 485 DBGFREGDESC_ST(0), 486 DBGFREGDESC_ST(1), 487 DBGFREGDESC_ST(2), 488 DBGFREGDESC_ST(3), 489 DBGFREGDESC_ST(4), 490 DBGFREGDESC_ST(5), 491 DBGFREGDESC_ST(6), 492 DBGFREGDESC_ST(7), 493 #define DBGFREGDESC_MM(n) \ 494 { "mm" #n, DBGFREG_MM##n, DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, fpu.aRegs[n].mmx), NULL, NULL, NULL, g_aDbgfRegFields_mmN } 495 DBGFREGDESC_MM(0), 496 DBGFREGDESC_MM(1), 497 DBGFREGDESC_MM(2), 498 DBGFREGDESC_MM(3), 499 DBGFREGDESC_MM(4), 500 DBGFREGDESC_MM(5), 501 DBGFREGDESC_MM(6), 502 DBGFREGDESC_MM(7), 503 #define DBGFREGDESC_XMM(n) \ 504 { "xmm" #n, DBGFREG_XMM##n, DBGFREGVALTYPE_U128, RT_OFFSETOF(CPUMCTX, fpu.aXMM[n].xmm), NULL, NULL, NULL, g_aDbgfRegFields_xmmN } 505 DBGFREGDESC_XMM(0), 506 DBGFREGDESC_XMM(1), 507 DBGFREGDESC_XMM(2), 508 DBGFREGDESC_XMM(3), 509 DBGFREGDESC_XMM(4), 510 DBGFREGDESC_XMM(5), 511 DBGFREGDESC_XMM(6), 512 DBGFREGDESC_XMM(7), 513 DBGFREGDESC_XMM(8), 514 DBGFREGDESC_XMM(9), 515 DBGFREGDESC_XMM(10), 516 DBGFREGDESC_XMM(11), 517 DBGFREGDESC_XMM(12), 518 DBGFREGDESC_XMM(13), 519 DBGFREGDESC_XMM(14), 520 DBGFREGDESC_XMM(15), 521 { "gdtr_base", DBGFREG_GDTR_BASE, DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, gdtr.pGdt), NULL, NULL, NULL, NULL }, 522 { "gdtr_limit", DBGFREG_GDTR_LIMIT, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, gdtr.cbGdt), NULL, NULL, NULL, NULL }, 523 { "idtr_base", DBGFREG_IDTR_BASE, DBGFREGVALTYPE_U64, RT_OFFSETOF(CPUMCTX, idtr.pIdt), NULL, NULL, NULL, NULL }, 524 { "idtr_limit", DBGFREG_IDTR_LIMIT, DBGFREGVALTYPE_U16, RT_OFFSETOF(CPUMCTX, idtr.cbIdt), NULL, NULL, NULL, NULL }, 525 DBGFREGDESC_SEG(LDTR, ldtr), 526 DBGFREGDESC_SEG(TR, tr), 527 { "cr0", DBGFREG_CR0, DBGFREGVALTYPE_U32, 0, dbgfR3RegGet_crX, dbgfR3RegSet_crX, g_aDbgfRegAliases_cr0, g_aDbgfRegFields_cr0 }, 528 { "cr2", DBGFREG_CR2, DBGFREGVALTYPE_U64, 2, dbgfR3RegGet_crX, dbgfR3RegSet_crX, NULL, NULL }, 529 { "cr3", DBGFREG_CR3, DBGFREGVALTYPE_U64, 3, dbgfR3RegGet_crX, dbgfR3RegSet_crX, NULL, g_aDbgfRegFields_cr3 }, 530 { "cr4", DBGFREG_CR4, DBGFREGVALTYPE_U32, 4, dbgfR3RegGet_crX, dbgfR3RegSet_crX, NULL, g_aDbgfRegFields_cr4 }, 531 { "cr8", DBGFREG_CR8, DBGFREGVALTYPE_U32, 8, dbgfR3RegGet_crX, dbgfR3RegSet_crX, NULL, NULL }, 532 { "dr0", DBGFREG_DR0, DBGFREGVALTYPE_U64, 0, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, NULL }, 533 { "dr1", DBGFREG_DR1, DBGFREGVALTYPE_U64, 1, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, NULL }, 534 { "dr2", DBGFREG_DR2, DBGFREGVALTYPE_U64, 2, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, NULL }, 535 { "dr3", DBGFREG_DR3, DBGFREGVALTYPE_U64, 3, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, NULL }, 536 { "dr6", DBGFREG_DR6, DBGFREGVALTYPE_U32, 6, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, g_aDbgfRegFields_dr6 }, 537 { "dr7", DBGFREG_DR7, DBGFREGVALTYPE_U32, 7, dbgfR3RegGet_drX, dbgfR3RegSet_drX, NULL, g_aDbgfRegFields_dr7 }, 538 { "apic_base", DBGFREG_MSR_IA32_APICBASE, DBGFREGVALTYPE_U32, MSR_IA32_APICBASE, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_apic_base }, 539 { "pat", DBGFREG_MSR_IA32_CR_PAT, DBGFREGVALTYPE_U64, MSR_IA32_CR_PAT, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_cr_pat }, 540 { "perf_status", DBGFREG_MSR_IA32_PERF_STATUS, DBGFREGVALTYPE_U64, MSR_IA32_PERF_STATUS, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_perf_status }, 541 { "sysenter_cs", DBGFREG_MSR_IA32_SYSENTER_CS, DBGFREGVALTYPE_U16, MSR_IA32_SYSENTER_CS, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL }, 542 { "sysenter_eip", DBGFREG_MSR_IA32_SYSENTER_EIP, DBGFREGVALTYPE_U32, MSR_IA32_SYSENTER_EIP, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL }, 543 { "sysenter_esp", DBGFREG_MSR_IA32_SYSENTER_ESP, DBGFREGVALTYPE_U32, MSR_IA32_SYSENTER_ESP, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL }, 544 { "tsc", DBGFREG_MSR_IA32_TSC, DBGFREGVALTYPE_U32, MSR_IA32_TSC, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL }, 545 { "efer", DBGFREG_MSR_K6_EFER, DBGFREGVALTYPE_U32, MSR_K6_EFER, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_efer }, 546 { "star", DBGFREG_MSR_K6_STAR, DBGFREGVALTYPE_U64, MSR_K6_STAR, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_star }, 547 { "cstar", DBGFREG_MSR_K8_CSTAR, DBGFREGVALTYPE_U64, MSR_K8_CSTAR, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_cstar }, 548 { "msr_fs_base", DBGFREG_MSR_K8_FS_BASE, DBGFREGVALTYPE_U64, MSR_K8_FS_BASE, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL }, 549 { "msr_gs_base", DBGFREG_MSR_K8_GS_BASE, DBGFREGVALTYPE_U64, MSR_K8_GS_BASE, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL }, 550 { "krnl_gs_base", DBGFREG_MSR_K8_KERNEL_GS_BASE, DBGFREGVALTYPE_U64, MSR_K8_KERNEL_GS_BASE, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL }, 551 { "lstar", DBGFREG_MSR_K8_LSTAR, DBGFREGVALTYPE_U64, MSR_K8_LSTAR, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, g_aDbgfRegFields_lstar }, 552 { "tsc_aux", DBGFREG_MSR_K8_TSC_AUX, DBGFREGVALTYPE_U64, MSR_K8_TSC_AUX, dbgfR3RegGet_msr, dbgfR3RegSet_msr, NULL, NULL }, 553 { "ah", DBGFREG_AH, DBGFREGVALTYPE_U8, RT_OFFSETOF(CPUMCTX, rax) + 1, NULL, NULL, NULL, NULL }, 554 { "ch", DBGFREG_CH, DBGFREGVALTYPE_U8, RT_OFFSETOF(CPUMCTX, rcx) + 1, NULL, NULL, NULL, NULL }, 555 { "dh", DBGFREG_DH, DBGFREGVALTYPE_U8, RT_OFFSETOF(CPUMCTX, rdx) + 1, NULL, NULL, NULL, NULL }, 556 { "bh", DBGFREG_BH, DBGFREGVALTYPE_U8, RT_OFFSETOF(CPUMCTX, rbx) + 1, NULL, NULL, NULL, NULL }, 557 { "gdtr", DBGFREG_GDTR, DBGFREGVALTYPE_DTR, ~(size_t)0, dbgfR3RegGet_gdtr, dbgfR3RegSet_gdtr, NULL, NULL }, 558 { "idtr", DBGFREG_IDTR, DBGFREGVALTYPE_DTR, ~(size_t)0, dbgfR3RegGet_idtr, dbgfR3RegSet_idtr, NULL, NULL }, 559 #undef DBGFREGDESC_REG 560 #undef DBGFREGDESC_SEG 561 #undef DBGFREGDESC_ST 562 #undef DBGFREGDESC_MM 563 #undef DBGFREGDESC_XMM 564 }; 565 566 567 static DECLCALLBACK(int) dbgfR3RegSet_seg(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 568 { 569 return VERR_NOT_IMPLEMENTED; 570 } 571 572 static DECLCALLBACK(int) dbgfR3RegGet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue) 573 { 574 return VERR_NOT_IMPLEMENTED; 575 } 576 577 static DECLCALLBACK(int) dbgfR3RegSet_crX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 578 { 579 return VERR_NOT_IMPLEMENTED; 580 } 581 582 static DECLCALLBACK(int) dbgfR3RegGet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue) 583 { 584 return VERR_NOT_IMPLEMENTED; 585 } 586 587 static DECLCALLBACK(int) dbgfR3RegSet_drX(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 588 { 589 return VERR_NOT_IMPLEMENTED; 590 } 591 592 static DECLCALLBACK(int) dbgfR3RegGet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue) 593 { 594 return VERR_NOT_IMPLEMENTED; 595 } 596 597 static DECLCALLBACK(int) dbgfR3RegSet_msr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 598 { 599 return VERR_NOT_IMPLEMENTED; 600 } 601 602 static DECLCALLBACK(int) dbgfR3RegGet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue) 603 { 604 return VERR_NOT_IMPLEMENTED; 605 } 606 607 static DECLCALLBACK(int) dbgfR3RegSet_gdtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 608 { 609 return VERR_NOT_IMPLEMENTED; 610 } 611 612 static DECLCALLBACK(int) dbgfR3RegGet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue) 613 { 614 return VERR_NOT_IMPLEMENTED; 615 } 616 617 static DECLCALLBACK(int) dbgfR3RegSet_idtr(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 618 { 619 return VERR_NOT_IMPLEMENTED; 620 } 621 622 static DECLCALLBACK(int) dbgfR3RegGet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue) 623 { 624 return VERR_NOT_IMPLEMENTED; 625 } 626 627 static DECLCALLBACK(int) dbgfR3RegSet_ftw(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 628 { 629 return VERR_NOT_IMPLEMENTED; 630 } 631 632 static DECLCALLBACK(int) dbgfR3RegGet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCCPUMCTX pCtx, PRTUINT128U puValue) 633 { 634 return VERR_NOT_IMPLEMENTED; 635 } 636 637 static DECLCALLBACK(int) dbgfR3RegSet_stN(PVMCPU pVCpu, struct DBGFREGDESC const *pDesc, PCPUMCTX pCtx, RTUINT128U uValue, RTUINT128U fMask) 638 { 639 return VERR_NOT_IMPLEMENTED; 640 } 641 642 643 644 /** 645 * Wrapper around CPUMQueryGuestMsr for dbgfR3RegQueryWorker. 212 213 /* 214 * Allocate a new record. 215 */ 216 PDBGFREGSET pRegRec = (PDBGFREGSET)MMR3HeapAlloc(pVM, MM_TAG_DBGF_REG, RT_OFFSETOF(DBGFREGSET, szPrefix[cchPrefix + 4 + 1])); 217 if (!pRegRec) 218 return VERR_NO_MEMORY; 219 220 pRegRec->Core.pszString = pRegRec->szPrefix; 221 pRegRec->enmType = enmType; 222 pRegRec->uUserArg.pv = pvUserArg; 223 pRegRec->paDescs = paRegisters; 224 pRegRec->cDescs = iDesc; 225 if (fNeedUnderscore) 226 RTStrPrintf(pRegRec->szPrefix, cchPrefix + 4 + 1, "%s_%u", pszPrefix, iInstance); 227 else 228 RTStrPrintf(pRegRec->szPrefix, cchPrefix + 4 + 1, "%s%u", pszPrefix, iInstance); 229 230 DBGF_REG_DB_LOCK_WRITE(pVM); 231 bool fInserted = RTStrSpaceInsert(&pVM->dbgf.s.RegSetSpace, &pRegRec->Core); 232 DBGF_REG_DB_UNLOCK_WRITE(pVM); 233 if (fInserted) 234 return VINF_SUCCESS; 235 236 MMR3HeapFree(pRegRec); 237 return VERR_DUPLICATE; 238 } 239 240 241 /** 242 * Registers a set of registers for a CPU. 243 * 244 * @returns VBox status code. 245 * @param pVCpu The virtual CPU handle. 246 * @param paRegisters The register descriptors. 247 */ 248 VMMR3_INT_DECL(int) DBGFR3RegRegisterDevice(PVMCPU pVCpu, PCDBGFREGDESC paRegisters) 249 { 250 return dbgfR3RegRegisterCommon(pVCpu->pVMR3, paRegisters, DBGFREGSETTYPE_CPU, pVCpu, "cpu", pVCpu->idCpu); 251 } 252 253 254 /** 255 * Registers a set of registers for a device. 256 * 257 * @returns VBox status code. 258 * @param enmReg The register identifier. 259 * @param enmType The register type. This is for sort out 260 * aliases. Pass DBGFREGVALTYPE_INVALID to get 261 * the standard name. 262 */ 263 VMMR3DECL(int) DBGFR3RegRegisterDevice(PVM pVM, PCDBGFREGDESC paRegisters, PPDMDEVINS pDevIns, const char *pszPrefix, uint32_t iInstance) 264 { 265 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 266 AssertPtrReturn(paRegisters, VERR_INVALID_POINTER); 267 AssertPtrReturn(pDevIns, VERR_INVALID_POINTER); 268 AssertPtrReturn(pszPrefix, VERR_INVALID_POINTER); 269 270 return dbgfR3RegRegisterCommon(pVM, paRegisters, DBGFREGSETTYPE_DEVICE, pDevIns, pszPrefix, iInstance); 271 } 272 273 274 /** 275 * Clears the register value variable. 276 * 277 * @param pValue The variable to clear. 278 */ 279 DECLINLINE(void) dbgfR3RegValClear(PDBGFREGVAL pValue) 280 { 281 pValue->au64[0] = 0; 282 pValue->au64[1] = 0; 283 } 284 285 286 /** 287 * Performs a cast between register value types. 646 288 * 647 289 * @retval VINF_SUCCESS 290 * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER 291 * @retval VINF_DBGF_TRUNCATED_REGISTER 292 * @retval VERR_DBGF_UNSUPPORTED_CAST 293 * 294 * @param pValue The value to cast (input + output). 295 * @param enmFromType The input value. 296 * @param enmToType The desired output value. 297 */ 298 static int dbgfR3RegValCast(PDBGFREGVAL pValue, DBGFREGVALTYPE enmFromType, DBGFREGVALTYPE enmToType) 299 { 300 DBGFREGVAL const InVal = *pValue; 301 dbgfR3RegValClear(pValue); 302 303 switch (enmFromType) 304 { 305 case DBGFREGVALTYPE_U8: 306 switch (enmToType) 307 { 308 case DBGFREGVALTYPE_U8: pValue->u8 = InVal.u8; return VINF_SUCCESS; 309 case DBGFREGVALTYPE_U16: pValue->u16 = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER; 310 case DBGFREGVALTYPE_U32: pValue->u32 = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER; 311 case DBGFREGVALTYPE_U64: pValue->u64 = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER; 312 case DBGFREGVALTYPE_U128: pValue->u128.s.Lo = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER; 313 case DBGFREGVALTYPE_80: return VERR_DBGF_UNSUPPORTED_CAST; 314 case DBGFREGVALTYPE_LRD: pValue->lrd = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER; 315 case DBGFREGVALTYPE_DTR: return VERR_DBGF_UNSUPPORTED_CAST; 316 317 case DBGFREGVALTYPE_32BIT_HACK: 318 case DBGFREGVALTYPE_END: 319 case DBGFREGVALTYPE_INVALID: 320 break; 321 } 322 break; 323 324 case DBGFREGVALTYPE_U16: 325 switch (enmToType) 326 { 327 case DBGFREGVALTYPE_U8: pValue->u8 = InVal.u16; return VINF_DBGF_TRUNCATED_REGISTER; 328 case DBGFREGVALTYPE_U16: pValue->u16 = InVal.u16; return VINF_SUCCESS; 329 case DBGFREGVALTYPE_U32: pValue->u32 = InVal.u16; return VINF_DBGF_ZERO_EXTENDED_REGISTER; 330 case DBGFREGVALTYPE_U64: pValue->u64 = InVal.u16; return VINF_DBGF_ZERO_EXTENDED_REGISTER; 331 case DBGFREGVALTYPE_U128: pValue->u128.s.Lo = InVal.u16; return VINF_DBGF_ZERO_EXTENDED_REGISTER; 332 case DBGFREGVALTYPE_80: return VERR_DBGF_UNSUPPORTED_CAST; 333 case DBGFREGVALTYPE_LRD: pValue->lrd = InVal.u16; return VINF_DBGF_ZERO_EXTENDED_REGISTER; 334 case DBGFREGVALTYPE_DTR: return VERR_DBGF_UNSUPPORTED_CAST; 335 336 case DBGFREGVALTYPE_32BIT_HACK: 337 case DBGFREGVALTYPE_END: 338 case DBGFREGVALTYPE_INVALID: 339 break; 340 } 341 break; 342 343 case DBGFREGVALTYPE_U32: 344 switch (enmToType) 345 { 346 case DBGFREGVALTYPE_U8: pValue->u8 = InVal.u32; return VINF_DBGF_TRUNCATED_REGISTER; 347 case DBGFREGVALTYPE_U16: pValue->u16 = InVal.u32; return VINF_DBGF_TRUNCATED_REGISTER; 348 case DBGFREGVALTYPE_U32: pValue->u32 = InVal.u32; return VINF_SUCCESS; 349 case DBGFREGVALTYPE_U64: pValue->u64 = InVal.u32; return VINF_DBGF_ZERO_EXTENDED_REGISTER; 350 case DBGFREGVALTYPE_U128: pValue->u128.s.Lo = InVal.u32; return VINF_DBGF_ZERO_EXTENDED_REGISTER; 351 case DBGFREGVALTYPE_80: return VERR_DBGF_UNSUPPORTED_CAST; 352 case DBGFREGVALTYPE_LRD: pValue->lrd = InVal.u32; return VINF_DBGF_ZERO_EXTENDED_REGISTER; 353 case DBGFREGVALTYPE_DTR: return VERR_DBGF_UNSUPPORTED_CAST; 354 355 case DBGFREGVALTYPE_32BIT_HACK: 356 case DBGFREGVALTYPE_END: 357 case DBGFREGVALTYPE_INVALID: 358 break; 359 } 360 break; 361 362 case DBGFREGVALTYPE_U64: 363 switch (enmToType) 364 { 365 case DBGFREGVALTYPE_U8: pValue->u8 = InVal.u64; return VINF_DBGF_TRUNCATED_REGISTER; 366 case DBGFREGVALTYPE_U16: pValue->u16 = InVal.u64; return VINF_DBGF_TRUNCATED_REGISTER; 367 case DBGFREGVALTYPE_U32: pValue->u32 = InVal.u64; return VINF_DBGF_TRUNCATED_REGISTER; 368 case DBGFREGVALTYPE_U64: pValue->u64 = InVal.u64; return VINF_SUCCESS; 369 case DBGFREGVALTYPE_U128: pValue->u128.s.Lo = InVal.u64; return VINF_DBGF_TRUNCATED_REGISTER; 370 case DBGFREGVALTYPE_80: return VERR_DBGF_UNSUPPORTED_CAST; 371 case DBGFREGVALTYPE_LRD: pValue->lrd = InVal.u64; return VINF_DBGF_ZERO_EXTENDED_REGISTER; 372 case DBGFREGVALTYPE_DTR: return VERR_DBGF_UNSUPPORTED_CAST; 373 374 case DBGFREGVALTYPE_32BIT_HACK: 375 case DBGFREGVALTYPE_END: 376 case DBGFREGVALTYPE_INVALID: 377 break; 378 } 379 break; 380 381 case DBGFREGVALTYPE_U128: 382 switch (enmToType) 383 { 384 case DBGFREGVALTYPE_U8: pValue->u8 = InVal.u128.s.Lo; return VINF_DBGF_TRUNCATED_REGISTER; 385 case DBGFREGVALTYPE_U16: pValue->u16 = InVal.u128.s.Lo; return VINF_DBGF_TRUNCATED_REGISTER; 386 case DBGFREGVALTYPE_U32: pValue->u32 = InVal.u128.s.Lo; return VINF_DBGF_TRUNCATED_REGISTER; 387 case DBGFREGVALTYPE_U64: pValue->u64 = InVal.u128.s.Lo; return VINF_DBGF_TRUNCATED_REGISTER; 388 case DBGFREGVALTYPE_U128: pValue->u128 = InVal.u128; return VINF_SUCCESS; 389 case DBGFREGVALTYPE_80: return VERR_DBGF_UNSUPPORTED_CAST; 390 case DBGFREGVALTYPE_LRD: pValue->lrd = InVal.u64; return VINF_DBGF_TRUNCATED_REGISTER; 391 case DBGFREGVALTYPE_DTR: return VERR_DBGF_UNSUPPORTED_CAST; 392 393 case DBGFREGVALTYPE_32BIT_HACK: 394 case DBGFREGVALTYPE_END: 395 case DBGFREGVALTYPE_INVALID: 396 break; 397 } 398 break; 399 400 case DBGFREGVALTYPE_80: 401 return VERR_DBGF_UNSUPPORTED_CAST; 402 403 case DBGFREGVALTYPE_LRD: 404 switch (enmToType) 405 { 406 case DBGFREGVALTYPE_U8: pValue->u8 = InVal.lrd; return VINF_DBGF_TRUNCATED_REGISTER; 407 case DBGFREGVALTYPE_U16: pValue->u16 = InVal.lrd; return VINF_DBGF_TRUNCATED_REGISTER; 408 case DBGFREGVALTYPE_U32: pValue->u32 = InVal.lrd; return VINF_DBGF_TRUNCATED_REGISTER; 409 case DBGFREGVALTYPE_U64: pValue->u64 = InVal.lrd; return VINF_DBGF_TRUNCATED_REGISTER; 410 case DBGFREGVALTYPE_U128: 411 pValue->u128.s.Lo = (uint64_t)InVal.lrd; 412 pValue->u128.s.Hi = InVal.lrd / _4G / _4G; 413 return VINF_DBGF_TRUNCATED_REGISTER; 414 case DBGFREGVALTYPE_80: return VERR_DBGF_UNSUPPORTED_CAST; 415 case DBGFREGVALTYPE_LRD: pValue->lrd = InVal.lrd; return VINF_SUCCESS; 416 case DBGFREGVALTYPE_DTR: return VERR_DBGF_UNSUPPORTED_CAST; 417 418 case DBGFREGVALTYPE_32BIT_HACK: 419 case DBGFREGVALTYPE_END: 420 case DBGFREGVALTYPE_INVALID: 421 break; 422 } 423 break; 424 425 case DBGFREGVALTYPE_DTR: 426 switch (enmToType) 427 { 428 case DBGFREGVALTYPE_U8: pValue->u8 = InVal.dtr.u64Base; return VINF_DBGF_TRUNCATED_REGISTER; 429 case DBGFREGVALTYPE_U16: pValue->u16 = InVal.dtr.u64Base; return VINF_DBGF_TRUNCATED_REGISTER; 430 case DBGFREGVALTYPE_U32: pValue->u32 = InVal.dtr.u64Base; return VINF_DBGF_TRUNCATED_REGISTER; 431 case DBGFREGVALTYPE_U64: pValue->u64 = InVal.dtr.u64Base; return VINF_DBGF_TRUNCATED_REGISTER; 432 case DBGFREGVALTYPE_U128: pValue->u128.s.Lo = InVal.dtr.u64Base; return VINF_DBGF_TRUNCATED_REGISTER; 433 case DBGFREGVALTYPE_80: return VERR_DBGF_UNSUPPORTED_CAST; 434 case DBGFREGVALTYPE_LRD: pValue->lrd = InVal.dtr.u64Base; return VINF_DBGF_TRUNCATED_REGISTER; 435 case DBGFREGVALTYPE_DTR: pValue->dtr = InVal.dtr; return VINF_SUCCESS; 436 437 case DBGFREGVALTYPE_32BIT_HACK: 438 case DBGFREGVALTYPE_END: 439 case DBGFREGVALTYPE_INVALID: 440 break; 441 } 442 break; 443 444 case DBGFREGVALTYPE_INVALID: 445 case DBGFREGVALTYPE_END: 446 case DBGFREGVALTYPE_32BIT_HACK: 447 break; 448 } 449 450 AssertMsgFailed(("%d / %d\n", enmFromType, enmToType)); 451 return VERR_DBGF_UNSUPPORTED_CAST; 452 } 453 454 455 /** 456 * Worker for the CPU register queries. 457 * 458 * @returns VBox status code. 459 * @retval VINF_SUCCESS 460 * @retval VERR_INVALID_VM_HANDLE 461 * @retval VERR_INVALID_CPU_ID 648 462 * @retval VERR_DBGF_INVALID_REGISTER 649 * 650 * @param pVCpu The current CPU. 651 * @param pu64 Where to store the register value. 652 * @param pfRegSizes Where to store the register sizes. 653 * @param idMsr The MSR to get. 654 */ 655 static uint64_t dbgfR3RegGetMsr(PVMCPU pVCpu, uint64_t *pu64, uint32_t *pfRegSizes, uint32_t idMsr) 656 { 657 *pfRegSizes = R_SZ_64; 658 int rc = CPUMQueryGuestMsr(pVCpu, idMsr, pu64); 659 if (RT_FAILURE(rc)) 463 * @retval VERR_DBGF_UNSUPPORTED_CAST 464 * @retval VINF_DBGF_TRUNCATED_REGISTER 465 * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER 466 * 467 * @param pVM The VM handle. 468 * @param idCpu The virtual CPU ID. 469 * @param enmReg The register to query. 470 * @param enmType The desired return type. 471 * @param puValue Where to return the register value. 472 */ 473 static DECLCALLBACK(int) dbgfR3RegCpuQueryWorker(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, DBGFREGVALTYPE enmType, PDBGFREGVAL puValue) 474 { 475 int rc = VINF_SUCCESS; 476 DBGF_REG_DB_LOCK_READ(pVM); 477 478 /* 479 * Look up the register set of the CPU. 480 */ 481 /** @todo optimize this by adding a cpu register set array to DBGF. */ 482 char szSetName[16]; 483 RTStrPrintf(szSetName, sizeof(szSetName), "cpu%u", idCpu); 484 PDBGFREGSET pSet = (PDBGFREGSET)RTStrSpaceGet(&pVM->dbgf.s.RegSetSpace, szSetName); 485 if (RT_LIKELY(pSet)) 660 486 { 661 AssertMsg(rc == VERR_CPUM_RAISE_GP_0, ("%Rrc\n", rc)); 662 *pu64 = 0; 487 /* 488 * Look up the register and get the register value. 489 */ 490 if (RT_LIKELY(pSet->cDescs > (size_t)enmReg)) 491 { 492 PCDBGFREGDESC pDesc = &pSet->paDescs[enmReg]; 493 494 puValue->au64[0] = puValue->au64[1] = 0; 495 rc = pDesc->pfnGet(pSet->uUserArg.pv, pDesc, puValue); 496 if (RT_SUCCESS(rc)) 497 { 498 /* 499 * Do the cast if the desired return type doesn't match what 500 * the getter returned. 501 */ 502 if (pDesc->enmType == enmType) 503 rc = VINF_SUCCESS; 504 else 505 rc = dbgfR3RegValCast(puValue, pDesc->enmType, enmType); 506 } 507 } 508 else 509 rc = VERR_DBGF_INVALID_REGISTER; 663 510 } 664 return VINF_SUCCESS; 665 } 666 667 /** 668 * Worker for DBGFR3RegQueryU8, DBGFR3RegQueryU16, DBGFR3RegQueryU32 and 669 * DBGFR3RegQueryU64. 511 else 512 rc = VERR_INVALID_CPU_ID; 513 514 DBGF_REG_DB_UNLOCK_READ(pVM); 515 return rc; 516 } 517 518 519 /** 520 * Queries a 8-bit CPU register value. 521 * 522 * @retval VINF_SUCCESS 523 * @retval VERR_INVALID_VM_HANDLE 524 * @retval VERR_INVALID_CPU_ID 525 * @retval VERR_DBGF_INVALID_REGISTER 526 * @retval VERR_DBGF_UNSUPPORTED_CAST 527 * @retval VINF_DBGF_TRUNCATED_REGISTER 528 * 529 * @param pVM The VM handle. 530 * @param idCpu The target CPU ID. 531 * @param enmReg The register that's being queried. 532 * @param pu8 Where to store the register value. 533 */ 534 VMMR3DECL(int) DBGFR3RegCpuQueryU8(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t *pu8) 535 { 536 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 537 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID); 538 539 DBGFREGVAL Value; 540 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegCpuQueryWorker, 5, pVM, idCpu, enmReg, DBGFREGVALTYPE_U8, &Value); 541 if (RT_SUCCESS(rc)) 542 *pu8 = Value.u8; 543 else 544 *pu8 = 0; 545 546 return rc; 547 } 548 549 550 /** 551 * Queries a 16-bit CPU register value. 552 * 553 * @retval VINF_SUCCESS 554 * @retval VERR_INVALID_VM_HANDLE 555 * @retval VERR_INVALID_CPU_ID 556 * @retval VERR_DBGF_INVALID_REGISTER 557 * @retval VERR_DBGF_UNSUPPORTED_CAST 558 * @retval VINF_DBGF_TRUNCATED_REGISTER 559 * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER 560 * 561 * @param pVM The VM handle. 562 * @param idCpu The target CPU ID. 563 * @param enmReg The register that's being queried. 564 * @param pu16 Where to store the register value. 565 */ 566 VMMR3DECL(int) DBGFR3RegCpuQueryU16(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t *pu16) 567 { 568 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 569 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID); 570 571 DBGFREGVAL Value; 572 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegCpuQueryWorker, 5, pVM, idCpu, enmReg, DBGFREGVALTYPE_U16, &Value); 573 if (RT_SUCCESS(rc)) 574 *pu16 = Value.u16; 575 else 576 *pu16 = 0; 577 578 return rc; 579 } 580 581 582 /** 583 * Queries a 32-bit CPU register value. 584 * 585 * @retval VINF_SUCCESS 586 * @retval VERR_INVALID_VM_HANDLE 587 * @retval VERR_INVALID_CPU_ID 588 * @retval VERR_DBGF_INVALID_REGISTER 589 * @retval VERR_DBGF_UNSUPPORTED_CAST 590 * @retval VINF_DBGF_TRUNCATED_REGISTER 591 * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER 592 * 593 * @param pVM The VM handle. 594 * @param idCpu The target CPU ID. 595 * @param enmReg The register that's being queried. 596 * @param pu32 Where to store the register value. 597 */ 598 VMMR3DECL(int) DBGFR3RegCpuQueryU32(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t *pu32) 599 { 600 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 601 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID); 602 603 DBGFREGVAL Value; 604 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegCpuQueryWorker, 5, pVM, idCpu, enmReg, DBGFREGVALTYPE_U32, &Value); 605 if (RT_SUCCESS(rc)) 606 *pu32 = Value.u32; 607 else 608 *pu32 = 0; 609 610 return rc; 611 } 612 613 614 /** 615 * Queries a 64-bit CPU register value. 616 * 617 * @retval VINF_SUCCESS 618 * @retval VERR_INVALID_VM_HANDLE 619 * @retval VERR_INVALID_CPU_ID 620 * @retval VERR_DBGF_INVALID_REGISTER 621 * @retval VERR_DBGF_UNSUPPORTED_CAST 622 * @retval VINF_DBGF_TRUNCATED_REGISTER 623 * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER 670 624 * 671 625 * @param pVM The VM handle. … … 673 627 * @param enmReg The register that's being queried. 674 628 * @param pu64 Where to store the register value. 675 * @param pfRegSizes Where to store the register sizes. 676 */ 677 static DECLCALLBACK(int) dbgfR3RegQueryWorker(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64, uint32_t *pfRegSizes) 678 { 679 /** @todo rewrite this to use the register descriptors. */ 680 PVMCPU pVCpu = &pVM->aCpus[idCpu]; 681 PCCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); 682 switch (enmReg) 683 { 684 case DBGFREG_RAX: *pu64 = pCtx->rax; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 685 case DBGFREG_RCX: *pu64 = pCtx->rcx; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 686 case DBGFREG_RDX: *pu64 = pCtx->rdx; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 687 case DBGFREG_RBX: *pu64 = pCtx->rbx; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 688 case DBGFREG_RSP: *pu64 = pCtx->rsp; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 689 case DBGFREG_RBP: *pu64 = pCtx->rbp; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 690 case DBGFREG_RSI: *pu64 = pCtx->rsi; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 691 case DBGFREG_RDI: *pu64 = pCtx->rdi; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 692 case DBGFREG_R8: *pu64 = pCtx->r8; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 693 case DBGFREG_R9: *pu64 = pCtx->r9; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 694 case DBGFREG_R10: *pu64 = pCtx->r10; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 695 case DBGFREG_R11: *pu64 = pCtx->r11; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 696 case DBGFREG_R12: *pu64 = pCtx->r12; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 697 case DBGFREG_R13: *pu64 = pCtx->r13; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 698 case DBGFREG_R14: *pu64 = pCtx->r14; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 699 case DBGFREG_R15: *pu64 = pCtx->r15; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; 700 701 case DBGFREG_CS: *pu64 = pCtx->cs; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; 702 case DBGFREG_DS: *pu64 = pCtx->ds; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; 703 case DBGFREG_ES: *pu64 = pCtx->es; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; 704 case DBGFREG_FS: *pu64 = pCtx->fs; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; 705 case DBGFREG_GS: *pu64 = pCtx->gs; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; 706 case DBGFREG_SS: *pu64 = pCtx->ss; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; 707 708 case DBGFREG_CS_ATTR: *pu64 = pCtx->csHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 709 case DBGFREG_DS_ATTR: *pu64 = pCtx->dsHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 710 case DBGFREG_ES_ATTR: *pu64 = pCtx->esHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 711 case DBGFREG_FS_ATTR: *pu64 = pCtx->fsHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 712 case DBGFREG_GS_ATTR: *pu64 = pCtx->gsHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 713 case DBGFREG_SS_ATTR: *pu64 = pCtx->ssHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 714 715 case DBGFREG_CS_BASE: *pu64 = pCtx->csHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; 716 case DBGFREG_DS_BASE: *pu64 = pCtx->dsHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; 717 case DBGFREG_ES_BASE: *pu64 = pCtx->esHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; 718 case DBGFREG_FS_BASE: *pu64 = pCtx->fsHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; 719 case DBGFREG_GS_BASE: *pu64 = pCtx->gsHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; 720 case DBGFREG_SS_BASE: *pu64 = pCtx->ssHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; 721 722 case DBGFREG_CS_LIMIT: *pu64 = pCtx->csHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 723 case DBGFREG_DS_LIMIT: *pu64 = pCtx->dsHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 724 case DBGFREG_ES_LIMIT: *pu64 = pCtx->esHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 725 case DBGFREG_FS_LIMIT: *pu64 = pCtx->fsHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 726 case DBGFREG_GS_LIMIT: *pu64 = pCtx->gsHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 727 case DBGFREG_SS_LIMIT: *pu64 = pCtx->ssHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 728 729 case DBGFREG_RIP: *pu64 = pCtx->rip; *pfRegSizes = R_SZ_16_TO_64; return VINF_SUCCESS; 730 case DBGFREG_FLAGS: *pu64 = pCtx->rflags.u; *pfRegSizes = R_SZ_16_TO_64; return VINF_SUCCESS; 731 732 /** @todo check fxsave/fsave format? */ 733 case DBGFREG_FCW: *pu64 = pCtx->fpu.FCW; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; 734 case DBGFREG_FSW: *pu64 = pCtx->fpu.FSW; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; 735 case DBGFREG_FTW: *pu64 = pCtx->fpu.FTW; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; 736 case DBGFREG_FOP: *pu64 = pCtx->fpu.FOP; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; 737 case DBGFREG_FPUIP: *pu64 = pCtx->fpu.FPUIP; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 738 case DBGFREG_FPUCS: *pu64 = pCtx->fpu.CS; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; 739 case DBGFREG_FPUDP: *pu64 = pCtx->fpu.FPUDP; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 740 case DBGFREG_FPUDS: *pu64 = pCtx->fpu.DS; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; 741 case DBGFREG_MXCSR: *pu64 = pCtx->fpu.MXCSR; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 742 case DBGFREG_MXCSR_MASK:*pu64 = pCtx->fpu.MXCSR_MASK; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 743 744 case DBGFREG_ST0: 745 case DBGFREG_ST1: 746 case DBGFREG_ST2: 747 case DBGFREG_ST3: 748 case DBGFREG_ST4: 749 case DBGFREG_ST5: 750 case DBGFREG_ST6: 751 case DBGFREG_ST7: 752 { 753 /** @todo check tags and fxsave/fsave format. */ 754 unsigned iReg = (pCtx->fpu.FSW >> 11) & 7; 755 iReg += enmReg - DBGFREG_ST0; 756 iReg &= 7; 757 758 *pu64 = pCtx->fpu.aRegs[iReg].au64[0]; 759 *pfRegSizes = R_SZ_80; 760 return VINF_SUCCESS; 761 } 762 763 case DBGFREG_MM0: 764 case DBGFREG_MM1: 765 case DBGFREG_MM2: 766 case DBGFREG_MM3: 767 case DBGFREG_MM4: 768 case DBGFREG_MM5: 769 case DBGFREG_MM6: 770 case DBGFREG_MM7: 771 *pu64 = pCtx->fpu.aRegs[enmReg - DBGFREG_MM0].mmx; 772 *pfRegSizes = R_SZ_64; 773 return VINF_SUCCESS; 774 775 case DBGFREG_XMM0: 776 case DBGFREG_XMM1: 777 case DBGFREG_XMM2: 778 case DBGFREG_XMM3: 779 case DBGFREG_XMM4: 780 case DBGFREG_XMM5: 781 case DBGFREG_XMM6: 782 case DBGFREG_XMM7: 783 case DBGFREG_XMM8: 784 case DBGFREG_XMM9: 785 case DBGFREG_XMM10: 786 case DBGFREG_XMM11: 787 case DBGFREG_XMM12: 788 case DBGFREG_XMM13: 789 case DBGFREG_XMM14: 790 case DBGFREG_XMM15: 791 *pu64 = pCtx->fpu.aRegs[enmReg - DBGFREG_XMM0].au64[0]; 792 *pfRegSizes = R_SZ_128; 793 return VINF_SUCCESS; 794 795 case DBGFREG_GDTR_BASE: *pu64 = pCtx->gdtr.pGdt; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; 796 case DBGFREG_GDTR_LIMIT: *pu64 = pCtx->gdtr.cbGdt; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 797 case DBGFREG_IDTR_BASE: *pu64 = pCtx->idtr.pIdt; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; 798 case DBGFREG_IDTR_LIMIT: *pu64 = pCtx->idtr.cbIdt; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 799 case DBGFREG_LDTR: *pu64 = pCtx->ldtr; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; 800 case DBGFREG_LDTR_ATTR: *pu64 = pCtx->ldtrHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 801 case DBGFREG_LDTR_BASE: *pu64 = pCtx->ldtrHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; 802 case DBGFREG_LDTR_LIMIT: *pu64 = pCtx->ldtrHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 803 case DBGFREG_TR: *pu64 = pCtx->tr; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; 804 case DBGFREG_TR_ATTR: *pu64 = pCtx->trHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 805 case DBGFREG_TR_BASE: *pu64 = pCtx->trHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; 806 case DBGFREG_TR_LIMIT: *pu64 = pCtx->trHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; 807 808 case DBGFREG_CR0: *pu64 = CPUMGetGuestCR0(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; 809 case DBGFREG_CR2: *pu64 = CPUMGetGuestCR2(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; 810 case DBGFREG_CR3: *pu64 = CPUMGetGuestCR3(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; 811 case DBGFREG_CR4: *pu64 = CPUMGetGuestCR4(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; 812 case DBGFREG_CR8: *pu64 = CPUMGetGuestCR8(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; 813 814 case DBGFREG_DR0: *pu64 = CPUMGetGuestDR0(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; 815 case DBGFREG_DR1: *pu64 = CPUMGetGuestDR1(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; 816 case DBGFREG_DR2: *pu64 = CPUMGetGuestDR2(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; 817 case DBGFREG_DR3: *pu64 = CPUMGetGuestDR3(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; 818 case DBGFREG_DR6: *pu64 = CPUMGetGuestDR6(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; 819 case DBGFREG_DR7: *pu64 = CPUMGetGuestDR7(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; 820 821 case DBGFREG_MSR_IA32_APICBASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_APICBASE); 822 case DBGFREG_MSR_IA32_CR_PAT: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_CR_PAT); 823 case DBGFREG_MSR_IA32_PERF_STATUS: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_PERF_STATUS); 824 case DBGFREG_MSR_IA32_SYSENTER_CS: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_CS); 825 case DBGFREG_MSR_IA32_SYSENTER_EIP: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_EIP); 826 case DBGFREG_MSR_IA32_SYSENTER_ESP: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_ESP); 827 case DBGFREG_MSR_IA32_TSC: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_TSC); 828 case DBGFREG_MSR_K6_EFER: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K6_EFER); 829 case DBGFREG_MSR_K6_STAR: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K6_STAR); 830 case DBGFREG_MSR_K8_CSTAR: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_CSTAR); 831 case DBGFREG_MSR_K8_FS_BASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_FS_BASE); 832 case DBGFREG_MSR_K8_GS_BASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_GS_BASE); 833 case DBGFREG_MSR_K8_KERNEL_GS_BASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_KERNEL_GS_BASE); 834 case DBGFREG_MSR_K8_LSTAR: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_LSTAR); 835 case DBGFREG_MSR_K8_SF_MASK: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_SF_MASK); 836 case DBGFREG_MSR_K8_TSC_AUX: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_TSC_AUX); 837 838 case DBGFREG_AH: *pu64 = RT_BYTE2(pCtx->ax); *pfRegSizes = R_SZ_8; return VINF_SUCCESS; 839 case DBGFREG_CH: *pu64 = RT_BYTE2(pCtx->cx); *pfRegSizes = R_SZ_8; return VINF_SUCCESS; 840 case DBGFREG_DH: *pu64 = RT_BYTE2(pCtx->dx); *pfRegSizes = R_SZ_8; return VINF_SUCCESS; 841 case DBGFREG_BH: *pu64 = RT_BYTE2(pCtx->bx); *pfRegSizes = R_SZ_8; return VINF_SUCCESS; 842 case DBGFREG_GDTR: *pu64 = pCtx->gdtr.pGdt; *pfRegSizes = R_SZ_64_16; return VINF_SUCCESS; 843 case DBGFREG_IDTR: *pu64 = pCtx->idtr.pIdt; *pfRegSizes = R_SZ_64_16; return VINF_SUCCESS; 844 845 case DBGFREG_END: 846 case DBGFREG_32BIT_HACK: 847 /* no default! We want GCC warnings. */ 848 break; 849 } 850 851 AssertMsgFailed(("%d (%#x)\n", enmReg, enmReg)); 852 return VERR_DBGF_INVALID_REGISTER; 853 } 854 855 856 /** 857 * Queries a 8-bit register value. 858 * 859 * @retval VINF_SUCCESS 860 * @retval VERR_INVALID_VM_HANDLE 861 * @retval VERR_INVALID_CPU_ID 862 * @retval VERR_DBGF_INVALID_REGISTER 863 * @retval VINF_DBGF_TRUNCATED_REGISTER 864 * 865 * @param pVM The VM handle. 866 * @param idCpu The target CPU ID. 867 * @param enmReg The register that's being queried. 868 * @param pu8 Where to store the register value. 869 */ 870 VMMR3DECL(int) DBGFR3RegQueryU8(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t *pu8) 629 */ 630 VMMR3DECL(int) DBGFR3RegCpuQueryU64(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64) 871 631 { 872 632 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 873 633 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID); 874 634 875 uint64_t u64Value; 876 uint32_t fRegSizes; 877 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes); 635 DBGFREGVAL Value; 636 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegCpuQueryWorker, 5, pVM, idCpu, enmReg, DBGFREGVALTYPE_U64, &Value); 878 637 if (RT_SUCCESS(rc)) 879 { 880 *pu8 = (uint8_t)u64Value; 881 if (R_SZ_8 & fRegSizes) 882 rc = VINF_SUCCESS; 883 else 884 rc = VINF_DBGF_TRUNCATED_REGISTER; 885 } 886 else 887 *pu8 = 0; 888 return rc; 889 } 890 891 892 /** 893 * Queries a 16-bit register value. 894 * 895 * @retval VINF_SUCCESS 896 * @retval VERR_INVALID_VM_HANDLE 897 * @retval VERR_INVALID_CPU_ID 898 * @retval VERR_DBGF_INVALID_REGISTER 899 * @retval VINF_DBGF_TRUNCATED_REGISTER 900 * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER 901 * 902 * @param pVM The VM handle. 903 * @param idCpu The target CPU ID. 904 * @param enmReg The register that's being queried. 905 * @param pu16 Where to store the register value. 906 */ 907 VMMR3DECL(int) DBGFR3RegQueryU16(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t *pu16) 908 { 909 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 910 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID); 911 912 uint64_t u64Value; 913 uint32_t fRegSizes; 914 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes); 915 if (RT_SUCCESS(rc)) 916 { 917 *pu16 = (uint16_t)u64Value; 918 if (R_SZ_16 & fRegSizes) 919 rc = VINF_SUCCESS; 920 else if (~(R_SZ_8 | R_SZ_16) & fRegSizes) 921 rc = VINF_DBGF_TRUNCATED_REGISTER; 922 else 923 rc = VINF_DBGF_ZERO_EXTENDED_REGISTER; 924 } 925 else 926 *pu16 = 0; 927 return rc; 928 } 929 930 931 /** 932 * Queries a 32-bit register value. 933 * 934 * @retval VINF_SUCCESS 935 * @retval VERR_INVALID_VM_HANDLE 936 * @retval VERR_INVALID_CPU_ID 937 * @retval VERR_DBGF_INVALID_REGISTER 938 * @retval VINF_DBGF_TRUNCATED_REGISTER 939 * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER 940 * 941 * @param pVM The VM handle. 942 * @param idCpu The target CPU ID. 943 * @param enmReg The register that's being queried. 944 * @param pu32 Where to store the register value. 945 */ 946 VMMR3DECL(int) DBGFR3RegQueryU32(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t *pu32) 947 { 948 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 949 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID); 950 951 uint64_t u64Value; 952 uint32_t fRegSizes; 953 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes); 954 if (RT_SUCCESS(rc)) 955 { 956 *pu32 = (uint32_t)u64Value; 957 if (R_SZ_32 & fRegSizes) 958 rc = VINF_SUCCESS; 959 else if (~(R_SZ_8 | R_SZ_16 | R_SZ_32) & fRegSizes) 960 rc = VINF_DBGF_TRUNCATED_REGISTER; 961 else 962 rc = VINF_DBGF_ZERO_EXTENDED_REGISTER; 963 } 964 else 965 *pu32 = 0; 966 return rc; 967 } 968 969 970 /** 971 * Queries a 64-bit register value. 972 * 973 * @retval VINF_SUCCESS 974 * @retval VERR_INVALID_VM_HANDLE 975 * @retval VERR_INVALID_CPU_ID 976 * @retval VERR_DBGF_INVALID_REGISTER 977 * @retval VINF_DBGF_TRUNCATED_REGISTER 978 * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER 979 * 980 * @param pVM The VM handle. 981 * @param idCpu The target CPU ID. 982 * @param enmReg The register that's being queried. 983 * @param pu64 Where to store the register value. 984 */ 985 VMMR3DECL(int) DBGFR3RegQueryU64(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64) 986 { 987 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 988 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID); 989 990 uint64_t u64Value; 991 uint32_t fRegSizes; 992 int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes); 993 if (RT_SUCCESS(rc)) 994 { 995 *pu64 = u64Value; 996 if (R_SZ_64 & fRegSizes) 997 rc = VINF_SUCCESS; 998 else if (~(R_SZ_8 | R_SZ_16 | R_SZ_32 | R_SZ_64) & fRegSizes) 999 rc = VINF_DBGF_TRUNCATED_REGISTER; 1000 else 1001 rc = VINF_DBGF_ZERO_EXTENDED_REGISTER; 1002 } 638 *pu64 = Value.u64; 1003 639 else 1004 640 *pu64 = 0; 641 1005 642 return rc; 1006 643 } … … 1008 645 1009 646 /** 1010 * Wrapper around CPUMQueryGuestMsr for dbgfR3Reg QueryBatchWorker.647 * Wrapper around CPUMQueryGuestMsr for dbgfR3RegCpuQueryBatchWorker. 1011 648 * 1012 649 * @retval VINF_SUCCESS … … 1030 667 1031 668 1032 static DECLCALLBACK(int) dbgfR3RegQueryBatchWorker(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs) 1033 { 669 static DECLCALLBACK(int) dbgfR3RegCpuQueryBatchWorker(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs) 670 { 671 #if 0 1034 672 PVMCPU pVCpu = &pVM->aCpus[idCpu]; 1035 673 PCCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); … … 1077 715 } 1078 716 } 1079 1080 717 return VINF_SUCCESS; 718 #else 719 return VERR_NOT_IMPLEMENTED; 720 #endif 1081 721 } 1082 722 … … 1099 739 * @param cRegs The number of entries in @a paRegs. 1100 740 */ 1101 VMMR3DECL(int) DBGFR3Reg QueryBatch(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)741 VMMR3DECL(int) DBGFR3RegCpuQueryBatch(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs) 1102 742 { 1103 743 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); … … 1114 754 } 1115 755 1116 return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3Reg QueryBatchWorker, 4, pVM, idCpu, paRegs, cRegs);756 return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegCpuQueryBatchWorker, 4, pVM, idCpu, paRegs, cRegs); 1117 757 } 1118 758 … … 1135 775 * recommended value is DBGFREG_ALL_COUNT. 1136 776 */ 1137 VMMR3DECL(int) DBGFR3Reg QueryAll(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs)777 VMMR3DECL(int) DBGFR3RegCpuQueryAll(PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs) 1138 778 { 1139 779 /* … … 1159 799 paRegs[iReg++].enmReg = DBGFREG_END; 1160 800 1161 return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3Reg QueryBatchWorker, 4, pVM, idCpu, paRegs, cRegs);801 return VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegCpuQueryBatchWorker, 4, pVM, idCpu, paRegs, cRegs); 1162 802 } 1163 803 … … 1174 814 * the standard name. 1175 815 */ 1176 VMMR3DECL(const char *) DBGFR3Reg Name(DBGFREG enmReg, DBGFREGVALTYPE enmType)816 VMMR3DECL(const char *) DBGFR3RegCpuName(DBGFREG enmReg, DBGFREGVALTYPE enmType) 1177 817 { 1178 818 AssertReturn(enmReg >= DBGFREG_AL && enmReg < DBGFREG_END, NULL); 1179 819 AssertReturn(enmType >= DBGFREGVALTYPE_INVALID && enmType < DBGFREGVALTYPE_END, NULL); 1180 820 821 #if 0 /** @todo need the optimization */ 1181 822 PCDBGFREGDESC pDesc = &g_aDbgfRegDescs[enmReg]; 1182 823 PCDBGFREGALIAS pAlias = pDesc->paAliases; … … 1194 835 1195 836 return pDesc->pszName; 1196 } 1197 837 #else 838 return NULL; 839 #endif 840 } 841 842 /** @todo Implementing missing APIs. */ -
trunk/src/VBox/VMM/VMMR3/VBoxVMMDeps.cpp
r35346 r35410 45 45 (PFNRT)DBGFR3CoreWrite, 46 46 (PFNRT)DBGFR3MemScan, 47 (PFNRT)DBGFR3Reg QueryU8,47 (PFNRT)DBGFR3RegCpuQueryU8, 48 48 (PFNRT)EMInterpretInstruction, 49 49 (PFNRT)IOMIOPortRead,
Note:
See TracChangeset
for help on using the changeset viewer.