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.

3162 lines
70 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. ia32emul.c
  5. Abstract:
  6. This module implements an x86 instruction decoder and emulator.
  7. Author:
  8. Samer Arafeh (samera) 30-Oct-2000
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "ki.h"
  14. #include "ia32def.h"
  15. #include "wow64t.h"
  16. #if DBG
  17. BOOLEAN KiIa32InstructionEmulationDbg = 0;
  18. #endif
  19. #define KiIa32GetX86Eflags(efl) efl.Value = __getReg(CV_IA64_AR24)
  20. #define KiIa32SetX86Eflags(efl) __setReg(CV_IA64_AR24, efl.Value)
  21. #define IA32_GETEFLAGS_CF(efl) (efl & 0x01UI64)
  22. //
  23. // Ia32 instruction handlers
  24. //
  25. NTSTATUS
  26. KiIa32InstructionAdc (
  27. IN PKTRAP_FRAME TrapFrame,
  28. IN PIA32_INSTRUCTION Instruction
  29. );
  30. NTSTATUS
  31. KiIa32InstructionAdd (
  32. IN PKTRAP_FRAME TrapFrame,
  33. IN PIA32_INSTRUCTION Instruction
  34. );
  35. NTSTATUS
  36. KiIa32InstructionArithmeticBitwiseHelper (
  37. IN PKTRAP_FRAME TrapFrame,
  38. IN PIA32_INSTRUCTION Instruction
  39. );
  40. NTSTATUS
  41. KiIa32InstructionBitTestHelper (
  42. IN PKTRAP_FRAME TrapFrame,
  43. IN PIA32_INSTRUCTION Instruction
  44. );
  45. NTSTATUS
  46. KiIa32InstructionOneParamHelper (
  47. IN PKTRAP_FRAME TrapFrame,
  48. IN PIA32_INSTRUCTION Instruction
  49. );
  50. NTSTATUS
  51. KiIa32InstructionXadd (
  52. IN PKTRAP_FRAME TrapFrame,
  53. IN PIA32_INSTRUCTION Instruction
  54. );
  55. NTSTATUS
  56. KiIa32InstructionXchg (
  57. IN PKTRAP_FRAME TrapFrame,
  58. IN PIA32_INSTRUCTION Instruction
  59. );
  60. NTSTATUS
  61. KiIa32InstructionCmpXchg (
  62. IN PKTRAP_FRAME TrapFrame,
  63. IN PIA32_INSTRUCTION Instruction
  64. );
  65. NTSTATUS
  66. KiIa32InstructionCmpXchg8b (
  67. IN PKTRAP_FRAME TrapFrame,
  68. IN PIA32_INSTRUCTION Instruction
  69. );
  70. NTSTATUS
  71. KiIa32InstructionMoveSeg (
  72. IN PKTRAP_FRAME TrapFrame,
  73. IN PIA32_INSTRUCTION Instruction
  74. );
  75. //
  76. // Opcode Ids
  77. //
  78. typedef enum _IA32_OPCODE
  79. {
  80. Ia32_Adc,
  81. Ia32_Add,
  82. Ia32_And,
  83. Ia32_Bt,
  84. Ia32_Btc,
  85. Ia32_Btr,
  86. Ia32_Bts,
  87. Ia32_Cmpxchg,
  88. Ia32_Cmpxchg8b,
  89. Ia32_Dec,
  90. Ia32_Inc,
  91. Ia32_Neg,
  92. Ia32_Not,
  93. Ia32_Or,
  94. Ia32_Sbb,
  95. Ia32_Sub,
  96. Ia32_Xadd,
  97. Ia32_Xchg,
  98. Ia32_Xor,
  99. Ia32_MovToSeg,
  100. //
  101. // This needs always to be the last element
  102. //
  103. Ia32_LastOpcode
  104. } IA32_OPCODE;
  105. //
  106. // Array of Ia32 instruction handlers
  107. // NOTE : The following table must be in sync with the above enum.
  108. //
  109. typedef NTSTATUS (*IA32_INSTRUCTION_HANDLER) (PKTRAP_FRAME, PIA32_INSTRUCTION);
  110. IA32_INSTRUCTION_HANDLER KiIa32InstructionHandler [] =
  111. {
  112. KiIa32InstructionAdc,
  113. KiIa32InstructionAdd,
  114. KiIa32InstructionArithmeticBitwiseHelper,
  115. KiIa32InstructionBitTestHelper,
  116. KiIa32InstructionBitTestHelper,
  117. KiIa32InstructionBitTestHelper,
  118. KiIa32InstructionBitTestHelper,
  119. KiIa32InstructionCmpXchg,
  120. KiIa32InstructionCmpXchg8b,
  121. KiIa32InstructionOneParamHelper,
  122. KiIa32InstructionOneParamHelper,
  123. KiIa32InstructionOneParamHelper,
  124. KiIa32InstructionOneParamHelper,
  125. KiIa32InstructionArithmeticBitwiseHelper,
  126. KiIa32InstructionAdc,
  127. KiIa32InstructionAdd,
  128. KiIa32InstructionXadd,
  129. KiIa32InstructionXchg,
  130. KiIa32InstructionArithmeticBitwiseHelper,
  131. KiIa32InstructionMoveSeg,
  132. NULL
  133. };
  134. #if DBG
  135. PCHAR KiIa32InstructionHandlerNames [] =
  136. {
  137. "KiIa32InstructionAdc",
  138. "KiIa32InstructionAdd",
  139. "KiIa32InstructionAnd",
  140. "KiIa32InstructionBt",
  141. "KiIa32InstructionBtc",
  142. "KiIa32InstructionBtr",
  143. "KiIa32InstructionBts",
  144. "KiIa32InstructionCmpXchg",
  145. "KiIa32InstructionCmpXchg8b",
  146. "KiIa32InstructionDec",
  147. "KiIa32InstructionInc",
  148. "KiIa32InstructionNeg",
  149. "KiIa32InstructionNot",
  150. "KiIa32InstructionOr",
  151. "KiIa32InstructionSbb",
  152. "KiIa32InstructionSub",
  153. "KiIa32InstructionXadd",
  154. "KiIa32InstructionXchg",
  155. "KiIa32InstructionXor",
  156. "KiIa32InstructionMoveSeg",
  157. NULL,
  158. };
  159. #endif
  160. IA32_OPCODE_DESCRIPTION OpcodesDescription[] =
  161. {
  162. //
  163. // Adc
  164. //
  165. // Adc r/m8, imm8
  166. {
  167. 0x80, 0x00, 0x02, 0x11, IA32_PARAM_RM8_IMM8, Ia32_Adc
  168. },
  169. // Adc r/m, imm
  170. {
  171. 0x81, 0x00, 0x02, 0x11, IA32_PARAM_RM_IMM, Ia32_Adc
  172. },
  173. // Adc r/m, imm8 (sign)
  174. {
  175. 0x83, 0x00, 0x02, 0x11, IA32_PARAM_RM_IMM8SIGN, Ia32_Adc
  176. },
  177. // Adc r/m8, r8
  178. {
  179. 0x10, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_Adc
  180. },
  181. // Adc r/m, r
  182. {
  183. 0x11, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_Adc
  184. },
  185. // Adc r, r/m8
  186. {
  187. 0x12, 0x00, 0x00, 0x01, IA32_PARAM_R_RM8, Ia32_Adc
  188. },
  189. // Adc r, r/m
  190. {
  191. 0x13, 0x00, 0x00, 0x01, IA32_PARAM_R_RM, Ia32_Adc
  192. },
  193. //
  194. // Add
  195. //
  196. // Add r/m8, imm8
  197. {
  198. 0x80, 0x00, 0x00, 0x11, IA32_PARAM_RM8_IMM8, Ia32_Add
  199. },
  200. // Add r/m, imm
  201. {
  202. 0x81, 0x00, 0x00, 0x11, IA32_PARAM_RM_IMM, Ia32_Add
  203. },
  204. // Add r/m, imm8 (sign)
  205. {
  206. 0x83, 0x00, 0x00, 0x11, IA32_PARAM_RM_IMM8SIGN, Ia32_Add
  207. },
  208. // Add r/m8, r8
  209. {
  210. 0x00, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_Add
  211. },
  212. // Add r/m, r
  213. {
  214. 0x01, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_Add
  215. },
  216. // Add r, r/m8
  217. {
  218. 0x02, 0x00, 0x00, 0x01, IA32_PARAM_R_RM8, Ia32_Add
  219. },
  220. // Add r, r/m
  221. {
  222. 0x03, 0x00, 0x00, 0x01, IA32_PARAM_R_RM, Ia32_Add
  223. },
  224. //
  225. // And
  226. //
  227. // And r/m8, imm8
  228. {
  229. 0x80, 0x00, 0x04, 0x11, IA32_PARAM_RM8_IMM8, Ia32_And
  230. },
  231. // And r/m, imm
  232. {
  233. 0x81, 0x00, 0x04, 0x11, IA32_PARAM_RM_IMM, Ia32_And
  234. },
  235. // And r/m, imm8
  236. {
  237. 0x83, 0x00, 0x04, 0x11, IA32_PARAM_RM_IMM8SIGN, Ia32_And
  238. },
  239. // And r/m8, r8
  240. {
  241. 0x20, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_And
  242. },
  243. // And rm, r
  244. {
  245. 0x21, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_And
  246. },
  247. // And r8, r/m8
  248. {
  249. 0x22, 0x00, 0x00, 0x01, IA32_PARAM_R_RM8, Ia32_And
  250. },
  251. // And r, r/m
  252. {
  253. 0x23, 0x00, 0x00, 0x01, IA32_PARAM_R_RM, Ia32_And
  254. },
  255. //
  256. // Or
  257. //
  258. // Or r/m8, imm8
  259. {
  260. 0x80, 0x00, 0x01, 0x11, IA32_PARAM_RM8_IMM8, Ia32_Or
  261. },
  262. // Or r/m, imm
  263. {
  264. 0x81, 0x00, 0x01, 0x11, IA32_PARAM_RM_IMM, Ia32_Or
  265. },
  266. // Or r/m, imm8
  267. {
  268. 0x83, 0x00, 0x01, 0x11, IA32_PARAM_RM_IMM8SIGN, Ia32_Or
  269. },
  270. // Or r/m8, r8
  271. {
  272. 0x08, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_Or
  273. },
  274. // Or rm, r
  275. {
  276. 0x09, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_Or
  277. },
  278. // Or r8, r/m8
  279. {
  280. 0x0a, 0x00, 0x00, 0x01, IA32_PARAM_R_RM8, Ia32_Or
  281. },
  282. // Or r, r/m
  283. {
  284. 0x0b, 0x00, 0x00, 0x01, IA32_PARAM_R_RM, Ia32_Or
  285. },
  286. //
  287. // Xor
  288. //
  289. // Xor r/m8, imm8
  290. {
  291. 0x80, 0x00, 0x06, 0x11, IA32_PARAM_RM8_IMM8, Ia32_Xor
  292. },
  293. // Xor r/m, imm
  294. {
  295. 0x81, 0x00, 0x06, 0x11, IA32_PARAM_RM_IMM, Ia32_Xor
  296. },
  297. // Xor r/m, imm8
  298. {
  299. 0x83, 0x00, 0x06, 0x11, IA32_PARAM_RM_IMM8SIGN, Ia32_Xor
  300. },
  301. // Xor r/m8, r8
  302. {
  303. 0x30, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_Xor
  304. },
  305. // Xor rm, r
  306. {
  307. 0x31, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_Xor
  308. },
  309. // Xor r8, r/m8
  310. {
  311. 0x32, 0x00, 0x00, 0x01, IA32_PARAM_R_RM8, Ia32_Xor
  312. },
  313. // Xor r, r/m
  314. {
  315. 0x33, 0x00, 0x00, 0x01, IA32_PARAM_R_RM, Ia32_Xor
  316. },
  317. //
  318. // Inc
  319. //
  320. // Inc r/m8
  321. {
  322. 0xfe, 0x00, 0x00, 0x11, IA32_PARAM_RM8, Ia32_Inc
  323. },
  324. // Inc r/m
  325. {
  326. 0xff, 0x00, 0x00, 0x11, IA32_PARAM_RM, Ia32_Inc
  327. },
  328. //
  329. // Dec
  330. //
  331. // Dec r/m8
  332. {
  333. 0xfe, 0x00, 0x01, 0x11, IA32_PARAM_RM8, Ia32_Dec
  334. },
  335. // Dec r/m
  336. {
  337. 0xff, 0x00, 0x01, 0x11, IA32_PARAM_RM, Ia32_Dec
  338. },
  339. //
  340. // Xchg
  341. //
  342. // Xchg r/m8, r
  343. {
  344. 0x86, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_Xchg
  345. },
  346. // Xchg r/m, r
  347. {
  348. 0x87, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_Xchg
  349. },
  350. //
  351. // Cmpxchg
  352. //
  353. // Cmpxchg r/m8, r
  354. {
  355. 0x0f, 0xb0, 0x00, 0x02, IA32_PARAM_RM8_R, Ia32_Cmpxchg
  356. },
  357. // Cmpxchg r/m, r
  358. {
  359. 0x0f, 0xb1, 0x00, 0x02, IA32_PARAM_RM_R, Ia32_Cmpxchg
  360. },
  361. //
  362. // Cmpxchg8b
  363. //
  364. // Cmpxchg8b m64
  365. {
  366. 0x0f, 0xc7, 0x01, 0x12, IA32_PARAM_RM, Ia32_Cmpxchg8b
  367. },
  368. //
  369. // Xadd
  370. //
  371. // Xadd r/m8, r
  372. {
  373. 0x0f, 0xc0, 0x00, 0x02, IA32_PARAM_RM8_R, Ia32_Xadd
  374. },
  375. // Xadd r/m, r
  376. {
  377. 0x0f, 0xc1, 0x00, 0x02, IA32_PARAM_RM_R, Ia32_Xadd
  378. },
  379. //
  380. // Neg
  381. //
  382. // Neg r/m8
  383. {
  384. 0xf6, 0x00, 0x03, 0x11, IA32_PARAM_RM8, Ia32_Neg
  385. },
  386. // Neg r/m
  387. {
  388. 0xf7, 0x00, 0x03, 0x11, IA32_PARAM_RM, Ia32_Neg
  389. },
  390. //
  391. // Not
  392. //
  393. // Not r/m8
  394. {
  395. 0xf6, 0x00, 0x02, 0x11, IA32_PARAM_RM8, Ia32_Not
  396. },
  397. // Not r/m
  398. {
  399. 0xf7, 0x00, 0x02, 0x11, IA32_PARAM_RM, Ia32_Not
  400. },
  401. //
  402. // Bt (Bit Test)
  403. //
  404. // Bt r/m, r
  405. {
  406. 0x0f, 0xa3, 0x00, 0x02, IA32_PARAM_RM_R, Ia32_Bt
  407. },
  408. // Bt r/m, imm8
  409. {
  410. 0x0f, 0xba, 0x04, 0x12, IA32_PARAM_RM_IMM8SIGN, Ia32_Bt
  411. },
  412. //
  413. // Btc
  414. //
  415. // Btc r/m, r
  416. {
  417. 0x0f, 0xbb, 0x00, 0x02, IA32_PARAM_RM_R, Ia32_Btc
  418. },
  419. // Btc r/m, imm8
  420. {
  421. 0x0f, 0xba, 0x07, 0x12, IA32_PARAM_RM_IMM8SIGN, Ia32_Btc
  422. },
  423. //
  424. // Btr
  425. //
  426. // Btr r/m, r
  427. {
  428. 0x0f, 0xb3, 0x00, 0x02, IA32_PARAM_RM_R, Ia32_Btr
  429. },
  430. // Btr r/m, imm8
  431. {
  432. 0x0f, 0xba, 0x06, 0x12, IA32_PARAM_RM_IMM8SIGN, Ia32_Btr
  433. },
  434. //
  435. // Bts
  436. //
  437. // Bts r/m, r
  438. {
  439. 0x0f, 0xab, 0x00, 0x02, IA32_PARAM_RM_R, Ia32_Bts
  440. },
  441. // Bts r/m, imm8
  442. {
  443. 0x0f, 0xba, 0x05, 0x12, IA32_PARAM_RM_IMM8SIGN, Ia32_Bts
  444. },
  445. //
  446. // Sub
  447. //
  448. // Sub r/m8, imm8
  449. {
  450. 0x80, 0x00, 0x05, 0x11, IA32_PARAM_RM8_IMM8, Ia32_Sub
  451. },
  452. // Sub r/m, imm
  453. {
  454. 0x81, 0x00, 0x05, 0x11, IA32_PARAM_RM_IMM, Ia32_Sub
  455. },
  456. // Sub r/m, imm8 (sign)
  457. {
  458. 0x83, 0x00, 0x05, 0x11, IA32_PARAM_RM_IMM8SIGN, Ia32_Sub
  459. },
  460. // Sub r/m8, r8
  461. {
  462. 0x28, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_Sub
  463. },
  464. // Sub r/m, r
  465. {
  466. 0x29, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_Sub
  467. },
  468. // Sub r, r/m8
  469. {
  470. 0x2a, 0x00, 0x00, 0x01, IA32_PARAM_R_RM8, Ia32_Sub
  471. },
  472. // Sub r, r/m
  473. {
  474. 0x2b, 0x00, 0x00, 0x01, IA32_PARAM_R_RM, Ia32_Sub
  475. },
  476. //
  477. // Sbb
  478. //
  479. // Sbb r/m8, imm8
  480. {
  481. 0x80, 0x00, 0x03, 0x11, IA32_PARAM_RM8_IMM8, Ia32_Sbb
  482. },
  483. // Sbb r/m, imm
  484. {
  485. 0x81, 0x00, 0x03, 0x11, IA32_PARAM_RM_IMM, Ia32_Sbb
  486. },
  487. // Sbb r/m, imm8 (sign)
  488. {
  489. 0x83, 0x00, 0x03, 0x11, IA32_PARAM_RM_IMM8SIGN, Ia32_Sbb
  490. },
  491. // Sbb r/m8, r8
  492. {
  493. 0x18, 0x00, 0x00, 0x01, IA32_PARAM_RM8_R, Ia32_Sbb
  494. },
  495. // Sbb r/m, r
  496. {
  497. 0x19, 0x00, 0x00, 0x01, IA32_PARAM_RM_R, Ia32_Sbb
  498. },
  499. // Sbb r, r/m8
  500. {
  501. 0x1a, 0x00, 0x00, 0x01, IA32_PARAM_R_RM8, Ia32_Sbb
  502. },
  503. // Sbb r, r/m
  504. {
  505. 0x1b, 0x00, 0x00, 0x01, IA32_PARAM_R_RM, Ia32_Sbb
  506. },
  507. //
  508. // Mov
  509. //
  510. // Mov seg-reg, r/m8
  511. {
  512. 0x8e, 0x00, 0x00, 0x01, IA32_PARAM_SEGREG_RM8, Ia32_MovToSeg
  513. },
  514. // Mov seg-reg, r/m
  515. {
  516. 0x8e, 0x00, 0x00, 0x01, IA32_PARAM_SEGREG_RM, Ia32_MovToSeg
  517. },
  518. };
  519. //
  520. // Fast mutex that will serialize access to the instruction
  521. // emulator when the lock prefix is set.
  522. //
  523. FAST_MUTEX KiIa32MisalignedLockFastMutex;
  524. #define KiIa32AcquireMisalignedLockFastMutex() ExAcquireFastMutex(&KiIa32MisalignedLockFastMutex)
  525. #define KiIa32ReleaseMisalignedLockFastMutex() ExReleaseFastMutex(&KiIa32MisalignedLockFastMutex)
  526. //
  527. // This table contains the offset into the KTRAP_FRAME
  528. // for the appropriate register. This table is based on the
  529. // needs of the x86 instruction R/M bits
  530. //
  531. const ULONG RegOffsetTable[8] =
  532. {
  533. FIELD_OFFSET(KTRAP_FRAME, IntV0), // EAX
  534. FIELD_OFFSET(KTRAP_FRAME, IntT2), // ECX
  535. FIELD_OFFSET(KTRAP_FRAME, IntT3), // EDX
  536. FIELD_OFFSET(KTRAP_FRAME, IntT4), // EBX
  537. FIELD_OFFSET(KTRAP_FRAME, IntSp), // ESP
  538. FIELD_OFFSET(KTRAP_FRAME, IntTeb), // EBP
  539. FIELD_OFFSET(KTRAP_FRAME, IntT5), // ESI
  540. FIELD_OFFSET(KTRAP_FRAME, IntT6) // EDI
  541. };
  542. ULONG_PTR GetX86RegOffset (
  543. IN PKTRAP_FRAME TrapFrame,
  544. IN ULONG RegisterBase
  545. )
  546. /*++
  547. Routine Description:
  548. Retreives the offset into the aliased ia64 register for the ia32 register
  549. inside the trap frame.
  550. Arguments:
  551. TrapFrame - Pointer to TrapFrame on the stack.
  552. RegisterBase - Register number to retrieve the offset for.
  553. Return Value:
  554. Address of ia64 alias register for the ia32 register.
  555. --*/
  556. {
  557. return (ULONG_PTR)((PCHAR)TrapFrame + RegOffsetTable[RegisterBase]);
  558. }
  559. ULONG GetX86Reg (
  560. IN PKTRAP_FRAME TrapFrame,
  561. IN ULONG RegisterBase
  562. )
  563. /*++
  564. Routine Description:
  565. Retreives the ia32 register value.
  566. Arguments:
  567. TrapFrame - Pointer to TrapFrame on the stack.
  568. RegisterBase - Register number to retrieve the value for.
  569. Return Value:
  570. Ia32 register context.
  571. --*/
  572. {
  573. return (ULONG)(*(PULONG_PTR)GetX86RegOffset(TrapFrame, RegisterBase));
  574. }
  575. NTSTATUS
  576. KiIa32InitializeLockFastMutex (
  577. VOID
  578. )
  579. /*++
  580. Routine Description:
  581. Initializes the misaligned lock fast mutex. Used to serialize
  582. access if the r/m address is misaligned.
  583. Arguments:
  584. None.
  585. Return Value:
  586. NTSTATUS.
  587. --*/
  588. {
  589. ExInitializeFastMutex (&KiIa32MisalignedLockFastMutex);
  590. return STATUS_SUCCESS;
  591. }
  592. LONG
  593. KiIa32ComputeSIBAddress(
  594. IN PKTRAP_FRAME Frame,
  595. IN LONG Displacement,
  596. IN UCHAR Sib,
  597. IN UCHAR ModRm
  598. )
  599. /*++
  600. Routine Description:
  601. Compute an effective address based on the SIB bytes in an instruction
  602. using the register values in the trap frame
  603. Arguments:
  604. Frame - Pointer to iA32 TrapFrame in the stack.
  605. Displacement - The value of the displacement byte. If no displacement, this
  606. value should be passed in as zero.
  607. Sib - The sib byte that is causing all the trouble.
  608. ModRm - ModRm instruction value
  609. Return Value:
  610. The effective address to use for the memory operation
  611. --*/
  612. {
  613. LONG Base;
  614. LONG Index;
  615. LONG Scale;
  616. //
  617. // First get the base address that we will be using
  618. //
  619. if ((Sib & MI_SIB_BASEMASK) == 5)
  620. {
  621. //
  622. // Handle the special case where we don't use EBP for the base
  623. //
  624. //
  625. // EBP is an implicit reg-base if the Mod is not zero.
  626. //
  627. if ((ModRm >> MI_MODSHIFT) != 0) {
  628. Base = GetX86Reg (Frame, IA32_REG_EBP);
  629. } else {
  630. Base = 0;
  631. }
  632. }
  633. else
  634. {
  635. Base = GetX86Reg (Frame, (Sib & MI_SIB_BASEMASK) >> MI_SIB_BASESHIFT);
  636. }
  637. //
  638. // Now get the Index
  639. //
  640. if ((Sib & MI_SIB_INDEXMASK) == MI_SIB_INDEXNONE)
  641. {
  642. //
  643. // Handle the special case where we don't have an index
  644. //
  645. Index = 0;
  646. }
  647. else
  648. {
  649. Index = GetX86Reg (Frame, (Sib & MI_SIB_INDEXMASK) >> MI_SIB_INDEXSHIFT);
  650. }
  651. Scale = 1 << ((Sib & MI_SIB_SSMASK) >> MI_SIB_SSSHIFT);
  652. return (Base + (Index * Scale) + Displacement);
  653. }
  654. BOOLEAN
  655. KiIa32Compute32BitEffectiveAddress(
  656. IN PKTRAP_FRAME Frame,
  657. IN OUT PUCHAR *InstAddr,
  658. OUT PUINT_PTR Addr,
  659. OUT PBOOLEAN RegisterMode
  660. )
  661. /*++
  662. Routine Description:
  663. Compute an effective address based on bytes in memory and the register
  664. values passed in via the ia64 stack frame. The addressing mode is assumed to
  665. be 32-bit.
  666. Arguments:
  667. Frame - Pointer to iA32 TrapFrame in the stack
  668. InstAddr - Pointer to the first byte after the opcode.
  669. Addr - Effective address.
  670. RegisterMode - Indicates whether the effective address is inside a register or memory.
  671. Return Value:
  672. Returns TRUE if able to compute the EA, else returns FALSE.
  673. Note:
  674. Does not verify permission on an Effective Address. It only computes the
  675. value and lets someone else worry if the process should have access to
  676. that memory location.
  677. --*/
  678. {
  679. UNALIGNED ULONG * UlongAddress;
  680. UCHAR ModRm;
  681. UCHAR Sib = 0;
  682. LONG UNALIGNED *DisplacementPtr;
  683. BOOLEAN ReturnCode = TRUE;
  684. //
  685. // This needs to be a signed value. Start off assuming no displacement
  686. //
  687. LONG Displacement = 0;
  688. try
  689. {
  690. ModRm = *(*InstAddr)++;
  691. //
  692. // handle the register case first
  693. //
  694. if ((ModRm >> MI_MODSHIFT) == 3)
  695. {
  696. //
  697. // yup, we have a register - the easy case...
  698. //
  699. *Addr = GetX86RegOffset (Frame, ModRm & MI_RMMASK);
  700. *RegisterMode = TRUE;
  701. return ReturnCode;
  702. }
  703. *RegisterMode = FALSE;
  704. //
  705. // See if we have a SIB
  706. //
  707. if ((ModRm & MI_RMMASK) == 4)
  708. {
  709. Sib = *(*InstAddr)++;
  710. }
  711. //
  712. // Now decode the destination bits
  713. //
  714. switch (ModRm >> MI_MODSHIFT)
  715. {
  716. case 0:
  717. //
  718. // We have an indirect through a register
  719. //
  720. switch (ModRm & MI_RMMASK)
  721. {
  722. case 4:
  723. //
  724. // Deal with the SIB
  725. //
  726. *Addr = KiIa32ComputeSIBAddress (Frame, Displacement, Sib, ModRm);
  727. break;
  728. case 5:
  729. //
  730. // We have a 32-bit indirect...
  731. //
  732. UlongAddress = (UNALIGNED ULONG *)*InstAddr;
  733. *Addr = *UlongAddress;
  734. *InstAddr = (PUCHAR) (UlongAddress + 1);
  735. break;
  736. default:
  737. //
  738. // The default case is get the address from the register
  739. //
  740. *Addr = GetX86Reg (Frame, (ModRm & MI_RMMASK));
  741. break;
  742. }
  743. break;
  744. case 1:
  745. //
  746. // we have an 8 bit displacement, so grab the next byte
  747. //
  748. Displacement = (signed char) (*(*InstAddr)++);
  749. if ((ModRm & MI_RMMASK) == 4)
  750. {
  751. //
  752. // Have a SIB, so do that
  753. //
  754. *Addr = KiIa32ComputeSIBAddress (Frame, Displacement, Sib, ModRm);
  755. }
  756. else
  757. {
  758. //
  759. // No SIB, life is easy
  760. //
  761. *Addr = GetX86Reg (Frame, (ModRm & MI_RMMASK)) + Displacement;
  762. }
  763. break;
  764. case 2:
  765. //
  766. // we have a 32-bit displacement, so grab the next 4 bytes
  767. //
  768. DisplacementPtr = (PLONG) (*InstAddr);
  769. Displacement = *DisplacementPtr++;
  770. *InstAddr = (PUCHAR)DisplacementPtr;
  771. if ((ModRm & MI_RMMASK) == 4)
  772. {
  773. //
  774. // Have a SIB, so do that
  775. //
  776. *Addr = KiIa32ComputeSIBAddress (Frame, Displacement, Sib, ModRm);
  777. }
  778. else
  779. {
  780. //
  781. // No SIB, life is easy
  782. //
  783. *Addr = GetX86Reg (Frame, (ModRm & MI_RMMASK)) + Displacement;
  784. }
  785. break;
  786. default:
  787. //
  788. // we should have handled case 3 (register access)
  789. // before getting here...
  790. //
  791. ReturnCode = FALSE;
  792. break;
  793. }
  794. }
  795. except (EXCEPTION_EXECUTE_HANDLER)
  796. {
  797. ReturnCode = FALSE;
  798. #if DBG
  799. if (KiIa32InstructionEmulationDbg)
  800. {
  801. DbgPrint("KE: KiIa32Compute32BitEffectiveAddress - Exception %lx\n",
  802. GetExceptionCode());
  803. }
  804. #endif
  805. }
  806. //
  807. // Make sure the address stays within 4GB range
  808. //
  809. if (ReturnCode == TRUE) {
  810. *Addr = (*Addr & 0x000000007fffffffI64);
  811. }
  812. return ReturnCode;
  813. }
  814. BOOLEAN
  815. KiIa32Compute16BitEffectiveAddress (
  816. IN PKTRAP_FRAME Frame,
  817. IN OUT PUCHAR *InstAddr,
  818. OUT PUINT_PTR Addr,
  819. OUT PBOOLEAN RegisterMode
  820. )
  821. /*++
  822. Routine Description:
  823. Compute an effective address based on bytes in memory and
  824. the register values passed in via the ia64 stack frame. The addressing
  825. mode is assumed to be 16-bit.
  826. Arguments:
  827. Frame - Pointer to iA32 TrapFrame in the stack.
  828. InstAddr - Pointer to the first byte after the opcode.
  829. Addr - Effective address.
  830. RegisterMode - Indicates whether the effective address is inside a register or memory.
  831. Return Value:
  832. Returns TRUE if able to compute the EA, else returns FALSE.
  833. Note:
  834. Does not verify permission on an Effective Address. It only computes the
  835. value and lets someone else worry if the process should have access to
  836. that memory location.
  837. --*/
  838. {
  839. UCHAR ModRm;
  840. UCHAR DisplacementType = IA32_DISP_NONE;
  841. USHORT UNALIGNED *Disp16;
  842. LONG EffectiveAddress = 0;
  843. BOOLEAN ReturnCode = TRUE;
  844. try
  845. {
  846. //
  847. // Read in the Mod/Rm and increment the instruction address
  848. //
  849. ModRm = *(*InstAddr)++;
  850. *RegisterMode = FALSE;
  851. //
  852. // First pass
  853. //
  854. switch (ModRm >> MI_MODSHIFT)
  855. {
  856. case 0:
  857. if ((ModRm & MI_RMMASK) == 6)
  858. {
  859. Disp16 = (USHORT UNALIGNED *) InstAddr;
  860. *Addr = *Disp16;
  861. *InstAddr = (*InstAddr + 2);
  862. return ReturnCode;
  863. }
  864. DisplacementType = IA32_DISP_NONE;
  865. break;
  866. case 1:
  867. DisplacementType = IA32_DISP8;
  868. break;
  869. case 2:
  870. DisplacementType = IA32_DISP16;
  871. break;
  872. case 3:
  873. *Addr = GetX86RegOffset (Frame, ModRm & MI_RMMASK);
  874. *RegisterMode = TRUE;
  875. return ReturnCode;
  876. }
  877. //
  878. // Second pass
  879. //
  880. switch (ModRm & MI_RMMASK)
  881. {
  882. case 0:
  883. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_EBX) & 0xffff) +
  884. (GetX86Reg(Frame, IA32_REG_ESI) & 0xffff) ;
  885. break;
  886. case 1:
  887. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_EBX) & 0xffff) +
  888. (GetX86Reg(Frame, IA32_REG_EDI) & 0xffff) ;
  889. break;
  890. case 2:
  891. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_EBP) & 0xffff) +
  892. (GetX86Reg(Frame, IA32_REG_ESI) & 0xffff) ;
  893. break;
  894. case 3:
  895. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_EBP) & 0xffff) +
  896. (GetX86Reg(Frame, IA32_REG_EDI) & 0xffff) ;
  897. break;
  898. case 4:
  899. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_ESI) & 0xffff);
  900. break;
  901. case 5:
  902. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_EDI) & 0xffff);
  903. break;
  904. case 6:
  905. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_EBP) & 0xffff);
  906. break;
  907. case 7:
  908. EffectiveAddress = (GetX86Reg(Frame, IA32_REG_EBX) & 0xffff);
  909. break;
  910. }
  911. //
  912. // Read the displacement, if any
  913. //
  914. if (DisplacementType != IA32_DISP_NONE)
  915. {
  916. switch (DisplacementType)
  917. {
  918. case IA32_DISP8:
  919. {
  920. EffectiveAddress += (LONG) (**InstAddr);
  921. *InstAddr = *InstAddr + 1;
  922. }
  923. break;
  924. case IA32_DISP16:
  925. {
  926. Disp16 = (USHORT UNALIGNED *) InstAddr;
  927. EffectiveAddress += (LONG) *Disp16;
  928. *InstAddr = *InstAddr + 2;
  929. }
  930. break;
  931. default:
  932. #if DBG
  933. DbgPrint("KE: KiIa32Compute16BitEffectiveAddress - Invalid displacement type %lx\n",
  934. DisplacementType);
  935. #endif
  936. ReturnCode = FALSE;
  937. break;
  938. }
  939. }
  940. *Addr = EffectiveAddress;
  941. }
  942. except (EXCEPTION_EXECUTE_HANDLER)
  943. {
  944. #if DBG
  945. if (KiIa32InstructionEmulationDbg)
  946. {
  947. DbgPrint("KE: KiIa32Compute16BitEffectiveAddress - Exception %lx\n",
  948. GetExceptionCode());
  949. }
  950. #endif
  951. ReturnCode = FALSE;
  952. }
  953. //
  954. // Make sure the address stays within 4GB range
  955. //
  956. if (ReturnCode == TRUE) {
  957. *Addr = (*Addr & 0x000000007fffffffI64);
  958. }
  959. return ReturnCode;
  960. }
  961. NTSTATUS
  962. KiIa32UpdateFlags (
  963. IN PIA32_INSTRUCTION Instruction,
  964. IN ULONGLONG Operand1,
  965. IN ULONGLONG Result,
  966. IN ULONG Ia32Eflags
  967. )
  968. /*++
  969. Routine Description:
  970. Updates the Ia32 specified eflags according to the result value.
  971. Arguments:
  972. Instruction - Pointer to the instruction being processed.
  973. Operand1 - First operand (value) of the instruction being emulated.
  974. Result - Result value.
  975. Ia32Eflags - Specific flags to update based on the result value.
  976. Return Value:
  977. NTSTATUS
  978. --*/
  979. {
  980. ULONGLONG Temp = 0;
  981. IA32_EFLAGS Eflags = Instruction->Eflags;
  982. //
  983. // Sanitize the destination value.
  984. //
  985. Result = (Result & MAXULONG);
  986. if ((Ia32Eflags & IA32_EFLAGS_CF) != 0)
  987. {
  988. if (Result > Instruction->OperandMask)
  989. {
  990. Eflags.u.cf = 1;
  991. }
  992. else
  993. {
  994. Eflags.u.cf = 0;
  995. }
  996. }
  997. if ((Ia32Eflags & IA32_EFLAGS_OF) != 0)
  998. {
  999. if (((Operand1 & Result) & 0x80000000UI64) != 0)
  1000. {
  1001. Eflags.u.of = 1;
  1002. }
  1003. else
  1004. {
  1005. Eflags.u.of = 0;
  1006. }
  1007. }
  1008. if ((Ia32Eflags & IA32_EFLAGS_SF) != 0)
  1009. {
  1010. switch (Instruction->OperandSize)
  1011. {
  1012. case 0xff:
  1013. Temp = 0x80UI64;
  1014. break;
  1015. case 0xffff:
  1016. Temp = 0x8000UI64;
  1017. break;
  1018. case 0xffffffff:
  1019. Temp = 0x80000000UI64;
  1020. break;
  1021. }
  1022. if (Result & Temp)
  1023. {
  1024. Eflags.u.sf = 1;
  1025. }
  1026. else
  1027. {
  1028. Eflags.u.sf = 0;
  1029. }
  1030. }
  1031. if ((Ia32Eflags & IA32_EFLAGS_ZF) != 0)
  1032. {
  1033. if (Result == 0)
  1034. {
  1035. Eflags.u.zf = 1;
  1036. }
  1037. else
  1038. {
  1039. Eflags.u.zf = 0;
  1040. }
  1041. }
  1042. if ((Ia32Eflags & IA32_EFLAGS_AF) != 0)
  1043. {
  1044. Eflags.u.af = (((Operand1 ^ Result) >> 4) & 0x01UI64);
  1045. }
  1046. //
  1047. // This needs to be the last one as it modifies the 'Result'
  1048. //
  1049. if ((Ia32Eflags & IA32_EFLAGS_PF) != 0)
  1050. {
  1051. Result = Result & Instruction->OperandMask;
  1052. Temp = 0;
  1053. while (Result)
  1054. {
  1055. Result = (Result & (Result - 1));
  1056. Temp++;
  1057. }
  1058. if ((Temp & 0x01UI64) == 0)
  1059. {
  1060. Eflags.u.pf = 1;
  1061. }
  1062. else
  1063. {
  1064. Eflags.u.pf = 1;
  1065. }
  1066. }
  1067. //
  1068. // Reset reserved values.
  1069. //
  1070. Eflags.u.v1 = 1;
  1071. Eflags.u.v2 = 0;
  1072. Eflags.u.v3 = 0;
  1073. Eflags.u.v4 = 0;
  1074. //
  1075. // Sanitize the flags
  1076. //
  1077. Eflags.Value = SANITIZE_AR24_EFLAGS (Eflags.Value, UserMode);
  1078. Instruction->Eflags = Eflags;
  1079. return STATUS_SUCCESS;
  1080. }
  1081. NTSTATUS
  1082. KiIa32UpdateResult (
  1083. IN PIA32_INSTRUCTION Instruction,
  1084. IN PIA32_OPERAND DestinationOperand,
  1085. IN ULONGLONG Result
  1086. )
  1087. /*++
  1088. Routine Description:
  1089. Writes the result value taking into consideration operand size.
  1090. Arguments:
  1091. Instruction - Pointer to the instruction being processed.
  1092. DestinationOperand - Operand to receive the result.
  1093. Result - Result value to write
  1094. Return Value:
  1095. NTSTATUS
  1096. --*/
  1097. {
  1098. UNALIGNED USHORT *UshortPtr;
  1099. UNALIGNED ULONG *UlongPtr;
  1100. NTSTATUS NtStatus = STATUS_SUCCESS;
  1101. PVOID MaxWowAddress;
  1102. MaxWowAddress = MmGetMaxWowAddress ();
  1103. //
  1104. // Update results according to operand size
  1105. //
  1106. try
  1107. {
  1108. if (DestinationOperand->RegisterMode == FALSE)
  1109. {
  1110. if ((PVOID)DestinationOperand->v >= MaxWowAddress)
  1111. {
  1112. return STATUS_ACCESS_VIOLATION;
  1113. }
  1114. }
  1115. switch (Instruction->OperandSize)
  1116. {
  1117. case OPERANDSIZE_ONEBYTE:
  1118. *(PUCHAR)DestinationOperand->v = (UCHAR)Result;
  1119. break;
  1120. case OPERANDSIZE_TWOBYTES:
  1121. UshortPtr = (UNALIGNED USHORT *) DestinationOperand->v;
  1122. *UshortPtr = (USHORT)Result;
  1123. break;
  1124. case OPERANDSIZE_FOURBYTES:
  1125. UlongPtr =(UNALIGNED ULONG *) DestinationOperand->v;
  1126. *UlongPtr = (ULONG)Result;
  1127. break;
  1128. default:
  1129. #if DBG
  1130. if (KiIa32InstructionEmulationDbg)
  1131. {
  1132. DbgPrint("KE: KiIa32UpdateResult() - Invalid operand size - %lx - %p\n",
  1133. Instruction->OperandSize, Instruction);
  1134. }
  1135. #endif
  1136. NtStatus = STATUS_UNSUCCESSFUL;
  1137. break;
  1138. }
  1139. }
  1140. except (EXCEPTION_EXECUTE_HANDLER)
  1141. {
  1142. NtStatus = GetExceptionCode ();
  1143. #if DBG
  1144. DbgPrint("KE: KiIa32UpdateResult - Exception %lx - %p\n",
  1145. NtStatus, Instruction);
  1146. #endif
  1147. }
  1148. return NtStatus;
  1149. }
  1150. NTSTATUS
  1151. KiIa32ReadOperand1 (
  1152. IN PIA32_INSTRUCTION Instruction,
  1153. OUT PULONGLONG Operand1
  1154. )
  1155. /*++
  1156. Routine Description:
  1157. Reads the first (destination) operand of an instruction.
  1158. Arguments:
  1159. Instruction - Pointer to the instruction being processed.
  1160. Operand1 - Buffer to receive the operand value.
  1161. Return Value:
  1162. NTSTATUS
  1163. --*/
  1164. {
  1165. UNALIGNED ULONG *UlongPtr;
  1166. UNALIGNED USHORT *UshortPtr;
  1167. NTSTATUS NtStatus = STATUS_SUCCESS;
  1168. try
  1169. {
  1170. switch (Instruction->Description->Type)
  1171. {
  1172. case IA32_PARAM_RM_IMM8SIGN:
  1173. case IA32_PARAM_RM_IMM:
  1174. case IA32_PARAM_RM_R:
  1175. case IA32_PARAM_R_RM8:
  1176. case IA32_PARAM_R_RM:
  1177. case IA32_PARAM_RM:
  1178. case IA32_PARAM_SEGREG_RM:
  1179. if (Instruction->OperandSize == OPERANDSIZE_TWOBYTES)
  1180. {
  1181. UshortPtr = (UNALIGNED USHORT *) Instruction->Operand1.v;
  1182. *Operand1 = (ULONGLONG) *UshortPtr;
  1183. }
  1184. else
  1185. {
  1186. UlongPtr = (UNALIGNED ULONG *) Instruction->Operand1.v;
  1187. *Operand1 = (ULONGLONG) *UlongPtr;
  1188. }
  1189. break;
  1190. case IA32_PARAM_RM8_IMM8:
  1191. case IA32_PARAM_RM8_R:
  1192. case IA32_PARAM_RM8:
  1193. case IA32_PARAM_SEGREG_RM8:
  1194. *Operand1 = (ULONGLONG) (*(PUCHAR)Instruction->Operand1.v);
  1195. break;
  1196. default:
  1197. #if DBG
  1198. if (KiIa32InstructionEmulationDbg)
  1199. {
  1200. DbgPrint("KE: KiIa32ReadRm - Invalid opcode type %lx - %p\n",
  1201. Instruction->Description->Type, Instruction);
  1202. }
  1203. NtStatus = STATUS_UNSUCCESSFUL;
  1204. #endif
  1205. break;
  1206. }
  1207. }
  1208. except (EXCEPTION_EXECUTE_HANDLER)
  1209. {
  1210. NtStatus = GetExceptionCode ();
  1211. #if DBG
  1212. DbgPrint("KE: KiIa32ReadOperand1 - Exception %lx - %p\n",
  1213. NtStatus, Instruction);
  1214. #endif
  1215. }
  1216. return NtStatus;
  1217. }
  1218. NTSTATUS
  1219. KiIa32ReadOperand2 (
  1220. IN PIA32_INSTRUCTION Instruction,
  1221. OUT PULONGLONG Operand2
  1222. )
  1223. /*++
  1224. Routine Description:
  1225. Reads the second (source) operand of an instruction.
  1226. Arguments:
  1227. Instruction - Pointer to the instruction being processed.
  1228. Operand1 - Buffer to receive the operand value.
  1229. Return Value:
  1230. NTSTATUS
  1231. --*/
  1232. {
  1233. UNALIGNED ULONG *UlongPtr;
  1234. UNALIGNED USHORT *UshortPtr;
  1235. NTSTATUS NtStatus = STATUS_SUCCESS;
  1236. try
  1237. {
  1238. switch (Instruction->Description->Type)
  1239. {
  1240. case IA32_PARAM_RM8_IMM8:
  1241. case IA32_PARAM_RM_IMM8SIGN:
  1242. *Operand2 = (UCHAR)Instruction->Operand2.v;
  1243. break;
  1244. case IA32_PARAM_RM_IMM:
  1245. *Operand2 = Instruction->Operand2.v & Instruction->OperandMask;
  1246. break;
  1247. case IA32_PARAM_RM8_R:
  1248. case IA32_PARAM_R_RM8:
  1249. *Operand2 = (ULONGLONG)(*(PUCHAR)Instruction->Operand2.v);
  1250. break;
  1251. case IA32_PARAM_RM_R:
  1252. case IA32_PARAM_R_RM:
  1253. if (Instruction->OperandSize == OPERANDSIZE_TWOBYTES)
  1254. {
  1255. UshortPtr = (UNALIGNED USHORT *) Instruction->Operand2.v;
  1256. *Operand2 = (ULONGLONG) *UshortPtr;
  1257. }
  1258. else
  1259. {
  1260. UlongPtr = (UNALIGNED ULONG *) Instruction->Operand2.v;
  1261. *Operand2 = (ULONGLONG) *UlongPtr;
  1262. }
  1263. break;
  1264. case IA32_PARAM_SEGREG_RM8:
  1265. case IA32_PARAM_SEGREG_RM:
  1266. break;
  1267. default:
  1268. #if DBG
  1269. if (KiIa32InstructionEmulationDbg)
  1270. {
  1271. DbgPrint("KE: KiIa32ReadOperand2 - Invalid type %lx - %p\n",
  1272. Instruction->Description->Type, Instruction);
  1273. }
  1274. NtStatus = STATUS_UNSUCCESSFUL;
  1275. #endif
  1276. break;
  1277. }
  1278. }
  1279. except (EXCEPTION_EXECUTE_HANDLER)
  1280. {
  1281. NtStatus = GetExceptionCode ();
  1282. #if DBG
  1283. DbgPrint("KE: KiIa32ReadOperand2 - Exception %lx - %p\n",
  1284. NtStatus, Instruction);
  1285. #endif
  1286. }
  1287. return NtStatus;
  1288. }
  1289. NTSTATUS
  1290. KiIa32InstructionAddWithIncrement (
  1291. IN PIA32_INSTRUCTION Instruction,
  1292. IN ULONG Increment
  1293. )
  1294. /*++
  1295. Routine Description:
  1296. Common routine implementing Ia32 add, adc, sub and sbb instructions.
  1297. Arguments:
  1298. Instruction - Pointer to the instruction being processed.
  1299. Increment - Specifies the carry value.
  1300. Return Value:
  1301. NTSTATUS
  1302. --*/
  1303. {
  1304. ULONGLONG UlongDst;
  1305. ULONGLONG UlongSrc;
  1306. ULONGLONG Operand1;
  1307. UCHAR Imm8;
  1308. char SignImm8;
  1309. BOOLEAN Subtract;
  1310. NTSTATUS NtStatus;
  1311. switch (Instruction->Description->Opcode)
  1312. {
  1313. case Ia32_Add:
  1314. case Ia32_Adc:
  1315. Subtract = FALSE;
  1316. break;
  1317. case Ia32_Sub:
  1318. case Ia32_Sbb:
  1319. Subtract = TRUE;
  1320. break;
  1321. default:
  1322. #if DBG
  1323. if (KiIa32InstructionEmulationDbg)
  1324. {
  1325. DbgPrint("KE: KiIa32InstructionAddWithIncrement - Invalid opcode %lx - %p\n",
  1326. Instruction->Description->Opcode, Instruction);
  1327. }
  1328. #endif
  1329. return STATUS_UNSUCCESSFUL;
  1330. break;
  1331. }
  1332. NtStatus = KiIa32ReadOperand1 (Instruction, &UlongDst);
  1333. if (NT_SUCCESS (NtStatus))
  1334. {
  1335. Operand1 = UlongDst;
  1336. NtStatus = KiIa32ReadOperand2 (Instruction, &UlongSrc);
  1337. if (NT_SUCCESS (NtStatus))
  1338. {
  1339. switch (Instruction->Description->Type)
  1340. {
  1341. case IA32_PARAM_RM_IMM8SIGN:
  1342. SignImm8 = (char) UlongSrc;
  1343. if (Subtract)
  1344. UlongDst = (UlongDst - (Increment + SignImm8));
  1345. else
  1346. UlongDst = UlongDst + Increment + SignImm8;
  1347. break;
  1348. case IA32_PARAM_RM8_IMM8:
  1349. Imm8 = (UCHAR) UlongSrc;
  1350. if (Subtract)
  1351. UlongDst = (UlongDst - (Increment + Imm8));
  1352. else
  1353. UlongDst = UlongDst + Increment + Imm8;
  1354. break;
  1355. case IA32_PARAM_RM_IMM:
  1356. default:
  1357. if (Subtract)
  1358. UlongDst = (UlongDst - (Increment + UlongSrc));
  1359. else
  1360. UlongDst = UlongDst + Increment + UlongSrc;
  1361. break;
  1362. }
  1363. //
  1364. // Update results according to operand size
  1365. //
  1366. NtStatus = KiIa32UpdateResult (
  1367. Instruction,
  1368. &Instruction->Operand1,
  1369. UlongDst
  1370. );
  1371. //
  1372. // Eflags update
  1373. //
  1374. if (NT_SUCCESS (NtStatus))
  1375. {
  1376. KiIa32UpdateFlags (
  1377. Instruction,
  1378. Operand1,
  1379. UlongDst,
  1380. (IA32_EFLAGS_CF | IA32_EFLAGS_SF | IA32_EFLAGS_OF |
  1381. IA32_EFLAGS_PF | IA32_EFLAGS_ZF | IA32_EFLAGS_AF)
  1382. );
  1383. }
  1384. }
  1385. }
  1386. return NtStatus;
  1387. }
  1388. NTSTATUS
  1389. KiIa32InstructionAdc (
  1390. IN PKTRAP_FRAME TrapFrame,
  1391. IN PIA32_INSTRUCTION Instruction
  1392. )
  1393. /*++
  1394. Routine Description:
  1395. Adc instruction handler.
  1396. Arguments:
  1397. TrapFrame - Pointer to TrapFrame.
  1398. Instruction - Pointer to the instruction being processed.
  1399. Return Value:
  1400. NTSTATUS
  1401. --*/
  1402. {
  1403. return KiIa32InstructionAddWithIncrement (
  1404. Instruction,
  1405. (ULONG)Instruction->Eflags.u.cf);
  1406. UNREFERENCED_PARAMETER (TrapFrame);
  1407. }
  1408. NTSTATUS
  1409. KiIa32InstructionAdd (
  1410. IN PKTRAP_FRAME TrapFrame,
  1411. IN PIA32_INSTRUCTION Instruction
  1412. )
  1413. /*++
  1414. Routine Description:
  1415. Add instruction handler.
  1416. Arguments:
  1417. TrapFrame - Pointer to TrapFrame.
  1418. Instruction - Pointer to the instruction being processed.
  1419. Return Value:
  1420. NTSTATUS
  1421. --*/
  1422. {
  1423. return KiIa32InstructionAddWithIncrement (
  1424. Instruction,
  1425. 0);
  1426. UNREFERENCED_PARAMETER (TrapFrame);
  1427. }
  1428. NTSTATUS
  1429. KiIa32InstructionArithmeticBitwiseHelper (
  1430. IN PKTRAP_FRAME TrapFrame,
  1431. IN PIA32_INSTRUCTION Instruction
  1432. )
  1433. /*++
  1434. Routine Description:
  1435. And, Or & Xor instructions handler.
  1436. Arguments:
  1437. TrapFrame - Pointer to TrapFrame.
  1438. Instruction - Pointer to the instruction being processed.
  1439. Return Value:
  1440. NTSTATUS
  1441. --*/
  1442. {
  1443. ULONGLONG UlongDst;
  1444. ULONGLONG UlongSrc;
  1445. ULONGLONG Operand1;
  1446. NTSTATUS NtStatus;
  1447. NtStatus = KiIa32ReadOperand1 (Instruction, &UlongDst);
  1448. if (NT_SUCCESS (NtStatus))
  1449. {
  1450. Operand1 = UlongDst;
  1451. NtStatus = KiIa32ReadOperand2 (Instruction, &UlongSrc);
  1452. if (NT_SUCCESS (NtStatus))
  1453. {
  1454. switch (Instruction->Description->Opcode)
  1455. {
  1456. case Ia32_And:
  1457. UlongDst = UlongDst & UlongSrc;
  1458. break;
  1459. case Ia32_Or:
  1460. UlongDst = UlongDst | UlongSrc;
  1461. break;
  1462. case Ia32_Xor:
  1463. UlongDst = UlongDst ^ UlongSrc;
  1464. break;
  1465. default:
  1466. #if DBG
  1467. NtStatus = STATUS_UNSUCCESSFUL;
  1468. if (KiIa32InstructionEmulationDbg)
  1469. {
  1470. DbgPrint("KE: KiIa32InstructionBitwiseHelper - Invalid operation %lx - %p\n",
  1471. Instruction->Description->Opcode, Instruction);
  1472. }
  1473. #endif
  1474. break;
  1475. }
  1476. if (NT_SUCCESS (NtStatus))
  1477. {
  1478. NtStatus = KiIa32UpdateResult (
  1479. Instruction,
  1480. &Instruction->Operand1,
  1481. UlongDst
  1482. );
  1483. if (NT_SUCCESS (NtStatus))
  1484. {
  1485. NtStatus = KiIa32UpdateFlags (
  1486. Instruction,
  1487. Operand1,
  1488. UlongDst,
  1489. (IA32_EFLAGS_SF | IA32_EFLAGS_PF | IA32_EFLAGS_ZF)
  1490. );
  1491. Instruction->Eflags.u.cf = 0;
  1492. Instruction->Eflags.u.of = 0;
  1493. }
  1494. }
  1495. }
  1496. }
  1497. return NtStatus;
  1498. UNREFERENCED_PARAMETER (TrapFrame);
  1499. }
  1500. NTSTATUS
  1501. KiIa32InstructionBitTestHelper (
  1502. IN PKTRAP_FRAME TrapFrame,
  1503. IN PIA32_INSTRUCTION Instruction
  1504. )
  1505. /*++
  1506. Routine Description:
  1507. Bt, Bts, Btr & Btc instructions handler.
  1508. Arguments:
  1509. TrapFrame - Pointer to TrapFrame.
  1510. Instruction - Pointer to the instruction being processed.
  1511. Return Value:
  1512. NTSTATUS
  1513. --*/
  1514. {
  1515. ULONGLONG UlongDst;
  1516. ULONGLONG UlongSrc;
  1517. ULONGLONG BitTestResult;
  1518. NTSTATUS NtStatus;
  1519. NtStatus = KiIa32ReadOperand2 (Instruction, &UlongSrc);
  1520. if (NT_SUCCESS (NtStatus))
  1521. {
  1522. if (Instruction->Operand2.RegisterMode == TRUE)
  1523. {
  1524. if (Instruction->Prefix.b.AddressOverride == 1)
  1525. {
  1526. Instruction->Operand1.v += ((UlongSrc >> 4) << 1);
  1527. UlongSrc &= 0x0f;
  1528. }
  1529. else
  1530. {
  1531. Instruction->Operand1.v += ((UlongSrc >> 5) << 2);
  1532. UlongSrc &= 0x1f;
  1533. }
  1534. }
  1535. NtStatus = KiIa32ReadOperand1 (Instruction, &UlongDst);
  1536. if (NT_SUCCESS (NtStatus))
  1537. {
  1538. BitTestResult = (UlongDst & (1 << UlongSrc));
  1539. if (BitTestResult)
  1540. {
  1541. Instruction->Eflags.u.cf = 1;
  1542. }
  1543. else
  1544. {
  1545. Instruction->Eflags.u.cf = 0;
  1546. }
  1547. switch (Instruction->Description->Opcode)
  1548. {
  1549. case Ia32_Btc:
  1550. UlongDst ^= (1 << UlongSrc);
  1551. break;
  1552. case Ia32_Btr:
  1553. UlongDst &= (~(1 << UlongSrc));
  1554. break;
  1555. case Ia32_Bts:
  1556. UlongDst |= (1 << UlongSrc);
  1557. break;
  1558. }
  1559. NtStatus = KiIa32UpdateResult (
  1560. Instruction,
  1561. &Instruction->Operand1,
  1562. UlongDst
  1563. );
  1564. }
  1565. }
  1566. return NtStatus;
  1567. UNREFERENCED_PARAMETER (TrapFrame);
  1568. }
  1569. NTSTATUS
  1570. KiIa32InstructionOneParamHelper (
  1571. IN PKTRAP_FRAME TrapFrame,
  1572. IN PIA32_INSTRUCTION Instruction
  1573. )
  1574. /*++
  1575. Routine Description:
  1576. Inc, Dec, Neg & Not instructions handler.
  1577. Arguments:
  1578. TrapFrame - Pointer to TrapFrame.
  1579. Instruction - Pointer to the instruction being processed.
  1580. Return Value:
  1581. NTSTATUS
  1582. --*/
  1583. {
  1584. UCHAR Opcode;
  1585. ULONG FlagsAffected = 0;
  1586. ULONGLONG UlongDst;
  1587. ULONGLONG UlongSrc;
  1588. NTSTATUS NtStatus;
  1589. NtStatus = KiIa32ReadOperand1 (
  1590. Instruction,
  1591. &UlongDst
  1592. );
  1593. if (NT_SUCCESS (NtStatus))
  1594. {
  1595. UlongSrc = UlongDst;
  1596. Opcode = Instruction->Description->Opcode;
  1597. switch (Opcode)
  1598. {
  1599. case Ia32_Inc:
  1600. UlongDst += 1;
  1601. break;
  1602. case Ia32_Dec:
  1603. UlongDst -= 1;
  1604. break;
  1605. case Ia32_Neg:
  1606. UlongDst = -(LONGLONG)UlongDst;
  1607. break;
  1608. case Ia32_Not:
  1609. UlongDst = ~UlongDst;
  1610. break;
  1611. }
  1612. NtStatus = KiIa32UpdateResult (
  1613. Instruction,
  1614. &Instruction->Operand1,
  1615. UlongDst
  1616. );
  1617. if (NT_SUCCESS (NtStatus))
  1618. {
  1619. switch (Opcode)
  1620. {
  1621. case Ia32_Inc:
  1622. case Ia32_Dec:
  1623. FlagsAffected = (IA32_EFLAGS_SF | IA32_EFLAGS_PF |
  1624. IA32_EFLAGS_ZF);
  1625. break;
  1626. case Ia32_Neg:
  1627. if (UlongDst == 0)
  1628. Instruction->Eflags.u.cf = 0;
  1629. else
  1630. Instruction->Eflags.u.cf = 1;
  1631. FlagsAffected = (IA32_EFLAGS_SF | IA32_EFLAGS_PF |
  1632. IA32_EFLAGS_ZF | IA32_EFLAGS_AF | IA32_EFLAGS_OF);
  1633. break;
  1634. }
  1635. if (FlagsAffected != 0)
  1636. {
  1637. NtStatus = KiIa32UpdateFlags (
  1638. Instruction,
  1639. UlongSrc,
  1640. UlongDst,
  1641. FlagsAffected
  1642. );
  1643. }
  1644. }
  1645. }
  1646. return NtStatus;
  1647. UNREFERENCED_PARAMETER (TrapFrame);
  1648. }
  1649. NTSTATUS
  1650. KiIa32InstructionXadd (
  1651. IN PKTRAP_FRAME TrapFrame,
  1652. IN PIA32_INSTRUCTION Instruction
  1653. )
  1654. /*++
  1655. Routine Description:
  1656. Xadd instruction handler.
  1657. Arguments:
  1658. TrapFrame - Pointer to TrapFrame.
  1659. Instruction - Pointer to the instruction being processed.
  1660. Return Value:
  1661. NTSTATUS
  1662. --*/
  1663. {
  1664. ULONGLONG UlongDst;
  1665. ULONGLONG UlongSrc;
  1666. ULONGLONG Operand1;
  1667. ULONGLONG Temp;
  1668. NTSTATUS NtStatus;
  1669. NtStatus = KiIa32ReadOperand1 (Instruction, &UlongDst);
  1670. if (NT_SUCCESS (NtStatus))
  1671. {
  1672. Operand1 = UlongDst;
  1673. NtStatus = KiIa32ReadOperand2 (Instruction, &UlongSrc);
  1674. if (NT_SUCCESS (NtStatus))
  1675. {
  1676. Temp = UlongDst;
  1677. UlongDst += UlongSrc;
  1678. NtStatus = KiIa32UpdateResult (
  1679. Instruction,
  1680. &Instruction->Operand1,
  1681. UlongDst
  1682. );
  1683. if (NT_SUCCESS (NtStatus))
  1684. {
  1685. NtStatus = KiIa32UpdateResult (
  1686. Instruction,
  1687. &Instruction->Operand2,
  1688. Temp
  1689. );
  1690. if (NT_SUCCESS (NtStatus))
  1691. {
  1692. NtStatus = KiIa32UpdateFlags (
  1693. Instruction,
  1694. Operand1,
  1695. UlongDst,
  1696. (IA32_EFLAGS_CF | IA32_EFLAGS_SF | IA32_EFLAGS_PF |
  1697. IA32_EFLAGS_ZF | IA32_EFLAGS_OF | IA32_EFLAGS_AF)
  1698. );
  1699. }
  1700. }
  1701. }
  1702. }
  1703. return NtStatus;
  1704. UNREFERENCED_PARAMETER (TrapFrame);
  1705. }
  1706. NTSTATUS
  1707. KiIa32InstructionXchg (
  1708. IN PKTRAP_FRAME TrapFrame,
  1709. IN PIA32_INSTRUCTION Instruction
  1710. )
  1711. /*++
  1712. Routine Description:
  1713. Xchg instruction handler.
  1714. Arguments:
  1715. TrapFrame - Pointer to TrapFrame.
  1716. Instruction - Pointer to the instruction being processed.
  1717. Return Value:
  1718. NTSTATUS
  1719. --*/
  1720. {
  1721. ULONGLONG UlongDst;
  1722. ULONGLONG UlongSrc;
  1723. NTSTATUS NtStatus;
  1724. NtStatus = KiIa32ReadOperand1 (Instruction, &UlongDst);
  1725. if (NT_SUCCESS (NtStatus))
  1726. {
  1727. NtStatus = KiIa32ReadOperand2 (Instruction, &UlongSrc);
  1728. if (NT_SUCCESS (NtStatus))
  1729. {
  1730. NtStatus = KiIa32UpdateResult (
  1731. Instruction,
  1732. &Instruction->Operand1,
  1733. UlongSrc
  1734. );
  1735. if (NT_SUCCESS (NtStatus))
  1736. {
  1737. NtStatus = KiIa32UpdateResult (
  1738. Instruction,
  1739. &Instruction->Operand2,
  1740. UlongDst
  1741. );
  1742. }
  1743. }
  1744. }
  1745. return NtStatus;
  1746. UNREFERENCED_PARAMETER (TrapFrame);
  1747. }
  1748. NTSTATUS
  1749. KiIa32InstructionCmpXchg (
  1750. IN PKTRAP_FRAME TrapFrame,
  1751. IN PIA32_INSTRUCTION Instruction
  1752. )
  1753. /*++
  1754. Routine Description:
  1755. Cmpxchg instruction handler.
  1756. Arguments:
  1757. TrapFrame - Pointer to TrapFrame.
  1758. Instruction - Pointer to the instruction being processed.
  1759. Return Value:
  1760. NTSTATUS
  1761. --*/
  1762. {
  1763. ULONGLONG UlongDst;
  1764. ULONGLONG UlongSrc;
  1765. ULONGLONG Accumulator;
  1766. IA32_OPERAND AccumulatorOperand;
  1767. NTSTATUS NtStatus;
  1768. NtStatus = KiIa32ReadOperand1 (Instruction, &UlongDst);
  1769. if (NT_SUCCESS (NtStatus))
  1770. {
  1771. NtStatus = KiIa32ReadOperand2 (Instruction, &UlongSrc);
  1772. if (NT_SUCCESS (NtStatus))
  1773. {
  1774. Accumulator = GetX86Reg (TrapFrame, IA32_REG_EAX);
  1775. Accumulator &= Instruction->OperandMask;
  1776. if (Accumulator == UlongDst)
  1777. {
  1778. Instruction->Eflags.u.zf = 1;
  1779. NtStatus = KiIa32UpdateResult (
  1780. Instruction,
  1781. &Instruction->Operand1,
  1782. UlongSrc
  1783. );
  1784. }
  1785. else
  1786. {
  1787. Instruction->Eflags.u.zf = 0;
  1788. AccumulatorOperand.RegisterMode = TRUE;
  1789. AccumulatorOperand.v = GetX86RegOffset (TrapFrame, IA32_REG_EAX);
  1790. NtStatus = KiIa32UpdateResult (
  1791. Instruction,
  1792. &AccumulatorOperand,
  1793. UlongDst
  1794. );
  1795. }
  1796. if (NT_SUCCESS (NtStatus))
  1797. {
  1798. NtStatus = KiIa32UpdateFlags (
  1799. Instruction,
  1800. UlongDst,
  1801. UlongDst,
  1802. (IA32_EFLAGS_CF | IA32_EFLAGS_SF |
  1803. IA32_EFLAGS_PF | IA32_EFLAGS_OF |
  1804. IA32_EFLAGS_AF)
  1805. );
  1806. }
  1807. }
  1808. }
  1809. return NtStatus;
  1810. }
  1811. NTSTATUS
  1812. KiIa32InstructionCmpXchg8b (
  1813. IN PKTRAP_FRAME TrapFrame,
  1814. IN PIA32_INSTRUCTION Instruction
  1815. )
  1816. /*++
  1817. Routine Description:
  1818. Cmpxchg8b instruction handler.
  1819. Arguments:
  1820. TrapFrame - Pointer to TrapFrame.
  1821. Instruction - Pointer to the instruction being processed.
  1822. Return Value:
  1823. NTSTATUS
  1824. --*/
  1825. {
  1826. UNALIGNED ULONGLONG *UlongDst;
  1827. UNALIGNED ULONGLONG *UlongSrc;
  1828. ULONGLONG EdxEax;
  1829. EdxEax = GetX86Reg (TrapFrame, IA32_REG_EDX);
  1830. EdxEax <<= 32;
  1831. EdxEax |= GetX86Reg (TrapFrame, IA32_REG_EAX);
  1832. UlongDst = (PULONGLONG)Instruction->Operand1.v;
  1833. if (*UlongDst == EdxEax)
  1834. {
  1835. Instruction->Eflags.u.zf = 1;
  1836. *UlongDst = ((((ULONGLONG) GetX86Reg (TrapFrame, IA32_REG_ECX)) << 32) |
  1837. ((ULONGLONG) GetX86Reg (TrapFrame, IA32_REG_EBX)));
  1838. }
  1839. else
  1840. {
  1841. Instruction->Eflags.u.zf = 0;
  1842. UlongSrc = (PULONGLONG) GetX86RegOffset (TrapFrame, IA32_REG_EDX);
  1843. *UlongSrc = ((*UlongDst) >> 32);
  1844. UlongSrc = (PULONGLONG) GetX86RegOffset (TrapFrame, IA32_REG_EAX);
  1845. *UlongSrc = ((*UlongDst) & 0xffffffff);
  1846. }
  1847. return STATUS_SUCCESS;
  1848. }
  1849. NTSTATUS
  1850. KiIa32InstructionMoveSeg (
  1851. IN PKTRAP_FRAME TrapFrame,
  1852. IN PIA32_INSTRUCTION Instruction
  1853. )
  1854. /*++
  1855. Routine Description:
  1856. Mov Seg-Reg instruction handler.
  1857. Arguments:
  1858. TrapFrame - Pointer to TrapFrame.
  1859. Instruction - Pointer to the instruction being processed.
  1860. Return Value:
  1861. NTSTATUS
  1862. --*/
  1863. {
  1864. return STATUS_NOT_IMPLEMENTED;
  1865. UNREFERENCED_PARAMETER (TrapFrame);
  1866. UNREFERENCED_PARAMETER (Instruction);
  1867. }
  1868. NTSTATUS
  1869. KiIa32LocateInstruction (
  1870. IN PKTRAP_FRAME TrapFrame,
  1871. OUT PIA32_INSTRUCTION Instruction
  1872. )
  1873. /*++
  1874. Routine Description:
  1875. Searches the OpcodeDescription table for matching instruction. Fills any relevant
  1876. prefix values inside the Instruction structure.
  1877. Arguments:
  1878. TrapFrame - Pointer to TrapFrame.
  1879. Instruction - Pointer to an Instruction structure to receive the opcode description.
  1880. Return Value:
  1881. NTSTATUS
  1882. --*/
  1883. {
  1884. BOOLEAN PrefixLoop;
  1885. BOOLEAN Match;
  1886. UCHAR ByteValue;
  1887. UCHAR ByteBuffer[4];
  1888. PUCHAR RegOpcodeByte;
  1889. PIA32_OPCODE_DESCRIPTION OpcodeDescription;
  1890. ULONG Count;
  1891. NTSTATUS NtStatus = STATUS_SUCCESS;
  1892. PrefixLoop = TRUE;
  1893. while (PrefixLoop)
  1894. {
  1895. try
  1896. {
  1897. ByteValue = ProbeAndReadUchar ((PUCHAR)Instruction->Eip);
  1898. }
  1899. except (EXCEPTION_EXECUTE_HANDLER)
  1900. {
  1901. NtStatus = GetExceptionCode();
  1902. break;
  1903. }
  1904. switch (ByteValue)
  1905. {
  1906. case MI_LOCK_PREFIX:
  1907. Instruction->Prefix.b.Lock = 1;
  1908. break;
  1909. case MI_REPNE_PREFIX:
  1910. Instruction->Prefix.b.RepNe = 1;
  1911. break;
  1912. case MI_REP_PREFIX:
  1913. Instruction->Prefix.b.Rep = 1;
  1914. break;
  1915. case MI_SEGCS_PREFIX:
  1916. Instruction->Prefix.b.CsOverride = 1;
  1917. break;
  1918. case MI_SEGSS_PREFIX:
  1919. Instruction->Prefix.b.SsOverride = 1;
  1920. break;
  1921. case MI_SEGDS_PREFIX:
  1922. Instruction->Prefix.b.DsOverride = 1;
  1923. break;
  1924. case MI_SEGES_PREFIX:
  1925. Instruction->Prefix.b.EsOverride = 1;
  1926. break;
  1927. case MI_SEGFS_PREFIX:
  1928. Instruction->Prefix.b.FsOverride = 1;
  1929. break;
  1930. case MI_SEGGS_PREFIX:
  1931. Instruction->Prefix.b.GsOverride = 1;
  1932. break;
  1933. case MI_OPERANDSIZE_PREFIX:
  1934. Instruction->Prefix.b.SizeOverride = 1;
  1935. break;
  1936. case MI_ADDRESSOVERRIDE_PREFIX:
  1937. Instruction->Prefix.b.AddressOverride = 1;
  1938. break;
  1939. default:
  1940. PrefixLoop = FALSE;
  1941. break;
  1942. }
  1943. if (PrefixLoop == TRUE)
  1944. {
  1945. Instruction->Eip++;
  1946. }
  1947. }
  1948. try
  1949. {
  1950. RtlCopyMemory(ByteBuffer, Instruction->Eip, sizeof (ByteBuffer));
  1951. }
  1952. except (EXCEPTION_EXECUTE_HANDLER)
  1953. {
  1954. NtStatus = GetExceptionCode();
  1955. }
  1956. if (NT_SUCCESS (NtStatus))
  1957. {
  1958. //
  1959. // Locate the opcode
  1960. //
  1961. Match = FALSE;
  1962. OpcodeDescription = OpcodesDescription;
  1963. Count = (sizeof (OpcodesDescription) / sizeof (IA32_OPCODE_DESCRIPTION));
  1964. while (Count != 0)
  1965. {
  1966. Count--;
  1967. if (OpcodeDescription->Byte1 == ByteBuffer[0])
  1968. {
  1969. Match = TRUE;
  1970. if (OpcodeDescription->Count.m.Bytes == 2)
  1971. {
  1972. RegOpcodeByte = &ByteBuffer[2];
  1973. if (OpcodeDescription->Byte2 != ByteBuffer[1])
  1974. {
  1975. Match = FALSE;
  1976. }
  1977. }
  1978. else
  1979. {
  1980. RegOpcodeByte = &ByteBuffer[1];
  1981. }
  1982. if ((Match == TRUE) &&
  1983. (OpcodeDescription->Count.m.RegOpcode))
  1984. {
  1985. if (OpcodeDescription->Byte3 != ((*RegOpcodeByte & MI_REGMASK) >> MI_REGSHIFT))
  1986. {
  1987. Match = FALSE;
  1988. }
  1989. }
  1990. if (Match == TRUE)
  1991. {
  1992. break;
  1993. }
  1994. }
  1995. OpcodeDescription++;
  1996. }
  1997. if (Match != TRUE)
  1998. {
  1999. #if DBG
  2000. if (KiIa32InstructionEmulationDbg)
  2001. {
  2002. DbgPrint("KE: KiIa32LocateInstruction - Unable to locate instruction %p\n",
  2003. Instruction);
  2004. }
  2005. #endif
  2006. NtStatus = STATUS_UNSUCCESSFUL;
  2007. }
  2008. if (NT_SUCCESS (NtStatus))
  2009. {
  2010. Instruction->Description = OpcodeDescription;
  2011. Instruction->Eip += OpcodeDescription->Count.m.Bytes;
  2012. }
  2013. }
  2014. return NtStatus;
  2015. UNREFERENCED_PARAMETER (TrapFrame);
  2016. }
  2017. NTSTATUS
  2018. KiIa32DecodeInstruction (
  2019. IN PKTRAP_FRAME TrapFrame,
  2020. OUT PIA32_INSTRUCTION Instruction
  2021. )
  2022. /*++
  2023. Routine Description:
  2024. Decodes the instruction prefixes and operands.
  2025. Arguments:
  2026. TrapFrame - Pointer to TrapFrame.
  2027. Instruction - Pointer to an Instruction structure to receive the opcode description.
  2028. Return Value:
  2029. NTSTATUS
  2030. --*/
  2031. {
  2032. UCHAR InstructionType;
  2033. UCHAR ModRm;
  2034. UNALIGNED USHORT *UnalignedUshort;
  2035. UNALIGNED ULONG *UnalignedUlong;
  2036. IA32_OPERAND Temp;
  2037. BOOLEAN ReturnCode;
  2038. NTSTATUS NtStatus;
  2039. PVOID MaxWowAddress;
  2040. MaxWowAddress = MmGetMaxWowAddress ();
  2041. //
  2042. // Check instruction pointer validity
  2043. //
  2044. if (TrapFrame->StIIP >= (ULONGLONG) MaxWowAddress) {
  2045. return STATUS_ACCESS_VIOLATION;
  2046. }
  2047. //
  2048. // Initialize the instruction pointer
  2049. //
  2050. Instruction->Eip = (PCHAR) TrapFrame->StIIP;
  2051. KiIa32GetX86Eflags (Instruction->Eflags);
  2052. //
  2053. // Locate a description for the instruction
  2054. //
  2055. NtStatus = KiIa32LocateInstruction (TrapFrame, Instruction);
  2056. if (NT_SUCCESS (NtStatus))
  2057. {
  2058. //
  2059. // Let's parse the arguments
  2060. //
  2061. InstructionType = Instruction->Description->Type;
  2062. switch (InstructionType)
  2063. {
  2064. case IA32_PARAM_RM8_IMM8:
  2065. case IA32_PARAM_RM8_R:
  2066. case IA32_PARAM_R_RM8:
  2067. case IA32_PARAM_RM8:
  2068. case IA32_PARAM_SEGREG_RM8:
  2069. Instruction->OperandSize = OPERANDSIZE_ONEBYTE;
  2070. Instruction->OperandMask = 0xff;
  2071. break;
  2072. case IA32_PARAM_RM_IMM:
  2073. case IA32_PARAM_RM_IMM8SIGN:
  2074. case IA32_PARAM_RM_R:
  2075. case IA32_PARAM_R_RM:
  2076. case IA32_PARAM_RM:
  2077. if (Instruction->Prefix.b.SizeOverride)
  2078. {
  2079. Instruction->OperandSize = OPERANDSIZE_TWOBYTES;
  2080. Instruction->OperandMask = 0xffff;
  2081. }
  2082. else
  2083. {
  2084. Instruction->OperandSize = OPERANDSIZE_FOURBYTES;
  2085. Instruction->OperandMask = 0xffffffff;
  2086. }
  2087. break;
  2088. break;
  2089. case IA32_PARAM_SEGREG_RM:
  2090. Instruction->OperandSize = OPERANDSIZE_TWOBYTES;
  2091. Instruction->OperandMask = 0xffff;
  2092. break;
  2093. default:
  2094. #if DBG
  2095. if (KiIa32InstructionEmulationDbg)
  2096. {
  2097. DbgPrint("KE: KiIa32DecodeInstruction - Invalid Instruction type %lx, %p\n",
  2098. Instruction->Description->Type, Instruction);
  2099. }
  2100. #endif
  2101. return STATUS_UNSUCCESSFUL;
  2102. break;
  2103. }
  2104. try
  2105. {
  2106. ModRm = ProbeAndReadUchar ((PUCHAR)Instruction->Eip);
  2107. }
  2108. except (EXCEPTION_EXECUTE_HANDLER)
  2109. {
  2110. return GetExceptionCode();
  2111. }
  2112. //
  2113. // Eip should be pointing now at the bytes following the opcode
  2114. //
  2115. if (Instruction->Prefix.b.AddressOverride == 0)
  2116. {
  2117. ReturnCode = KiIa32Compute32BitEffectiveAddress (
  2118. TrapFrame,
  2119. (PUCHAR *)&Instruction->Eip,
  2120. &Instruction->Operand1.v,
  2121. &Instruction->Operand1.RegisterMode
  2122. );
  2123. }
  2124. else
  2125. {
  2126. ReturnCode = KiIa32Compute16BitEffectiveAddress (
  2127. TrapFrame,
  2128. (PUCHAR *)&Instruction->Eip,
  2129. &Instruction->Operand1.v,
  2130. &Instruction->Operand1.RegisterMode
  2131. );
  2132. }
  2133. if (ReturnCode != TRUE)
  2134. {
  2135. NtStatus = STATUS_UNSUCCESSFUL;
  2136. }
  2137. if (Instruction->Prefix.b.FsOverride)
  2138. {
  2139. try
  2140. {
  2141. Instruction->Operand1.v += (ULONGLONG)NtCurrentTeb32();
  2142. }
  2143. except (EXCEPTION_EXECUTE_HANDLER)
  2144. {
  2145. NtStatus = GetExceptionCode ();
  2146. #if DBG
  2147. if (KiIa32InstructionEmulationDbg)
  2148. {
  2149. DbgPrint("KE: KiIa32DecodeInstruction - Exception while reading NtCurrentTeb32() - %p\n",
  2150. Instruction);
  2151. }
  2152. #endif
  2153. }
  2154. }
  2155. //
  2156. // Read in more args
  2157. //
  2158. if (NT_SUCCESS (NtStatus))
  2159. {
  2160. switch (InstructionType)
  2161. {
  2162. case IA32_PARAM_RM8_IMM8:
  2163. case IA32_PARAM_RM_IMM8SIGN:
  2164. try
  2165. {
  2166. Instruction->Operand2.v = (ULONG_PTR) ProbeAndReadUchar ((PUCHAR)Instruction->Eip);
  2167. Instruction->Eip += 1;
  2168. }
  2169. except (EXCEPTION_EXECUTE_HANDLER)
  2170. {
  2171. NtStatus = GetExceptionCode();
  2172. }
  2173. break;
  2174. case IA32_PARAM_RM_IMM:
  2175. try
  2176. {
  2177. if (Instruction->OperandSize == OPERANDSIZE_TWOBYTES)
  2178. {
  2179. UnalignedUshort = (UNALIGNED USHORT *) Instruction->Eip;
  2180. Instruction->Operand2.v = (ULONG_PTR) *UnalignedUshort;
  2181. Instruction->Eip += sizeof (USHORT);
  2182. }
  2183. else
  2184. {
  2185. UnalignedUlong = (UNALIGNED ULONG *) Instruction->Eip;
  2186. Instruction->Operand2.v = (ULONG_PTR) *UnalignedUlong;
  2187. Instruction->Eip += sizeof (ULONG);
  2188. }
  2189. }
  2190. except (EXCEPTION_EXECUTE_HANDLER)
  2191. {
  2192. NtStatus = GetExceptionCode();
  2193. }
  2194. break;
  2195. case IA32_PARAM_RM8_R:
  2196. case IA32_PARAM_R_RM8:
  2197. case IA32_PARAM_RM_R:
  2198. case IA32_PARAM_R_RM:
  2199. Instruction->Operand2.v = GetX86RegOffset (
  2200. TrapFrame,
  2201. (ModRm & MI_REGMASK) >> MI_REGSHIFT);
  2202. Instruction->Operand2.RegisterMode = TRUE;
  2203. break;
  2204. case IA32_PARAM_RM8:
  2205. case IA32_PARAM_RM:
  2206. case IA32_PARAM_SEGREG_RM8:
  2207. case IA32_PARAM_SEGREG_RM:
  2208. break;
  2209. default:
  2210. NtStatus = STATUS_UNSUCCESSFUL;
  2211. #if DBG
  2212. DbgPrint("KE: KiIa32DecodeInstruction - Invalid instruction type %lx - %p\n",
  2213. InstructionType, Instruction);
  2214. #endif
  2215. break;
  2216. }
  2217. //
  2218. // Adjust operands order
  2219. //
  2220. if (NT_SUCCESS (NtStatus))
  2221. {
  2222. switch (InstructionType)
  2223. {
  2224. case IA32_PARAM_R_RM8:
  2225. case IA32_PARAM_R_RM:
  2226. Temp = Instruction->Operand2;
  2227. Instruction->Operand2 = Instruction->Operand1;
  2228. Instruction->Operand1 = Temp;
  2229. break;
  2230. }
  2231. }
  2232. }
  2233. }
  2234. return NtStatus;
  2235. }
  2236. NTSTATUS
  2237. KiIa32ExecuteInstruction (
  2238. IN PKTRAP_FRAME TrapFrame,
  2239. IN PIA32_INSTRUCTION Instruction
  2240. )
  2241. /*++
  2242. Routine Description:
  2243. Executes the instruction handler.
  2244. Arguments:
  2245. TrapFrame - Pointer to TrapFrame.
  2246. Instruction - Pointer to the instruction being processed.
  2247. Return Value:
  2248. NTSTATUS
  2249. --*/
  2250. {
  2251. NTSTATUS NtStatus;
  2252. #if DBG
  2253. if (KiIa32InstructionEmulationDbg)
  2254. {
  2255. DbgPrint("KE: KiIa32ExecuteInstruction - Calling %s %lx, %lx. Instruction = %p\n",
  2256. KiIa32InstructionHandlerNames[Instruction->Description->Opcode],
  2257. Instruction->Operand1.v,
  2258. Instruction->Operand2.v,
  2259. Instruction);
  2260. }
  2261. #endif
  2262. NtStatus = KiIa32InstructionHandler[Instruction->Description->Opcode] (
  2263. TrapFrame,
  2264. Instruction
  2265. );
  2266. //
  2267. // If all is good...
  2268. //
  2269. if (NT_SUCCESS (NtStatus))
  2270. {
  2271. TrapFrame->StIIP = (ULONGLONG) Instruction->Eip;
  2272. KiIa32SetX86Eflags (Instruction->Eflags);
  2273. }
  2274. return NtStatus;
  2275. }
  2276. NTSTATUS
  2277. KiIa32EmulateInstruction (
  2278. IN PKTRAP_FRAME TrapFrame,
  2279. IN PIA32_INSTRUCTION Instruction
  2280. )
  2281. /*++
  2282. Routine Description:
  2283. Emulates the instruction and emulates the lock prefix, if any.
  2284. Arguments:
  2285. TrapFrame - Pointer to TrapFrame.
  2286. Instruction - Pointer to the instruction being processed.
  2287. Return Value:
  2288. NTSTATUS
  2289. --*/
  2290. {
  2291. NTSTATUS NtStatus;
  2292. //
  2293. // Acquire the lock mutex
  2294. //
  2295. if (Instruction->Prefix.b.Lock)
  2296. {
  2297. if (ExAcquireRundownProtection (&PsGetCurrentThread()->RundownProtect) == FALSE)
  2298. {
  2299. return STATUS_UNSUCCESSFUL;
  2300. }
  2301. KiIa32AcquireMisalignedLockFastMutex ();
  2302. }
  2303. try
  2304. {
  2305. NtStatus = KiIa32ExecuteInstruction (TrapFrame, Instruction);
  2306. }
  2307. except (EXCEPTION_EXECUTE_HANDLER)
  2308. {
  2309. NtStatus = GetExceptionCode();
  2310. }
  2311. //
  2312. // Release the lock mutex
  2313. //
  2314. if (Instruction->Prefix.b.Lock)
  2315. {
  2316. KiIa32ReleaseMisalignedLockFastMutex ();
  2317. ExReleaseRundownProtection (&PsGetCurrentThread()->RundownProtect);
  2318. }
  2319. return NtStatus;
  2320. }
  2321. NTSTATUS
  2322. KiIa32InterceptUnalignedLock (
  2323. IN PKTRAP_FRAME TrapFrame
  2324. )
  2325. /*++
  2326. Routine Description:
  2327. Handles misaligned lock interception raised by the iVE.
  2328. Arguments:
  2329. TrapFrame - Pointer to TrapFrame.
  2330. Return Value:
  2331. NTSTATUS
  2332. --*/
  2333. {
  2334. NTSTATUS NtStatus;
  2335. IA32_INSTRUCTION Instruction;
  2336. RtlZeroMemory (&Instruction, sizeof (Instruction));
  2337. //
  2338. // Decode the faulting instruction
  2339. //
  2340. NtStatus = KiIa32DecodeInstruction (TrapFrame, &Instruction);
  2341. if (NT_SUCCESS (NtStatus))
  2342. {
  2343. //
  2344. // xchg instruction asserts the lock by default
  2345. //
  2346. if (Instruction.Description->Opcode == Ia32_Xchg)
  2347. {
  2348. Instruction.Prefix.b.Lock = 1;
  2349. }
  2350. //
  2351. // Execute the x86 instruction by emulating its behaviour
  2352. //
  2353. NtStatus = KiIa32EmulateInstruction (TrapFrame, &Instruction);
  2354. }
  2355. if (NtStatus == STATUS_UNSUCCESSFUL)
  2356. {
  2357. NtStatus = STATUS_PRIVILEGED_INSTRUCTION;
  2358. }
  2359. return NtStatus;
  2360. }
  2361. NTSTATUS
  2362. KiIa32ValidateInstruction (
  2363. IN PKTRAP_FRAME TrapFrame
  2364. )
  2365. /*++
  2366. Routine Description:
  2367. This routine valiates the instruction that we trapped for. Currently,
  2368. the following instructions are checked:
  2369. - mov ss, r/m : the register/memory is validated to contain
  2370. a valid stack-selector value.
  2371. NOTE: This routine is only called for trap instructions (i.e. IIP is incremented
  2372. after the fault).
  2373. Arguments:
  2374. TrapFrame - Pointer to TrapFrame.
  2375. Return Value:
  2376. NTSTATUS
  2377. --*/
  2378. {
  2379. NTSTATUS NtStatus;
  2380. IA32_INSTRUCTION Instruction;
  2381. ULONGLONG UlongSrc;
  2382. ULONGLONG StIIP;
  2383. RtlZeroMemory (&Instruction, sizeof (Instruction));
  2384. //
  2385. // Adjust the instruction
  2386. //
  2387. StIIP = TrapFrame->StIIP;
  2388. TrapFrame->StIIP = TrapFrame->StIIPA;
  2389. //
  2390. // Decode the faulting instruction
  2391. //
  2392. NtStatus = KiIa32DecodeInstruction (TrapFrame, &Instruction);
  2393. if (NT_SUCCESS (NtStatus))
  2394. {
  2395. //
  2396. // Parse the opcode here
  2397. //
  2398. switch (Instruction.Description->Opcode)
  2399. {
  2400. case Ia32_MovToSeg:
  2401. {
  2402. //
  2403. // Validate the stack-selector being loaded
  2404. //
  2405. NtStatus = KiIa32ReadOperand1 (&Instruction, &UlongSrc);
  2406. if (NT_SUCCESS (NtStatus)) {
  2407. //
  2408. // If not a valid selector value
  2409. //
  2410. if ((UlongSrc != 0x23) &&
  2411. (UlongSrc != 0x1b) &&
  2412. (UlongSrc != 0x3b)) {
  2413. NtStatus = STATUS_ILLEGAL_INSTRUCTION;
  2414. }
  2415. }
  2416. }
  2417. break;
  2418. default:
  2419. NtStatus = STATUS_ILLEGAL_INSTRUCTION;
  2420. break;
  2421. }
  2422. } else {
  2423. NtStatus = STATUS_ILLEGAL_INSTRUCTION;
  2424. }
  2425. //
  2426. // Restore the saved IIP
  2427. //
  2428. if (NT_SUCCESS (NtStatus)) {
  2429. TrapFrame->StIIP = StIIP;
  2430. }
  2431. return NtStatus;
  2432. }