Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

890 lines
35 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Module: detours.lib
  4. // File: disasm.cpp
  5. // Author: Doug Brubacher
  6. //
  7. // Detours for binary functions. Version 1.2. (Build 35)
  8. // Includes support for all x86 chips prior to the Pentium III.
  9. //
  10. // Copyright 1999, Microsoft Corporation
  11. //
  12. // http://research.microsoft.com/sn/detours
  13. //
  14. #include "stdafx.h"
  15. #include <imagehlp.h>
  16. #undef ASSERT
  17. #define ASSERT(x)
  18. //////////////////////////////////////////////////////////////////////////////
  19. //
  20. // Function:
  21. // DetourCopyInstruction(PBYTE pbDst, PBYTE pbSrc, PBYTE *ppbTarget)
  22. // Purpose:
  23. // Copy a single instruction from pbSrc to pbDst.
  24. // Arguments:
  25. // pbDst:
  26. // Destination address for the instruction. May be NULL in which
  27. // case DetourCopyInstruction is used to measure an instruction.
  28. // If not NULL then the source instruction is copied to the
  29. // destination instruction and any relative arguments are adjusted.
  30. // pbSrc:
  31. // Source address of the instruction.
  32. // ppbTarget:
  33. // Out parameter for any target instruction address pointed to by
  34. // the instruction. For example, a branch or a jump insruction has
  35. // a target, but a load or store instruction doesn't. A target is
  36. // another instruction that may be executed as a result of this
  37. // instruction. ppbTarget may be NULL.
  38. // plExtra:
  39. // Out parameter for the number of extra bytes needed by the
  40. // instruction to reach the target. For example, lExtra = 3 if the
  41. // instruction had an 8-bit relative offset, but needs a 32-bit
  42. // relative offset.
  43. // Returns:
  44. // Returns the address of the next instruction (following in the source)
  45. // instruction. By subtracting pbSrc from the return value, the caller
  46. // can determinte the size of the instruction copied.
  47. // Comments:
  48. // By following the pbTarget, the caller can follow alternate
  49. // instruction streams. However, it is not always possible to determine
  50. // the target based on static analysis. For example, the destination of
  51. // a jump relative to a register cannot be determined from just the
  52. // instruction stream. The output value, pbTarget, can have any of the
  53. // following outputs:
  54. // DETOUR_INSTRUCTION_TARGET_NONE:
  55. // The instruction has no targets.
  56. // DETOUR_INSTRUCTION_TARGET_DYNAMIC:
  57. // The instruction has a non-deterministic (dynamic) target.
  58. // (i.e. the jump is to an address held in a register.)
  59. // Address: The instruction has the specified target.
  60. //
  61. // When copying instructions, DetourCopyInstruction insures that any
  62. // targets remain constant. It does so by adjusting any IP relative
  63. // offsets.
  64. //
  65. PBYTE WINAPI DetourCopyInstructionEx(PBYTE pbDst,
  66. PBYTE pbSrc,
  67. PBYTE *ppbTarget,
  68. LONG *plExtra)
  69. {
  70. CDetourDis oDetourDisasm(ppbTarget, plExtra);
  71. return oDetourDisasm.CopyInstruction(pbDst, pbSrc);
  72. }
  73. PBYTE WINAPI DetourCopyInstruction(PBYTE pbDst, PBYTE pbSrc, PBYTE *ppbTarget)
  74. {
  75. CDetourDis oDetourDisasm(ppbTarget, NULL);
  76. return oDetourDisasm.CopyInstruction(pbDst, pbSrc);
  77. }
  78. /////////////////////////////////////////////////////////// Disassembler Code.
  79. //
  80. CDetourDis::CDetourDis(PBYTE *ppbTarget, LONG *plExtra)
  81. {
  82. Set32BitOperand();
  83. Set32BitAddress();
  84. m_ppbTarget = ppbTarget ? ppbTarget : &m_pbScratchTarget;
  85. m_plExtra = plExtra ? plExtra : &m_lScratchExtra;
  86. *m_ppbTarget = DETOUR_INSTRUCTION_TARGET_NONE;
  87. *m_plExtra = 0;
  88. }
  89. VOID CDetourDis::Set16BitOperand()
  90. {
  91. m_b16BitOperand = TRUE;
  92. }
  93. VOID CDetourDis::Set32BitOperand()
  94. {
  95. m_b16BitOperand = FALSE;
  96. }
  97. VOID CDetourDis::Set16BitAddress()
  98. {
  99. m_b16BitAddress = TRUE;
  100. }
  101. VOID CDetourDis::Set32BitAddress()
  102. {
  103. m_b16BitAddress = FALSE;
  104. }
  105. PBYTE CDetourDis::CopyInstruction(PBYTE pbDst, PBYTE pbSrc)
  106. {
  107. // Configure scratch areas if real areas are not available.
  108. if (NULL == pbDst) {
  109. pbDst = m_rbScratchDst;
  110. }
  111. if (NULL == pbSrc) {
  112. // We can't copy a non-existent instruction.
  113. SetLastError(ERROR_INVALID_DATA);
  114. return NULL;
  115. }
  116. // Figure out how big the instruction is, do the appropriate copy,
  117. // and figure out what the target of the instruction is if any.
  118. //
  119. REFCOPYENTRY pEntry = &s_rceCopyTable[pbSrc[0]];
  120. return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
  121. }
  122. PBYTE CDetourDis::CopyBytes(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  123. {
  124. LONG nBytesFixed = (pEntry->nFlagBits & ADDRESS)
  125. ? (m_b16BitAddress ? pEntry->nFixedSize16 : pEntry->nFixedSize)
  126. : (m_b16BitOperand ? pEntry->nFixedSize16 : pEntry->nFixedSize);
  127. LONG nBytes = nBytesFixed;
  128. if (pEntry->nModOffset > 0) {
  129. BYTE bModRm = pbSrc[pEntry->nModOffset];
  130. BYTE bFlags = s_rbModRm[bModRm];
  131. if (bFlags & SIB) {
  132. BYTE bSib = pbSrc[pEntry->nModOffset + 1];
  133. if ((bSib & 0x07) == 0x05) {
  134. if ((bModRm & 0xc0) == 0x00) {
  135. nBytes += 4;
  136. }
  137. else if ((bModRm & 0xc0) == 0x40) {
  138. nBytes += 1;
  139. }
  140. else if ((bModRm & 0xc0) == 0x80) {
  141. nBytes += 4;
  142. }
  143. }
  144. }
  145. nBytes += bFlags & NOTSIB;
  146. }
  147. CopyMemory(pbDst, pbSrc, nBytes);
  148. if (pEntry->nRelOffset) {
  149. *m_ppbTarget = AdjustTarget(pbDst, pbSrc, nBytesFixed, pEntry->nRelOffset);
  150. }
  151. if (pEntry->nFlagBits & NOENLARGE) {
  152. *m_plExtra = -*m_plExtra;
  153. }
  154. if (pEntry->nFlagBits & DYNAMIC) {
  155. *m_ppbTarget = DETOUR_INSTRUCTION_TARGET_DYNAMIC;
  156. }
  157. return pbSrc + nBytes;
  158. }
  159. PBYTE CDetourDis::CopyBytesPrefix(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  160. {
  161. CopyBytes(pEntry, pbDst, pbSrc);
  162. pEntry = &s_rceCopyTable[pbSrc[1]];
  163. return (this->*pEntry->pfCopy)(pEntry, pbDst + 1, pbSrc + 1);
  164. }
  165. PBYTE CDetourDis::AdjustTarget(PBYTE pbDst, PBYTE pbSrc, LONG cbOp, LONG cbTargetOffset)
  166. {
  167. LONG cbTargetSize = cbOp - cbTargetOffset;
  168. PBYTE pbTarget = NULL;
  169. PVOID pvTargetAddr = &pbDst[cbTargetOffset];
  170. LONG nOldOffset = 0;
  171. switch (cbTargetSize) {
  172. case 1:
  173. nOldOffset = (LONG)*(PCHAR&)pvTargetAddr;
  174. *m_plExtra = 3;
  175. break;
  176. case 2:
  177. nOldOffset = (LONG)*(PSHORT&)pvTargetAddr;
  178. *m_plExtra = 2;
  179. break;
  180. case 4:
  181. nOldOffset = (LONG)*(PLONG&)pvTargetAddr;
  182. *m_plExtra = 0;
  183. break;
  184. default:
  185. ASSERT(!"cbTargetSize is invalid.");
  186. break;
  187. }
  188. pbTarget = pbSrc + cbOp + nOldOffset;
  189. LONG nNewOffset = nOldOffset - (pbDst - pbSrc);
  190. switch (cbTargetSize) {
  191. case 1:
  192. *(PCHAR&)pvTargetAddr = (CHAR)nNewOffset;
  193. break;
  194. case 2:
  195. *(PSHORT&)pvTargetAddr = (SHORT)nNewOffset;
  196. break;
  197. case 4:
  198. *(PLONG&)pvTargetAddr = (LONG)nNewOffset;
  199. break;
  200. }
  201. ASSERT(pbDst + cbOp + nNewOffset == pbTarget);
  202. return pbTarget;
  203. }
  204. PBYTE CDetourDis::Invalid(REFCOPYENTRY /*pEntry*/, PBYTE /*pbDst*/, PBYTE pbSrc)
  205. {
  206. ASSERT(!"Invalid Instruction");
  207. return pbSrc + 1;
  208. }
  209. ////////////////////////////////////////////////////// Individual Bytes Codes.
  210. //
  211. PBYTE CDetourDis::Copy0F(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  212. {
  213. CopyBytes(pEntry, pbDst, pbSrc);
  214. pEntry = &s_rceCopyTable0F[pbSrc[1]];
  215. return (this->*pEntry->pfCopy)(pEntry, pbDst + 1, pbSrc + 1);
  216. }
  217. PBYTE CDetourDis::Copy66(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  218. { // Operand-size override prefix
  219. Set16BitOperand();
  220. return CopyBytesPrefix(pEntry, pbDst, pbSrc);
  221. }
  222. PBYTE CDetourDis::Copy67(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
  223. { // Address size override prefix
  224. Set16BitAddress();
  225. return CopyBytesPrefix(pEntry, pbDst, pbSrc);
  226. }
  227. PBYTE CDetourDis::CopyF6(REFCOPYENTRY /*pEntry*/, PBYTE pbDst, PBYTE pbSrc)
  228. {
  229. // TEST BYTE /0
  230. if (0x00 == (0x38 & pbSrc[1])) { // reg(bits 543) of ModR/M == 0
  231. const COPYENTRY ce = { 0xf6, ENTRY_CopyBytes2Mod1 };
  232. return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
  233. }
  234. // DIV /6
  235. // IDIV /7
  236. // IMUL /5
  237. // MUL /4
  238. // NEG /3
  239. // NOT /2
  240. const COPYENTRY ce = { 0xf6, ENTRY_CopyBytes2Mod };
  241. return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
  242. }
  243. PBYTE CDetourDis::CopyF7(REFCOPYENTRY /*pEntry*/, PBYTE pbDst, PBYTE pbSrc)
  244. {
  245. // TEST WORD /0
  246. if (0x00 == (0x38 & pbSrc[1])) { // reg(bits 543) of ModR/M == 0
  247. const COPYENTRY ce = { 0xf7, ENTRY_CopyBytes2ModOperand };
  248. return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
  249. }
  250. // DIV /6
  251. // IDIV /7
  252. // IMUL /5
  253. // MUL /4
  254. // NEG /3
  255. // NOT /2
  256. const COPYENTRY ce = { 0xf7, ENTRY_CopyBytes2Mod };
  257. return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
  258. }
  259. PBYTE CDetourDis::CopyFF(REFCOPYENTRY /*pEntry*/, PBYTE pbDst, PBYTE pbSrc)
  260. { // CALL /2
  261. // CALL /3
  262. // INC /0
  263. // JMP /4
  264. // JMP /5
  265. // PUSH /6
  266. if (0x15 == pbSrc[1] || 0x25 == pbSrc[1]) { // CALL [], JMP []
  267. PBYTE *ppbTarget = *(PBYTE**) &pbSrc[2];
  268. *m_ppbTarget = *ppbTarget;
  269. }
  270. else if (0x10 == (0x38 & pbSrc[1]) || // CALL /2 --> reg(bits 543) of ModR/M == 010
  271. 0x18 == (0x38 & pbSrc[1]) || // CALL /3 --> reg(bits 543) of ModR/M == 011
  272. 0x20 == (0x38 & pbSrc[1]) || // JMP /4 --> reg(bits 543) of ModR/M == 100
  273. 0x28 == (0x38 & pbSrc[1]) // JMP /5 --> reg(bits 543) of ModR/M == 101
  274. ) {
  275. *m_ppbTarget = DETOUR_INSTRUCTION_TARGET_DYNAMIC;
  276. }
  277. const COPYENTRY ce = { 0xff, ENTRY_CopyBytes2Mod };
  278. return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
  279. }
  280. ///////////////////////////////////////////////////////// Disassembler Tables.
  281. //
  282. const BYTE CDetourDis::s_rbModRm[256] = {
  283. 0,0,0,0, SIB|1,4,0,0, 0,0,0,0, SIB|1,4,0,0, // 0x
  284. 0,0,0,0, SIB|1,4,0,0, 0,0,0,0, SIB|1,4,0,0, // 1x
  285. 0,0,0,0, SIB|1,4,0,0, 0,0,0,0, SIB|1,4,0,0, // 2x
  286. 0,0,0,0, SIB|1,4,0,0, 0,0,0,0, SIB|1,4,0,0, // 3x
  287. 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 4x
  288. 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 5x
  289. 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 6x
  290. 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 7x
  291. 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // 8x
  292. 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // 9x
  293. 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // Ax
  294. 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // Bx
  295. 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // Cx
  296. 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // Dx
  297. 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // Ex
  298. 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 // Fx
  299. };
  300. const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable[257] =
  301. {
  302. { 0x00, ENTRY_CopyBytes2Mod }, // ADD /r
  303. { 0x01, ENTRY_CopyBytes2Mod }, // ADD /r
  304. { 0x02, ENTRY_CopyBytes2Mod }, // ADD /r
  305. { 0x03, ENTRY_CopyBytes2Mod }, // ADD /r
  306. { 0x04, ENTRY_CopyBytes2 }, // ADD ib
  307. { 0x05, ENTRY_CopyBytes3Or5 }, // ADD iw
  308. { 0x06, ENTRY_CopyBytes1 }, // PUSH
  309. { 0x07, ENTRY_CopyBytes1 }, // POP
  310. { 0x08, ENTRY_CopyBytes2Mod }, // OR /r
  311. { 0x09, ENTRY_CopyBytes2Mod }, // OR /r
  312. { 0x0A, ENTRY_CopyBytes2Mod }, // OR /r
  313. { 0x0B, ENTRY_CopyBytes2Mod }, // OR /r
  314. { 0x0C, ENTRY_CopyBytes2 }, // OR ib
  315. { 0x0D, ENTRY_CopyBytes3Or5 }, // OR iw
  316. { 0x0E, ENTRY_CopyBytes1 }, // PUSH
  317. { 0x0F, ENTRY_Copy0F }, // Extension Ops
  318. { 0x10, ENTRY_CopyBytes2Mod }, // ADC /r
  319. { 0x11, ENTRY_CopyBytes2Mod }, // ADC /r
  320. { 0x12, ENTRY_CopyBytes2Mod }, // ADC /r
  321. { 0x13, ENTRY_CopyBytes2Mod }, // ADC /r
  322. { 0x14, ENTRY_CopyBytes2 }, // ADC ib
  323. { 0x15, ENTRY_CopyBytes3Or5 }, // ADC id
  324. { 0x16, ENTRY_CopyBytes1 }, // PUSH
  325. { 0x17, ENTRY_CopyBytes1 }, // POP
  326. { 0x18, ENTRY_CopyBytes2Mod }, // SBB /r
  327. { 0x19, ENTRY_CopyBytes2Mod }, // SBB /r
  328. { 0x1A, ENTRY_CopyBytes2Mod }, // SBB /r
  329. { 0x1B, ENTRY_CopyBytes2Mod }, // SBB /r
  330. { 0x1C, ENTRY_CopyBytes2 }, // SBB ib
  331. { 0x1D, ENTRY_CopyBytes3Or5 }, // SBB id
  332. { 0x1E, ENTRY_CopyBytes1 }, // PUSH
  333. { 0x1F, ENTRY_CopyBytes1 }, // POP
  334. { 0x20, ENTRY_CopyBytes2Mod }, // AND /r
  335. { 0x21, ENTRY_CopyBytes2Mod }, // AND /r
  336. { 0x22, ENTRY_CopyBytes2Mod }, // AND /r
  337. { 0x23, ENTRY_CopyBytes2Mod }, // AND /r
  338. { 0x24, ENTRY_CopyBytes2 }, // AND ib
  339. { 0x25, ENTRY_CopyBytes3Or5 }, // AND id
  340. { 0x26, ENTRY_CopyBytesPrefix }, // ES prefix
  341. { 0x27, ENTRY_CopyBytes1 }, // DAA
  342. { 0x28, ENTRY_CopyBytes2Mod }, // SUB /r
  343. { 0x29, ENTRY_CopyBytes2Mod }, // SUB /r
  344. { 0x2A, ENTRY_CopyBytes2Mod }, // SUB /r
  345. { 0x2B, ENTRY_CopyBytes2Mod }, // SUB /r
  346. { 0x2C, ENTRY_CopyBytes2 }, // SUB ib
  347. { 0x2D, ENTRY_CopyBytes3Or5 }, // SUB id
  348. { 0x2E, ENTRY_CopyBytesPrefix }, // CS prefix
  349. { 0x2F, ENTRY_CopyBytes1 }, // DAS
  350. { 0x30, ENTRY_CopyBytes2Mod }, // XOR /r
  351. { 0x31, ENTRY_CopyBytes2Mod }, // XOR /r
  352. { 0x32, ENTRY_CopyBytes2Mod }, // XOR /r
  353. { 0x33, ENTRY_CopyBytes2Mod }, // XOR /r
  354. { 0x34, ENTRY_CopyBytes2 }, // XOR ib
  355. { 0x35, ENTRY_CopyBytes3Or5 }, // XOR id
  356. { 0x36, ENTRY_CopyBytesPrefix }, // SS prefix
  357. { 0x37, ENTRY_CopyBytes1 }, // AAA
  358. { 0x38, ENTRY_CopyBytes2Mod }, // CMP /r
  359. { 0x39, ENTRY_CopyBytes2Mod }, // CMP /r
  360. { 0x3A, ENTRY_CopyBytes2Mod }, // CMP /r
  361. { 0x3B, ENTRY_CopyBytes2Mod }, // CMP /r
  362. { 0x3C, ENTRY_CopyBytes2 }, // CMP ib
  363. { 0x3D, ENTRY_CopyBytes3Or5 }, // CMP id
  364. { 0x3E, ENTRY_CopyBytesPrefix }, // DS prefix
  365. { 0x3F, ENTRY_CopyBytes1 }, // AAS
  366. { 0x40, ENTRY_CopyBytes1 }, // INC
  367. { 0x41, ENTRY_CopyBytes1 }, // INC
  368. { 0x42, ENTRY_CopyBytes1 }, // INC
  369. { 0x43, ENTRY_CopyBytes1 }, // INC
  370. { 0x44, ENTRY_CopyBytes1 }, // INC
  371. { 0x45, ENTRY_CopyBytes1 }, // INC
  372. { 0x46, ENTRY_CopyBytes1 }, // INC
  373. { 0x47, ENTRY_CopyBytes1 }, // INC
  374. { 0x48, ENTRY_CopyBytes1 }, // DEC
  375. { 0x49, ENTRY_CopyBytes1 }, // DEC
  376. { 0x4A, ENTRY_CopyBytes1 }, // DEC
  377. { 0x4B, ENTRY_CopyBytes1 }, // DEC
  378. { 0x4C, ENTRY_CopyBytes1 }, // DEC
  379. { 0x4D, ENTRY_CopyBytes1 }, // DEC
  380. { 0x4E, ENTRY_CopyBytes1 }, // DEC
  381. { 0x4F, ENTRY_CopyBytes1 }, // DEC
  382. { 0x50, ENTRY_CopyBytes1 }, // PUSH
  383. { 0x51, ENTRY_CopyBytes1 }, // PUSH
  384. { 0x52, ENTRY_CopyBytes1 }, // PUSH
  385. { 0x53, ENTRY_CopyBytes1 }, // PUSH
  386. { 0x54, ENTRY_CopyBytes1 }, // PUSH
  387. { 0x55, ENTRY_CopyBytes1 }, // PUSH
  388. { 0x56, ENTRY_CopyBytes1 }, // PUSH
  389. { 0x57, ENTRY_CopyBytes1 }, // PUSH
  390. { 0x58, ENTRY_CopyBytes1 }, // POP
  391. { 0x59, ENTRY_CopyBytes1 }, // POP
  392. { 0x5A, ENTRY_CopyBytes1 }, // POP
  393. { 0x5B, ENTRY_CopyBytes1 }, // POP
  394. { 0x5C, ENTRY_CopyBytes1 }, // POP
  395. { 0x5D, ENTRY_CopyBytes1 }, // POP
  396. { 0x5E, ENTRY_CopyBytes1 }, // POP
  397. { 0x5F, ENTRY_CopyBytes1 }, // POP
  398. { 0x60, ENTRY_CopyBytes1 }, // PUSHAD
  399. { 0x61, ENTRY_CopyBytes1 }, // POPAD
  400. { 0x62, ENTRY_CopyBytes2Mod }, // BOUND /r
  401. { 0x63, ENTRY_CopyBytes2Mod }, // ARPL /r
  402. { 0x64, ENTRY_CopyBytesPrefix }, // FS prefix
  403. { 0x65, ENTRY_CopyBytesPrefix }, // GS prefix
  404. { 0x66, ENTRY_Copy66 }, // Operand Prefix
  405. { 0x67, ENTRY_Copy67 }, // Address Prefix
  406. { 0x68, ENTRY_CopyBytes3Or5 }, // PUSH
  407. { 0x69, ENTRY_CopyBytes2ModOperand }, //
  408. { 0x6A, ENTRY_CopyBytes2 }, // PUSH
  409. { 0x6B, ENTRY_CopyBytes2Mod1 }, // IMUL /r ib
  410. { 0x6C, ENTRY_CopyBytes1 }, // INS
  411. { 0x6D, ENTRY_CopyBytes1 }, // INS
  412. { 0x6E, ENTRY_CopyBytes1 }, // OUTS/OUTSB
  413. { 0x6F, ENTRY_CopyBytes1 }, // OUTS/OUTSW
  414. { 0x70, ENTRY_CopyBytes2Jump }, // JO
  415. { 0x71, ENTRY_CopyBytes2Jump }, // JNO
  416. { 0x72, ENTRY_CopyBytes2Jump }, // JB/JC/JNAE
  417. { 0x73, ENTRY_CopyBytes2Jump }, // JAE/JNB/JNC
  418. { 0x74, ENTRY_CopyBytes2Jump }, // JE/JZ
  419. { 0x75, ENTRY_CopyBytes2Jump }, // JNE/JNZ
  420. { 0x76, ENTRY_CopyBytes2Jump }, // JBE/JNA
  421. { 0x77, ENTRY_CopyBytes2Jump }, // JA/JNBE
  422. { 0x78, ENTRY_CopyBytes2Jump }, // JS
  423. { 0x79, ENTRY_CopyBytes2Jump }, // JNS
  424. { 0x7A, ENTRY_CopyBytes2Jump }, // JP/JPE
  425. { 0x7B, ENTRY_CopyBytes2Jump }, // JNP/JPO
  426. { 0x7C, ENTRY_CopyBytes2Jump }, // JL/JNGE
  427. { 0x7D, ENTRY_CopyBytes2Jump }, // JGE/JNL
  428. { 0x7E, ENTRY_CopyBytes2Jump }, // JLE/JNG
  429. { 0x7F, ENTRY_CopyBytes2Jump }, // JG/JNLE
  430. { 0x80, ENTRY_CopyBytes2Mod1 }, // ADC/2 ib, etc.s
  431. { 0x81, ENTRY_CopyBytes2ModOperand }, //
  432. { 0x82, ENTRY_CopyBytes2 }, // MOV al,x
  433. { 0x83, ENTRY_CopyBytes2Mod1 }, // ADC/2 ib, etc.
  434. { 0x84, ENTRY_CopyBytes2Mod }, // TEST /r
  435. { 0x85, ENTRY_CopyBytes2Mod }, // TEST /r
  436. { 0x86, ENTRY_CopyBytes2Mod }, // XCHG /r @todo
  437. { 0x87, ENTRY_CopyBytes2Mod }, // XCHG /r @todo
  438. { 0x88, ENTRY_CopyBytes2Mod }, // MOV /r
  439. { 0x89, ENTRY_CopyBytes2Mod }, // MOV /r
  440. { 0x8A, ENTRY_CopyBytes2Mod }, // MOV /r
  441. { 0x8B, ENTRY_CopyBytes2Mod }, // MOV /r
  442. { 0x8C, ENTRY_CopyBytes2Mod }, // MOV /r
  443. { 0x8D, ENTRY_CopyBytes2Mod }, // LEA /r
  444. { 0x8E, ENTRY_CopyBytes2Mod }, // MOV /r
  445. { 0x8F, ENTRY_CopyBytes2Mod }, // POP /0
  446. { 0x90, ENTRY_CopyBytes1 }, // NOP
  447. { 0x91, ENTRY_CopyBytes1 }, // XCHG
  448. { 0x92, ENTRY_CopyBytes1 }, // XCHG
  449. { 0x93, ENTRY_CopyBytes1 }, // XCHG
  450. { 0x94, ENTRY_CopyBytes1 }, // XCHG
  451. { 0x95, ENTRY_CopyBytes1 }, // XCHG
  452. { 0x96, ENTRY_CopyBytes1 }, // XCHG
  453. { 0x97, ENTRY_CopyBytes1 }, // XCHG
  454. { 0x98, ENTRY_CopyBytes1 }, // CWDE
  455. { 0x99, ENTRY_CopyBytes1 }, // CDQ
  456. { 0x9A, ENTRY_CopyBytes5Or7Dynamic }, // CALL cp
  457. { 0x9B, ENTRY_CopyBytes1 }, // WAIT/FWAIT
  458. { 0x9C, ENTRY_CopyBytes1 }, // PUSHFD
  459. { 0x9D, ENTRY_CopyBytes1 }, // POPFD
  460. { 0x9E, ENTRY_CopyBytes1 }, // SAHF
  461. { 0x9F, ENTRY_CopyBytes1 }, // LAHF
  462. { 0xA0, ENTRY_CopyBytes3Or5Address }, // MOV
  463. { 0xA1, ENTRY_CopyBytes3Or5Address }, // MOV
  464. { 0xA2, ENTRY_CopyBytes3Or5Address }, // MOV
  465. { 0xA3, ENTRY_CopyBytes3Or5Address }, // MOV
  466. { 0xA4, ENTRY_CopyBytes1 }, // MOVS
  467. { 0xA5, ENTRY_CopyBytes1 }, // MOVS/MOVSD
  468. { 0xA6, ENTRY_CopyBytes1 }, // CMPS/CMPSB
  469. { 0xA7, ENTRY_CopyBytes1 }, // CMPS/CMPSW
  470. { 0xA8, ENTRY_CopyBytes2 }, // TEST
  471. { 0xA9, ENTRY_CopyBytes3Or5 }, // TEST
  472. { 0xAA, ENTRY_CopyBytes1 }, // STOS/STOSB
  473. { 0xAB, ENTRY_CopyBytes1 }, // STOS/STOSW
  474. { 0xAC, ENTRY_CopyBytes1 }, // LODS/LODSB
  475. { 0xAD, ENTRY_CopyBytes1 }, // LODS/LODSW
  476. { 0xAE, ENTRY_CopyBytes1 }, // SCAS/SCASB
  477. { 0xAF, ENTRY_CopyBytes1 }, // SCAS/SCASD
  478. { 0xB0, ENTRY_CopyBytes2 }, // MOV B0+rb
  479. { 0xB1, ENTRY_CopyBytes2 }, // MOV B0+rb
  480. { 0xB2, ENTRY_CopyBytes2 }, // MOV B0+rb
  481. { 0xB3, ENTRY_CopyBytes2 }, // MOV B0+rb
  482. { 0xB4, ENTRY_CopyBytes2 }, // MOV B0+rb
  483. { 0xB5, ENTRY_CopyBytes2 }, // MOV B0+rb
  484. { 0xB6, ENTRY_CopyBytes2 }, // MOV B0+rb
  485. { 0xB7, ENTRY_CopyBytes2 }, // MOV B0+rb
  486. { 0xB8, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
  487. { 0xB9, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
  488. { 0xBA, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
  489. { 0xBB, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
  490. { 0xBC, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
  491. { 0xBD, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
  492. { 0xBE, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
  493. { 0xBF, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
  494. { 0xC0, ENTRY_CopyBytes2Mod1 }, // RCL/2 ib, etc.
  495. { 0xC1, ENTRY_CopyBytes2Mod1 }, // RCL/2 ib, etc.
  496. { 0xC2, ENTRY_CopyBytes3 }, // RET
  497. { 0xC3, ENTRY_CopyBytes1 }, // RET
  498. { 0xC4, ENTRY_CopyBytes2Mod }, // LES
  499. { 0xC5, ENTRY_CopyBytes2Mod }, // LDS
  500. { 0xC6, ENTRY_CopyBytes2Mod1 }, // MOV
  501. { 0xC7, ENTRY_CopyBytes2ModOperand }, // MOV
  502. { 0xC8, ENTRY_CopyBytes4 }, // ENTER
  503. { 0xC9, ENTRY_CopyBytes1 }, // LEAVE
  504. { 0xCA, ENTRY_CopyBytes3Dynamic }, // RET
  505. { 0xCB, ENTRY_CopyBytes1Dynamic }, // RET
  506. { 0xCC, ENTRY_CopyBytes1Dynamic }, // INT 3
  507. { 0xCD, ENTRY_CopyBytes2Dynamic }, // INT ib
  508. { 0xCE, ENTRY_CopyBytes1Dynamic }, // INTO
  509. { 0xCF, ENTRY_CopyBytes1Dynamic }, // IRET
  510. { 0xD0, ENTRY_CopyBytes2Mod }, // RCL/2, etc.
  511. { 0xD1, ENTRY_CopyBytes2Mod }, // RCL/2, etc.
  512. { 0xD2, ENTRY_CopyBytes2Mod }, // RCL/2, etc.
  513. { 0xD3, ENTRY_CopyBytes2Mod }, // RCL/2, etc.
  514. { 0xD4, ENTRY_CopyBytes2 }, // AAM
  515. { 0xD5, ENTRY_CopyBytes2 }, // AAD
  516. { 0xD6, ENTRY_Invalid }, //
  517. { 0xD7, ENTRY_CopyBytes1 }, // XLAT/XLATB
  518. { 0xD8, ENTRY_CopyBytes2Mod }, // FADD, etc.
  519. { 0xD9, ENTRY_CopyBytes2Mod }, // F2XM1, etc.
  520. { 0xDA, ENTRY_CopyBytes2Mod }, // FLADD, etc.
  521. { 0xDB, ENTRY_CopyBytes2Mod }, // FCLEX, etc.
  522. { 0xDC, ENTRY_CopyBytes2Mod }, // FADD/0, etc.
  523. { 0xDD, ENTRY_CopyBytes2Mod }, // FFREE, etc.
  524. { 0xDE, ENTRY_CopyBytes2Mod }, // FADDP, etc.
  525. { 0xDF, ENTRY_CopyBytes2Mod }, // FBLD/4, etc.
  526. { 0xE0, ENTRY_CopyBytes2CantJump }, // LOOPNE cb
  527. { 0xE1, ENTRY_CopyBytes2CantJump }, // LOOPE cb
  528. { 0xE2, ENTRY_CopyBytes2CantJump }, // LOOP cb
  529. { 0xE3, ENTRY_CopyBytes2Jump }, // JCXZ/JECXZ
  530. { 0xE4, ENTRY_CopyBytes2 }, // IN ib
  531. { 0xE5, ENTRY_CopyBytes2 }, // IN id
  532. { 0xE6, ENTRY_CopyBytes2 }, // OUT ib
  533. { 0xE7, ENTRY_CopyBytes2 }, // OUT ib
  534. { 0xE8, ENTRY_CopyBytes3Or5Target }, // CALL cd
  535. { 0xE9, ENTRY_CopyBytes3Or5Target }, // JMP cd
  536. { 0xEA, ENTRY_CopyBytes5Or7Dynamic }, // JMP cp
  537. { 0xEB, ENTRY_CopyBytes2Jump }, // JMP cb
  538. { 0xEC, ENTRY_CopyBytes1 }, // IN ib
  539. { 0xED, ENTRY_CopyBytes1 }, // IN id
  540. { 0xEE, ENTRY_CopyBytes1 }, // OUT
  541. { 0xEF, ENTRY_CopyBytes1 }, // OUT
  542. { 0xF0, ENTRY_CopyBytesPrefix }, // LOCK prefix
  543. { 0xF1, ENTRY_Invalid }, //
  544. { 0xF2, ENTRY_CopyBytesPrefix }, // REPNE prefix
  545. { 0xF3, ENTRY_CopyBytesPrefix }, // REPE prefix
  546. { 0xF4, ENTRY_CopyBytes1 }, // HLT
  547. { 0xF5, ENTRY_CopyBytes1 }, // CMC
  548. { 0xF6, ENTRY_CopyF6 }, // TEST/0, DIV/6
  549. { 0xF7, ENTRY_CopyF7 }, // TEST/0, DIV/6
  550. { 0xF8, ENTRY_CopyBytes1 }, // CLC
  551. { 0xF9, ENTRY_CopyBytes1 }, // STC
  552. { 0xFA, ENTRY_CopyBytes1 }, // CLI
  553. { 0xFB, ENTRY_CopyBytes1 }, // STI
  554. { 0xFC, ENTRY_CopyBytes1 }, // CLD
  555. { 0xFD, ENTRY_CopyBytes1 }, // STD
  556. { 0xFE, ENTRY_CopyBytes2Mod }, // DEC/1,INC/0
  557. { 0xFF, ENTRY_CopyFF }, // CALL/2
  558. { 0, ENTRY_End },
  559. };
  560. const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable0F[257] =
  561. {
  562. { 0x00, ENTRY_CopyBytes2Mod }, // LLDT/2, etc.
  563. { 0x01, ENTRY_CopyBytes2Mod }, // INVLPG/7, etc.
  564. { 0x02, ENTRY_CopyBytes2Mod }, // LAR/r
  565. { 0x03, ENTRY_CopyBytes2Mod }, // LSL/r
  566. { 0x04, ENTRY_Invalid }, // _04
  567. { 0x05, ENTRY_Invalid }, // _05
  568. { 0x06, ENTRY_CopyBytes2 }, // CLTS
  569. { 0x07, ENTRY_Invalid }, // _07
  570. { 0x08, ENTRY_CopyBytes2 }, // INVD
  571. { 0x09, ENTRY_CopyBytes2 }, // WBINVD
  572. { 0x0A, ENTRY_Invalid }, // _0A
  573. { 0x0B, ENTRY_CopyBytes2 }, // UD2
  574. { 0x0C, ENTRY_Invalid }, // _0C
  575. { 0x0D, ENTRY_Invalid }, // _0D
  576. { 0x0E, ENTRY_Invalid }, // _0E
  577. { 0x0F, ENTRY_Invalid }, // _0F
  578. { 0x10, ENTRY_Invalid }, // _10
  579. { 0x11, ENTRY_Invalid }, // _11
  580. { 0x12, ENTRY_Invalid }, // _12
  581. { 0x13, ENTRY_Invalid }, // _13
  582. { 0x14, ENTRY_Invalid }, // _14
  583. { 0x15, ENTRY_Invalid }, // _15
  584. { 0x16, ENTRY_Invalid }, // _16
  585. { 0x17, ENTRY_Invalid }, // _17
  586. { 0x18, ENTRY_Invalid }, // _18
  587. { 0x19, ENTRY_Invalid }, // _19
  588. { 0x1A, ENTRY_Invalid }, // _1A
  589. { 0x1B, ENTRY_Invalid }, // _1B
  590. { 0x1C, ENTRY_Invalid }, // _1C
  591. { 0x1D, ENTRY_Invalid }, // _1D
  592. { 0x1E, ENTRY_Invalid }, // _1E
  593. { 0x1F, ENTRY_Invalid }, // _1F
  594. { 0x20, ENTRY_CopyBytes2Mod }, // MOV/r
  595. { 0x21, ENTRY_CopyBytes2Mod }, // MOV/r
  596. { 0x22, ENTRY_CopyBytes2Mod }, // MOV/r
  597. { 0x23, ENTRY_CopyBytes2Mod }, // MOV/r
  598. { 0x24, ENTRY_Invalid }, // _24
  599. { 0x25, ENTRY_Invalid }, // _25
  600. { 0x26, ENTRY_Invalid }, // _26
  601. { 0x27, ENTRY_Invalid }, // _27
  602. { 0x28, ENTRY_Invalid }, // _28
  603. { 0x29, ENTRY_Invalid }, // _29
  604. { 0x2A, ENTRY_Invalid }, // _2A
  605. { 0x2B, ENTRY_Invalid }, // _2B
  606. { 0x2C, ENTRY_Invalid }, // _2C
  607. { 0x2D, ENTRY_Invalid }, // _2D
  608. { 0x2E, ENTRY_Invalid }, // _2E
  609. { 0x2F, ENTRY_Invalid }, // _2F
  610. { 0x30, ENTRY_CopyBytes2 }, // WRMSR
  611. { 0x31, ENTRY_CopyBytes2 }, // RDTSC
  612. { 0x32, ENTRY_CopyBytes2 }, // RDMSR
  613. { 0x33, ENTRY_CopyBytes2 }, // RDPMC
  614. { 0x34, ENTRY_CopyBytes2 }, // SYSENTER
  615. { 0x35, ENTRY_CopyBytes2 }, // SYSEXIT
  616. { 0x36, ENTRY_Invalid }, // _36
  617. { 0x37, ENTRY_Invalid }, // _37
  618. { 0x38, ENTRY_Invalid }, // _38
  619. { 0x39, ENTRY_Invalid }, // _39
  620. { 0x3A, ENTRY_Invalid }, // _3A
  621. { 0x3B, ENTRY_Invalid }, // _3B
  622. { 0x3C, ENTRY_Invalid }, // _3C
  623. { 0x3D, ENTRY_Invalid }, // _3D
  624. { 0x3E, ENTRY_Invalid }, // _3E
  625. { 0x3F, ENTRY_Invalid }, // _3F
  626. { 0x40, ENTRY_CopyBytes2Mod }, // CMOVO (0F 40)
  627. { 0x41, ENTRY_CopyBytes2Mod }, // CMOVNO (0F 41)
  628. { 0x42, ENTRY_CopyBytes2Mod }, // CMOVB & CMOVNE (0F 42)
  629. { 0x43, ENTRY_CopyBytes2Mod }, // CMOVAE & CMOVNB (0F 43)
  630. { 0x44, ENTRY_CopyBytes2Mod }, // CMOVE & CMOVZ (0F 44)
  631. { 0x45, ENTRY_CopyBytes2Mod }, // CMOVNE & CMOVNZ (0F 45)
  632. { 0x46, ENTRY_CopyBytes2Mod }, // CMOVBE & CMOVNA (0F 46)
  633. { 0x47, ENTRY_CopyBytes2Mod }, // CMOVA & CMOVNBE (0F 47)
  634. { 0x48, ENTRY_CopyBytes2Mod }, // CMOVS (0F 48)
  635. { 0x49, ENTRY_CopyBytes2Mod }, // CMOVNS (0F 49)
  636. { 0x4A, ENTRY_CopyBytes2Mod }, // CMOVP & CMOVPE (0F 4A)
  637. { 0x4B, ENTRY_CopyBytes2Mod }, // CMOVNP & CMOVPO (0F 4B)
  638. { 0x4C, ENTRY_CopyBytes2Mod }, // CMOVL & CMOVNGE (0F 4C)
  639. { 0x4D, ENTRY_CopyBytes2Mod }, // CMOVGE & CMOVNL (0F 4D)
  640. { 0x4E, ENTRY_CopyBytes2Mod }, // CMOVLE & CMOVNG (0F 4E)
  641. { 0x4F, ENTRY_CopyBytes2Mod }, // CMOVG & CMOVNLE (0F 4F)
  642. { 0x50, ENTRY_Invalid }, // _50
  643. { 0x51, ENTRY_Invalid }, // _51
  644. { 0x52, ENTRY_Invalid }, // _52
  645. { 0x53, ENTRY_Invalid }, // _53
  646. { 0x54, ENTRY_Invalid }, // _54
  647. { 0x55, ENTRY_Invalid }, // _55
  648. { 0x56, ENTRY_Invalid }, // _56
  649. { 0x57, ENTRY_Invalid }, // _57
  650. { 0x58, ENTRY_Invalid }, // _58
  651. { 0x59, ENTRY_Invalid }, // _59
  652. { 0x5A, ENTRY_Invalid }, // _5A
  653. { 0x5B, ENTRY_Invalid }, // _5B
  654. { 0x5C, ENTRY_Invalid }, // _5C
  655. { 0x5D, ENTRY_Invalid }, // _5D
  656. { 0x5E, ENTRY_Invalid }, // _5E
  657. { 0x5F, ENTRY_Invalid }, // _5F
  658. { 0x60, ENTRY_CopyBytes2Mod }, // PUNPCKLBW/r
  659. { 0x61, ENTRY_Invalid }, // _61
  660. { 0x62, ENTRY_CopyBytes2Mod }, // PUNPCKLWD/r
  661. { 0x63, ENTRY_CopyBytes2Mod }, // PACKSSWB/r
  662. { 0x64, ENTRY_CopyBytes2Mod }, // PCMPGTB/r
  663. { 0x65, ENTRY_CopyBytes2Mod }, // PCMPGTW/r
  664. { 0x66, ENTRY_CopyBytes2Mod }, // PCMPGTD/r
  665. { 0x67, ENTRY_CopyBytes2Mod }, // PACKUSWB/r
  666. { 0x68, ENTRY_CopyBytes2Mod }, // PUNPCKHBW/r
  667. { 0x69, ENTRY_CopyBytes2Mod }, // PUNPCKHWD/r
  668. { 0x6A, ENTRY_CopyBytes2Mod }, // PUNPCKHDQ/r
  669. { 0x6B, ENTRY_CopyBytes2Mod }, // PACKSSDW/r
  670. { 0x6C, ENTRY_Invalid }, // _6C
  671. { 0x6D, ENTRY_Invalid }, // _6D
  672. { 0x6E, ENTRY_CopyBytes2Mod }, // MOVD/r
  673. { 0x6F, ENTRY_CopyBytes2Mod }, // MOV/r
  674. { 0x70, ENTRY_Invalid }, // _70
  675. { 0x71, ENTRY_CopyBytes2Mod1 }, // PSLLW/6 ib,PSRAW/4 ib,PSRLW/2 ib
  676. { 0x72, ENTRY_CopyBytes2Mod1 }, // PSLLD/6 ib,PSRAD/4 ib,PSRLD/2 ib
  677. { 0x73, ENTRY_CopyBytes2Mod1 }, // PSLLQ/6 ib,PSRLQ/2 ib
  678. { 0x74, ENTRY_CopyBytes2Mod }, // PCMPEQB/r
  679. { 0x75, ENTRY_CopyBytes2Mod }, // PCMPEQW/r
  680. { 0x76, ENTRY_CopyBytes2Mod }, // PCMPEQD/r
  681. { 0x77, ENTRY_CopyBytes2 }, // EMMS
  682. { 0x78, ENTRY_Invalid }, // _78
  683. { 0x79, ENTRY_Invalid }, // _79
  684. { 0x7A, ENTRY_Invalid }, // _7A
  685. { 0x7B, ENTRY_Invalid }, // _7B
  686. { 0x7C, ENTRY_Invalid }, // _7C
  687. { 0x7D, ENTRY_Invalid }, // _7D
  688. { 0x7E, ENTRY_CopyBytes2Mod }, // MOVD/r
  689. { 0x7F, ENTRY_CopyBytes2Mod }, // MOV/r
  690. { 0x80, ENTRY_CopyBytes3Or5Target }, // JO
  691. { 0x81, ENTRY_CopyBytes3Or5Target }, // JNO
  692. { 0x82, ENTRY_CopyBytes3Or5Target }, // JB,JC,JNAE
  693. { 0x83, ENTRY_CopyBytes3Or5Target }, // JAE,JNB,JNC
  694. { 0x84, ENTRY_CopyBytes3Or5Target }, // JE,JZ,JZ
  695. { 0x85, ENTRY_CopyBytes3Or5Target }, // JNE,JNZ
  696. { 0x86, ENTRY_CopyBytes3Or5Target }, // JBE,JNA
  697. { 0x87, ENTRY_CopyBytes3Or5Target }, // JA,JNBE
  698. { 0x88, ENTRY_CopyBytes3Or5Target }, // JS
  699. { 0x89, ENTRY_CopyBytes3Or5Target }, // JNS
  700. { 0x8A, ENTRY_CopyBytes3Or5Target }, // JP,JPE
  701. { 0x8B, ENTRY_CopyBytes3Or5Target }, // JNP,JPO
  702. { 0x8C, ENTRY_CopyBytes3Or5Target }, // JL,NGE
  703. { 0x8D, ENTRY_CopyBytes3Or5Target }, // JGE,JNL
  704. { 0x8E, ENTRY_CopyBytes3Or5Target }, // JLE,JNG
  705. { 0x8F, ENTRY_CopyBytes3Or5Target }, // JG,JNLE
  706. { 0x90, ENTRY_CopyBytes2Mod }, // CMOVO (0F 40)
  707. { 0x91, ENTRY_CopyBytes2Mod }, // CMOVNO (0F 41)
  708. { 0x92, ENTRY_CopyBytes2Mod }, // CMOVB & CMOVC & CMOVNAE (0F 42)
  709. { 0x93, ENTRY_CopyBytes2Mod }, // CMOVAE & CMOVNB & CMOVNC (0F 43)
  710. { 0x94, ENTRY_CopyBytes2Mod }, // CMOVE & CMOVZ (0F 44)
  711. { 0x95, ENTRY_CopyBytes2Mod }, // CMOVNE & CMOVNZ (0F 45)
  712. { 0x96, ENTRY_CopyBytes2Mod }, // CMOVBE & CMOVNA (0F 46)
  713. { 0x97, ENTRY_CopyBytes2Mod }, // CMOVA & CMOVNBE (0F 47)
  714. { 0x98, ENTRY_CopyBytes2Mod }, // CMOVS (0F 48)
  715. { 0x99, ENTRY_CopyBytes2Mod }, // CMOVNS (0F 49)
  716. { 0x9A, ENTRY_CopyBytes2Mod }, // CMOVP & CMOVPE (0F 4A)
  717. { 0x9B, ENTRY_CopyBytes2Mod }, // CMOVNP & CMOVPO (0F 4B)
  718. { 0x9C, ENTRY_CopyBytes2Mod }, // CMOVL & CMOVNGE (0F 4C)
  719. { 0x9D, ENTRY_CopyBytes2Mod }, // CMOVGE & CMOVNL (0F 4D)
  720. { 0x9E, ENTRY_CopyBytes2Mod }, // CMOVLE & CMOVNG (0F 4E)
  721. { 0x9F, ENTRY_CopyBytes2Mod }, // CMOVG & CMOVNLE (0F 4F)
  722. { 0xA0, ENTRY_CopyBytes2 }, // PUSH
  723. { 0xA1, ENTRY_CopyBytes2 }, // POP
  724. { 0xA2, ENTRY_CopyBytes2 }, // CPUID
  725. { 0xA3, ENTRY_CopyBytes2Mod }, // BT (0F A3)
  726. { 0xA4, ENTRY_CopyBytes2Mod1 }, // SHLD
  727. { 0xA5, ENTRY_CopyBytes2Mod }, // SHLD
  728. { 0xA6, ENTRY_Invalid }, // _A6
  729. { 0xA7, ENTRY_Invalid }, // _A7
  730. { 0xA8, ENTRY_CopyBytes2 }, // PUSH
  731. { 0xA9, ENTRY_CopyBytes2 }, // POP
  732. { 0xAA, ENTRY_CopyBytes2 }, // RSM
  733. { 0xAB, ENTRY_CopyBytes2Mod }, // BTS (0F AB)
  734. { 0xAC, ENTRY_CopyBytes2Mod1 }, // SHRD
  735. { 0xAD, ENTRY_CopyBytes2Mod }, // SHRD
  736. { 0xAE, ENTRY_CopyBytes2Mod }, // FXRSTOR/1,FXSAVE/0
  737. { 0xAF, ENTRY_CopyBytes2Mod }, // IMUL (0F AF)
  738. { 0xB0, ENTRY_CopyBytes2Mod }, // CMPXCHG (0F B0)
  739. { 0xB1, ENTRY_CopyBytes2Mod }, // CMPXCHG (0F B1)
  740. { 0xB2, ENTRY_CopyBytes2Mod }, // LSS/r
  741. { 0xB3, ENTRY_CopyBytes2Mod }, // BTR (0F B3)
  742. { 0xB4, ENTRY_CopyBytes2Mod }, // LFS/r
  743. { 0xB5, ENTRY_CopyBytes2Mod }, // LGS/r
  744. { 0xB6, ENTRY_CopyBytes2Mod }, // MOVZX/r
  745. { 0xB7, ENTRY_CopyBytes2Mod }, // MOVZX/r
  746. { 0xB8, ENTRY_Invalid }, // _B8
  747. { 0xB9, ENTRY_Invalid }, // _B9
  748. { 0xBA, ENTRY_CopyBytes2Mod1 }, // BT & BTC & BTR & BTS (0F BA)
  749. { 0xBB, ENTRY_CopyBytes2Mod }, // BTC (0F BB)
  750. { 0xBC, ENTRY_CopyBytes2Mod }, // BSF (0F BC)
  751. { 0xBD, ENTRY_CopyBytes2Mod }, // BSR (0F BD)
  752. { 0xBE, ENTRY_CopyBytes2Mod }, // MOVSX/r
  753. { 0xBF, ENTRY_CopyBytes2Mod }, // MOVSX/r
  754. { 0xC0, ENTRY_CopyBytes2Mod }, // XADD/r
  755. { 0xC1, ENTRY_CopyBytes2Mod }, // XADD/r
  756. { 0xC2, ENTRY_Invalid }, // _C2
  757. { 0xC3, ENTRY_Invalid }, // _C3
  758. { 0xC4, ENTRY_Invalid }, // _C4
  759. { 0xC5, ENTRY_Invalid }, // _C5
  760. { 0xC6, ENTRY_Invalid }, // _C6
  761. { 0xC7, ENTRY_CopyBytes2Mod }, // CMPXCHG8B (0F C7)
  762. { 0xC8, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
  763. { 0xC9, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
  764. { 0xCA, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
  765. { 0xCB, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
  766. { 0xCC, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
  767. { 0xCD, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
  768. { 0xCE, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
  769. { 0xCF, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
  770. { 0xD0, ENTRY_Invalid }, // _D0
  771. { 0xD1, ENTRY_CopyBytes2Mod }, // PSRLW/r
  772. { 0xD2, ENTRY_CopyBytes2Mod }, // PSRLD/r
  773. { 0xD3, ENTRY_CopyBytes2Mod }, // PSRLQ/r
  774. { 0xD4, ENTRY_Invalid }, // _D4
  775. { 0xD5, ENTRY_CopyBytes2Mod }, // PMULLW/r
  776. { 0xD6, ENTRY_Invalid }, // _D6
  777. { 0xD7, ENTRY_Invalid }, // _D7
  778. { 0xD8, ENTRY_CopyBytes2Mod }, // PSUBUSB/r
  779. { 0xD9, ENTRY_CopyBytes2Mod }, // PSUBUSW/r
  780. { 0xDA, ENTRY_Invalid }, // _DA
  781. { 0xDB, ENTRY_CopyBytes2Mod }, // PAND/r
  782. { 0xDC, ENTRY_CopyBytes2Mod }, // PADDUSB/r
  783. { 0xDD, ENTRY_CopyBytes2Mod }, // PADDUSW/r
  784. { 0xDE, ENTRY_Invalid }, // _DE
  785. { 0xDF, ENTRY_CopyBytes2Mod }, // PANDN/r
  786. { 0xE0, ENTRY_Invalid }, // _E0
  787. { 0xE1, ENTRY_CopyBytes2Mod }, // PSRAW/r
  788. { 0xE2, ENTRY_CopyBytes2Mod }, // PSRAD/r
  789. { 0xE3, ENTRY_Invalid }, // _E3
  790. { 0xE4, ENTRY_Invalid }, // _E4
  791. { 0xE5, ENTRY_CopyBytes2Mod }, // PMULHW/r
  792. { 0xE6, ENTRY_Invalid }, // _E6
  793. { 0xE7, ENTRY_Invalid }, // _E7
  794. { 0xE8, ENTRY_CopyBytes2Mod }, // PSUBB/r
  795. { 0xE9, ENTRY_CopyBytes2Mod }, // PSUBW/r
  796. { 0xEA, ENTRY_Invalid }, // _EA
  797. { 0xEB, ENTRY_CopyBytes2Mod }, // POR/r
  798. { 0xEC, ENTRY_CopyBytes2Mod }, // PADDSB/r
  799. { 0xED, ENTRY_CopyBytes2Mod }, // PADDSW/r
  800. { 0xEE, ENTRY_Invalid }, // _EE
  801. { 0xEF, ENTRY_CopyBytes2Mod }, // PXOR/r
  802. { 0xF0, ENTRY_Invalid }, // _F0
  803. { 0xF1, ENTRY_CopyBytes2Mod }, // PSLLW/r
  804. { 0xF2, ENTRY_CopyBytes2Mod }, // PSLLD/r
  805. { 0xF3, ENTRY_CopyBytes2Mod }, // PSLLQ/r
  806. { 0xF4, ENTRY_Invalid }, // _F4
  807. { 0xF5, ENTRY_CopyBytes2Mod }, // PMADDWD/r
  808. { 0xF6, ENTRY_Invalid }, // _F6
  809. { 0xF7, ENTRY_Invalid }, // _F7
  810. { 0xF8, ENTRY_CopyBytes2Mod }, // PSUBB/r
  811. { 0xF9, ENTRY_CopyBytes2Mod }, // PSUBW/r
  812. { 0xFA, ENTRY_CopyBytes2Mod }, // PSUBD/r
  813. { 0xFB, ENTRY_Invalid }, // _FB
  814. { 0xFC, ENTRY_CopyBytes2Mod }, // PADDB/r
  815. { 0xFD, ENTRY_CopyBytes2Mod }, // PADDW/r
  816. { 0xFE, ENTRY_CopyBytes2Mod }, // PADDD/r
  817. { 0xFF, ENTRY_Invalid }, // _FF
  818. { 0, ENTRY_End },
  819. };
  820. BOOL CDetourDis::SanityCheckSystem()
  821. {
  822. for (ULONG n = 0; n < 256; n++) {
  823. REFCOPYENTRY pEntry = &s_rceCopyTable[n];
  824. if (n != pEntry->nOpcode) {
  825. ASSERT(n == pEntry->nOpcode);
  826. return FALSE;
  827. }
  828. }
  829. if (s_rceCopyTable[256].pfCopy != NULL) {
  830. ASSERT(!"Missing end marker.");
  831. return FALSE;
  832. }
  833. for (n = 0; n < 256; n++) {
  834. REFCOPYENTRY pEntry = &s_rceCopyTable0F[n];
  835. if (n != pEntry->nOpcode) {
  836. ASSERT(n == pEntry->nOpcode);
  837. return FALSE;
  838. }
  839. }
  840. if (s_rceCopyTable0F[256].pfCopy != NULL) {
  841. ASSERT(!"Missing end marker.");
  842. return FALSE;
  843. }
  844. return TRUE;
  845. }
  846. //
  847. ///////////////////////////////////////////////////////////////// End of File.