be_i386.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  1. /*
  2. * Debugger i386 specific functions
  3. *
  4. * Copyright 2004 Eric Pouech
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #include "debugger.h"
  21. #include "wine/debug.h"
  22. #if defined(__i386__) || defined(__x86_64__)
  23. WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
  24. /* db_disasm.c */
  25. extern void be_i386_disasm_one_insn(ADDRESS64* addr, int display);
  26. #define STEP_FLAG 0x00000100 /* single step flag */
  27. #define V86_FLAG 0x00020000
  28. #define IS_VM86_MODE(ctx) (ctx->EFlags & V86_FLAG)
  29. static ADDRESS_MODE get_selector_type(HANDLE hThread, const WOW64_CONTEXT *ctx, WORD sel)
  30. {
  31. LDT_ENTRY le;
  32. if (IS_VM86_MODE(ctx)) return AddrModeReal;
  33. /* null or system selector */
  34. if (!(sel & 4) || ((sel >> 3) < 17)) return AddrModeFlat;
  35. if (dbg_curr_process->process_io->get_selector(hThread, sel, &le))
  36. return le.HighWord.Bits.Default_Big ? AddrMode1632 : AddrMode1616;
  37. /* selector doesn't exist */
  38. return -1;
  39. }
  40. static void* be_i386_linearize(HANDLE hThread, const ADDRESS64* addr)
  41. {
  42. LDT_ENTRY le;
  43. switch (addr->Mode)
  44. {
  45. case AddrModeReal:
  46. return (void*)((DWORD_PTR)(LOWORD(addr->Segment) << 4) + (DWORD_PTR)addr->Offset);
  47. case AddrMode1632:
  48. if (!(addr->Segment & 4) || ((addr->Segment >> 3) < 17))
  49. return (void*)(DWORD_PTR)addr->Offset;
  50. /* fall through */
  51. case AddrMode1616:
  52. if (!dbg_curr_process->process_io->get_selector(hThread, addr->Segment, &le)) return NULL;
  53. return (void*)((le.HighWord.Bits.BaseHi << 24) +
  54. (le.HighWord.Bits.BaseMid << 16) + le.BaseLow +
  55. (DWORD_PTR)addr->Offset);
  56. case AddrModeFlat:
  57. return (void*)(DWORD_PTR)addr->Offset;
  58. }
  59. return NULL;
  60. }
  61. static BOOL be_i386_build_addr(HANDLE hThread, const dbg_ctx_t *ctx, ADDRESS64* addr,
  62. unsigned seg, unsigned long offset)
  63. {
  64. addr->Mode = AddrModeFlat;
  65. addr->Segment = seg;
  66. addr->Offset = offset;
  67. if (seg)
  68. {
  69. addr->Mode = get_selector_type(hThread, &ctx->x86, seg);
  70. switch (addr->Mode)
  71. {
  72. case AddrModeReal:
  73. case AddrMode1616:
  74. addr->Offset &= 0xffff;
  75. break;
  76. case AddrModeFlat:
  77. case AddrMode1632:
  78. break;
  79. default:
  80. addr->Mode = -1;
  81. return FALSE;
  82. }
  83. }
  84. return TRUE;
  85. }
  86. static BOOL be_i386_get_addr(HANDLE hThread, const dbg_ctx_t *ctx,
  87. enum be_cpu_addr bca, ADDRESS64* addr)
  88. {
  89. switch (bca)
  90. {
  91. case be_cpu_addr_pc:
  92. return be_i386_build_addr(hThread, ctx, addr, ctx->x86.SegCs, ctx->x86.Eip);
  93. case be_cpu_addr_stack:
  94. return be_i386_build_addr(hThread, ctx, addr, ctx->x86.SegSs, ctx->x86.Esp);
  95. case be_cpu_addr_frame:
  96. return be_i386_build_addr(hThread, ctx, addr, ctx->x86.SegSs, ctx->x86.Ebp);
  97. }
  98. return FALSE;
  99. }
  100. static BOOL be_i386_get_register_info(int regno, enum be_cpu_addr* kind)
  101. {
  102. switch (regno)
  103. {
  104. case CV_REG_EIP: *kind = be_cpu_addr_pc; return TRUE;
  105. case CV_REG_EBP: *kind = be_cpu_addr_frame; return TRUE;
  106. case CV_REG_ESP: *kind = be_cpu_addr_stack; return TRUE;
  107. }
  108. return FALSE;
  109. }
  110. static void be_i386_single_step(dbg_ctx_t *ctx, BOOL enable)
  111. {
  112. if (enable) ctx->x86.EFlags |= STEP_FLAG;
  113. else ctx->x86.EFlags &= ~STEP_FLAG;
  114. }
  115. static void be_i386_all_print_context(HANDLE hThread, const dbg_ctx_t *pctx)
  116. {
  117. static const char mxcsr_flags[16][4] = { "IE", "DE", "ZE", "OE", "UE", "PE", "DAZ", "IM",
  118. "DM", "ZM", "OM", "UM", "PM", "R-", "R+", "FZ" };
  119. const WOW64_CONTEXT *ctx = &pctx->x86;
  120. XSAVE_FORMAT *xmm_area;
  121. long double ST[8]; /* These are for floating regs */
  122. int cnt;
  123. /* Break out the FPU state and the floating point registers */
  124. dbg_printf("Floating Point Unit status:\n");
  125. dbg_printf(" FLCW:%04x ", LOWORD(ctx->FloatSave.ControlWord));
  126. dbg_printf(" FLTW:%04x ", LOWORD(ctx->FloatSave.TagWord));
  127. dbg_printf(" FLEO:%08x ", (unsigned int) ctx->FloatSave.ErrorOffset);
  128. dbg_printf(" FLSW:%04x", LOWORD(ctx->FloatSave.StatusWord));
  129. /* Isolate the condition code bits - note they are not contiguous */
  130. dbg_printf("(CC:%d%d%d%d", (ctx->FloatSave.StatusWord & 0x00004000) >> 14,
  131. (ctx->FloatSave.StatusWord & 0x00000400) >> 10,
  132. (ctx->FloatSave.StatusWord & 0x00000200) >> 9,
  133. (ctx->FloatSave.StatusWord & 0x00000100) >> 8);
  134. /* Now pull out the 3 bit of the TOP stack pointer */
  135. dbg_printf(" TOP:%01x", (unsigned int) (ctx->FloatSave.StatusWord & 0x00003800) >> 11);
  136. /* Lets analyse the error bits and indicate the status
  137. * the Invalid Op flag has sub status which is tested as follows */
  138. if (ctx->FloatSave.StatusWord & 0x00000001) { /* Invalid Fl OP */
  139. if (ctx->FloatSave.StatusWord & 0x00000040) { /* Stack Fault */
  140. if (ctx->FloatSave.StatusWord & 0x00000200) /* C1 says Overflow */
  141. dbg_printf(" #IE(Stack Overflow)");
  142. else
  143. dbg_printf(" #IE(Stack Underflow)"); /* Underflow */
  144. }
  145. else dbg_printf(" #IE(Arthimetic error)"); /* Invalid Fl OP */
  146. }
  147. if (ctx->FloatSave.StatusWord & 0x00000002) dbg_printf(" #DE"); /* Denormalised OP */
  148. if (ctx->FloatSave.StatusWord & 0x00000004) dbg_printf(" #ZE"); /* Zero Divide */
  149. if (ctx->FloatSave.StatusWord & 0x00000008) dbg_printf(" #OE"); /* Overflow */
  150. if (ctx->FloatSave.StatusWord & 0x00000010) dbg_printf(" #UE"); /* Underflow */
  151. if (ctx->FloatSave.StatusWord & 0x00000020) dbg_printf(" #PE"); /* Precision error */
  152. if (ctx->FloatSave.StatusWord & 0x00000040)
  153. if (!(ctx->FloatSave.StatusWord & 0x00000001))
  154. dbg_printf(" #SE"); /* Stack Fault (don't think this can occur) */
  155. if (ctx->FloatSave.StatusWord & 0x00000080) dbg_printf(" #ES"); /* Error Summary */
  156. if (ctx->FloatSave.StatusWord & 0x00008000) dbg_printf(" #FB"); /* FPU Busy */
  157. dbg_printf(")\n");
  158. /* Here are the rest of the registers */
  159. dbg_printf(" FLES:%08x FLDO:%08x FLDS:%08x FLCNS:%08x\n",
  160. ctx->FloatSave.ErrorSelector,
  161. ctx->FloatSave.DataOffset,
  162. ctx->FloatSave.DataSelector,
  163. ctx->FloatSave.Cr0NpxState);
  164. /* Now for the floating point registers */
  165. dbg_printf("Floating Point Registers:\n");
  166. for (cnt = 0; cnt < 4; cnt++)
  167. {
  168. memcpy(&ST[cnt], &ctx->FloatSave.RegisterArea[cnt * 10], 10);
  169. dbg_printf(" ST%d:%Lf ", cnt, ST[cnt]);
  170. }
  171. dbg_printf("\n");
  172. for (cnt = 4; cnt < 8; cnt++)
  173. {
  174. memcpy(&ST[cnt], &ctx->FloatSave.RegisterArea[cnt * 10], 10);
  175. dbg_printf(" ST%d:%Lf ", cnt, ST[cnt]);
  176. }
  177. xmm_area = (XSAVE_FORMAT *) &ctx->ExtendedRegisters;
  178. dbg_printf(" mxcsr: %04x (", xmm_area->MxCsr );
  179. for (cnt = 0; cnt < 16; cnt++)
  180. if (xmm_area->MxCsr & (1 << cnt)) dbg_printf( " %s", mxcsr_flags[cnt] );
  181. dbg_printf(" )\n");
  182. for (cnt = 0; cnt < 8; cnt++)
  183. {
  184. dbg_printf( " xmm%u: uint=%08x%08x%08x%08x", cnt,
  185. *((unsigned int *)&xmm_area->XmmRegisters[cnt] + 3),
  186. *((unsigned int *)&xmm_area->XmmRegisters[cnt] + 2),
  187. *((unsigned int *)&xmm_area->XmmRegisters[cnt] + 1),
  188. *((unsigned int *)&xmm_area->XmmRegisters[cnt] + 0));
  189. dbg_printf( " double={%g; %g}", *(double *)&xmm_area->XmmRegisters[cnt].Low,
  190. *(double *)&xmm_area->XmmRegisters[cnt].High );
  191. dbg_printf( " float={%g; %g; %g; %g}\n",
  192. (double)*((float *)&xmm_area->XmmRegisters[cnt] + 0),
  193. (double)*((float *)&xmm_area->XmmRegisters[cnt] + 1),
  194. (double)*((float *)&xmm_area->XmmRegisters[cnt] + 2),
  195. (double)*((float *)&xmm_area->XmmRegisters[cnt] + 3) );
  196. }
  197. dbg_printf("\n");
  198. }
  199. static void be_i386_print_context(HANDLE hThread, const dbg_ctx_t *pctx, int all_regs)
  200. {
  201. static const char flags[] = "aVR-N--ODITSZ-A-P-C";
  202. const WOW64_CONTEXT *ctx = &pctx->x86;
  203. int i;
  204. char buf[33];
  205. dbg_printf("Register dump:\n");
  206. /* First get the segment registers out of the way */
  207. dbg_printf(" CS:%04x SS:%04x DS:%04x ES:%04x FS:%04x GS:%04x",
  208. (WORD)ctx->SegCs, (WORD)ctx->SegSs,
  209. (WORD)ctx->SegDs, (WORD)ctx->SegEs,
  210. (WORD)ctx->SegFs, (WORD)ctx->SegGs);
  211. strcpy(buf, flags);
  212. for (i = 0; buf[i]; i++)
  213. if (buf[i] != '-' && !(ctx->EFlags & (1 << (sizeof(flags) - 2 - i))))
  214. buf[i] = ' ';
  215. switch (get_selector_type(hThread, ctx, ctx->SegCs))
  216. {
  217. case AddrMode1616:
  218. case AddrModeReal:
  219. dbg_printf("\n IP:%04x SP:%04x BP:%04x FLAGS:%04x(%s)\n",
  220. LOWORD(ctx->Eip), LOWORD(ctx->Esp),
  221. LOWORD(ctx->Ebp), LOWORD(ctx->EFlags), buf);
  222. dbg_printf(" AX:%04x BX:%04x CX:%04x DX:%04x SI:%04x DI:%04x\n",
  223. LOWORD(ctx->Eax), LOWORD(ctx->Ebx),
  224. LOWORD(ctx->Ecx), LOWORD(ctx->Edx),
  225. LOWORD(ctx->Esi), LOWORD(ctx->Edi));
  226. break;
  227. case AddrModeFlat:
  228. case AddrMode1632:
  229. dbg_printf("\n EIP:%08x ESP:%08x EBP:%08x EFLAGS:%08x(%s)\n",
  230. ctx->Eip, ctx->Esp, ctx->Ebp, ctx->EFlags, buf);
  231. dbg_printf(" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n",
  232. ctx->Eax, ctx->Ebx, ctx->Ecx, ctx->Edx);
  233. dbg_printf(" ESI:%08x EDI:%08x\n",
  234. ctx->Esi, ctx->Edi);
  235. break;
  236. }
  237. if (all_regs) be_i386_all_print_context(hThread, pctx);
  238. }
  239. static void be_i386_print_segment_info(HANDLE hThread, const dbg_ctx_t *ctx)
  240. {
  241. if (get_selector_type(hThread, &ctx->x86, ctx->x86.SegCs) == AddrMode1616)
  242. {
  243. info_win32_segments(ctx->x86.SegDs >> 3, 1);
  244. if (ctx->x86.SegEs != ctx->x86.SegDs)
  245. info_win32_segments(ctx->x86.SegEs >> 3, 1);
  246. }
  247. info_win32_segments(ctx->x86.SegFs >> 3, 1);
  248. }
  249. static struct dbg_internal_var be_i386_ctx[] =
  250. {
  251. {CV_REG_AL, "AL", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Eax), dbg_itype_unsigned_char_int},
  252. {CV_REG_CL, "CL", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Ecx), dbg_itype_unsigned_char_int},
  253. {CV_REG_DL, "DL", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Edx), dbg_itype_unsigned_char_int},
  254. {CV_REG_BL, "BL", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Ebx), dbg_itype_unsigned_char_int},
  255. {CV_REG_AH, "AH", (DWORD_PTR*)(FIELD_OFFSET(WOW64_CONTEXT, Eax)+1), dbg_itype_unsigned_char_int},
  256. {CV_REG_CH, "CH", (DWORD_PTR*)(FIELD_OFFSET(WOW64_CONTEXT, Ecx)+1), dbg_itype_unsigned_char_int},
  257. {CV_REG_DH, "DH", (DWORD_PTR*)(FIELD_OFFSET(WOW64_CONTEXT, Edx)+1), dbg_itype_unsigned_char_int},
  258. {CV_REG_BH, "BH", (DWORD_PTR*)(FIELD_OFFSET(WOW64_CONTEXT, Ebx)+1), dbg_itype_unsigned_char_int},
  259. {CV_REG_AX, "AX", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Eax), dbg_itype_unsigned_short_int},
  260. {CV_REG_CX, "CX", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Ecx), dbg_itype_unsigned_short_int},
  261. {CV_REG_DX, "DX", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Edx), dbg_itype_unsigned_short_int},
  262. {CV_REG_BX, "BX", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Ebx), dbg_itype_unsigned_short_int},
  263. {CV_REG_SP, "SP", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Esp), dbg_itype_unsigned_short_int},
  264. {CV_REG_BP, "BP", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Ebp), dbg_itype_unsigned_short_int},
  265. {CV_REG_SI, "SI", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Esi), dbg_itype_unsigned_short_int},
  266. {CV_REG_DI, "DI", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Edi), dbg_itype_unsigned_short_int},
  267. {CV_REG_EAX, "EAX", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Eax), dbg_itype_unsigned_int},
  268. {CV_REG_ECX, "ECX", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Ecx), dbg_itype_unsigned_int},
  269. {CV_REG_EDX, "EDX", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Edx), dbg_itype_unsigned_int},
  270. {CV_REG_EBX, "EBX", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Ebx), dbg_itype_unsigned_int},
  271. {CV_REG_ESP, "ESP", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Esp), dbg_itype_unsigned_int},
  272. {CV_REG_EBP, "EBP", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Ebp), dbg_itype_unsigned_int},
  273. {CV_REG_ESI, "ESI", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Esi), dbg_itype_unsigned_int},
  274. {CV_REG_EDI, "EDI", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Edi), dbg_itype_unsigned_int},
  275. {CV_REG_ES, "ES", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, SegEs), dbg_itype_unsigned_short_int},
  276. {CV_REG_CS, "CS", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, SegCs), dbg_itype_unsigned_short_int},
  277. {CV_REG_SS, "SS", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, SegSs), dbg_itype_unsigned_short_int},
  278. {CV_REG_DS, "DS", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, SegDs), dbg_itype_unsigned_short_int},
  279. {CV_REG_FS, "FS", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, SegFs), dbg_itype_unsigned_short_int},
  280. {CV_REG_GS, "GS", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, SegGs), dbg_itype_unsigned_short_int},
  281. {CV_REG_IP, "IP", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Eip), dbg_itype_unsigned_short_int},
  282. {CV_REG_FLAGS, "FLAGS", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, EFlags), dbg_itype_unsigned_short_int},
  283. {CV_REG_EIP, "EIP", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, Eip), dbg_itype_unsigned_int},
  284. {CV_REG_EFLAGS, "EFLAGS", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, EFlags), dbg_itype_unsigned_int},
  285. {CV_REG_ST0, "ST0", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[ 0]), dbg_itype_long_real},
  286. {CV_REG_ST0+1, "ST1", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[10]), dbg_itype_long_real},
  287. {CV_REG_ST0+2, "ST2", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[20]), dbg_itype_long_real},
  288. {CV_REG_ST0+3, "ST3", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[30]), dbg_itype_long_real},
  289. {CV_REG_ST0+4, "ST4", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[40]), dbg_itype_long_real},
  290. {CV_REG_ST0+5, "ST5", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[50]), dbg_itype_long_real},
  291. {CV_REG_ST0+6, "ST6", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[60]), dbg_itype_long_real},
  292. {CV_REG_ST0+7, "ST7", (DWORD_PTR*)FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[70]), dbg_itype_long_real},
  293. {CV_AMD64_XMM0, "XMM0", (DWORD_PTR*)(FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[0])), dbg_itype_m128a},
  294. {CV_AMD64_XMM0+1, "XMM1", (DWORD_PTR*)(FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[1])), dbg_itype_m128a},
  295. {CV_AMD64_XMM0+2, "XMM2", (DWORD_PTR*)(FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[2])), dbg_itype_m128a},
  296. {CV_AMD64_XMM0+3, "XMM3", (DWORD_PTR*)(FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[3])), dbg_itype_m128a},
  297. {CV_AMD64_XMM0+4, "XMM4", (DWORD_PTR*)(FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[4])), dbg_itype_m128a},
  298. {CV_AMD64_XMM0+5, "XMM5", (DWORD_PTR*)(FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[5])), dbg_itype_m128a},
  299. {CV_AMD64_XMM0+6, "XMM6", (DWORD_PTR*)(FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[6])), dbg_itype_m128a},
  300. {CV_AMD64_XMM0+7, "XMM7", (DWORD_PTR*)(FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[7])), dbg_itype_m128a},
  301. {0, NULL, 0, dbg_itype_none}
  302. };
  303. static BOOL be_i386_is_step_over_insn(const void* insn)
  304. {
  305. BYTE ch;
  306. for (;;)
  307. {
  308. if (!dbg_read_memory(insn, &ch, sizeof(ch))) return FALSE;
  309. switch (ch)
  310. {
  311. /* Skip all prefixes */
  312. case 0x2e: /* cs: */
  313. case 0x36: /* ss: */
  314. case 0x3e: /* ds: */
  315. case 0x26: /* es: */
  316. case 0x64: /* fs: */
  317. case 0x65: /* gs: */
  318. case 0x66: /* opcode size prefix */
  319. case 0x67: /* addr size prefix */
  320. case 0xf0: /* lock */
  321. case 0xf2: /* repne */
  322. case 0xf3: /* repe */
  323. insn = (const char*)insn + 1;
  324. continue;
  325. /* Handle call instructions */
  326. case 0xcd: /* int <intno> */
  327. case 0xe8: /* call <offset> */
  328. case 0x9a: /* lcall <seg>:<off> */
  329. return TRUE;
  330. case 0xff: /* call <regmodrm> */
  331. if (!dbg_read_memory((const char*)insn + 1, &ch, sizeof(ch)))
  332. return FALSE;
  333. return (((ch & 0x38) == 0x10) || ((ch & 0x38) == 0x18));
  334. /* Handle string instructions */
  335. case 0x6c: /* insb */
  336. case 0x6d: /* insw */
  337. case 0x6e: /* outsb */
  338. case 0x6f: /* outsw */
  339. case 0xa4: /* movsb */
  340. case 0xa5: /* movsw */
  341. case 0xa6: /* cmpsb */
  342. case 0xa7: /* cmpsw */
  343. case 0xaa: /* stosb */
  344. case 0xab: /* stosw */
  345. case 0xac: /* lodsb */
  346. case 0xad: /* lodsw */
  347. case 0xae: /* scasb */
  348. case 0xaf: /* scasw */
  349. return TRUE;
  350. default:
  351. return FALSE;
  352. }
  353. }
  354. }
  355. static BOOL be_i386_is_function_return(const void* insn)
  356. {
  357. BYTE ch;
  358. if (!dbg_read_memory(insn, &ch, sizeof(ch))) return FALSE;
  359. if (ch == 0xF3) /* REP */
  360. {
  361. insn = (const char*)insn + 1;
  362. if (!dbg_read_memory(insn, &ch, sizeof(ch))) return FALSE;
  363. }
  364. return (ch == 0xC2) || (ch == 0xC3);
  365. }
  366. static BOOL be_i386_is_break_insn(const void* insn)
  367. {
  368. BYTE c;
  369. if (!dbg_read_memory(insn, &c, sizeof(c))) return FALSE;
  370. return c == 0xCC;
  371. }
  372. static unsigned get_size(ADDRESS_MODE am)
  373. {
  374. if (am == AddrModeReal || am == AddrMode1616) return 16;
  375. return 32;
  376. }
  377. static BOOL fetch_value(const char* addr, unsigned sz, int* value)
  378. {
  379. char value8;
  380. short value16;
  381. switch (sz)
  382. {
  383. case 8:
  384. if (!dbg_read_memory(addr, &value8, sizeof(value8)))
  385. return FALSE;
  386. *value = value8;
  387. break;
  388. case 16:
  389. if (!dbg_read_memory(addr, &value16, sizeof(value16)))
  390. return FALSE;
  391. *value = value16;
  392. break;
  393. case 32:
  394. if (!dbg_read_memory(addr, value, sizeof(*value)))
  395. return FALSE;
  396. break;
  397. default: return FALSE;
  398. }
  399. return TRUE;
  400. }
  401. static BOOL be_i386_is_func_call(const void* insn, ADDRESS64* callee)
  402. {
  403. BYTE ch;
  404. int delta;
  405. short segment;
  406. unsigned dst = 0;
  407. unsigned operand_size;
  408. ADDRESS_MODE cs_addr_mode;
  409. cs_addr_mode = get_selector_type(dbg_curr_thread->handle, &dbg_context.x86,
  410. dbg_context.x86.SegCs);
  411. operand_size = get_size(cs_addr_mode);
  412. /* get operand_size (also getting rid of the various prefixes */
  413. do
  414. {
  415. if (!dbg_read_memory(insn, &ch, sizeof(ch))) return FALSE;
  416. if (ch == 0x66)
  417. {
  418. operand_size = 48 - operand_size; /* 16 => 32, 32 => 16 */
  419. insn = (const char*)insn + 1;
  420. }
  421. } while (ch == 0x66 || ch == 0x67);
  422. switch (ch)
  423. {
  424. case 0xe8: /* relative near call */
  425. callee->Mode = cs_addr_mode;
  426. if (!fetch_value((const char*)insn + 1, operand_size, &delta))
  427. return FALSE;
  428. callee->Segment = dbg_context.x86.SegCs;
  429. callee->Offset = (DWORD_PTR)insn + 1 + (operand_size / 8) + delta;
  430. return TRUE;
  431. case 0x9a: /* absolute far call */
  432. if (!dbg_read_memory((const char*)insn + 1 + operand_size / 8,
  433. &segment, sizeof(segment)))
  434. return FALSE;
  435. callee->Mode = get_selector_type(dbg_curr_thread->handle, &dbg_context.x86,
  436. segment);
  437. if (!fetch_value((const char*)insn + 1, operand_size, &delta))
  438. return FALSE;
  439. callee->Segment = segment;
  440. callee->Offset = delta;
  441. return TRUE;
  442. case 0xff:
  443. if (!dbg_read_memory((const char*)insn + 1, &ch, sizeof(ch)))
  444. return FALSE;
  445. /* keep only the CALL and LCALL insn:s */
  446. switch ((ch >> 3) & 0x07)
  447. {
  448. case 0x02:
  449. segment = dbg_context.x86.SegCs;
  450. break;
  451. case 0x03:
  452. if (!dbg_read_memory((const char*)insn + 1 + operand_size / 8,
  453. &segment, sizeof(segment)))
  454. return FALSE;
  455. break;
  456. default: return FALSE;
  457. }
  458. /* FIXME: we only support the 32 bit far calls for now */
  459. if (operand_size != 32)
  460. {
  461. WINE_FIXME("Unsupported yet call insn (0xFF 0x%02x) with 16 bit operand-size at %p\n", ch, insn);
  462. return FALSE;
  463. }
  464. switch (ch & 0xC7) /* keep Mod R/M only (skip reg) */
  465. {
  466. case 0x04:
  467. case 0x44:
  468. case 0x84:
  469. WINE_FIXME("Unsupported yet call insn (0xFF 0x%02x) (SIB bytes) at %p\n", ch, insn);
  470. return FALSE;
  471. case 0x05: /* addr32 */
  472. if ((ch & 0x38) == 0x10 || /* call */
  473. (ch & 0x38) == 0x18) /* lcall */
  474. {
  475. void *addr;
  476. if (!dbg_read_memory((const char *)insn + 2, &addr, sizeof(addr)))
  477. return FALSE;
  478. if ((ch & 0x38) == 0x18) /* lcall */
  479. {
  480. if (!dbg_read_memory((const char*)addr + operand_size, &segment, sizeof(segment)))
  481. return FALSE;
  482. }
  483. else segment = dbg_context.x86.SegCs;
  484. if (!dbg_read_memory((const char*)addr, &dst, sizeof(dst)))
  485. return FALSE;
  486. callee->Mode = get_selector_type(dbg_curr_thread->handle, &dbg_context.x86, segment);
  487. callee->Segment = segment;
  488. callee->Offset = dst;
  489. return TRUE;
  490. }
  491. return FALSE;
  492. default:
  493. switch (ch & 0x07)
  494. {
  495. case 0x00: dst = dbg_context.x86.Eax; break;
  496. case 0x01: dst = dbg_context.x86.Ecx; break;
  497. case 0x02: dst = dbg_context.x86.Edx; break;
  498. case 0x03: dst = dbg_context.x86.Ebx; break;
  499. case 0x04: dst = dbg_context.x86.Esp; break;
  500. case 0x05: dst = dbg_context.x86.Ebp; break;
  501. case 0x06: dst = dbg_context.x86.Esi; break;
  502. case 0x07: dst = dbg_context.x86.Edi; break;
  503. }
  504. if ((ch >> 6) != 0x03) /* indirect address */
  505. {
  506. if (ch >> 6) /* we got a displacement */
  507. {
  508. if (!fetch_value((const char*)insn + 2, (ch >> 6) == 0x01 ? 8 : 32, &delta))
  509. return FALSE;
  510. dst += delta;
  511. }
  512. if (((ch >> 3) & 0x07) == 0x03) /* LCALL */
  513. {
  514. if (!dbg_read_memory((const char*)(UINT_PTR)dst + operand_size, &segment, sizeof(segment)))
  515. return FALSE;
  516. }
  517. else segment = dbg_context.x86.SegCs;
  518. if (!dbg_read_memory((const char*)(UINT_PTR)dst, &delta, sizeof(delta)))
  519. return FALSE;
  520. callee->Mode = get_selector_type(dbg_curr_thread->handle, &dbg_context.x86,
  521. segment);
  522. callee->Segment = segment;
  523. callee->Offset = delta;
  524. }
  525. else
  526. {
  527. callee->Mode = cs_addr_mode;
  528. callee->Segment = dbg_context.x86.SegCs;
  529. callee->Offset = dst;
  530. }
  531. }
  532. return TRUE;
  533. default:
  534. return FALSE;
  535. }
  536. }
  537. static BOOL be_i386_is_jump(const void* insn, ADDRESS64* jumpee)
  538. {
  539. BYTE ch;
  540. int delta;
  541. unsigned operand_size;
  542. ADDRESS_MODE cs_addr_mode;
  543. cs_addr_mode = get_selector_type(dbg_curr_thread->handle, &dbg_context.x86,
  544. dbg_context.x86.SegCs);
  545. operand_size = get_size(cs_addr_mode);
  546. /* get operand_size (also getting rid of the various prefixes */
  547. do
  548. {
  549. if (!dbg_read_memory(insn, &ch, sizeof(ch))) return FALSE;
  550. if (ch == 0x66)
  551. {
  552. operand_size = 48 - operand_size; /* 16 => 32, 32 => 16 */
  553. insn = (const char*)insn + 1;
  554. }
  555. } while (ch == 0x66 || ch == 0x67);
  556. switch (ch)
  557. {
  558. case 0xe9: /* jmp near */
  559. jumpee->Mode = cs_addr_mode;
  560. if (!fetch_value((const char*)insn + 1, operand_size, &delta))
  561. return FALSE;
  562. jumpee->Segment = dbg_context.x86.SegCs;
  563. jumpee->Offset = (DWORD_PTR)insn + 1 + (operand_size / 8) + delta;
  564. return TRUE;
  565. default: WINE_FIXME("unknown %x\n", ch); return FALSE;
  566. }
  567. return FALSE;
  568. }
  569. #define DR7_CONTROL_SHIFT 16
  570. #define DR7_CONTROL_SIZE 4
  571. #define DR7_RW_EXECUTE (0x0)
  572. #define DR7_RW_WRITE (0x1)
  573. #define DR7_RW_READ (0x3)
  574. #define DR7_LEN_1 (0x0)
  575. #define DR7_LEN_2 (0x4)
  576. #define DR7_LEN_4 (0xC)
  577. #define DR7_LOCAL_ENABLE_SHIFT 0
  578. #define DR7_GLOBAL_ENABLE_SHIFT 1
  579. #define DR7_ENABLE_SIZE 2
  580. #define DR7_LOCAL_ENABLE_MASK (0x55)
  581. #define DR7_GLOBAL_ENABLE_MASK (0xAA)
  582. #define DR7_CONTROL_RESERVED (0xFC00)
  583. #define DR7_LOCAL_SLOWDOWN (0x100)
  584. #define DR7_GLOBAL_SLOWDOWN (0x200)
  585. #define DR7_ENABLE_MASK(dr) (1<<(DR7_LOCAL_ENABLE_SHIFT+DR7_ENABLE_SIZE*(dr)))
  586. #define IS_DR7_SET(ctrl,dr) ((ctrl)&DR7_ENABLE_MASK(dr))
  587. static inline int be_i386_get_unused_DR(dbg_ctx_t *pctx, DWORD** r)
  588. {
  589. WOW64_CONTEXT *ctx = &pctx->x86;
  590. if (!IS_DR7_SET(ctx->Dr7, 0))
  591. {
  592. *r = &ctx->Dr0;
  593. return 0;
  594. }
  595. if (!IS_DR7_SET(ctx->Dr7, 1))
  596. {
  597. *r = &ctx->Dr1;
  598. return 1;
  599. }
  600. if (!IS_DR7_SET(ctx->Dr7, 2))
  601. {
  602. *r = &ctx->Dr2;
  603. return 2;
  604. }
  605. if (!IS_DR7_SET(ctx->Dr7, 3))
  606. {
  607. *r = &ctx->Dr3;
  608. return 3;
  609. }
  610. dbg_printf("All hardware registers have been used\n");
  611. return -1;
  612. }
  613. static BOOL be_i386_insert_Xpoint(HANDLE hProcess, const struct be_process_io* pio,
  614. dbg_ctx_t *ctx, enum be_xpoint_type type,
  615. void* addr, unsigned long* val, unsigned size)
  616. {
  617. unsigned char ch;
  618. SIZE_T sz;
  619. DWORD *pr;
  620. int reg;
  621. unsigned long bits;
  622. switch (type)
  623. {
  624. case be_xpoint_break:
  625. if (size != 0) return FALSE;
  626. if (!pio->read(hProcess, addr, &ch, 1, &sz) || sz != 1) return FALSE;
  627. *val = ch;
  628. ch = 0xcc;
  629. if (!pio->write(hProcess, addr, &ch, 1, &sz) || sz != 1) return FALSE;
  630. break;
  631. case be_xpoint_watch_exec:
  632. bits = DR7_RW_EXECUTE;
  633. goto hw_bp;
  634. case be_xpoint_watch_read:
  635. bits = DR7_RW_READ;
  636. goto hw_bp;
  637. case be_xpoint_watch_write:
  638. bits = DR7_RW_WRITE;
  639. hw_bp:
  640. if ((reg = be_i386_get_unused_DR(ctx, &pr)) == -1) return FALSE;
  641. *pr = (DWORD_PTR)addr;
  642. if (type != be_xpoint_watch_exec) switch (size)
  643. {
  644. case 4: bits |= DR7_LEN_4; break;
  645. case 2: bits |= DR7_LEN_2; break;
  646. case 1: bits |= DR7_LEN_1; break;
  647. default: return FALSE;
  648. }
  649. *val = reg;
  650. /* clear old values */
  651. ctx->x86.Dr7 &= ~(0x0F << (DR7_CONTROL_SHIFT + DR7_CONTROL_SIZE * reg));
  652. /* set the correct ones */
  653. ctx->x86.Dr7 |= bits << (DR7_CONTROL_SHIFT + DR7_CONTROL_SIZE * reg);
  654. ctx->x86.Dr7 |= DR7_ENABLE_MASK(reg) | DR7_LOCAL_SLOWDOWN;
  655. break;
  656. default:
  657. dbg_printf("Unknown bp type %c\n", type);
  658. return FALSE;
  659. }
  660. return TRUE;
  661. }
  662. static BOOL be_i386_remove_Xpoint(HANDLE hProcess, const struct be_process_io* pio,
  663. dbg_ctx_t *ctx, enum be_xpoint_type type,
  664. void* addr, unsigned long val, unsigned size)
  665. {
  666. SIZE_T sz;
  667. unsigned char ch;
  668. switch (type)
  669. {
  670. case be_xpoint_break:
  671. if (size != 0) return FALSE;
  672. if (!pio->read(hProcess, addr, &ch, 1, &sz) || sz != 1) return FALSE;
  673. if (ch != (unsigned char)0xCC)
  674. WINE_FIXME("Cannot get back %02x instead of 0xCC at %p\n", ch, addr);
  675. ch = (unsigned char)val;
  676. if (!pio->write(hProcess, addr, &ch, 1, &sz) || sz != 1) return FALSE;
  677. break;
  678. case be_xpoint_watch_exec:
  679. case be_xpoint_watch_read:
  680. case be_xpoint_watch_write:
  681. /* simply disable the entry */
  682. ctx->x86.Dr7 &= ~DR7_ENABLE_MASK(val);
  683. break;
  684. default:
  685. dbg_printf("Unknown bp type %c\n", type);
  686. return FALSE;
  687. }
  688. return TRUE;
  689. }
  690. static BOOL be_i386_is_watchpoint_set(const dbg_ctx_t *ctx, unsigned idx)
  691. {
  692. return ctx->x86.Dr6 & (1 << idx);
  693. }
  694. static void be_i386_clear_watchpoint(dbg_ctx_t *ctx, unsigned idx)
  695. {
  696. ctx->x86.Dr6 &= ~(1 << idx);
  697. }
  698. static int be_i386_adjust_pc_for_break(dbg_ctx_t *ctx, BOOL way)
  699. {
  700. if (way)
  701. {
  702. ctx->x86.Eip--;
  703. return -1;
  704. }
  705. ctx->x86.Eip++;
  706. return 1;
  707. }
  708. static BOOL be_i386_fetch_integer(const struct dbg_lvalue* lvalue, unsigned size,
  709. BOOL is_signed, LONGLONG* ret)
  710. {
  711. if (size != 1 && size != 2 && size != 4 && size != 8 && size != 16) return FALSE;
  712. memset(ret, 0, sizeof(*ret)); /* clear unread bytes */
  713. /* FIXME: this assumes that debuggee and debugger use the same
  714. * integral representation
  715. */
  716. if (!memory_read_value(lvalue, size, ret)) return FALSE;
  717. /* propagate sign information */
  718. if (is_signed && size < 8 && (*ret >> (size * 8 - 1)) != 0)
  719. {
  720. ULONGLONG neg = -1;
  721. *ret |= neg << (size * 8);
  722. }
  723. return TRUE;
  724. }
  725. static BOOL be_i386_fetch_float(const struct dbg_lvalue* lvalue, unsigned size,
  726. long double* ret)
  727. {
  728. char tmp[sizeof(long double)];
  729. /* FIXME: this assumes that debuggee and debugger use the same
  730. * representation for reals
  731. */
  732. if (!memory_read_value(lvalue, size, tmp)) return FALSE;
  733. /* float & double types have to be promoted to a long double */
  734. if (size == 4) *ret = *(float*)tmp;
  735. else if (size == 8) *ret = *(double*)tmp;
  736. else if (size == 10) *ret = *(long double*)tmp;
  737. else return FALSE;
  738. return TRUE;
  739. }
  740. static BOOL be_i386_store_integer(const struct dbg_lvalue* lvalue, unsigned size,
  741. BOOL is_signed, LONGLONG val)
  742. {
  743. /* this is simple as we're on a little endian CPU */
  744. return memory_write_value(lvalue, size, &val);
  745. }
  746. static BOOL be_i386_get_context(HANDLE thread, dbg_ctx_t *ctx)
  747. {
  748. ctx->x86.ContextFlags = WOW64_CONTEXT_ALL;
  749. return Wow64GetThreadContext(thread, &ctx->x86);
  750. }
  751. static BOOL be_i386_set_context(HANDLE thread, const dbg_ctx_t *ctx)
  752. {
  753. return Wow64SetThreadContext(thread, &ctx->x86);
  754. }
  755. #define REG(f,n,t,r) {f, n, t, FIELD_OFFSET(WOW64_CONTEXT, r), sizeof(((WOW64_CONTEXT*)NULL)->r)}
  756. static struct gdb_register be_i386_gdb_register_map[] = {
  757. REG("core", "eax", NULL, Eax),
  758. REG(NULL, "ecx", NULL, Ecx),
  759. REG(NULL, "edx", NULL, Edx),
  760. REG(NULL, "ebx", NULL, Ebx),
  761. REG(NULL, "esp", "data_ptr", Esp),
  762. REG(NULL, "ebp", "data_ptr", Ebp),
  763. REG(NULL, "esi", NULL, Esi),
  764. REG(NULL, "edi", NULL, Edi),
  765. REG(NULL, "eip", "code_ptr", Eip),
  766. REG(NULL, "eflags", "i386_eflags", EFlags),
  767. REG(NULL, "cs", NULL, SegCs),
  768. REG(NULL, "ss", NULL, SegSs),
  769. REG(NULL, "ds", NULL, SegDs),
  770. REG(NULL, "es", NULL, SegEs),
  771. REG(NULL, "fs", NULL, SegFs),
  772. REG(NULL, "gs", NULL, SegGs),
  773. { NULL, "st0", "i387_ext", FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[ 0]), 10},
  774. { NULL, "st1", "i387_ext", FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[10]), 10},
  775. { NULL, "st2", "i387_ext", FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[20]), 10},
  776. { NULL, "st3", "i387_ext", FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[30]), 10},
  777. { NULL, "st4", "i387_ext", FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[40]), 10},
  778. { NULL, "st5", "i387_ext", FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[50]), 10},
  779. { NULL, "st6", "i387_ext", FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[60]), 10},
  780. { NULL, "st7", "i387_ext", FIELD_OFFSET(WOW64_CONTEXT, FloatSave.RegisterArea[70]), 10},
  781. { NULL, "fctrl", NULL, FIELD_OFFSET(WOW64_CONTEXT, FloatSave.ControlWord), 2},
  782. { NULL, "fstat", NULL, FIELD_OFFSET(WOW64_CONTEXT, FloatSave.StatusWord), 2},
  783. { NULL, "ftag", NULL, FIELD_OFFSET(WOW64_CONTEXT, FloatSave.TagWord), 2},
  784. { NULL, "fiseg", NULL, FIELD_OFFSET(WOW64_CONTEXT, FloatSave.ErrorSelector), 2},
  785. REG(NULL, "fioff", NULL, FloatSave.ErrorOffset),
  786. { NULL, "foseg", NULL, FIELD_OFFSET(WOW64_CONTEXT, FloatSave.DataSelector), 2},
  787. REG(NULL, "fooff", NULL, FloatSave.DataOffset),
  788. { NULL, "fop", NULL, FIELD_OFFSET(WOW64_CONTEXT, FloatSave.ErrorSelector)+2, 2},
  789. { "sse", "xmm0", "vec128", FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[0]), 16},
  790. { NULL, "xmm1", "vec128", FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[1]), 16},
  791. { NULL, "xmm2", "vec128", FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[2]), 16},
  792. { NULL, "xmm3", "vec128", FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[3]), 16},
  793. { NULL, "xmm4", "vec128", FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[4]), 16},
  794. { NULL, "xmm5", "vec128", FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[5]), 16},
  795. { NULL, "xmm6", "vec128", FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[6]), 16},
  796. { NULL, "xmm7", "vec128", FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, XmmRegisters[7]), 16},
  797. { NULL, "mxcsr", "i386_mxcsr", FIELD_OFFSET(WOW64_CONTEXT, ExtendedRegisters) + FIELD_OFFSET(XSAVE_FORMAT, MxCsr), 4},
  798. };
  799. struct backend_cpu be_i386 =
  800. {
  801. IMAGE_FILE_MACHINE_I386,
  802. 4,
  803. be_i386_linearize,
  804. be_i386_build_addr,
  805. be_i386_get_addr,
  806. be_i386_get_register_info,
  807. be_i386_single_step,
  808. be_i386_print_context,
  809. be_i386_print_segment_info,
  810. be_i386_ctx,
  811. be_i386_is_step_over_insn,
  812. be_i386_is_function_return,
  813. be_i386_is_break_insn,
  814. be_i386_is_func_call,
  815. be_i386_is_jump,
  816. be_i386_disasm_one_insn,
  817. be_i386_insert_Xpoint,
  818. be_i386_remove_Xpoint,
  819. be_i386_is_watchpoint_set,
  820. be_i386_clear_watchpoint,
  821. be_i386_adjust_pc_for_break,
  822. be_i386_fetch_integer,
  823. be_i386_fetch_float,
  824. be_i386_store_integer,
  825. be_i386_get_context,
  826. be_i386_set_context,
  827. be_i386_gdb_register_map,
  828. ARRAY_SIZE(be_i386_gdb_register_map),
  829. };
  830. #endif