VirtualBox

Changeset 47427 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Jul 26, 2013 4:06:01 PM (12 years ago)
Author:
vboxsync
Message:

PATM,IEM: Added interface for safely and quickly reading patch code.

Location:
trunk/src/VBox/VMM
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/Makefile.kmk

    r47421 r47427  
    3636 VMM_COMMON_DEFS += VBOX_WITH_FIRST_IEM_STEP
    3737endif
    38 ifdef VBOX_WITH_IEM
    39  VMM_COMMON_DEFS += VBOX_WITH_IEM
    40 endif
     38#ifdef VBOX_WITH_IEM
     39# VMM_COMMON_DEFS += VBOX_WITH_IEM
     40#endif
    4141ifdef VBOX_WITH_REM
    4242 VMM_COMMON_DEFS += VBOX_WITH_REM
  • trunk/src/VBox/VMM/VMMAll/IEMAll.cpp

    r47413 r47427  
    824824    pIemCpu->rcPassUp           = VINF_SUCCESS;
    825825    pIemCpu->fBypassHandlers    = fBypassHandlers;
    826 #ifdef IN_RC
     826#ifdef VBOX_WITH_RAW_MODE_NOT_R0
    827827    pIemCpu->fInPatchCode       = pIemCpu->uCpl == 0
    828828                               && pCtx->cs.u64Base == 0
     
    872872            return iemRaiseSelectorBounds(pIemCpu, X86_SREG_CS, IEM_ACCESS_INSTRUCTION);
    873873        cbToTryRead = pCtx->cs.u32Limit - GCPtrPC32 + 1;
     874        if (!cbToTryRead) /* overflowed */
     875        {
     876            Assert(GCPtrPC32 == 0); Assert(pCtx->cs.u32Limit == UINT32_MAX);
     877            cbToTryRead = UINT32_MAX;
     878        }
    874879        GCPtrPC = pCtx->cs.u64Base + GCPtrPC32;
    875880    }
    876881
    877 #if defined(IN_RC) && defined(VBOX_WITH_RAW_MODE)
     882#ifdef VBOX_WITH_RAW_MODE_NOT_R0
    878883    /* Allow interpretation of patch manager code blocks since they can for
    879884       instance throw #PFs for perfectly good reasons. */
    880885    if (pIemCpu->fInPatchCode)
    881886    {
    882         uint32_t cbLeftOnPage = PAGE_SIZE - (GCPtrPC & PAGE_OFFSET_MASK);
    883         if (cbToTryRead > cbLeftOnPage)
    884             cbToTryRead = cbLeftOnPage;
    885         if (cbToTryRead > sizeof(pIemCpu->abOpcode))
    886             cbToTryRead = sizeof(pIemCpu->abOpcode);
    887         memcpy(pIemCpu->abOpcode, (void const *)(uintptr_t)GCPtrPC, cbToTryRead);
    888         pIemCpu->cbOpcode = cbToTryRead;
     887        size_t cbRead = 0;
     888        int rc = PATMReadPatchCode(IEMCPU_TO_VM(pIemCpu), GCPtrPC, pIemCpu->abOpcode, sizeof(pIemCpu->abOpcode), &cbRead);
     889        AssertRCReturn(rc, rc);
     890        pIemCpu->cbOpcode = (uint8_t)cbRead; Assert(pIemCpu->cbOpcode == cbRead); Assert(cbRead > 0);
    889891        return VINF_SUCCESS;
    890892    }
    891 #endif
     893#endif /* VBOX_WITH_RAW_MODE_NOT_R0 */
    892894
    893895    RTGCPHYS    GCPhys;
     
    965967 * @returns Strict VBox status code.
    966968 * @param   pIemCpu             The IEM state.
    967  * @param   cbMin               Where to return the opcode byte.
     969 * @param   cbMin               The minimum number of bytes relative offOpcode
     970 *                              that must be read.
    968971 */
    969972static VBOXSTRICTRC iemOpcodeFetchMoreBytes(PIEMCPU pIemCpu, size_t cbMin)
     
    984987        if (!IEM_IS_CANONICAL(GCPtrNext))
    985988            return iemRaiseGeneralProtectionFault0(pIemCpu);
    986         cbToTryRead = PAGE_SIZE - (GCPtrNext & PAGE_OFFSET_MASK);
    987         Assert(cbToTryRead >= cbMin - cbLeft); /* ASSUMPTION based on iemInitDecoderAndPrefetchOpcodes. */
    988989    }
    989990    else
     
    995996            return iemRaiseSelectorBounds(pIemCpu, X86_SREG_CS, IEM_ACCESS_INSTRUCTION);
    996997        cbToTryRead = pCtx->cs.u32Limit - GCPtrNext32 + 1;
     998        if (!cbToTryRead) /* overflowed */
     999        {
     1000            Assert(GCPtrNext32 == 0); Assert(pCtx->cs.u32Limit == UINT32_MAX);
     1001            cbToTryRead = UINT32_MAX;
     1002            /** @todo check out wrapping around the code segment.  */
     1003        }
    9971004        if (cbToTryRead < cbMin - cbLeft)
    9981005            return iemRaiseSelectorBounds(pIemCpu, X86_SREG_CS, IEM_ACCESS_INSTRUCTION);
    9991006        GCPtrNext = pCtx->cs.u64Base + GCPtrNext32;
    10001007    }
     1008
     1009    /* Only read up to the end of the page, and make sure we don't read more
     1010       than the opcode buffer can hold. */
     1011    uint32_t cbLeftOnPage = PAGE_SIZE - (GCPtrNext & PAGE_OFFSET_MASK);
     1012    if (cbToTryRead > cbLeftOnPage)
     1013        cbToTryRead = cbLeftOnPage;
     1014    if (cbToTryRead > sizeof(pIemCpu->abOpcode) - pIemCpu->cbOpcode)
     1015        cbToTryRead = sizeof(pIemCpu->abOpcode) - pIemCpu->cbOpcode;
     1016    Assert(cbToTryRead >= cbMin - cbLeft); /* ASSUMPTION based on iemInitDecoderAndPrefetchOpcodes. */
     1017
     1018#ifdef VBOX_WITH_RAW_MODE_NOT_R0
     1019    /* Allow interpretation of patch manager code blocks since they can for
     1020       instance throw #PFs for perfectly good reasons. */
     1021    if (pIemCpu->fInPatchCode)
     1022    {
     1023        size_t cbRead = 0;
     1024        int rc = PATMReadPatchCode(IEMCPU_TO_VM(pIemCpu), GCPtrNext, pIemCpu->abOpcode, cbToTryRead, &cbRead);
     1025        AssertRCReturn(rc, rc);
     1026        pIemCpu->cbOpcode = (uint8_t)cbRead; Assert(pIemCpu->cbOpcode == cbRead); Assert(cbRead > 0);
     1027        return VINF_SUCCESS;
     1028    }
     1029#endif /* VBOX_WITH_RAW_MODE_NOT_R0 */
    10011030
    10021031    RTGCPHYS    GCPhys;
     
    10271056     * Read the bytes at this address.
    10281057     */
    1029     uint32_t cbLeftOnPage = PAGE_SIZE - (GCPtrNext & PAGE_OFFSET_MASK);
    1030     if (cbToTryRead > cbLeftOnPage)
    1031         cbToTryRead = cbLeftOnPage;
    1032     if (cbToTryRead > sizeof(pIemCpu->abOpcode) - pIemCpu->cbOpcode)
    1033         cbToTryRead = sizeof(pIemCpu->abOpcode) - pIemCpu->cbOpcode;
    1034     Assert(cbToTryRead >= cbMin - cbLeft);
    10351058    if (!pIemCpu->fBypassHandlers)
    10361059        rc = PGMPhysRead(IEMCPU_TO_VM(pIemCpu), GCPhys, &pIemCpu->abOpcode[pIemCpu->cbOpcode], cbToTryRead);
  • trunk/src/VBox/VMM/VMMAll/PATMAll.cpp

    r46165 r47427  
    3636#include <VBox/log.h>
    3737#include <iprt/assert.h>
     38#include <iprt/string.h>
    3839
    3940
     
    282283{
    283284    return (PATMIsEnabled(pVM) && pAddrGC - (RTRCUINTPTR)pVM->patm.s.pPatchMemGC < pVM->patm.s.cbPatchMem) ? true : false;
     285}
     286
     287/**
     288 * Reads patch code.
     289 *
     290 * @returns
     291 * @retval  VINF_SUCCESS on success.
     292 * @retval  VERR_PATCH_NOT_FOUND if the request is entirely outside the patch
     293 *          code.
     294 *
     295 * @param   pVM             The cross context VM structure.
     296 * @param   GCPtrPatchCode  The patch address to start reading at.
     297 * @param   pvDst           Where to return the patch code.
     298 * @param   cbToRead        Number of bytes to read.
     299 * @param   pcbRead         Where to return the actual number of bytes we've
     300 *                          read. Optional.
     301 */
     302VMM_INT_DECL(int) PATMReadPatchCode(PVM pVM, RTGCPTR GCPtrPatchCode, void *pvDst, size_t cbToRead, size_t *pcbRead)
     303{
     304    /* Shortcut. */
     305    if (!PATMIsEnabled(pVM))
     306        return VERR_PATCH_NOT_FOUND;
     307    Assert(!HMIsEnabled(pVM));
     308
     309    RTGCPTR offPatchedInstr = GCPtrPatchCode - (RTGCPTR32)pVM->patm.s.pPatchMemGC;
     310    if (offPatchedInstr >= pVM->patm.s.cbPatchMem)
     311        return VERR_PATCH_NOT_FOUND;
     312
     313    uint32_t cbMaxRead = pVM->patm.s.cbPatchMem - (uint32_t)offPatchedInstr;
     314    if (cbToRead > cbMaxRead)
     315        cbToRead = cbMaxRead;
     316
     317#ifdef IN_RC
     318    memcpy(pvDst, pVM->patm.s.pPatchMemGC + (uint32_t)offPatchedInstr, cbToRead);
     319#else
     320    memcpy(pvDst, pVM->patm.s.pPatchMemHC + (uint32_t)offPatchedInstr, cbToRead);
     321#endif
     322    if (pcbRead)
     323        *pcbRead = cbToRead;
     324    return VINF_SUCCESS;
    284325}
    285326
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette