PGMDbg.cpp revision 61028bf0d1927cff20200e587be6f306aa331fe2
/* $Id$ */
/** @file
* PGM - Page Manager and Monitor - Debugger & Debugging APIs.
*/
/*
* Copyright (C) 2006-2007 innotek GmbH
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License 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_PGM
#include "PGMInternal.h"
/** The max needle size that we will bother searching for
* This must not be more than half a page! */
#define MAX_NEEDLE_SIZE 256
/**
* Converts a HC pointer to a GC physical address.
*
* Only for the debugger.
*
* @returns VBox status code.
* @retval VINF_SUCCESS on success, *pGCPhys is set.
* @retval VERR_INVALID_POINTER if the pointer is not within the GC physical memory.
*
* @param pVM The VM handle.
* @param HCPtr The HC pointer to convert.
* @param pGCPhys Where to store the GC physical address on success.
*/
{
#ifdef NEW_PHYS_CODE
*pGCPhys = NIL_RTGCPHYS;
return VERR_NOT_IMPLEMENTED;
#else
pRam;
{
{
{
{
if (off < PGM_DYNAMIC_CHUNK_SIZE)
{
return VINF_SUCCESS;
}
}
}
}
{
{
return VINF_SUCCESS;
}
}
}
return VERR_INVALID_POINTER;
#endif
}
/**
* Converts a HC pointer to a GC physical address.
*
* @returns VBox status code.
* @retval VINF_SUCCESS on success, *pHCPhys is set.
* @retval VERR_PGM_PHYS_PAGE_RESERVED it it's a valid GC physical page but has no physical backing.
* @retval VERR_INVALID_POINTER if the pointer is not within the GC physical memory.
*
* @param pVM The VM handle.
* @param HCPtr The HC pointer to convert.
* @param pHCPhys Where to store the HC physical address on success.
*/
{
#ifdef NEW_PHYS_CODE
*pHCPhys = NIL_RTHCPHYS;
return VERR_NOT_IMPLEMENTED;
#else
pRam;
{
{
{
{
if (off < PGM_DYNAMIC_CHUNK_SIZE)
{
if (PGM_PAGE_IS_RESERVED(pPage))
return VERR_PGM_PHYS_PAGE_RESERVED;
| (off & PAGE_OFFSET_MASK);
return VINF_SUCCESS;
}
}
}
}
{
{
if (PGM_PAGE_IS_RESERVED(pPage))
return VERR_PGM_PHYS_PAGE_RESERVED;
| (off & PAGE_OFFSET_MASK);
return VINF_SUCCESS;
}
}
}
return VERR_INVALID_POINTER;
#endif
}
/**
* Converts a HC physical address to a GC physical address.
*
* Only for the debugger.
*
* @returns VBox status code
* @retval VINF_SUCCESS on success, *pGCPhys is set.
* @retval VERR_INVALID_POINTER if the HC physical address is not within the GC physical memory.
*
* @param pVM The VM handle.
* @param HCPhys The HC physical address to convert.
* @param pGCPhys Where to store the GC physical address on success.
*/
{
/*
* Validate and adjust the input a bit.
*/
if (HCPhys == NIL_RTHCPHYS)
return VERR_INVALID_POINTER;
if (HCPhys == 0)
return VERR_INVALID_POINTER;
pRam;
{
while (iPage-- > 0)
{
return VINF_SUCCESS;
}
}
return VERR_INVALID_POINTER;
}
/**
* Scans a page for a byte string, keeping track of potential
* cross page matches.
*
* @returns true and *poff on match.
* false on mismatch.
* @param pbPage Pointer to the current page.
* @param poff Input: The offset into the page.
* Output: The page offset of the match on success.
* @param cb The number of bytes to search, starting of *poff.
* @param pabNeedle The byte string to search for.
* @param cbNeedle The length of the byte string.
* @param pabPrev The buffer that keeps track of a partial match that we
* bring over from the previous page. This buffer must be
* at least cbNeedle - 1 big.
* @param pcbPrev Input: The number of partial matching bytes from the previous page.
* Output: The number of partial matching bytes from this page.
* Initialize to 0 before the first call to this function.
*/
{
/*
* Try complete any partial match from the previous page.
*/
if (*pcbPrev > 0)
{
{
return false;
return true;
}
/* check out the remainder of the previous page. */
while (cbPrev-- > 0)
{
if (!pb)
break;
{
return false;
return true;
}
}
*pcbPrev = 0;
}
/*
* Match the body of the page.
*/
for (;;)
{
if (!pb)
break;
{
/* match? */
{
return true;
}
}
else
{
/* paritial match at the end of the page? */
{
/* We're copying one byte more that we really need here, but wtf. */
return false;
}
}
/* no match, skip a byte ahead. */
if (cb <= 1)
break;
pb++;
}
return false;
}
/**
* Scans guest physical memory for a byte string.
*
* @returns VBox status codes:
* @retval VINF_SUCCESS and *pGCPtrHit on success.
* @retval VERR_DBGF_MEM_NOT_FOUND if not found.
* @retval VERR_INVALID_POINTER if any of the pointer arguments are invalid.
* @retval VERR_INVALID_ARGUMENT if any other arguments are invalid.
*
* @param pVM Pointer to the shared VM structure.
* @param GCPhys Where to start searching.
* @param cbRange The number of bytes to search.
* @param pabNeedle The byte string to search for.
* @param cbNeedle The length of the byte string. Max 256 bytes.
* @param pGCPhysHit Where to store the address of the first occurence on success.
*/
PDMR3DECL(int) PGMR3DbgScanPhysical(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cbRange, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCPHYS pGCPhysHit)
{
/*
* Validate and adjust the input a bit.
*/
if (!VALID_PTR(pGCPhysHit))
return VERR_INVALID_POINTER;
|| GCPhys == NIL_RTGCPHYS)
return VERR_INVALID_POINTER;
if (!cbNeedle)
return VERR_INVALID_PARAMETER;
if (cbRange > MAX_NEEDLE_SIZE)
return VERR_INVALID_PARAMETER;
if (!cbRange)
return VERR_DBGF_MEM_NOT_FOUND;
return VERR_DBGF_MEM_NOT_FOUND;
: ~(RTGCPHYS)0;
/*
* Search the memory - ignore MMIO and zero pages, also don't
* bother to match across ranges.
*/
pRam;
{
/*
* If the search range starts prior to the current ram range record,
* adjust the search range and possibly conclude the search.
*/
{
break;
off = 0;
}
else
{
/*
* Iterate the relevant pages.
*/
{
if ( !PGM_PAGE_IS_ZERO(pPage)
&& !PGM_PAGE_IS_MMIO(pPage))
{
void const *pvPage;
if (RT_SUCCESS(rc))
{
if (fRc)
{
return VINF_SUCCESS;
}
}
else
cbPrev = 0; /* ignore error. */
}
else
cbPrev = 0;
/* advance to the the next page. */
if (GCPhys++ >= GCPhysLast)
return VERR_DBGF_MEM_NOT_FOUND;
}
}
}
return VERR_DBGF_MEM_NOT_FOUND;
}
/**
* Scans (guest) virtual memory for a byte string.
*
* @returns VBox status codes:
* @retval VINF_SUCCESS and *pGCPtrHit on success.
* @retval VERR_DBGF_MEM_NOT_FOUND if not found.
* @retval VERR_INVALID_POINTER if any of the pointer arguments are invalid.
* @retval VERR_INVALID_ARGUMENT if any other arguments are invalid.
*
* @param pVM Pointer to the shared VM structure.
* @param GCPtr Where to start searching.
* @param cbRange The number of bytes to search. Max 256 bytes.
* @param pabNeedle The byte string to search for.
* @param cbNeedle The length of the byte string.
* @param pGCPtrHit Where to store the address of the first occurence on success.
*/
PDMR3DECL(int) PGMR3DbgScanVirtual(PVM pVM, RTGCUINTPTR GCPtr, RTGCUINTPTR cbRange, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCUINTPTR pGCPtrHit)
{
/*
* Validate and adjust the input a bit.
*/
return VERR_INVALID_POINTER;
*pGCPtrHit = 0;
return VERR_INVALID_POINTER;
if (!cbNeedle)
return VERR_INVALID_PARAMETER;
if (cbRange > MAX_NEEDLE_SIZE)
return VERR_INVALID_PARAMETER;
if (!cbRange)
return VERR_DBGF_MEM_NOT_FOUND;
return VERR_DBGF_MEM_NOT_FOUND;
/*
* Search the memory - ignore MMIO, zero and not-present pages.
*/
: ~(RTGCUINTPTR)0;
while (cPages-- > 0)
{
if (RT_SUCCESS(rc))
{
if ( pPage
&& !PGM_PAGE_IS_ZERO(pPage)
&& !PGM_PAGE_IS_MMIO(pPage))
{
void const *pvPage;
if (RT_SUCCESS(rc))
{
if (fRc)
{
return VINF_SUCCESS;
}
}
else
cbPrev = 0; /* ignore error. */
}
else
cbPrev = 0;
}
else
cbPrev = 0; /* ignore error. */
}
return VERR_DBGF_MEM_NOT_FOUND;
}