Example #1
0
/**
 * Checks if the interrupt flag is enabled or not.
 *
 * @returns true if it's enabled.
 * @returns false if it's disabled.
 *
 * @param   pVM         Pointer to the VM.
 * @param   pCtxCore    CPU context
 */
VMM_INT_DECL(bool) PATMAreInterruptsEnabledByCtxCore(PVM pVM, PCPUMCTXCORE pCtxCore)
{
    if (PATMIsEnabled(pVM))
    {
        if (PATMIsPatchGCAddr(pVM, pCtxCore->eip))
            return false;
    }
    return !!(pCtxCore->eflags.u32 & X86_EFL_IF);
}
/**
 * Returns the current patch manager enabled flag.
 *
 * @returns COM status code
 * @param   enabled address of result variable
 */
STDMETHODIMP MachineDebugger::COMGETTER(PATMEnabled)(BOOL *enabled)
{
    if (!enabled)
        return E_POINTER;
    if (gpVM)
        *enabled = PATMIsEnabled(gpVM);
    else
        *enabled = false;
    return S_OK;
}
Example #3
0
/**
 * Checks if the interrupt flag is enabled or not.
 *
 * @returns true if it's enabled.
 * @returns false if it's disabled.
 *
 * @param   pVM         The cross context VM structure.
 * @param   pCtx        The guest CPU context.
 * @todo CPUM should wrap this, EM.cpp shouldn't call us.
 */
VMM_INT_DECL(bool) PATMAreInterruptsEnabledByCtx(PVM pVM, PCPUMCTX pCtx)
{
    if (PATMIsEnabled(pVM))
    {
        Assert(!HMIsEnabled(pVM));
        if (PATMIsPatchGCAddr(pVM, pCtx->eip))
            return false;
    }
    return !!(pCtx->eflags.u32 & X86_EFL_IF);
}
Example #4
0
/**
 * Reads patch code.
 *
 * @retval  VINF_SUCCESS on success.
 * @retval  VERR_PATCH_NOT_FOUND if the request is entirely outside the patch
 *          code.
 *
 * @param   pVM            The cross context VM structure.
 * @param   GCPtrPatchCode  The patch address to start reading at.
 * @param   pvDst           Where to return the patch code.
 * @param   cbToRead        Number of bytes to read.
 * @param   pcbRead         Where to return the actual number of bytes we've
 *                          read. Optional.
 */
VMM_INT_DECL(int) PATMReadPatchCode(PVM pVM, RTGCPTR GCPtrPatchCode, void *pvDst, size_t cbToRead, size_t *pcbRead)
{
    /* Shortcut. */
    if (!PATMIsEnabled(pVM))
        return VERR_PATCH_NOT_FOUND;
    Assert(!HMIsEnabled(pVM));

    /*
     * Check patch code and patch helper code.  We assume the requested bytes
     * are not in either.
     */
    RTGCPTR offPatchCode = GCPtrPatchCode - (RTGCPTR32)pVM->patm.s.pPatchMemGC;
    if (offPatchCode >= pVM->patm.s.cbPatchMem)
    {
        offPatchCode = GCPtrPatchCode - (RTGCPTR32)pVM->patm.s.pbPatchHelpersRC;
        if (offPatchCode >= pVM->patm.s.cbPatchHelpers)
            return VERR_PATCH_NOT_FOUND;

        /*
         * Patch helper memory.
         */
        uint32_t cbMaxRead = pVM->patm.s.cbPatchHelpers - (uint32_t)offPatchCode;
        if (cbToRead > cbMaxRead)
            cbToRead = cbMaxRead;
#ifdef IN_RC
        memcpy(pvDst, pVM->patm.s.pbPatchHelpersRC + (uint32_t)offPatchCode, cbToRead);
#else
        memcpy(pvDst, pVM->patm.s.pbPatchHelpersR3 + (uint32_t)offPatchCode, cbToRead);
#endif
    }
    else
    {
        /*
         * Patch memory.
         */
        uint32_t cbMaxRead = pVM->patm.s.cbPatchMem - (uint32_t)offPatchCode;
        if (cbToRead > cbMaxRead)
            cbToRead = cbMaxRead;
#ifdef IN_RC
        memcpy(pvDst, pVM->patm.s.pPatchMemGC + (uint32_t)offPatchCode, cbToRead);
#else
        memcpy(pvDst, pVM->patm.s.pPatchMemHC + (uint32_t)offPatchCode, cbToRead);
#endif
    }

    if (pcbRead)
        *pcbRead = cbToRead;
    return VINF_SUCCESS;
}
/**
 * Returns the current patch manager enabled flag.
 *
 * @returns COM status code
 * @param   aEnabled address of result variable
 */
STDMETHODIMP MachineDebugger::COMGETTER(PATMEnabled) (BOOL *aEnabled)
{
    CheckComArgOutPointerValid(aEnabled);

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);

    Console::SafeVMPtrQuiet pVM (mParent);

    if (pVM.isOk())
        *aEnabled = PATMIsEnabled (pVM.raw());
    else
        *aEnabled = false;

    return S_OK;
}
Example #6
0
/**
 * Load virtualized flags.
 *
 * This function is called from CPUMRawEnter(). It doesn't have to update the
 * IF and IOPL eflags bits, the caller will enforce those to set and 0 respectively.
 *
 * @param   pVM         Pointer to the VM.
 * @param   pCtxCore    The cpu context core.
 * @see     pg_raw
 */
VMM_INT_DECL(void) PATMRawEnter(PVM pVM, PCPUMCTXCORE pCtxCore)
{
    bool fPatchCode = PATMIsPatchGCAddr(pVM, pCtxCore->eip);

    /*
     * Currently we don't bother to check whether PATM is enabled or not.
     * For all cases where it isn't, IOPL will be safe and IF will be set.
     */
    register uint32_t efl = pCtxCore->eflags.u32;
    CTXSUFF(pVM->patm.s.pGCState)->uVMFlags = efl & PATM_VIRTUAL_FLAGS_MASK;
    AssertMsg((efl & X86_EFL_IF) || PATMShouldUseRawMode(pVM, (RTRCPTR)pCtxCore->eip), ("X86_EFL_IF is clear and PATM is disabled! (eip=%RRv eflags=%08x fPATM=%d pPATMGC=%RRv-%RRv\n", pCtxCore->eip, pCtxCore->eflags.u32, PATMIsEnabled(pVM), pVM->patm.s.pPatchMemGC, pVM->patm.s.pPatchMemGC + pVM->patm.s.cbPatchMem));

    AssertReleaseMsg(CTXSUFF(pVM->patm.s.pGCState)->fPIF || fPatchCode, ("fPIF=%d eip=%RRv\n", CTXSUFF(pVM->patm.s.pGCState)->fPIF, pCtxCore->eip));

    efl &= ~PATM_VIRTUAL_FLAGS_MASK;
    efl |= X86_EFL_IF;
    pCtxCore->eflags.u32 = efl;

#ifdef IN_RING3
#ifdef PATM_EMULATE_SYSENTER
    PCPUMCTX pCtx;

    /* Check if the sysenter handler has changed. */
    pCtx = CPUMQueryGuestCtxPtr(pVM);
    if (   pCtx->SysEnter.cs  != 0
        && pCtx->SysEnter.eip != 0
       )
    {
        if (pVM->patm.s.pfnSysEnterGC != (RTRCPTR)pCtx->SysEnter.eip)
        {
            pVM->patm.s.pfnSysEnterPatchGC = 0;
            pVM->patm.s.pfnSysEnterGC = 0;

            Log2(("PATMRawEnter: installing sysenter patch for %RRv\n", pCtx->SysEnter.eip));
            pVM->patm.s.pfnSysEnterPatchGC = PATMR3QueryPatchGCPtr(pVM, pCtx->SysEnter.eip);
            if (pVM->patm.s.pfnSysEnterPatchGC == 0)
            {
                rc = PATMR3InstallPatch(pVM, pCtx->SysEnter.eip, PATMFL_SYSENTER | PATMFL_CODE32);
                if (rc == VINF_SUCCESS)
                {
                    pVM->patm.s.pfnSysEnterPatchGC  = PATMR3QueryPatchGCPtr(pVM, pCtx->SysEnter.eip);
                    pVM->patm.s.pfnSysEnterGC       = (RTRCPTR)pCtx->SysEnter.eip;
                    Assert(pVM->patm.s.pfnSysEnterPatchGC);
                }
            }
            else
                pVM->patm.s.pfnSysEnterGC = (RTRCPTR)pCtx->SysEnter.eip;
        }
    }
    else
    {
        pVM->patm.s.pfnSysEnterPatchGC = 0;
        pVM->patm.s.pfnSysEnterGC = 0;
    }
#endif
#endif
}
Example #7
0
/**
 * Checks whether the GC address is part of our patch region
 *
 * @returns VBox status code.
 * @param   pVM         Pointer to the VM.
 * @param   pAddrGC     Guest context address
 * @internal
 */
VMMDECL(bool) PATMIsPatchGCAddr(PVM pVM, RTRCUINTPTR pAddrGC)
{
    return (PATMIsEnabled(pVM) && pAddrGC - (RTRCUINTPTR)pVM->patm.s.pPatchMemGC < pVM->patm.s.cbPatchMem) ? true : false;
}
Example #8
0
/**
 * Check if we must use raw mode (patch code being executed)
 *
 * @param   pVM         Pointer to the VM.
 * @param   pAddrGC     Guest context address
 */
VMM_INT_DECL(bool) PATMShouldUseRawMode(PVM pVM, RTRCPTR pAddrGC)
{
    return (    PATMIsEnabled(pVM)
            && ((pAddrGC >= (RTRCPTR)pVM->patm.s.pPatchMemGC && pAddrGC < (RTRCPTR)((RTRCUINTPTR)pVM->patm.s.pPatchMemGC + pVM->patm.s.cbPatchMem)))) ? true : false;
}
/**
 * Annotates an instruction if patched.
 *
 * @param   pVM         The cross context VM structure.
 * @param   RCPtr       The instruction address.
 * @param   cbInstr     The instruction length.
 * @param   pszBuf      The output buffer.  This will be an empty string if the
 *                      instruction wasn't patched.  If it's patched, it will
 *                      hold a symbol-like string describing the patch.
 * @param   cbBuf       The size of the output buffer.
 */
VMMR3_INT_DECL(void) PATMR3DbgAnnotatePatchedInstruction(PVM pVM, RTRCPTR RCPtr, uint8_t cbInstr, char *pszBuf, size_t cbBuf)
{
    /*
     * Always zero the buffer.
     */
    AssertReturnVoid(cbBuf > 0);
    *pszBuf = '\0';

    /*
     * Drop out immediately if it cannot be a patched instruction.
     */
    if (!PATMIsEnabled(pVM))
        return;
    if (   RCPtr < pVM->patm.s.pPatchedInstrGCLowest
        || RCPtr > pVM->patm.s.pPatchedInstrGCHighest)
        return;

    /*
     * Look for a patch record covering any part of the instruction.
     *
     * The first query results in a patched less or equal to RCPtr. While the
     * second results in one that's greater than RCPtr.
     */
    PPATMPATCHREC pPatchRec;
    pPatchRec = (PPATMPATCHREC)RTAvloU32GetBestFit(&pVM->patm.s.PatchLookupTreeHC->PatchTree, RCPtr, false /*fFromAbove*/);
    if (   !pPatchRec
        || RCPtr - pPatchRec->patch.pPrivInstrGC > pPatchRec->patch.cbPrivInstr)
    {
        pPatchRec = (PPATMPATCHREC)RTAvloU32GetBestFit(&pVM->patm.s.PatchLookupTreeHC->PatchTree, RCPtr, true /*fFromAbove*/);
        if (   !pPatchRec
            || (RTRCPTR)(RCPtr + cbInstr) < pPatchRec->patch.pPrivInstrGC )
            return;
    }

    /*
     * Lazy bird uses the symbol name generation code for describing the patch.
     */
    size_t off = patmR3DbgDescribePatchAsSymbol(pPatchRec, pszBuf, cbBuf);
    if (off + 1 < cbBuf)
    {
        const char *pszState;
        switch (pPatchRec->patch.uState)
        {
            case PATCH_REFUSED:             pszState = "Refused"; break;
            case PATCH_DISABLED:            pszState = "Disabled"; break;
            case PATCH_ENABLED:             pszState = "Enabled"; break;
            case PATCH_UNUSABLE:            pszState = "Unusable"; break;
            case PATCH_DIRTY:               pszState = "Dirty"; break;
            case PATCH_DISABLE_PENDING:     pszState = "DisablePending"; break;
            default:                        pszState = "State???"; AssertFailed(); break;
        }

        if (pPatchRec->patch.cbPatchBlockSize > 0)
            off += RTStrPrintf(&pszBuf[off], cbBuf - off, " - %s (%u b) - %#x LB %#x",
                               pszState, pPatchRec->patch.cbPatchJump,
                               pPatchRec->patch.pPatchBlockOffset + pVM->patm.s.pPatchMemGC,
                               pPatchRec->patch.cbPatchBlockSize);
        else
            off += RTStrPrintf(&pszBuf[off], cbBuf - off, " - %s (%u b)", pszState, pPatchRec->patch.cbPatchJump);
    }

}
Example #10
0
/**
 * Checks whether the GC address is part of our patch region.
 *
 * @returns VBox status code.
 * @param   pVM         The cross context VM structure.
 * @param   uGCAddr     Guest context address.
 * @internal
 */
VMMDECL(bool) PATMIsPatchGCAddrExclHelpers(PVM pVM, RTRCUINTPTR uGCAddr)
{
    return PATMIsEnabled(pVM)
        && uGCAddr - (RTRCUINTPTR)pVM->patm.s.pPatchMemGC < pVM->patm.s.cbPatchMem;
}
Example #11
0
/**
 * Checks whether the GC address is part of our patch or helper regions.
 *
 * @returns VBox status code.
 * @param   pVM         The cross context VM structure.
 * @param   uGCAddr     Guest context address.
 * @internal
 */
VMMDECL(bool) PATMIsPatchGCAddr(PVM pVM, RTRCUINTPTR uGCAddr)
{
    return PATMIsEnabled(pVM)
        && (   uGCAddr - (RTRCUINTPTR)pVM->patm.s.pPatchMemGC      < pVM->patm.s.cbPatchMem
            || uGCAddr - (RTRCUINTPTR)pVM->patm.s.pbPatchHelpersRC < pVM->patm.s.cbPatchHelpers);
}
Example #12
0
/**
 * Check if we must use raw mode (patch code being executed)
 *
 * @param   pVM         The cross context VM structure.
 * @param   pAddrGC     Guest context address
 */
VMM_INT_DECL(bool) PATMShouldUseRawMode(PVM pVM, RTRCPTR pAddrGC)
{
    return   PATMIsEnabled(pVM)
          && (   (RTRCUINTPTR)pAddrGC - (RTRCUINTPTR)pVM->patm.s.pPatchMemGC      < pVM->patm.s.cbPatchMem
              || (RTRCUINTPTR)pAddrGC - (RTRCUINTPTR)pVM->patm.s.pbPatchHelpersRC < pVM->patm.s.cbPatchHelpers);
}