1
/* $Id: PATMInternal.h 4071 2007-08-07 17:07:59Z vboxsync $ */
3
* PATM - Internal header file.
7
* Copyright (C) 2006-2007 innotek GmbH
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.
18
#ifndef ___PATMInternal_h
19
#define ___PATMInternal_h
21
#include <VBox/cdefs.h>
22
#include <VBox/types.h>
23
#include <VBox/patm.h>
24
#include <VBox/stam.h>
27
#include <iprt/param.h>
30
#if !defined(IN_PATM_R3) && !defined(IN_PATM_R0) && !defined(IN_PATM_GC)
31
# error "Not in PATM! This is an internal header!"
35
#define PATM_SSM_VERSION 53
37
/* Enable for call patching. */
38
#define PATM_ENABLE_CALL
39
#define PATCH_MEMORY_SIZE (2*1024*1024)
40
#define MAX_PATCH_SIZE (1024*4)
43
* Internal patch type flags (starts at BIT(11))
46
#define PATMFL_CHECK_SIZE BIT64(11)
47
#define PATMFL_FOUND_PATCHEND BIT64(12)
48
#define PATMFL_SINGLE_INSTRUCTION BIT64(13)
49
#define PATMFL_SYSENTER_XP BIT64(14)
50
#define PATMFL_JUMP_CONFLICT BIT64(15)
51
#define PATMFL_READ_ORIGINAL_BYTES BIT64(16) /** opcode might have already been patched */
52
#define PATMFL_INT3_REPLACEMENT BIT64(17)
53
#define PATMFL_SUPPORT_CALLS BIT64(18)
54
#define PATMFL_SUPPORT_INDIRECT_CALLS BIT64(19)
55
#define PATMFL_IDTHANDLER_WITHOUT_ENTRYPOINT BIT64(20) /** internal flag to avoid duplicate entrypoints */
56
#define PATMFL_INHIBIT_IRQS BIT64(21) /** temporary internal flag */
57
#define PATMFL_GENERATE_JUMPTOGUEST BIT64(22) /** temporary internal flag */
58
#define PATMFL_RECOMPILE_NEXT BIT64(23) /** for recompilation of the next instruction */
59
#define PATMFL_CODE_MONITORED BIT64(24) /** code pages of guest monitored for self-modifying code. */
60
#define PATMFL_CALLABLE_AS_FUNCTION BIT64(25) /** cli and pushf blocks can be used as callable functions. */
61
#define PATMFL_GLOBAL_FUNCTIONS BIT64(26) /** fake patch for global patm functions. */
62
#define PATMFL_TRAMPOLINE BIT64(27) /** trampoline patch that clears PATM_INTERRUPTFLAG and jumps to patch destination */
63
#define PATMFL_GENERATE_SETPIF BIT64(28) /** generate set PIF for the next instruction */
64
#define PATMFL_INSTR_HINT BIT64(29) /** Generate patch, but don't activate it. */
65
#define PATMFL_PATCHED_GUEST_CODE BIT64(30) /** Patched guest code. */
66
#define PATMFL_MUST_INSTALL_PATCHJMP BIT64(31) /** Need to patch guest code in order to activate patch. */
67
#define PATMFL_INT3_REPLACEMENT_BLOCK BIT64(32) /** int 3 replacement block */
68
#define PATMFL_EXTERNAL_JUMP_INSIDE BIT64(33) /** A trampoline patch was created that jumps to an instruction in the patch block */
70
#define SIZEOF_NEARJUMP8 2 //opcode byte + 1 byte relative offset
71
#define SIZEOF_NEARJUMP16 3 //opcode byte + 2 byte relative offset
72
#define SIZEOF_NEARJUMP32 5 //opcode byte + 4 byte relative offset
73
#define SIZEOF_NEAR_COND_JUMP32 6 //0xF + opcode byte + 4 byte relative offset
75
#define MAX_INSTR_SIZE 16
78
#define PATCH_REFUSED 1
79
#define PATCH_DISABLED 2
80
#define PATCH_ENABLED 4
81
#define PATCH_UNUSABLE 8
82
#define PATCH_DIRTY 16
83
#define PATCH_DISABLE_PENDING 32
86
#define MAX_PATCH_TRAPS 4
87
#define PATM_MAX_CALL_DEPTH 32
88
/* Maximum nr of writes before a patch is marked dirty. (disabled) */
89
#define PATM_MAX_CODE_WRITES 32
90
/* Maximum nr of invalid writes before a patch is disabled. */
91
#define PATM_MAX_INVALID_WRITES 16384
93
#define FIXUP_ABSOLUTE 0
94
#define FIXUP_REL_JMPTOPATCH 1
95
#define FIXUP_REL_JMPTOGUEST 2
97
#define PATM_ILLEGAL_DESTINATION 0xDEADBEEF
99
/** Size of the instruction that's used for requests from patch code (currently only call) */
100
#define PATM_ILLEGAL_INSTR_SIZE 2
103
/** No statistics counter index allocated just yet */
104
#define PATM_STAT_INDEX_NONE (uint32_t)-1
105
/** Dummy counter to handle overflows */
106
#define PATM_STAT_INDEX_DUMMY 0
107
#define PATM_STAT_INDEX_IS_VALID(a) (a != PATM_STAT_INDEX_DUMMY && a != PATM_STAT_INDEX_NONE)
109
#ifdef VBOX_WITH_STATISTICS
110
#define PATM_STAT_RUN_INC(pPatch) \
111
if (PATM_STAT_INDEX_IS_VALID((pPatch)->uPatchIdx)) \
112
CTXSUFF(pVM->patm.s.pStats)[(pPatch)->uPatchIdx].u32A++;
113
#define PATM_STAT_FAULT_INC(pPatch) \
114
if (PATM_STAT_INDEX_IS_VALID((pPatch)->uPatchIdx)) \
115
CTXSUFF(pVM->patm.s.pStats)[(pPatch)->uPatchIdx].u32B++;
117
#define PATM_STAT_RUN_INC(pPatch) do { } while (0)
118
#define PATM_STAT_FAULT_INC(pPatch) do { } while (0)
121
/** Maximum number of stat counters. */
122
#define PATM_STAT_MAX_COUNTERS 1024
123
/** Size of memory allocated for patch statistics. */
124
#define PATM_STAT_MEMSIZE (PATM_STAT_MAX_COUNTERS*sizeof(STAMRATIOU32))
129
/** The key is a HC virtual address. */
133
HCPTRTYPE(uint8_t *) pRelocPos;
136
} RELOCREC, *PRELOCREC;
140
HCPTRTYPE(uint8_t *) pPatchLocStartHC;
141
HCPTRTYPE(uint8_t *) pPatchLocEndHC;
142
GCPTRTYPE(uint8_t *) pGuestLoc;
144
} P2GLOOKUPREC, *PP2GLOOKUPREC;
148
/** The key is a pointer to a JUMPREC structure. */
151
HCPTRTYPE(uint8_t *) pJumpHC;
152
GCPTRTYPE(uint8_t *) pTargetGC;
155
} JUMPREC, *PJUMPREC;
158
* Patch to guest lookup type (single or both direction)
162
PATM_LOOKUP_PATCH2GUEST, /* patch to guest */
163
PATM_LOOKUP_BOTHDIR /* guest to patch + patch to guest */
167
* Patch to guest address lookup record
169
typedef struct RECPATCHTOGUEST
171
/** The key is an offset inside the patch memory block. */
175
PATM_LOOKUP_TYPE enmType;
178
uint8_t u8DirtyOpcode; /* original opcode before writing 0xCC there to mark it dirty */
179
} RECPATCHTOGUEST, *PRECPATCHTOGUEST;
182
* Guest to patch address lookup record
184
typedef struct RECGUESTTOPATCH
186
/** The key is a GC virtual address. */
187
AVLGCPTRNODECORE Core;
189
/** Patch offset (relative to PATM::pPatchMemGC / PATM::pPatchMemHC). */
190
uint32_t PatchOffset;
191
} RECGUESTTOPATCH, *PRECGUESTTOPATCH;
194
* Temporary information used in ring 3 only; no need to waste memory in the patch record itself.
198
/* Temporary tree for storing the addresses of illegal instructions. */
199
HCPTRTYPE(PAVLPVNODECORE) IllegalInstrTree;
200
uint32_t nrIllegalInstr;
205
/* Temporary tree of encountered jumps. (debug only) */
206
HCPTRTYPE(PAVLPVNODECORE) DisasmJumpTree;
210
/** Last original guest instruction pointer; used for disassmebly log. */
211
RTGCPTR pLastDisasmInstrGC;
213
/** Keeping track of multiple ret instructions. */
214
RTGCPTR pPatchRetInstrGC;
215
uint32_t uPatchRetParam1;
216
} PATCHINFOTEMP, *PPATCHINFOTEMP;
218
typedef struct _PATCHINFO
224
GCPTRTYPE(uint8_t *) pPrivInstrGC; //GC pointer of privileged instruction
225
HCPTRTYPE(uint8_t *) pPrivInstrHC; //HC pointer of privileged instruction
226
uint8_t aPrivInstr[MAX_INSTR_SIZE];
227
uint32_t cbPrivInstr;
228
uint32_t opcode; //opcode for priv instr (OP_*)
229
uint32_t cbPatchJump; //patch jump size
231
/* Only valid for PATMFL_JUMP_CONFLICT patches */
232
RTGCPTR pPatchJumpDestGC;
234
RTGCUINTPTR pPatchBlockOffset;
235
uint32_t cbPatchBlockSize;
236
uint32_t uCurPatchOffset;
237
#if HC_ARCH_BITS == 64
238
uint32_t Alignment0; /**< Align flags correctly. */
244
* Lowest and highest patched GC instruction address. To optimize searches.
246
RTGCPTR pInstrGCLowest;
247
RTGCPTR pInstrGCHighest;
249
/* Tree of fixup records for the patch. */
250
HCPTRTYPE(PAVLPVNODECORE) FixupTree;
253
/* Tree of jumps inside the generated patch code. */
255
HCPTRTYPE(PAVLPVNODECORE) JumpTree;
258
* Lookup trees for determining the corresponding guest address of an
259
* instruction in the patch block.
261
HCPTRTYPE(PAVLU32NODECORE) Patch2GuestAddrTree;
262
HCPTRTYPE(PAVLGCPTRNODECORE) Guest2PatchAddrTree;
263
uint32_t nrPatch2GuestRecs;
264
#if HC_ARCH_BITS == 64
268
// Cache record for PATMGCVirtToHCVirt
269
P2GLOOKUPREC cacheRec;
271
/* Temporary information during patch creation. Don't waste hypervisor memory for this. */
272
HCPTRTYPE(PPATCHINFOTEMP) pTempInfo;
274
/* Count the number of writes to the corresponding guest code. */
275
uint32_t cCodeWrites;
277
/* Count the number of invalid writes to pages monitored for the patch. */
278
//some statistics to determine if we should keep this patch activated
281
uint32_t cInvalidWrites;
283
// Index into the uPatchRun and uPatchTrap arrays (0..MAX_PATCHES-1)
286
/* First opcode byte, that's overwritten when a patch is marked dirty. */
287
uint8_t bDirtyOpcode;
288
uint8_t Alignment2[7]; /**< Align the structure size on a 8-byte boundrary. */
289
} PATCHINFO, *PPATCHINFO;
291
#define PATCHCODE_PTR_GC(pPatch) (RTGCPTR) (pVM->patm.s.pPatchMemGC + (pPatch)->pPatchBlockOffset)
292
#define PATCHCODE_PTR_HC(pPatch) (uint8_t *)(pVM->patm.s.pPatchMemHC + (pPatch)->pPatchBlockOffset)
295
* Lookup record for patches
297
typedef struct PATMPATCHREC
299
/** The key is a GC virtual address. */
300
AVLOGCPTRNODECORE Core;
301
/** The key is a patch offset. */
302
AVLOGCPTRNODECORE CoreOffset;
305
} PATMPATCHREC, *PPATMPATCHREC;
307
/** Increment for allocating room for pointer array */
308
#define PATMPATCHPAGE_PREALLOC_INCREMENT 16
311
* Lookup record for patch pages
313
typedef struct PATMPATCHPAGE
315
/** The key is a GC virtual address. */
316
AVLOGCPTRNODECORE Core;
317
/** Region to monitor. */
318
RTGCPTR pLowestAddrGC;
319
RTGCPTR pHighestAddrGC;
320
/** Number of patches for this page. */
322
/** Maximum nr of pointers in the array. */
323
uint32_t cMaxPatches;
324
/** Array of patch pointers for this page. */
325
HCPTRTYPE(PPATCHINFO *) aPatch;
326
} PATMPATCHPAGE, *PPATMPATCHPAGE;
328
#define PATM_PATCHREC_FROM_COREOFFSET(a) (PPATMPATCHREC)((uintptr_t)a - RT_OFFSETOF(PATMPATCHREC, CoreOffset))
329
#define PATM_PATCHREC_FROM_PATCHINFO(a) (PPATMPATCHREC)((uintptr_t)a - RT_OFFSETOF(PATMPATCHREC, patch))
331
typedef struct PATMTREES
334
* AVL tree with all patches (active or disabled) sorted by guest instruction address
336
AVLOGCPTRTREE PatchTree;
339
* AVL tree with all patches sorted by patch address (offset actually)
341
AVLOGCPTRTREE PatchTreeByPatchAddr;
344
* AVL tree with all pages which were (partly) patched
346
AVLOGCPTRTREE PatchTreeByPage;
349
} PATMTREES, *PPATMTREES;
352
* PATM VM Instance data.
353
* Changes to this must checked against the padding of the patm union in VM!
357
/** Offset to the VM structure.
361
GCPTRTYPE(uint8_t *) pPatchMemGC;
362
HCPTRTYPE(uint8_t *) pPatchMemHC;
364
uint32_t offPatchMem;
369
/* GC PATM state pointers */
370
HCPTRTYPE(PPATMGCSTATE) pGCStateHC;
371
GCPTRTYPE(PPATMGCSTATE) pGCStateGC;
373
/** PATM stack page for call instruction execution. (2 parts: one for our private stack and one to store the original return address */
374
GCPTRTYPE(RTGCPTR *) pGCStackGC;
375
HCPTRTYPE(RTGCPTR *) pGCStackHC;
377
/** GC pointer to CPUMCTX structure. */
378
GCPTRTYPE(PCPUMCTX) pCPUMCtxGC;
380
/* GC statistics pointers */
381
GCPTRTYPE(PSTAMRATIOU32) pStatsGC;
382
HCPTRTYPE(PSTAMRATIOU32) pStatsHC;
384
/* Current free index value (uPatchRun/uPatchTrap arrays). */
385
uint32_t uCurrentPatchIdx;
387
/* Temporary counter for patch installation call depth. (in order not to go on forever) */
388
uint32_t ulCallDepth;
390
/** Number of page lookup records. */
391
uint32_t cPageRecords;
394
* Lowest and highest patched GC instruction addresses. To optimize searches.
396
RTGCPTR pPatchedInstrGCLowest;
397
RTGCPTR pPatchedInstrGCHighest;
399
/** Pointer to the patch tree for instructions replaced by 'int 3'. */
400
GCPTRTYPE(PPATMTREES) PatchLookupTreeGC;
401
HCPTRTYPE(PPATMTREES) PatchLookupTreeHC;
403
/** Global PATM lookup and call function (used by call patches). */
404
RTGCPTR pfnHelperCallGC;
405
/** Global PATM return function (used by ret patches). */
406
RTGCPTR pfnHelperRetGC;
407
/** Global PATM jump function (used by indirect jmp patches). */
408
RTGCPTR pfnHelperJumpGC;
409
/** Global PATM return function (used by iret patches). */
410
RTGCPTR pfnHelperIretGC;
412
/** Fake patch record for global functions. */
413
HCPTRTYPE(PPATMPATCHREC) pGlobalPatchRec;
415
/** Pointer to original sysenter handler */
416
RTGCPTR pfnSysEnterGC;
417
/** Pointer to sysenter handler trampoline */
418
RTGCPTR pfnSysEnterPatchGC;
419
/** Sysenter patch index (for stats only) */
420
uint32_t uSysEnterPatchIdx;
422
// GC address of fault in monitored page (set by PATMGCMonitorPage, used by PATMR3HandleMonitoredPage)
423
RTGCPTR pvFaultMonitor;
425
/* Temporary information for pending MMIO patch. Set in GC or R0 context. */
432
/* Temporary storage during load/save state */
435
HCPTRTYPE(PSSMHANDLE) pSSM;
437
#if HC_ARCH_BITS == 64
438
uint32_t Alignment0; /**< Align the structure size on a 8-byte boundrary. */
442
STAMCOUNTER StatNrOpcodeRead;
443
STAMCOUNTER StatDisabled;
444
STAMCOUNTER StatUnusable;
445
STAMCOUNTER StatEnabled;
446
STAMCOUNTER StatInstalled;
447
STAMCOUNTER StatInstalledFunctionPatches;
448
STAMCOUNTER StatInstalledTrampoline;
449
STAMCOUNTER StatInstalledJump;
450
STAMCOUNTER StatInt3Callable;
451
STAMCOUNTER StatInt3BlockRun;
452
STAMCOUNTER StatOverwritten;
453
STAMCOUNTER StatFixedConflicts;
454
STAMCOUNTER StatFlushed;
455
STAMCOUNTER StatPageBoundaryCrossed;
456
STAMCOUNTER StatMonitored;
457
STAMPROFILEADV StatHandleTrap;
458
STAMCOUNTER StatSwitchBack;
459
STAMCOUNTER StatSwitchBackFail;
460
STAMCOUNTER StatPATMMemoryUsed;
461
STAMCOUNTER StatDuplicateREQSuccess;
462
STAMCOUNTER StatDuplicateREQFailed;
463
STAMCOUNTER StatDuplicateUseExisting;
464
STAMCOUNTER StatFunctionFound;
465
STAMCOUNTER StatFunctionNotFound;
466
STAMPROFILEADV StatPatchWrite;
467
STAMPROFILEADV StatPatchWriteDetect;
468
STAMCOUNTER StatDirty;
469
STAMCOUNTER StatPushTrap;
470
STAMCOUNTER StatPatchWriteInterpreted;
471
STAMCOUNTER StatPatchWriteInterpretedFailed;
473
STAMCOUNTER StatSysEnter;
474
STAMCOUNTER StatSysExit;
475
STAMCOUNTER StatEmulIret;
476
STAMCOUNTER StatEmulIretFailed;
478
STAMCOUNTER StatInstrDirty;
479
STAMCOUNTER StatInstrDirtyGood;
480
STAMCOUNTER StatInstrDirtyBad;
482
STAMCOUNTER StatPatchPageInserted;
483
STAMCOUNTER StatPatchPageRemoved;
485
STAMCOUNTER StatPatchRefreshSuccess;
486
STAMCOUNTER StatPatchRefreshFailed;
488
STAMCOUNTER StatGenRet;
489
STAMCOUNTER StatGenRetReused;
490
STAMCOUNTER StatGenJump;
491
STAMCOUNTER StatGenCall;
492
STAMCOUNTER StatGenPopf;
494
STAMCOUNTER StatCheckPendingIRQ;
496
STAMCOUNTER StatFunctionLookupReplace;
497
STAMCOUNTER StatFunctionLookupInsert;
498
uint32_t StatU32FunctionMaxSlotsUsed;
499
uint32_t Alignment0; /**< Align the structure size on a 8-byte boundrary. */
504
* Execute state save operation.
506
* @returns VBox status code.
507
* @param pVM VM Handle.
508
* @param pSSM SSM operation handle.
510
DECLCALLBACK(int) patmr3Save(PVM pVM, PSSMHANDLE pSSM);
514
* Execute state load operation.
516
* @returns VBox status code.
517
* @param pVM VM Handle.
518
* @param pSSM SSM operation handle.
519
* @param u32Version Data layout version.
521
DECLCALLBACK(int) patmr3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
524
RTGCPTR patmPatchGCPtr2GuestGCPtr(PVM pVM, PPATCHINFO pPatch, GCPTRTYPE(uint8_t *) pPatchGC);
525
RTGCPTR patmGuestGCPtrToPatchGCPtr(PVM pVM, PPATCHINFO pPatch, GCPTRTYPE(uint8_t*) pInstrGC);
528
/* Add a patch to guest lookup record
530
* @param pVM The VM to operate on.
531
* @param pPatch Patch structure ptr
532
* @param pPatchInstrHC Guest context pointer to patch block
533
* @param pInstrGC Guest context pointer to privileged instruction
534
* @param enmType Lookup type
535
* @param fDirty Dirty flag
538
void patmr3AddP2GLookupRecord(PVM pVM, PPATCHINFO pPatch, uint8_t *pPatchInstrHC, RTGCPTR pInstrGC, PATM_LOOKUP_TYPE enmType, bool fDirty=false);
541
* Insert page records for all guest pages that contain instructions that were recompiled for this patch
543
* @returns VBox status code.
544
* @param pVM The VM to operate on.
545
* @param pPatch Patch record
547
int patmInsertPatchPages(PVM pVM, PPATCHINFO pPatch);
550
* Remove page records for all guest pages that contain instructions that were recompiled for this patch
552
* @returns VBox status code.
553
* @param pVM The VM to operate on.
554
* @param pPatch Patch record
556
int patmRemovePatchPages(PVM pVM, PPATCHINFO pPatch);
559
* Returns the GC address of the corresponding patch statistics counter
561
* @returns Stat address
562
* @param pVM The VM to operate on.
563
* @param pPatch Patch structure
565
RTGCPTR patmPatchQueryStatAddress(PVM pVM, PPATCHINFO pPatch);
568
* Remove patch for privileged instruction at specified location
570
* @returns VBox status code.
571
* @param pVM The VM to operate on.
572
* @param pPatchRec Patch record
573
* @param fForceRemove Remove *all* patches
575
int PATMRemovePatch(PVM pVM, PPATMPATCHREC pPatchRec, bool fForceRemove);
578
* Call for analysing the instructions following the privileged instr. for compliance with our heuristics
580
* @returns VBox status code.
581
* @param pVM The VM to operate on.
582
* @param pCpu CPU disassembly state
583
* @param pInstrHC Guest context pointer to privileged instruction
584
* @param pCurInstrHC Guest context pointer to current instruction
585
* @param pUserData User pointer
588
typedef int (VBOXCALL *PFN_PATMR3ANALYSE)(PVM pVM, DISCPUSTATE *pCpu, GCPTRTYPE(uint8_t *) pInstrGC, GCPTRTYPE(uint8_t *) pCurInstrGC, void *pUserData);
591
* Install guest OS specific patch
593
* @returns VBox status code.
594
* @param pVM The VM to operate on
595
* @param pCpu Disassembly state of instruction.
596
* @param pInstrGC GC Instruction pointer for instruction
597
* @param pInstrHC GC Instruction pointer for instruction
598
* @param pPatchRec Patch structure
601
int PATMInstallGuestSpecificPatch(PVM pVM, PDISCPUSTATE pCpu, RTGCPTR pInstrGC, uint8_t *pInstrHC, PPATMPATCHREC pPatchRec);
604
* Convert guest context address to host context pointer
606
* @returns VBox status code.
607
* @param pVM The VM to operate on.
608
* @param pPatch Patch block structure pointer
609
* @param pGCPtr Guest context pointer
611
* @returns Host context pointer or NULL in case of an error
614
HCPTRTYPE(uint8_t *) PATMGCVirtToHCVirt(PVM pVM, PPATCHINFO pPatch, GCPTRTYPE(uint8_t *) pGCPtr);
618
* Check if the instruction is patched as a duplicated function
620
* @returns patch record
621
* @param pVM The VM to operate on.
622
* @param pInstrGC Guest context point to the instruction
625
PATMDECL(PPATMPATCHREC) PATMQueryFunctionPatch(PVM pVM, RTGCPTR pInstrGC);
629
* Empty the specified tree (PV tree, MMR3 heap)
631
* @param pVM The VM to operate on.
632
* @param ppTree Tree to empty
634
void patmEmptyTree(PVM pVM, PPAVLPVNODECORE ppTree);
638
* Empty the specified tree (U32 tree, MMR3 heap)
640
* @param pVM The VM to operate on.
641
* @param ppTree Tree to empty
643
void patmEmptyTreeU32(PVM pVM, PPAVLU32NODECORE ppTree);
647
* Return the name of the patched instruction
649
* @returns instruction name
651
* @param opcode DIS instruction opcode
652
* @param fPatchFlags Patch flags
654
PATMDECL(const char *) patmGetInstructionString(uint32_t opcode, uint32_t fPatchFlags);
658
* Read callback for disassembly function; supports reading bytes that cross a page boundary
660
* @returns VBox status code.
661
* @param pSrc GC source pointer
662
* @param pDest HC destination pointer
663
* @param size Number of bytes to read
664
* @param dwUserdata Callback specific user data (pCpu)
667
int32_t patmReadBytes(RTHCUINTPTR pSrc, uint8_t *pDest, uint32_t size, RTHCUINTPTR dwUserdata);
672
#define PATMREAD_RAWCODE 1 /* read code as-is */
673
#define PATMREAD_ORGCODE 2 /* read original guest opcode bytes; not the patched bytes */
674
#define PATMREAD_NOCHECK 4 /* don't check for patch conflicts */
677
* Private structure used during disassembly
682
PPATCHINFO pPatchInfo;
683
HCPTRTYPE(uint8_t *) pInstrHC;
686
} PATMDISASM, *PPATMDISASM;
688
inline bool PATMR3DISInstr(PVM pVM, PPATCHINFO pPatch, DISCPUSTATE *pCpu, RTGCPTR InstrGC,
689
uint8_t *InstrHC, uint32_t *pOpsize, char *pszOutput,
690
uint32_t fReadFlags = PATMREAD_ORGCODE)
694
disinfo.pPatchInfo = pPatch;
695
disinfo.pInstrHC = InstrHC;
696
disinfo.pInstrGC = InstrGC;
697
disinfo.fReadFlags = fReadFlags;
698
(pCpu)->pfnReadBytes = patmReadBytes;
699
(pCpu)->dwUserData[0] = (RTHCUINTPTR)&disinfo;
700
return DISInstr(pCpu, InstrGC, 0, pOpsize, pszOutput);
706
* #PF Virtual Handler callback for Guest access a page monitored by PATM
708
* @returns VBox status code (appropritate for trap handling and GC return).
709
* @param pVM VM Handle.
710
* @param uErrorCode CPU Error code.
711
* @param pRegFrame Trap register frame.
712
* @param pvFault The fault address (cr2).
713
* @param pvRange The base address of the handled virtual range.
714
* @param offRange The offset of the access into this range.
715
* (If it's a EIP range this's the EIP, if not it's pvFault.)
717
PATMGCDECL(int) PATMGCMonitorPage(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, void *pvRange, uintptr_t offRange);
720
* Find patch for privileged instruction at specified location
722
* @returns Patch structure pointer if found; else NULL
723
* @param pVM The VM to operate on.
724
* @param pInstr Guest context point to instruction that might lie within 5 bytes of an existing patch jump
725
* @param fIncludeHints Include hinted patches or not
728
PPATCHINFO PATMFindActivePatchByEntrypoint(PVM pVM, RTGCPTR pInstrGC, bool fIncludeHints=false);
731
* Patch cli/sti pushf/popf instruction block at specified location
733
* @returns VBox status code.
734
* @param pVM The VM to operate on.
735
* @param pInstrGC Guest context point to privileged instruction
736
* @param pInstrHC Host context point to privileged instruction
737
* @param uOpcode Instruction opcodee
738
* @param uOpSize Size of starting instruction
739
* @param pPatchRec Patch record
741
* @note returns failure if patching is not allowed or possible
744
PATMR3DECL(int) PATMR3PatchBlock(PVM pVM, RTGCPTR pInstrGC, HCPTRTYPE(uint8_t *) pInstrHC,
745
uint32_t uOpcode, uint32_t uOpSize, PPATMPATCHREC pPatchRec);
749
* Replace an instruction with a breakpoint (0xCC), that is handled dynamically in the guest context.
751
* @returns VBox status code.
752
* @param pVM The VM to operate on.
753
* @param pInstrGC Guest context point to privileged instruction
754
* @param pInstrHC Host context point to privileged instruction
755
* @param pCpu Disassembly CPU structure ptr
756
* @param pPatch Patch record
758
* @note returns failure if patching is not allowed or possible
761
PATMR3DECL(int) PATMR3PatchInstrInt3(PVM pVM, RTGCPTR pInstrGC, HCPTRTYPE(uint8_t *) pInstrHC, DISCPUSTATE *pCpu, PPATCHINFO pPatch);
764
* Mark patch as dirty
766
* @returns VBox status code.
767
* @param pVM The VM to operate on.
768
* @param pPatch Patch record
770
* @note returns failure if patching is not allowed or possible
773
PATMR3DECL(int) PATMR3MarkDirtyPatch(PVM pVM, PPATCHINFO pPatch);
776
* Calculate the branch destination
778
* @returns branch destination or 0 if failed
779
* @param pCpu Disassembly state of instruction.
780
* @param pBranchInstrGC GC pointer of branch instruction
782
inline RTGCPTR PATMResolveBranch(PDISCPUSTATE pCpu, RTGCPTR pBranchInstrGC)
785
if (pCpu->param1.flags & USE_IMMEDIATE8_REL)
787
disp = (int32_t)(char)pCpu->param1.parval;
790
if (pCpu->param1.flags & USE_IMMEDIATE16_REL)
792
disp = (int32_t)(uint16_t)pCpu->param1.parval;
795
if (pCpu->param1.flags & USE_IMMEDIATE32_REL)
797
disp = (int32_t)pCpu->param1.parval;
801
Log(("We don't support far jumps here!! (%08X)\n", pCpu->param1.flags));
805
return (RTGCPTR)((uint8_t *)pBranchInstrGC + pCpu->opsize + disp);
807
return pBranchInstrGC + pCpu->opsize + disp;
814
int patmr3DisasmCallback(PVM pVM, DISCPUSTATE *pCpu, GCPTRTYPE(uint8_t *) pInstrGC, GCPTRTYPE(uint8_t *) pCurInstrGC, void *pUserData);
815
int patmr3DisasmCodeStream(PVM pVM, GCPTRTYPE(uint8_t *) pInstrGC, GCPTRTYPE(uint8_t *) pCurInstrGC, PFN_PATMR3ANALYSE pfnPATMR3Analyse, void *pUserData);