/* $Id: DBGFReg.cpp 31491 2010-08-09 16:13:37Z vboxsync $ */ /** @file * DBGF - Debugger Facility, Register Methods. */ /* * Copyright (C) 2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ /******************************************************************************* * Header Files * *******************************************************************************/ #define LOG_GROUP LOG_GROUP_DBGF #include #include "DBGFInternal.h" #include #include #include #include /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ /** @name Register and value sizes used by dbgfR3RegQueryWorker and * dbgfR3RegSetWorker. * @{ */ #define R_SZ_8 RT_BIT(0) #define R_SZ_16 RT_BIT(1) #define R_SZ_32 RT_BIT(2) #define R_SZ_64 RT_BIT(3) #define R_SZ_64_16 RT_BIT(4) #define R_SZ_8_TO_64 (R_SZ_8 | R_SZ_16 | R_SZ_32 | R_SZ_64) #define R_SZ_16_TO_64 (R_SZ_16 | R_SZ_32 | R_SZ_64) #define R_SZ_32_OR_64 (R_SZ_32 | R_SZ_64) /** @} */ /** * Wrapper around CPUMQueryGuestMsr. * * @retval VINF_SUCCESS * @retval VERR_DBGF_INVALID_REGISTER * * @param pVCpu The current CPU. * @param pu64 Where to store the register value. * @param pfRegSizes Where to store the register sizes. * @param idMsr The MSR to get. */ static uint64_t dbgfR3RegGetMsr(PVMCPU pVCpu, uint64_t *pu64, uint32_t *pfRegSizes, uint32_t idMsr) { *pfRegSizes = R_SZ_64; int rc = CPUMQueryGuestMsr(pVCpu, idMsr, pu64); if (RT_FAILURE(rc)) { AssertMsg(rc == VERR_CPUM_RAISE_GP_0, ("%Rrc\n", rc)); *pu64 = 0; } return VINF_SUCCESS; } /** * Worker for DBGFR3RegQueryU8, DBGFR3RegQueryU16, DBGFR3RegQueryU32 and * DBGFR3RegQueryU64. * * @param pVM The VM handle. * @param idCpu The target CPU ID. * @param enmReg The register that's being queried. * @param pu64 Where to store the register value. * @param pfRegSizes Where to store the register sizes. */ static DECLCALLBACK(int) dbgfR3RegQueryWorker(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64, uint32_t *pfRegSizes) { PVMCPU pVCpu = &pVM->aCpus[idCpu]; PCCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); switch (enmReg) { case DBGFREG_RAX: *pu64 = pCtx->rax; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_RCX: *pu64 = pCtx->rcx; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_RDX: *pu64 = pCtx->rdx; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_RBX: *pu64 = pCtx->rbx; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_RSP: *pu64 = pCtx->rsp; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_RBP: *pu64 = pCtx->rbp; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_RSI: *pu64 = pCtx->rsi; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_RDI: *pu64 = pCtx->rdi; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_R8: *pu64 = pCtx->r8; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_R9: *pu64 = pCtx->r9; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_R10: *pu64 = pCtx->r10; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_R11: *pu64 = pCtx->r11; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_R12: *pu64 = pCtx->r12; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_R13: *pu64 = pCtx->r13; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_R14: *pu64 = pCtx->r14; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_R15: *pu64 = pCtx->r15; *pfRegSizes = R_SZ_8_TO_64; return VINF_SUCCESS; case DBGFREG_AH: *pu64 = RT_BYTE2(pCtx->ax); *pfRegSizes = R_SZ_8; return VINF_SUCCESS; case DBGFREG_CH: *pu64 = RT_BYTE2(pCtx->cx); *pfRegSizes = R_SZ_8; return VINF_SUCCESS; case DBGFREG_DH: *pu64 = RT_BYTE2(pCtx->dx); *pfRegSizes = R_SZ_8; return VINF_SUCCESS; case DBGFREG_BH: *pu64 = RT_BYTE2(pCtx->bx); *pfRegSizes = R_SZ_8; return VINF_SUCCESS; case DBGFREG_CS: *pu64 = pCtx->cs; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; case DBGFREG_DS: *pu64 = pCtx->ds; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; case DBGFREG_ES: *pu64 = pCtx->es; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; case DBGFREG_FS: *pu64 = pCtx->fs; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; case DBGFREG_GS: *pu64 = pCtx->gs; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; case DBGFREG_SS: *pu64 = pCtx->ss; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; case DBGFREG_CS_ATTR: *pu64 = pCtx->csHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_DS_ATTR: *pu64 = pCtx->dsHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_ES_ATTR: *pu64 = pCtx->esHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_FS_ATTR: *pu64 = pCtx->fsHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_GS_ATTR: *pu64 = pCtx->gsHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_SS_ATTR: *pu64 = pCtx->ssHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_CS_BASE: *pu64 = pCtx->csHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; case DBGFREG_DS_BASE: *pu64 = pCtx->dsHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; case DBGFREG_ES_BASE: *pu64 = pCtx->esHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; case DBGFREG_FS_BASE: *pu64 = pCtx->fsHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; case DBGFREG_GS_BASE: *pu64 = pCtx->gsHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; case DBGFREG_SS_BASE: *pu64 = pCtx->ssHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; case DBGFREG_CS_LIMIT: *pu64 = pCtx->csHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_DS_LIMIT: *pu64 = pCtx->dsHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_ES_LIMIT: *pu64 = pCtx->esHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_FS_LIMIT: *pu64 = pCtx->fsHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_GS_LIMIT: *pu64 = pCtx->gsHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_SS_LIMIT: *pu64 = pCtx->ssHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_RIP: *pu64 = pCtx->rip; *pfRegSizes = R_SZ_16_TO_64; return VINF_SUCCESS; case DBGFREG_FLAGS: *pu64 = pCtx->rflags.u; *pfRegSizes = R_SZ_16_TO_64; return VINF_SUCCESS; case DBGFREG_ST0: return VERR_NOT_IMPLEMENTED; case DBGFREG_ST1: return VERR_NOT_IMPLEMENTED; case DBGFREG_ST2: return VERR_NOT_IMPLEMENTED; case DBGFREG_ST3: return VERR_NOT_IMPLEMENTED; case DBGFREG_ST4: return VERR_NOT_IMPLEMENTED; case DBGFREG_ST5: return VERR_NOT_IMPLEMENTED; case DBGFREG_ST6: return VERR_NOT_IMPLEMENTED; case DBGFREG_ST7: return VERR_NOT_IMPLEMENTED; case DBGFREG_MM0: return VERR_NOT_IMPLEMENTED; case DBGFREG_MM1: return VERR_NOT_IMPLEMENTED; case DBGFREG_MM2: return VERR_NOT_IMPLEMENTED; case DBGFREG_MM3: return VERR_NOT_IMPLEMENTED; case DBGFREG_MM4: return VERR_NOT_IMPLEMENTED; case DBGFREG_MM5: return VERR_NOT_IMPLEMENTED; case DBGFREG_MM6: return VERR_NOT_IMPLEMENTED; case DBGFREG_MM7: return VERR_NOT_IMPLEMENTED; case DBGFREG_FCW: return VERR_NOT_IMPLEMENTED; case DBGFREG_FSW: return VERR_NOT_IMPLEMENTED; case DBGFREG_FTW: return VERR_NOT_IMPLEMENTED; case DBGFREG_FOP: return VERR_NOT_IMPLEMENTED; case DBGFREG_FPUIP: return VERR_NOT_IMPLEMENTED; case DBGFREG_FPUCS: return VERR_NOT_IMPLEMENTED; case DBGFREG_FPUDP: return VERR_NOT_IMPLEMENTED; case DBGFREG_FPUDS: return VERR_NOT_IMPLEMENTED; case DBGFREG_MXCSR: return VERR_NOT_IMPLEMENTED; case DBGFREG_MXCSR_MASK: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM0: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM1: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM2: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM3: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM4: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM5: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM6: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM7: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM8: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM9: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM10: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM11: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM12: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM13: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM14: return VERR_NOT_IMPLEMENTED; case DBGFREG_XMM15: return VERR_NOT_IMPLEMENTED; case DBGFREG_GDTR: *pu64 = pCtx->gdtr.pGdt; *pfRegSizes = R_SZ_64_16; return VINF_SUCCESS; case DBGFREG_GDTR_BASE: *pu64 = pCtx->gdtr.pGdt; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; case DBGFREG_GDTR_LIMIT: *pu64 = pCtx->gdtr.cbGdt; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_IDTR: *pu64 = pCtx->idtr.pIdt; *pfRegSizes = R_SZ_64_16; return VINF_SUCCESS; case DBGFREG_IDTR_BASE: *pu64 = pCtx->idtr.pIdt; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; case DBGFREG_IDTR_LIMIT: *pu64 = pCtx->idtr.cbIdt; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_LDTR: *pu64 = pCtx->ldtr; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; case DBGFREG_LDTR_ATTR: *pu64 = pCtx->ldtrHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_LDTR_BASE: *pu64 = pCtx->ldtrHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; case DBGFREG_LDTR_LIMIT: *pu64 = pCtx->ldtrHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_TR: *pu64 = pCtx->tr; *pfRegSizes = R_SZ_16; return VINF_SUCCESS; case DBGFREG_TR_ATTR: *pu64 = pCtx->trHid.Attr.u; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_TR_BASE: *pu64 = pCtx->trHid.u64Base; *pfRegSizes = R_SZ_64; return VINF_SUCCESS; case DBGFREG_TR_LIMIT: *pu64 = pCtx->trHid.u32Limit; *pfRegSizes = R_SZ_32; return VINF_SUCCESS; case DBGFREG_CR0: *pu64 = CPUMGetGuestCR0(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; case DBGFREG_CR2: *pu64 = CPUMGetGuestCR2(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; case DBGFREG_CR3: *pu64 = CPUMGetGuestCR3(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; case DBGFREG_CR4: *pu64 = CPUMGetGuestCR4(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; case DBGFREG_CR8: *pu64 = CPUMGetGuestCR8(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; case DBGFREG_DR0: *pu64 = CPUMGetGuestDR0(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; case DBGFREG_DR1: *pu64 = CPUMGetGuestDR1(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; case DBGFREG_DR2: *pu64 = CPUMGetGuestDR2(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; case DBGFREG_DR3: *pu64 = CPUMGetGuestDR3(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; case DBGFREG_DR6: *pu64 = CPUMGetGuestDR6(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; case DBGFREG_DR7: *pu64 = CPUMGetGuestDR7(pVCpu); *pfRegSizes = R_SZ_32_OR_64; return VINF_SUCCESS; case DBGFREG_MSR_IA32_APICBASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_APICBASE); case DBGFREG_MSR_IA32_CR_PAT: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_CR_PAT); case DBGFREG_MSR_IA32_PERF_STATUS: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_PERF_STATUS); case DBGFREG_MSR_IA32_SYSENTER_CS: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_CS); case DBGFREG_MSR_IA32_SYSENTER_EIP: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_EIP); case DBGFREG_MSR_IA32_SYSENTER_ESP: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_SYSENTER_ESP); case DBGFREG_MSR_IA32_TSC: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_IA32_TSC); case DBGFREG_MSR_K6_EFER: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K6_EFER); case DBGFREG_MSR_K6_STAR: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K6_STAR); case DBGFREG_MSR_K8_CSTAR: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_CSTAR); case DBGFREG_MSR_K8_FS_BASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_FS_BASE); case DBGFREG_MSR_K8_GS_BASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_GS_BASE); case DBGFREG_MSR_K8_KERNEL_GS_BASE: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_KERNEL_GS_BASE); case DBGFREG_MSR_K8_LSTAR: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_LSTAR); case DBGFREG_MSR_K8_SF_MASK: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_SF_MASK); case DBGFREG_MSR_K8_TSC_AUX: return dbgfR3RegGetMsr(pVCpu, pu64, pfRegSizes, MSR_K8_TSC_AUX); case DBGFREG_END: case DBGFREG_32BIT_HACK: /* no default! We want GCC warnings. */ break; } AssertMsgFailed(("%d (%#x)\n", enmReg, enmReg)); return VERR_DBGF_INVALID_REGISTER; } /** * Queries a 8-bit register value. * * @retval VINF_SUCCESS * @retval VERR_INVALID_VM_HANDLE * @retval VERR_INVALID_CPU_ID * @retval VERR_DBGF_INVALID_REGISTER * @retval VINF_DBGF_TRUNCATED_REGISTER * * @param pVM The VM handle. * @param idCpu The target CPU ID. * @param enmReg The register that's being queried. * @param pu8 Where to store the register value. */ VMMR3DECL(int) DBGFR3RegQueryU8(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t *pu8) { VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID); uint64_t u64Value; uint32_t fRegSizes; int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes); if (RT_SUCCESS(rc)) { *pu8 = (uint8_t)u64Value; if (R_SZ_8 & fRegSizes) rc = VINF_SUCCESS; else rc = VINF_DBGF_TRUNCATED_REGISTER; } else *pu8 = 0; return rc; } /** * Queries a 16-bit register value. * * @retval VINF_SUCCESS * @retval VERR_INVALID_VM_HANDLE * @retval VERR_INVALID_CPU_ID * @retval VERR_DBGF_INVALID_REGISTER * @retval VINF_DBGF_TRUNCATED_REGISTER * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER * * @param pVM The VM handle. * @param idCpu The target CPU ID. * @param enmReg The register that's being queried. * @param pu16 Where to store the register value. */ VMMR3DECL(int) DBGFR3RegQueryU16(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t *pu16) { VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID); uint64_t u64Value; uint32_t fRegSizes; int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes); if (RT_SUCCESS(rc)) { *pu16 = (uint16_t)u64Value; if (R_SZ_16 & fRegSizes) rc = VINF_SUCCESS; else if (~(R_SZ_8 | R_SZ_16) & fRegSizes) rc = VINF_DBGF_TRUNCATED_REGISTER; else rc = VINF_DBGF_ZERO_EXTENDED_REGISTER; } else *pu16 = 0; return rc; } /** * Queries a 32-bit register value. * * @retval VINF_SUCCESS * @retval VERR_INVALID_VM_HANDLE * @retval VERR_INVALID_CPU_ID * @retval VERR_DBGF_INVALID_REGISTER * @retval VINF_DBGF_TRUNCATED_REGISTER * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER * * @param pVM The VM handle. * @param idCpu The target CPU ID. * @param enmReg The register that's being queried. * @param pu32 Where to store the register value. */ VMMR3DECL(int) DBGFR3RegQueryU32(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t *pu32) { VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID); uint64_t u64Value; uint32_t fRegSizes; int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes); if (RT_SUCCESS(rc)) { *pu32 = (uint32_t)u64Value; if (R_SZ_32 & fRegSizes) rc = VINF_SUCCESS; else if (~(R_SZ_8 | R_SZ_16 | R_SZ_32) & fRegSizes) rc = VINF_DBGF_TRUNCATED_REGISTER; else rc = VINF_DBGF_ZERO_EXTENDED_REGISTER; } else *pu32 = 0; return rc; } /** * Queries a 64-bit register value. * * @retval VINF_SUCCESS * @retval VERR_INVALID_VM_HANDLE * @retval VERR_INVALID_CPU_ID * @retval VERR_DBGF_INVALID_REGISTER * @retval VINF_DBGF_TRUNCATED_REGISTER * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER * * @param pVM The VM handle. * @param idCpu The target CPU ID. * @param enmReg The register that's being queried. * @param pu64 Where to store the register value. */ VMMR3DECL(int) DBGFR3RegQueryU64(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64) { VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID); uint64_t u64Value; uint32_t fRegSizes; int rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3RegQueryWorker, 5, pVM, idCpu, enmReg, &u64Value, &fRegSizes); if (RT_SUCCESS(rc)) { *pu64 = u64Value; if (R_SZ_64 & fRegSizes) rc = VINF_SUCCESS; else if (~(R_SZ_8 | R_SZ_16 | R_SZ_32 | R_SZ_64) & fRegSizes) rc = VINF_DBGF_TRUNCATED_REGISTER; else rc = VINF_DBGF_ZERO_EXTENDED_REGISTER; } else *pu64 = 0; return rc; }