Lines Matching defs:pPatch
95 static int patmDisableUnusablePatch(PVM pVM, RTRCPTR pInstrGC, RTRCPTR pConflictAddr, PPATCHINFO pPatch);
96 static int patmActivateInt3Patch(PVM pVM, PPATCHINFO pPatch);
97 static int patmDeactivateInt3Patch(PVM pVM, PPATCHINFO pPatch);
103 static const char *PATMPatchType(PVM pVM, PPATCHINFO pPatch);
114 static int patmR3MarkDirtyPatch(PVM pVM, PPATCHINFO pPatch);
668 DECLINLINE(bool) patmR3DisInstrToStr(PVM pVM, PPATCHINFO pPatch, RTGCPTR32 InstrGCPtr32, uint8_t *pbInstrHC, uint32_t fReadFlags,
673 disinfo.pPatchInfo = pPatch;
678 (pPatch->flags & PATMFL_CODE32) ? DISCPUMODE_32BIT : DISCPUMODE_16BIT,
684 DECLINLINE(bool) patmR3DisInstr(PVM pVM, PPATCHINFO pPatch, RTGCPTR32 InstrGCPtr32, uint8_t *pbInstrHC, uint32_t fReadFlags,
689 disinfo.pPatchInfo = pPatch;
694 (pPatch->flags & PATMFL_CODE32) ? DISCPUMODE_32BIT : DISCPUMODE_16BIT,
700 DECLINLINE(bool) patmR3DisInstrNoStrOpMode(PVM pVM, PPATCHINFO pPatch, RTGCPTR32 InstrGCPtr32, uint8_t *pbInstrHC,
706 disinfo.pPatchInfo = pPatch;
710 return RT_SUCCESS(DISInstrWithReader(InstrGCPtr32, pPatch->uOpMode, patmReadBytes, &disinfo,
726 static void patmLogRawPatchInstr(PVM pVM, PPATCHINFO pPatch, uint32_t fFlags,
732 patmR3DisInstrToStr(pVM, pPatch, pPatch->pPrivInstrGC, NULL, fFlags,
755 PPATMPATCHREC pPatch = (PPATMPATCHREC)pNode;
761 if (pPatch->patch.uState == PATCH_REFUSED)
764 if (pPatch->patch.flags & PATMFL_PATCHED_GUEST_CODE)
765 PATM_LOG_PATCH_INSTR(pVM, &pPatch->patch, PATMREAD_RAWCODE, "Org patch jump:", "");
767 Log(("Nr of fixups %d\n", pPatch->patch.nrFixups));
777 PRELOCREC pRec = (PRELOCREC)RTAvlPVGetBestFit(&pPatch->patch.FixupTree, key, true);
802 Assert(pRec->pSource && pPatch->patch.cbPrivInstr <= 15);
804 Assert(!(pPatch->patch.flags & PATMFL_GLOBAL_FUNCTIONS));
806 memcpy(oldInstr, pPatch->patch.aPrivInstr, pPatch->patch.cbPrivInstr);
807 *(RTRCPTR *)&oldInstr[pPatch->patch.cbPrivInstr - sizeof(RTRCPTR)] = pRec->pDest;
809 rc = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), curInstr, pPatch->patch.pPrivInstrGC, pPatch->patch.cbPrivInstr);
817 RTRCPTR pPage = pPatch->patch.pPrivInstrGC & PAGE_BASE_GC_MASK;
824 if (memcmp(curInstr, oldInstr, pPatch->patch.cbPrivInstr))
831 pPatch->patch.uState = PATCH_DISABLED;
836 *(RTRCPTR *)&curInstr[pPatch->patch.cbPrivInstr - sizeof(RTRCPTR)] = pRec->pDest;
837 rc = PGMPhysSimpleDirtyWriteGCPtr(VMMGetCpu0(pVM), pRec->pSource, curInstr, pPatch->patch.cbPrivInstr);
847 if ( pPatch->patch.uState == PATCH_ENABLED
848 && (pPatch->patch.flags & PATMFL_PATCHED_GUEST_CODE))
862 Assert(pRec->pSource - pPatch->patch.cbPatchJump == pPatch->patch.pPrivInstrGC);
864 if (pPatch->patch.cbPatchJump == SIZEOF_NEAR_COND_JUMP32)
866 Assert(pPatch->patch.flags & PATMFL_JUMP_CONFLICT);
868 pJumpOffGC = pPatch->patch.pPrivInstrGC + 2; //two byte opcode
869 oldJump[0] = pPatch->patch.aPrivInstr[0];
870 oldJump[1] = pPatch->patch.aPrivInstr[1];
875 if (pPatch->patch.cbPatchJump == SIZEOF_NEARJUMP32)
877 pJumpOffGC = pPatch->patch.pPrivInstrGC + 1; //one byte opcode
883 AssertMsgFailed(("Invalid patch jump size %d\n", pPatch->patch.cbPatchJump));
886 Assert(pPatch->patch.cbPatchJump <= sizeof(temp));
891 rc = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), temp, pPatch->patch.pPrivInstrGC, pPatch->patch.cbPatchJump);
897 RTRCPTR pPage = pPatch->patch.pPrivInstrGC & PAGE_BASE_GC_MASK;
903 if (memcmp(temp, oldJump, pPatch->patch.cbPatchJump))
910 pPatch->patch.uState = PATCH_DISABLED;
922 Log(("Skip the guest jump to patch code for this disabled patch %RGv - %08X\n", pPatch->patch.pPrivInstrGC, pRec->pRelocPos));
933 Assert(!(pPatch->patch.flags & PATMFL_GLOBAL_FUNCTIONS));
953 if (pPatch->patch.flags & PATMFL_PATCHED_GUEST_CODE)
954 PATM_LOG_PATCH_INSTR(pVM, &pPatch->patch, PATMREAD_RAWCODE, "Rel patch jump:", "");
999 PPATMPATCHREC pPatch = (PPATMPATCHREC)pNode;
1001 PATMR3EnablePatch((PVM)pVM, (RTRCPTR)pPatch->Core.Key);
1017 PPATMPATCHREC pPatch = (PPATMPATCHREC)pNode;
1019 PATMR3DisablePatch((PVM)pVM, (RTRCPTR)pPatch->Core.Key);
1117 PPATCHINFO pPatch = (PPATCHINFO)pCacheRec->pPatch;
1118 Assert(pPatch); Assert(offset - pPatch->pPatchBlockOffset < pPatch->cbPatchBlockSize);
1152 * @param pPatch Current patch block pointer
1155 static int patmr3SetBranchTargets(PVM pVM, PPATCHINFO pPatch)
1171 pRec = (PJUMPREC)RTAvlPVRemoveBestFit(&pPatch->JumpTree, 0, true);
1206 pPatchGC = patmGuestGCPtrToPatchGCPtr(pVM, pPatch, pOrgInstrGC);
1226 pBranchTargetGC = patmGuestGCPtrToPatchGCPtr(pVM, pPatch, pRec->pTargetGC);
1239 Assert(nrJumpRecs == pPatch->nrJumpRecs);
1240 Assert(pPatch->JumpTree == 0);
1248 * @param pPatch Patch structure ptr
1252 static void patmAddIllegalInstrRecord(PVM pVM, PPATCHINFO pPatch, RTRCPTR pInstrGC)
1260 bool ret = RTAvlPVInsert(&pPatch->pTempInfo->IllegalInstrTree, pRec);
1262 pPatch->pTempInfo->nrIllegalInstr++;
1265 static bool patmIsIllegalInstr(PPATCHINFO pPatch, RTRCPTR pInstrGC)
1269 pRec = RTAvlPVGet(&pPatch->pTempInfo->IllegalInstrTree, (AVLPVKEY)(uintptr_t)pInstrGC);
1280 * @param pPatch Patch structure ptr
1289 void patmR3AddP2GLookupRecord(PVM pVM, PPATCHINFO pPatch, uint8_t *pPatchInstrHC, RTRCPTR pInstrGC, PATM_LOOKUP_TYPE enmType, bool fDirty)
1296 LogFlowFunc(("pVM=%#p pPatch=%#p pPatchInstrHC=%#p pInstrGC=%#x enmType=%d fDirty=%RTbool\n",
1297 pVM, pPatch, pPatchInstrHC, pInstrGC, enmType, fDirty));
1301 pPatchToGuestRec = (PRECPATCHTOGUEST)RTAvlU32Get(&pPatch->Patch2GuestAddrTree, PatchOffset);
1310 pPatchToGuestRec = (PRECPATCHTOGUEST)RTAvlU32Get(&pPatch->Patch2GuestAddrTree, PatchOffset);
1322 ret = RTAvlU32Insert(&pPatch->Patch2GuestAddrTree, &pPatchToGuestRec->Core);
1328 pGuestToPatchRec = (PRECGUESTTOPATCH)RTAvlU32Get(&pPatch->Guest2PatchAddrTree, pInstrGC);
1335 ret = RTAvlU32Insert(&pPatch->Guest2PatchAddrTree, &pGuestToPatchRec->Core);
1340 pPatch->nrPatch2GuestRecs++;
1348 * @param pPatch Patch structure ptr
1351 void patmr3RemoveP2GLookupRecord(PVM pVM, PPATCHINFO pPatch, RTRCPTR pPatchInstrGC)
1358 pPatchToGuestRec = (PRECPATCHTOGUEST)RTAvlU32Get(&pPatch->Patch2GuestAddrTree, PatchOffset);
1367 pNode2 = RTAvlU32Remove(&pPatch->Guest2PatchAddrTree, pGuestToPatchRec->Core.Key);
1370 pNode = RTAvlU32Remove(&pPatch->Patch2GuestAddrTree, pPatchToGuestRec->Core.Key);
1374 pPatch->nrPatch2GuestRecs--;
1436 PPATCHINFO pPatch = (PPATCHINFO)pCacheRec->pPatch;
1451 if (pPatch->cbPatchBlockSize >= MAX_PATCH_SIZE)
1453 Log(("Code block too big (%x) for patch at %RRv!!\n", pPatch->cbPatchBlockSize, pCurInstrGC));
1455 patmAddIllegalInstrRecord(pVM, pPatch, pCurInstrGC);
1466 || (pCpu->pCurInstr->uOpcode == OP_CALL && !(pPatch->flags & PATMFL_SUPPORT_CALLS))
1467 || (OP_PARM_VTYPE(pCpu->pCurInstr->fParam1) != OP_PARM_J && !(pPatch->flags & PATMFL_SUPPORT_INDIRECT_CALLS))
1471 patmAddIllegalInstrRecord(pVM, pPatch, pCurInstrGC);
1476 if (pPatch->opcode == OP_CLI && pCpu->pCurInstr->uOpcode == OP_JMP)
1478 if ( pCurInstrGC > pPatch->pPrivInstrGC
1479 && pCurInstrGC + pCpu->cbInstr < pPatch->pPrivInstrGC + SIZEOF_NEARJUMP32) /* hardcoded patch jump size; cbPatchJump is still zero */
1481 Log(("Dangerous unconditional jump ends in our generated patch jump!! (%x vs %x)\n", pCurInstrGC, pPatch->pPrivInstrGC));
1483 pPatch->flags |= PATMFL_INT3_REPLACEMENT_BLOCK;
1488 if (pPatch->opcode == OP_PUSHF)
1493 patmAddIllegalInstrRecord(pVM, pPatch, pCurInstrGC);
1500 pPatch->pTempInfo->nrRetInstr++;
1502 patmAddIllegalInstrRecord(pVM, pPatch, pCurInstrGC);
1510 patmAddIllegalInstrRecord(pVM, pPatch, pCurInstrGC);
1514 pPatch->cbPatchBlockSize += pCpu->cbInstr;
1517 if (fIllegalInstr || patmIsIllegalInstr(pPatch, pCurInstrGC))
1534 Assert(!(pPatch->flags & (PATMFL_DUPLICATE_FUNCTION)));
1536 if (pCurInstrGC > pPatch->pPrivInstrGC && pCurInstrGC < pPatch->pPrivInstrGC + SIZEOF_NEARJUMP32) /* hardcoded patch jump size; cbPatchJump is still zero */
1538 Log(("Exit point within patch jump itself!! (%x vs %x)\n", pCurInstrGC, pPatch->pPrivInstrGC));
1541 if (pPatch->opcode == OP_PUSHF)
1545 if (pPatch->cbPatchBlockSize >= SIZEOF_NEARJUMP32)
1550 pPatch->flags |= PATMFL_CHECK_SIZE;
1574 patmAddIllegalInstrRecord(pVM, pPatch, pCurInstrGC);
1581 if ((pPatch->flags & PATMFL_CHECK_SIZE) && pPatch->cbPatchBlockSize > SIZEOF_NEARJUMP32 && !(pCpu->pCurInstr->fOpType & DISOPTYPE_RELATIVE_CONTROLFLOW))
1604 PPATCHINFO pPatch = (PPATCHINFO)pCacheRec->pPatch;
1612 Assert(pPatch->flags & (PATMFL_DUPLICATE_FUNCTION));
1615 if (pPatch->cbPatchBlockSize >= MAX_PATCH_SIZE)
1617 Log(("Code block too big (%x) for function patch at %RRv!!\n", pPatch->cbPatchBlockSize, pCurInstrGC));
1619 patmAddIllegalInstrRecord(pVM, pPatch, pCurInstrGC);
1630 || (pCpu->pCurInstr->uOpcode == OP_CALL && !(pPatch->flags & PATMFL_SUPPORT_CALLS))
1631 || (OP_PARM_VTYPE(pCpu->pCurInstr->fParam1) != OP_PARM_J && !(pPatch->flags & PATMFL_SUPPORT_INDIRECT_CALLS))
1635 patmAddIllegalInstrRecord(pVM, pPatch, pCurInstrGC);
1641 patmAddIllegalInstrRecord(pVM, pPatch, pCurInstrGC);
1647 patmAddIllegalInstrRecord(pVM, pPatch, pCurInstrGC);
1661 pPatch->cbPatchBlockSize += pCpu->cbInstr;
1664 if (fIllegalInstr || patmIsIllegalInstr(pPatch, pCurInstrGC))
1693 patmAddIllegalInstrRecord(pVM, pPatch, pCurInstrGC);
1715 PPATCHINFO pPatch = (PPATCHINFO)pCacheRec->pPatch;
1721 if ( patmGuestGCPtrToPatchGCPtr(pVM, pPatch, pCurInstrGC) != 0
1722 && !(pPatch->flags & PATMFL_RECOMPILE_NEXT)) /* do not do this when the next instruction *must* be executed! */
1729 return patmPatchGenRelJump(pVM, pPatch, pCurInstrGC, OP_JMP, !!(pCpu->fPrefix & DISPREFIX_OPSIZE));
1732 if (pPatch->flags & (PATMFL_DUPLICATE_FUNCTION))
1745 if (pPatch->flags & PATMFL_RECOMPILE_NEXT)
1746 pPatch->flags &= ~PATMFL_RECOMPILE_NEXT;
1749 patmR3AddP2GLookupRecord(pVM, pPatch, PATCHCODE_PTR_HC(pPatch) + pPatch->uCurPatchOffset, pCurInstrGC, PATM_LOOKUP_BOTHDIR);
1752 if (pCurInstrGC < pPatch->pInstrGCLowest)
1753 pPatch->pInstrGCLowest = pCurInstrGC;
1755 if (pCurInstrGC > pPatch->pInstrGCHighest)
1756 pPatch->pInstrGCHighest = pCurInstrGC + pCpu->cbInstr;
1759 if (patmIsIllegalInstr(pPatch, pCurInstrGC))
1762 rc = patmPatchGenIllegalInstr(pVM, pPatch);
1770 && (pCpu->pCurInstr->uOpcode != OP_CALL || (pPatch->flags & PATMFL_SUPPORT_CALLS))
1783 rc = patmPatchGenCall(pVM, pPatch, pCpu, pCurInstrGC, pTargetGC, false);
1788 rc = patmPatchGenRelJump(pVM, pPatch, pTargetGC, pCpu->pCurInstr->uOpcode, !!(pCpu->fPrefix & DISPREFIX_OPSIZE));
1804 && !(pPatch->flags & (PATMFL_DUPLICATE_FUNCTION))
1808 pPatch->flags &= ~(PATMFL_CHECK_SIZE | PATMFL_SINGLE_INSTRUCTION);
1811 pPatch->flags &= ~PATMFL_GENERATE_JUMPTOGUEST;
1813 rc = patmPatchGenCli(pVM, pPatch);
1827 pPatch->flags |= PATMFL_RECOMPILE_NEXT;
1837 rc = patmPatchGenMovFromSS(pVM, pPatch, pCpu, pCurInstrGC);
1853 pPatch->flags |= PATMFL_RECOMPILE_NEXT;
1862 if (!(pPatch->flags & PATMFL_INHIBIT_IRQS))
1864 pPatch->flags |= PATMFL_INHIBIT_IRQS | PATMFL_GENERATE_JUMPTOGUEST;
1869 rc = patmPatchGenSti(pVM, pPatch, pCurInstrGC, pNextInstrGC);
1878 pPatch->flags |= PATMFL_FOUND_PATCHEND;
1890 disret = patmR3DisInstr(pVM, pPatch, pNextInstrGC, pNextInstrHC, PATMREAD_ORGCODE, &cpu, &cbInstr);
1899 if ( (pPatch->flags & (PATMFL_DUPLICATE_FUNCTION))
1905 if ( (pPatch->flags & PATMFL_DUPLICATE_FUNCTION)
1908 pPatch->flags &= ~PATMFL_GENERATE_JUMPTOGUEST; /* Don't generate a jump back */
1928 if (pPatch->flags & (PATMFL_IDTHANDLER|PATMFL_DUPLICATE_FUNCTION))
1931 rc = patmPatchGenPopf(pVM, pPatch, pCurInstrGC + pCpu->cbInstr, !!(pCpu->fPrefix & DISPREFIX_OPSIZE), fGenerateJmpBack);
1941 pPatch->flags |= PATMFL_FOUND_PATCHEND;
1949 rc = patmPatchGenPushf(pVM, pPatch, !!(pCpu->fPrefix & DISPREFIX_OPSIZE));
1958 rc = patmPatchGenPushCS(pVM, pPatch);
1967 rc = patmPatchGenIret(pVM, pPatch, pCurInstrGC, !!(pCpu->fPrefix & DISPREFIX_OPSIZE));
1970 pPatch->flags |= PATMFL_FOUND_PATCHEND;
1977 rc = patmPatchGenIllegalInstr(pVM, pPatch);
1984 rc = patmPatchGenCpuid(pVM, pPatch, pCurInstrGC);
1995 rc = patmPatchGenSldtStr(pVM, pPatch, pCpu, pCurInstrGC);
2002 rc = patmPatchGenSxDT(pVM, pPatch, pCpu, pCurInstrGC);
2009 rc = patmPatchGenRet(pVM, pPatch, pCpu, pCurInstrGC);
2016 rc = patmPatchGenDuplicate(pVM, pPatch, pCpu, pCurInstrGC);
2022 Assert(pPatch->flags & PATMFL_SUPPORT_INDIRECT_CALLS);
2027 if (pPatch->flags & PATMFL_SUPPORT_INDIRECT_CALLS && pCpu->Param1.cb == 4 /* no far calls! */)
2029 rc = patmPatchGenCall(pVM, pPatch, pCpu, pCurInstrGC, (RTRCPTR)0xDEADBEEF, true);
2039 Assert(pPatch->flags & PATMFL_SUPPORT_INDIRECT_CALLS);
2044 if (pPatch->flags & PATMFL_SUPPORT_INDIRECT_CALLS && pCpu->Param1.cb == 4 /* no far jumps! */)
2046 rc = patmPatchGenJump(pVM, pPatch, pCpu, pCurInstrGC);
2062 rc = patmPatchGenMovDebug(pVM, pPatch, pCpu);
2073 rc = patmPatchGenMovControl(pVM, pPatch, pCpu);
2084 rc = patmPatchGenIllegalInstr(pVM, pPatch);
2092 rc = patmPatchGenDuplicate(pVM, pPatch, pCpu, pCurInstrGC);
2102 && (pPatch->flags & PATMFL_INHIBIT_IRQS))
2107 pPatch->flags &= ~PATMFL_INHIBIT_IRQS;
2109 if (pPatch->flags & PATMFL_GENERATE_JUMPTOGUEST)
2113 rc2 = patmPatchGenJumpToGuest(pVM, pPatch, pNextInstrGC, true /* clear inhibit irq flag */);
2114 pPatch->flags &= ~PATMFL_GENERATE_JUMPTOGUEST;
2119 rc2 = patmPatchGenClearInhibitIRQ(pVM, pPatch, pNextInstrGC);
2128 if ( (pPatch->flags & PATMFL_CHECK_SIZE)
2131 && !(pPatch->flags & PATMFL_RECOMPILE_NEXT) /* do not do this when the next instruction *must* be executed! */
2139 rc = patmPatchGenJumpToGuest(pVM, pPatch, pNextInstrGC);
2153 * @param pPatch Patch structure ptr
2157 static void patmPatchAddDisasmJump(PVM pVM, PPATCHINFO pPatch, RTRCPTR pInstrGC)
2165 int ret = RTAvlPVInsert(&pPatch->pTempInfo->DisasmJumpTree, pRec);
2173 * @param pPatch Patch struct
2177 static bool patmIsKnownDisasmJump(PPATCHINFO pPatch, RTRCPTR pInstrGC)
2181 pRec = RTAvlPVGet(&pPatch->pTempInfo->DisasmJumpTree, (AVLPVKEY)(uintptr_t)pInstrGC);
2200 PPATCHINFO pPatch = (PPATCHINFO)pCacheRec->pPatch;
2209 pOrgJumpGC = patmPatchGCPtr2GuestGCPtr(pVM, pPatch, pCurInstrGC);
2214 bool disret = patmR3DisInstr(pVM, pPatch, pOrgJumpGC, pOrgJumpHC, PATMREAD_ORGCODE, &cpu, NULL);
2228 if ( (pCpu->pCurInstr->uOpcode == OP_CALL && !(pPatch->flags & PATMFL_SUPPORT_CALLS))
2259 PPATCHINFO pPatch = (PPATCHINFO)pCacheRec->pPatch;
2266 Assert(pCurInstrHC != PATCHCODE_PTR_HC(pPatch) || pPatch->pTempInfo->DisasmJumpTree == 0);
2280 disret = patmR3DisInstrToStr(pVM, pPatch, pCurInstrGC, pCurInstrHC, PATMREAD_RAWCODE,
2284 RTRCPTR pOrgInstrGC = patmPatchGCPtr2GuestGCPtr(pVM, pPatch, pCurInstrGC);
2286 if (pOrgInstrGC != pPatch->pTempInfo->pLastDisasmInstrGC)
2291 pPatch->pTempInfo->pLastDisasmInstrGC = pOrgInstrGC;
2292 if (patmIsIllegalInstr(pPatch, pOrgInstrGC))
2343 if (patmIsKnownDisasmJump(pPatch, pTargetGC) == false)
2346 patmPatchAddDisasmJump(pVM, pPatch, pTargetGC);
2348 if (cpu.pCurInstr->uOpcode == OP_CALL) pPatch->pTempInfo->nrCalls++;
2350 if (cpu.pCurInstr->uOpcode == OP_CALL) pPatch->pTempInfo->nrCalls--;
2384 PPATCHINFO pPatch = (PPATCHINFO)pCacheRec->pPatch;
2388 patmEmptyTree(pVM, &pPatch->pTempInfo->DisasmJumpTree);
2428 PPATCHINFO pPatch = (PPATCHINFO)pCacheRec->pPatch;
2446 disret = patmR3DisInstrToStr(pVM, pPatch, pCurInstrGC, pCurInstrHC, PATMREAD_ORGCODE,
2450 disret = patmR3DisInstr(pVM, pPatch, pCurInstrGC, pCurInstrHC, PATMREAD_ORGCODE, &cpu, &cbInstr);
2457 patmR3AddP2GLookupRecord(pVM, pPatch, PATCHCODE_PTR_HC(pPatch) + pPatch->uCurPatchOffset, pCurInstrGC, PATM_LOOKUP_BOTHDIR);
2458 patmPatchGenIllegalInstr(pVM, pPatch);
2468 && (pPatch->flags & PATMFL_INHIBIT_IRQS))
2486 disret = patmR3DisInstr(pVM, pPatch, pNextInstrGC, pNextInstrHC, PATMREAD_ORGCODE, &cpunext, &opsizenext);
2504 rc = patmPatchGenJumpToGuest(pVM, pPatch, pNextInstrGC, true /* clear inhibit irq flag */);
2506 pPatch->flags &= ~PATMFL_INHIBIT_IRQS;
2562 if (patmGuestGCPtrToPatchGCPtr(pVM, pPatch, addr) == 0)
2580 if (cpu.pCurInstr->uOpcode == OP_CALL) pPatch->pTempInfo->nrCalls++;
2582 if (cpu.pCurInstr->uOpcode == OP_CALL) pPatch->pTempInfo->nrCalls--;
2606 Assert(!(pPatch->flags & PATMFL_RECOMPILE_NEXT));
2616 * @param pPatch Patch record
2619 static int patmGenJumpToPatch(PVM pVM, PPATCHINFO pPatch, PPATMP2GLOOKUPREC pCacheRec, bool fAddFixup = true)
2625 Assert(pPatch->cbPatchJump <= sizeof(temp));
2626 Assert(!(pPatch->flags & PATMFL_PATCHED_GUEST_CODE));
2628 pPB = patmR3GCVirtToHCVirt(pVM, pCacheRec, pPatch->pPrivInstrGC);
2632 if (pPatch->flags & PATMFL_JUMP_CONFLICT)
2634 Assert(pPatch->pPatchJumpDestGC);
2636 if (pPatch->cbPatchJump == SIZEOF_NEARJUMP32)
2641 if (patmPatchAddReloc32(pVM, pPatch, &pPB[1], FIXUP_REL_JMPTOPATCH, pPatch->pPrivInstrGC + pPatch->cbPatchJump,
2642 pPatch->pPatchJumpDestGC) != VINF_SUCCESS)
2649 temp[0] = pPatch->aPrivInstr[0]; //jump opcode copied from original instruction
2650 *(uint32_t *)&temp[1] = (uint32_t)pPatch->pPatchJumpDestGC - ((uint32_t)pPatch->pPrivInstrGC + pPatch->cbPatchJump); //return address
2653 if (pPatch->cbPatchJump == SIZEOF_NEAR_COND_JUMP32)
2658 if (patmPatchAddReloc32(pVM, pPatch, &pPB[2], FIXUP_REL_JMPTOPATCH, pPatch->pPrivInstrGC + pPatch->cbPatchJump,
2659 pPatch->pPatchJumpDestGC) != VINF_SUCCESS)
2666 temp[0] = pPatch->aPrivInstr[0]; //jump opcode copied from original instruction
2667 temp[1] = pPatch->aPrivInstr[1]; //jump opcode copied from original instruction
2668 *(uint32_t *)&temp[2] = (uint32_t)pPatch->pPatchJumpDestGC - ((uint32_t)pPatch->pPrivInstrGC + pPatch->cbPatchJump); //return address
2679 Assert(pPatch->cbPatchJump == SIZEOF_NEARJUMP32);
2684 if (patmPatchAddReloc32(pVM, pPatch, &pPB[1], FIXUP_REL_JMPTOPATCH, pPatch->pPrivInstrGC + SIZEOF_NEARJUMP32,
2685 PATCHCODE_PTR_GC(pPatch)) != VINF_SUCCESS)
2692 *(uint32_t *)&temp[1] = (RTRCUINTPTR)PATCHCODE_PTR_GC(pPatch) - ((RTRCUINTPTR)pPatch->pPrivInstrGC + SIZEOF_NEARJUMP32); //return address
2694 rc = PGMPhysSimpleDirtyWriteGCPtr(VMMGetCpu0(pVM), pPatch->pPrivInstrGC, temp, pPatch->cbPatchJump);
2698 pPatch->flags |= PATMFL_PATCHED_GUEST_CODE;
2708 * @param pPatch Patch record
2710 static int patmRemoveJumpToPatch(PVM pVM, PPATCHINFO pPatch)
2718 while (i < pPatch->cbPrivInstr)
2720 disret = patmR3DisInstrToStr(pVM, pPatch, pPatch->pPrivInstrGC + i, NULL, PATMREAD_ORGCODE,
2732 int rc = PGMPhysSimpleDirtyWriteGCPtr(VMMGetCpu0(pVM), pPatch->pPrivInstrGC, pPatch->aPrivInstr, pPatch->cbPatchJump);
2737 while (i < pPatch->cbPrivInstr)
2739 disret = patmR3DisInstrToStr(pVM, pPatch, pPatch->pPrivInstrGC + i, NULL, PATMREAD_ORGCODE,
2750 pPatch->flags &= ~PATMFL_PATCHED_GUEST_CODE;
2759 * @param pPatch Patch record
2763 static int patmGenCallToPatch(PVM pVM, PPATCHINFO pPatch, RTRCPTR pTargetGC, PPATMP2GLOOKUPREC pCacheRec, bool fAddFixup = true)
2769 Assert(pPatch->cbPatchJump <= sizeof(temp));
2771 pPB = patmR3GCVirtToHCVirt(pVM, pCacheRec, pPatch->pPrivInstrGC);
2774 Assert(pPatch->cbPatchJump == SIZEOF_NEARJUMP32);
2779 if (patmPatchAddReloc32(pVM, pPatch, &pPB[1], FIXUP_REL_JMPTOPATCH,
2780 pPatch->pPrivInstrGC + SIZEOF_NEARJUMP32, pTargetGC) != VINF_SUCCESS)
2787 Assert(pPatch->aPrivInstr[0] == 0xE8 || pPatch->aPrivInstr[0] == 0xE9); /* call or jmp */
2788 temp[0] = pPatch->aPrivInstr[0];
2789 *(uint32_t *)&temp[1] = (uint32_t)pTargetGC - ((uint32_t)pPatch->pPrivInstrGC + SIZEOF_NEARJUMP32); //return address
2791 rc = PGMPhysSimpleDirtyWriteGCPtr(VMMGetCpu0(pVM), pPatch->pPrivInstrGC, temp, pPatch->cbPatchJump);
2815 PPATCHINFO pPatch = &pPatchRec->patch;
2826 Assert(!(pPatch->flags & (PATMFL_GUEST_SPECIFIC|PATMFL_USER_MODE|PATMFL_TRAPHANDLER)));
2836 pPatch->flags |= PATMFL_CALLABLE_AS_FUNCTION;
2840 if (!(pPatch->flags & PATMFL_IDTHANDLER))
2847 if (!(pPatch->flags & (PATMFL_IDTHANDLER|PATMFL_IDTHANDLER_WITHOUT_ENTRYPOINT|PATMFL_SYSENTER|PATMFL_INT3_REPLACEMENT_BLOCK)))
2848 pPatch->flags |= PATMFL_MUST_INSTALL_PATCHJMP;
2851 if ( (pPatch->flags & PATMFL_MUST_INSTALL_PATCHJMP)
2861 pPatch->nrPatch2GuestRecs = 0;
2865 pPatch->flags |= PATMFL_SUPPORT_CALLS | PATMFL_SUPPORT_INDIRECT_CALLS;
2868 pPatch->pPatchBlockOffset = pVM->patm.s.offPatchMem;
2869 pPatch->uCurPatchOffset = 0;
2871 if ((pPatch->flags & (PATMFL_IDTHANDLER|PATMFL_IDTHANDLER_WITHOUT_ENTRYPOINT|PATMFL_SYSENTER)) == PATMFL_IDTHANDLER)
2873 Assert(pPatch->flags & PATMFL_INTHANDLER);
2876 rc = patmPatchGenIntEntry(pVM, pPatch, pInstrGC);
2885 if (!(pPatch->flags & PATMFL_SYSENTER))
2887 rc = patmPatchGenStats(pVM, pPatch, pInstrGC);
2895 cacheRec.pPatch = pPatch;
2911 if (pPatch->cbPatchBlockSize < SIZEOF_NEARJUMP32)
2921 pPatch->cbPatchBlockSize = pPatch->uCurPatchOffset;
2925 pVM->patm.s.offPatchMem += pPatch->cbPatchBlockSize;
2932 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset));
2933 pPatchRec->CoreOffset.Key = pPatch->pPatchBlockOffset;
2943 rc = patmr3SetBranchTargets(pVM, pPatch);
2952 patmr3DisasmCodeStream(pVM, PATCHCODE_PTR_GC(pPatch), PATCHCODE_PTR_GC(pPatch), patmr3DisasmCallback, &cacheRec);
2963 pPatch->cbPatchJump = SIZEOF_NEARJUMP32;
2965 rc = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), pPatch->aPrivInstr, pPatch->pPrivInstrGC, pPatch->cbPatchJump);
2968 if (pPatch->flags & PATMFL_INT3_REPLACEMENT_BLOCK)
2972 Log(("patmR3PatchBlock %RRv -> int 3 callable patch.\n", pPatch->pPrivInstrGC));
2974 rc = patmActivateInt3Patch(pVM, pPatch);
2979 pPatch->flags &= ~PATMFL_MUST_INSTALL_PATCHJMP;
2981 pPatch->flags &= ~PATMFL_INSTR_HINT;
2985 if (pPatch->flags & PATMFL_MUST_INSTALL_PATCHJMP)
2987 Assert(!(pPatch->flags & (PATMFL_IDTHANDLER|PATMFL_IDTHANDLER_WITHOUT_ENTRYPOINT|PATMFL_SYSENTER|PATMFL_INT3_REPLACEMENT_BLOCK)));
2989 rc = patmGenJumpToPatch(pVM, pPatch, &cacheRec, true);
2998 PATM_LOG_RAW_PATCH_INSTR(pVM, pPatch, patmGetInstructionString(pPatch->opcode, pPatch->flags));
3000 patmEmptyTree(pVM, &pPatch->pTempInfo->IllegalInstrTree);
3001 pPatch->pTempInfo->nrIllegalInstr = 0;
3003 Log(("Successfully installed %s patch at %RRv\n", patmGetInstructionString(pPatch->opcode, pPatch->flags), pInstrGC));
3005 pPatch->uState = PATCH_ENABLED;
3012 patmEmptyTree(pVM, &pPatch->FixupTree);
3013 pPatch->nrFixups = 0;
3015 patmEmptyTree(pVM, &pPatch->JumpTree);
3016 pPatch->nrJumpRecs = 0;
3018 patmEmptyTree(pVM, &pPatch->pTempInfo->IllegalInstrTree);
3019 pPatch->pTempInfo->nrIllegalInstr = 0;
3022 pPatch->uState = PATCH_REFUSED;
3023 pPatch->pPatchBlockOffset = 0;
3047 PPATCHINFO pPatch = &pPatchRec->patch;
3063 disret = patmR3DisInstr(pVM, pPatch, pCurInstrGC, pCurInstrHC, PATMREAD_ORGCODE, &cpuPush, &cbInstr);
3071 disret = patmR3DisInstr(pVM, pPatch, pCurInstrGC, pCurInstrHC, PATMREAD_ORGCODE, &cpuJmp, &cbInstr);
3082 rc = PATMR3InstallPatch(pVM, pJmpInstrGC, pPatch->flags | PATMFL_IDTHANDLER_WITHOUT_ENTRYPOINT);
3094 pPatch->pPatchBlockOffset = pVM->patm.s.offPatchMem;
3095 pPatch->uCurPatchOffset = 0;
3096 pPatch->nrPatch2GuestRecs = 0;
3099 rc = patmPatchGenStats(pVM, pPatch, pInstrGC);
3105 rc = patmPatchGenIntEntry(pVM, pPatch, pInstrGC);
3110 patmR3AddP2GLookupRecord(pVM, pPatch, PATCHCODE_PTR_HC(pPatch) + pPatch->uCurPatchOffset, pInstrGC, PATM_LOOKUP_BOTHDIR);
3113 rc = patmPatchGenDuplicate(pVM, pPatch, &cpuPush, pInstrGC);
3118 rc = patmPatchGenPatchJump(pVM, pPatch, pCurInstrGC, PATCHCODE_PTR_GC(&pJmpPatch->patch));
3123 pPatch->cbPatchBlockSize = pPatch->uCurPatchOffset;
3126 pVM->patm.s.offPatchMem += pPatch->cbPatchBlockSize;
3131 pPatch->cbPatchJump = 0;
3136 patmr3DisasmCodeStream(pVM, PATCHCODE_PTR_GC(pPatch), PATCHCODE_PTR_GC(pPatch), patmr3DisasmCallback, pCacheRec);
3144 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset));
3145 pPatchRec->CoreOffset.Key = pPatch->pPatchBlockOffset;
3150 pPatch->uState = PATCH_ENABLED;
3175 PPATCHINFO pPatch = &pPatchRec->patch;
3183 pPatch->pPatchBlockOffset = pVM->patm.s.offPatchMem;
3184 pPatch->uCurPatchOffset = 0;
3185 pPatch->nrPatch2GuestRecs = 0;
3188 rc = patmPatchGenStats(pVM, pPatch, pInstrGC);
3193 rc = patmPatchGenTrapEntry(pVM, pPatch, pInstrGC);
3198 pPatch->cbPatchBlockSize = pPatch->uCurPatchOffset;
3201 pVM->patm.s.offPatchMem += pPatch->cbPatchBlockSize;
3206 pPatch->cbPatchJump = 0;
3210 patmr3DisasmCodeStream(pVM, PATCHCODE_PTR_GC(pPatch), PATCHCODE_PTR_GC(pPatch), patmr3DisasmCallback, pCacheRec);
3213 PATM_LOG_ORG_PATCH_INSTR(pVM, pPatch, "TRAP handler");
3219 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset));
3220 pPatchRec->CoreOffset.Key = pPatch->pPatchBlockOffset;
3225 pPatch->uState = PATCH_ENABLED;
3232 pPatch->uState = PATCH_REFUSED;
3233 pPatch->pPatchBlockOffset = 0;
3276 PPATCHINFO pPatch = &pPatchRec->patch;
3295 pPatch->flags |= PATMFL_SUPPORT_CALLS | PATMFL_SUPPORT_INDIRECT_CALLS;
3298 Assert(pPatch->flags & (PATMFL_DUPLICATE_FUNCTION));
3300 pPatch->nrPatch2GuestRecs = 0;
3301 pPatch->pPatchBlockOffset = pVM->patm.s.offPatchMem;
3302 pPatch->uCurPatchOffset = 0;
3305 rc = patmPatchGenSetPIF(pVM, pPatch, pInstrGC);
3310 rc = patmPatchGenStats(pVM, pPatch, pInstrGC);
3323 pPatch->cbPatchBlockSize = pPatch->uCurPatchOffset;
3326 pVM->patm.s.offPatchMem += pPatch->cbPatchBlockSize;
3330 pPatch->uState = PATCH_ENABLED;
3335 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset));
3336 pPatchRec->CoreOffset.Key = pPatch->pPatchBlockOffset;
3346 rc = patmr3SetBranchTargets(pVM, pPatch);
3357 patmr3DisasmCodeStream(pVM, PATCHCODE_PTR_GC(pPatch), PATCHCODE_PTR_GC(pPatch), patmr3DisasmCallback, pCacheRec);
3363 patmEmptyTree(pVM, &pPatch->pTempInfo->IllegalInstrTree);
3364 pPatch->pTempInfo->nrIllegalInstr = 0;
3374 patmEmptyTree(pVM, &pPatch->FixupTree);
3375 pPatch->nrFixups = 0;
3377 patmEmptyTree(pVM, &pPatch->JumpTree);
3378 pPatch->nrJumpRecs = 0;
3380 patmEmptyTree(pVM, &pPatch->pTempInfo->IllegalInstrTree);
3381 pPatch->pTempInfo->nrIllegalInstr = 0;
3384 pPatch->uState = PATCH_REFUSED;
3385 pPatch->pPatchBlockOffset = 0;
3407 PPATCHINFO pPatch = &pPatchRec->patch;
3474 pPatch->nrPatch2GuestRecs = 0;
3475 pPatch->pPatchBlockOffset = pVM->patm.s.offPatchMem;
3476 pPatch->uCurPatchOffset = 0;
3479 rc = patmPatchGenSetPIF(pVM, pPatch, pInstrGC);
3484 rc = patmPatchGenStats(pVM, pPatch, pInstrGC);
3489 rc = patmPatchGenPatchJump(pVM, pPatch, pInstrGC, pPatchTargetGC);
3496 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset));
3497 pPatchRec->CoreOffset.Key = pPatch->pPatchBlockOffset;
3508 pPatch->cbPatchBlockSize = pPatch->uCurPatchOffset;
3511 pVM->patm.s.offPatchMem += pPatch->cbPatchBlockSize;
3516 pPatch->cbPatchJump = 0;
3519 pPatch->uState = PATCH_ENABLED;
3521 pPatch->flags |= PATMFL_CALLABLE_AS_FUNCTION;
3535 patmEmptyTree(pVM, &pPatch->FixupTree);
3536 pPatch->nrFixups = 0;
3538 patmEmptyTree(pVM, &pPatch->JumpTree);
3539 pPatch->nrJumpRecs = 0;
3541 patmEmptyTree(pVM, &pPatch->pTempInfo->IllegalInstrTree);
3542 pPatch->pTempInfo->nrIllegalInstr = 0;
3545 pPatch->uState = PATCH_REFUSED;
3546 pPatch->pPatchBlockOffset = 0;
3590 PPATCHINFO pPatch = pPatchPage->papPatch[i];
3592 if ( (pPatch->flags & PATMFL_DUPLICATE_FUNCTION)
3593 && pPatch->uState == PATCH_ENABLED)
3595 pPatchTargetGC = patmGuestGCPtrToPatchGCPtr(pVM, pPatch, pBranchTarget);
3654 PPATCHINFO pPatch = (PPATCHINFO)pCacheRec->pPatch;
3662 Assert(pPatch->flags & PATMFL_REPLACE_FUNCTION_CALL);
3694 disret = patmR3DisInstr(pVM, pPatch, pTargetGC, pTmpInstrHC, PATMREAD_ORGCODE, &cpu, &cbInstr);
3716 pPatch->cbPatchJump = SIZEOF_NEARJUMP32;
3718 rc = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), pPatch->aPrivInstr, pPatch->pPrivInstrGC, pPatch->cbPatchJump);
3722 rc = patmGenCallToPatch(pVM, pPatch, PATCHCODE_PTR_GC(&pPatchFunction->patch), pCacheRec, true);
3728 pPatch->pInstrGCLowest = pInstrGC;
3729 pPatch->pInstrGCHighest = pInstrGC + pCpu->cbInstr;
3730 PATM_LOG_ORG_PATCH_INSTR(pVM, pPatch, "Call");
3734 pPatch->uState = PATCH_ENABLED;
3739 pPatch->uState = PATCH_REFUSED;
3758 PPATCHINFO pPatch = (PPATCHINFO)pCacheRec->pPatch;
3769 pPB = patmR3GCVirtToHCVirt(pVM, pCacheRec, pPatch->pPrivInstrGC);
3774 if (patmPatchAddReloc32(pVM, pPatch, &pPB[pCpu->cbInstr - sizeof(RTRCPTR)], FIXUP_ABSOLUTE, pPatch->pPrivInstrGC,
3780 PATM_LOG_PATCH_INSTR(pVM, pPatch, PATMREAD_ORGCODE, "MMIO patch old instruction:", "");
3783 rc = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), pPatch->aPrivInstr, pPatch->pPrivInstrGC, pPatch->cbPrivInstr);
3786 pPatch->cbPatchJump = pPatch->cbPrivInstr; /* bit of a misnomer in this case; size of replacement instruction. */
3797 PATM_LOG_ORG_PATCH_INSTR(pVM, pPatch, "MMIO");
3800 pPatch->uState = PATCH_ENABLED;
3805 pPatch->uState = PATCH_REFUSED;
3817 * @param pPatch Patch record
3822 static int patmPatchPATMMMIOInstr(PVM pVM, RTRCPTR pInstrGC, PPATCHINFO pPatch)
3836 disret = patmR3DisInstrNoStrOpMode(pVM, pPatch, pInstrGC, pInstrHC, PATMREAD_ORGCODE,
3851 if (patmPatchAddReloc32(pVM, pPatch, &pInstrHC[cpu.cbInstr - sizeof(RTRCPTR)], FIXUP_ABSOLUTE) != VINF_SUCCESS)
3860 pPatch->pInstrGCLowest = pInstrGC;
3861 pPatch->pInstrGCHighest = pInstrGC + cpu.cbInstr;
3863 PATM_LOG_ORG_PATCH_INSTR(pVM, pPatch, "MMIO");
3874 * @param pPatch Patch record
3876 static int patmActivateInt3Patch(PVM pVM, PPATCHINFO pPatch)
3881 Assert(pPatch->flags & (PATMFL_INT3_REPLACEMENT|PATMFL_INT3_REPLACEMENT_BLOCK));
3882 Assert(pPatch->uState != PATCH_ENABLED);
3885 rc = PGMPhysSimpleDirtyWriteGCPtr(VMMGetCpu0(pVM), pPatch->pPrivInstrGC, &bASMInt3, sizeof(bASMInt3));
3888 pPatch->cbPatchJump = sizeof(bASMInt3);
3898 * @param pPatch Patch record
3900 static int patmDeactivateInt3Patch(PVM pVM, PPATCHINFO pPatch)
3905 Assert(pPatch->flags & (PATMFL_INT3_REPLACEMENT|PATMFL_INT3_REPLACEMENT_BLOCK));
3906 Assert(pPatch->uState == PATCH_ENABLED || pPatch->uState == PATCH_DIRTY);
3909 rc = PGMPhysSimpleDirtyWriteGCPtr(VMMGetCpu0(pVM), pPatch->pPrivInstrGC, pPatch->aPrivInstr, sizeof(ASMInt3));
3923 * @param pPatch Patch record
3928 int patmR3PatchInstrInt3(PVM pVM, RTRCPTR pInstrGC, R3PTRTYPE(uint8_t *) pInstrHC, DISCPUSTATE *pCpu, PPATCHINFO pPatch)
3934 PATM_LOG_PATCH_INSTR(pVM, pPatch, PATMREAD_ORGCODE, "patmR3PatchInstrInt3:", "");
3937 rc = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), pPatch->aPrivInstr, pPatch->pPrivInstrGC, pPatch->cbPrivInstr);
3939 pPatch->cbPatchJump = sizeof(bASMInt3); /* bit of a misnomer in this case; size of replacement instruction. */
3941 pPatch->flags |= PATMFL_INT3_REPLACEMENT;
3944 rc = patmActivateInt3Patch(pVM, pPatch);
3949 pPatch->pInstrGCLowest = pInstrGC;
3950 pPatch->pInstrGCHighest = pInstrGC + pCpu->cbInstr;
3952 pPatch->uState = PATCH_ENABLED;
3976 PPATCHINFO pPatch = &pPatchRec->patch;
3979 pPatch->pPatchBlockOffset = 0; /* doesn't use patch memory */
3980 pPatch->uCurPatchOffset = 0;
3981 pPatch->cbPatchBlockSize = 0;
3982 pPatch->flags |= PATMFL_SINGLE_INSTRUCTION;
4007 Assert(pPatch->flags & PATMFL_JUMP_CONFLICT);
4031 Assert(pCpu->cbInstr <= sizeof(pPatch->aPrivInstr));
4033 pPatch->cbPatchJump = pCpu->cbInstr;
4035 rc = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), pPatch->aPrivInstr, pPatch->pPrivInstrGC, pPatch->cbPatchJump);
4046 pPatch->pPatchJumpDestGC = pJmpDest;
4050 cacheRec.pPatch = pPatch;
4052 rc = patmGenJumpToPatch(pVM, pPatch, &cacherec, true);
4063 pPatch->flags |= PATMFL_MUST_INSTALL_PATCHJMP;
4065 PATM_LOG_ORG_PATCH_INSTR(pVM, pPatch, patmGetInstructionString(pPatch->opcode, pPatch->flags));
4066 Log(("Successfully installed %s patch at %RRv\n", patmGetInstructionString(pPatch->opcode, pPatch->flags), pInstrGC));
4071 pPatch->pInstrGCLowest = pInstrGC;
4072 pPatch->pInstrGCHighest = pInstrGC + pPatch->cbPatchJump;
4074 pPatch->uState = PATCH_ENABLED;
4079 pPatch->uState = PATCH_REFUSED;
4378 cacheRec.pPatch = &pPatchRec->patch;
4607 * @param pPatch Patch record
4610 static uint32_t patmGetInstrSize(PVM pVM, PPATCHINFO pPatch, RTRCPTR pInstrGC)
4622 disret = patmR3DisInstr(pVM, pPatch, pInstrGC, pInstrHC, PATMREAD_ORGCODE | PATMREAD_NOCHECK, &cpu, &cbInstr);
4636 * @param pPatch Patch record
4638 int patmAddPatchToPage(PVM pVM, RTRCUINTPTR pPage, PPATCHINFO pPatch)
4643 Log(("patmAddPatchToPage: insert patch %RHv to page %RRv\n", pPatch, pPage));
4665 pPatchPage->papPatch[pPatchPage->cCount] = pPatch;
4690 pPatchPage->papPatch[0] = pPatch;
4701 PRECGUESTTOPATCH pGuestToPatchRec = (PRECGUESTTOPATCH)RTAvlU32GetBestFit(&pPatch->Guest2PatchAddrTree, pPage, true);
4720 pGuestToPatchRec = (PRECGUESTTOPATCH)RTAvlU32GetBestFit(&pPatch->Guest2PatchAddrTree, pPage-1, false);
4724 uint32_t size = patmGetInstrSize(pVM, pPatch, (RTRCPTR)pGuestToPatchRec->Core.Key);
4736 pGuestToPatchRec = (PRECGUESTTOPATCH)RTAvlU32GetBestFit(&pPatch->Guest2PatchAddrTree, pPage+PAGE_SIZE-1, false);
4746 uint32_t size = patmGetInstrSize(pVM, pPatch, pPatchPage->pHighestAddrGC);
4762 * @param pPatch Patch record
4764 int patmRemovePatchFromPage(PVM pVM, RTRCUINTPTR pPage, PPATCHINFO pPatch)
4777 Log(("patmRemovePatchPage: remove patch %RHv from page %RRv\n", pPatch, pPage));
4785 if (pPatchPage->papPatch[i] == pPatch)
4795 AssertMsgFailed(("Unable to find patch %RHv in page %RRv\n", pPatch, pPage));
4822 * @param pPatch Patch record
4824 int patmInsertPatchPages(PVM pVM, PPATCHINFO pPatch)
4830 pPatchPageStart = (RTRCUINTPTR)pPatch->pInstrGCLowest & PAGE_BASE_GC_MASK;
4831 pPatchPageEnd = (RTRCUINTPTR)pPatch->pInstrGCHighest & PAGE_BASE_GC_MASK;
4837 PRECGUESTTOPATCH pGuestToPatchRec = (PRECGUESTTOPATCH)RTAvlU32GetBestFit(&pPatch->Guest2PatchAddrTree, pPage, true);
4843 rc = patmAddPatchToPage(pVM, pPage, pPatch);
4847 pPatch->flags |= PATMFL_CODE_MONITORED;
4856 * @param pPatch Patch record
4858 static int patmRemovePatchPages(PVM pVM, PPATCHINFO pPatch)
4864 pPatchPageStart = (RTRCUINTPTR)pPatch->pInstrGCLowest & PAGE_BASE_GC_MASK;
4865 pPatchPageEnd = (RTRCUINTPTR)pPatch->pInstrGCHighest & PAGE_BASE_GC_MASK;
4870 PRECGUESTTOPATCH pGuestToPatchRec = (PRECGUESTTOPATCH)RTAvlU32GetBestFit(&pPatch->Guest2PatchAddrTree, pPage, true);
4876 rc = patmRemovePatchFromPage(pVM, pPage, pPatch);
4880 pPatch->flags &= ~PATMFL_CODE_MONITORED;
4933 PPATCHINFO pPatch = pPatchPage->papPatch[i];
4943 if ( pPatch->cbPatchJump
4944 && pGuestPtrGC >= pPatch->pPrivInstrGC
4945 && pGuestPtrGC < pPatch->pPrivInstrGC + pPatch->cbPatchJump)
4949 int rc = PATMR3RemovePatch(pVM, pPatch->pPrivInstrGC);
4958 pPatchInstrGC = patmGuestGCPtrToPatchGCPtr(pVM, pPatch, pGuestPtrGC);
4964 pPatchInstrGC = patmGuestGCPtrToClosestPatchGCPtr(pVM, pPatch, pGuestPtrGC);
4967 pClosestInstrGC = patmPatchGCPtr2GuestGCPtr(pVM, pPatch, pPatchInstrGC);
4969 size = patmGetInstrSize(pVM, pPatch, pClosestInstrGC);
4981 PRECPATCHTOGUEST pPatchToGuestRec = (PRECPATCHTOGUEST)RTAvlU32Get(&pPatch->Patch2GuestAddrTree, PatchOffset);
4987 if (++pPatch->cCodeWrites > PATM_MAX_CODE_WRITES)
4989 LogRel(("PATM: Disable block at %RRv - write %RRv-%RRv\n", pPatch->pPrivInstrGC, pGuestPtrGC, pGuestPtrGC+cbWrite));
4991 patmR3MarkDirtyPatch(pVM, pPatch);
5028 PPATCHINFO pPatch = pPatchPage->papPatch[i];
5030 if (pPatch->cInvalidWrites > PATM_MAX_INVALID_WRITES)
5033 if (pPatch->flags & PATMFL_IDTHANDLER)
5035 LogRel(("PATM: Stop monitoring IDT handler pages at %RRv - invalid write %RRv-%RRv (this is not a fatal error)\n", pPatch->pPrivInstrGC, GCPtr, GCPtr+cbWrite));
5037 Assert(pPatch->flags & PATMFL_CODE_MONITORED);
5038 int rc = patmRemovePatchPages(pVM, pPatch);
5043 LogRel(("PATM: Disable block at %RRv - invalid write %RRv-%RRv \n", pPatch->pPrivInstrGC, GCPtr, GCPtr+cbWrite));
5044 patmR3MarkDirtyPatch(pVM, pPatch);
5084 PPATCHINFO pPatch = pPatchPage->papPatch[i];
5086 Log(("PATMR3FlushPage %RRv remove patch at %RRv\n", addr, pPatch->pPrivInstrGC));
5087 patmR3MarkDirtyPatch(pVM, pPatch);
5228 PPATCHINFO pPatch;
5237 pPatch = &pPatchRec->patch;
5240 if (pPatch->uState == PATCH_DISABLED)
5246 if (pPatch->flags & PATMFL_IDTHANDLER)
5250 iGate = TRPMR3QueryGateByHandler(pVM, PATCHCODE_PTR_GC(pPatch));
5260 if ( pPatch->pPatchBlockOffset
5261 && pPatch->uState == PATCH_ENABLED)
5263 Log(("Invalidate patch at %RRv (HC=%RRv)\n", PATCHCODE_PTR_GC(pPatch), PATCHCODE_PTR_HC(pPatch)));
5264 pPatch->bDirtyOpcode = *PATCHCODE_PTR_HC(pPatch);
5265 *PATCHCODE_PTR_HC(pPatch) = 0xCC;
5269 if (pPatch->flags & PATMFL_PATCHED_GUEST_CODE)
5271 Assert(pPatch->flags & PATMFL_MUST_INSTALL_PATCHJMP);
5272 Assert(!(pPatch->flags & (PATMFL_DUPLICATE_FUNCTION|PATMFL_IDTHANDLER|PATMFL_TRAMPOLINE|PATMFL_INT3_REPLACEMENT|PATMFL_INT3_REPLACEMENT_BLOCK)));
5274 if (pPatch->uState != PATCH_REFUSED)
5278 Assert(pPatch->cbPatchJump < sizeof(temp));
5281 rc = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), temp, pPatch->pPrivInstrGC, pPatch->cbPatchJump);
5285 RTRCINTPTR displ = (RTRCUINTPTR)PATCHCODE_PTR_GC(pPatch) - ((RTRCUINTPTR)pPatch->pPrivInstrGC + SIZEOF_NEARJUMP32);
5294 pPatch->uState = PATCH_DISABLED; /* don't call PATMR3DisablePatch again */
5299 patmRemoveJumpToPatch(pVM, pPatch);
5304 pPatch->uState = PATCH_DISABLE_PENDING;
5314 if (pPatch->flags & (PATMFL_INT3_REPLACEMENT|PATMFL_INT3_REPLACEMENT_BLOCK))
5318 Assert(pPatch->cbPatchJump < sizeof(temp));
5321 rc = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), temp, pPatch->pPrivInstrGC, pPatch->cbPatchJump);
5330 pPatch->uState = PATCH_DISABLED; /* don't call PATMR3DisablePatch again */
5335 patmDeactivateInt3Patch(pVM, pPatch);
5342 if (pPatch->uState == PATCH_DISABLE_PENDING)
5345 pPatch->uState = PATCH_UNUSABLE;
5348 if (pPatch->uState != PATCH_DIRTY)
5350 pPatch->uOldState = pPatch->uState;
5351 pPatch->uState = PATCH_DISABLED;
5475 PPATCHINFO pPatch;
5484 pPatch = &pPatchRec->patch;
5486 if (pPatch->uState == PATCH_DISABLED)
5488 if (pPatch->flags & PATMFL_MUST_INSTALL_PATCHJMP)
5490 Assert(!(pPatch->flags & PATMFL_PATCHED_GUEST_CODE));
5493 Assert(pPatch->cbPatchJump < sizeof(temp));
5496 int rc2 = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), temp, pPatch->pPrivInstrGC, pPatch->cbPatchJump);
5500 if (memcmp(temp, pPatch->aPrivInstr, pPatch->cbPatchJump))
5512 cacheRec.pPatch = pPatch;
5514 rc2 = patmGenJumpToPatch(pVM, pPatch, &cacheRec, false);
5532 while(i < pPatch->cbPatchJump)
5534 disret = patmR3DisInstrToStr(pVM, pPatch, pPatch->pPrivInstrGC + i, NULL, PATMREAD_ORGCODE,
5544 if (pPatch->flags & (PATMFL_INT3_REPLACEMENT|PATMFL_INT3_REPLACEMENT_BLOCK))
5548 Assert(pPatch->cbPatchJump < sizeof(temp));
5551 int rc2 = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), temp, pPatch->pPrivInstrGC, pPatch->cbPatchJump);
5554 if (memcmp(temp, pPatch->aPrivInstr, pPatch->cbPatchJump))
5563 rc2 = patmActivateInt3Patch(pVM, pPatch);
5568 pPatch->uState = pPatch->uOldState; //restore state
5571 if (pPatch->pPatchBlockOffset)
5572 *PATCHCODE_PTR_HC(pPatch) = pPatch->bDirtyOpcode;
5577 Log(("PATMR3EnablePatch: Unable to enable patch %RRv with state %d\n", pInstrGC, pPatch->uState));
5594 PPATCHINFO pPatch;
5596 pPatch = &pPatchRec->patch;
5599 if (!fForceRemove && (pPatch->flags & (PATMFL_DUPLICATE_FUNCTION|PATMFL_CODE_REFERENCED)))
5601 Log(("PATMRemovePatch %RRv REFUSED!\n", pPatch->pPrivInstrGC));
5604 Log(("PATMRemovePatch %RRv\n", pPatch->pPrivInstrGC));
5632 patmEmptyTreeU32(pVM, &pPatch->Patch2GuestAddrTree);
5633 pPatch->nrPatch2GuestRecs = 0;
5634 Assert(pPatch->Patch2GuestAddrTree == 0);
5636 patmEmptyTree(pVM, &pPatch->FixupTree);
5637 pPatch->nrFixups = 0;
5638 Assert(pPatch->FixupTree == 0);
5700 PPATCHINFO pPatch;
5707 pPatch = &pPatchRec->patch;
5708 AssertReturn(pPatch->flags & (PATMFL_DUPLICATE_FUNCTION|PATMFL_IDTHANDLER|PATMFL_TRAPHANDLER), VERR_PATCHING_REFUSED);
5709 if (pPatch->flags & PATMFL_EXTERNAL_JUMP_INSIDE)
5711 if (!pPatch->pTrampolinePatchesHead)
5726 pTrampolinePatchesHead = pPatch->pTrampolinePatchesHead;
5747 rc = PATMR3InstallPatch(pVM, pInstrGC, pPatch->flags & (PATMFL_CODE32|PATMFL_IDTHANDLER|PATMFL_INTHANDLER|PATMFL_TRAPHANDLER|PATMFL_DUPLICATE_FUNCTION|PATMFL_TRAPHANDLER_WITH_ERRORCODE|PATMFL_IDTHANDLER_WITHOUT_ENTRYPOINT));
5763 pPatch->uCurPatchOffset = 0;
5766 rc = patmPatchGenPatchJump(pVM, pPatch, pInstrGC, pPatchTargetGC, false /* no lookup record */);
5890 PPATCHINFO pPatch;
5901 pPatch = patmFindActivePatchByEntrypoint(pVM, pAddr);
5902 if (pPatch)
5903 *pPatchAddr = pPatch->pPrivInstrGC;
5941 * @param pPatch Patch record
5946 static int patmR3MarkDirtyPatch(PVM pVM, PPATCHINFO pPatch)
5948 if (pPatch->pPatchBlockOffset)
5950 Log(("Invalidate patch at %RRv (HC=%RRv)\n", PATCHCODE_PTR_GC(pPatch), PATCHCODE_PTR_HC(pPatch)));
5951 pPatch->bDirtyOpcode = *PATCHCODE_PTR_HC(pPatch);
5952 *PATCHCODE_PTR_HC(pPatch) = 0xCC;
5957 int rc = PATMR3DisablePatch(pVM, pPatch->pPrivInstrGC);
5965 if (pPatch->flags & PATMFL_CODE_MONITORED)
5967 rc = patmRemovePatchPages(pVM, pPatch);
5970 pPatch->uState = PATCH_DIRTY;
5983 * @param pPatch Patch block structure pointer
5986 RTRCPTR patmPatchGCPtr2GuestGCPtr(PVM pVM, PPATCHINFO pPatch, RCPTRTYPE(uint8_t *) pPatchGC)
5988 Assert(pPatch->Patch2GuestAddrTree);
5990 PRECPATCHTOGUEST pPatchToGuestRec = (PRECPATCHTOGUEST)RTAvlU32GetBestFit(&pPatch->Patch2GuestAddrTree, pPatchGC - pVM->patm.s.pPatchMemGC, false);
6002 * @param pPatch Current patch block pointer
6006 RTRCPTR patmGuestGCPtrToPatchGCPtr(PVM pVM, PPATCHINFO pPatch, RCPTRTYPE(uint8_t*) pInstrGC)
6008 if (pPatch->Guest2PatchAddrTree)
6010 PRECGUESTTOPATCH pGuestToPatchRec = (PRECGUESTTOPATCH)RTAvlU32Get(&pPatch->Guest2PatchAddrTree, pInstrGC);
6039 * @param pPatch Current patch block pointer
6043 RTRCPTR patmGuestGCPtrToClosestPatchGCPtr(PVM pVM, PPATCHINFO pPatch, RCPTRTYPE(uint8_t*) pInstrGC)
6045 PRECGUESTTOPATCH pGuestToPatchRec = (PRECGUESTTOPATCH)RTAvlU32GetBestFit(&pPatch->Guest2PatchAddrTree, pInstrGC, false);
6147 * @param pPatch Patch record.
6151 static int patmR3HandleDirtyInstr(PVM pVM, PCPUMCTX pCtx, PPATMPATCHREC pPatch, PRECPATCHTOGUEST pPatchToGuestRec, RTRCPTR pEip)
6206 patmr3RemoveP2GLookupRecord(pVM, &pPatch->patch, pCurPatchInstrGC);
6213 pRec = (PRECPATCHTOGUEST)RTAvlU32GetBestFit(&pPatch->patch.Patch2GuestAddrTree, pCurPatchInstrGC - pVM->patm.s.pPatchMemGC, true);
6271 patmR3AddP2GLookupRecord(pVM, &pPatch->patch, pCurPatchInstrHC, pCurInstrGC, PATM_LOOKUP_BOTHDIR);
6282 patmR3AddP2GLookupRecord(pVM, &pPatch->patch, pCurPatchInstrHC, pCurInstrGC, PATM_LOOKUP_BOTHDIR);
6297 if (RTAvlU32Get(&pPatch->patch.Patch2GuestAddrTree, pCurPatchInstrGC - pVM->patm.s.pPatchMemGC) == NULL)
6299 pRec = (PRECPATCHTOGUEST)RTAvlU32GetBestFit(&pPatch->patch.Patch2GuestAddrTree, pCurPatchInstrGC - pVM->patm.s.pPatchMemGC, true);
6354 && (pPatch->patch.flags & (PATMFL_DUPLICATE_FUNCTION|PATMFL_IDTHANDLER|PATMFL_TRAPHANDLER)))
6356 rc = patmR3RefreshPatch(pVM, pPatch);
6359 LogRel(("PATM: Failed to refresh dirty patch at %RRv. Disabling it.\n", pPatch->patch.pPrivInstrGC));
6379 PPATMPATCHREC pPatch = 0;
6401 pPatch = PATM_PATCHREC_FROM_COREOFFSET(pvPatchCoreOffset);
6403 Assert(offset >= pPatch->patch.pPatchBlockOffset && offset < pPatch->patch.pPatchBlockOffset + pPatch->patch.cbPatchBlockSize);
6405 if (pPatch->patch.uState == PATCH_DIRTY)
6408 if (pPatch->patch.flags & (PATMFL_DUPLICATE_FUNCTION|PATMFL_CODE_REFERENCED))
6415 if (pPatch->patch.uState == PATCH_DISABLED)
6418 if (pPatch->patch.flags & (PATMFL_DUPLICATE_FUNCTION|PATMFL_CODE_REFERENCED))
6425 if (pPatch->patch.uState == PATCH_DISABLE_PENDING)
6427 RTRCPTR pPrivInstrGC = pPatch->patch.pPrivInstrGC;
6429 Log(("PATMR3HandleTrap: disable operation is pending for patch at %RRv\n", pPatch->patch.pPrivInstrGC));
6430 rc = PATMR3DisablePatch(pVM, pPatch->patch.pPrivInstrGC);
6432 AssertMsg(pPatch->patch.uState == PATCH_DISABLED || pPatch->patch.uState == PATCH_UNUSABLE, ("Unexpected failure to disable patch state=%d rc=%Rrc\n", pPatch->patch.uState, rc));
6435 pPatchToGuestRec = (PRECPATCHTOGUEST)RTAvlU32GetBestFit(&pPatch->patch.Patch2GuestAddrTree, offset, false);
6439 pPatch->patch.cTraps++;
6440 PATM_STAT_FAULT_INC(&pPatch->patch);
6500 if (pPatch->patch.pPrivInstrGC == pNewEip)
6522 if (pPatch)
6526 pEip, pNewEip, CPUMGetGuestESP(pVCpu), pPatch->patch.uState, pPatch->patch.flags,
6549 rc = patmR3HandleDirtyInstr(pVM, pCtx, pPatch, pPatchToGuestRec, pEip);
6570 if (pPatch->patch.flags & PATMFL_DUPLICATE_FUNCTION)
6577 cacheRec.pPatch = &pPatch->patch;
6579 disret = patmR3DisInstr(pVM, &pPatch->patch, pNewEip, patmR3GCVirtToHCVirt(pVM, &cacheRec, pNewEip), PATMREAD_RAWCODE,
6616 cacheRec.pPatch = &pPatch->patch;
6618 disret = patmR3DisInstr(pVM, &pPatch->patch, pNewEip, patmR3GCVirtToHCVirt(pVM, &cacheRec, pNewEip), PATMREAD_ORGCODE,
6625 disret = patmR3DisInstr(pVM, &pPatch->patch, pNewEip, patmR3GCVirtToHCVirt(pVM, &cacheRec, pNewEip), PATMREAD_RAWCODE,
6637 Log2(("pPatchBlockGC %RRv - pEip %RRv corresponding GC address %RRv\n", PATCHCODE_PTR_GC(&pPatch->patch), pEip, pNewEip));
6639 if (pNewEip >= pPatch->patch.pPrivInstrGC && pNewEip < pPatch->patch.pPrivInstrGC + pPatch->patch.cbPatchJump)
6642 Log(("Disabling patch at location %RRv due to trap too close to the privileged instruction \n", pPatch->patch.pPrivInstrGC));
6643 PATMR3DisablePatch(pVM, pPatch->patch.pPrivInstrGC);
6650 if (pPatch->patch.cTraps > MAX_PATCH_TRAPS)
6652 Log(("Disabling patch at location %RRv due to too many traps inside patch code\n", pPatch->patch.pPrivInstrGC));
6654 PATMR3DisablePatch(pVM, pPatch->patch.pPrivInstrGC);
6721 static const char *PATMPatchType(PVM pVM, PPATCHINFO pPatch)
6723 if (pPatch->flags & PATMFL_SYSENTER)
6728 if (pPatch->flags & (PATMFL_TRAPHANDLER|PATMFL_INTHANDLER))
6733 iGate = TRPMR3QueryGateByHandler(pVM, PATCHCODE_PTR_GC(pPatch));
6735 RTStrPrintf(szTrap, sizeof(szTrap), (pPatch->flags & PATMFL_INTHANDLER) ? "INT-%2X" : "TRAP-%2X", iGate);
6737 RTStrPrintf(szTrap, sizeof(szTrap), (pPatch->flags & PATMFL_INTHANDLER) ? "INT-??" : "TRAP-??");
6741 if (pPatch->flags & (PATMFL_DUPLICATE_FUNCTION))
6744 if (pPatch->flags & PATMFL_REPLACE_FUNCTION_CALL)
6747 if (pPatch->flags & PATMFL_TRAMPOLINE)
6750 return patmGetInstructionString(pPatch->opcode, pPatch->flags);
6753 static const char *PATMPatchState(PVM pVM, PPATCHINFO pPatch)
6756 switch(pPatch->uState)
6783 PPATCHINFO pPatch = (PPATCHINFO)pvSample;
6784 Assert(pPatch);
6786 pVM->patm.s.pStatsHC[pPatch->uPatchIdx].u32A = 0;
6787 pVM->patm.s.pStatsHC[pPatch->uPatchIdx].u32B = 0;
6800 PPATCHINFO pPatch = (PPATCHINFO)pvSample;
6801 Assert(pPatch);
6803 Assert(pPatch->uState != PATCH_REFUSED);
6804 Assert(!(pPatch->flags & (PATMFL_REPLACE_FUNCTION_CALL|PATMFL_MMIO_ACCESS)));
6807 pPatch->cbPatchBlockSize, PATMPatchState(pVM, pPatch), PATMPatchType(pVM, pPatch),
6808 pVM->patm.s.pStatsHC[pPatch->uPatchIdx].u32A, pVM->patm.s.pStatsHC[pPatch->uPatchIdx].u32B);
6816 * @param pPatch Patch structure
6818 RTRCPTR patmPatchQueryStatAddress(PVM pVM, PPATCHINFO pPatch)
6820 Assert(pPatch->uPatchIdx != PATM_STAT_INDEX_NONE);
6821 return pVM->patm.s.pStatsGC + sizeof(STAMRATIOU32) * pPatch->uPatchIdx + RT_OFFSETOF(STAMRATIOU32, u32A);