Source code of Windows XP (NT5)
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.

3158 lines
91 KiB

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