PGMDbg.cpp revision 6a9b5d2a23485ebbd7b1063849d37bc5a8ef44d4
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * PGM - Page Manager and Monitor - Debugger & Debugging APIs.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * available from http://www.virtualbox.org. This file is free software;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * General Public License (GPL) as published by the Free Software
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * additional information or have any questions.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/*******************************************************************************
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync* Header Files *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync*******************************************************************************/
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** The max needle size that we will bother searching for
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * This must not be more than half a page! */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Converts a R3 pointer to a GC physical address.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Only for the debugger.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns VBox status code.
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync * @retval VINF_SUCCESS on success, *pGCPhys is set.
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync * @retval VERR_INVALID_POINTER if the pointer is not within the GC physical memory.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pVM The VM handle.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param R3Ptr The R3 pointer to convert.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pGCPhys Where to store the GC physical address on success.
060711075893fd64c1eaaefe41f318d83011e4e3vboxsyncVMMR3DECL(int) PGMR3DbgR3Ptr2GCPhys(PVM pVM, RTR3PTR R3Ptr, PRTGCPHYS pGCPhys)
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync for (PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(pRamRanges);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync for (unsigned iChunk = 0; iChunk < (pRam->cb >> PGM_DYNAMIC_CHUNK_SHIFT); iChunk++)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTR3UINTPTR off = (RTR3UINTPTR)R3Ptr - pRam->paChunkR3Ptrs[iChunk];
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *pGCPhys = pRam->GCPhys + iChunk*PGM_DYNAMIC_CHUNK_SIZE + off;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTR3UINTPTR off = (RTR3UINTPTR)R3Ptr - (RTR3UINTPTR)pRam->pvR3;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Converts a R3 pointer to a HC physical address.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Only for the debugger.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns VBox status code.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @retval VINF_SUCCESS on success, *pHCPhys is set.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @retval VERR_PGM_PHYS_PAGE_RESERVED it it's a valid GC physical page but has no physical backing.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @retval VERR_INVALID_POINTER if the pointer is not within the GC physical memory.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pVM The VM handle.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param R3Ptr The R3 pointer to convert.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pHCPhys Where to store the HC physical address on success.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncVMMR3DECL(int) PGMR3DbgR3Ptr2HCPhys(PVM pVM, RTR3PTR R3Ptr, PRTHCPHYS pHCPhys)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync for (PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(pRamRanges);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync for (unsigned iChunk = 0; iChunk < (pRam->cb >> PGM_DYNAMIC_CHUNK_SHIFT); iChunk++)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTR3UINTPTR off = (RTR3UINTPTR)R3Ptr - pRam->paChunkR3Ptrs[iChunk];
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTR3UINTPTR off = (RTR3UINTPTR)R3Ptr - (RTR3UINTPTR)pRam->pvR3;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Converts a HC physical address to a GC physical address.
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync * Only for the debugger.
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync * @returns VBox status code
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync * @retval VINF_SUCCESS on success, *pGCPhys is set.
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync * @retval VERR_INVALID_POINTER if the HC physical address is not within the GC physical memory.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pVM The VM handle.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param HCPhys The HC physical address to convert.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pGCPhys Where to store the GC physical address on success.
060711075893fd64c1eaaefe41f318d83011e4e3vboxsyncVMMR3DECL(int) PGMR3DbgHCPhys2GCPhys(PVM pVM, RTHCPHYS HCPhys, PRTGCPHYS pGCPhys)
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync * Validate and adjust the input a bit.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync for (PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(pRamRanges);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync while (iPage-- > 0)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if ( PGM_PAGE_GET_HCPHYS(&pRam->aPages[iPage]) == HCPhys
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *pGCPhys = pRam->GCPhys + (iPage << PAGE_SHIFT) + off;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Scans a page for a byte string, keeping track of potential
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * cross page matches.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns true and *poff on match.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * false on mismatch.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pbPage Pointer to the current page.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param poff Input: The offset into the page.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Output: The page offset of the match on success.
8b90eb0585fa16024709ca374c69f1eb5d5a5a7cvboxsync * @param cb The number of bytes to search, starting of *poff.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pabNeedle The byte string to search for.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param cbNeedle The length of the byte string.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pabPrev The buffer that keeps track of a partial match that we
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * bring over from the previous page. This buffer must be
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * at least cbNeedle - 1 big.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pcbPrev Input: The number of partial matching bytes from the previous page.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Output: The number of partial matching bytes from this page.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Initialize to 0 before the first call to this function.
060711075893fd64c1eaaefe41f318d83011e4e3vboxsyncstatic bool pgmR3DbgScanPage(const uint8_t *pbPage, int32_t *poff, uint32_t cb,
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync * Try complete any partial match from the previous page.
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync if (!memcmp(pbPage, pabNeedle + cbPrev, cbNeedle - cbPrev))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return false;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return true;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* check out the remainder of the previous page. */
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync while (cbPrev-- > 0)
060711075893fd64c1eaaefe41f318d83011e4e3vboxsync pb = (const uint8_t *)memchr(pb + 1, *pabNeedle, cbPrev);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync && !memcmp(pbPage, pabNeedle + cbPrev, cbNeedle - cbPrev))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return false;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return true;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Match the body of the page.
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync /* match? */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return true;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* paritial match at the end of the page? */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* We're copying one byte more that we really need here, but wtf. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return false;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* no match, skip a byte ahead. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return false;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Scans guest physical memory for a byte string.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns VBox status codes:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @retval VINF_SUCCESS and *pGCPtrHit on success.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @retval VERR_DBGF_MEM_NOT_FOUND if not found.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @retval VERR_INVALID_POINTER if any of the pointer arguments are invalid.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @retval VERR_INVALID_ARGUMENT if any other arguments are invalid.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pVM Pointer to the shared VM structure.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param GCPhys Where to start searching.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param cbRange The number of bytes to search.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pabNeedle The byte string to search for.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param cbNeedle The length of the byte string. Max 256 bytes.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pGCPhysHit Where to store the address of the first occurence on success.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncVMMR3DECL(int) PGMR3DbgScanPhysical(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cbRange, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCPHYS pGCPhysHit)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Validate and adjust the input a bit.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync const RTGCPHYS GCPhysLast = GCPhys + cbRange - 1 >= GCPhys
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Search the memory - ignore MMIO and zero pages, also don't
3864d226a840ec3ae21abc27459c3cbbc7ef21a3vboxsync * bother to match across ranges.
3864d226a840ec3ae21abc27459c3cbbc7ef21a3vboxsync for (PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(pRamRanges);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * If the search range starts prior to the current ram range record,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * adjust the search range and possibly conclude the search.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Iterate the relevant pages.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync for (uint32_t iPage = off >> PAGE_SHIFT; iPage < cPages; iPage++)
a898eb6a3ace2594099a60b478ae5cc164bfe3dcvboxsync if ( /** @todo !PGM_PAGE_IS_ZERO(pPage)
3864d226a840ec3ae21abc27459c3cbbc7ef21a3vboxsync void const *pvPage;
3864d226a840ec3ae21abc27459c3cbbc7ef21a3vboxsync int rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys & ~(RTGCPHYS)PAGE_OFFSET_MASK, &pvPage, &Lock);
8b90eb0585fa16024709ca374c69f1eb5d5a5a7cvboxsync uint32_t cbSearch = (GCPhys ^ GCPhysLast) & ~(RTGCPHYS)PAGE_OFFSET_MASK
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync : (GCPhysLast & PAGE_OFFSET_MASK) + 1 - (uint32_t)offPage;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync bool fRc = pgmR3DbgScanPage((uint8_t const *)pvPage, &offPage, cbSearch,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *pGCPhysHit = (GCPhys & ~(RTGCPHYS)PAGE_OFFSET_MASK) + offPage;
96a7e06717e2d7398642eadb5ebab1bf13fbe2dbvboxsync /* advance to the the next page. */
return VERR_DBGF_MEM_NOT_FOUND;
VMMR3DECL(int) PGMR3DbgScanVirtual(PVM pVM, RTGCUINTPTR GCPtr, RTGCUINTPTR cbRange, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCUINTPTR pGCPtrHit)
return VERR_INVALID_POINTER;
*pGCPtrHit = 0;
return VERR_INVALID_POINTER;
if (!cbNeedle)
return VERR_INVALID_PARAMETER;
return VERR_INVALID_PARAMETER;
if (!cbRange)
return VERR_DBGF_MEM_NOT_FOUND;
return VERR_DBGF_MEM_NOT_FOUND;
: ~(RTGCUINTPTR)0;
while (cPages-- > 0)
if ( pPage
void const *pvPage;
if (fRc)
return VINF_SUCCESS;
cbPrev = 0;
GCPtr++;
return VERR_DBGF_MEM_NOT_FOUND;