VirtualBox

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

Last change on this file since 21987 was 19259, checked in by vboxsync, 16 years ago

Fixes for guest smp assertions

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