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.

3197 lines
96 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Disassembly portions of X86 machine implementation.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. #include "i386_dis.h"
  10. UCHAR g_X86Int3[] = { 0xcc };
  11. //----------------------------------------------------------------------------
  12. //
  13. // BaseX86MachineInfo methods.
  14. //
  15. //----------------------------------------------------------------------------
  16. /***** macros and defines *****/
  17. #define X86_CS_OVR 0x2e
  18. #define BIT20(b) ((b) & 0x07)
  19. #define BIT53(b) (((b) >> 3) & 0x07)
  20. #define BIT76(b) (((b) >> 6) & 0x03)
  21. #define MAXOPLEN 10
  22. /***** static tables and variables *****/
  23. char* g_X86Reg8[] =
  24. {
  25. "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
  26. "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
  27. };
  28. char* g_Amd64ExtendedReg8[] =
  29. {
  30. "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil"
  31. };
  32. char* g_X86RegBase[] =
  33. {
  34. "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
  35. "8", "9", "10", "11", "12", "13", "14", "15"
  36. };
  37. char *g_X86Mrm16[] =
  38. {
  39. "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx",
  40. "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
  41. };
  42. char *g_X86Mrm32[] =
  43. {
  44. "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
  45. "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
  46. };
  47. char *g_X86Mrm64[] =
  48. {
  49. "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
  50. "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
  51. };
  52. UCHAR g_X86Reg16Idx[] =
  53. {
  54. X86_NBX, X86_NBX, X86_NBP, X86_NBP,
  55. X86_NSI, X86_NDI, X86_NBP, X86_NBX,
  56. };
  57. UCHAR g_X86Reg16Idx2[] =
  58. {
  59. X86_NSI, X86_NDI, X86_NSI, X86_NDI
  60. };
  61. UCHAR g_X86RegIdx[] =
  62. {
  63. X86_NAX, X86_NCX, X86_NDX, X86_NBX,
  64. X86_NSP, X86_NBP, X86_NSI, X86_NDI,
  65. AMD64_R8, AMD64_R9, AMD64_R10, AMD64_R11,
  66. AMD64_R12, AMD64_R13, AMD64_R14, AMD64_R15
  67. };
  68. static char sregtab[] = "ecsdfg"; // first letter of ES, CS, SS, DS, FS, GS
  69. char* g_CompareIb[] = { "eq", "lt", "le", "unord", "ne", "nlt", "nle", "ord" };
  70. char hexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
  71. '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
  72. static int g_MrmMod; /* mod of mod/rm byte */
  73. static int g_MrmRm; /* rm of mod/rm byte */
  74. static int g_MrmArg; /* return reg value (of mod/rm) */
  75. static unsigned char *g_InstrMem; /* current position in instruction */
  76. ADDR EAaddr[2]; // offset of effective address
  77. static int EAsize[2]; // size of effective address item
  78. static char *g_EaSegNames[2]; // normal segment for operand
  79. #define IPREL_MARKER "<-IPREL->"
  80. BOOL g_X86ModrmHasIpRelOffset;
  81. LONG g_X86IpRelOffset;
  82. int g_SegAddrMode; /* global address size in bits */
  83. int g_SegOpSize; /* global operand size in bits */
  84. int g_AddrMode; /* local address size in bits */
  85. int g_OpSize; /* operand size in bits */
  86. int g_ExtendOpCode;
  87. int g_ExtendAny;
  88. int g_ExtendMrmReg;
  89. int g_ExtendSibIndex;
  90. int g_ExtendRm;
  91. BOOL g_MovX; // Indicates a MOVSX or MOVZX.
  92. BOOL g_MovSXD;
  93. BOOL g_ForceMrmReg32; // M/RM register is always 32-bit.
  94. BOOL g_MmRegEa; // Use mm? registers in reg-only EA.
  95. BOOL g_XmmRegEa; // Use xmm? registers in reg-only EA.
  96. BOOL g_ControlFlow; // Control flow instruction.
  97. int g_RepPrefix;
  98. enum
  99. {
  100. XMM_SS,
  101. XMM_SD,
  102. XMM_PS,
  103. XMM_PD,
  104. };
  105. int g_XmmOpSize;
  106. enum
  107. {
  108. JCC_EA_NONE,
  109. // Branch must be no-branch + 1.
  110. JCC_EA_NO_BRANCH,
  111. JCC_EA_BRANCH,
  112. };
  113. // First entry are bits that must be zero, second
  114. // and third entries are bit shifts for bits that must match.
  115. ULONG g_JccCheckTable[][3] =
  116. {
  117. X86_BIT_FLAGOF, 0, 0, // JNO
  118. X86_BIT_FLAGCF, 0, 0, // JNB
  119. X86_BIT_FLAGZF, 0, 0, // JNZ
  120. X86_BIT_FLAGCF | X86_BIT_FLAGZF, 0, 0, // JNBE
  121. X86_BIT_FLAGSF, 0, 0, // JNS
  122. X86_BIT_FLAGPF, 0, 0, // JNP
  123. 0, 7, 11, // JNL
  124. X86_BIT_FLAGZF, 7, 11, // JNLE
  125. };
  126. // internal function definitions
  127. void OutputHexString(char **, PUCHAR, int);
  128. void OutputHexValue(char **, PUCHAR, int, int);
  129. void OutputExHexValue(char **, PUCHAR, int, int);
  130. void OutputHexCode(char **, PUCHAR, int);
  131. void X86OutputString(char **, char *);
  132. void OutputHexAddr(PSTR *, PADDR);
  133. #define FormSelAddress(Addr, Sel, Off) \
  134. FormAddr(Sel, Off, 0, Addr)
  135. #define FormSegRegAddress(Addr, SegReg, Off) \
  136. FormAddr(SegReg, Off, FORM_SEGREG, Addr)
  137. void
  138. GetSegAddrOpSizes(MachineInfo* Machine, PADDR Addr)
  139. {
  140. if ((Type(*Addr) & ADDR_1664) ||
  141. ((Type(*Addr) & ADDR_FLAT) &&
  142. Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_AMD64))
  143. {
  144. g_SegAddrMode = 64;
  145. // X86-64 defaults to 32-bit operand sizes even in 64-bit code.
  146. // Only the address size changes. An operand size prefix
  147. // switches from 32- to 64-bit.
  148. g_SegOpSize = 32;
  149. }
  150. else if (Type(*Addr) & (ADDR_V86 | ADDR_16))
  151. {
  152. g_SegAddrMode = 16;
  153. g_SegOpSize = 16;
  154. }
  155. else
  156. {
  157. g_SegAddrMode = 32;
  158. g_SegOpSize = 32;
  159. }
  160. g_AddrMode = g_SegAddrMode;
  161. g_OpSize = g_SegOpSize;
  162. }
  163. void
  164. OverrideAddrMode(void)
  165. {
  166. switch(g_SegAddrMode)
  167. {
  168. case 16:
  169. g_AddrMode = 32;
  170. break;
  171. case 32:
  172. g_AddrMode = 16;
  173. break;
  174. case 64:
  175. g_AddrMode = 32;
  176. break;
  177. default:
  178. DBG_ASSERT(FALSE);
  179. break;
  180. }
  181. }
  182. void
  183. OverrideOpSize(int OverrideOp)
  184. {
  185. switch(g_SegAddrMode)
  186. {
  187. case 16:
  188. g_OpSize = 32;
  189. break;
  190. case 32:
  191. g_OpSize = 16;
  192. break;
  193. case 64:
  194. // X86-64 defaults to 32-bit operand sizes even in 64-bit code.
  195. // Only the address size changes. A REX operand size prefix
  196. // switches from 32- to 64-bit.
  197. if (OverrideOp == 0x66)
  198. {
  199. g_OpSize = 16;
  200. }
  201. else if (OverrideOp & 8)
  202. {
  203. g_OpSize = 64;
  204. }
  205. break;
  206. default:
  207. DBG_ASSERT(FALSE);
  208. break;
  209. }
  210. }
  211. void
  212. ExtendOps(int opcode)
  213. {
  214. // x86-64 uses these opcodes as the REX override.
  215. OverrideOpSize(opcode);
  216. g_ExtendOpCode = opcode;
  217. g_ExtendAny = 8;
  218. if (opcode & 1)
  219. {
  220. g_ExtendRm = 8;
  221. }
  222. if (opcode & 2)
  223. {
  224. g_ExtendSibIndex = 8;
  225. }
  226. if (opcode & 4)
  227. {
  228. g_ExtendMrmReg = 8;
  229. }
  230. }
  231. void
  232. IgnoreExtend(BOOL Verbose)
  233. {
  234. //
  235. // Resets any extensions that may have happened.
  236. // The REX prefix must be the last
  237. // prefix of an instruction and is ignored otherwise,
  238. // so this reset is done when any prefix is encountered
  239. // after the REX prefix. This should normally never
  240. // happen but technically it's valid code so we should handle it.
  241. //
  242. if (g_ExtendOpCode)
  243. {
  244. if (Verbose)
  245. {
  246. WarnOut("REX prefix ignored\n");
  247. }
  248. if (g_ExtendOpCode & 8)
  249. {
  250. // Op size was changed so put it back. This
  251. // is tricky since in theory an op size override
  252. // prefix could also be present, but let's not
  253. // worry about that for now.
  254. g_OpSize = g_SegOpSize;
  255. }
  256. g_ExtendOpCode = 0;
  257. g_ExtendAny = 0;
  258. g_ExtendRm = 0;
  259. g_ExtendSibIndex = 0;
  260. g_ExtendMrmReg = 0;
  261. }
  262. }
  263. struct AMD_3DNOW_OPSTR
  264. {
  265. PSTR Str;
  266. UCHAR Opcode;
  267. };
  268. AMD_3DNOW_OPSTR g_Amd3DNowOpStr[] =
  269. {
  270. "pavgusb", 0xBF,
  271. "pfadd", 0x9E,
  272. "pfsub", 0x9A,
  273. "pfsubr", 0xAA,
  274. "pfacc", 0xAE,
  275. "pfcmpge", 0x90,
  276. "pfcmpgt", 0xA0,
  277. "pfcmpeq", 0xB0,
  278. "pfmin", 0x94,
  279. "pfmax", 0xA4,
  280. "pi2fd", 0x0D,
  281. "pf2id", 0x1D,
  282. "pfrcp", 0x96,
  283. "pfrsqrt", 0x97,
  284. "pfmul", 0xB4,
  285. "pfrcpit1", 0xA6,
  286. "pfrsqit1", 0xA7,
  287. "pfrcpit2", 0xB6,
  288. "pmulhrw", 0xB7,
  289. "pf2iw", 0x1C,
  290. "pfnacc", 0x8A,
  291. "pfpnacc", 0x8E,
  292. "pi2fw", 0x0C,
  293. "pswapd", 0xBB,
  294. };
  295. PSTR
  296. GetAmd3DNowOpString(UCHAR Opcode)
  297. {
  298. UCHAR i;
  299. for (i = 0; i < sizeof(g_Amd3DNowOpStr) / sizeof(g_Amd3DNowOpStr[0]); i++)
  300. {
  301. if (g_Amd3DNowOpStr[i].Opcode == Opcode)
  302. {
  303. return g_Amd3DNowOpStr[i].Str;
  304. }
  305. }
  306. return NULL;
  307. }
  308. BOOL
  309. BaseX86MachineInfo::Disassemble(ProcessInfo* Process,
  310. PADDR paddr, PSTR pchDst, BOOL fEAout)
  311. {
  312. ULONG64 Offset = Off(*paddr);
  313. int opcode; /* current opcode */
  314. int olen = 2; /* operand length */
  315. int alen = 2; /* address length */
  316. int end = FALSE; /* end of instruction flag */
  317. int mrm = FALSE; /* indicator that modrm is generated*/
  318. unsigned char *action; /* action for operand interpretation*/
  319. int indx; /* temporary index */
  320. int action2; /* secondary action */
  321. ULONG instlen; /* instruction length */
  322. ULONG cBytes; // bytes read into instr buffer
  323. int segOvr = 0; /* segment override opcode */
  324. UCHAR membuf[X86_MAX_INSTRUCTION_LEN]; /* current instruction buffer */
  325. char *pEAlabel = ""; // optional label for operand
  326. char *pchResultBuf = pchDst; // working copy of pchDst pointer
  327. char RepPrefixBuffer[32]; // rep prefix buffer
  328. char *pchRepPrefixBuf = RepPrefixBuffer; // pointer to prefix buffer
  329. char OpcodeBuffer[16]; // opcode buffer
  330. char *pchOpcodeBuf = OpcodeBuffer; // pointer to opcode buffer
  331. char OperandBuffer[MAX_SYMBOL_LEN + 20]; // operand buffer
  332. char *pchOperandBuf = OperandBuffer; // pointer to operand buffer
  333. char ModrmBuffer[MAX_SYMBOL_LEN + 20]; // modRM buffer
  334. char *pchModrmBuf = ModrmBuffer; // pointer to modRM buffer
  335. char EABuffer[128]; // effective address buffer
  336. char *pchEABuf = EABuffer; // pointer to EA buffer
  337. unsigned char BOPaction;
  338. int subcode; /* bop subcode */
  339. int JccEa;
  340. LONGLONG Branch;
  341. g_X86ModrmHasIpRelOffset = FALSE;
  342. g_MovX = FALSE;
  343. g_MovSXD = FALSE;
  344. g_ForceMrmReg32 = FALSE;
  345. g_MmRegEa = FALSE;
  346. g_XmmRegEa = FALSE;
  347. g_ControlFlow = FALSE;
  348. EAsize[0] = EAsize[1] = 0; // no effective address
  349. g_EaSegNames[0] = dszDS_;
  350. g_EaSegNames[1] = dszES_;
  351. g_RepPrefix = 0;
  352. g_XmmOpSize = XMM_PS;
  353. g_ExtendOpCode = 0;
  354. g_ExtendAny = 0;
  355. g_ExtendMrmReg = 0;
  356. g_ExtendSibIndex = 0;
  357. g_ExtendRm = 0;
  358. JccEa = JCC_EA_NONE;
  359. GetSegAddrOpSizes(this, paddr);
  360. alen = g_AddrMode / 8;
  361. olen = g_OpSize / 8;
  362. OutputHexAddr(&pchResultBuf, paddr);
  363. *pchResultBuf++ = ' ';
  364. if (fnotFlat(*paddr) ||
  365. m_Target->ReadVirtual(Process, Flat(*paddr),
  366. membuf, X86_MAX_INSTRUCTION_LEN,
  367. &cBytes) != S_OK)
  368. {
  369. ZeroMemory(membuf, X86_MAX_INSTRUCTION_LEN);
  370. cBytes = 0;
  371. }
  372. g_InstrMem = membuf; /* point to begin of instruction */
  373. opcode = *g_InstrMem++; /* get opcode */
  374. if ( opcode == 0xc4 && *g_InstrMem == 0xC4 )
  375. {
  376. g_InstrMem++;
  377. X86OutputString(&pchOpcodeBuf,"BOP");
  378. action = &BOPaction;
  379. BOPaction = IB | END;
  380. subcode = *g_InstrMem;
  381. if ( subcode == 0x50 || subcode == 0x52 || subcode == 0x53 ||
  382. subcode == 0x54 || subcode == 0x57 || subcode == 0x58 ||
  383. subcode == 0x58 )
  384. {
  385. BOPaction = IW | END;
  386. }
  387. }
  388. else
  389. {
  390. X86OutputString(&pchOpcodeBuf, distbl[opcode].instruct);
  391. action = actiontbl + distbl[opcode].opr; /* get operand action */
  392. }
  393. /***** loop through all operand actions *****/
  394. do
  395. {
  396. action2 = (*action) & 0xc0;
  397. switch((*action++) & 0x3f)
  398. {
  399. case ALT: /* alter the opcode if not 16-bit */
  400. if (g_OpSize > 16)
  401. {
  402. indx = *action++;
  403. pchOpcodeBuf = &OpcodeBuffer[indx];
  404. if (indx == 0)
  405. {
  406. X86OutputString(&pchOpcodeBuf, g_OpSize == 32 ?
  407. dszCWDE : dszCDQE);
  408. }
  409. else if (g_OpSize == 64)
  410. {
  411. *pchOpcodeBuf++ = 'q';
  412. if (indx == 1)
  413. {
  414. *pchOpcodeBuf++ = 'o';
  415. }
  416. }
  417. else
  418. {
  419. *pchOpcodeBuf++ = 'd';
  420. if (indx == 1)
  421. {
  422. *pchOpcodeBuf++ = 'q';
  423. }
  424. }
  425. }
  426. break;
  427. case XMMSD: /* SSE-style opcode rewriting */
  428. {
  429. char ScalarOrPacked, SingleOrDouble;
  430. char* DquOrQ, *DqOrQ, *SsdOrUpsd, *CvtPd, *CvtPs;
  431. char* MovQD6, *Shuf;
  432. char* Scan;
  433. g_MmRegEa = TRUE;
  434. DquOrQ = "q";
  435. DqOrQ = "q";
  436. SsdOrUpsd = "s?";
  437. CvtPd = NULL;
  438. CvtPs = NULL;
  439. MovQD6 = NULL;
  440. switch(g_RepPrefix)
  441. {
  442. case X86_REPN:
  443. // Scalar double operation.
  444. ScalarOrPacked = 's';
  445. SingleOrDouble = 'd';
  446. CvtPd = "pd2dq";
  447. MovQD6 = "dq2q";
  448. Shuf = "lw";
  449. g_XmmOpSize = XMM_SD;
  450. // Assume there was no other lock/rep/etc.
  451. pchRepPrefixBuf = RepPrefixBuffer;
  452. break;
  453. case X86_REP:
  454. // Scalar single operation.
  455. ScalarOrPacked = 's';
  456. SingleOrDouble = 's';
  457. CvtPd = "dq2pd";
  458. CvtPs = "tps2dq";
  459. MovQD6 = "q2dq";
  460. Shuf = "hw";
  461. g_XmmOpSize = XMM_SS;
  462. // Assume there was no other lock/rep/etc.
  463. pchRepPrefixBuf = RepPrefixBuffer;
  464. break;
  465. default:
  466. // No rep prefix means packed single or double
  467. // depending on operand size.
  468. ScalarOrPacked = 'p';
  469. SsdOrUpsd = "up?";
  470. if (g_OpSize == g_SegOpSize)
  471. {
  472. SingleOrDouble = 's';
  473. CvtPs = "dq2ps";
  474. Shuf = "w";
  475. g_XmmOpSize = XMM_PS;
  476. }
  477. else
  478. {
  479. SingleOrDouble = 'd';
  480. DqOrQ = "dq";
  481. DquOrQ = "dqu";
  482. CvtPd = "tpd2dq";
  483. CvtPs = "ps2dq";
  484. MovQD6 = "q";
  485. Shuf = "d";
  486. g_XmmRegEa = TRUE;
  487. g_XmmOpSize = XMM_PD;
  488. }
  489. break;
  490. }
  491. pchOpcodeBuf = OpcodeBuffer;
  492. while (*pchOpcodeBuf && *pchOpcodeBuf != ' ')
  493. {
  494. switch(*pchOpcodeBuf)
  495. {
  496. case ':':
  497. *pchOpcodeBuf = ScalarOrPacked;
  498. break;
  499. case '?':
  500. *pchOpcodeBuf = SingleOrDouble;
  501. break;
  502. case ',':
  503. *pchOpcodeBuf = SingleOrDouble == 's' ? 'd' : 's';
  504. break;
  505. }
  506. pchOpcodeBuf++;
  507. }
  508. switch(opcode)
  509. {
  510. case X86_MOVFREGMEM:
  511. case X86_MOVFMEMREG:
  512. // Append characters for MOVS[SD] and MOVUP[SD].
  513. strcpy(pchOpcodeBuf, SsdOrUpsd);
  514. if ((Scan = strchr(pchOpcodeBuf, '?')) != NULL)
  515. {
  516. *Scan = SingleOrDouble;
  517. }
  518. pchOpcodeBuf += strlen(pchOpcodeBuf);
  519. break;
  520. case X86_MOVNT:
  521. // Append characters for MOVNTQ and MOVNTDQ.
  522. X86OutputString(&pchOpcodeBuf, DqOrQ);
  523. break;
  524. case X86_MASKMOV:
  525. // Append characters for MASKMOVQ and MASKMOVDQU.
  526. X86OutputString(&pchOpcodeBuf, DquOrQ);
  527. break;
  528. case X86_CVTPD:
  529. if (CvtPd == NULL)
  530. {
  531. // Invalid opcode.
  532. pchOpcodeBuf = OpcodeBuffer;
  533. X86OutputString(&pchOpcodeBuf, dszRESERVED);
  534. action2 = END;
  535. }
  536. else
  537. {
  538. // Append characters for CVT<PD>.
  539. X86OutputString(&pchOpcodeBuf, CvtPd);
  540. }
  541. break;
  542. case X86_CVTPS:
  543. if (CvtPs == NULL)
  544. {
  545. // Invalid opcode.
  546. pchOpcodeBuf = OpcodeBuffer;
  547. X86OutputString(&pchOpcodeBuf, dszRESERVED);
  548. action2 = END;
  549. }
  550. else
  551. {
  552. // Append characters for CVT<PS>.
  553. X86OutputString(&pchOpcodeBuf, CvtPs);
  554. }
  555. break;
  556. case X86_MOVQ_D6:
  557. if (MovQD6 == NULL)
  558. {
  559. // Invalid opcode.
  560. pchOpcodeBuf = OpcodeBuffer;
  561. X86OutputString(&pchOpcodeBuf, dszRESERVED);
  562. action2 = END;
  563. }
  564. else
  565. {
  566. // Append characters for MOVQ D6 family.
  567. X86OutputString(&pchOpcodeBuf, MovQD6);
  568. }
  569. break;
  570. case X86_PSHUF:
  571. // Append characters for PSHUF variants.
  572. X86OutputString(&pchOpcodeBuf, Shuf);
  573. break;
  574. }
  575. }
  576. break;
  577. case AMD3DNOW: /* AMD 3DNow post-instruction byte */
  578. {
  579. PSTR OpStr;
  580. // Get the trailing byte and look up
  581. // the opcode string.
  582. OpStr = GetAmd3DNowOpString(*g_InstrMem++);
  583. if (OpStr == NULL)
  584. {
  585. // Not a defined 3DNow instruction.
  586. // Leave the ??? in the opstring.
  587. break;
  588. }
  589. // Update opstring to real text.
  590. pchOpcodeBuf = OpcodeBuffer;
  591. X86OutputString(&pchOpcodeBuf, OpStr);
  592. }
  593. break;
  594. case STROP:
  595. // compute size of operands in indx
  596. // also if dword operands, change fifth
  597. // opcode letter from 'w' to 'd'.
  598. if (opcode & 1)
  599. {
  600. if (g_OpSize == 64)
  601. {
  602. indx = 8;
  603. OpcodeBuffer[4] = 'q';
  604. }
  605. else if (g_OpSize == 32)
  606. {
  607. indx = 4;
  608. OpcodeBuffer[4] = 'd';
  609. }
  610. else
  611. {
  612. indx = 2;
  613. }
  614. }
  615. else
  616. {
  617. indx = 1;
  618. }
  619. if (*action & 1)
  620. {
  621. if (fEAout)
  622. {
  623. if (g_AddrMode > 16)
  624. {
  625. FormSelAddress(&EAaddr[0], 0, GetReg64(X86_NSI));
  626. }
  627. else
  628. {
  629. FormSegRegAddress(&EAaddr[0], SEGREG_DATA,
  630. GetReg16(X86_NSI));
  631. }
  632. EAsize[0] = indx;
  633. }
  634. }
  635. if (*action++ & 2)
  636. {
  637. if (fEAout)
  638. {
  639. if (g_AddrMode > 16)
  640. {
  641. FormSelAddress(&EAaddr[1], 0, GetReg64(X86_NDI));
  642. }
  643. else
  644. {
  645. FormSegRegAddress(&EAaddr[1], SEGREG_ES,
  646. GetReg16(X86_NDI));
  647. }
  648. EAsize[1] = indx;
  649. }
  650. }
  651. break;
  652. case CHR: /* insert a character */
  653. *pchOperandBuf++ = *action++;
  654. break;
  655. case CREG: /* set debug, test or control reg */
  656. if (opcode & 0x04)
  657. {
  658. *pchOperandBuf++ = 't';
  659. }
  660. else if (opcode & 0x01)
  661. {
  662. *pchOperandBuf++ = 'd';
  663. }
  664. else
  665. {
  666. *pchOperandBuf++ = 'c';
  667. }
  668. *pchOperandBuf++ = 'r';
  669. if (g_MrmArg >= 10)
  670. {
  671. *pchOperandBuf++ = (char)('0' + g_MrmArg / 10);
  672. g_MrmArg %= 10;
  673. }
  674. *pchOperandBuf++ = (char)('0' + g_MrmArg);
  675. break;
  676. case SREG2: /* segment register */
  677. g_MrmArg = BIT53(opcode); // set value to fall through
  678. case SREG3: /* segment register */
  679. *pchOperandBuf++ = sregtab[g_MrmArg]; // reg is part of modrm
  680. *pchOperandBuf++ = 's';
  681. break;
  682. case BRSTR: /* get index to register string */
  683. g_MrmArg = *action++; /* from action table */
  684. goto BREGlabel;
  685. case BOREG: /* byte register (in opcode) */
  686. g_MrmArg = BIT20(opcode); /* register is part of opcode */
  687. goto BREGlabel;
  688. case ALSTR:
  689. g_MrmArg = 0; /* point to AL register */
  690. BREGlabel:
  691. case BREG: /* general register */
  692. if (g_ExtendAny && g_MrmArg < 8)
  693. {
  694. X86OutputString(&pchOperandBuf, g_Amd64ExtendedReg8[g_MrmArg]);
  695. }
  696. else
  697. {
  698. X86OutputString(&pchOperandBuf, g_X86Reg8[g_MrmArg]);
  699. }
  700. break;
  701. case WRSTR: /* get index to register string */
  702. g_MrmArg = *action++; /* from action table */
  703. goto WREGlabel;
  704. case VOREG: /* register is part of opcode */
  705. if (m_ExecTypes[0] == IMAGE_FILE_MACHINE_AMD64 &&
  706. opcode >= 0x40 && opcode <= 0x4f)
  707. {
  708. // Get rid of the inc/dec text as this
  709. // isn't really an inc/dec.
  710. pchOpcodeBuf = OpcodeBuffer;
  711. // Process the REX override.
  712. ExtendOps(opcode);
  713. olen = g_OpSize / 8;
  714. action2 = 0;
  715. goto getNxtByte;
  716. }
  717. g_MrmArg = BIT20(opcode) + g_ExtendRm;
  718. goto VREGlabel;
  719. case AXSTR:
  720. g_MrmArg = 0; /* point to eAX register */
  721. VREGlabel:
  722. case VREG: /* general register */
  723. if ((g_SegAddrMode == 64 &&
  724. opcode >= 0x50 && opcode <= 0x5f) ||
  725. g_MrmArg >= 8)
  726. {
  727. // Push/pops are always 64-bit in 64-bit segments.
  728. *pchOperandBuf++ = 'r';
  729. }
  730. else if (g_OpSize == 32 ||
  731. opcode == X86_PEXTRW ||
  732. opcode == X86_PMOVMSKB)
  733. {
  734. *pchOperandBuf++ = 'e';
  735. }
  736. else if (g_OpSize == 64)
  737. {
  738. *pchOperandBuf++ = 'r';
  739. }
  740. WREGlabel:
  741. case WREG: /* register is word size */
  742. X86OutputString(&pchOperandBuf, g_X86RegBase[g_MrmArg]);
  743. if (g_MrmArg >= 8)
  744. {
  745. if (g_OpSize == 32)
  746. {
  747. *pchOperandBuf++ = 'd';
  748. }
  749. else if (g_OpSize == 16)
  750. {
  751. *pchOperandBuf++ = 'w';
  752. }
  753. }
  754. break;
  755. case MMORWREG:
  756. if (g_XmmOpSize == XMM_SS || g_XmmOpSize == XMM_SD)
  757. {
  758. goto VREGlabel;
  759. }
  760. // Fall through.
  761. MMWREGlabel:
  762. case MMWREG:
  763. if ((g_OpSize != g_SegOpSize &&
  764. opcode != X86_CVTSPSD2SPI) ||
  765. (g_RepPrefix == X86_REP &&
  766. (opcode == X86_MOVDQAU_MR || opcode == X86_MOVDQAU_RM)))
  767. {
  768. *pchOperandBuf++ = 'x';
  769. }
  770. *pchOperandBuf++ = 'm';
  771. *pchOperandBuf++ = 'm';
  772. if (g_MrmArg >= 10)
  773. {
  774. *pchOperandBuf++ = (char)('0' + g_MrmArg / 10);
  775. g_MrmArg %= 10;
  776. }
  777. *pchOperandBuf++ = g_MrmArg + '0';
  778. break;
  779. case XORMMREG:
  780. if (g_OpSize == g_SegOpSize)
  781. {
  782. goto MMWREGlabel;
  783. }
  784. // Fall through.
  785. case XMMWREG:
  786. if (opcode != X86_PSHUF || g_XmmOpSize != XMM_PS)
  787. {
  788. *pchOperandBuf++ = 'x';
  789. }
  790. *pchOperandBuf++ = 'm';
  791. *pchOperandBuf++ = 'm';
  792. if (g_MrmArg >= 10)
  793. {
  794. *pchOperandBuf++ = (char)('0' + g_MrmArg / 10);
  795. g_MrmArg %= 10;
  796. }
  797. *pchOperandBuf++ = g_MrmArg + '0';
  798. break;
  799. case IST_ST:
  800. X86OutputString(&pchOperandBuf, "st(0),st");
  801. *(pchOperandBuf - 5) += (char)g_MrmRm;
  802. break;
  803. case ST_IST:
  804. X86OutputString(&pchOperandBuf, "st,");
  805. case IST:
  806. X86OutputString(&pchOperandBuf, "st(0)");
  807. *(pchOperandBuf - 2) += (char)g_MrmRm;
  808. break;
  809. case xBYTE: /* set instruction to byte only */
  810. EAsize[0] = 1;
  811. pEAlabel = "byte ptr ";
  812. break;
  813. case VAR:
  814. if ((g_SegAddrMode == 64 || g_ExtendAny > 0) &&
  815. opcode == 0x63)
  816. {
  817. // In AMD64 REX32 and 64-bit modes this instruction
  818. // is MOVSXD r64, r/m32 instead of ARPL r/m, reg.
  819. pchOpcodeBuf = OpcodeBuffer;
  820. X86OutputString(&pchOpcodeBuf, dszMOVSXD);
  821. action = &actiontbl[O_Reg_Modrm] + 1;
  822. g_OpSize = 64;
  823. g_MovSXD = TRUE;
  824. goto DWORDlabel;
  825. }
  826. else if (opcode == 0xff)
  827. {
  828. UCHAR Extra = BIT53(*g_InstrMem);
  829. if (Extra >= 2 && Extra <= 5)
  830. {
  831. g_ControlFlow = TRUE;
  832. // On x86-64 control-flow operations default to
  833. // 64-bit opsize.
  834. if (g_SegAddrMode == 64)
  835. {
  836. if (g_OpSize == 32)
  837. {
  838. g_OpSize = 64;
  839. }
  840. }
  841. }
  842. else if (g_SegAddrMode == 64 && Extra == 6)
  843. {
  844. // Push/pops are always 64-bit in 64-bit segments.
  845. g_OpSize = 64;
  846. }
  847. }
  848. else if (g_SegAddrMode == 64 && opcode == 0x8f)
  849. {
  850. // Push/pops are always 64-bit in 64-bit segments.
  851. g_OpSize = 64;
  852. }
  853. olen = g_OpSize / 8;
  854. if (g_OpSize == 64)
  855. {
  856. goto QWORDlabel;
  857. }
  858. else if (g_OpSize == 32)
  859. {
  860. goto DWORDlabel;
  861. }
  862. case xWORD:
  863. if (opcode == X86_PINSRW)
  864. {
  865. g_ForceMrmReg32 = TRUE;
  866. }
  867. EAsize[0] = 2;
  868. pEAlabel = "word ptr ";
  869. break;
  870. case EDWORD:
  871. // Control register opsize is mode-independent.
  872. g_OpSize = g_SegAddrMode;
  873. if (g_OpSize == 64)
  874. {
  875. goto QWORDlabel;
  876. }
  877. case xDWORD:
  878. if (opcode == X86_MOVDQ_7E && g_RepPrefix == X86_REP)
  879. {
  880. // Switch to MOVQ xmm1, xmm2/m64.
  881. pchRepPrefixBuf = RepPrefixBuffer;
  882. *(pchOpcodeBuf - 1) = 'q';
  883. EAsize[0] = 8;
  884. pEAlabel = "qword ptr ";
  885. g_XmmRegEa = TRUE;
  886. action = &actiontbl[O_Sd_XmmReg_qModrm] + 2;
  887. break;
  888. }
  889. // Fall through.
  890. DWORDlabel:
  891. EAsize[0] = 4;
  892. pEAlabel = "dword ptr ";
  893. break;
  894. case XMMOWORD:
  895. if (opcode == X86_PSHUF)
  896. {
  897. if (g_XmmOpSize == XMM_PS)
  898. {
  899. g_MmRegEa = TRUE;
  900. goto QWORDlabel;
  901. }
  902. else
  903. {
  904. EAsize[0] = 16;
  905. pEAlabel = "oword ptr ";
  906. break;
  907. }
  908. }
  909. g_XmmRegEa = TRUE;
  910. if (opcode == X86_CVTPD)
  911. {
  912. if (g_XmmOpSize == XMM_SS)
  913. {
  914. EAsize[0] = 8;
  915. pEAlabel = "qword ptr ";
  916. }
  917. else
  918. {
  919. EAsize[0] = 16;
  920. pEAlabel = "oword ptr ";
  921. }
  922. break;
  923. }
  924. else if (opcode == X86_CVTPS)
  925. {
  926. EAsize[0] = 16;
  927. pEAlabel = "oword ptr ";
  928. break;
  929. }
  930. else if (opcode == X86_MOVQ_D6)
  931. {
  932. if (g_XmmOpSize == XMM_SD)
  933. {
  934. // Switch to MOVDQ2Q mm, xmm.
  935. EAsize[0] = 16;
  936. pEAlabel = "oword ptr ";
  937. action = &actiontbl[O_MmReg_qModrm] + 1;
  938. break;
  939. }
  940. }
  941. else if (opcode == X86_MOVHLPS && g_XmmOpSize == XMM_PS &&
  942. BIT76(*g_InstrMem) == 3)
  943. {
  944. // reg-reg form of MOVLPS is called MOVHLPS.
  945. pchOpcodeBuf = OpcodeBuffer;
  946. X86OutputString(&pchOpcodeBuf, dszMOVHLPS);
  947. }
  948. else if (opcode == X86_MOVLHPS && g_XmmOpSize == XMM_PS &&
  949. BIT76(*g_InstrMem) == 3)
  950. {
  951. // reg-reg form of MOVHPS is called MOVLHPS.
  952. pchOpcodeBuf = OpcodeBuffer;
  953. X86OutputString(&pchOpcodeBuf, dszMOVLHPS);
  954. }
  955. // Fall through.
  956. OWORDlabel:
  957. case OWORD:
  958. switch(g_XmmOpSize)
  959. {
  960. case XMM_SS:
  961. EAsize[0] = 4;
  962. pEAlabel = "dword ptr ";
  963. if (opcode == X86_MOVQ_D6)
  964. {
  965. // Switch to MOVQ xmm1, xmm2/m64.
  966. g_XmmRegEa = FALSE;
  967. action = &actiontbl[O_Sd_XmmReg_qModrm] + 1;
  968. }
  969. break;
  970. case XMM_SD:
  971. EAsize[0] = 8;
  972. pEAlabel = "qword ptr ";
  973. break;
  974. default:
  975. if (opcode == 0x112 || opcode == 0x113 ||
  976. opcode == 0x116 || opcode == 0x117 ||
  977. opcode == X86_MOVQ_D6 ||
  978. (g_OpSize == g_SegOpSize &&
  979. (opcode == 0x12c || opcode == X86_CVTSPSD2SPI ||
  980. opcode == X86_CVTSPSD2SPSD)))
  981. {
  982. EAsize[0] = 8;
  983. pEAlabel = "qword ptr ";
  984. }
  985. else
  986. {
  987. EAsize[0] = 16;
  988. pEAlabel = "oword ptr ";
  989. }
  990. break;
  991. }
  992. break;
  993. case XMMXWORD:
  994. g_XmmRegEa = TRUE;
  995. if (g_OpSize == g_SegOpSize)
  996. {
  997. if (opcode == X86_MOVNT)
  998. {
  999. EAsize[0] = 8;
  1000. pEAlabel = "qword ptr ";
  1001. }
  1002. else
  1003. {
  1004. EAsize[0] = 4;
  1005. pEAlabel = "dword ptr ";
  1006. }
  1007. }
  1008. else
  1009. {
  1010. if (opcode == X86_MOVNT)
  1011. {
  1012. EAsize[0] = 16;
  1013. pEAlabel = "oword ptr ";
  1014. }
  1015. else
  1016. {
  1017. EAsize[0] = 8;
  1018. pEAlabel = "qword ptr ";
  1019. }
  1020. }
  1021. break;
  1022. case MMQWORD:
  1023. // The REX prefix is ignored in front of most
  1024. // FP and MM operations. The only affect it
  1025. // has is to allow extended register selection.
  1026. // Reset the opsize as the 64-bit opsize behavior
  1027. // of the REX prefix is ignored.
  1028. if (g_ExtendOpCode & 8)
  1029. {
  1030. g_OpSize = g_SegOpSize;
  1031. }
  1032. if (g_OpSize != g_SegOpSize &&
  1033. (opcode == X86_MOVDQAU_MR || opcode == X86_MOVDQAU_RM))
  1034. {
  1035. pchOpcodeBuf = OpcodeBuffer;
  1036. X86OutputString(&pchOpcodeBuf, dszMOVDQA);
  1037. }
  1038. else if (g_RepPrefix == X86_REP &&
  1039. (opcode == X86_MOVDQAU_MR || opcode == X86_MOVDQAU_RM))
  1040. {
  1041. pchRepPrefixBuf = RepPrefixBuffer;
  1042. pchOpcodeBuf = OpcodeBuffer;
  1043. X86OutputString(&pchOpcodeBuf, dszMOVDQU);
  1044. g_XmmRegEa = TRUE;
  1045. goto OWORDlabel;
  1046. }
  1047. if (opcode == X86_CVTSPI2SPSD)
  1048. {
  1049. g_XmmRegEa = FALSE;
  1050. if (g_XmmOpSize == XMM_SS || g_XmmOpSize == XMM_SD)
  1051. {
  1052. g_MmRegEa = FALSE;
  1053. goto DWORDlabel;
  1054. }
  1055. }
  1056. else if (g_OpSize != g_SegOpSize)
  1057. {
  1058. g_XmmRegEa = TRUE;
  1059. goto OWORDlabel;
  1060. }
  1061. g_MmRegEa = TRUE;
  1062. QWORDlabel:
  1063. case QWORD:
  1064. EAsize[0] = 8;
  1065. pEAlabel = "qword ptr ";
  1066. break;
  1067. case TBYTE:
  1068. EAsize[0] = 10;
  1069. pEAlabel = "tbyte ptr ";
  1070. break;
  1071. case FARPTR:
  1072. g_ControlFlow = TRUE;
  1073. // On x86-64 control-flow operations default to
  1074. // 64-bit opsize.
  1075. if (g_SegAddrMode == 64)
  1076. {
  1077. if (g_OpSize == 32)
  1078. {
  1079. g_OpSize = 64;
  1080. }
  1081. }
  1082. switch(g_OpSize)
  1083. {
  1084. case 16:
  1085. EAsize[0] = 4;
  1086. pEAlabel = "dword ptr ";
  1087. break;
  1088. default:
  1089. EAsize[0] = 6;
  1090. pEAlabel = "fword ptr ";
  1091. break;
  1092. }
  1093. break;
  1094. case LMODRM: // output modRM data type
  1095. if (g_MrmMod != 3)
  1096. {
  1097. X86OutputString(&pchOperandBuf, pEAlabel);
  1098. }
  1099. else
  1100. {
  1101. EAsize[0] = 0;
  1102. }
  1103. case MODRM: /* output modrm string */
  1104. if (segOvr) /* in case of segment override */
  1105. {
  1106. X86OutputString(&pchOperandBuf, distbl[segOvr].instruct);
  1107. }
  1108. *pchModrmBuf = '\0';
  1109. X86OutputString(&pchOperandBuf, ModrmBuffer);
  1110. break;
  1111. case ADDRP: /* address pointer */
  1112. // segment
  1113. OutputHexString(&pchOperandBuf, g_InstrMem + olen, 2);
  1114. *pchOperandBuf++ = ':';
  1115. // offset
  1116. OutputSymbol(&pchOperandBuf, g_InstrMem, olen, segOvr);
  1117. g_InstrMem += olen + 2;
  1118. break;
  1119. case JCC8:
  1120. JccEa = ComputeJccEa(opcode, fEAout);
  1121. // Fall through.
  1122. case REL8: /* relative address 8-bit */
  1123. if (opcode == 0xe3 && g_AddrMode > 16)
  1124. {
  1125. pchOpcodeBuf = OpcodeBuffer;
  1126. X86OutputString(&pchOpcodeBuf, g_AddrMode == 64 ?
  1127. dszJRCXZ : dszJECXZ);
  1128. }
  1129. Branch = *(char *)g_InstrMem++; /* get the 8-bit rel offset */
  1130. goto DoRelDispl;
  1131. case JCCX:
  1132. JccEa = ComputeJccEa(opcode, fEAout);
  1133. // Fall through.
  1134. case REL16: /* relative address 16-/32-bit */
  1135. switch(g_AddrMode)
  1136. {
  1137. case 16:
  1138. Branch = *(short UNALIGNED *)g_InstrMem;
  1139. g_InstrMem += 2;
  1140. break;
  1141. default:
  1142. Branch = *(long UNALIGNED *)g_InstrMem;
  1143. g_InstrMem += 4;
  1144. break;
  1145. }
  1146. DoRelDispl:
  1147. /* calculate address */
  1148. Branch += Offset + (g_InstrMem - membuf);
  1149. // rel8 and rel16 are only used in control-flow
  1150. // instructions so the target is always relative
  1151. // to CS. Pass in the CS override to force this.
  1152. OutputSymbol(&pchOperandBuf, (PUCHAR)&Branch, alen, X86_CS_OVR);
  1153. break;
  1154. case UBYTE: // unsigned byte for int/in/out
  1155. OutputHexString(&pchOperandBuf, g_InstrMem, 1); // ubyte
  1156. g_InstrMem++;
  1157. break;
  1158. case CMPIB:
  1159. // Immediate byte comparison encoding for CMP[SP][SD].
  1160. if (*g_InstrMem < 8)
  1161. {
  1162. X86OutputString(&pchOperandBuf, g_CompareIb[*g_InstrMem]);
  1163. g_InstrMem++;
  1164. }
  1165. else
  1166. {
  1167. olen = 1;
  1168. goto DoImmed;
  1169. }
  1170. break;
  1171. case IB: /* operand is immediate byte */
  1172. // postop for AAD/AAM is 0x0a
  1173. if ((opcode & ~1) == 0xd4)
  1174. {
  1175. // test post-opcode byte
  1176. if (*g_InstrMem++ != 0x0a)
  1177. {
  1178. X86OutputString(&pchOperandBuf, dszRESERVED);
  1179. }
  1180. break;
  1181. }
  1182. olen = 1; /* set operand length */
  1183. goto DoImmed;
  1184. case IW: /* operand is immediate word */
  1185. olen = 2; /* set operand length */
  1186. case IV: /* operand is word or dword */
  1187. DoImmed:
  1188. // AMD64 immediates are only 64-bit in the case of
  1189. // mov reg, immed. All other operations involving
  1190. // immediates stay 32-bit.
  1191. if (olen == 8 &&
  1192. (opcode < 0xb8 || opcode > 0xbf))
  1193. {
  1194. olen = 4;
  1195. }
  1196. OutputHexValue(&pchOperandBuf, g_InstrMem, olen, FALSE);
  1197. g_InstrMem += olen;
  1198. break;
  1199. case XB:
  1200. OutputExHexValue(&pchOperandBuf, g_InstrMem, 1, g_OpSize / 8);
  1201. g_InstrMem++;
  1202. break;
  1203. case OFFS: /* operand is offset */
  1204. EAsize[0] = (opcode & 1) ? olen : 1;
  1205. if (segOvr) /* in case of segment override */
  1206. {
  1207. X86OutputString(&pchOperandBuf, distbl[segOvr].instruct);
  1208. }
  1209. *pchOperandBuf++ = '[';
  1210. // offset
  1211. OutputSymbol(&pchOperandBuf, g_InstrMem, alen, segOvr);
  1212. g_InstrMem += alen;
  1213. *pchOperandBuf++ = ']';
  1214. break;
  1215. case X86_GROUP: /* operand is of group 1,2,4,6 or 8 */
  1216. /* output opcode symbol */
  1217. X86OutputString(&pchOpcodeBuf, group[*action++][g_MrmArg]);
  1218. break;
  1219. case GROUPT: /* operand is of group 3,5 or 7 */
  1220. indx = *action; /* get indx into group from action */
  1221. goto doGroupT;
  1222. case EGROUPT: /* x87 ESC (D8-DF) group index */
  1223. indx = BIT20(opcode) * 2; /* get group index from opcode */
  1224. /* some operand variations exist */
  1225. if (g_MrmMod == 3)
  1226. {
  1227. /* for x87 and mod == 3 */
  1228. ++indx; /* take the next group table entry */
  1229. if (indx == 3)
  1230. {
  1231. /* for x87 ESC==D9 and mod==3 */
  1232. if (g_MrmArg > 3)
  1233. {
  1234. /* for those D9 instructions */
  1235. indx = 12 + g_MrmArg; /* offset index to table by 12 */
  1236. g_MrmArg = g_MrmRm; /* set secondary index to rm */
  1237. }
  1238. }
  1239. else if (indx == 7)
  1240. {
  1241. /* for x87 ESC==DB and mod==3 */
  1242. if (g_MrmArg == 4)
  1243. {
  1244. /* if g_MrmArg==4 */
  1245. g_MrmArg = g_MrmRm; /* set secondary group table index */
  1246. }
  1247. else if ((g_MrmArg < 4) || (g_MrmArg > 4 && g_MrmArg < 7))
  1248. {
  1249. // adjust for pentium pro opcodes
  1250. indx = 24; /* offset index to table by 24*/
  1251. }
  1252. }
  1253. }
  1254. doGroupT:
  1255. /* handle group with different types of operands */
  1256. X86OutputString(&pchOpcodeBuf, groupt[indx][g_MrmArg].instruct);
  1257. action = actiontbl + groupt[indx][g_MrmArg].opr;
  1258. /* get new action */
  1259. break;
  1260. case OPC0F: /* secondary opcode table (opcode 0F) */
  1261. opcode = *g_InstrMem++; /* get real opcode */
  1262. g_MovX = (BOOL)(opcode == 0xBF || opcode == 0xB7);
  1263. // Point opcode into secondary opcode portion of table.
  1264. opcode += 256;
  1265. goto getNxtByte1;
  1266. case ADR_OVR: /* address override */
  1267. IgnoreExtend(TRUE);
  1268. olen = g_OpSize / 8;
  1269. OverrideAddrMode();
  1270. alen = g_AddrMode / 8;
  1271. goto getNxtByte;
  1272. case OPR_OVR: /* operand size override */
  1273. IgnoreExtend(TRUE);
  1274. OverrideOpSize(opcode);
  1275. olen = g_OpSize / 8;
  1276. goto getNxtByte;
  1277. case SEG_OVR: /* handle segment override */
  1278. IgnoreExtend(TRUE);
  1279. olen = g_OpSize / 8;
  1280. segOvr = opcode; /* save segment override opcode */
  1281. pchOpcodeBuf = OpcodeBuffer; // restart the opcode string
  1282. goto getNxtByte;
  1283. case REP: /* handle rep/lock prefixes */
  1284. IgnoreExtend(TRUE);
  1285. olen = g_OpSize / 8;
  1286. g_RepPrefix = opcode;
  1287. *pchOpcodeBuf = '\0';
  1288. if (pchRepPrefixBuf != RepPrefixBuffer)
  1289. {
  1290. *pchRepPrefixBuf++ = ' ';
  1291. }
  1292. X86OutputString(&pchRepPrefixBuf, OpcodeBuffer);
  1293. pchOpcodeBuf = OpcodeBuffer;
  1294. getNxtByte:
  1295. opcode = *g_InstrMem++; /* next byte is opcode */
  1296. getNxtByte1:
  1297. action = actiontbl + distbl[opcode].opr;
  1298. X86OutputString(&pchOpcodeBuf, distbl[opcode].instruct);
  1299. break;
  1300. case NOP:
  1301. if (opcode == X86_PAUSE && g_RepPrefix == X86_REP)
  1302. {
  1303. pchRepPrefixBuf = RepPrefixBuffer;
  1304. pchOpcodeBuf = OpcodeBuffer;
  1305. X86OutputString(&pchOpcodeBuf, dszPAUSE);
  1306. }
  1307. // Fall through.
  1308. default: /* opcode has no operand */
  1309. break;
  1310. }
  1311. /* secondary action */
  1312. switch (action2)
  1313. {
  1314. case MRM:
  1315. /* generate modrm for later use */
  1316. /* ignore if it has been generated */
  1317. if (!mrm)
  1318. {
  1319. /* generate modrm */
  1320. DIdoModrm(Process, &pchModrmBuf, segOvr, fEAout);
  1321. mrm = TRUE; /* remember its generation */
  1322. }
  1323. break;
  1324. case COM: /* insert a comma after operand */
  1325. *pchOperandBuf++ = ',';
  1326. break;
  1327. case END: /* end of instruction */
  1328. end = TRUE;
  1329. break;
  1330. }
  1331. } while (!end); /* loop til end of instruction */
  1332. /***** prepare disassembled instruction for output *****/
  1333. // dprintf("EAaddr[] = %08lx\n", (ULONG)Flat(EAaddr[0]));
  1334. instlen = (ULONG)(g_InstrMem - membuf);
  1335. if (instlen < cBytes)
  1336. {
  1337. cBytes = instlen;
  1338. }
  1339. int obOpcode = m_Ptr64 ? 35 : 26;
  1340. int obOpcodeMin;
  1341. int obOpcodeMax;
  1342. int obOperand = m_Ptr64 ? 43 : 34;
  1343. int obOperandMin;
  1344. int obOperandMax;
  1345. int cbOpcode;
  1346. int cbOperand;
  1347. int cbOffset;
  1348. int cbEAddr;
  1349. int obLineEnd = g_OutputWidth - 3;
  1350. if (g_AsmOptions & DEBUG_ASMOPT_IGNORE_OUTPUT_WIDTH)
  1351. {
  1352. // Extend the line end out a long way but
  1353. // not so much that overflows may occur.
  1354. obLineEnd = 0x7fffff;
  1355. }
  1356. if (!(g_AsmOptions & DEBUG_ASMOPT_NO_CODE_BYTES))
  1357. {
  1358. OutputHexCode(&pchResultBuf, membuf, cBytes);
  1359. }
  1360. else
  1361. {
  1362. obOpcode -= 16;
  1363. obOperand -= 16;
  1364. }
  1365. if (instlen > cBytes)
  1366. {
  1367. *pchResultBuf++ = '?';
  1368. *pchResultBuf++ = '?';
  1369. // point past unread byte
  1370. AddrAdd(paddr, 1);
  1371. do
  1372. {
  1373. *pchResultBuf++ = ' ';
  1374. } while (pchResultBuf < pchDst + obOpcode);
  1375. X86OutputString(&pchResultBuf, "???\n");
  1376. *pchResultBuf++ = '\0';
  1377. return FALSE;
  1378. }
  1379. AddrAdd(paddr, instlen);
  1380. PSTR Mark;
  1381. // Now that we know the complete size of the instruction
  1382. // we can correctly compute IP-relative absolute addresses.
  1383. *pchOperandBuf = 0;
  1384. if (g_X86ModrmHasIpRelOffset &&
  1385. (Mark = strstr(OperandBuffer, IPREL_MARKER)) != NULL)
  1386. {
  1387. PSTR TailFrom, TailTo;
  1388. ULONG64 IpRelAddr;
  1389. size_t TailLen;
  1390. // Move the tail of the string to the end of the buffer
  1391. // to make space.
  1392. TailFrom = Mark + sizeof(IPREL_MARKER) - 1;
  1393. TailLen = pchOperandBuf - TailFrom;
  1394. TailTo = OperandBuffer + (sizeof(OperandBuffer) - 1 - TailLen);
  1395. memmove(TailTo, TailFrom, TailLen);
  1396. // Compute the absolute address from the new IP
  1397. // and the offset and format it into the buffer.
  1398. IpRelAddr = Flat(*paddr) + g_X86IpRelOffset;
  1399. OutputSymbol(&Mark, (PUCHAR)&IpRelAddr, g_SegAddrMode == 64 ? 8 : 4,
  1400. X86_CS_OVR);
  1401. if (Mark < TailTo)
  1402. {
  1403. memmove(Mark, TailTo, TailLen);
  1404. pchOperandBuf = Mark + TailLen;
  1405. }
  1406. else if (Mark >= TailTo + TailLen)
  1407. {
  1408. pchOperandBuf = Mark;
  1409. }
  1410. else
  1411. {
  1412. pchOperandBuf = Mark + (TailLen - (Mark - TailTo));
  1413. }
  1414. }
  1415. // if fEAout is set, build each EA with trailing space in EABuf
  1416. // point back over final trailing space if buffer nonnull
  1417. if (fEAout)
  1418. {
  1419. for (indx = 0; indx < 2; indx++)
  1420. {
  1421. if (EAsize[indx])
  1422. {
  1423. X86OutputString(&pchEABuf, segOvr ? distbl[segOvr].instruct
  1424. : g_EaSegNames[indx]);
  1425. OutputHexAddr(&pchEABuf, &EAaddr[indx]);
  1426. *pchEABuf++ = '=';
  1427. if (fFlat(EAaddr[indx]) &&
  1428. m_Target->ReadAllVirtual(Process, Flat(EAaddr[indx]),
  1429. membuf, EAsize[indx]) == S_OK)
  1430. {
  1431. OutputHexString(&pchEABuf, membuf, EAsize[indx]);
  1432. }
  1433. else
  1434. {
  1435. while (EAsize[indx]--)
  1436. {
  1437. *pchEABuf++ = '?';
  1438. *pchEABuf++ = '?';
  1439. }
  1440. }
  1441. *pchEABuf++ = ' ';
  1442. }
  1443. }
  1444. if (pchEABuf != EABuffer)
  1445. {
  1446. pchEABuf--;
  1447. }
  1448. switch(JccEa)
  1449. {
  1450. case JCC_EA_NO_BRANCH:
  1451. X86OutputString(&pchEABuf, "[br=0]");
  1452. break;
  1453. case JCC_EA_BRANCH:
  1454. X86OutputString(&pchEABuf, "[br=1]");
  1455. break;
  1456. }
  1457. }
  1458. // compute lengths of component strings.
  1459. // if the rep string is nonnull,
  1460. // add the opcode string length to the operand
  1461. // make the rep string the opcode string
  1462. cbOffset = (int)(pchResultBuf - pchDst);
  1463. cbOperand = (int)(pchOperandBuf - OperandBuffer);
  1464. cbOpcode = (int)(pchOpcodeBuf - OpcodeBuffer);
  1465. if (pchRepPrefixBuf != RepPrefixBuffer)
  1466. {
  1467. cbOperand += cbOpcode + (cbOperand != 0);
  1468. cbOpcode = (int)(pchRepPrefixBuf - RepPrefixBuffer);
  1469. }
  1470. cbEAddr = (int)(pchEABuf - EABuffer);
  1471. // compute the minimum and maximum offset values for
  1472. // opcode and operand strings.
  1473. // if strings are nonnull, add extra for separating space
  1474. obOpcodeMin = cbOffset + 1;
  1475. obOperandMin = obOpcodeMin + cbOpcode + 1;
  1476. obOperandMax = obLineEnd - cbEAddr - (cbEAddr != 0) - cbOperand;
  1477. obOpcodeMax = obOperandMax - (cbOperand != 0) - cbOpcode;
  1478. // compute the opcode and operand offsets. set offset as
  1479. // close to the default values as possible.
  1480. if (obOpcodeMin > obOpcode)
  1481. {
  1482. obOpcode = obOpcodeMin;
  1483. }
  1484. else if (obOpcodeMax < obOpcode)
  1485. {
  1486. obOpcode = obOpcodeMax;
  1487. }
  1488. obOperandMin = obOpcode + cbOpcode + 1;
  1489. if (obOperandMin > obOperand)
  1490. {
  1491. obOperand = obOperandMin;
  1492. }
  1493. else if (obOperandMax < obOperand)
  1494. {
  1495. obOperand = obOperandMax;
  1496. }
  1497. // build the resultant string with the offsets computed
  1498. // output rep, opcode, and operand strings
  1499. do
  1500. {
  1501. *pchResultBuf++ = ' ';
  1502. } while (pchResultBuf < pchDst + obOpcode);
  1503. if (pchRepPrefixBuf != RepPrefixBuffer)
  1504. {
  1505. *pchRepPrefixBuf = '\0';
  1506. X86OutputString(&pchResultBuf, RepPrefixBuffer);
  1507. do
  1508. {
  1509. *pchResultBuf++ = ' ';
  1510. } while (pchResultBuf < pchDst + obOperand);
  1511. }
  1512. *pchOpcodeBuf = '\0';
  1513. X86OutputString(&pchResultBuf, OpcodeBuffer);
  1514. if (pchOperandBuf != OperandBuffer)
  1515. {
  1516. do
  1517. {
  1518. *pchResultBuf++ = ' ';
  1519. } while (pchResultBuf < pchDst + obOperand);
  1520. *pchOperandBuf = '\0';
  1521. X86OutputString(&pchResultBuf, OperandBuffer);
  1522. }
  1523. // append the EAddr string
  1524. if (pchEABuf != EABuffer)
  1525. {
  1526. *pchEABuf = '\0';
  1527. do
  1528. {
  1529. *pchResultBuf++ = ' ';
  1530. } while (pchResultBuf < pchDst + obLineEnd - cbEAddr);
  1531. X86OutputString(&pchResultBuf, EABuffer);
  1532. }
  1533. *pchResultBuf++ = '\n';
  1534. *pchResultBuf = '\0';
  1535. return TRUE;
  1536. }
  1537. void
  1538. BaseX86MachineInfo::GetNextOffset(ProcessInfo* Process, BOOL StepOver,
  1539. PADDR NextAddr, PULONG NextMachine)
  1540. {
  1541. ULONG cBytes;
  1542. UCHAR membuf[X86_MAX_INSTRUCTION_LEN]; // current instruction buffer
  1543. UCHAR *InstrMem;
  1544. UCHAR opcode;
  1545. int fPrefix = TRUE;
  1546. int fRepPrefix = FALSE;
  1547. int MrmMod;
  1548. int MrmArg;
  1549. int MrmRm;
  1550. ULONG64 instroffset;
  1551. int subcode;
  1552. // NextMachine is always the same.
  1553. *NextMachine = m_ExecTypes[0];
  1554. // read instruction stream bytes into membuf and set mode and
  1555. // opcode size flags
  1556. GetPC(NextAddr);
  1557. instroffset = Flat(*NextAddr);
  1558. GetSegAddrOpSizes(this, NextAddr);
  1559. /* move full inst to local buffer */
  1560. if (fnotFlat(*NextAddr) ||
  1561. m_Target->ReadVirtual(Process, Flat(*NextAddr),
  1562. membuf, X86_MAX_INSTRUCTION_LEN,
  1563. &cBytes) != S_OK)
  1564. {
  1565. cBytes = 0;
  1566. }
  1567. // Ensure that membuf is padded with innocuous bytes in
  1568. // the section that wasn't read.
  1569. if (cBytes < X86_MAX_INSTRUCTION_LEN)
  1570. {
  1571. memset(membuf + cBytes, 0xcc, X86_MAX_INSTRUCTION_LEN - cBytes);
  1572. }
  1573. /* point to begin of instruction */
  1574. InstrMem = membuf;
  1575. // read and process any prefixes first
  1576. do
  1577. {
  1578. opcode = *InstrMem++; /* get opcode */
  1579. if (opcode == 0x66)
  1580. {
  1581. OverrideOpSize(opcode);
  1582. }
  1583. else if (m_ExecTypes[0] == IMAGE_FILE_MACHINE_AMD64 &&
  1584. opcode >= 0x40 && opcode <= 0x4f)
  1585. {
  1586. ExtendOps(opcode);
  1587. }
  1588. else if (opcode == 0x67)
  1589. {
  1590. OverrideAddrMode();
  1591. }
  1592. else if ((opcode & ~1) == 0xf2)
  1593. {
  1594. fRepPrefix = TRUE;
  1595. }
  1596. else if (opcode != 0xf0 && (opcode & ~0x18) != 0x26 &&
  1597. (opcode & ~1) != 0x64)
  1598. {
  1599. fPrefix = FALSE;
  1600. }
  1601. } while (fPrefix);
  1602. // for instructions that alter the TF (trace flag), return the
  1603. // offset of the next instruction despite the flag of StepOver
  1604. if (((opcode & ~0x3) == 0x9c) && !g_WatchTrace)
  1605. {
  1606. // 9c-9f, pushf, popf, sahf, lahf
  1607. ;
  1608. }
  1609. else if (opcode == 0xcf)
  1610. {
  1611. ULONG64 RetAddr[2];
  1612. ADDR Sp;
  1613. ULONG Seg;
  1614. // cf - iret - get RA from stack
  1615. FormSegRegAddress(&Sp, SEGREG_STACK, GetReg64(X86_NSP));
  1616. if (fnotFlat(Sp) ||
  1617. m_Target->ReadAllVirtual(Process, Flat(Sp),
  1618. RetAddr, g_SegAddrMode / 4) != S_OK)
  1619. {
  1620. instroffset = OFFSET_TRACE;
  1621. goto Exit;
  1622. }
  1623. Seg = *(PUSHORT)((PUCHAR)RetAddr + g_SegAddrMode / 8);
  1624. switch(g_SegAddrMode)
  1625. {
  1626. case 16:
  1627. instroffset = EXTEND64(*(PUSHORT)RetAddr);
  1628. break;
  1629. case 32:
  1630. instroffset = EXTEND64(*(PULONG)RetAddr);
  1631. break;
  1632. case 64:
  1633. instroffset = RetAddr[0];
  1634. break;
  1635. }
  1636. FormSelAddress(NextAddr, Seg, instroffset);
  1637. ComputeFlatAddress(NextAddr, NULL);
  1638. return;
  1639. }
  1640. else if (opcode == 0xc4 && *InstrMem == 0xc4)
  1641. {
  1642. subcode = *(InstrMem+1);
  1643. if ( subcode == 0x50 ||
  1644. subcode == 0x52 ||
  1645. subcode == 0x53 ||
  1646. subcode == 0x54 ||
  1647. subcode == 0x57 ||
  1648. subcode == 0x58 ||
  1649. subcode == 0x5D )
  1650. {
  1651. InstrMem += 3;
  1652. }
  1653. else
  1654. {
  1655. InstrMem += 2;
  1656. }
  1657. }
  1658. else if (!StepOver)
  1659. {
  1660. // if tracing just return OFFSET_TRACE to trace
  1661. instroffset = OFFSET_TRACE;
  1662. }
  1663. else if (opcode == 0xe8)
  1664. {
  1665. // near direct jump
  1666. InstrMem += g_OpSize > 16 ? 4 : 2;
  1667. }
  1668. else if (opcode == 0x9a)
  1669. {
  1670. // far direct jump
  1671. InstrMem += g_OpSize > 16 ? 6 : 4;
  1672. }
  1673. else if (opcode == 0xcd ||
  1674. (opcode >= 0xe0 && opcode <= 0xe2))
  1675. {
  1676. // loop / int nn instrs
  1677. InstrMem++;
  1678. }
  1679. else if (opcode == 0xff)
  1680. {
  1681. // indirect call - compute length
  1682. opcode = *InstrMem++; // get modRM
  1683. MrmArg = BIT53(opcode);
  1684. if ((MrmArg & ~1) == 2)
  1685. {
  1686. MrmMod = BIT76(opcode);
  1687. if (MrmMod != 3)
  1688. {
  1689. // nonregister operand
  1690. MrmRm = BIT20(opcode);
  1691. if (g_AddrMode > 16)
  1692. {
  1693. if (MrmRm == 4)
  1694. {
  1695. MrmRm = BIT20(*InstrMem++); // get base from SIB
  1696. }
  1697. if (MrmMod == 0)
  1698. {
  1699. if (MrmRm == 5)
  1700. {
  1701. InstrMem += 4; // long direct address
  1702. } // else register
  1703. }
  1704. else if (MrmMod == 1)
  1705. {
  1706. InstrMem++; // register with byte offset
  1707. }
  1708. else
  1709. {
  1710. InstrMem += 4; // register with long offset
  1711. }
  1712. }
  1713. else
  1714. {
  1715. // 16-bit mode
  1716. if (MrmMod == 0)
  1717. {
  1718. if (MrmRm == 6)
  1719. {
  1720. InstrMem += 2; // short direct address
  1721. }
  1722. }
  1723. else
  1724. {
  1725. InstrMem += MrmMod; // reg, byte, word offset
  1726. }
  1727. }
  1728. }
  1729. }
  1730. else
  1731. {
  1732. instroffset = OFFSET_TRACE; // 0xff, but not call
  1733. }
  1734. }
  1735. else if (!((fRepPrefix && ((opcode & ~3) == 0x6c ||
  1736. (opcode & ~3) == 0xa4 ||
  1737. (opcode & ~1) == 0xaa ||
  1738. (opcode & ~3) == 0xac)) ||
  1739. opcode == 0xcc || opcode == 0xce))
  1740. {
  1741. instroffset = OFFSET_TRACE; // not repeated string op
  1742. } // or int 3 / into
  1743. // if not enough bytes were read for instruction parse,
  1744. // just give up and trace the instruction
  1745. if (cBytes < (ULONG)(InstrMem - (PUCHAR)membuf))
  1746. {
  1747. instroffset = OFFSET_TRACE;
  1748. }
  1749. Exit:
  1750. // if not tracing, compute the new instruction offset
  1751. if (instroffset != OFFSET_TRACE)
  1752. {
  1753. instroffset += InstrMem - (PUCHAR)membuf;
  1754. }
  1755. Flat(*NextAddr) = instroffset;
  1756. ComputeNativeAddress(NextAddr);
  1757. }
  1758. /*...........................internal function..............................*/
  1759. /* */
  1760. /* generate a mod/rm string */
  1761. /* */
  1762. void
  1763. BaseX86MachineInfo::DIdoModrm(ProcessInfo* Process,
  1764. char **ppchBuf, int segOvr, BOOL fEAout)
  1765. {
  1766. int mrm; /* modrm byte */
  1767. char *src; /* source string */
  1768. int sib;
  1769. int ss;
  1770. int ind;
  1771. int oldrm;
  1772. mrm = *g_InstrMem++; /* get the mrm byte from instruction */
  1773. g_MrmMod = BIT76(mrm); /* get mod */
  1774. g_MrmArg = BIT53(mrm) + g_ExtendMrmReg; /* get reg - used outside routine */
  1775. g_MrmRm = BIT20(mrm); /* get rm */
  1776. if (g_MrmMod == 3)
  1777. {
  1778. g_MrmRm += g_ExtendRm;
  1779. /* register only mode */
  1780. if (g_XmmRegEa)
  1781. {
  1782. *(*ppchBuf)++ = 'x';
  1783. *(*ppchBuf)++ = 'm';
  1784. *(*ppchBuf)++ = 'm';
  1785. if (g_MrmRm >= 10)
  1786. {
  1787. *(*ppchBuf)++ = (char)('0' + g_MrmRm / 10);
  1788. g_MrmRm %= 10;
  1789. }
  1790. *(*ppchBuf)++ = g_MrmRm + '0';
  1791. }
  1792. else if (g_MmRegEa)
  1793. {
  1794. *(*ppchBuf)++ = 'm';
  1795. *(*ppchBuf)++ = 'm';
  1796. *(*ppchBuf)++ = g_MrmRm + '0';
  1797. }
  1798. else
  1799. {
  1800. if (EAsize[0] == 1)
  1801. {
  1802. /* point to 8-bit register */
  1803. if (g_ExtendAny && g_MrmRm < 8)
  1804. {
  1805. src = g_Amd64ExtendedReg8[g_MrmRm];
  1806. }
  1807. else
  1808. {
  1809. src = g_X86Reg8[g_MrmRm];
  1810. }
  1811. X86OutputString(ppchBuf, src);
  1812. }
  1813. else
  1814. {
  1815. src = g_X86RegBase[g_MrmRm];
  1816. if (g_ForceMrmReg32)
  1817. {
  1818. *(*ppchBuf)++ = 'e';
  1819. }
  1820. else if (g_OpSize > 16 &&
  1821. (!g_MovX || g_MrmRm >= 8))
  1822. {
  1823. /* make it a 32- or 64-bit register */
  1824. *(*ppchBuf)++ = (g_MrmRm >= 8 || g_OpSize == 64 && !g_MovSXD) ?
  1825. 'r' : 'e';
  1826. }
  1827. X86OutputString(ppchBuf, src);
  1828. if (g_MrmRm >= 8)
  1829. {
  1830. if (g_OpSize == 32)
  1831. {
  1832. *(*ppchBuf)++ = 'd';
  1833. }
  1834. else if (g_OpSize == 16)
  1835. {
  1836. *(*ppchBuf)++ = 'w';
  1837. }
  1838. }
  1839. if (g_ControlFlow && fEAout)
  1840. {
  1841. // This is a call/jmp through a register.
  1842. // Output a code symbol for the target.
  1843. ULONG64 Target = GetReg64(g_X86RegIdx[g_MrmRm]);
  1844. *(*ppchBuf)++ = ' ';
  1845. *(*ppchBuf)++ = '{';
  1846. OutputSymbol(ppchBuf, (PUCHAR)&Target, g_OpSize / 8,
  1847. X86_CS_OVR);
  1848. *(*ppchBuf)++ = '}';
  1849. }
  1850. }
  1851. }
  1852. EAsize[0] = 0; // no EA value to output
  1853. return;
  1854. }
  1855. if (g_AddrMode == 64)
  1856. {
  1857. oldrm = g_MrmRm;
  1858. if (g_MrmRm == 4)
  1859. {
  1860. /* g_MrmRm == 4 implies sib byte */
  1861. sib = *g_InstrMem++; /* get s_i_b byte */
  1862. g_MrmRm = BIT20(sib);
  1863. }
  1864. *(*ppchBuf)++ = '[';
  1865. if (g_MrmMod == 0 && g_MrmRm == 5)
  1866. {
  1867. if (g_SegAddrMode == 64 && oldrm == 5)
  1868. {
  1869. // IP-relative 32-bit displacement. The
  1870. // displacement is relative to the IP of the
  1871. // next instruction, which can't be computed
  1872. // yet so just put in a marker for post-processing.
  1873. g_X86ModrmHasIpRelOffset = TRUE;
  1874. g_X86IpRelOffset = *(LONG UNALIGNED *)g_InstrMem;
  1875. X86OutputString(ppchBuf, IPREL_MARKER);
  1876. }
  1877. else
  1878. {
  1879. // Absolute 32-bit displacement.
  1880. OutputSymbol(ppchBuf, g_InstrMem, 4, segOvr);
  1881. }
  1882. g_InstrMem += 4;
  1883. }
  1884. else
  1885. {
  1886. g_MrmRm += g_ExtendRm;
  1887. if (fEAout)
  1888. {
  1889. if (segOvr)
  1890. {
  1891. FormSegRegAddress(&EAaddr[0], GetSegReg(segOvr),
  1892. GetReg64(g_X86RegIdx[g_MrmRm]));
  1893. g_EaSegNames[0] = distbl[segOvr].instruct;
  1894. }
  1895. else if (g_X86RegIdx[g_MrmRm] == X86_NBP ||
  1896. g_X86RegIdx[g_MrmRm] == X86_NSP)
  1897. {
  1898. FormSegRegAddress(&EAaddr[0], SEGREG_STACK,
  1899. GetReg64(g_X86RegIdx[g_MrmRm]));
  1900. g_EaSegNames[0] = dszSS_;
  1901. }
  1902. else
  1903. {
  1904. FormSegRegAddress(&EAaddr[0], SEGREG_DATA,
  1905. GetReg64(g_X86RegIdx[g_MrmRm]));
  1906. }
  1907. }
  1908. X86OutputString(ppchBuf, g_X86Mrm64[g_MrmRm]);
  1909. }
  1910. if (oldrm == 4)
  1911. {
  1912. // finish processing sib
  1913. ind = BIT53(sib);
  1914. if (ind != 4)
  1915. {
  1916. ind += g_ExtendSibIndex;
  1917. *(*ppchBuf)++ = '+';
  1918. X86OutputString(ppchBuf, g_X86Mrm64[ind]);
  1919. ss = 1 << BIT76(sib);
  1920. if (ss != 1)
  1921. {
  1922. *(*ppchBuf)++ = '*';
  1923. *(*ppchBuf)++ = (char)(ss + '0');
  1924. }
  1925. if (fEAout)
  1926. {
  1927. AddrAdd(&EAaddr[0], GetReg64(g_X86RegIdx[ind]) * ss);
  1928. }
  1929. }
  1930. }
  1931. }
  1932. else if (g_AddrMode == 32)
  1933. {
  1934. oldrm = g_MrmRm;
  1935. if (g_MrmRm == 4)
  1936. {
  1937. /* g_MrmRm == 4 implies sib byte */
  1938. sib = *g_InstrMem++; /* get s_i_b byte */
  1939. g_MrmRm = BIT20(sib);
  1940. }
  1941. *(*ppchBuf)++ = '[';
  1942. if (g_MrmMod == 0 && g_MrmRm == 5)
  1943. {
  1944. if (g_SegAddrMode == 64 && oldrm == 5)
  1945. {
  1946. // IP-relative 32-bit displacement. The
  1947. // displacement is relative to the IP of the
  1948. // next instruction, which can't be computed
  1949. // yet so just put in a marker for post-processing.
  1950. g_X86ModrmHasIpRelOffset = TRUE;
  1951. g_X86IpRelOffset = *(LONG UNALIGNED *)g_InstrMem;
  1952. X86OutputString(ppchBuf, IPREL_MARKER);
  1953. }
  1954. else
  1955. {
  1956. // Absolute 32-bit displacement.
  1957. OutputSymbol(ppchBuf, g_InstrMem, 4, segOvr);
  1958. }
  1959. g_InstrMem += 4;
  1960. }
  1961. else
  1962. {
  1963. g_MrmRm += g_ExtendRm;
  1964. if (fEAout)
  1965. {
  1966. if (segOvr)
  1967. {
  1968. FormSegRegAddress(&EAaddr[0], GetSegReg(segOvr),
  1969. EXTEND64(GetReg32(g_X86RegIdx[g_MrmRm])));
  1970. g_EaSegNames[0] = distbl[segOvr].instruct;
  1971. }
  1972. else if (g_X86RegIdx[g_MrmRm] == X86_NBP ||
  1973. g_X86RegIdx[g_MrmRm] == X86_NSP)
  1974. {
  1975. FormSegRegAddress(&EAaddr[0], SEGREG_STACK,
  1976. EXTEND64(GetReg32(g_X86RegIdx[g_MrmRm])));
  1977. g_EaSegNames[0] = dszSS_;
  1978. }
  1979. else
  1980. {
  1981. FormSegRegAddress(&EAaddr[0], SEGREG_DATA,
  1982. EXTEND64(GetReg32(g_X86RegIdx[g_MrmRm])));
  1983. }
  1984. }
  1985. X86OutputString(ppchBuf, g_X86Mrm32[g_MrmRm]);
  1986. }
  1987. if (oldrm == 4)
  1988. {
  1989. // finish processing sib
  1990. ind = BIT53(sib);
  1991. if (ind != 4)
  1992. {
  1993. ind += g_ExtendSibIndex;
  1994. *(*ppchBuf)++ = '+';
  1995. X86OutputString(ppchBuf, g_X86Mrm32[ind]);
  1996. ss = 1 << BIT76(sib);
  1997. if (ss != 1)
  1998. {
  1999. *(*ppchBuf)++ = '*';
  2000. *(*ppchBuf)++ = (char)(ss + '0');
  2001. }
  2002. if (fEAout)
  2003. {
  2004. AddrAdd(&EAaddr[0],
  2005. EXTEND64(GetReg32(g_X86RegIdx[ind])) * ss);
  2006. }
  2007. }
  2008. }
  2009. }
  2010. else
  2011. {
  2012. // 16-bit addressing mode
  2013. *(*ppchBuf)++ = '[';
  2014. if (g_MrmMod == 0 && g_MrmRm == 6)
  2015. {
  2016. OutputSymbol(ppchBuf, g_InstrMem, 2, segOvr); // 16-bit offset
  2017. g_InstrMem += 2;
  2018. }
  2019. else
  2020. {
  2021. if (fEAout)
  2022. {
  2023. if (segOvr)
  2024. {
  2025. FormSegRegAddress(&EAaddr[0], GetSegReg(segOvr),
  2026. GetReg16(g_X86Reg16Idx[g_MrmRm]));
  2027. g_EaSegNames[0] = distbl[segOvr].instruct;
  2028. }
  2029. else if (g_X86Reg16Idx[g_MrmRm] == X86_NBP)
  2030. {
  2031. FormSegRegAddress(&EAaddr[0], SEGREG_STACK,
  2032. GetReg16(g_X86Reg16Idx[g_MrmRm]));
  2033. g_EaSegNames[0] = dszSS_;
  2034. }
  2035. else
  2036. {
  2037. FormSegRegAddress(&EAaddr[0], SEGREG_DATA,
  2038. GetReg16(g_X86Reg16Idx[g_MrmRm]));
  2039. }
  2040. if (g_MrmRm < 4)
  2041. {
  2042. AddrAdd(&EAaddr[0], GetReg16(g_X86Reg16Idx2[g_MrmRm]));
  2043. }
  2044. }
  2045. X86OutputString(ppchBuf, g_X86Mrm16[g_MrmRm]);
  2046. }
  2047. }
  2048. // output any displacement
  2049. if (g_MrmMod == 1)
  2050. {
  2051. if (fEAout)
  2052. {
  2053. AddrAdd(&EAaddr[0], (long)*(char *)g_InstrMem);
  2054. }
  2055. OutputHexValue(ppchBuf, g_InstrMem, 1, TRUE);
  2056. g_InstrMem++;
  2057. }
  2058. else if (g_MrmMod == 2)
  2059. {
  2060. long tmp = 0;
  2061. if (g_AddrMode > 16)
  2062. {
  2063. memmove(&tmp, g_InstrMem, sizeof(long));
  2064. if (fEAout)
  2065. {
  2066. AddrAdd(&EAaddr[0], tmp);
  2067. }
  2068. OutputHexValue(ppchBuf, g_InstrMem, 4, TRUE);
  2069. g_InstrMem += 4;
  2070. }
  2071. else
  2072. {
  2073. memmove(&tmp,g_InstrMem,sizeof(short));
  2074. if (fEAout)
  2075. {
  2076. AddrAdd(&EAaddr[0], tmp);
  2077. }
  2078. OutputHexValue(ppchBuf, g_InstrMem, 2, TRUE);
  2079. g_InstrMem += 2;
  2080. }
  2081. }
  2082. if (g_AddrMode == 16 && fEAout)
  2083. {
  2084. Off(EAaddr[0]) &= 0xffff;
  2085. NotFlat(EAaddr[0]);
  2086. Off(EAaddr[1]) &= 0xffff;
  2087. NotFlat(EAaddr[1]);
  2088. ComputeFlatAddress(&EAaddr[0], NULL);
  2089. ComputeFlatAddress(&EAaddr[1], NULL);
  2090. }
  2091. *(*ppchBuf)++ = ']';
  2092. // The value at the effective address may be pointing to an interesting
  2093. // symbol, as with indirect jumps or memory operations.
  2094. // If there's an EA and an exact symbol match, display
  2095. // the extra symbol.
  2096. if (fEAout)
  2097. {
  2098. DWORD64 symbol;
  2099. if (m_Target->
  2100. ReadPointer(Process, this, Flat(EAaddr[0]), &symbol) == S_OK)
  2101. {
  2102. char* pchBuf = *ppchBuf;
  2103. (*ppchBuf)++;
  2104. if (OutputExactSymbol(ppchBuf, (PUCHAR)&symbol,
  2105. m_Ptr64 ? 8 : 4, segOvr))
  2106. {
  2107. *pchBuf = '{';
  2108. *(*ppchBuf)++ = '}';
  2109. }
  2110. else
  2111. {
  2112. (*ppchBuf)--;
  2113. }
  2114. }
  2115. }
  2116. }
  2117. LONGLONG
  2118. GetSignExtendedValue(int OpLen, PUCHAR Mem)
  2119. {
  2120. switch(OpLen)
  2121. {
  2122. case 1:
  2123. return *(char *)Mem;
  2124. case 2:
  2125. return *(short UNALIGNED *)Mem;
  2126. case 4:
  2127. return *(long UNALIGNED *)Mem;
  2128. case 8:
  2129. return *(LONGLONG UNALIGNED *)Mem;
  2130. }
  2131. DBG_ASSERT(FALSE);
  2132. return 0;
  2133. }
  2134. /*** OutputHexValue - output hex value
  2135. * 07-Jun-1999 -by- Andre Vachon
  2136. * Purpose:
  2137. * Output the value pointed by *ppchBuf of the specified
  2138. * length. The value is treated as signed and leading
  2139. * zeroes are not printed. The string is prefaced by a
  2140. * '+' or '-' sign as appropriate.
  2141. *
  2142. * Input:
  2143. * *ppchBuf - pointer to text buffer to fill
  2144. * *pchMemBuf - pointer to memory buffer to extract value
  2145. * length - length in bytes of value (1, 2, and 4 supported)
  2146. * fDisp - set if displacement to output '+'
  2147. *
  2148. * Output:
  2149. * *ppchBuf - pointer updated to next text character
  2150. *
  2151. *************************************************************************/
  2152. void
  2153. OutputHexValue (char **ppchBuf, PUCHAR pchMemBuf, int length, int fDisp)
  2154. {
  2155. LONGLONG value;
  2156. int index;
  2157. char digit[32];
  2158. value = GetSignExtendedValue(length, pchMemBuf);
  2159. length <<= 1; // shift once to get hex length
  2160. if (value != 0 || !fDisp)
  2161. {
  2162. if (fDisp)
  2163. {
  2164. // use neg value for byte displacement
  2165. // assume very large DWORDs are negative too
  2166. if (value < 0 &&
  2167. (length == 2 ||
  2168. ((unsigned long)value & 0xff000000) == 0xff000000))
  2169. {
  2170. value = -value;
  2171. *(*ppchBuf)++ = '-';
  2172. }
  2173. else
  2174. {
  2175. *(*ppchBuf)++ = '+';
  2176. }
  2177. }
  2178. *(*ppchBuf)++ = '0';
  2179. *(*ppchBuf)++ = 'x';
  2180. for (index = length - 1; index != -1; index--)
  2181. {
  2182. digit[index] = (char)(value & 0xf);
  2183. value >>= 4;
  2184. }
  2185. index = 0;
  2186. while (digit[index] == 0 && index < length - 1)
  2187. {
  2188. index++;
  2189. }
  2190. while (index < length)
  2191. {
  2192. *(*ppchBuf)++ = hexdigit[digit[index++]];
  2193. }
  2194. }
  2195. }
  2196. void
  2197. OutputExHexValue(char **ppchBuf, PUCHAR pchMemBuf, int MemLen, int OpLen)
  2198. {
  2199. LONGLONG Value = GetSignExtendedValue(MemLen, pchMemBuf);
  2200. OutputHexValue(ppchBuf, (PUCHAR)&Value, OpLen, FALSE);
  2201. }
  2202. /*** OutputHexString - output hex string
  2203. *
  2204. * Purpose:
  2205. * Output the value pointed by *ppchMemBuf of the specified
  2206. * length. The value is treated as unsigned and leading
  2207. * zeroes are printed.
  2208. *
  2209. * Input:
  2210. * *ppchBuf - pointer to text buffer to fill
  2211. * *pchValue - pointer to memory buffer to extract value
  2212. * length - length in bytes of value
  2213. *
  2214. * Output:
  2215. * *ppchBuf - pointer updated to next text character
  2216. * *ppchMemBuf - pointer update to next memory byte
  2217. *
  2218. *************************************************************************/
  2219. void
  2220. OutputHexString (char **ppchBuf, PUCHAR pchValue, int length)
  2221. {
  2222. UCHAR chMem;
  2223. pchValue += length;
  2224. while (length--)
  2225. {
  2226. chMem = *--pchValue;
  2227. *(*ppchBuf)++ = hexdigit[chMem >> 4];
  2228. *(*ppchBuf)++ = hexdigit[chMem & 0x0f];
  2229. }
  2230. }
  2231. /*** OutputHexCode - output hex code
  2232. *
  2233. * Purpose:
  2234. * Output the code pointed by pchMemBuf of the specified
  2235. * length. The value is treated as unsigned and leading
  2236. * zeroes are printed. This differs from OutputHexString
  2237. * in that bytes are printed from low to high addresses.
  2238. *
  2239. * Input:
  2240. * *ppchBuf - pointer to text buffer to fill
  2241. * pchMemBuf - pointer to memory buffer to extract value
  2242. * length - length in bytes of value
  2243. *
  2244. * Output:
  2245. * *ppchBuf - pointer updated to next text character
  2246. *
  2247. *************************************************************************/
  2248. void OutputHexCode (char **ppchBuf, PUCHAR pchMemBuf, int length)
  2249. {
  2250. UCHAR chMem;
  2251. while (length--)
  2252. {
  2253. chMem = *pchMemBuf++;
  2254. *(*ppchBuf)++ = hexdigit[chMem >> 4];
  2255. *(*ppchBuf)++ = hexdigit[chMem & 0x0f];
  2256. }
  2257. }
  2258. /*** X86OutputString - output string
  2259. *
  2260. * Purpose:
  2261. * Copy the string into the buffer pointed by *ppBuf.
  2262. *
  2263. * Input:
  2264. * *pStr - pointer to string
  2265. *
  2266. * Output:
  2267. * *ppBuf points to next character in buffer.
  2268. *
  2269. *************************************************************************/
  2270. void
  2271. X86OutputString (
  2272. char **ppBuf,
  2273. char *pStr
  2274. )
  2275. {
  2276. while (*pStr)
  2277. {
  2278. *(*ppBuf)++ = *pStr++;
  2279. }
  2280. }
  2281. /*** OutputSymbol - output symbolic value
  2282. *
  2283. * Purpose:
  2284. * Output the value in outvalue into the buffer
  2285. * pointed by *pBuf. Express the value as a
  2286. * symbol plus displacment, if possible.
  2287. *
  2288. * Input:
  2289. * *ppBuf - pointer to text buffer to fill
  2290. * *pValue - pointer to memory buffer to extract value
  2291. * length - length in bytes of value
  2292. *
  2293. * Output:
  2294. * *ppBuf - pointer updated to next text character
  2295. *
  2296. *************************************************************************/
  2297. void
  2298. BaseX86MachineInfo::OutputSymbol (
  2299. char **ppBuf,
  2300. PUCHAR pValue,
  2301. int length,
  2302. int segOvr
  2303. )
  2304. {
  2305. CHAR chSymbol[MAX_SYMBOL_LEN];
  2306. ULONG64 displacement;
  2307. ULONG64 value;
  2308. value = 0;
  2309. memcpy(&value, pValue, length);
  2310. if (length == 4)
  2311. {
  2312. value = EXTEND64(value);
  2313. }
  2314. if (IS_CONTEXT_POSSIBLE(m_Target))
  2315. {
  2316. FormSegRegAddress(&EAaddr[0], GetSegReg(segOvr), value);
  2317. value = Flat(EAaddr[0]);
  2318. }
  2319. GetSymbol(value, chSymbol, sizeof(chSymbol), &displacement);
  2320. if (chSymbol[0])
  2321. {
  2322. X86OutputString(ppBuf, chSymbol);
  2323. OutputHexValue(ppBuf, (PUCHAR)&displacement, length, TRUE);
  2324. *(*ppBuf)++ = ' ';
  2325. *(*ppBuf)++ = '(';
  2326. OutputHexString(ppBuf, pValue, length);
  2327. *(*ppBuf)++ = ')';
  2328. }
  2329. else
  2330. {
  2331. OutputHexString(ppBuf, pValue, length);
  2332. }
  2333. }
  2334. /*** OutputExactSymbol - Output symbolic value only for exact symbol
  2335. * matches.
  2336. *
  2337. *************************************************************************/
  2338. BOOL
  2339. BaseX86MachineInfo::OutputExactSymbol (
  2340. char **ppBuf,
  2341. PUCHAR pValue,
  2342. int length,
  2343. int segOvr
  2344. )
  2345. {
  2346. CHAR chSymbol[MAX_SYMBOL_LEN];
  2347. ULONG64 displacement;
  2348. ULONG64 value;
  2349. value = 0;
  2350. memcpy(&value, pValue, length);
  2351. if (length == 4)
  2352. {
  2353. value = EXTEND64(value);
  2354. }
  2355. GetSymbol(value, chSymbol, sizeof(chSymbol), &displacement);
  2356. if (chSymbol[0] && displacement == 0)
  2357. {
  2358. X86OutputString(ppBuf, chSymbol);
  2359. OutputHexValue(ppBuf, (PUCHAR)&displacement, length, TRUE);
  2360. *(*ppBuf)++ = ' ';
  2361. *(*ppBuf)++ = '(';
  2362. OutputHexString(ppBuf, pValue, length);
  2363. *(*ppBuf)++ = ')';
  2364. return TRUE;
  2365. }
  2366. else
  2367. {
  2368. return FALSE;
  2369. }
  2370. }
  2371. void
  2372. OutputHexAddr(PSTR *ppBuffer, PADDR paddr)
  2373. {
  2374. sprintAddr(ppBuffer, paddr);
  2375. // Remove trailing space.
  2376. (*ppBuffer)--;
  2377. **ppBuffer = 0;
  2378. }
  2379. ULONG
  2380. BaseX86MachineInfo::GetSegReg(int SegOpcode)
  2381. {
  2382. switch(SegOpcode)
  2383. {
  2384. case 0x26:
  2385. return SEGREG_ES;
  2386. case X86_CS_OVR:
  2387. return SEGREG_CODE;
  2388. case 0x36:
  2389. return SEGREG_STACK;
  2390. case 0x64:
  2391. return SEGREG_FS;
  2392. case 0x65:
  2393. return SEGREG_GS;
  2394. case 0x3e:
  2395. default:
  2396. return SEGREG_DATA;
  2397. }
  2398. }
  2399. int
  2400. BaseX86MachineInfo::ComputeJccEa(int Opcode, BOOL EaOut)
  2401. {
  2402. if (!EaOut)
  2403. {
  2404. return JCC_EA_NONE;
  2405. }
  2406. ULONG Flags;
  2407. int Branch;
  2408. if ((Opcode >= 0x70 && Opcode <= 0x7f) ||
  2409. (Opcode >= 0x180 && Opcode <= 0x18f))
  2410. {
  2411. int Table = (Opcode >> 1) & 7;
  2412. Flags = GetReg32(X86_NFL);
  2413. Branch = Opcode & 1;
  2414. if ((Flags & g_JccCheckTable[Table][0]) != 0 ||
  2415. ((Flags >> g_JccCheckTable[Table][1]) & 1) !=
  2416. ((Flags >> g_JccCheckTable[Table][2]) & 1))
  2417. {
  2418. Branch ^= 1;
  2419. }
  2420. return JCC_EA_NO_BRANCH + Branch;
  2421. }
  2422. else
  2423. {
  2424. ULONG64 Cx = GetReg64(X86_NCX);
  2425. switch(g_OpSize)
  2426. {
  2427. case 16:
  2428. Cx &= 0xffff;
  2429. break;
  2430. case 32:
  2431. Cx &= 0xffffffff;
  2432. break;
  2433. }
  2434. switch(Opcode)
  2435. {
  2436. case 0xe0: // LOOPNE.
  2437. Flags = GetReg32(X86_NFL);
  2438. Branch = (Flags & X86_BIT_FLAGZF) == 0 && Cx != 1 ?
  2439. JCC_EA_BRANCH : JCC_EA_NO_BRANCH;
  2440. break;
  2441. case 0xe1: // LOOPE.
  2442. Flags = GetReg32(X86_NFL);
  2443. Branch = (Flags & X86_BIT_FLAGZF) != 0 && Cx != 1 ?
  2444. JCC_EA_BRANCH : JCC_EA_NO_BRANCH;
  2445. break;
  2446. case 0xe2: // LOOP.
  2447. Branch = Cx == 1 ? JCC_EA_NO_BRANCH : JCC_EA_BRANCH;
  2448. break;
  2449. case 0xe3: // J*CXZ.
  2450. Branch = Cx == 0 ? JCC_EA_BRANCH : JCC_EA_NO_BRANCH;
  2451. break;
  2452. default:
  2453. DBG_ASSERT(FALSE);
  2454. Branch = JCC_EA_NONE;
  2455. break;
  2456. }
  2457. return Branch;
  2458. }
  2459. }
  2460. BOOL
  2461. BaseX86MachineInfo::IsBreakpointInstruction(ProcessInfo* Process, PADDR Addr)
  2462. {
  2463. UCHAR Instr[X86_INT3_LEN];
  2464. if (fnotFlat(*Addr) ||
  2465. m_Target->ReadAllVirtual(Process, Flat(*Addr),
  2466. Instr, X86_INT3_LEN) != S_OK)
  2467. {
  2468. return FALSE;
  2469. }
  2470. return !memcmp(Instr, g_X86Int3, X86_INT3_LEN);
  2471. }
  2472. HRESULT
  2473. BaseX86MachineInfo::InsertBreakpointInstruction(PUSER_DEBUG_SERVICES Services,
  2474. ULONG64 Process,
  2475. ULONG64 Offset,
  2476. ULONG Flags,
  2477. PUCHAR SaveInstr,
  2478. PULONG64 ChangeStart,
  2479. PULONG ChangeLen)
  2480. {
  2481. if (Flags != IBI_DEFAULT)
  2482. {
  2483. return E_INVALIDARG;
  2484. }
  2485. if ((m_Target->m_MachineType != IMAGE_FILE_MACHINE_I386) &&
  2486. (g_Wow64exts != NULL))
  2487. {
  2488. ProcessInfo* ProcInfo = m_Target->FindProcessByHandle(Process);
  2489. if (ProcInfo != NULL)
  2490. {
  2491. (*g_Wow64exts)(WOW64EXTS_FLUSH_CACHE_WITH_HANDLE,
  2492. ProcInfo->m_SysHandle, Offset, X86_INT3_LEN);
  2493. }
  2494. }
  2495. *ChangeStart = Offset;
  2496. *ChangeLen = X86_INT3_LEN;
  2497. ULONG Done;
  2498. HRESULT Status;
  2499. Status = Services->ReadVirtual(Process, Offset, SaveInstr,
  2500. X86_INT3_LEN, &Done);
  2501. if (Status == S_OK && Done != X86_INT3_LEN)
  2502. {
  2503. Status = HRESULT_FROM_WIN32(ERROR_READ_FAULT);
  2504. }
  2505. if (Status == S_OK)
  2506. {
  2507. Status = Services->WriteVirtual(Process, Offset, g_X86Int3,
  2508. X86_INT3_LEN, &Done);
  2509. if (Status == S_OK && Done != X86_INT3_LEN)
  2510. {
  2511. Status = HRESULT_FROM_WIN32(ERROR_WRITE_FAULT);
  2512. }
  2513. }
  2514. return Status;
  2515. }
  2516. HRESULT
  2517. BaseX86MachineInfo::RemoveBreakpointInstruction(PUSER_DEBUG_SERVICES Services,
  2518. ULONG64 Process,
  2519. ULONG64 Offset,
  2520. PUCHAR SaveInstr,
  2521. PULONG64 ChangeStart,
  2522. PULONG ChangeLen)
  2523. {
  2524. if ((m_Target->m_MachineType != IMAGE_FILE_MACHINE_I386) &&
  2525. (g_Wow64exts != NULL))
  2526. {
  2527. ProcessInfo* ProcInfo = m_Target->FindProcessByHandle(Process);
  2528. if (ProcInfo != NULL)
  2529. {
  2530. (*g_Wow64exts)(WOW64EXTS_FLUSH_CACHE_WITH_HANDLE,
  2531. ProcInfo->m_SysHandle, Offset, X86_INT3_LEN);
  2532. }
  2533. }
  2534. *ChangeStart = Offset;
  2535. *ChangeLen = X86_INT3_LEN;
  2536. ULONG Done;
  2537. HRESULT Status;
  2538. Status = Services->WriteVirtual(Process, Offset, SaveInstr,
  2539. X86_INT3_LEN, &Done);
  2540. if (Status == S_OK && Done != X86_INT3_LEN)
  2541. {
  2542. Status = HRESULT_FROM_WIN32(ERROR_WRITE_FAULT);
  2543. }
  2544. return Status;
  2545. }
  2546. void
  2547. BaseX86MachineInfo::AdjustPCPastBreakpointInstruction(PADDR Addr,
  2548. ULONG BreakType)
  2549. {
  2550. if (BreakType == DEBUG_BREAKPOINT_CODE)
  2551. {
  2552. AddrAdd(Addr, X86_INT3_LEN);
  2553. SetPC(Addr);
  2554. }
  2555. }
  2556. BOOL
  2557. BaseX86MachineInfo::IsCallDisasm(PCSTR Disasm)
  2558. {
  2559. return strstr(Disasm, " call") != NULL;
  2560. }
  2561. BOOL
  2562. BaseX86MachineInfo::IsReturnDisasm(PCSTR Disasm)
  2563. {
  2564. return strstr(Disasm, " ret") != NULL ||
  2565. (IS_KERNEL_TARGET(m_Target) && strstr(Disasm, " iretd") != NULL);
  2566. }
  2567. BOOL
  2568. BaseX86MachineInfo::IsSystemCallDisasm(PCSTR Disasm)
  2569. {
  2570. return (strstr(Disasm, " int ") != NULL &&
  2571. strstr(Disasm, " 2e") != NULL) ||
  2572. strstr(Disasm, " sysenter") != NULL ||
  2573. strstr(Disasm, " syscall") != NULL;
  2574. }
  2575. BOOL
  2576. BaseX86MachineInfo::IsDelayInstruction(PADDR Addr)
  2577. {
  2578. // X86 does not have delay slots.
  2579. return FALSE;
  2580. }
  2581. void
  2582. BaseX86MachineInfo::GetEffectiveAddr(PADDR Addr, PULONG Size)
  2583. {
  2584. *Addr = EAaddr[0];
  2585. *Size = EAsize[0];
  2586. }
  2587. void
  2588. BaseX86MachineInfo::IncrementBySmallestInstruction(PADDR Addr)
  2589. {
  2590. AddrAdd(Addr, 1);
  2591. }
  2592. void
  2593. BaseX86MachineInfo::DecrementBySmallestInstruction(PADDR Addr)
  2594. {
  2595. AddrSub(Addr, 1);
  2596. }
  2597. //----------------------------------------------------------------------------
  2598. //
  2599. // X86MachineInfo methods.
  2600. //
  2601. //----------------------------------------------------------------------------
  2602. HRESULT
  2603. X86MachineInfo::NewBreakpoint(DebugClient* Client,
  2604. ULONG Type,
  2605. ULONG Id,
  2606. Breakpoint** RetBp)
  2607. {
  2608. HRESULT Status;
  2609. switch(Type & (DEBUG_BREAKPOINT_CODE | DEBUG_BREAKPOINT_DATA))
  2610. {
  2611. case DEBUG_BREAKPOINT_CODE:
  2612. *RetBp = new CodeBreakpoint(Client, Id, IMAGE_FILE_MACHINE_I386);
  2613. Status = (*RetBp) ? S_OK : E_OUTOFMEMORY;
  2614. break;
  2615. case DEBUG_BREAKPOINT_DATA:
  2616. *RetBp = new X86DataBreakpoint(Client, Id, X86_CR4, X86_DR6,
  2617. IMAGE_FILE_MACHINE_I386);
  2618. Status = (*RetBp) ? S_OK : E_OUTOFMEMORY;
  2619. break;
  2620. default:
  2621. // Unknown breakpoint type.
  2622. Status = E_NOINTERFACE;
  2623. }
  2624. return Status;
  2625. }
  2626. void
  2627. X86MachineInfo::InsertThreadDataBreakpoints(void)
  2628. {
  2629. ULONG Dr7Value;
  2630. BpOut("Thread %d data breaks %d\n",
  2631. g_Thread->m_UserId, g_Thread->m_NumDataBreaks);
  2632. // Start with all breaks turned off.
  2633. Dr7Value = GetIntReg(X86_DR7) & ~X86_DR7_CTRL_03_MASK;
  2634. if (g_Thread->m_NumDataBreaks > 0)
  2635. {
  2636. ULONG i;
  2637. for (i = 0; i < g_Thread->m_NumDataBreaks; i++)
  2638. {
  2639. X86DataBreakpoint* Bp =
  2640. (X86DataBreakpoint *)g_Thread->m_DataBreakBps[i];
  2641. ULONG64 Addr = Flat(*Bp->GetAddr());
  2642. BpOut(" dbp %d at %p\n", i, Addr);
  2643. if (g_DataBreakpointsChanged)
  2644. {
  2645. SetReg32(X86_DR0 + i, (ULONG)Addr);
  2646. }
  2647. // There are two enable bits per breakpoint
  2648. // and four len/rw bits so split up enables
  2649. // and len/rw when shifting into place.
  2650. Dr7Value |=
  2651. ((Bp->m_Dr7Bits & 0xffff0000) << (i * 4)) |
  2652. ((Bp->m_Dr7Bits & X86_DR7_ALL_ENABLES) << (i * 2));
  2653. }
  2654. // The kernel automatically clears DR6 when it
  2655. // processes a DBGKD_CONTROL_SET.
  2656. if (IS_USER_TARGET(m_Target))
  2657. {
  2658. SetReg32(X86_DR6, 0);
  2659. }
  2660. // Set local exact match, which is effectively global on NT.
  2661. Dr7Value |= X86_DR7_LOCAL_EXACT_ENABLE;
  2662. }
  2663. BpOut(" thread %d DR7 %X\n", g_Thread->m_UserId, Dr7Value);
  2664. SetReg32(X86_DR7, Dr7Value);
  2665. }
  2666. void
  2667. X86MachineInfo::RemoveThreadDataBreakpoints(void)
  2668. {
  2669. SetReg32(X86_DR7, 0);
  2670. }
  2671. ULONG
  2672. X86MachineInfo::IsBreakpointOrStepException(PEXCEPTION_RECORD64 Record,
  2673. ULONG FirstChance,
  2674. PADDR BpAddr,
  2675. PADDR RelAddr)
  2676. {
  2677. if (Record->ExceptionCode == STATUS_BREAKPOINT ||
  2678. Record->ExceptionCode == STATUS_WX86_BREAKPOINT)
  2679. {
  2680. // Data breakpoints hit as STATUS_SINGLE_STEP so
  2681. // this can only be a code breakpoint.
  2682. if (IS_USER_TARGET(m_Target) && FirstChance)
  2683. {
  2684. // Back up to the actual breakpoint instruction.
  2685. AddrSub(BpAddr, X86_INT3_LEN);
  2686. SetPC(BpAddr);
  2687. }
  2688. return EXBS_BREAKPOINT_CODE;
  2689. }
  2690. else if (Record->ExceptionCode == STATUS_SINGLE_STEP ||
  2691. Record->ExceptionCode == STATUS_WX86_SINGLE_STEP)
  2692. {
  2693. // XXX t-tcheng - Conversion for Dr6, Dr7 not implemented yet...
  2694. ULONG Dr6 = GetIntReg(X86_DR6);
  2695. ULONG Dr7 = GetIntReg(X86_DR7);
  2696. BpOut("X86 step: DR6 %X, DR7 %X\n", Dr6, Dr7);
  2697. // The single step bit should always be clear if a data breakpoint
  2698. // is hit but also check the DR7 enables just in case.
  2699. // We've also seen cases where DR6 shows no hits, so consider
  2700. // that a single step also.
  2701. if ((Dr6 & X86_DR6_SINGLE_STEP) || (Dr7 & X86_DR7_ALL_ENABLES) == 0 ||
  2702. (Dr6 & X86_DR6_BREAK_03) == 0)
  2703. {
  2704. // There's no way to tell if this particular
  2705. // step was a branch step or not so only
  2706. // try to look up the branch source if we're
  2707. // in branch-trace mode.
  2708. if (m_SupportsBranchTrace &&
  2709. g_CmdState == 'b')
  2710. {
  2711. HRESULT Status;
  2712. ULONG64 LastIp;
  2713. // The Pentium IV handles last-branch tracking
  2714. // differently from the P6.
  2715. if (m_Target->m_FirstProcessorId.X86.Family >= 15)
  2716. {
  2717. ULONG64 LbrTos;
  2718. Status = m_Target->ReadMsr(X86_MSR_LAST_BRANCH_TOS,
  2719. &LbrTos);
  2720. if (Status == S_OK)
  2721. {
  2722. Status = m_Target->ReadMsr(X86_MSR_LAST_BRANCH_0 +
  2723. (ULONG)LbrTos,
  2724. &LastIp);
  2725. // The result is a 64-bit value with the
  2726. // from address in the upper 32-bits.
  2727. LastIp >>= 32;
  2728. }
  2729. }
  2730. else
  2731. {
  2732. Status = m_Target->ReadMsr(X86_MSR_LAST_BRANCH_FROM_IP,
  2733. &LastIp);
  2734. }
  2735. if (Status == S_OK)
  2736. {
  2737. // The branch may have come from a different
  2738. // segment. We could try and determine what
  2739. // code segment it was by reading the stack to
  2740. // get the saved CS value but it's not worth
  2741. // it right now.
  2742. FormAddr(SEGREG_CODE, EXTEND64(LastIp),
  2743. FORM_CODE | FORM_SEGREG |
  2744. X86_FORM_VM86(GetIntReg(X86_EFL)),
  2745. RelAddr);
  2746. }
  2747. }
  2748. // This is a true single step exception, not
  2749. // a data breakpoint.
  2750. return EXBS_STEP_INSTRUCTION;
  2751. }
  2752. else
  2753. {
  2754. // Some data breakpoint must be hit.
  2755. // There doesn't appear to be any way to get the
  2756. // faulting instruction address so just leave the PC.
  2757. return EXBS_BREAKPOINT_DATA;
  2758. }
  2759. }
  2760. return EXBS_NONE;
  2761. }
  2762. void
  2763. X86MachineInfo::PrintStackFrameAddressesTitle(ULONG Flags)
  2764. {
  2765. PrintMultiPtrTitle("ChildEBP", 1);
  2766. PrintMultiPtrTitle("RetAddr", 1);
  2767. }
  2768. void
  2769. X86MachineInfo::PrintStackFrameAddresses(ULONG Flags,
  2770. PDEBUG_STACK_FRAME StackFrame)
  2771. {
  2772. dprintf("%s %s ",
  2773. FormatAddr64(StackFrame->FrameOffset),
  2774. FormatAddr64(StackFrame->ReturnOffset));
  2775. }
  2776. void
  2777. X86MachineInfo::PrintStackArgumentsTitle(ULONG Flags)
  2778. {
  2779. PrintMultiPtrTitle("Args to Child", 3);
  2780. }
  2781. void
  2782. X86MachineInfo::PrintStackArguments(ULONG Flags,
  2783. PDEBUG_STACK_FRAME StackFrame)
  2784. {
  2785. dprintf("%s %s %s ",
  2786. FormatAddr64(StackFrame->Params[0]),
  2787. FormatAddr64(StackFrame->Params[1]),
  2788. FormatAddr64(StackFrame->Params[2]));
  2789. }
  2790. void
  2791. X86MachineInfo::PrintStackCallSiteTitle(ULONG Flags)
  2792. {
  2793. }
  2794. void
  2795. X86MachineInfo::PrintStackCallSite(ULONG Flags,
  2796. PDEBUG_STACK_FRAME StackFrame,
  2797. PSYMBOL_INFO SiteSymbol,
  2798. PSTR SymName,
  2799. DWORD64 Displacement)
  2800. {
  2801. // Truncate the displacement to 32 bits since it can never be
  2802. // greater than 32 bit for X86, and we don't want addresses with no
  2803. // symbols to show up with the leading 0xfffffff
  2804. MachineInfo::PrintStackCallSite(Flags, StackFrame, SiteSymbol, SymName,
  2805. (DWORD64)(DWORD)Displacement);
  2806. if (!(Flags & DEBUG_STACK_FUNCTION_INFO))
  2807. {
  2808. return;
  2809. }
  2810. if (StackFrame->FuncTableEntry)
  2811. {
  2812. PFPO_DATA FpoData = (PFPO_DATA)StackFrame->FuncTableEntry;
  2813. switch(FpoData->cbFrame)
  2814. {
  2815. case FRAME_FPO:
  2816. if (FpoData->fHasSEH)
  2817. {
  2818. dprintf(" (FPO: [SEH])");
  2819. }
  2820. else
  2821. {
  2822. dprintf(" (FPO:");
  2823. if (FpoData->fUseBP)
  2824. {
  2825. dprintf(" [EBP 0x%s]",
  2826. FormatAddr64(SAVE_EBP(StackFrame)));
  2827. }
  2828. dprintf(" [%d,%d,%d])",
  2829. FpoData->cdwParams,
  2830. FpoData->cdwLocals,
  2831. FpoData->cbRegs);
  2832. }
  2833. break;
  2834. case FRAME_NONFPO:
  2835. dprintf(" (FPO: [Non-Fpo])" );
  2836. break;
  2837. case FRAME_TRAP:
  2838. if (!IS_KERNEL_TARGET(m_Target))
  2839. {
  2840. goto UnknownFpo;
  2841. }
  2842. dprintf(" (FPO: [%d,%d] TrapFrame%s @ %s)",
  2843. FpoData->cdwParams,
  2844. FpoData->cdwLocals,
  2845. TRAP_EDITED(StackFrame) ? "" : "-EDITED",
  2846. FormatAddr64(SAVE_TRAP(StackFrame)));
  2847. break;
  2848. case FRAME_TSS:
  2849. if (!IS_KERNEL_TARGET(m_Target))
  2850. {
  2851. goto UnknownFpo;
  2852. }
  2853. dprintf(" (FPO: TaskGate %lx:0)",
  2854. (ULONG)TRAP_TSS(StackFrame));
  2855. break;
  2856. default:
  2857. UnknownFpo:
  2858. dprintf(" (UNKNOWN FPO TYPE)");
  2859. break;
  2860. }
  2861. }
  2862. if (SiteSymbol->Tag == SymTagFunction)
  2863. {
  2864. ULONG CallConv;
  2865. // Look up the type symbol for the function.
  2866. if (SymGetTypeInfo(g_Process->m_SymHandle,
  2867. SiteSymbol->ModBase,
  2868. SiteSymbol->TypeIndex,
  2869. TI_GET_CALLING_CONVENTION,
  2870. &CallConv) &&
  2871. CallConv < CV_CALL_RESERVED)
  2872. {
  2873. dprintf(" (CONV: %s)", g_CallConv[CallConv]);
  2874. }
  2875. }
  2876. }
  2877. void
  2878. X86MachineInfo::PrintStackFrameMemoryUsage(PDEBUG_STACK_FRAME CurFrame,
  2879. PDEBUG_STACK_FRAME PrevFrame)
  2880. {
  2881. if (CurFrame->FrameOffset >= PrevFrame->FrameOffset)
  2882. {
  2883. dprintf(" %6x ",
  2884. (ULONG)(CurFrame->FrameOffset - PrevFrame->FrameOffset));
  2885. }
  2886. else
  2887. {
  2888. dprintf(" ");
  2889. }
  2890. }