/** * Scan guest memory for an exact byte string. * * @returns VBox status code. * @param pUVM The user mode VM handle. * @param idCpu The ID of the CPU context to search in. * @param pAddress Where to store the mixed address. * @param puAlign The alignment restriction imposed on the search result. * @param pcbRange The number of bytes to scan. Passed as a pointer because * it may be 64-bit. * @param pabNeedle What to search for - exact search. * @param cbNeedle Size of the search byte string. * @param pHitAddress Where to put the address of the first hit. */ static DECLCALLBACK(int) dbgfR3MemScan(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, PCRTGCUINTPTR pcbRange, RTGCUINTPTR *puAlign, const uint8_t *pabNeedle, size_t cbNeedle, PDBGFADDRESS pHitAddress) { PVM pVM = pUVM->pVM; VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); Assert(idCpu == VMMGetCpuId(pVM)); /* * Validate the input we use, PGM does the rest. */ RTGCUINTPTR cbRange = *pcbRange; if (!DBGFR3AddrIsValid(pUVM, pAddress)) return VERR_INVALID_POINTER; if (!VALID_PTR(pHitAddress)) return VERR_INVALID_POINTER; if (DBGFADDRESS_IS_HMA(pAddress)) return VERR_INVALID_POINTER; /* * Select DBGF worker by addressing mode. */ int rc; PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu); PGMMODE enmMode = PGMGetGuestMode(pVCpu); if ( enmMode == PGMMODE_REAL || enmMode == PGMMODE_PROTECTED || DBGFADDRESS_IS_PHYS(pAddress) ) { RTGCPHYS GCPhysAlign = *puAlign; if (GCPhysAlign != *puAlign) return VERR_OUT_OF_RANGE; RTGCPHYS PhysHit; rc = PGMR3DbgScanPhysical(pVM, pAddress->FlatPtr, cbRange, GCPhysAlign, pabNeedle, cbNeedle, &PhysHit); if (RT_SUCCESS(rc)) DBGFR3AddrFromPhys(pUVM, pHitAddress, PhysHit); } else { #if GC_ARCH_BITS > 32 if ( ( pAddress->FlatPtr >= _4G || pAddress->FlatPtr + cbRange > _4G) && enmMode != PGMMODE_AMD64 && enmMode != PGMMODE_AMD64_NX) return VERR_DBGF_MEM_NOT_FOUND; #endif RTGCUINTPTR GCPtrHit; rc = PGMR3DbgScanVirtual(pVM, pVCpu, pAddress->FlatPtr, cbRange, *puAlign, pabNeedle, cbNeedle, &GCPtrHit); if (RT_SUCCESS(rc)) DBGFR3AddrFromFlat(pUVM, pHitAddress, GCPtrHit); } return rc; }
/** * @interface_method_impl{DBGCCMDHLP,pfnVarToDbgfAddr} */ static DECLCALLBACK(int) dbgcHlpVarToDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PDBGFADDRESS pAddress) { PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp); AssertPtr(pVar); AssertPtr(pAddress); switch (pVar->enmType) { case DBGCVAR_TYPE_GC_FLAT: DBGFR3AddrFromFlat(pDbgc->pUVM, pAddress, pVar->u.GCFlat); return VINF_SUCCESS; case DBGCVAR_TYPE_NUMBER: DBGFR3AddrFromFlat(pDbgc->pUVM, pAddress, (RTGCUINTPTR)pVar->u.u64Number); return VINF_SUCCESS; case DBGCVAR_TYPE_GC_FAR: return DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, pAddress, pVar->u.GCFar.sel, pVar->u.GCFar.off); case DBGCVAR_TYPE_GC_PHYS: DBGFR3AddrFromPhys(pDbgc->pUVM, pAddress, pVar->u.GCPhys); return VINF_SUCCESS; case DBGCVAR_TYPE_SYMBOL: { DBGCVAR Var; int rc = DBGCCmdHlpEval(&pDbgc->CmdHlp, &Var, "%%(%DV)", pVar); if (RT_FAILURE(rc)) return rc; return dbgcHlpVarToDbgfAddr(pCmdHlp, &Var, pAddress); } case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_HC_FLAT: case DBGCVAR_TYPE_HC_PHYS: default: return VERR_DBGC_PARSE_CONVERSION_FAILED; } }
/** * @interface_method_impl{DBGCCMDHLP,pfnVarConvert} */ static DECLCALLBACK(int) dbgcHlpVarConvert(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pInVar, DBGCVARTYPE enmToType, bool fConvSyms, PDBGCVAR pResult) { PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp); DBGCVAR const InVar = *pInVar; /* if pInVar == pResult */ PCDBGCVAR pArg = &InVar; /* lazy bird, clean up later */ DBGFADDRESS Address; int rc; Assert(pDbgc->pUVM); *pResult = InVar; switch (InVar.enmType) { case DBGCVAR_TYPE_GC_FLAT: switch (enmToType) { case DBGCVAR_TYPE_GC_FLAT: return VINF_SUCCESS; case DBGCVAR_TYPE_GC_FAR: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_PHYS: pResult->enmType = DBGCVAR_TYPE_GC_PHYS; rc = DBGFR3AddrToPhys(pDbgc->pUVM, pDbgc->idCpu, DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat), &pResult->u.GCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_HC_FLAT: pResult->enmType = DBGCVAR_TYPE_HC_FLAT; rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu, DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat), false /*fReadOnly */, &pResult->u.pvHCFlat); if (RT_SUCCESS(rc)) return VINF_SUCCESS; return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_HC_PHYS: pResult->enmType = DBGCVAR_TYPE_HC_PHYS; rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu, DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat), &pResult->u.GCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_NUMBER: pResult->enmType = enmToType; pResult->u.u64Number = InVar.u.GCFlat; return VINF_SUCCESS; case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_SYMBOL: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } break; case DBGCVAR_TYPE_GC_FAR: switch (enmToType) { case DBGCVAR_TYPE_GC_FLAT: rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off); if (RT_SUCCESS(rc)) { pResult->enmType = DBGCVAR_TYPE_GC_FLAT; pResult->u.GCFlat = Address.FlatPtr; return VINF_SUCCESS; } return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_GC_FAR: return VINF_SUCCESS; case DBGCVAR_TYPE_GC_PHYS: rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off); if (RT_SUCCESS(rc)) { pResult->enmType = DBGCVAR_TYPE_GC_PHYS; rc = DBGFR3AddrToPhys(pDbgc->pUVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; } return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_HC_FLAT: rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off); if (RT_SUCCESS(rc)) { pResult->enmType = DBGCVAR_TYPE_HC_FLAT; rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu, &Address, false /*fReadOnly*/, &pResult->u.pvHCFlat); if (RT_SUCCESS(rc)) return VINF_SUCCESS; } return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_HC_PHYS: rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off); if (RT_SUCCESS(rc)) { pResult->enmType = DBGCVAR_TYPE_HC_PHYS; rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; } return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_NUMBER: pResult->enmType = enmToType; pResult->u.u64Number = InVar.u.GCFar.off; return VINF_SUCCESS; case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_SYMBOL: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } break; case DBGCVAR_TYPE_GC_PHYS: switch (enmToType) { case DBGCVAR_TYPE_GC_FLAT: //rc = MMR3PhysGCPhys2GCVirtEx(pDbgc->pVM, pResult->u.GCPhys, ..., &pResult->u.GCFlat); - yea, sure. return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_FAR: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_PHYS: return VINF_SUCCESS; case DBGCVAR_TYPE_HC_FLAT: pResult->enmType = DBGCVAR_TYPE_HC_FLAT; rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu, DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, pArg->u.GCPhys), false /*fReadOnly */, &pResult->u.pvHCFlat); if (RT_SUCCESS(rc)) return VINF_SUCCESS; return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_HC_PHYS: pResult->enmType = DBGCVAR_TYPE_HC_PHYS; rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu, DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, pArg->u.GCPhys), &pResult->u.HCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_NUMBER: pResult->enmType = enmToType; pResult->u.u64Number = InVar.u.GCPhys; return VINF_SUCCESS; case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_SYMBOL: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } break; case DBGCVAR_TYPE_HC_FLAT: switch (enmToType) { case DBGCVAR_TYPE_GC_FLAT: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_FAR: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_PHYS: pResult->enmType = DBGCVAR_TYPE_GC_PHYS; rc = PGMR3DbgR3Ptr2GCPhys(pDbgc->pUVM, pArg->u.pvHCFlat, &pResult->u.GCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; /** @todo more memory types! */ return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_HC_FLAT: return VINF_SUCCESS; case DBGCVAR_TYPE_HC_PHYS: pResult->enmType = DBGCVAR_TYPE_HC_PHYS; rc = PGMR3DbgR3Ptr2HCPhys(pDbgc->pUVM, pArg->u.pvHCFlat, &pResult->u.HCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; /** @todo more memory types! */ return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_NUMBER: pResult->enmType = enmToType; pResult->u.u64Number = (uintptr_t)InVar.u.pvHCFlat; return VINF_SUCCESS; case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_SYMBOL: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } break; case DBGCVAR_TYPE_HC_PHYS: switch (enmToType) { case DBGCVAR_TYPE_GC_FLAT: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_FAR: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_PHYS: pResult->enmType = DBGCVAR_TYPE_GC_PHYS; rc = PGMR3DbgHCPhys2GCPhys(pDbgc->pUVM, pArg->u.HCPhys, &pResult->u.GCPhys); if (RT_SUCCESS(rc)) return VINF_SUCCESS; return VERR_DBGC_PARSE_CONVERSION_FAILED; case DBGCVAR_TYPE_HC_FLAT: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_HC_PHYS: return VINF_SUCCESS; case DBGCVAR_TYPE_NUMBER: pResult->enmType = enmToType; pResult->u.u64Number = InVar.u.HCPhys; return VINF_SUCCESS; case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_SYMBOL: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } break; case DBGCVAR_TYPE_NUMBER: switch (enmToType) { case DBGCVAR_TYPE_GC_FLAT: pResult->enmType = DBGCVAR_TYPE_GC_FLAT; pResult->u.GCFlat = (RTGCPTR)InVar.u.u64Number; return VINF_SUCCESS; case DBGCVAR_TYPE_GC_FAR: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_GC_PHYS: pResult->enmType = DBGCVAR_TYPE_GC_PHYS; pResult->u.GCPhys = (RTGCPHYS)InVar.u.u64Number; return VINF_SUCCESS; case DBGCVAR_TYPE_HC_FLAT: pResult->enmType = DBGCVAR_TYPE_HC_FLAT; pResult->u.pvHCFlat = (void *)(uintptr_t)InVar.u.u64Number; return VINF_SUCCESS; case DBGCVAR_TYPE_HC_PHYS: pResult->enmType = DBGCVAR_TYPE_HC_PHYS; pResult->u.HCPhys = (RTHCPHYS)InVar.u.u64Number; return VINF_SUCCESS; case DBGCVAR_TYPE_NUMBER: return VINF_SUCCESS; case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_SYMBOL: return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } break; case DBGCVAR_TYPE_SYMBOL: case DBGCVAR_TYPE_STRING: switch (enmToType) { case DBGCVAR_TYPE_GC_FLAT: case DBGCVAR_TYPE_GC_FAR: case DBGCVAR_TYPE_GC_PHYS: case DBGCVAR_TYPE_HC_FLAT: case DBGCVAR_TYPE_HC_PHYS: case DBGCVAR_TYPE_NUMBER: if (fConvSyms) { rc = dbgcSymbolGet(pDbgc, InVar.u.pszString, enmToType, pResult); if (RT_SUCCESS(rc)) return VINF_SUCCESS; } return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; case DBGCVAR_TYPE_STRING: case DBGCVAR_TYPE_SYMBOL: pResult->enmType = enmToType; return VINF_SUCCESS; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } break; case DBGCVAR_TYPE_UNKNOWN: case DBGCVAR_TYPE_ANY: break; } AssertMsgFailed(("f=%d t=%d\n", InVar.enmType, enmToType)); return VERR_INVALID_PARAMETER; }
/** * @interface_method_impl{DBGCCMDHLP,pfnMemWrite} */ static DECLCALLBACK(int) dbgcHlpMemWrite(PDBGCCMDHLP pCmdHlp, const void *pvBuffer, size_t cbWrite, PCDBGCVAR pVarPointer, size_t *pcbWritten) { PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp); DBGFADDRESS Address; int rc; /* * Dummy check. */ if (cbWrite == 0) { if (*pcbWritten) *pcbWritten = 0; return VINF_SUCCESS; } /* * Convert Far addresses getting size and the correct base address. * Getting and checking the size is what makes this messy and slow. */ DBGCVAR Var = *pVarPointer; switch (pVarPointer->enmType) { case DBGCVAR_TYPE_GC_FAR: { /* Use DBGFR3AddrFromSelOff for the conversion. */ Assert(pDbgc->pUVM); rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, Var.u.GCFar.sel, Var.u.GCFar.off); if (RT_FAILURE(rc)) return rc; /* don't bother with flat selectors (for now). */ if (!DBGFADDRESS_IS_FLAT(&Address)) { DBGFSELINFO SelInfo; rc = DBGFR3SelQueryInfo(pDbgc->pUVM, pDbgc->idCpu, Address.Sel, DBGFSELQI_FLAGS_DT_GUEST | DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE, &SelInfo); if (RT_SUCCESS(rc)) { RTGCUINTPTR cb; /* -1 byte */ if (DBGFSelInfoIsExpandDown(&SelInfo)) { if ( !SelInfo.u.Raw.Gen.u1Granularity && Address.off > UINT16_C(0xffff)) return VERR_OUT_OF_SELECTOR_BOUNDS; if (Address.off <= SelInfo.cbLimit) return VERR_OUT_OF_SELECTOR_BOUNDS; cb = (SelInfo.u.Raw.Gen.u1Granularity ? UINT32_C(0xffffffff) : UINT32_C(0xffff)) - Address.off; } else { if (Address.off > SelInfo.cbLimit) return VERR_OUT_OF_SELECTOR_BOUNDS; cb = SelInfo.cbLimit - Address.off; } if (cbWrite - 1 > cb) { if (!pcbWritten) return VERR_OUT_OF_SELECTOR_BOUNDS; cbWrite = cb + 1; } } } Var.enmType = DBGCVAR_TYPE_GC_FLAT; Var.u.GCFlat = Address.FlatPtr; } /* fall thru */ case DBGCVAR_TYPE_GC_FLAT: rc = DBGFR3MemWrite(pDbgc->pUVM, pDbgc->idCpu, DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, Var.u.GCFlat), pvBuffer, cbWrite); if (pcbWritten && RT_SUCCESS(rc)) *pcbWritten = cbWrite; return rc; case DBGCVAR_TYPE_GC_PHYS: rc = DBGFR3MemWrite(pDbgc->pUVM, pDbgc->idCpu, DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, Var.u.GCPhys), pvBuffer, cbWrite); if (pcbWritten && RT_SUCCESS(rc)) *pcbWritten = cbWrite; return rc; case DBGCVAR_TYPE_HC_FLAT: case DBGCVAR_TYPE_HC_PHYS: { /* * Copy HC memory page by page. */ if (pcbWritten) *pcbWritten = 0; while (cbWrite > 0) { /* convert to flat address */ DBGCVAR Var2; rc = dbgcOpAddrFlat(pDbgc, &Var, DBGCVAR_CAT_ANY, &Var2); if (RT_FAILURE(rc)) { if (pcbWritten && *pcbWritten) return -VERR_INVALID_POINTER; return VERR_INVALID_POINTER; } /* calc size. */ size_t cbChunk = PAGE_SIZE; cbChunk -= (uintptr_t)Var.u.pvHCFlat & PAGE_OFFSET_MASK; if (cbChunk > cbWrite) cbChunk = cbWrite; /** @todo protect this!!! */ memcpy(Var2.u.pvHCFlat, pvBuffer, cbChunk); /* advance */ if (Var.enmType == DBGCVAR_TYPE_HC_FLAT) Var.u.pvHCFlat = (uint8_t *)Var.u.pvHCFlat + cbChunk; else Var.u.HCPhys += cbChunk; pvBuffer = (uint8_t const *)pvBuffer + cbChunk; if (pcbWritten) *pcbWritten += cbChunk; cbWrite -= cbChunk; } return VINF_SUCCESS; } default: return VERR_NOT_IMPLEMENTED; } }
/** * @interface_method_impl{DBGCCMDHLP,pfnMemRead} */ static DECLCALLBACK(int) dbgcHlpMemRead(PDBGCCMDHLP pCmdHlp, void *pvBuffer, size_t cbRead, PCDBGCVAR pVarPointer, size_t *pcbRead) { PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp); DBGFADDRESS Address; int rc; /* * Dummy check. */ if (cbRead == 0) { if (*pcbRead) *pcbRead = 0; return VINF_SUCCESS; } /* * Convert Far addresses getting size and the correct base address. * Getting and checking the size is what makes this messy and slow. */ DBGCVAR Var = *pVarPointer; switch (pVarPointer->enmType) { case DBGCVAR_TYPE_GC_FAR: /* Use DBGFR3AddrFromSelOff for the conversion. */ Assert(pDbgc->pUVM); rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, Var.u.GCFar.sel, Var.u.GCFar.off); if (RT_FAILURE(rc)) return rc; /* don't bother with flat selectors (for now). */ if (!DBGFADDRESS_IS_FLAT(&Address)) { DBGFSELINFO SelInfo; rc = DBGFR3SelQueryInfo(pDbgc->pUVM, pDbgc->idCpu, Address.Sel, DBGFSELQI_FLAGS_DT_GUEST | DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE, &SelInfo); if (RT_SUCCESS(rc)) { RTGCUINTPTR cb; /* -1 byte */ if (DBGFSelInfoIsExpandDown(&SelInfo)) { if ( !SelInfo.u.Raw.Gen.u1Granularity && Address.off > UINT16_C(0xffff)) return VERR_OUT_OF_SELECTOR_BOUNDS; if (Address.off <= SelInfo.cbLimit) return VERR_OUT_OF_SELECTOR_BOUNDS; cb = (SelInfo.u.Raw.Gen.u1Granularity ? UINT32_C(0xffffffff) : UINT32_C(0xffff)) - Address.off; } else { if (Address.off > SelInfo.cbLimit) return VERR_OUT_OF_SELECTOR_BOUNDS; cb = SelInfo.cbLimit - Address.off; } if (cbRead - 1 > cb) { if (!pcbRead) return VERR_OUT_OF_SELECTOR_BOUNDS; cbRead = cb + 1; } } } Var.enmType = DBGCVAR_TYPE_GC_FLAT; Var.u.GCFlat = Address.FlatPtr; break; case DBGCVAR_TYPE_GC_FLAT: case DBGCVAR_TYPE_GC_PHYS: case DBGCVAR_TYPE_HC_FLAT: case DBGCVAR_TYPE_HC_PHYS: break; default: return VERR_NOT_IMPLEMENTED; } /* * Copy page by page. */ size_t cbLeft = cbRead; for (;;) { /* * Calc read size. */ size_t cb = RT_MIN(PAGE_SIZE, cbLeft); switch (pVarPointer->enmType) { case DBGCVAR_TYPE_GC_FLAT: cb = RT_MIN(cb, PAGE_SIZE - (Var.u.GCFlat & PAGE_OFFSET_MASK)); break; case DBGCVAR_TYPE_GC_PHYS: cb = RT_MIN(cb, PAGE_SIZE - (Var.u.GCPhys & PAGE_OFFSET_MASK)); break; case DBGCVAR_TYPE_HC_FLAT: cb = RT_MIN(cb, PAGE_SIZE - ((uintptr_t)Var.u.pvHCFlat & PAGE_OFFSET_MASK)); break; case DBGCVAR_TYPE_HC_PHYS: cb = RT_MIN(cb, PAGE_SIZE - ((size_t)Var.u.HCPhys & PAGE_OFFSET_MASK)); break; /* size_t: MSC has braindead loss of data warnings! */ default: break; } /* * Perform read. */ switch (Var.enmType) { case DBGCVAR_TYPE_GC_FLAT: rc = DBGFR3MemRead(pDbgc->pUVM, pDbgc->idCpu, DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, Var.u.GCFlat), pvBuffer, cb); break; case DBGCVAR_TYPE_GC_PHYS: rc = DBGFR3MemRead(pDbgc->pUVM, pDbgc->idCpu, DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, Var.u.GCPhys), pvBuffer, cb); break; case DBGCVAR_TYPE_HC_PHYS: case DBGCVAR_TYPE_HC_FLAT: { DBGCVAR Var2; rc = dbgcOpAddrFlat(pDbgc, &Var, DBGCVAR_CAT_ANY, &Var2); if (RT_SUCCESS(rc)) { /** @todo protect this!!! */ memcpy(pvBuffer, Var2.u.pvHCFlat, cb); rc = 0; } else rc = VERR_INVALID_POINTER; break; } default: rc = VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; } /* * Check for failure. */ if (RT_FAILURE(rc)) { if (pcbRead && (*pcbRead = cbRead - cbLeft) > 0) return VINF_SUCCESS; return rc; } /* * Next. */ cbLeft -= cb; if (!cbLeft) break; pvBuffer = (char *)pvBuffer + cb; rc = DBGCCmdHlpEval(pCmdHlp, &Var, "%DV + %d", &Var, cb); if (RT_FAILURE(rc)) { if (pcbRead && (*pcbRead = cbRead - cbLeft) > 0) return VINF_SUCCESS; return rc; } } /* * Done */ if (pcbRead) *pcbRead = cbRead; return 0; }