VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/PATMAll.cpp@ 45707

Last change on this file since 45707 was 45628, checked in by vboxsync, 12 years ago

VMM: build fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 20.9 KB
Line 
1/* $Id: PATMAll.cpp 45628 2013-04-19 07:13:55Z vboxsync $ */
2/** @file
3 * PATM - The Patch Manager, all contexts.
4 */
5
6/*
7 * Copyright (C) 2006-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_PATM
22#include <VBox/vmm/patm.h>
23#include <VBox/vmm/cpum.h>
24#include <VBox/vmm/em.h>
25#include <VBox/vmm/hm.h>
26#include <VBox/vmm/selm.h>
27#include <VBox/vmm/mm.h>
28#include "PATMInternal.h"
29#include <VBox/vmm/vm.h>
30#include <VBox/vmm/vmm.h>
31#include "PATMA.h"
32
33#include <VBox/dis.h>
34#include <VBox/disopcode.h>
35#include <VBox/err.h>
36#include <VBox/log.h>
37#include <iprt/assert.h>
38
39
40/**
41 * Load virtualized flags.
42 *
43 * This function is called from CPUMRawEnter(). It doesn't have to update the
44 * IF and IOPL eflags bits, the caller will enforce those to set and 0 respectively.
45 *
46 * @param pVM Pointer to the VM.
47 * @param pCtxCore The cpu context core.
48 * @see pg_raw
49 */
50VMM_INT_DECL(void) PATMRawEnter(PVM pVM, PCPUMCTXCORE pCtxCore)
51{
52 bool fPatchCode = PATMIsPatchGCAddr(pVM, pCtxCore->eip);
53 Assert(!HMIsEnabled(pVM));
54
55 /*
56 * Currently we don't bother to check whether PATM is enabled or not.
57 * For all cases where it isn't, IOPL will be safe and IF will be set.
58 */
59 register uint32_t efl = pCtxCore->eflags.u32;
60 CTXSUFF(pVM->patm.s.pGCState)->uVMFlags = efl & PATM_VIRTUAL_FLAGS_MASK;
61 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));
62
63 AssertReleaseMsg(CTXSUFF(pVM->patm.s.pGCState)->fPIF || fPatchCode, ("fPIF=%d eip=%RRv\n", CTXSUFF(pVM->patm.s.pGCState)->fPIF, pCtxCore->eip));
64
65 efl &= ~PATM_VIRTUAL_FLAGS_MASK;
66 efl |= X86_EFL_IF;
67 pCtxCore->eflags.u32 = efl;
68
69#ifdef IN_RING3
70#ifdef PATM_EMULATE_SYSENTER
71 PCPUMCTX pCtx;
72
73 /* Check if the sysenter handler has changed. */
74 pCtx = CPUMQueryGuestCtxPtr(pVM);
75 if ( pCtx->SysEnter.cs != 0
76 && pCtx->SysEnter.eip != 0
77 )
78 {
79 if (pVM->patm.s.pfnSysEnterGC != (RTRCPTR)pCtx->SysEnter.eip)
80 {
81 pVM->patm.s.pfnSysEnterPatchGC = 0;
82 pVM->patm.s.pfnSysEnterGC = 0;
83
84 Log2(("PATMRawEnter: installing sysenter patch for %RRv\n", pCtx->SysEnter.eip));
85 pVM->patm.s.pfnSysEnterPatchGC = PATMR3QueryPatchGCPtr(pVM, pCtx->SysEnter.eip);
86 if (pVM->patm.s.pfnSysEnterPatchGC == 0)
87 {
88 rc = PATMR3InstallPatch(pVM, pCtx->SysEnter.eip, PATMFL_SYSENTER | PATMFL_CODE32);
89 if (rc == VINF_SUCCESS)
90 {
91 pVM->patm.s.pfnSysEnterPatchGC = PATMR3QueryPatchGCPtr(pVM, pCtx->SysEnter.eip);
92 pVM->patm.s.pfnSysEnterGC = (RTRCPTR)pCtx->SysEnter.eip;
93 Assert(pVM->patm.s.pfnSysEnterPatchGC);
94 }
95 }
96 else
97 pVM->patm.s.pfnSysEnterGC = (RTRCPTR)pCtx->SysEnter.eip;
98 }
99 }
100 else
101 {
102 pVM->patm.s.pfnSysEnterPatchGC = 0;
103 pVM->patm.s.pfnSysEnterGC = 0;
104 }
105#endif
106#endif
107}
108
109
110/**
111 * Restores virtualized flags.
112 *
113 * This function is called from CPUMRawLeave(). It will update the eflags register.
114 *
115 ** @note Only here we are allowed to switch back to guest code (without a special reason such as a trap in patch code)!!
116 *
117 * @param pVM Pointer to the VM.
118 * @param pCtxCore The cpu context core.
119 * @param rawRC Raw mode return code
120 * @see @ref pg_raw
121 */
122VMM_INT_DECL(void) PATMRawLeave(PVM pVM, PCPUMCTXCORE pCtxCore, int rawRC)
123{
124 Assert(!HMIsEnabled(pVM));
125 bool fPatchCode = PATMIsPatchGCAddr(pVM, pCtxCore->eip);
126 /*
127 * We will only be called if PATMRawEnter was previously called.
128 */
129 register uint32_t efl = pCtxCore->eflags.u32;
130 efl = (efl & ~PATM_VIRTUAL_FLAGS_MASK) | (CTXSUFF(pVM->patm.s.pGCState)->uVMFlags & PATM_VIRTUAL_FLAGS_MASK);
131 pCtxCore->eflags.u32 = efl;
132 CTXSUFF(pVM->patm.s.pGCState)->uVMFlags = X86_EFL_IF;
133
134 AssertReleaseMsg((efl & X86_EFL_IF) || fPatchCode || rawRC == VINF_PATM_PENDING_IRQ_AFTER_IRET || RT_FAILURE(rawRC), ("Inconsistent state at %RRv rc=%Rrc\n", pCtxCore->eip, rawRC));
135 AssertReleaseMsg(CTXSUFF(pVM->patm.s.pGCState)->fPIF || fPatchCode || RT_FAILURE(rawRC), ("fPIF=%d eip=%RRv rc=%Rrc\n", CTXSUFF(pVM->patm.s.pGCState)->fPIF, pCtxCore->eip, rawRC));
136
137#ifdef IN_RING3
138 if ( (efl & X86_EFL_IF)
139 && fPatchCode
140 )
141 {
142 if ( rawRC < VINF_PATM_LEAVE_RC_FIRST
143 || rawRC > VINF_PATM_LEAVE_RC_LAST)
144 {
145 /*
146 * Golden rules:
147 * - Don't interrupt special patch streams that replace special instructions
148 * - Don't break instruction fusing (sti, pop ss, mov ss)
149 * - Don't go back to an instruction that has been overwritten by a patch jump
150 * - Don't interrupt an idt handler on entry (1st instruction); technically incorrect
151 *
152 */
153 if (CTXSUFF(pVM->patm.s.pGCState)->fPIF == 1) /* consistent patch instruction state */
154 {
155 PATMTRANSSTATE enmState;
156 RTRCPTR pOrgInstrGC = PATMR3PatchToGCPtr(pVM, pCtxCore->eip, &enmState);
157
158 AssertRelease(pOrgInstrGC);
159
160 Assert(enmState != PATMTRANS_OVERWRITTEN);
161 if (enmState == PATMTRANS_SAFE)
162 {
163 Assert(!patmFindActivePatchByEntrypoint(pVM, pOrgInstrGC));
164 Log(("Switchback from %RRv to %RRv (Psp=%x)\n", pCtxCore->eip, pOrgInstrGC, CTXSUFF(pVM->patm.s.pGCState)->Psp));
165 STAM_COUNTER_INC(&pVM->patm.s.StatSwitchBack);
166 pCtxCore->eip = pOrgInstrGC;
167 fPatchCode = false; /* to reset the stack ptr */
168
169 CTXSUFF(pVM->patm.s.pGCState)->GCPtrInhibitInterrupts = 0; /* reset this pointer; safe otherwise the state would be PATMTRANS_INHIBITIRQ */
170 }
171 else
172 {
173 LogFlow(("Patch address %RRv can't be interrupted (state=%d)!\n", pCtxCore->eip, enmState));
174 STAM_COUNTER_INC(&pVM->patm.s.StatSwitchBackFail);
175 }
176 }
177 else
178 {
179 LogFlow(("Patch address %RRv can't be interrupted (fPIF=%d)!\n", pCtxCore->eip, CTXSUFF(pVM->patm.s.pGCState)->fPIF));
180 STAM_COUNTER_INC(&pVM->patm.s.StatSwitchBackFail);
181 }
182 }
183 }
184#else /* !IN_RING3 */
185 AssertMsgFailed(("!IN_RING3"));
186#endif /* !IN_RING3 */
187
188 if (!fPatchCode)
189 {
190 if (CTXSUFF(pVM->patm.s.pGCState)->GCPtrInhibitInterrupts == (RTRCPTR)pCtxCore->eip)
191 {
192 EMSetInhibitInterruptsPC(VMMGetCpu0(pVM), pCtxCore->eip);
193 }
194 CTXSUFF(pVM->patm.s.pGCState)->GCPtrInhibitInterrupts = 0;
195
196 /* Reset the stack pointer to the top of the stack. */
197#ifdef DEBUG
198 if (CTXSUFF(pVM->patm.s.pGCState)->Psp != PATM_STACK_SIZE)
199 {
200 LogFlow(("PATMRawLeave: Reset PATM stack (Psp = %x)\n", CTXSUFF(pVM->patm.s.pGCState)->Psp));
201 }
202#endif
203 CTXSUFF(pVM->patm.s.pGCState)->Psp = PATM_STACK_SIZE;
204 }
205}
206
207/**
208 * Get the EFLAGS.
209 * This is a worker for CPUMRawGetEFlags().
210 *
211 * @returns The eflags.
212 * @param pVM Pointer to the VM.
213 * @param pCtxCore The context core.
214 */
215VMM_INT_DECL(uint32_t) PATMRawGetEFlags(PVM pVM, PCCPUMCTXCORE pCtxCore)
216{
217 Assert(!HMIsEnabled(pVM));
218 uint32_t efl = pCtxCore->eflags.u32;
219 efl &= ~PATM_VIRTUAL_FLAGS_MASK;
220 efl |= pVM->patm.s.CTXSUFF(pGCState)->uVMFlags & PATM_VIRTUAL_FLAGS_MASK;
221 return efl;
222}
223
224/**
225 * Updates the EFLAGS.
226 * This is a worker for CPUMRawSetEFlags().
227 *
228 * @param pVM Pointer to the VM.
229 * @param pCtxCore The context core.
230 * @param efl The new EFLAGS value.
231 */
232VMM_INT_DECL(void) PATMRawSetEFlags(PVM pVM, PCPUMCTXCORE pCtxCore, uint32_t efl)
233{
234 Assert(!HMIsEnabled(pVM));
235 pVM->patm.s.CTXSUFF(pGCState)->uVMFlags = efl & PATM_VIRTUAL_FLAGS_MASK;
236 efl &= ~PATM_VIRTUAL_FLAGS_MASK;
237 efl |= X86_EFL_IF;
238 pCtxCore->eflags.u32 = efl;
239}
240
241/**
242 * Check if we must use raw mode (patch code being executed)
243 *
244 * @param pVM Pointer to the VM.
245 * @param pAddrGC Guest context address
246 */
247VMM_INT_DECL(bool) PATMShouldUseRawMode(PVM pVM, RTRCPTR pAddrGC)
248{
249 return ( PATMIsEnabled(pVM)
250 && ((pAddrGC >= (RTRCPTR)pVM->patm.s.pPatchMemGC && pAddrGC < (RTRCPTR)((RTRCUINTPTR)pVM->patm.s.pPatchMemGC + pVM->patm.s.cbPatchMem)))) ? true : false;
251}
252
253/**
254 * Returns the guest context pointer and size of the GC context structure
255 *
256 * @returns VBox status code.
257 * @param pVM Pointer to the VM.
258 */
259VMM_INT_DECL(RCPTRTYPE(PPATMGCSTATE)) PATMGetGCState(PVM pVM)
260{
261 AssertReturn(!HMIsEnabled(pVM), NIL_RTRCPTR);
262 return pVM->patm.s.pGCStateGC;
263}
264
265/**
266 * Checks whether the GC address is part of our patch region
267 *
268 * @returns VBox status code.
269 * @param pVM Pointer to the VM.
270 * @param pAddrGC Guest context address
271 * @internal
272 */
273VMMDECL(bool) PATMIsPatchGCAddr(PVM pVM, RTRCUINTPTR pAddrGC)
274{
275 return (PATMIsEnabled(pVM) && pAddrGC - (RTRCUINTPTR)pVM->patm.s.pPatchMemGC < pVM->patm.s.cbPatchMem) ? true : false;
276}
277
278/**
279 * Set parameters for pending MMIO patch operation
280 *
281 * @returns VBox status code.
282 * @param pDevIns Device instance.
283 * @param GCPhys MMIO physical address
284 * @param pCachedData GC pointer to cached data
285 */
286VMM_INT_DECL(int) PATMSetMMIOPatchInfo(PVM pVM, RTGCPHYS GCPhys, RTRCPTR pCachedData)
287{
288 if (!HMIsEnabled(pVM))
289 {
290 pVM->patm.s.mmio.GCPhys = GCPhys;
291 pVM->patm.s.mmio.pCachedData = (RTRCPTR)pCachedData;
292 }
293
294 return VINF_SUCCESS;
295}
296
297/**
298 * Checks if the interrupt flag is enabled or not.
299 *
300 * @returns true if it's enabled.
301 * @returns false if it's disabled.
302 *
303 * @param pVM Pointer to the VM.
304 * @todo CPUM should wrap this, EM.cpp shouldn't call us.
305 */
306VMM_INT_DECL(bool) PATMAreInterruptsEnabled(PVM pVM)
307{
308 PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(VMMGetCpu(pVM));
309
310 return PATMAreInterruptsEnabledByCtxCore(pVM, CPUMCTX2CORE(pCtx));
311}
312
313/**
314 * Checks if the interrupt flag is enabled or not.
315 *
316 * @returns true if it's enabled.
317 * @returns false if it's disabled.
318 *
319 * @param pVM Pointer to the VM.
320 * @param pCtxCore CPU context
321 * @todo CPUM should wrap this, EM.cpp shouldn't call us.
322 */
323VMM_INT_DECL(bool) PATMAreInterruptsEnabledByCtxCore(PVM pVM, PCPUMCTXCORE pCtxCore)
324{
325 if (PATMIsEnabled(pVM))
326 {
327 Assert(!HMIsEnabled(pVM));
328 if (PATMIsPatchGCAddr(pVM, pCtxCore->eip))
329 return false;
330 }
331 return !!(pCtxCore->eflags.u32 & X86_EFL_IF);
332}
333
334/**
335 * Check if the instruction is patched as a duplicated function
336 *
337 * @returns patch record
338 * @param pVM Pointer to the VM.
339 * @param pInstrGC Guest context point to the instruction
340 *
341 */
342PPATMPATCHREC patmQueryFunctionPatch(PVM pVM, RTRCPTR pInstrGC)
343{
344 PPATMPATCHREC pRec;
345
346 AssertCompile(sizeof(AVLOU32KEY) == sizeof(pInstrGC));
347 pRec = (PPATMPATCHREC)RTAvloU32Get(&CTXSUFF(pVM->patm.s.PatchLookupTree)->PatchTree, (AVLOU32KEY)pInstrGC);
348 if ( pRec
349 && (pRec->patch.uState == PATCH_ENABLED)
350 && (pRec->patch.flags & (PATMFL_DUPLICATE_FUNCTION|PATMFL_CALLABLE_AS_FUNCTION))
351 )
352 return pRec;
353 return 0;
354}
355
356/**
357 * Checks if the int 3 was caused by a patched instruction
358 *
359 * @returns VBox status
360 *
361 * @param pVM Pointer to the VM.
362 * @param pInstrGC Instruction pointer
363 * @param pOpcode Original instruction opcode (out, optional)
364 * @param pSize Original instruction size (out, optional)
365 */
366VMM_INT_DECL(bool) PATMIsInt3Patch(PVM pVM, RTRCPTR pInstrGC, uint32_t *pOpcode, uint32_t *pSize)
367{
368 PPATMPATCHREC pRec;
369 Assert(!HMIsEnabled(pVM));
370
371 pRec = (PPATMPATCHREC)RTAvloU32Get(&CTXSUFF(pVM->patm.s.PatchLookupTree)->PatchTree, (AVLOU32KEY)pInstrGC);
372 if ( pRec
373 && (pRec->patch.uState == PATCH_ENABLED)
374 && (pRec->patch.flags & (PATMFL_INT3_REPLACEMENT|PATMFL_INT3_REPLACEMENT_BLOCK))
375 )
376 {
377 if (pOpcode) *pOpcode = pRec->patch.opcode;
378 if (pSize) *pSize = pRec->patch.cbPrivInstr;
379 return true;
380 }
381 return false;
382}
383
384/**
385 * Emulate sysenter, sysexit and syscall instructions
386 *
387 * @returns VBox status
388 *
389 * @param pVM Pointer to the VM.
390 * @param pCtxCore The relevant core context.
391 * @param pCpu Disassembly context
392 */
393VMMDECL(int) PATMSysCall(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
394{
395 PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(VMMGetCpu0(pVM));
396 AssertReturn(!HMIsEnabled(pVM), VERR_PATM_HM_IPE);
397
398 if (pCpu->pCurInstr->uOpcode == OP_SYSENTER)
399 {
400 if ( pCtx->SysEnter.cs == 0
401 || pRegFrame->eflags.Bits.u1VM
402 || (pRegFrame->cs.Sel & X86_SEL_RPL) != 3
403 || pVM->patm.s.pfnSysEnterPatchGC == 0
404 || pVM->patm.s.pfnSysEnterGC != (RTRCPTR)(RTRCUINTPTR)pCtx->SysEnter.eip
405 || !(PATMRawGetEFlags(pVM, pRegFrame) & X86_EFL_IF))
406 goto end;
407
408 Log2(("PATMSysCall: sysenter from %RRv to %RRv\n", pRegFrame->eip, pVM->patm.s.pfnSysEnterPatchGC));
409 /** @todo the base and limit are forced to 0 & 4G-1 resp. We assume the selector is wide open here. */
410 /** @note The Intel manual suggests that the OS is responsible for this. */
411 pRegFrame->cs.Sel = (pCtx->SysEnter.cs & ~X86_SEL_RPL) | 1;
412 pRegFrame->eip = /** @todo ugly conversion! */(uint32_t)pVM->patm.s.pfnSysEnterPatchGC;
413 pRegFrame->ss.Sel = pRegFrame->cs.Sel + 8; /* SysEnter.cs + 8 */
414 pRegFrame->esp = pCtx->SysEnter.esp;
415 pRegFrame->eflags.u32 &= ~(X86_EFL_VM | X86_EFL_RF);
416 pRegFrame->eflags.u32 |= X86_EFL_IF;
417
418 /* Turn off interrupts. */
419 pVM->patm.s.CTXSUFF(pGCState)->uVMFlags &= ~X86_EFL_IF;
420
421 STAM_COUNTER_INC(&pVM->patm.s.StatSysEnter);
422
423 return VINF_SUCCESS;
424 }
425 if (pCpu->pCurInstr->uOpcode == OP_SYSEXIT)
426 {
427 if ( pCtx->SysEnter.cs == 0
428 || (pRegFrame->cs.Sel & X86_SEL_RPL) != 1
429 || pRegFrame->eflags.Bits.u1VM
430 || !(PATMRawGetEFlags(pVM, pRegFrame) & X86_EFL_IF))
431 goto end;
432
433 Log2(("PATMSysCall: sysexit from %RRv to %RRv\n", pRegFrame->eip, pRegFrame->edx));
434
435 pRegFrame->cs.Sel = ((pCtx->SysEnter.cs + 16) & ~X86_SEL_RPL) | 3;
436 pRegFrame->eip = pRegFrame->edx;
437 pRegFrame->ss.Sel = pRegFrame->cs.Sel + 8; /* SysEnter.cs + 24 */
438 pRegFrame->esp = pRegFrame->ecx;
439
440 STAM_COUNTER_INC(&pVM->patm.s.StatSysExit);
441
442 return VINF_SUCCESS;
443 }
444 if (pCpu->pCurInstr->uOpcode == OP_SYSCALL)
445 {
446 /** @todo implement syscall */
447 }
448 else
449 if (pCpu->pCurInstr->uOpcode == OP_SYSRET)
450 {
451 /** @todo implement sysret */
452 }
453
454end:
455 return VINF_EM_RAW_RING_SWITCH;
456}
457
458/**
459 * Adds branch pair to the lookup cache of the particular branch instruction
460 *
461 * @returns VBox status
462 * @param pVM Pointer to the VM.
463 * @param pJumpTableGC Pointer to branch instruction lookup cache
464 * @param pBranchTarget Original branch target
465 * @param pRelBranchPatch Relative duplicated function address
466 */
467int patmAddBranchToLookupCache(PVM pVM, RTRCPTR pJumpTableGC, RTRCPTR pBranchTarget, RTRCUINTPTR pRelBranchPatch)
468{
469 PPATCHJUMPTABLE pJumpTable;
470
471 Log(("PATMAddBranchToLookupCache: Adding (%RRv->%RRv (%RRv)) to table %RRv\n", pBranchTarget, pRelBranchPatch + pVM->patm.s.pPatchMemGC, pRelBranchPatch, pJumpTableGC));
472
473 AssertReturn(PATMIsPatchGCAddr(pVM, (RTRCUINTPTR)pJumpTableGC), VERR_INVALID_PARAMETER);
474
475#ifdef IN_RC
476 pJumpTable = (PPATCHJUMPTABLE) pJumpTableGC;
477#else
478 pJumpTable = (PPATCHJUMPTABLE) (pJumpTableGC - pVM->patm.s.pPatchMemGC + pVM->patm.s.pPatchMemHC);
479#endif
480 Log(("Nr addresses = %d, insert pos = %d\n", pJumpTable->cAddresses, pJumpTable->ulInsertPos));
481 if (pJumpTable->cAddresses < pJumpTable->nrSlots)
482 {
483 uint32_t i;
484
485 for (i=0;i<pJumpTable->nrSlots;i++)
486 {
487 if (pJumpTable->Slot[i].pInstrGC == 0)
488 {
489 pJumpTable->Slot[i].pInstrGC = pBranchTarget;
490 /* Relative address - eases relocation */
491 pJumpTable->Slot[i].pRelPatchGC = pRelBranchPatch;
492 pJumpTable->cAddresses++;
493 break;
494 }
495 }
496 AssertReturn(i < pJumpTable->nrSlots, VERR_INTERNAL_ERROR);
497#ifdef VBOX_WITH_STATISTICS
498 STAM_COUNTER_INC(&pVM->patm.s.StatFunctionLookupInsert);
499 if (pVM->patm.s.StatU32FunctionMaxSlotsUsed < i)
500 pVM->patm.s.StatU32FunctionMaxSlotsUsed = i + 1;
501#endif
502 }
503 else
504 {
505 /* Replace an old entry. */
506 /** @todo replacement strategy isn't really bright. change to something better if required. */
507 Assert(pJumpTable->ulInsertPos < pJumpTable->nrSlots);
508 Assert((pJumpTable->nrSlots & 1) == 0);
509
510 pJumpTable->ulInsertPos &= (pJumpTable->nrSlots-1);
511 pJumpTable->Slot[pJumpTable->ulInsertPos].pInstrGC = pBranchTarget;
512 /* Relative address - eases relocation */
513 pJumpTable->Slot[pJumpTable->ulInsertPos].pRelPatchGC = pRelBranchPatch;
514
515 pJumpTable->ulInsertPos = (pJumpTable->ulInsertPos+1) & (pJumpTable->nrSlots-1);
516
517 STAM_COUNTER_INC(&pVM->patm.s.StatFunctionLookupReplace);
518 }
519
520 return VINF_SUCCESS;
521}
522
523
524#if defined(VBOX_WITH_STATISTICS) || defined(LOG_ENABLED)
525/**
526 * Return the name of the patched instruction
527 *
528 * @returns instruction name
529 *
530 * @param opcode DIS instruction opcode
531 * @param fPatchFlags Patch flags
532 */
533const char *patmGetInstructionString(uint32_t opcode, uint32_t fPatchFlags)
534{
535 const char *pszInstr = NULL;
536
537 switch (opcode)
538 {
539 case OP_CLI:
540 pszInstr = "cli";
541 break;
542 case OP_PUSHF:
543 pszInstr = "pushf";
544 break;
545 case OP_POPF:
546 pszInstr = "popf";
547 break;
548 case OP_STR:
549 pszInstr = "str";
550 break;
551 case OP_LSL:
552 pszInstr = "lsl";
553 break;
554 case OP_LAR:
555 pszInstr = "lar";
556 break;
557 case OP_SGDT:
558 pszInstr = "sgdt";
559 break;
560 case OP_SLDT:
561 pszInstr = "sldt";
562 break;
563 case OP_SIDT:
564 pszInstr = "sidt";
565 break;
566 case OP_SMSW:
567 pszInstr = "smsw";
568 break;
569 case OP_VERW:
570 pszInstr = "verw";
571 break;
572 case OP_VERR:
573 pszInstr = "verr";
574 break;
575 case OP_CPUID:
576 pszInstr = "cpuid";
577 break;
578 case OP_JMP:
579 pszInstr = "jmp";
580 break;
581 case OP_JO:
582 pszInstr = "jo";
583 break;
584 case OP_JNO:
585 pszInstr = "jno";
586 break;
587 case OP_JC:
588 pszInstr = "jc";
589 break;
590 case OP_JNC:
591 pszInstr = "jnc";
592 break;
593 case OP_JE:
594 pszInstr = "je";
595 break;
596 case OP_JNE:
597 pszInstr = "jne";
598 break;
599 case OP_JBE:
600 pszInstr = "jbe";
601 break;
602 case OP_JNBE:
603 pszInstr = "jnbe";
604 break;
605 case OP_JS:
606 pszInstr = "js";
607 break;
608 case OP_JNS:
609 pszInstr = "jns";
610 break;
611 case OP_JP:
612 pszInstr = "jp";
613 break;
614 case OP_JNP:
615 pszInstr = "jnp";
616 break;
617 case OP_JL:
618 pszInstr = "jl";
619 break;
620 case OP_JNL:
621 pszInstr = "jnl";
622 break;
623 case OP_JLE:
624 pszInstr = "jle";
625 break;
626 case OP_JNLE:
627 pszInstr = "jnle";
628 break;
629 case OP_JECXZ:
630 pszInstr = "jecxz";
631 break;
632 case OP_LOOP:
633 pszInstr = "loop";
634 break;
635 case OP_LOOPNE:
636 pszInstr = "loopne";
637 break;
638 case OP_LOOPE:
639 pszInstr = "loope";
640 break;
641 case OP_MOV:
642 if (fPatchFlags & PATMFL_IDTHANDLER)
643 pszInstr = "mov (Int/Trap Handler)";
644 else
645 pszInstr = "mov (cs)";
646 break;
647 case OP_SYSENTER:
648 pszInstr = "sysenter";
649 break;
650 case OP_PUSH:
651 pszInstr = "push (cs)";
652 break;
653 case OP_CALL:
654 pszInstr = "call";
655 break;
656 case OP_IRET:
657 pszInstr = "iret";
658 break;
659 }
660 return pszInstr;
661}
662#endif
Note: See TracBrowser for help on using the repository browser.

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