/** * Writes guest memory. * * @returns VBox status code. * * @param pVM Pointer to the shared VM structure. * @param idCpu The ID of the target CPU context (for the address). * @param pAddress Where to start writing. * @param pvBuf The data to write. * @param cbWrite The number of bytes to write. */ static DECLCALLBACK(int) dbgfR3MemWrite(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void const *pvBuf, size_t cbWrite) { /* * Validate the input we use, PGM does the rest. */ if (!DBGFR3AddrIsValid(pVM, pAddress)) return VERR_INVALID_POINTER; if (!VALID_PTR(pvBuf)) return VERR_INVALID_POINTER; /* * HMA is always special. */ int rc; if (DBGFADDRESS_IS_HMA(pAddress)) { /** @todo write to HMA. */ rc = VERR_ACCESS_DENIED; } else { /* * Select PGM function by addressing mode. */ PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu); PGMMODE enmMode = PGMGetGuestMode(pVCpu); if ( enmMode == PGMMODE_REAL || enmMode == PGMMODE_PROTECTED || DBGFADDRESS_IS_PHYS(pAddress) ) rc = PGMPhysSimpleWriteGCPhys(pVM, pAddress->FlatPtr, pvBuf, cbWrite); else { #if GC_ARCH_BITS > 32 if ( ( pAddress->FlatPtr >= _4G || pAddress->FlatPtr + cbWrite > _4G) && enmMode != PGMMODE_AMD64 && enmMode != PGMMODE_AMD64_NX) return VERR_PAGE_TABLE_NOT_PRESENT; #endif rc = PGMPhysSimpleWriteGCPtr(pVCpu, pAddress->FlatPtr, pvBuf, cbWrite); } } return rc; }
/** * Walks the entire stack allocating memory as we walk. */ static DECLCALLBACK(int) dbgfR3StackWalkCtxFull(PUVM pUVM, VMCPUID idCpu, PCCPUMCTXCORE pCtxCore, RTDBGAS hAs, DBGFCODETYPE enmCodeType, PCDBGFADDRESS pAddrFrame, PCDBGFADDRESS pAddrStack, PCDBGFADDRESS pAddrPC, DBGFRETURNTYPE enmReturnType, PCDBGFSTACKFRAME *ppFirstFrame) { /* alloc first frame. */ PDBGFSTACKFRAME pCur = (PDBGFSTACKFRAME)MMR3HeapAllocZU(pUVM, MM_TAG_DBGF_STACK, sizeof(*pCur)); if (!pCur) return VERR_NO_MEMORY; /* * Initialize the frame. */ pCur->pNextInternal = NULL; pCur->pFirstInternal = pCur; int rc = VINF_SUCCESS; if (pAddrPC) pCur->AddrPC = *pAddrPC; else if (enmCodeType != DBGFCODETYPE_GUEST) DBGFR3AddrFromFlat(pUVM, &pCur->AddrPC, pCtxCore->rip); else rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrPC, pCtxCore->cs.Sel, pCtxCore->rip); if (RT_SUCCESS(rc)) { if (enmReturnType == DBGFRETURNTYPE_INVALID) switch (pCur->AddrPC.fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) { case DBGFADDRESS_FLAGS_FAR16: pCur->enmReturnType = DBGFRETURNTYPE_NEAR16; break; case DBGFADDRESS_FLAGS_FAR32: pCur->enmReturnType = DBGFRETURNTYPE_NEAR32; break; case DBGFADDRESS_FLAGS_FAR64: pCur->enmReturnType = DBGFRETURNTYPE_NEAR64; break; case DBGFADDRESS_FLAGS_RING0: pCur->enmReturnType = HC_ARCH_BITS == 64 ? DBGFRETURNTYPE_NEAR64 : DBGFRETURNTYPE_NEAR32; break; default: pCur->enmReturnType = DBGFRETURNTYPE_NEAR32; break; /// @todo 64-bit guests } uint64_t fAddrMask; if (enmCodeType == DBGFCODETYPE_RING0) fAddrMask = HC_ARCH_BITS == 64 ? UINT64_MAX : UINT32_MAX; else if (enmCodeType == DBGFCODETYPE_HYPER) fAddrMask = UINT32_MAX; else if (DBGFADDRESS_IS_FAR16(&pCur->AddrPC)) fAddrMask = UINT16_MAX; else if (DBGFADDRESS_IS_FAR32(&pCur->AddrPC)) fAddrMask = UINT32_MAX; else if (DBGFADDRESS_IS_FAR64(&pCur->AddrPC)) fAddrMask = UINT64_MAX; else { PVMCPU pVCpu = VMMGetCpuById(pUVM->pVM, idCpu); CPUMMODE CpuMode = CPUMGetGuestMode(pVCpu); if (CpuMode == CPUMMODE_REAL) fAddrMask = UINT16_MAX; else if ( CpuMode == CPUMMODE_PROTECTED || !CPUMIsGuestIn64BitCode(pVCpu)) fAddrMask = UINT32_MAX; else fAddrMask = UINT64_MAX; } if (pAddrStack) pCur->AddrStack = *pAddrStack; else if (enmCodeType != DBGFCODETYPE_GUEST) DBGFR3AddrFromFlat(pUVM, &pCur->AddrStack, pCtxCore->rsp & fAddrMask); else rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrStack, pCtxCore->ss.Sel, pCtxCore->rsp & fAddrMask); if (pAddrFrame) pCur->AddrFrame = *pAddrFrame; else if (enmCodeType != DBGFCODETYPE_GUEST) DBGFR3AddrFromFlat(pUVM, &pCur->AddrFrame, pCtxCore->rbp & fAddrMask); else if (RT_SUCCESS(rc)) rc = DBGFR3AddrFromSelOff(pUVM, idCpu, &pCur->AddrFrame, pCtxCore->ss.Sel, pCtxCore->rbp & fAddrMask); } else pCur->enmReturnType = enmReturnType; /* * The first frame. */ if (RT_SUCCESS(rc)) rc = dbgfR3StackWalk(pUVM, idCpu, hAs, pCur); if (RT_FAILURE(rc)) { DBGFR3StackWalkEnd(pCur); return rc; } /* * The other frames. */ DBGFSTACKFRAME Next = *pCur; while (!(pCur->fFlags & (DBGFSTACKFRAME_FLAGS_LAST | DBGFSTACKFRAME_FLAGS_MAX_DEPTH | DBGFSTACKFRAME_FLAGS_LOOP))) { /* try walk. */ rc = dbgfR3StackWalk(pUVM, idCpu, hAs, &Next); if (RT_FAILURE(rc)) break; /* add the next frame to the chain. */ PDBGFSTACKFRAME pNext = (PDBGFSTACKFRAME)MMR3HeapAllocU(pUVM, MM_TAG_DBGF_STACK, sizeof(*pNext)); if (!pNext) { DBGFR3StackWalkEnd(pCur); return VERR_NO_MEMORY; } *pNext = Next; pCur->pNextInternal = pNext; pCur = pNext; Assert(pCur->pNextInternal == NULL); /* check for loop */ for (PCDBGFSTACKFRAME pLoop = pCur->pFirstInternal; pLoop && pLoop != pCur; pLoop = pLoop->pNextInternal) if (pLoop->AddrFrame.FlatPtr == pCur->AddrFrame.FlatPtr) { pCur->fFlags |= DBGFSTACKFRAME_FLAGS_LOOP; break; } /* check for insane recursion */ if (pCur->iFrame >= 2048) pCur->fFlags |= DBGFSTACKFRAME_FLAGS_MAX_DEPTH; } *ppFirstFrame = pCur->pFirstInternal; return rc; }