VirtualBox

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

Last change on this file since 3020 was 3020, checked in by vboxsync, 17 years ago

Added missing space after ')' in macro invocations so VCC doesn't mess up the precompiler output.

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