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

3269 lines
102 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Register portions of X86 machine implementation.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. BOOL g_X86InCode16;
  10. BOOL g_X86InVm86;
  11. #define REGALL_SEGREG REGALL_EXTRA0
  12. #define REGALL_MMXREG REGALL_EXTRA1
  13. #define REGALL_DREG REGALL_EXTRA2
  14. REGALLDESC g_X86AllExtraDesc[] =
  15. {
  16. REGALL_SEGREG, "Segment registers",
  17. REGALL_MMXREG, "MMX registers",
  18. REGALL_DREG, "Debug registers and, in kernel, CR4",
  19. REGALL_XMMREG, "SSE XMM registers",
  20. 0, NULL,
  21. };
  22. #define REGALL_CREG REGALL_EXTRA4
  23. #define REGALL_DESC REGALL_EXTRA5
  24. REGALLDESC g_X86KernelExtraDesc[] =
  25. {
  26. REGALL_CREG, "CR0, CR2 and CR3",
  27. REGALL_DESC, "Descriptor and task state",
  28. 0, NULL,
  29. };
  30. char g_Gs[] = "gs";
  31. char g_Fs[] = "fs";
  32. char g_Es[] = "es";
  33. char g_Ds[] = "ds";
  34. char g_Edi[] = "edi";
  35. char g_Esi[] = "esi";
  36. char g_Ebx[] = "ebx";
  37. char g_Edx[] = "edx";
  38. char g_Ecx[] = "ecx";
  39. char g_Eax[] = "eax";
  40. char g_Ebp[] = "ebp";
  41. char g_Eip[] = "eip";
  42. char g_Cs[] = "cs";
  43. char g_Efl[] = "efl";
  44. char g_Esp[] = "esp";
  45. char g_Ss[] = "ss";
  46. char g_Dr0[] = "dr0";
  47. char g_Dr1[] = "dr1";
  48. char g_Dr2[] = "dr2";
  49. char g_Dr3[] = "dr3";
  50. char g_Dr6[] = "dr6";
  51. char g_Dr7[] = "dr7";
  52. char g_Cr0[] = "cr0";
  53. char g_Cr2[] = "cr2";
  54. char g_Cr3[] = "cr3";
  55. char g_Cr4[] = "cr4";
  56. char g_Gdtr[] = "gdtr";
  57. char g_Gdtl[] = "gdtl";
  58. char g_Idtr[] = "idtr";
  59. char g_Idtl[] = "idtl";
  60. char g_Tr[] = "tr";
  61. char g_Ldtr[] = "ldtr";
  62. char g_Di[] = "di";
  63. char g_Si[] = "si";
  64. char g_Bx[] = "bx";
  65. char g_Dx[] = "dx";
  66. char g_Cx[] = "cx";
  67. char g_Ax[] = "ax";
  68. char g_Bp[] = "bp";
  69. char g_Ip[] = "ip";
  70. char g_Fl[] = "fl";
  71. char g_Sp[] = "sp";
  72. char g_Bl[] = "bl";
  73. char g_Dl[] = "dl";
  74. char g_Cl[] = "cl";
  75. char g_Al[] = "al";
  76. char g_Bh[] = "bh";
  77. char g_Dh[] = "dh";
  78. char g_Ch[] = "ch";
  79. char g_Ah[] = "ah";
  80. char g_Iopl[] = "iopl";
  81. char g_Of[] = "of";
  82. char g_Df[] = "df";
  83. char g_If[] = "if";
  84. char g_Tf[] = "tf";
  85. char g_Sf[] = "sf";
  86. char g_Zf[] = "zf";
  87. char g_Af[] = "af";
  88. char g_Pf[] = "pf";
  89. char g_Cf[] = "cf";
  90. char g_Vip[] = "vip";
  91. char g_Vif[] = "vif";
  92. char g_Fpcw[] = "fpcw";
  93. char g_Fpsw[] = "fpsw";
  94. char g_Fptw[] = "fptw";
  95. char g_St0[] = "st0";
  96. char g_St1[] = "st1";
  97. char g_St2[] = "st2";
  98. char g_St3[] = "st3";
  99. char g_St4[] = "st4";
  100. char g_St5[] = "st5";
  101. char g_St6[] = "st6";
  102. char g_St7[] = "st7";
  103. char g_Mm0[] = "mm0";
  104. char g_Mm1[] = "mm1";
  105. char g_Mm2[] = "mm2";
  106. char g_Mm3[] = "mm3";
  107. char g_Mm4[] = "mm4";
  108. char g_Mm5[] = "mm5";
  109. char g_Mm6[] = "mm6";
  110. char g_Mm7[] = "mm7";
  111. char g_Mxcsr[] = "mxcsr";
  112. char g_Xmm0[] = "xmm0";
  113. char g_Xmm1[] = "xmm1";
  114. char g_Xmm2[] = "xmm2";
  115. char g_Xmm3[] = "xmm3";
  116. char g_Xmm4[] = "xmm4";
  117. char g_Xmm5[] = "xmm5";
  118. char g_Xmm6[] = "xmm6";
  119. char g_Xmm7[] = "xmm7";
  120. REGDEF g_X86Defs[] =
  121. {
  122. { g_Gs, X86_GS },
  123. { g_Fs, X86_FS },
  124. { g_Es, X86_ES },
  125. { g_Ds, X86_DS },
  126. { g_Edi, X86_EDI },
  127. { g_Esi, X86_ESI },
  128. { g_Ebx, X86_EBX },
  129. { g_Edx, X86_EDX },
  130. { g_Ecx, X86_ECX },
  131. { g_Eax, X86_EAX },
  132. { g_Ebp, X86_EBP },
  133. { g_Eip, X86_EIP },
  134. { g_Cs, X86_CS },
  135. { g_Efl, X86_EFL },
  136. { g_Esp, X86_ESP },
  137. { g_Ss, X86_SS },
  138. { g_Dr0, X86_DR0 },
  139. { g_Dr1, X86_DR1 },
  140. { g_Dr2, X86_DR2 },
  141. { g_Dr3, X86_DR3 },
  142. { g_Dr6, X86_DR6 },
  143. { g_Dr7, X86_DR7 },
  144. { g_Di, X86_DI },
  145. { g_Si, X86_SI },
  146. { g_Bx, X86_BX },
  147. { g_Dx, X86_DX },
  148. { g_Cx, X86_CX },
  149. { g_Ax, X86_AX },
  150. { g_Bp, X86_BP },
  151. { g_Ip, X86_IP },
  152. { g_Fl, X86_FL },
  153. { g_Sp, X86_SP },
  154. { g_Bl, X86_BL },
  155. { g_Dl, X86_DL },
  156. { g_Cl, X86_CL },
  157. { g_Al, X86_AL },
  158. { g_Bh, X86_BH },
  159. { g_Dh, X86_DH },
  160. { g_Ch, X86_CH },
  161. { g_Ah, X86_AH },
  162. { g_Fpcw, X86_FPCW },
  163. { g_Fpsw, X86_FPSW },
  164. { g_Fptw, X86_FPTW },
  165. { g_St0, X86_ST0 },
  166. { g_St1, X86_ST1 },
  167. { g_St2, X86_ST2 },
  168. { g_St3, X86_ST3 },
  169. { g_St4, X86_ST4 },
  170. { g_St5, X86_ST5 },
  171. { g_St6, X86_ST6 },
  172. { g_St7, X86_ST7 },
  173. { g_Mm0, X86_MM0 },
  174. { g_Mm1, X86_MM1 },
  175. { g_Mm2, X86_MM2 },
  176. { g_Mm3, X86_MM3 },
  177. { g_Mm4, X86_MM4 },
  178. { g_Mm5, X86_MM5 },
  179. { g_Mm6, X86_MM6 },
  180. { g_Mm7, X86_MM7 },
  181. { g_Mxcsr, X86_MXCSR},
  182. { g_Xmm0, X86_XMM0 },
  183. { g_Xmm1, X86_XMM1 },
  184. { g_Xmm2, X86_XMM2 },
  185. { g_Xmm3, X86_XMM3 },
  186. { g_Xmm4, X86_XMM4 },
  187. { g_Xmm5, X86_XMM5 },
  188. { g_Xmm6, X86_XMM6 },
  189. { g_Xmm7, X86_XMM7 },
  190. { g_Iopl, X86_IOPL },
  191. { g_Of, X86_OF },
  192. { g_Df, X86_DF },
  193. { g_If, X86_IF },
  194. { g_Tf, X86_TF },
  195. { g_Sf, X86_SF },
  196. { g_Zf, X86_ZF },
  197. { g_Af, X86_AF },
  198. { g_Pf, X86_PF },
  199. { g_Cf, X86_CF },
  200. { g_Vip, X86_VIP },
  201. { g_Vif, X86_VIF },
  202. { NULL, REG_ERROR },
  203. };
  204. REGDEF g_X86KernelReg[] =
  205. {
  206. { g_Cr0, X86_CR0 },
  207. { g_Cr2, X86_CR2 },
  208. { g_Cr3, X86_CR3 },
  209. { g_Cr4, X86_CR4 },
  210. { g_Gdtr, X86_GDTR },
  211. { g_Gdtl, X86_GDTL },
  212. { g_Idtr, X86_IDTR },
  213. { g_Idtl, X86_IDTL },
  214. { g_Tr, X86_TR },
  215. { g_Ldtr, X86_LDTR },
  216. { NULL, REG_ERROR },
  217. };
  218. REGSUBDEF g_X86SubDefs[] =
  219. {
  220. { X86_DI, X86_EDI, 0, 0xffff }, // DI register
  221. { X86_SI, X86_ESI, 0, 0xffff }, // SI register
  222. { X86_BX, X86_EBX, 0, 0xffff }, // BX register
  223. { X86_DX, X86_EDX, 0, 0xffff }, // DX register
  224. { X86_CX, X86_ECX, 0, 0xffff }, // CX register
  225. { X86_AX, X86_EAX, 0, 0xffff }, // AX register
  226. { X86_BP, X86_EBP, 0, 0xffff }, // BP register
  227. { X86_IP, X86_EIP, 0, 0xffff }, // IP register
  228. { X86_FL, X86_EFL, 0, 0xffff }, // FL register
  229. { X86_SP, X86_ESP, 0, 0xffff }, // SP register
  230. { X86_BL, X86_EBX, 0, 0xff }, // BL register
  231. { X86_DL, X86_EDX, 0, 0xff }, // DL register
  232. { X86_CL, X86_ECX, 0, 0xff }, // CL register
  233. { X86_AL, X86_EAX, 0, 0xff }, // AL register
  234. { X86_BH, X86_EBX, 8, 0xff }, // BH register
  235. { X86_DH, X86_EDX, 8, 0xff }, // DH register
  236. { X86_CH, X86_ECX, 8, 0xff }, // CH register
  237. { X86_AH, X86_EAX, 8, 0xff }, // AH register
  238. { X86_IOPL, X86_EFL,12, 3 }, // IOPL level value
  239. { X86_OF, X86_EFL,11, 1 }, // OF (overflow flag)
  240. { X86_DF, X86_EFL,10, 1 }, // DF (direction flag)
  241. { X86_IF, X86_EFL, 9, 1 }, // IF (interrupt enable flag)
  242. { X86_TF, X86_EFL, 8, 1 }, // TF (trace flag)
  243. { X86_SF, X86_EFL, 7, 1 }, // SF (sign flag)
  244. { X86_ZF, X86_EFL, 6, 1 }, // ZF (zero flag)
  245. { X86_AF, X86_EFL, 4, 1 }, // AF (aux carry flag)
  246. { X86_PF, X86_EFL, 2, 1 }, // PF (parity flag)
  247. { X86_CF, X86_EFL, 0, 1 }, // CF (carry flag)
  248. { X86_VIP, X86_EFL,20, 1 }, // VIP (virtual interrupt pending)
  249. { X86_VIF, X86_EFL,19, 1 }, // VIF (virtual interrupt flag)
  250. { REG_ERROR, REG_ERROR, 0, 0 }
  251. };
  252. RegisterGroup g_X86BaseGroup =
  253. {
  254. 0, g_X86Defs, g_X86SubDefs, g_X86AllExtraDesc
  255. };
  256. RegisterGroup g_X86KernelGroup =
  257. {
  258. 0, g_X86KernelReg, NULL, g_X86KernelExtraDesc
  259. };
  260. // First ExecTypes entry must be the actual processor type.
  261. ULONG g_X86ExecTypes[] =
  262. {
  263. IMAGE_FILE_MACHINE_I386
  264. };
  265. // This array must be sorted by CV reg value.
  266. CvRegMap g_X86CvRegMap[] =
  267. {
  268. { CV_REG_AL, X86_AL},
  269. { CV_REG_CL, X86_CL},
  270. { CV_REG_DL, X86_DL},
  271. { CV_REG_BL, X86_BL},
  272. { CV_REG_AH, X86_AH},
  273. { CV_REG_CH, X86_CH},
  274. { CV_REG_DH, X86_DH},
  275. { CV_REG_BH, X86_BH},
  276. { CV_REG_AX, X86_AX},
  277. { CV_REG_CX, X86_CX},
  278. { CV_REG_DX, X86_DX},
  279. { CV_REG_BX, X86_BX},
  280. { CV_REG_SP, X86_SP},
  281. { CV_REG_BP, X86_BP},
  282. { CV_REG_SI, X86_SI},
  283. { CV_REG_DI, X86_DI},
  284. { CV_REG_EAX, X86_EAX},
  285. { CV_REG_ECX, X86_ECX},
  286. { CV_REG_EDX, X86_EDX},
  287. { CV_REG_EBX, X86_EBX},
  288. { CV_REG_ESP, X86_ESP},
  289. { CV_REG_EBP, X86_EBP},
  290. { CV_REG_ESI, X86_ESI},
  291. { CV_REG_EDI, X86_EDI},
  292. { CV_REG_ES, X86_ES},
  293. { CV_REG_CS, X86_CS},
  294. { CV_REG_SS, X86_SS},
  295. { CV_REG_DS, X86_DS},
  296. { CV_REG_FS, X86_FS},
  297. { CV_REG_GS, X86_GS},
  298. { CV_REG_IP, X86_IP},
  299. { CV_REG_FLAGS, X86_FL},
  300. { CV_REG_EIP, X86_EIP},
  301. { CV_REG_EFLAGS, X86_EFL},
  302. // { CV_REG_TEMP, REGTEMP},
  303. // { CV_REG_TEMPH, REGTEMPH},
  304. // { CV_REG_QUOTE, REGQUOTE},
  305. // { CV_REG_PCDR3, REGPCDR3},
  306. // { CV_REG_PCDR4, REGPCDR4},
  307. // { CV_REG_PCDR5, REGPCDR5},
  308. // { CV_REG_PCDR6, REGPCDR6},
  309. // { CV_REG_PCDR7, REGPCDR7},
  310. { CV_REG_CR0, X86_CR0},
  311. // { CV_REG_CR1, REGCR1},
  312. { CV_REG_CR2, X86_CR2},
  313. { CV_REG_CR3, X86_CR3},
  314. { CV_REG_CR4, X86_CR4},
  315. { CV_REG_DR0, X86_DR0},
  316. { CV_REG_DR1, X86_DR1},
  317. { CV_REG_DR2, X86_DR2},
  318. { CV_REG_DR3, X86_DR3},
  319. // { CV_REG_DR4, REGDR4},
  320. // { CV_REG_DR5, REGDR5},
  321. { CV_REG_DR6, X86_DR6},
  322. { CV_REG_DR7, X86_DR7},
  323. { CV_REG_GDTR, X86_GDTR},
  324. { CV_REG_GDTL, X86_GDTL},
  325. { CV_REG_IDTR, X86_IDTR},
  326. { CV_REG_IDTL, X86_IDTL},
  327. { CV_REG_LDTR, X86_LDTR},
  328. { CV_REG_TR, X86_TR},
  329. // { CV_REG_PSEUDO1, REGPSEUDO1},
  330. // { CV_REG_PSEUDO2, REGPSEUDO2},
  331. // { CV_REG_PSEUDO3, REGPSEUDO3},
  332. // { CV_REG_PSEUDO4, REGPSEUDO4},
  333. // { CV_REG_PSEUDO5, REGPSEUDO5},
  334. // { CV_REG_PSEUDO6, REGPSEUDO6},
  335. // { CV_REG_PSEUDO7, REGPSEUDO7},
  336. // { CV_REG_PSEUDO8, REGPSEUDO8},
  337. // { CV_REG_PSEUDO9, REGPSEUDO9},
  338. { CV_REG_ST0, X86_ST0},
  339. { CV_REG_ST1, X86_ST1},
  340. { CV_REG_ST2, X86_ST2},
  341. { CV_REG_ST3, X86_ST3},
  342. { CV_REG_ST4, X86_ST4},
  343. { CV_REG_ST5, X86_ST5},
  344. { CV_REG_ST6, X86_ST6},
  345. { CV_REG_ST7, X86_ST7},
  346. { CV_REG_CTRL, X86_FPCW},
  347. { CV_REG_STAT, X86_FPSW},
  348. { CV_REG_TAG, X86_FPTW},
  349. // { CV_REG_FPIP, REGFPIP},
  350. // { CV_REG_FPCS, REGFPCS},
  351. // { CV_REG_FPDO, REGFPDO},
  352. // { CV_REG_FPDS, REGFPDS},
  353. // { CV_REG_ISEM, REGISEM},
  354. // { CV_REG_FPEIP, REGFPEIP},
  355. // { CV_REG_FPEDO, REGFPEDO},
  356. { CV_REG_MM0, X86_MM0},
  357. { CV_REG_MM1, X86_MM1},
  358. { CV_REG_MM2, X86_MM2},
  359. { CV_REG_MM3, X86_MM3},
  360. { CV_REG_MM4, X86_MM4},
  361. { CV_REG_MM5, X86_MM5},
  362. { CV_REG_MM6, X86_MM6},
  363. { CV_REG_MM7, X86_MM7},
  364. };
  365. X86MachineInfo::X86MachineInfo(TargetInfo* Target)
  366. : BaseX86MachineInfo(Target)
  367. {
  368. m_FullName = "x86 compatible";
  369. m_AbbrevName = "x86";
  370. m_PageSize = X86_PAGE_SIZE;
  371. m_PageShift = X86_PAGE_SHIFT;
  372. m_NumExecTypes = 1;
  373. m_ExecTypes = g_X86ExecTypes;
  374. m_Ptr64 = FALSE;
  375. m_RetRegIndex = X86_EAX;
  376. m_AllMask = REGALL_INT32 | REGALL_SEGREG,
  377. m_MaxDataBreakpoints = 4;
  378. m_SymPrefix = NULL;
  379. m_SizeCanonicalContext = sizeof(X86_NT5_CONTEXT);
  380. m_SverCanonicalContext = NT_SVER_W2K;
  381. m_SupportsBranchTrace = FALSE;
  382. m_ResetBranchTrace = TRUE;
  383. m_CvRegMapSize = DIMA(g_X86CvRegMap);
  384. m_CvRegMap = g_X86CvRegMap;
  385. }
  386. HRESULT
  387. X86MachineInfo::Initialize(void)
  388. {
  389. m_Groups[0] = &g_X86BaseGroup;
  390. m_NumGroups = 1;
  391. if (IS_KERNEL_TARGET(m_Target))
  392. {
  393. m_Groups[m_NumGroups] = &g_X86KernelGroup;
  394. m_NumGroups++;
  395. }
  396. return MachineInfo::Initialize();
  397. }
  398. HRESULT
  399. X86MachineInfo::InitializeForProcessor(void)
  400. {
  401. if (!strcmp(m_Target->m_FirstProcessorId.X86.VendorString, "GenuineIntel"))
  402. {
  403. // Branch trace support was added for the Pentium Pro.
  404. m_SupportsBranchTrace = m_Target->m_FirstProcessorId.X86.Family >= 6;
  405. }
  406. return MachineInfo::InitializeForProcessor();
  407. }
  408. void
  409. X86MachineInfo::GetSystemTypeInfo(PSYSTEM_TYPE_INFO Info)
  410. {
  411. Info->TriagePrcbOffset = EXTEND64(X86_TRIAGE_PRCB_ADDRESS);
  412. Info->SizeTargetContext = sizeof(X86_CONTEXT);
  413. Info->OffsetSpecialRegisters = sizeof(X86_CONTEXT);
  414. Info->OffsetTargetContextFlags = FIELD_OFFSET(X86_CONTEXT, ContextFlags);
  415. Info->SizeControlReport = sizeof(X86_DBGKD_CONTROL_REPORT);
  416. Info->SizeKspecialRegisters = sizeof(X86_KSPECIAL_REGISTERS);
  417. Info->SizePageFrameNumber = sizeof(ULONG);
  418. Info->SizePte = m_Target->m_KdDebuggerData.PaeEnabled ?
  419. sizeof(ULONG64) : sizeof(ULONG);
  420. Info->SizeDynamicFunctionTable = 0;
  421. Info->SizeRuntimeFunction = 0;
  422. Info->SharedUserDataOffset = 0;
  423. Info->UmSharedUserDataOffset = 0;
  424. Info->UmSharedSysCallOffset = 0;
  425. Info->UmSharedSysCallSize = 0;
  426. if (m_Target->m_PlatformId == VER_PLATFORM_WIN32_NT)
  427. {
  428. Info->SharedUserDataOffset = IS_KERNEL_TARGET(m_Target) ?
  429. EXTEND64(X86_KI_USER_SHARED_DATA) : MM_SHARED_USER_DATA_VA;
  430. Info->UmSharedUserDataOffset = MM_SHARED_USER_DATA_VA;
  431. if (m_Target->m_SystemVersion >= NT_SVER_XP)
  432. {
  433. // The syscall offset should really be provided in the debugger
  434. // data block so that it automatically tracks system changes. It's
  435. // relatively stable, now, though.
  436. if (m_Target->m_BuildNumber >= 2492)
  437. {
  438. Info->UmSharedSysCallOffset = X86_SHARED_SYSCALL_BASE_GTE2492;
  439. }
  440. else if (m_Target->m_BuildNumber >= 2412)
  441. {
  442. Info->UmSharedSysCallOffset = X86_SHARED_SYSCALL_BASE_GTE2412;
  443. }
  444. else
  445. {
  446. Info->UmSharedSysCallOffset = X86_SHARED_SYSCALL_BASE_LT2412;
  447. }
  448. Info->UmSharedSysCallSize = X86_SHARED_SYSCALL_SIZE;
  449. }
  450. }
  451. if (m_Target->m_SystemVersion > NT_SVER_NT4)
  452. {
  453. Info->SizeTargetContext = sizeof(X86_NT5_CONTEXT);
  454. Info->OffsetSpecialRegisters = sizeof(X86_NT5_CONTEXT);
  455. Info->OffsetTargetContextFlags =
  456. FIELD_OFFSET(X86_NT5_CONTEXT, ContextFlags);
  457. }
  458. }
  459. void
  460. X86MachineInfo::GetDefaultKdData(PKDDEBUGGER_DATA64 KdData)
  461. {
  462. //
  463. // Parts of the data block may already be filled out
  464. // so don't destroy anything that's already set.
  465. //
  466. if (!KdData->OffsetKThreadApcProcess)
  467. {
  468. KdData->OffsetKThreadNextProcessor = X86_KTHREAD_NEXTPROCESSOR_OFFSET;
  469. KdData->OffsetKThreadTeb = X86_KTHREAD_TEB_OFFSET;
  470. KdData->OffsetKThreadKernelStack = X86_KTHREAD_KERNELSTACK_OFFSET;
  471. KdData->OffsetKThreadInitialStack = X86_KTHREAD_INITSTACK_OFFSET;
  472. KdData->OffsetKThreadApcProcess = X86_KTHREAD_APCPROCESS_OFFSET;
  473. KdData->OffsetKThreadState = X86_KTHREAD_STATE_OFFSET;
  474. KdData->OffsetEprocessPeb = X86_NT4_PEB_IN_EPROCESS;
  475. KdData->OffsetEprocessParentCID = X86_NT4_PCID_IN_EPROCESS;
  476. KdData->OffsetEprocessDirectoryTableBase =
  477. X86_DIRECTORY_TABLE_BASE_IN_EPROCESS;
  478. KdData->SizeEProcess = X86_NT5_EPROCESS_SIZE;
  479. KdData->SizePrcb = X86_NT4_KPRCB_SIZE;
  480. KdData->OffsetPrcbDpcRoutine = X86_KPRCB_DPC_ROUTINE_ACTIVE;
  481. KdData->OffsetPrcbCurrentThread = DEF_KPRCB_CURRENT_THREAD_OFFSET_32;
  482. KdData->OffsetPrcbMhz = X86_1381_KPRCB_MHZ;
  483. KdData->OffsetPrcbCpuType = X86_KPRCB_CPU_TYPE;
  484. KdData->OffsetPrcbVendorString = X86_1387_KPRCB_VENDOR_STRING;
  485. KdData->OffsetPrcbProcStateContext = X86_KPRCB_CONTEXT;
  486. KdData->OffsetPrcbNumber = X86_KPRCB_NUMBER;
  487. KdData->SizeEThread = X86_ETHREAD_SIZE;
  488. if (m_Target->m_SystemVersion > NT_SVER_NT4)
  489. {
  490. KdData->SizePrcb = X86_NT5_KPRCB_SIZE;
  491. KdData->OffsetEprocessPeb = X86_PEB_IN_EPROCESS;
  492. KdData->OffsetEprocessParentCID = X86_PCID_IN_EPROCESS;
  493. KdData->OffsetPrcbMhz = X86_2195_KPRCB_MHZ;
  494. }
  495. if (m_Target->m_BuildNumber >= 2087)
  496. {
  497. KdData->OffsetPrcbVendorString = X86_2087_KPRCB_VENDOR_STRING;
  498. }
  499. if (m_Target->m_BuildNumber > 2230)
  500. {
  501. KdData->OffsetKThreadNextProcessor =
  502. X86_2230_KTHREAD_NEXTPROCESSOR_OFFSET;
  503. }
  504. if (m_Target->m_BuildNumber >= 2251)
  505. {
  506. KdData->OffsetPrcbVendorString = X86_2251_KPRCB_VENDOR_STRING;
  507. }
  508. if (m_Target->m_SystemVersion > NT_SVER_W2K)
  509. {
  510. KdData->SizeEProcess = X86_NT51_EPROCESS_SIZE;
  511. }
  512. if (m_Target->m_BuildNumber > 2407)
  513. {
  514. KdData->SizeEThread = X86_NT51_ETHREAD_SIZE;
  515. KdData->OffsetKThreadNextProcessor =
  516. X86_NT51_KTHREAD_NEXTPROCESSOR_OFFSET;
  517. }
  518. if (m_Target->m_BuildNumber >= 2462)
  519. {
  520. KdData->OffsetPrcbMhz = X86_2462_KPRCB_MHZ;
  521. }
  522. if (m_Target->m_BuildNumber >= 2474)
  523. {
  524. KdData->OffsetPrcbVendorString = X86_2474_KPRCB_VENDOR_STRING;
  525. }
  526. if (m_Target->m_BuildNumber >= 2505)
  527. {
  528. KdData->OffsetPrcbMhz = X86_2505_KPRCB_MHZ;
  529. }
  530. if (m_Target->m_SystemVersion > NT_SVER_XP)
  531. {
  532. KdData->SizeEProcess = X86_NT511_EPROCESS_SIZE;
  533. }
  534. if (m_Target->m_BuildNumber > 3558)
  535. {
  536. KdData->OffsetKThreadApcProcess =
  537. X86_3555_KTHREAD_APCPROCESS_OFFSET;
  538. KdData->OffsetKThreadTeb =
  539. X86_3555_KTHREAD_TEB_OFFSET;
  540. KdData->OffsetKThreadKernelStack =
  541. X86_3555_KTHREAD_KERNELSTACK_OFFSET;
  542. KdData->OffsetKThreadNextProcessor =
  543. X86_3555_KTHREAD_NEXTPROCESSOR_OFFSET;
  544. KdData->OffsetKThreadState =
  545. X86_3555_KTHREAD_STATE_OFFSET;
  546. }
  547. }
  548. if (!KdData->SizePcr)
  549. {
  550. KdData->SizePcr = X86_1381_KPCR_SIZE;
  551. if (m_Target->m_BuildNumber >= 2195)
  552. {
  553. KdData->SizePcr = X86_2195_KPCR_SIZE;
  554. }
  555. if (m_Target->m_BuildNumber >= 2600)
  556. {
  557. KdData->SizePcr = X86_KPCR_SIZE;
  558. }
  559. KdData->OffsetPcrSelfPcr = X86_KPCR_SELF_PCR;
  560. KdData->OffsetPcrCurrentPrcb = X86_KPCR_PRCB;
  561. KdData->OffsetPcrContainedPrcb = X86_KPCR_PRCB_DATA;
  562. KdData->OffsetPcrInitialBStore = 0;
  563. KdData->OffsetPcrBStoreLimit = 0;
  564. KdData->OffsetPcrInitialStack = 0;
  565. KdData->OffsetPcrStackLimit = 0;
  566. KdData->OffsetPrcbPcrPage = 0;
  567. KdData->OffsetPrcbProcStateSpecialReg = X86_KPRCB_SPECIAL_REG;
  568. KdData->GdtR0Code = X86_KGDT_R0_CODE;
  569. KdData->GdtR0Data = X86_KGDT_R0_DATA;
  570. KdData->GdtR0Pcr = X86_KGDT_R0_PCR;
  571. KdData->GdtR3Code = X86_KGDT_R3_CODE + 3;
  572. KdData->GdtR3Data = X86_KGDT_R3_DATA + 3;
  573. KdData->GdtR3Teb = X86_KGDT_R3_TEB + 3;
  574. KdData->GdtLdt = X86_KGDT_LDT;
  575. KdData->GdtTss = X86_KGDT_TSS;
  576. KdData->Gdt64R3CmCode = 0;
  577. KdData->Gdt64R3CmTeb = 0;
  578. }
  579. }
  580. void
  581. X86MachineInfo::
  582. InitializeContext(ULONG64 Pc,
  583. PDBGKD_ANY_CONTROL_REPORT ControlReport)
  584. {
  585. ULONG Pc32 = (ULONG)Pc;
  586. m_Context.X86Nt5Context.Eip = Pc32;
  587. m_ContextState = Pc32 ? MCTX_PC : MCTX_NONE;
  588. if (ControlReport != NULL)
  589. {
  590. BpOut("InitializeContext(%d) DR6 %X DR7 %X\n",
  591. m_Target->m_RegContextProcessor,
  592. ControlReport->X86ControlReport.Dr6,
  593. ControlReport->X86ControlReport.Dr7);
  594. m_Context.X86Nt5Context.Dr6 = ControlReport->X86ControlReport.Dr6;
  595. m_Context.X86Nt5Context.Dr7 = ControlReport->X86ControlReport.Dr7;
  596. m_ContextState = MCTX_DR67_REPORT;
  597. if (ControlReport->X86ControlReport.ReportFlags &
  598. X86_REPORT_INCLUDES_SEGS)
  599. {
  600. //
  601. // This is for backwards compatibility - older kernels
  602. // won't pass these registers in the report record.
  603. //
  604. m_Context.X86Nt5Context.SegCs =
  605. ControlReport->X86ControlReport.SegCs;
  606. m_Context.X86Nt5Context.SegDs =
  607. ControlReport->X86ControlReport.SegDs;
  608. m_Context.X86Nt5Context.SegEs =
  609. ControlReport->X86ControlReport.SegEs;
  610. m_Context.X86Nt5Context.SegFs =
  611. ControlReport->X86ControlReport.SegFs;
  612. m_Context.X86Nt5Context.EFlags =
  613. ControlReport->X86ControlReport.EFlags;
  614. m_ContextState = MCTX_REPORT;
  615. }
  616. }
  617. if (!IS_CONTEXT_POSSIBLE(m_Target))
  618. {
  619. g_X86InVm86 = FALSE;
  620. g_X86InCode16 = FALSE;
  621. }
  622. else
  623. {
  624. // Check whether we're currently in V86 mode or 16-bit code.
  625. g_X86InVm86 = X86_IS_VM86(GetIntReg(X86_EFL));
  626. if (IS_KERNEL_TARGET(m_Target) && !g_X86InVm86)
  627. {
  628. if (ControlReport == NULL ||
  629. (ControlReport->X86ControlReport.ReportFlags &
  630. X86_REPORT_STANDARD_CS) == 0)
  631. {
  632. DESCRIPTOR64 Desc;
  633. if (GetSegRegDescriptor(SEGREG_CODE, &Desc) != S_OK)
  634. {
  635. WarnOut("CS descriptor lookup failed\n");
  636. g_X86InCode16 = FALSE;
  637. }
  638. else
  639. {
  640. g_X86InCode16 = (Desc.Flags & X86_DESC_DEFAULT_BIG) == 0;
  641. }
  642. }
  643. else
  644. {
  645. g_X86InCode16 = FALSE;
  646. // We're in a standard code segment so cache
  647. // a default descriptor for CS to avoid further
  648. // CS lookups.
  649. m_Target->
  650. EmulateNtX86SelDescriptor(m_Target->m_RegContextThread,
  651. this,
  652. m_Context.X86Nt5Context.SegCs,
  653. &m_SegRegDesc[SEGREG_CODE]);
  654. }
  655. }
  656. }
  657. // Add instructions to cache only if we're in 32-bit flat mode.
  658. if (Pc32 && ControlReport != NULL &&
  659. !g_X86InVm86 && !g_X86InCode16)
  660. {
  661. CacheReportInstructions
  662. (Pc, ControlReport->X86ControlReport.InstructionCount,
  663. ControlReport->X86ControlReport.InstructionStream);
  664. }
  665. }
  666. HRESULT
  667. X86MachineInfo::KdGetContextState(ULONG State)
  668. {
  669. HRESULT Status;
  670. if (State >= MCTX_CONTEXT && m_ContextState < MCTX_CONTEXT)
  671. {
  672. Status = m_Target->
  673. GetContext(m_Target->m_RegContextThread->m_Handle,
  674. &m_Context);
  675. if (Status != S_OK)
  676. {
  677. return Status;
  678. }
  679. m_ContextState = MCTX_CONTEXT;
  680. }
  681. if (State >= MCTX_FULL && m_ContextState < MCTX_FULL)
  682. {
  683. Status = m_Target->GetTargetSpecialRegisters
  684. (m_Target->m_RegContextThread->m_Handle,
  685. (PCROSS_PLATFORM_KSPECIAL_REGISTERS)&m_Special.X86Special);
  686. if (Status != S_OK)
  687. {
  688. return Status;
  689. }
  690. Status = m_Target->GetTargetSegRegDescriptors
  691. (m_Target->m_RegContextThread->m_Handle,
  692. 0, SEGREG_COUNT, m_SegRegDesc);
  693. if (Status != S_OK)
  694. {
  695. return Status;
  696. }
  697. m_ContextState = MCTX_FULL;
  698. KdSetSpecialRegistersInContext();
  699. BpOut("GetContextState(%d) DR6 %X DR7 %X DR0 %X\n",
  700. m_Target->m_RegContextProcessor, m_Special.X86Special.KernelDr6,
  701. m_Special.X86Special.KernelDr7, m_Special.X86Special.KernelDr0);
  702. }
  703. return S_OK;
  704. }
  705. HRESULT
  706. X86MachineInfo::KdSetContext(void)
  707. {
  708. HRESULT Status;
  709. Status = m_Target->SetContext(m_Target->m_RegContextThread->m_Handle,
  710. &m_Context);
  711. if (Status != S_OK)
  712. {
  713. return Status;
  714. }
  715. KdGetSpecialRegistersFromContext();
  716. Status = m_Target->SetTargetSpecialRegisters
  717. (m_Target->m_RegContextThread->m_Handle,
  718. (PCROSS_PLATFORM_KSPECIAL_REGISTERS)&m_Special.X86Special);
  719. if (Status != S_OK)
  720. {
  721. return Status;
  722. }
  723. BpOut("SetContext(%d) DR6 %X DR7 %X DR0 %X\n",
  724. m_Target->m_RegContextProcessor, m_Special.X86Special.KernelDr6,
  725. m_Special.X86Special.KernelDr7, m_Special.X86Special.KernelDr0);
  726. return S_OK;
  727. }
  728. HRESULT
  729. X86MachineInfo::ConvertContextFrom(PCROSS_PLATFORM_CONTEXT Context,
  730. ULONG FromSver, ULONG FromSize, PVOID From)
  731. {
  732. if (FromSver <= NT_SVER_NT4)
  733. {
  734. if (FromSize < sizeof(X86_CONTEXT))
  735. {
  736. return E_INVALIDARG;
  737. }
  738. memcpy(Context, From, sizeof(X86_CONTEXT));
  739. ZeroMemory(Context->X86Nt5Context.ExtendedRegisters,
  740. sizeof(Context->X86Nt5Context.ExtendedRegisters));
  741. }
  742. else if (FromSize >= sizeof(X86_NT5_CONTEXT))
  743. {
  744. memcpy(Context, From, sizeof(X86_NT5_CONTEXT));
  745. }
  746. else
  747. {
  748. return E_INVALIDARG;
  749. }
  750. return S_OK;
  751. }
  752. HRESULT
  753. X86MachineInfo::ConvertContextTo(PCROSS_PLATFORM_CONTEXT Context,
  754. ULONG ToSver, ULONG ToSize, PVOID To)
  755. {
  756. if (ToSver <= NT_SVER_NT4)
  757. {
  758. if (ToSize < sizeof(X86_CONTEXT))
  759. {
  760. return E_INVALIDARG;
  761. }
  762. memcpy(To, Context, sizeof(X86_CONTEXT));
  763. }
  764. else if (ToSize >= sizeof(X86_NT5_CONTEXT))
  765. {
  766. memcpy(To, Context, sizeof(X86_NT5_CONTEXT));
  767. }
  768. else
  769. {
  770. return E_INVALIDARG;
  771. }
  772. return S_OK;
  773. }
  774. void
  775. X86MachineInfo::InitializeContextFlags(PCROSS_PLATFORM_CONTEXT Context,
  776. ULONG Version)
  777. {
  778. ULONG ContextFlags;
  779. ContextFlags = VDMCONTEXT_CONTROL | VDMCONTEXT_INTEGER |
  780. VDMCONTEXT_SEGMENTS | VDMCONTEXT_FLOATING_POINT;
  781. if (IS_USER_TARGET(m_Target))
  782. {
  783. ContextFlags |= VDMCONTEXT_DEBUG_REGISTERS;
  784. }
  785. if (Version <= NT_SVER_NT4)
  786. {
  787. Context->X86Context.ContextFlags = ContextFlags;
  788. }
  789. else
  790. {
  791. Context->X86Nt5Context.ContextFlags = ContextFlags |
  792. VDMCONTEXT_EXTENDED_REGISTERS;
  793. }
  794. }
  795. HRESULT
  796. X86MachineInfo::GetContextFromThreadStack(ULONG64 ThreadBase,
  797. PCROSS_PLATFORM_CONTEXT Context,
  798. ULONG64 Stack)
  799. {
  800. HRESULT Status;
  801. X86_KSWITCHFRAME SwitchFrame;
  802. if ((Status = m_Target->ReadAllVirtual(m_Target->m_ProcessHead,
  803. Stack,
  804. &SwitchFrame,
  805. sizeof(SwitchFrame))) != S_OK)
  806. {
  807. return Status;
  808. }
  809. ZeroMemory(Context, sizeof(*Context));
  810. Context->X86Nt5Context.Eip = SwitchFrame.RetAddr;
  811. Context->X86Nt5Context.Esp = (ULONG)Stack + sizeof(SwitchFrame);
  812. if ((Status = m_Target->
  813. ReadAllVirtual(m_Target->m_ProcessHead,
  814. EXTEND64(Context->X86Nt5Context.Esp),
  815. &Context->X86Nt5Context.Ebp,
  816. sizeof(Context)->X86Nt5Context.Ebp)) != S_OK)
  817. {
  818. return Status;
  819. }
  820. // Fill the segments in from current information
  821. // instead of just leaving them blank.
  822. Context->X86Nt5Context.SegSs = GetIntReg(X86_SS);
  823. Context->X86Nt5Context.SegCs = GetIntReg(X86_CS);
  824. return S_OK;
  825. }
  826. HRESULT
  827. X86MachineInfo::GetContextFromFiber(ProcessInfo* Process,
  828. ULONG64 FiberBase,
  829. PCROSS_PLATFORM_CONTEXT Context,
  830. BOOL Verbose)
  831. {
  832. HRESULT Status;
  833. X86_FIBER Fiber;
  834. if ((Status = m_Target->
  835. ReadAllVirtual(Process, FiberBase, &Fiber, sizeof(Fiber))) != S_OK)
  836. {
  837. if (Verbose)
  838. {
  839. ErrOut("Unable to read fiber data at %s\n",
  840. FormatMachineAddr64(this, FiberBase));
  841. }
  842. return Status;
  843. }
  844. if ((Status = ConvertContextFrom(Context, m_Target->m_SystemVersion,
  845. m_Target->m_TypeInfo.SizeTargetContext,
  846. &Fiber.FiberContext)) != S_OK)
  847. {
  848. if (Verbose)
  849. {
  850. ErrOut("Unable to convert context to canonical form\n");
  851. }
  852. return Status;
  853. }
  854. if (Verbose)
  855. {
  856. dprintf("Fiber at %s Fiber data: %08X\n",
  857. FormatMachineAddr64(this, FiberBase),
  858. Fiber.FiberData);
  859. dprintf(" Stack base: %08X Stack limit: %08X\n",
  860. Fiber.StackBase,
  861. Fiber.StackLimit);
  862. }
  863. return S_OK;
  864. }
  865. HRESULT
  866. X86MachineInfo::GetContextFromTrapFrame(ULONG64 TrapBase,
  867. PCROSS_PLATFORM_CONTEXT Context,
  868. BOOL Verbose)
  869. {
  870. HRESULT Status;
  871. X86_KTRAP_FRAME Trap;
  872. if ((Status = m_Target->
  873. ReadAllVirtual(m_Target->m_ProcessHead,
  874. TrapBase, &Trap, sizeof(Trap))) != S_OK)
  875. {
  876. if (Verbose)
  877. {
  878. ErrOut("Unable to read trap frame at %s\n",
  879. FormatMachineAddr64(this, TrapBase));
  880. }
  881. return Status;
  882. }
  883. ZeroMemory(Context, sizeof(*Context));
  884. if ((Trap.SegCs & 1) || X86_IS_VM86(Trap.EFlags))
  885. {
  886. Context->X86Nt5Context.Esp = Trap.HardwareEsp;
  887. }
  888. else
  889. {
  890. Context->X86Nt5Context.Esp = (ULONG)TrapBase +
  891. FIELD_OFFSET(X86_KTRAP_FRAME, HardwareEsp);
  892. }
  893. if (X86_IS_VM86(Trap.EFlags))
  894. {
  895. Context->X86Nt5Context.SegSs =
  896. (USHORT)(Trap.HardwareSegSs & 0xffff);
  897. }
  898. else if ((Trap.SegCs & X86_MODE_MASK) != 0 /*KernelMode*/)
  899. {
  900. //
  901. // It's user mode. The HardwareSegSs contains R3 data selector.
  902. //
  903. Context->X86Nt5Context.SegSs =
  904. (USHORT)(Trap.HardwareSegSs | 3) & 0xffff;
  905. }
  906. else
  907. {
  908. Context->X86Nt5Context.SegSs = m_Target->m_KdDebuggerData.GdtR0Data;
  909. }
  910. Context->X86Nt5Context.SegGs = Trap.SegGs & 0xffff;
  911. Context->X86Nt5Context.SegFs = Trap.SegFs & 0xffff;
  912. Context->X86Nt5Context.SegEs = Trap.SegEs & 0xffff;
  913. Context->X86Nt5Context.SegDs = Trap.SegDs & 0xffff;
  914. Context->X86Nt5Context.SegCs = Trap.SegCs & 0xffff;
  915. Context->X86Nt5Context.Eip = Trap.Eip;
  916. Context->X86Nt5Context.Ebp = Trap.Ebp;
  917. Context->X86Nt5Context.Eax = Trap.Eax;
  918. Context->X86Nt5Context.Ebx = Trap.Ebx;
  919. Context->X86Nt5Context.Ecx = Trap.Ecx;
  920. Context->X86Nt5Context.Edx = Trap.Edx;
  921. Context->X86Nt5Context.Edi = Trap.Edi;
  922. Context->X86Nt5Context.Esi = Trap.Esi;
  923. Context->X86Nt5Context.EFlags = Trap.EFlags;
  924. return Status;
  925. }
  926. HRESULT
  927. X86MachineInfo::GetContextFromTaskSegment(ULONG64 TssBase,
  928. PCROSS_PLATFORM_CONTEXT Context,
  929. BOOL Verbose)
  930. {
  931. HRESULT Status;
  932. X86_KTSS Tss;
  933. if ((Status = m_Target->
  934. ReadAllVirtual(m_Target->m_ProcessHead,
  935. TssBase, &Tss, sizeof(Tss))) != S_OK)
  936. {
  937. if (Verbose)
  938. {
  939. ErrOut("Unable to read TSS at %s\n",
  940. FormatMachineAddr64(this, TssBase));
  941. }
  942. return Status;
  943. }
  944. ZeroMemory(Context, sizeof(*Context));
  945. if (X86_IS_VM86(Tss.EFlags))
  946. {
  947. Context->X86Nt5Context.SegSs = (USHORT)(Tss.Ss & 0xffff);
  948. }
  949. else if ((Tss.Cs & X86_MODE_MASK) != 0)
  950. {
  951. //
  952. // It's user mode.
  953. // The HardwareSegSs contains R3 data selector.
  954. //
  955. Context->X86Nt5Context.SegSs =
  956. (USHORT)(Tss.Ss | 3) & 0xffff;
  957. }
  958. else
  959. {
  960. Context->X86Nt5Context.SegSs = m_Target->m_KdDebuggerData.GdtR0Data;
  961. }
  962. Context->X86Nt5Context.SegGs = Tss.Gs & 0xffff;
  963. Context->X86Nt5Context.SegFs = Tss.Fs & 0xffff;
  964. Context->X86Nt5Context.SegEs = Tss.Es & 0xffff;
  965. Context->X86Nt5Context.SegDs = Tss.Ds & 0xffff;
  966. Context->X86Nt5Context.SegCs = Tss.Cs & 0xffff;
  967. Context->X86Nt5Context.Esp = Tss.Esp;
  968. Context->X86Nt5Context.Eip = Tss.Eip;
  969. Context->X86Nt5Context.Ebp = Tss.Ebp;
  970. Context->X86Nt5Context.Eax = Tss.Eax;
  971. Context->X86Nt5Context.Ebx = Tss.Ebx;
  972. Context->X86Nt5Context.Ecx = Tss.Ecx;
  973. Context->X86Nt5Context.Edx = Tss.Edx;
  974. Context->X86Nt5Context.Edi = Tss.Edi;
  975. Context->X86Nt5Context.Esi = Tss.Esi;
  976. Context->X86Nt5Context.EFlags = Tss.EFlags;
  977. return Status;
  978. }
  979. void
  980. X86MachineInfo::GetScopeFrameFromContext(PCROSS_PLATFORM_CONTEXT Context,
  981. PDEBUG_STACK_FRAME ScopeFrame)
  982. {
  983. ZeroMemory(ScopeFrame, sizeof(*ScopeFrame));
  984. StackTrace(NULL,
  985. EXTEND64(Context->X86Context.Ebp),
  986. EXTEND64(Context->X86Context.Esp),
  987. EXTEND64(Context->X86Context.Eip),
  988. STACK_NO_DEFAULT, ScopeFrame, 1, 0, 0, 0);
  989. }
  990. void
  991. X86MachineInfo::GetStackDefaultsFromContext(PCROSS_PLATFORM_CONTEXT Context,
  992. LPADDRESS64 Instr,
  993. LPADDRESS64 Stack,
  994. LPADDRESS64 Frame)
  995. {
  996. //
  997. // On x86 we want to fill out the addresses so that
  998. // dbghelp doesn't have to deal with segmentation and
  999. // such.
  1000. //
  1001. // At least, that's the theory, but most of the
  1002. // segmented stack support has been ripped out and
  1003. // this code doesn't really do much useful.
  1004. //
  1005. Instr->Mode = AddrModeFlat;
  1006. Instr->Segment = (USHORT)(Context->X86Nt5Context.SegCs & 0xffff);
  1007. Instr->Offset = EXTEND64(Context->X86Nt5Context.Eip);
  1008. Stack->Mode = AddrModeFlat;
  1009. Stack->Segment = (USHORT)(Context->X86Nt5Context.SegSs & 0xffff);
  1010. Stack->Offset = EXTEND64(Context->X86Nt5Context.Esp);
  1011. Frame->Mode = AddrModeFlat;
  1012. Frame->Segment = (USHORT)(Context->X86Nt5Context.SegSs & 0xffff);
  1013. Frame->Offset = EXTEND64(Context->X86Nt5Context.Ebp);
  1014. }
  1015. HRESULT
  1016. X86MachineInfo::GetScopeFrameRegister(ULONG Reg,
  1017. PDEBUG_STACK_FRAME ScopeFrame,
  1018. PULONG64 Value)
  1019. {
  1020. HRESULT Status;
  1021. REGVAL RegVal;
  1022. switch(Reg)
  1023. {
  1024. case X86_ESP:
  1025. *Value = ScopeFrame->StackOffset;
  1026. return S_OK;
  1027. case X86_EBP:
  1028. if (ScopeFrame->FuncTableEntry)
  1029. {
  1030. PFPO_DATA FpoData = (PFPO_DATA)ScopeFrame->FuncTableEntry;
  1031. if (FpoData->cbFrame == FRAME_FPO)
  1032. {
  1033. //
  1034. // Get EBP from FPO data, if available
  1035. //
  1036. if (SAVE_EBP(ScopeFrame) &&
  1037. (FpoData->fUseBP ||
  1038. ((SAVE_EBP(ScopeFrame) >> 32) == 0xEB)))
  1039. {
  1040. // Either the frame saved EBP or we saved it
  1041. // during stackwalk along with tag 0xEB on upper 32 bits.
  1042. *Value = EXTEND64(SAVE_EBP(ScopeFrame));
  1043. return S_OK;
  1044. }
  1045. else
  1046. {
  1047. //
  1048. // Guess the ebp value, in most cases for FPO frames its
  1049. // a DWORD off frameoffset
  1050. //
  1051. *Value = ScopeFrame->FrameOffset + sizeof(DWORD);
  1052. return S_OK;
  1053. }
  1054. }
  1055. }
  1056. *Value = ScopeFrame->FrameOffset;
  1057. return S_OK;
  1058. default:
  1059. RegVal.I64 = 0;
  1060. if ((Status = FullGetVal(Reg, &RegVal)) != S_OK)
  1061. {
  1062. return Status;
  1063. }
  1064. *Value = RegVal.I64;
  1065. return S_OK;
  1066. }
  1067. }
  1068. HRESULT
  1069. X86MachineInfo::SetScopeFrameRegister(ULONG Reg,
  1070. PDEBUG_STACK_FRAME ScopeFrame,
  1071. ULONG64 Value)
  1072. {
  1073. REGVAL RegVal;
  1074. switch(Reg)
  1075. {
  1076. case X86_ESP:
  1077. ScopeFrame->StackOffset = Value;
  1078. return S_OK;
  1079. case X86_EBP:
  1080. // Don't allow EBP updating due to the FPO complexities.
  1081. return E_INVALIDARG;
  1082. default:
  1083. RegVal.Type = GetType(Reg);
  1084. RegVal.I64 = Value;
  1085. return FullSetVal(Reg, &RegVal);
  1086. }
  1087. }
  1088. void
  1089. X86MachineInfo::SanitizeMemoryContext(PCROSS_PLATFORM_CONTEXT Context)
  1090. {
  1091. if (Context->X86Context.EFlags & X86_EFLAGS_V86_MASK)
  1092. {
  1093. Context->X86Context.SegSs &= 0xffff;
  1094. }
  1095. else if (Context->X86Context.SegCs & X86_MODE_MASK)
  1096. {
  1097. //
  1098. // It's user mode. The HardwareSegSs contains R3 data selector.
  1099. //
  1100. Context->X86Context.SegSs =
  1101. (USHORT)(Context->X86Context.SegSs | X86_RPL_MASK) & 0xffff;
  1102. }
  1103. else
  1104. {
  1105. Context->X86Context.SegSs = m_Target->m_KdDebuggerData.GdtR0Data;
  1106. }
  1107. }
  1108. HRESULT
  1109. X86MachineInfo::GetExdiContext(IUnknown* Exdi, PEXDI_CONTEXT Context,
  1110. EXDI_CONTEXT_TYPE CtxType)
  1111. {
  1112. // Always ask for everything.
  1113. switch(CtxType)
  1114. {
  1115. case EXDI_CTX_X86:
  1116. Context->X86Context.RegGroupSelection.fSegmentRegs = TRUE;
  1117. Context->X86Context.RegGroupSelection.fControlRegs = TRUE;
  1118. Context->X86Context.RegGroupSelection.fIntegerRegs = TRUE;
  1119. Context->X86Context.RegGroupSelection.fFloatingPointRegs = TRUE;
  1120. Context->X86Context.RegGroupSelection.fDebugRegs = TRUE;
  1121. return ((IeXdiX86Context*)Exdi)->GetContext(&Context->X86Context);
  1122. case EXDI_CTX_X86_EX:
  1123. Context->X86ExContext.RegGroupSelection.fSegmentRegs = TRUE;
  1124. Context->X86ExContext.RegGroupSelection.fControlRegs = TRUE;
  1125. Context->X86ExContext.RegGroupSelection.fIntegerRegs = TRUE;
  1126. Context->X86ExContext.RegGroupSelection.fFloatingPointRegs = TRUE;
  1127. Context->X86ExContext.RegGroupSelection.fDebugRegs = TRUE;
  1128. Context->X86ExContext.RegGroupSelection.fSegmentDescriptors = TRUE;
  1129. Context->X86ExContext.RegGroupSelection.fSSERegisters = TRUE;
  1130. Context->X86ExContext.RegGroupSelection.fSystemRegisters = TRUE;
  1131. return ((IeXdiX86ExContext*)Exdi)->GetContext(&Context->X86ExContext);
  1132. default:
  1133. return E_INVALIDARG;
  1134. }
  1135. }
  1136. HRESULT
  1137. X86MachineInfo::SetExdiContext(IUnknown* Exdi, PEXDI_CONTEXT Context,
  1138. EXDI_CONTEXT_TYPE CtxType)
  1139. {
  1140. // Don't change the existing group selections on the assumption
  1141. // that there was a full get prior to any modifications so
  1142. // all groups are valid.
  1143. switch(CtxType)
  1144. {
  1145. case EXDI_CTX_X86:
  1146. return ((IeXdiX86Context*)Exdi)->SetContext(Context->X86Context);
  1147. case EXDI_CTX_X86_EX:
  1148. return ((IeXdiX86ExContext*)Exdi)->SetContext(Context->X86ExContext);
  1149. default:
  1150. return E_INVALIDARG;
  1151. }
  1152. }
  1153. void
  1154. X86MachineInfo::ConvertExdiContextFromContext(PCROSS_PLATFORM_CONTEXT Context,
  1155. PEXDI_CONTEXT ExdiContext,
  1156. EXDI_CONTEXT_TYPE CtxType)
  1157. {
  1158. switch(CtxType)
  1159. {
  1160. case EXDI_CTX_X86:
  1161. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_SEGMENTS)
  1162. {
  1163. ExdiContext->X86Context.SegGs =
  1164. (USHORT)Context->X86Nt5Context.SegGs;
  1165. ExdiContext->X86Context.SegFs =
  1166. (USHORT)Context->X86Nt5Context.SegFs;
  1167. ExdiContext->X86Context.SegEs =
  1168. (USHORT)Context->X86Nt5Context.SegEs;
  1169. ExdiContext->X86Context.SegDs =
  1170. (USHORT)Context->X86Nt5Context.SegDs;
  1171. }
  1172. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_CONTROL)
  1173. {
  1174. ExdiContext->X86Context.Ebp = Context->X86Nt5Context.Ebp;
  1175. ExdiContext->X86Context.Eip = Context->X86Nt5Context.Eip;
  1176. ExdiContext->X86Context.SegCs =
  1177. (USHORT)Context->X86Nt5Context.SegCs;
  1178. ExdiContext->X86Context.EFlags = Context->X86Nt5Context.EFlags;
  1179. ExdiContext->X86Context.Esp = Context->X86Nt5Context.Esp;
  1180. ExdiContext->X86Context.SegSs =
  1181. (USHORT)Context->X86Nt5Context.SegSs;
  1182. }
  1183. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_INTEGER)
  1184. {
  1185. ExdiContext->X86Context.Eax = Context->X86Nt5Context.Eax;
  1186. ExdiContext->X86Context.Ebx = Context->X86Nt5Context.Ebx;
  1187. ExdiContext->X86Context.Ecx = Context->X86Nt5Context.Ecx;
  1188. ExdiContext->X86Context.Edx = Context->X86Nt5Context.Edx;
  1189. ExdiContext->X86Context.Esi = Context->X86Nt5Context.Esi;
  1190. ExdiContext->X86Context.Edi = Context->X86Nt5Context.Edi;
  1191. }
  1192. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_FLOATING_POINT)
  1193. {
  1194. C_ASSERT(sizeof(X86_FLOATING_SAVE_AREA) ==
  1195. FIELD_OFFSET(CONTEXT_X86, Dr0) -
  1196. FIELD_OFFSET(CONTEXT_X86, ControlWord));
  1197. memcpy(&ExdiContext->X86Context.ControlWord,
  1198. &Context->X86Nt5Context.FloatSave,
  1199. sizeof(X86_FLOATING_SAVE_AREA));
  1200. }
  1201. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_DEBUG_REGISTERS)
  1202. {
  1203. ExdiContext->X86Context.Dr0 = Context->X86Nt5Context.Dr0;
  1204. ExdiContext->X86Context.Dr1 = Context->X86Nt5Context.Dr1;
  1205. ExdiContext->X86Context.Dr2 = Context->X86Nt5Context.Dr2;
  1206. ExdiContext->X86Context.Dr3 = Context->X86Nt5Context.Dr3;
  1207. ExdiContext->X86Context.Dr6 = Context->X86Nt5Context.Dr6;
  1208. ExdiContext->X86Context.Dr7 = Context->X86Nt5Context.Dr7;
  1209. }
  1210. break;
  1211. case EXDI_CTX_X86_EX:
  1212. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_SEGMENTS)
  1213. {
  1214. ExdiContext->X86ExContext.SegGs =
  1215. (USHORT)Context->X86Nt5Context.SegGs;
  1216. ExdiContext->X86ExContext.SegFs =
  1217. (USHORT)Context->X86Nt5Context.SegFs;
  1218. ExdiContext->X86ExContext.SegEs =
  1219. (USHORT)Context->X86Nt5Context.SegEs;
  1220. ExdiContext->X86ExContext.SegDs =
  1221. (USHORT)Context->X86Nt5Context.SegDs;
  1222. }
  1223. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_CONTROL)
  1224. {
  1225. ExdiContext->X86ExContext.Ebp = Context->X86Nt5Context.Ebp;
  1226. ExdiContext->X86ExContext.Eip = Context->X86Nt5Context.Eip;
  1227. ExdiContext->X86ExContext.SegCs =
  1228. (USHORT)Context->X86Nt5Context.SegCs;
  1229. ExdiContext->X86ExContext.EFlags = Context->X86Nt5Context.EFlags;
  1230. ExdiContext->X86ExContext.Esp = Context->X86Nt5Context.Esp;
  1231. ExdiContext->X86ExContext.SegSs =
  1232. (USHORT)Context->X86Nt5Context.SegSs;
  1233. }
  1234. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_INTEGER)
  1235. {
  1236. ExdiContext->X86ExContext.Eax = Context->X86Nt5Context.Eax;
  1237. ExdiContext->X86ExContext.Ebx = Context->X86Nt5Context.Ebx;
  1238. ExdiContext->X86ExContext.Ecx = Context->X86Nt5Context.Ecx;
  1239. ExdiContext->X86ExContext.Edx = Context->X86Nt5Context.Edx;
  1240. ExdiContext->X86ExContext.Esi = Context->X86Nt5Context.Esi;
  1241. ExdiContext->X86ExContext.Edi = Context->X86Nt5Context.Edi;
  1242. }
  1243. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_FLOATING_POINT)
  1244. {
  1245. C_ASSERT(sizeof(X86_FLOATING_SAVE_AREA) ==
  1246. FIELD_OFFSET(CONTEXT_X86_EX, Dr0) -
  1247. FIELD_OFFSET(CONTEXT_X86_EX, ControlWord));
  1248. memcpy(&ExdiContext->X86ExContext.ControlWord,
  1249. &Context->X86Nt5Context.FloatSave,
  1250. sizeof(X86_FLOATING_SAVE_AREA));
  1251. }
  1252. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_DEBUG_REGISTERS)
  1253. {
  1254. ExdiContext->X86ExContext.Dr0 = Context->X86Nt5Context.Dr0;
  1255. ExdiContext->X86ExContext.Dr1 = Context->X86Nt5Context.Dr1;
  1256. ExdiContext->X86ExContext.Dr2 = Context->X86Nt5Context.Dr2;
  1257. ExdiContext->X86ExContext.Dr3 = Context->X86Nt5Context.Dr3;
  1258. ExdiContext->X86ExContext.Dr6 = Context->X86Nt5Context.Dr6;
  1259. ExdiContext->X86ExContext.Dr7 = Context->X86Nt5Context.Dr7;
  1260. }
  1261. if (Context->X86Nt5Context.ContextFlags &
  1262. VDMCONTEXT_EXTENDED_REGISTERS)
  1263. {
  1264. C_ASSERT(X86_SIZE_OF_FX_REGISTERS ==
  1265. sizeof(ExdiContext->X86ExContext.Sse));
  1266. memcpy(ExdiContext->X86ExContext.Sse,
  1267. Context->X86Nt5Context.FxSave.Reserved3,
  1268. X86_SIZE_OF_FX_REGISTERS);
  1269. ExdiContext->X86ExContext.Mxcsr =
  1270. Context->X86Nt5Context.FxSave.MXCsr;
  1271. }
  1272. break;
  1273. default:
  1274. DBG_ASSERT(FALSE);
  1275. break;
  1276. }
  1277. }
  1278. void
  1279. X86MachineInfo::ConvertExdiContextToContext(PEXDI_CONTEXT ExdiContext,
  1280. EXDI_CONTEXT_TYPE CtxType,
  1281. PCROSS_PLATFORM_CONTEXT Context)
  1282. {
  1283. switch(CtxType)
  1284. {
  1285. case EXDI_CTX_X86:
  1286. Context->X86Nt5Context.SegCs = ExdiContext->X86Context.SegCs;
  1287. Context->X86Nt5Context.SegSs = ExdiContext->X86Context.SegSs;
  1288. Context->X86Nt5Context.SegGs = ExdiContext->X86Context.SegGs;
  1289. Context->X86Nt5Context.SegFs = ExdiContext->X86Context.SegFs;
  1290. Context->X86Nt5Context.SegEs = ExdiContext->X86Context.SegEs;
  1291. Context->X86Nt5Context.SegDs = ExdiContext->X86Context.SegDs;
  1292. Context->X86Nt5Context.EFlags = ExdiContext->X86Context.EFlags;
  1293. Context->X86Nt5Context.Ebp = ExdiContext->X86Context.Ebp;
  1294. Context->X86Nt5Context.Eip = ExdiContext->X86Context.Eip;
  1295. Context->X86Nt5Context.Esp = ExdiContext->X86Context.Esp;
  1296. Context->X86Nt5Context.Eax = ExdiContext->X86Context.Eax;
  1297. Context->X86Nt5Context.Ebx = ExdiContext->X86Context.Ebx;
  1298. Context->X86Nt5Context.Ecx = ExdiContext->X86Context.Ecx;
  1299. Context->X86Nt5Context.Edx = ExdiContext->X86Context.Edx;
  1300. Context->X86Nt5Context.Esi = ExdiContext->X86Context.Esi;
  1301. Context->X86Nt5Context.Edi = ExdiContext->X86Context.Edi;
  1302. C_ASSERT(sizeof(X86_FLOATING_SAVE_AREA) ==
  1303. FIELD_OFFSET(CONTEXT_X86, Dr0) -
  1304. FIELD_OFFSET(CONTEXT_X86, ControlWord));
  1305. memcpy(&Context->X86Nt5Context.FloatSave,
  1306. &ExdiContext->X86Context.ControlWord,
  1307. sizeof(X86_FLOATING_SAVE_AREA));
  1308. Context->X86Nt5Context.Dr0 = ExdiContext->X86Context.Dr0;
  1309. Context->X86Nt5Context.Dr1 = ExdiContext->X86Context.Dr1;
  1310. Context->X86Nt5Context.Dr2 = ExdiContext->X86Context.Dr2;
  1311. Context->X86Nt5Context.Dr3 = ExdiContext->X86Context.Dr3;
  1312. Context->X86Nt5Context.Dr6 = ExdiContext->X86Context.Dr6;
  1313. Context->X86Nt5Context.Dr7 = ExdiContext->X86Context.Dr7;
  1314. break;
  1315. case EXDI_CTX_X86_EX:
  1316. Context->X86Nt5Context.SegCs = ExdiContext->X86ExContext.SegCs;
  1317. Context->X86Nt5Context.SegSs = ExdiContext->X86ExContext.SegSs;
  1318. Context->X86Nt5Context.SegGs = ExdiContext->X86ExContext.SegGs;
  1319. Context->X86Nt5Context.SegFs = ExdiContext->X86ExContext.SegFs;
  1320. Context->X86Nt5Context.SegEs = ExdiContext->X86ExContext.SegEs;
  1321. Context->X86Nt5Context.SegDs = ExdiContext->X86ExContext.SegDs;
  1322. Context->X86Nt5Context.EFlags = ExdiContext->X86ExContext.EFlags;
  1323. Context->X86Nt5Context.Ebp = ExdiContext->X86ExContext.Ebp;
  1324. Context->X86Nt5Context.Eip = ExdiContext->X86ExContext.Eip;
  1325. Context->X86Nt5Context.Esp = ExdiContext->X86ExContext.Esp;
  1326. Context->X86Nt5Context.Eax = ExdiContext->X86ExContext.Eax;
  1327. Context->X86Nt5Context.Ebx = ExdiContext->X86ExContext.Ebx;
  1328. Context->X86Nt5Context.Ecx = ExdiContext->X86ExContext.Ecx;
  1329. Context->X86Nt5Context.Edx = ExdiContext->X86ExContext.Edx;
  1330. Context->X86Nt5Context.Esi = ExdiContext->X86ExContext.Esi;
  1331. Context->X86Nt5Context.Edi = ExdiContext->X86ExContext.Edi;
  1332. C_ASSERT(sizeof(X86_FLOATING_SAVE_AREA) ==
  1333. FIELD_OFFSET(CONTEXT_X86, Dr0) -
  1334. FIELD_OFFSET(CONTEXT_X86, ControlWord));
  1335. memcpy(&Context->X86Nt5Context.FloatSave,
  1336. &ExdiContext->X86ExContext.ControlWord,
  1337. sizeof(X86_FLOATING_SAVE_AREA));
  1338. Context->X86Nt5Context.Dr0 = ExdiContext->X86ExContext.Dr0;
  1339. Context->X86Nt5Context.Dr1 = ExdiContext->X86ExContext.Dr1;
  1340. Context->X86Nt5Context.Dr2 = ExdiContext->X86ExContext.Dr2;
  1341. Context->X86Nt5Context.Dr3 = ExdiContext->X86ExContext.Dr3;
  1342. Context->X86Nt5Context.Dr6 = ExdiContext->X86ExContext.Dr6;
  1343. Context->X86Nt5Context.Dr7 = ExdiContext->X86ExContext.Dr7;
  1344. C_ASSERT(X86_SIZE_OF_FX_REGISTERS ==
  1345. sizeof(ExdiContext->X86ExContext.Sse));
  1346. memcpy(Context->X86Nt5Context.FxSave.Reserved3,
  1347. ExdiContext->X86ExContext.Sse,
  1348. X86_SIZE_OF_FX_REGISTERS);
  1349. Context->X86Nt5Context.FxSave.MXCsr =
  1350. ExdiContext->X86ExContext.Mxcsr;
  1351. break;
  1352. default:
  1353. DBG_ASSERT(FALSE);
  1354. break;
  1355. }
  1356. }
  1357. void
  1358. X86MachineInfo::ConvertExdiContextToSegDescs(PEXDI_CONTEXT ExdiContext,
  1359. EXDI_CONTEXT_TYPE CtxType,
  1360. ULONG Start, ULONG Count,
  1361. PDESCRIPTOR64 Descs)
  1362. {
  1363. switch(CtxType)
  1364. {
  1365. case EXDI_CTX_X86:
  1366. // The basic x86 context doesn't have descriptor
  1367. // state so just fake something up for basic boot state.
  1368. while (Count-- > 0)
  1369. {
  1370. ULONG Type;
  1371. if (Start == SEGREG_CODE)
  1372. {
  1373. Descs->Base = EXTEND64(0xffff0000);
  1374. Type = 0x13;
  1375. }
  1376. else
  1377. {
  1378. Descs->Base = 0;
  1379. Type = 0x1b;
  1380. }
  1381. Descs->Limit = 0xfffff;
  1382. Descs->Flags = X86_DESC_PRESENT | X86_DESC_DEFAULT_BIG | Type;
  1383. Descs++;
  1384. Start++;
  1385. }
  1386. break;
  1387. case EXDI_CTX_X86_EX:
  1388. while (Count-- > 0)
  1389. {
  1390. X86_SEG_DESC_INFO* Desc;
  1391. switch(Start)
  1392. {
  1393. case SEGREG_CODE:
  1394. Desc = &ExdiContext->X86ExContext.DescriptorCs;
  1395. break;
  1396. case SEGREG_DATA:
  1397. Desc = &ExdiContext->X86ExContext.DescriptorDs;
  1398. break;
  1399. case SEGREG_STACK:
  1400. Desc = &ExdiContext->X86ExContext.DescriptorSs;
  1401. break;
  1402. case SEGREG_ES:
  1403. Desc = &ExdiContext->X86ExContext.DescriptorEs;
  1404. break;
  1405. case SEGREG_FS:
  1406. Desc = &ExdiContext->X86ExContext.DescriptorFs;
  1407. break;
  1408. case SEGREG_GS:
  1409. Desc = &ExdiContext->X86ExContext.DescriptorGs;
  1410. break;
  1411. case SEGREG_GDT:
  1412. Descs->Base = ExdiContext->X86ExContext.GdtBase;
  1413. Descs->Limit = ExdiContext->X86ExContext.GdtLimit;
  1414. Descs->Flags = X86_DESC_PRESENT;
  1415. Desc = NULL;
  1416. break;
  1417. case SEGREG_LDT:
  1418. Desc = &ExdiContext->X86ExContext.DescriptorLdtr;
  1419. break;
  1420. default:
  1421. Descs->Flags = SEGDESC_INVALID;
  1422. Desc = NULL;
  1423. break;
  1424. }
  1425. if (Desc != NULL)
  1426. {
  1427. Descs->Base = EXTEND64(Desc->Base);
  1428. Descs->Limit = Desc->Limit;
  1429. Descs->Flags =
  1430. ((Desc->Flags >> 4) & 0xf00) |
  1431. (Desc->Flags & 0xff);
  1432. }
  1433. Descs++;
  1434. Start++;
  1435. }
  1436. break;
  1437. default:
  1438. DBG_ASSERT(FALSE);
  1439. break;
  1440. }
  1441. }
  1442. void
  1443. X86MachineInfo::ConvertExdiContextFromSpecial
  1444. (PCROSS_PLATFORM_KSPECIAL_REGISTERS Special,
  1445. PEXDI_CONTEXT ExdiContext, EXDI_CONTEXT_TYPE CtxType)
  1446. {
  1447. switch(CtxType)
  1448. {
  1449. case EXDI_CTX_X86:
  1450. // No such information.
  1451. break;
  1452. case EXDI_CTX_X86_EX:
  1453. ExdiContext->X86ExContext.Cr0 = Special->X86Special.Cr0;
  1454. ExdiContext->X86ExContext.Cr2 = Special->X86Special.Cr2;
  1455. ExdiContext->X86ExContext.Cr3 = Special->X86Special.Cr3;
  1456. ExdiContext->X86ExContext.Cr4 = Special->X86Special.Cr4;
  1457. ExdiContext->X86ExContext.Dr0 = Special->X86Special.KernelDr0;
  1458. ExdiContext->X86ExContext.Dr1 = Special->X86Special.KernelDr1;
  1459. ExdiContext->X86ExContext.Dr2 = Special->X86Special.KernelDr2;
  1460. ExdiContext->X86ExContext.Dr3 = Special->X86Special.KernelDr3;
  1461. ExdiContext->X86ExContext.Dr6 = Special->X86Special.KernelDr6;
  1462. ExdiContext->X86ExContext.Dr7 = Special->X86Special.KernelDr7;
  1463. ExdiContext->X86ExContext.GdtLimit = Special->X86Special.Gdtr.Limit;
  1464. ExdiContext->X86ExContext.GdtBase = Special->X86Special.Gdtr.Base;
  1465. ExdiContext->X86ExContext.IdtLimit = Special->X86Special.Idtr.Limit;
  1466. ExdiContext->X86ExContext.IdtBase = Special->X86Special.Idtr.Base;
  1467. ExdiContext->X86ExContext.Tr = Special->X86Special.Tr;
  1468. ExdiContext->X86ExContext.Ldtr = Special->X86Special.Ldtr;
  1469. break;
  1470. default:
  1471. DBG_ASSERT(FALSE);
  1472. break;
  1473. }
  1474. }
  1475. void
  1476. X86MachineInfo::ConvertExdiContextToSpecial
  1477. (PEXDI_CONTEXT ExdiContext, EXDI_CONTEXT_TYPE CtxType,
  1478. PCROSS_PLATFORM_KSPECIAL_REGISTERS Special)
  1479. {
  1480. switch(CtxType)
  1481. {
  1482. case EXDI_CTX_X86:
  1483. // No such information.
  1484. break;
  1485. case EXDI_CTX_X86_EX:
  1486. Special->X86Special.Cr0 = ExdiContext->X86ExContext.Cr0;
  1487. Special->X86Special.Cr2 = ExdiContext->X86ExContext.Cr2;
  1488. Special->X86Special.Cr3 = ExdiContext->X86ExContext.Cr3;
  1489. Special->X86Special.Cr4 = ExdiContext->X86ExContext.Cr4;
  1490. Special->X86Special.KernelDr0 = ExdiContext->X86ExContext.Dr0;
  1491. Special->X86Special.KernelDr1 = ExdiContext->X86ExContext.Dr1;
  1492. Special->X86Special.KernelDr2 = ExdiContext->X86ExContext.Dr2;
  1493. Special->X86Special.KernelDr3 = ExdiContext->X86ExContext.Dr3;
  1494. Special->X86Special.KernelDr6 = ExdiContext->X86ExContext.Dr6;
  1495. Special->X86Special.KernelDr7 = ExdiContext->X86ExContext.Dr7;
  1496. Special->X86Special.Gdtr.Limit =
  1497. (USHORT)ExdiContext->X86ExContext.GdtLimit;
  1498. Special->X86Special.Gdtr.Base = ExdiContext->X86ExContext.GdtBase;
  1499. Special->X86Special.Idtr.Limit =
  1500. (USHORT)ExdiContext->X86ExContext.IdtLimit;
  1501. Special->X86Special.Idtr.Base = ExdiContext->X86ExContext.IdtBase;
  1502. Special->X86Special.Tr = (USHORT)ExdiContext->X86ExContext.Tr;
  1503. Special->X86Special.Ldtr = (USHORT)ExdiContext->X86ExContext.Ldtr;
  1504. break;
  1505. default:
  1506. DBG_ASSERT(FALSE);
  1507. break;
  1508. }
  1509. }
  1510. int
  1511. X86MachineInfo::GetType(ULONG Reg)
  1512. {
  1513. if (Reg >= X86_MM_FIRST && Reg <= X86_MM_LAST)
  1514. {
  1515. return REGVAL_INT64;
  1516. }
  1517. else if (Reg >= X86_XMM_FIRST && Reg <= X86_XMM_LAST)
  1518. {
  1519. return REGVAL_VECTOR128;
  1520. }
  1521. else if (Reg >= X86_ST_FIRST && Reg <= X86_ST_LAST)
  1522. {
  1523. return REGVAL_FLOAT10;
  1524. }
  1525. else if (Reg < X86_FLAGBASE)
  1526. {
  1527. return REGVAL_INT32;
  1528. }
  1529. else
  1530. {
  1531. return REGVAL_SUB32;
  1532. }
  1533. }
  1534. HRESULT
  1535. X86MachineInfo::GetVal(ULONG Reg, REGVAL* Val)
  1536. {
  1537. HRESULT Status;
  1538. if (Reg >= X86_MM_FIRST && Reg <= X86_MM_LAST)
  1539. {
  1540. Val->Type = REGVAL_VECTOR64;
  1541. GetMmxReg(Reg, Val);
  1542. }
  1543. else if (Reg >= X86_XMM_FIRST && Reg <= X86_XMM_LAST)
  1544. {
  1545. if ((Status = GetContextState(MCTX_CONTEXT)) != S_OK)
  1546. {
  1547. return Status;
  1548. }
  1549. Val->Type = REGVAL_VECTOR128;
  1550. memcpy(Val->Bytes, m_Context.X86Nt5Context.FxSave.Reserved3 +
  1551. (Reg - X86_XMM_FIRST) * 16, 16);
  1552. }
  1553. else if (Reg >= X86_ST_FIRST && Reg <= X86_ST_LAST)
  1554. {
  1555. Val->Type = REGVAL_FLOAT10;
  1556. GetFloatReg(Reg, Val);
  1557. }
  1558. else if (Reg < X86_FLAGBASE)
  1559. {
  1560. Val->Type = REGVAL_INT32;
  1561. Val->I64 = (ULONG64)(LONG64)(LONG)GetIntReg(Reg);
  1562. }
  1563. else
  1564. {
  1565. ErrOut("X86MachineInfo::GetVal: "
  1566. "unknown register %lx requested\n", Reg);
  1567. return E_INVALIDARG;
  1568. }
  1569. return S_OK;
  1570. }
  1571. HRESULT
  1572. X86MachineInfo::SetVal(ULONG Reg, REGVAL* Val)
  1573. {
  1574. HRESULT Status;
  1575. if (m_ContextIsReadOnly)
  1576. {
  1577. return HRESULT_FROM_WIN32(ERROR_WRITE_FAULT);
  1578. }
  1579. if (Reg >= X86_FLAGBASE)
  1580. {
  1581. return E_INVALIDARG;
  1582. }
  1583. // Optimize away some common cases where registers are
  1584. // set to their current value.
  1585. if ((m_ContextState >= MCTX_PC && Reg == X86_EIP &&
  1586. Val->I32 == m_Context.X86Nt5Context.Eip) ||
  1587. (((m_ContextState >= MCTX_DR67_REPORT &&
  1588. m_ContextState <= MCTX_REPORT) ||
  1589. m_ContextState >= MCTX_FULL) && Reg == X86_DR7 &&
  1590. Val->I32 == m_Context.X86Nt5Context.Dr7))
  1591. {
  1592. return S_OK;
  1593. }
  1594. if ((Status = GetContextState(MCTX_DIRTY)) != S_OK)
  1595. {
  1596. return Status;
  1597. }
  1598. if (Reg >= X86_MM_FIRST && Reg <= X86_MM_LAST)
  1599. {
  1600. *(ULONG64 UNALIGNED *)GetMmxRegSlot(Reg) = Val->I64;
  1601. goto Notify;
  1602. }
  1603. else if (Reg >= X86_XMM_FIRST && Reg <= X86_XMM_LAST)
  1604. {
  1605. memcpy(m_Context.X86Nt5Context.FxSave.Reserved3 +
  1606. (Reg - X86_XMM_FIRST) * 16, Val->Bytes, 16);
  1607. goto Notify;
  1608. }
  1609. else if (Reg >= X86_ST_FIRST && Reg <= X86_ST_LAST)
  1610. {
  1611. memcpy(m_Context.X86Nt5Context.FloatSave.RegisterArea +
  1612. 10 * (Reg - X86_ST_FIRST), Val->F10, sizeof(Val->F10));
  1613. goto Notify;
  1614. }
  1615. BOOL Recognized;
  1616. Recognized = TRUE;
  1617. switch(Reg)
  1618. {
  1619. case X86_GS:
  1620. m_Context.X86Nt5Context.SegGs = Val->I16;
  1621. m_SegRegDesc[SEGREG_GS].Flags = SEGDESC_INVALID;
  1622. break;
  1623. case X86_FS:
  1624. m_Context.X86Nt5Context.SegFs = Val->I16;
  1625. m_SegRegDesc[SEGREG_FS].Flags = SEGDESC_INVALID;
  1626. break;
  1627. case X86_ES:
  1628. m_Context.X86Nt5Context.SegEs = Val->I16;
  1629. m_SegRegDesc[SEGREG_ES].Flags = SEGDESC_INVALID;
  1630. break;
  1631. case X86_DS:
  1632. m_Context.X86Nt5Context.SegDs = Val->I16;
  1633. m_SegRegDesc[SEGREG_DATA].Flags = SEGDESC_INVALID;
  1634. break;
  1635. case X86_EDI:
  1636. m_Context.X86Nt5Context.Edi = Val->I32;
  1637. break;
  1638. case X86_ESI:
  1639. m_Context.X86Nt5Context.Esi = Val->I32;
  1640. break;
  1641. case X86_EBX:
  1642. m_Context.X86Nt5Context.Ebx = Val->I32;
  1643. break;
  1644. case X86_EDX:
  1645. m_Context.X86Nt5Context.Edx = Val->I32;
  1646. break;
  1647. case X86_ECX:
  1648. m_Context.X86Nt5Context.Ecx = Val->I32;
  1649. break;
  1650. case X86_EAX:
  1651. m_Context.X86Nt5Context.Eax = Val->I32;
  1652. break;
  1653. case X86_EBP:
  1654. m_Context.X86Nt5Context.Ebp = Val->I32;
  1655. break;
  1656. case X86_EIP:
  1657. m_Context.X86Nt5Context.Eip = Val->I32;
  1658. break;
  1659. case X86_CS:
  1660. m_Context.X86Nt5Context.SegCs = Val->I16;
  1661. m_SegRegDesc[SEGREG_CODE].Flags = SEGDESC_INVALID;
  1662. break;
  1663. case X86_EFL:
  1664. if (IS_KERNEL_TARGET(m_Target))
  1665. {
  1666. // leave TF clear
  1667. m_Context.X86Nt5Context.EFlags = Val->I32 & ~0x100;
  1668. }
  1669. else
  1670. {
  1671. // allow TF set
  1672. m_Context.X86Nt5Context.EFlags = Val->I32;
  1673. }
  1674. break;
  1675. case X86_ESP:
  1676. m_Context.X86Nt5Context.Esp = Val->I32;
  1677. break;
  1678. case X86_SS:
  1679. m_Context.X86Nt5Context.SegSs = Val->I16;
  1680. m_SegRegDesc[SEGREG_STACK].Flags = SEGDESC_INVALID;
  1681. break;
  1682. case X86_DR0:
  1683. m_Context.X86Nt5Context.Dr0 = Val->I32;
  1684. break;
  1685. case X86_DR1:
  1686. m_Context.X86Nt5Context.Dr1 = Val->I32;
  1687. break;
  1688. case X86_DR2:
  1689. m_Context.X86Nt5Context.Dr2 = Val->I32;
  1690. break;
  1691. case X86_DR3:
  1692. m_Context.X86Nt5Context.Dr3 = Val->I32;
  1693. break;
  1694. case X86_DR6:
  1695. m_Context.X86Nt5Context.Dr6 = Val->I32;
  1696. break;
  1697. case X86_DR7:
  1698. m_Context.X86Nt5Context.Dr7 = Val->I32;
  1699. break;
  1700. case X86_FPCW:
  1701. m_Context.X86Nt5Context.FloatSave.ControlWord =
  1702. (m_Context.X86Nt5Context.FloatSave.ControlWord & 0xffff0000) |
  1703. (Val->I32 & 0xffff);
  1704. break;
  1705. case X86_FPSW:
  1706. m_Context.X86Nt5Context.FloatSave.StatusWord =
  1707. (m_Context.X86Nt5Context.FloatSave.StatusWord & 0xffff0000) |
  1708. (Val->I32 & 0xffff);
  1709. break;
  1710. case X86_FPTW:
  1711. m_Context.X86Nt5Context.FloatSave.TagWord =
  1712. (m_Context.X86Nt5Context.FloatSave.TagWord & 0xffff0000) |
  1713. (Val->I32 & 0xffff);
  1714. break;
  1715. case X86_MXCSR:
  1716. m_Context.X86Nt5Context.FxSave.MXCsr = Val->I32;
  1717. break;
  1718. default:
  1719. Recognized = FALSE;
  1720. break;
  1721. }
  1722. if (!Recognized && IS_KERNEL_TARGET(m_Target))
  1723. {
  1724. Recognized = TRUE;
  1725. switch(Reg)
  1726. {
  1727. case X86_CR0:
  1728. m_Special.X86Special.Cr0 = Val->I32;
  1729. break;
  1730. case X86_CR2:
  1731. m_Special.X86Special.Cr2 = Val->I32;
  1732. break;
  1733. case X86_CR3:
  1734. m_Special.X86Special.Cr3 = Val->I32;
  1735. break;
  1736. case X86_CR4:
  1737. m_Special.X86Special.Cr4 = Val->I32;
  1738. break;
  1739. case X86_GDTR:
  1740. m_Special.X86Special.Gdtr.Base = Val->I32;
  1741. break;
  1742. case X86_GDTL:
  1743. m_Special.X86Special.Gdtr.Limit = (USHORT)Val->I32;
  1744. break;
  1745. case X86_IDTR:
  1746. m_Special.X86Special.Idtr.Base = Val->I32;
  1747. break;
  1748. case X86_IDTL:
  1749. m_Special.X86Special.Idtr.Limit = (USHORT)Val->I32;
  1750. break;
  1751. case X86_TR:
  1752. m_Special.X86Special.Tr = (USHORT)Val->I32;
  1753. break;
  1754. case X86_LDTR:
  1755. m_Special.X86Special.Ldtr = (USHORT)Val->I32;
  1756. break;
  1757. default:
  1758. Recognized = FALSE;
  1759. break;
  1760. }
  1761. }
  1762. if (!Recognized)
  1763. {
  1764. ErrOut("X86MachineInfo::SetVal: "
  1765. "unknown register %lx requested\n", Reg);
  1766. return E_INVALIDARG;
  1767. }
  1768. Notify:
  1769. NotifyChangeDebuggeeState(DEBUG_CDS_REGISTERS,
  1770. RegCountFromIndex(Reg));
  1771. return S_OK;
  1772. }
  1773. void
  1774. X86MachineInfo::GetPC (PADDR Address)
  1775. {
  1776. FormAddr(SEGREG_CODE, EXTEND64(GetIntReg(X86_EIP)),
  1777. FORM_CODE | FORM_SEGREG | X86_FORM_VM86(GetIntReg(X86_EFL)),
  1778. Address);
  1779. }
  1780. void
  1781. X86MachineInfo::SetPC (PADDR paddr)
  1782. {
  1783. REGVAL Val;
  1784. // We set the EIP to the offset (the non-translated value),
  1785. // because we may not be in "flat" mode !!!
  1786. Val.Type = REGVAL_INT32;
  1787. Val.I32 = (ULONG)Off(*paddr);
  1788. SetVal(X86_EIP, &Val);
  1789. }
  1790. void
  1791. X86MachineInfo::GetFP(PADDR Addr)
  1792. {
  1793. FormAddr(SEGREG_STACK, EXTEND64(GetIntReg(X86_EBP)),
  1794. FORM_SEGREG | X86_FORM_VM86(GetIntReg(X86_EFL)), Addr);
  1795. }
  1796. void
  1797. X86MachineInfo::GetSP(PADDR Addr)
  1798. {
  1799. FormAddr(SEGREG_STACK, EXTEND64(GetIntReg(X86_ESP)),
  1800. FORM_SEGREG | X86_FORM_VM86(GetIntReg(X86_EFL)), Addr);
  1801. }
  1802. ULONG64
  1803. X86MachineInfo::GetArgReg(void)
  1804. {
  1805. return (ULONG64)(LONG64)(LONG)GetIntReg(X86_EAX);
  1806. }
  1807. ULONG64
  1808. X86MachineInfo::GetRetReg(void)
  1809. {
  1810. return (ULONG64)(LONG64)(LONG)GetIntReg(X86_EAX);
  1811. }
  1812. ULONG
  1813. X86MachineInfo::GetSegRegNum(ULONG SegReg)
  1814. {
  1815. switch(SegReg)
  1816. {
  1817. case SEGREG_CODE:
  1818. return X86_CS;
  1819. case SEGREG_DATA:
  1820. return X86_DS;
  1821. case SEGREG_STACK:
  1822. return X86_SS;
  1823. case SEGREG_ES:
  1824. return X86_ES;
  1825. case SEGREG_FS:
  1826. return X86_FS;
  1827. case SEGREG_GS:
  1828. return X86_GS;
  1829. case SEGREG_LDT:
  1830. return X86_LDTR;
  1831. }
  1832. return 0;
  1833. }
  1834. HRESULT
  1835. X86MachineInfo::GetSegRegDescriptor(ULONG SegReg, PDESCRIPTOR64 Desc)
  1836. {
  1837. if (SegReg == SEGREG_GDT)
  1838. {
  1839. Desc->Base = EXTEND64(GetIntReg(X86_GDTR));
  1840. Desc->Limit = GetIntReg(X86_GDTL);
  1841. Desc->Flags = 0;
  1842. return S_OK;
  1843. }
  1844. // Check and see if we already have a cached descriptor.
  1845. if (m_SegRegDesc[SegReg].Flags != SEGDESC_INVALID)
  1846. {
  1847. *Desc = m_SegRegDesc[SegReg];
  1848. return S_OK;
  1849. }
  1850. HRESULT Status;
  1851. // Attempt to retrieve segment descriptors directly.
  1852. if ((Status = GetContextState(MCTX_FULL)) != S_OK)
  1853. {
  1854. return Status;
  1855. }
  1856. // Check and see if we now have a cached descriptor.
  1857. if (m_SegRegDesc[SegReg].Flags != SEGDESC_INVALID)
  1858. {
  1859. *Desc = m_SegRegDesc[SegReg];
  1860. return S_OK;
  1861. }
  1862. //
  1863. // Direct information is not available so look things up
  1864. // in the descriptor tables.
  1865. //
  1866. ULONG RegNum = GetSegRegNum(SegReg);
  1867. if (RegNum == 0)
  1868. {
  1869. return E_INVALIDARG;
  1870. }
  1871. // Do a quick sanity test to prevent bad values
  1872. // from causing problems.
  1873. ULONG Selector = GetIntReg(RegNum);
  1874. if (SegReg == SEGREG_LDT && (Selector & 4))
  1875. {
  1876. // The ldtr selector says that it's an LDT selector,
  1877. // which is invalid. An LDT selector should always
  1878. // reference the GDT.
  1879. ErrOut("Invalid LDTR contents: %04X\n", Selector);
  1880. return E_FAIL;
  1881. }
  1882. return m_Target->GetSelDescriptor(m_Target->m_RegContextThread,
  1883. this, Selector, Desc);
  1884. }
  1885. /*** X86OutputAll - output all registers and present instruction
  1886. *
  1887. * Purpose:
  1888. * To output the current register state of the processor.
  1889. * All integer registers are output as well as processor status
  1890. * registers. Important flag fields are also output separately.
  1891. *
  1892. * Input:
  1893. * Mask - Which information to display.
  1894. *
  1895. * Output:
  1896. * None.
  1897. *
  1898. *************************************************************************/
  1899. void
  1900. X86MachineInfo::OutputAll(ULONG Mask, ULONG OutMask)
  1901. {
  1902. if (GetContextState(MCTX_FULL) != S_OK)
  1903. {
  1904. ErrOut("Unable to retrieve register information\n");
  1905. return;
  1906. }
  1907. if (Mask & (REGALL_INT32 | REGALL_INT64))
  1908. {
  1909. ULONG efl;
  1910. MaskOut(OutMask, "eax=%08lx ebx=%08lx ecx=%08lx "
  1911. "edx=%08lx esi=%08lx edi=%08lx\n",
  1912. GetIntReg(X86_EAX),
  1913. GetIntReg(X86_EBX),
  1914. GetIntReg(X86_ECX),
  1915. GetIntReg(X86_EDX),
  1916. GetIntReg(X86_ESI),
  1917. GetIntReg(X86_EDI));
  1918. efl = GetIntReg(X86_EFL);
  1919. MaskOut(OutMask, "eip=%08lx esp=%08lx ebp=%08lx iopl=%1lx "
  1920. "%s %s %s %s %s %s %s %s %s %s\n",
  1921. GetIntReg(X86_EIP),
  1922. GetIntReg(X86_ESP),
  1923. GetIntReg(X86_EBP),
  1924. ((efl >> X86_SHIFT_FLAGIOPL) & X86_BIT_FLAGIOPL),
  1925. (efl & X86_BIT_FLAGVIP) ? "vip" : " ",
  1926. (efl & X86_BIT_FLAGVIF) ? "vif" : " ",
  1927. (efl & X86_BIT_FLAGOF) ? "ov" : "nv",
  1928. (efl & X86_BIT_FLAGDF) ? "dn" : "up",
  1929. (efl & X86_BIT_FLAGIF) ? "ei" : "di",
  1930. (efl & X86_BIT_FLAGSF) ? "ng" : "pl",
  1931. (efl & X86_BIT_FLAGZF) ? "zr" : "nz",
  1932. (efl & X86_BIT_FLAGAF) ? "ac" : "na",
  1933. (efl & X86_BIT_FLAGPF) ? "po" : "pe",
  1934. (efl & X86_BIT_FLAGCF) ? "cy" : "nc");
  1935. }
  1936. if (Mask & REGALL_SEGREG)
  1937. {
  1938. MaskOut(OutMask, "cs=%04lx ss=%04lx ds=%04lx es=%04lx fs=%04lx "
  1939. "gs=%04lx efl=%08lx\n",
  1940. GetIntReg(X86_CS),
  1941. GetIntReg(X86_SS),
  1942. GetIntReg(X86_DS),
  1943. GetIntReg(X86_ES),
  1944. GetIntReg(X86_FS),
  1945. GetIntReg(X86_GS),
  1946. GetIntReg(X86_EFL));
  1947. }
  1948. if (Mask & REGALL_FLOAT)
  1949. {
  1950. ULONG i;
  1951. REGVAL val;
  1952. char buf[32];
  1953. MaskOut(OutMask, "fpcw=%04X fpsw=%04X fptw=%04X\n",
  1954. GetIntReg(X86_FPCW),
  1955. GetIntReg(X86_FPSW),
  1956. GetIntReg(X86_FPTW));
  1957. for (i = X86_ST_FIRST; i <= X86_ST_LAST; i++)
  1958. {
  1959. GetFloatReg(i, &val);
  1960. _uldtoa((_ULDOUBLE *)&val.F10, sizeof(buf), buf);
  1961. MaskOut(OutMask, "st%d=%s ", i - X86_ST_FIRST, buf);
  1962. i++;
  1963. GetFloatReg(i, &val);
  1964. _uldtoa((_ULDOUBLE *)&val.F10, sizeof(buf), buf);
  1965. MaskOut(OutMask, "st%d=%s\n", i - X86_ST_FIRST, buf);
  1966. }
  1967. }
  1968. if (Mask & REGALL_MMXREG)
  1969. {
  1970. ULONG i;
  1971. REGVAL val;
  1972. for (i = X86_MM_FIRST; i <= X86_MM_LAST; i++)
  1973. {
  1974. GetMmxReg(i, &val);
  1975. MaskOut(OutMask, "mm%d=%08x%08x ",
  1976. i - X86_MM_FIRST,
  1977. val.I64Parts.High, val.I64Parts.Low);
  1978. i++;
  1979. GetMmxReg(i, &val);
  1980. MaskOut(OutMask, "mm%d=%08x%08x\n",
  1981. i - X86_MM_FIRST,
  1982. val.I64Parts.High, val.I64Parts.Low);
  1983. }
  1984. }
  1985. if (Mask & REGALL_XMMREG)
  1986. {
  1987. ULONG i;
  1988. REGVAL Val;
  1989. for (i = X86_XMM_FIRST; i <= X86_XMM_LAST; i++)
  1990. {
  1991. GetVal(i, &Val);
  1992. MaskOut(OutMask, "xmm%d=%hg %hg %hg %hg\n", i - X86_XMM_FIRST,
  1993. *(float *)&Val.Bytes[3 * sizeof(float)],
  1994. *(float *)&Val.Bytes[2 * sizeof(float)],
  1995. *(float *)&Val.Bytes[1 * sizeof(float)],
  1996. *(float *)&Val.Bytes[0 * sizeof(float)]);
  1997. }
  1998. }
  1999. if (Mask & REGALL_CREG)
  2000. {
  2001. MaskOut(OutMask, "cr0=%08lx cr2=%08lx cr3=%08lx\n",
  2002. GetIntReg(X86_CR0),
  2003. GetIntReg(X86_CR2),
  2004. GetIntReg(X86_CR3));
  2005. }
  2006. if (Mask & REGALL_DREG)
  2007. {
  2008. MaskOut(OutMask, "dr0=%08lx dr1=%08lx dr2=%08lx\n",
  2009. GetIntReg(X86_DR0),
  2010. GetIntReg(X86_DR1),
  2011. GetIntReg(X86_DR2));
  2012. MaskOut(OutMask, "dr3=%08lx dr6=%08lx dr7=%08lx",
  2013. GetIntReg(X86_DR3),
  2014. GetIntReg(X86_DR6),
  2015. GetIntReg(X86_DR7));
  2016. if (IS_USER_TARGET(m_Target))
  2017. {
  2018. MaskOut(OutMask, "\n");
  2019. }
  2020. else
  2021. {
  2022. MaskOut(OutMask, " cr4=%08lx\n", GetIntReg(X86_CR4));
  2023. }
  2024. }
  2025. if (Mask & REGALL_DESC)
  2026. {
  2027. MaskOut(OutMask, "gdtr=%08lx gdtl=%04lx idtr=%08lx idtl=%04lx "
  2028. "tr=%04lx ldtr=%04x\n",
  2029. GetIntReg(X86_GDTR),
  2030. GetIntReg(X86_GDTL),
  2031. GetIntReg(X86_IDTR),
  2032. GetIntReg(X86_IDTL),
  2033. GetIntReg(X86_TR),
  2034. GetIntReg(X86_LDTR));
  2035. }
  2036. }
  2037. HRESULT
  2038. X86MachineInfo::SetAndOutputTrapFrame(ULONG64 TrapBase,
  2039. PCROSS_PLATFORM_CONTEXT Context)
  2040. {
  2041. HRESULT Status;
  2042. X86_KTRAP_FRAME TrapContents;
  2043. if ((Status = m_Target->ReadAllVirtual(m_Target->m_ProcessHead,
  2044. TrapBase, &TrapContents,
  2045. sizeof(TrapContents))) != S_OK)
  2046. {
  2047. ErrOut("Unable to read trap frame at %s\n",
  2048. FormatMachineAddr64(this, TrapBase));
  2049. return Status;
  2050. }
  2051. //
  2052. // Check to see if Esp has been edited, and dump new value if it has
  2053. //
  2054. if ((!(TrapContents.EFlags & X86_EFLAGS_V86_MASK)) &&
  2055. ((TrapContents.SegCs & X86_MODE_MASK) == 0 /*KernelMode*/))
  2056. {
  2057. if ((TrapContents.SegCs & X86_FRAME_EDITED) == 0)
  2058. {
  2059. dprintf("ESP EDITED! New esp=%08lx\n", TrapContents.TempEsp);
  2060. }
  2061. }
  2062. dprintf("ErrCode = %08lx\n", TrapContents.ErrCode);
  2063. return SetAndOutputContext(Context, TRUE, REGALL_INT32 | REGALL_SEGREG);
  2064. }
  2065. HRESULT
  2066. X86MachineInfo::SetAndOutputTaskSegment(ULONG64 TssBase,
  2067. PCROSS_PLATFORM_CONTEXT Context,
  2068. BOOL Extended)
  2069. {
  2070. HRESULT Status;
  2071. X86_KTSS TSS;
  2072. ULONG i;
  2073. if ((Status = m_Target->ReadAllVirtual(m_Target->m_ProcessHead,
  2074. TssBase, &TSS,
  2075. sizeof(TSS))) != S_OK)
  2076. {
  2077. ErrOut("Unable to read Task State Segment from host address %s\n",
  2078. FormatMachineAddr64(this, TssBase));
  2079. return Status;
  2080. }
  2081. //
  2082. // Display it.
  2083. //
  2084. if (Extended)
  2085. {
  2086. dprintf("\nTask State Segment 0x%p\n\n", TssBase);
  2087. dprintf("Previous Task Link = %4x\n", TSS.Previous);
  2088. for (i = 0 ; i < X86_MAX_RING; i++)
  2089. {
  2090. dprintf("Esp%d = %8x SS%d = %4x\n",
  2091. i, TSS.Ring[i].Esp,
  2092. i, TSS.Ring[i].Ss & 0xffff);
  2093. }
  2094. dprintf("CR3 (PDBR) = %08x\n", TSS.Cr3);
  2095. dprintf("I/O Map Base Address = %4x, Debug Trap (T) = %s\n",
  2096. TSS.IoMapBase,
  2097. TSS.T == 0 ? "False" : "True");
  2098. dprintf("\nSaved General Purpose Registers\n\n");
  2099. }
  2100. return SetAndOutputContext(Context, TRUE, REGALL_INT32 | REGALL_SEGREG);
  2101. }
  2102. TRACEMODE
  2103. X86MachineInfo::GetTraceMode (void)
  2104. {
  2105. if (IS_KERNEL_TARGET(m_Target))
  2106. {
  2107. return m_TraceMode;
  2108. }
  2109. else
  2110. {
  2111. return ((GetIntReg(X86_EFL) & X86_BIT_FLAGTF) != 0) ?
  2112. TRACE_INSTRUCTION : TRACE_NONE;
  2113. }
  2114. }
  2115. void
  2116. X86MachineInfo::SetTraceMode (TRACEMODE Mode)
  2117. {
  2118. DBG_ASSERT(Mode == TRACE_NONE ||
  2119. Mode == TRACE_INSTRUCTION ||
  2120. (IS_KERNEL_TARGET(m_Target) && m_SupportsBranchTrace &&
  2121. Mode == TRACE_TAKEN_BRANCH));
  2122. if (IS_KERNEL_TARGET(m_Target))
  2123. {
  2124. m_TraceMode = Mode;
  2125. }
  2126. else
  2127. {
  2128. ULONG Efl = GetIntReg(X86_EFL);
  2129. switch (Mode)
  2130. {
  2131. case TRACE_NONE:
  2132. Efl &= ~X86_BIT_FLAGTF;
  2133. break;
  2134. case TRACE_INSTRUCTION:
  2135. Efl |= X86_BIT_FLAGTF;
  2136. break;
  2137. }
  2138. SetReg32(X86_EFL, Efl);
  2139. }
  2140. }
  2141. BOOL
  2142. X86MachineInfo::IsStepStatusSupported(ULONG Status)
  2143. {
  2144. switch(Status)
  2145. {
  2146. case DEBUG_STATUS_STEP_INTO:
  2147. case DEBUG_STATUS_STEP_OVER:
  2148. return TRUE;
  2149. case DEBUG_STATUS_STEP_BRANCH:
  2150. return IS_KERNEL_TARGET(m_Target) && m_SupportsBranchTrace;
  2151. default:
  2152. return FALSE;
  2153. }
  2154. }
  2155. void
  2156. X86MachineInfo::KdUpdateControlSet
  2157. (PDBGKD_ANY_CONTROL_SET ControlSet)
  2158. {
  2159. TRACEMODE TraceMode = GetTraceMode();
  2160. ULONG64 DebugCtlMsr;
  2161. ControlSet->X86ControlSet.TraceFlag = TraceMode != TRACE_NONE;
  2162. ControlSet->X86ControlSet.Dr7 = GetIntReg(X86_DR7);
  2163. // We assume that branch tracing is off by default so if
  2164. // we haven't turned branch tracing on there's no need
  2165. // to do a RMW cycle on the control MSR. This saves two
  2166. // protocol transactions per step.
  2167. // The processor turns off the branch-trace and branch-record
  2168. // flags on every debug trap. That's not quite good enough
  2169. // as we may need to go back to instruction tracing after an
  2170. // AV or non-debug trap.
  2171. if (TraceMode != TRACE_NONE &&
  2172. m_SupportsBranchTrace &&
  2173. (TraceMode == TRACE_TAKEN_BRANCH || m_ResetBranchTrace) &&
  2174. m_Target->ReadMsr(X86_MSR_DEBUG_CTL, &DebugCtlMsr) == S_OK)
  2175. {
  2176. if (TraceMode == TRACE_TAKEN_BRANCH)
  2177. {
  2178. DebugCtlMsr |= (X86_DEBUG_CTL_BRANCH_TRACE |
  2179. X86_DEBUG_CTL_LAST_BRANCH_RECORD);
  2180. m_ResetBranchTrace = TRUE;
  2181. }
  2182. else
  2183. {
  2184. DebugCtlMsr &= ~(X86_DEBUG_CTL_BRANCH_TRACE |
  2185. X86_DEBUG_CTL_LAST_BRANCH_RECORD);
  2186. m_ResetBranchTrace = FALSE;
  2187. }
  2188. m_Target->WriteMsr(X86_MSR_DEBUG_CTL, DebugCtlMsr);
  2189. }
  2190. BpOut("UpdateControlSet(%d) trace %d, DR7 %X\n",
  2191. m_Target->m_RegContextProcessor, ControlSet->X86ControlSet.TraceFlag,
  2192. ControlSet->X86ControlSet.Dr7);
  2193. if (!g_WatchFunctions.IsStarted() && g_WatchBeginCurFunc != 1)
  2194. {
  2195. ControlSet->X86ControlSet.CurrentSymbolStart = 0;
  2196. ControlSet->X86ControlSet.CurrentSymbolEnd = 0;
  2197. }
  2198. else
  2199. {
  2200. ControlSet->X86ControlSet.CurrentSymbolStart =
  2201. (ULONG)g_WatchBeginCurFunc;
  2202. ControlSet->X86ControlSet.CurrentSymbolEnd =
  2203. (ULONG)g_WatchEndCurFunc;
  2204. }
  2205. }
  2206. ULONG
  2207. X86MachineInfo::ExecutingMachine(void)
  2208. {
  2209. return IMAGE_FILE_MACHINE_I386;
  2210. }
  2211. HRESULT
  2212. X86MachineInfo::SetPageDirectory(ThreadInfo* Thread,
  2213. ULONG Idx, ULONG64 PageDir,
  2214. PULONG NextIdx)
  2215. {
  2216. HRESULT Status;
  2217. ULONG ValidMask;
  2218. // Figure out which bits will be valid in the value.
  2219. if (m_Target->m_KdDebuggerData.PaeEnabled)
  2220. {
  2221. ValidMask = X86_PDBR_MASK;
  2222. }
  2223. else
  2224. {
  2225. ValidMask = X86_VALID_PFN_MASK;
  2226. }
  2227. *NextIdx = PAGE_DIR_COUNT;
  2228. if (PageDir == 0)
  2229. {
  2230. if (m_Target->m_ActualSystemVersion > XBOX_SVER_START &&
  2231. m_Target->m_ActualSystemVersion < XBOX_SVER_END)
  2232. {
  2233. // XBox has only one page directory in CR3 for everything.
  2234. // The process doesn't have a dirbase entry.
  2235. PageDir = GetReg32(X86_CR3) & ValidMask;
  2236. if (PageDir == 0)
  2237. {
  2238. // Register retrieval failure.
  2239. return E_FAIL;
  2240. }
  2241. }
  2242. else
  2243. {
  2244. // Assume NT structures.
  2245. if ((Status = m_Target->ReadImplicitProcessInfoPointer
  2246. (Thread,
  2247. m_Target->m_KdDebuggerData.OffsetEprocessDirectoryTableBase,
  2248. &PageDir)) != S_OK)
  2249. {
  2250. return Status;
  2251. }
  2252. PageDir &= ValidMask;
  2253. }
  2254. if (m_Target->m_ImplicitProcessDataIsDefault &&
  2255. Thread == m_Target->m_RegContextThread &&
  2256. !IS_LOCAL_KERNEL_TARGET(m_Target))
  2257. {
  2258. // Verify that the process dirbase matches the CR3 setting
  2259. // as a sanity check.
  2260. ULONG Cr3 = GetReg32(X86_CR3) & ValidMask;
  2261. if (Cr3 && Cr3 != (ULONG)PageDir)
  2262. {
  2263. WarnOut("WARNING: Process directory table base %08X "
  2264. "doesn't match CR3 %08X\n",
  2265. (ULONG)PageDir, Cr3);
  2266. }
  2267. }
  2268. }
  2269. else
  2270. {
  2271. PageDir &= ValidMask;
  2272. }
  2273. // There is only one page directory so update all the slots.
  2274. m_PageDirectories[PAGE_DIR_USER] = PageDir;
  2275. m_PageDirectories[PAGE_DIR_SESSION] = PageDir;
  2276. m_PageDirectories[PAGE_DIR_KERNEL] = PageDir;
  2277. return S_OK;
  2278. }
  2279. #define X86_PAGE_FILE_INDEX(Entry) \
  2280. (((ULONG)(Entry) >> 1) & MAX_PAGING_FILE_MASK)
  2281. #define X86_PAGE_FILE_OFFSET(Entry) \
  2282. (((Entry) >> 12) << X86_PAGE_SHIFT)
  2283. HRESULT
  2284. X86MachineInfo::GetVirtualTranslationPhysicalOffsets(ThreadInfo* Thread,
  2285. ULONG64 Virt,
  2286. PULONG64 Offsets,
  2287. ULONG OffsetsSize,
  2288. PULONG Levels,
  2289. PULONG PfIndex,
  2290. PULONG64 LastVal)
  2291. {
  2292. ULONG64 Addr;
  2293. HRESULT Status;
  2294. *Levels = 0;
  2295. if (m_Translating)
  2296. {
  2297. return E_UNEXPECTED;
  2298. }
  2299. m_Translating = TRUE;
  2300. //
  2301. // throw away top 32 bits on X86.
  2302. //
  2303. Virt &= 0x00000000FFFFFFFF;
  2304. //
  2305. // Reset the page directory in case it was 0
  2306. //
  2307. if (m_PageDirectories[PAGE_DIR_SINGLE] == 0)
  2308. {
  2309. if ((Status = SetDefaultPageDirectories(Thread,
  2310. 1 << PAGE_DIR_SINGLE)) != S_OK)
  2311. {
  2312. m_Translating = FALSE;
  2313. return Status;
  2314. }
  2315. }
  2316. KdOut("X86VtoP: Virt %s, pagedir %s\n",
  2317. FormatMachineAddr64(this, Virt),
  2318. FormatDisp64(m_PageDirectories[PAGE_DIR_SINGLE]));
  2319. (*Levels)++;
  2320. if (Offsets != NULL && OffsetsSize > 0)
  2321. {
  2322. *Offsets++ = m_PageDirectories[PAGE_DIR_SINGLE];
  2323. OffsetsSize--;
  2324. }
  2325. // This routine uses the fact that the PFN shift is the same
  2326. // as the page shift to simplify some expressions.
  2327. C_ASSERT(X86_VALID_PFN_SHIFT == X86_PAGE_SHIFT);
  2328. if (m_Target->m_KdDebuggerData.PaeEnabled)
  2329. {
  2330. ULONG64 Pdpe;
  2331. ULONG64 Entry;
  2332. KdOut(" x86VtoP: PaeEnabled\n");
  2333. // Read the Page Directory Pointer entry.
  2334. Pdpe = ((Virt >> X86_PDPE_SHIFT) * sizeof(Entry)) +
  2335. m_PageDirectories[PAGE_DIR_SINGLE];
  2336. KdOut("X86VtoP: PAE PDPE %s\n", FormatDisp64(Pdpe));
  2337. (*Levels)++;
  2338. if (Offsets != NULL && OffsetsSize > 0)
  2339. {
  2340. *Offsets++ = Pdpe;
  2341. OffsetsSize--;
  2342. }
  2343. if ((Status = m_Target->
  2344. ReadAllPhysical(Pdpe, &Entry, sizeof(Entry))) != S_OK)
  2345. {
  2346. KdOut("X86VtoP: PAE PDPE read error 0x%X\n", Status);
  2347. m_Translating = FALSE;
  2348. return Status;
  2349. }
  2350. // Read the Page Directory entry.
  2351. Addr = (((Virt >> X86_PDE_SHIFT_PAE) & X86_PDE_MASK_PAE) *
  2352. sizeof(Entry)) + (Entry & X86_VALID_PFN_MASK_PAE);
  2353. KdOut("X86VtoP: PAE PDE %s\n", FormatDisp64(Addr));
  2354. (*Levels)++;
  2355. if (Offsets != NULL && OffsetsSize > 0)
  2356. {
  2357. *Offsets++ = Addr;
  2358. OffsetsSize--;
  2359. }
  2360. if ((Status = m_Target->
  2361. ReadAllPhysical(Addr, &Entry, sizeof(Entry))) != S_OK)
  2362. {
  2363. KdOut("X86VtoP: PAE PDE read error 0x%X\n", Status);
  2364. m_Translating = FALSE;
  2365. return Status;
  2366. }
  2367. // Check for a large page. Large pages can
  2368. // never be paged out so also check for the present bit.
  2369. if ((Entry & (X86_LARGE_PAGE_MASK | 1)) == (X86_LARGE_PAGE_MASK | 1))
  2370. {
  2371. //
  2372. // If we have a large page and this is a summary dump, then
  2373. // the page may span multiple physical pages that may -- because
  2374. // of how the summary dump is written -- not be included in the
  2375. // dump. Fixup the large page address to its corresponding small
  2376. // page address.
  2377. //
  2378. if (IS_KERNEL_SUMMARY_DUMP(m_Target))
  2379. {
  2380. ULONG SpannedPages;
  2381. SpannedPages = (ULONG)
  2382. ((Virt & (X86_LARGE_PAGE_SIZE_PAE - 1)) >> X86_PAGE_SHIFT);
  2383. *LastVal = ((Entry & ~(X86_LARGE_PAGE_SIZE_PAE - 1)) |
  2384. ((ULONG64)SpannedPages << X86_PAGE_SHIFT) |
  2385. (Virt & (X86_PAGE_SIZE - 1)));
  2386. }
  2387. else
  2388. {
  2389. *LastVal = ((Entry & ~(X86_LARGE_PAGE_SIZE_PAE - 1)) |
  2390. (Virt & (X86_LARGE_PAGE_SIZE_PAE - 1)));
  2391. }
  2392. KdOut("X86VtoP: PAE Large page mapped phys %s\n",
  2393. FormatDisp64(*LastVal));
  2394. (*Levels)++;
  2395. if (Offsets != NULL && OffsetsSize > 0)
  2396. {
  2397. *Offsets++ = *LastVal;
  2398. OffsetsSize--;
  2399. }
  2400. m_Translating = FALSE;
  2401. return S_OK;
  2402. }
  2403. // Read the Page Table entry.
  2404. if (Entry == 0)
  2405. {
  2406. KdOut("X86VtoP: PAE zero PDE\n");
  2407. m_Translating = FALSE;
  2408. return HR_PAGE_NOT_AVAILABLE;
  2409. }
  2410. else if (!(Entry & 1))
  2411. {
  2412. Addr = (((Virt >> X86_PTE_SHIFT) & X86_PTE_MASK_PAE) *
  2413. sizeof(Entry)) + X86_PAGE_FILE_OFFSET(Entry);
  2414. KdOut("X86VtoP: pagefile PAE PTE %d:%s\n",
  2415. X86_PAGE_FILE_INDEX(Entry), FormatDisp64(Addr));
  2416. if ((Status = m_Target->
  2417. ReadPageFile(X86_PAGE_FILE_INDEX(Entry), Addr,
  2418. &Entry, sizeof(Entry))) != S_OK)
  2419. {
  2420. KdOut("X86VtoP: PAE PDE not present, 0x%X\n", Status);
  2421. m_Translating = FALSE;
  2422. return Status;
  2423. }
  2424. }
  2425. else
  2426. {
  2427. Addr = (((Virt >> X86_PTE_SHIFT) & X86_PTE_MASK_PAE) *
  2428. sizeof(Entry)) + (Entry & X86_VALID_PFN_MASK_PAE);
  2429. KdOut("X86VtoP: PAE PTE %s\n", FormatDisp64(Addr));
  2430. (*Levels)++;
  2431. if (Offsets != NULL && OffsetsSize > 0)
  2432. {
  2433. *Offsets++ = Addr;
  2434. OffsetsSize--;
  2435. }
  2436. if ((Status = m_Target->
  2437. ReadAllPhysical(Addr, &Entry, sizeof(Entry))) != S_OK)
  2438. {
  2439. KdOut("X86VtoP: PAE PTE read error 0x%X\n", Status);
  2440. m_Translating = FALSE;
  2441. return Status;
  2442. }
  2443. }
  2444. if (!(Entry & 0x1) &&
  2445. ((Entry & X86_MM_PTE_PROTOTYPE_MASK) ||
  2446. !(Entry & X86_MM_PTE_TRANSITION_MASK)))
  2447. {
  2448. if (Entry == 0)
  2449. {
  2450. KdOut("X86VtoP: PAE zero PTE\n");
  2451. Status = HR_PAGE_NOT_AVAILABLE;
  2452. }
  2453. else if (Entry & X86_MM_PTE_PROTOTYPE_MASK)
  2454. {
  2455. KdOut("X86VtoP: PAE prototype PTE\n");
  2456. Status = HR_PAGE_NOT_AVAILABLE;
  2457. }
  2458. else
  2459. {
  2460. *PfIndex = X86_PAGE_FILE_INDEX(Entry);
  2461. *LastVal = (Virt & (X86_PAGE_SIZE - 1)) +
  2462. X86_PAGE_FILE_OFFSET(Entry);
  2463. KdOut("X86VtoP: PAE PTE not present, pagefile %d:%s\n",
  2464. *PfIndex, FormatDisp64(*LastVal));
  2465. Status = HR_PAGE_IN_PAGE_FILE;
  2466. }
  2467. m_Translating = FALSE;
  2468. return Status;
  2469. }
  2470. *LastVal = ((Entry & X86_VALID_PFN_MASK_PAE) |
  2471. (Virt & (X86_PAGE_SIZE - 1)));
  2472. KdOut("X86VtoP: PAE Mapped phys %s\n",
  2473. FormatDisp64(*LastVal));
  2474. (*Levels)++;
  2475. if (Offsets != NULL && OffsetsSize > 0)
  2476. {
  2477. *Offsets++ = *LastVal;
  2478. OffsetsSize--;
  2479. }
  2480. m_Translating = FALSE;
  2481. return S_OK;
  2482. }
  2483. else
  2484. {
  2485. ULONG Entry;
  2486. // Read the Page Directory entry.
  2487. Addr = ((Virt >> X86_PDE_SHIFT) * sizeof(Entry)) +
  2488. m_PageDirectories[PAGE_DIR_SINGLE];
  2489. KdOut("X86VtoP: PDE %s\n", FormatDisp64(Addr));
  2490. (*Levels)++;
  2491. if (Offsets != NULL && OffsetsSize > 0)
  2492. {
  2493. *Offsets++ = Addr;
  2494. OffsetsSize--;
  2495. }
  2496. if ((Status = m_Target->
  2497. ReadAllPhysical(Addr, &Entry, sizeof(Entry))) != S_OK)
  2498. {
  2499. KdOut("X86VtoP: PDE read error 0x%X\n", Status);
  2500. m_Translating = FALSE;
  2501. return Status;
  2502. }
  2503. // Check for a large page. Large pages can
  2504. // never be paged out so also check for the present bit.
  2505. if ((Entry & (X86_LARGE_PAGE_MASK | 1)) == (X86_LARGE_PAGE_MASK | 1))
  2506. {
  2507. *LastVal = ((Entry & ~(X86_LARGE_PAGE_SIZE - 1)) |
  2508. (Virt & (X86_LARGE_PAGE_SIZE - 1)));
  2509. KdOut("X86VtoP: Large page mapped phys %s\n",
  2510. FormatDisp64(*LastVal));
  2511. (*Levels)++;
  2512. if (Offsets != NULL && OffsetsSize > 0)
  2513. {
  2514. *Offsets++ = *LastVal;
  2515. OffsetsSize--;
  2516. }
  2517. m_Translating = FALSE;
  2518. return S_OK;
  2519. }
  2520. // Read the Page Table entry.
  2521. if (Entry == 0)
  2522. {
  2523. KdOut("X86VtoP: zero PDE\n");
  2524. m_Translating = FALSE;
  2525. return HR_PAGE_NOT_AVAILABLE;
  2526. }
  2527. else if (!(Entry & 1))
  2528. {
  2529. Addr = (((Virt >> X86_PTE_SHIFT) & X86_PTE_MASK) *
  2530. sizeof(Entry)) + X86_PAGE_FILE_OFFSET(Entry);
  2531. KdOut("X86VtoP: pagefile PTE %d:%s\n",
  2532. X86_PAGE_FILE_INDEX(Entry), FormatDisp64(Addr));
  2533. if ((Status = m_Target->
  2534. ReadPageFile(X86_PAGE_FILE_INDEX(Entry), Addr,
  2535. &Entry, sizeof(Entry))) != S_OK)
  2536. {
  2537. KdOut("X86VtoP: PDE not present, 0x%X\n", Status);
  2538. m_Translating = FALSE;
  2539. return Status;
  2540. }
  2541. }
  2542. else
  2543. {
  2544. Addr = (((Virt >> X86_PTE_SHIFT) & X86_PTE_MASK) *
  2545. sizeof(Entry)) + (Entry & X86_VALID_PFN_MASK);
  2546. KdOut("X86VtoP: PTE %s\n", FormatDisp64(Addr));
  2547. (*Levels)++;
  2548. if (Offsets != NULL && OffsetsSize > 0)
  2549. {
  2550. *Offsets++ = Addr;
  2551. OffsetsSize--;
  2552. }
  2553. if ((Status = m_Target->
  2554. ReadAllPhysical(Addr, &Entry, sizeof(Entry))) != S_OK)
  2555. {
  2556. KdOut("X86VtoP: PTE read error 0x%X\n", Status);
  2557. m_Translating = FALSE;
  2558. return Status;
  2559. }
  2560. }
  2561. if (!(Entry & 0x1) &&
  2562. ((Entry & X86_MM_PTE_PROTOTYPE_MASK) ||
  2563. !(Entry & X86_MM_PTE_TRANSITION_MASK)))
  2564. {
  2565. if (Entry == 0)
  2566. {
  2567. KdOut("X86VtoP: zero PTE\n");
  2568. Status = HR_PAGE_NOT_AVAILABLE;
  2569. }
  2570. else if (Entry & X86_MM_PTE_PROTOTYPE_MASK)
  2571. {
  2572. KdOut("X86VtoP: prototype PTE\n");
  2573. Status = HR_PAGE_NOT_AVAILABLE;
  2574. }
  2575. else
  2576. {
  2577. *PfIndex = X86_PAGE_FILE_INDEX(Entry);
  2578. *LastVal = (Virt & (X86_PAGE_SIZE - 1)) +
  2579. X86_PAGE_FILE_OFFSET(Entry);
  2580. KdOut("X86VtoP: PTE not present, pagefile %d:%s\n",
  2581. *PfIndex, FormatDisp64(*LastVal));
  2582. Status = HR_PAGE_IN_PAGE_FILE;
  2583. }
  2584. m_Translating = FALSE;
  2585. return Status;
  2586. }
  2587. *LastVal = ((Entry & X86_VALID_PFN_MASK) |
  2588. (Virt & (X86_PAGE_SIZE - 1)));
  2589. KdOut("X86VtoP: Mapped phys %s\n", FormatDisp64(*LastVal));
  2590. (*Levels)++;
  2591. if (Offsets != NULL && OffsetsSize > 0)
  2592. {
  2593. *Offsets++ = *LastVal;
  2594. OffsetsSize--;
  2595. }
  2596. m_Translating = FALSE;
  2597. return S_OK;
  2598. }
  2599. }
  2600. HRESULT
  2601. X86MachineInfo::GetBaseTranslationVirtualOffset(PULONG64 Offset)
  2602. {
  2603. if (m_Target->m_KdDebuggerData.PaeEnabled)
  2604. {
  2605. *Offset = EXTEND64(X86_BASE_VIRT_PAE);
  2606. }
  2607. else
  2608. {
  2609. *Offset = EXTEND64(X86_BASE_VIRT);
  2610. }
  2611. return S_OK;
  2612. }
  2613. void
  2614. X86MachineInfo::DecodePte(ULONG64 Pte, PULONG64 PageFrameNumber,
  2615. PULONG Flags)
  2616. {
  2617. *PageFrameNumber = (Pte & X86_VALID_PFN_MASK) >> X86_PAGE_SHIFT;
  2618. *Flags = (Pte & 1) ? MPTE_FLAG_VALID : 0;
  2619. }
  2620. void
  2621. X86MachineInfo::OutputFunctionEntry(PVOID RawEntry)
  2622. {
  2623. PFPO_DATA FpoData = (PFPO_DATA)RawEntry;
  2624. dprintf("OffStart: %08x\n", FpoData->ulOffStart);
  2625. dprintf("ProcSize: 0x%x\n", FpoData->cbProcSize);
  2626. switch(FpoData->cbFrame)
  2627. {
  2628. case FRAME_FPO:
  2629. dprintf("Params: %d\n", FpoData->cdwParams);
  2630. dprintf("Locals: %d\n", FpoData->cdwLocals);
  2631. dprintf("Registers: %d\n", FpoData->cbRegs);
  2632. if (FpoData->fHasSEH)
  2633. {
  2634. dprintf("Has SEH\n");
  2635. }
  2636. if (FpoData->fUseBP)
  2637. {
  2638. dprintf("Uses EBP\n");
  2639. }
  2640. break;
  2641. case FRAME_NONFPO:
  2642. dprintf("Non-FPO\n");
  2643. break;
  2644. case FRAME_TRAP:
  2645. if (!IS_KERNEL_TARGET(m_Target))
  2646. {
  2647. goto UnknownFpo;
  2648. }
  2649. dprintf("Params: %d\n", FpoData->cdwParams);
  2650. dprintf("Locals: %d\n", FpoData->cdwLocals);
  2651. dprintf("Trap frame\n");
  2652. break;
  2653. case FRAME_TSS:
  2654. if (!IS_KERNEL_TARGET(m_Target))
  2655. {
  2656. goto UnknownFpo;
  2657. }
  2658. dprintf("Task gate\n");
  2659. break;
  2660. default:
  2661. UnknownFpo:
  2662. dprintf("Unknown FPO type\n");
  2663. break;
  2664. }
  2665. }
  2666. HRESULT
  2667. X86MachineInfo::ReadKernelProcessorId
  2668. (ULONG Processor, PDEBUG_PROCESSOR_IDENTIFICATION_ALL Id)
  2669. {
  2670. HRESULT Status;
  2671. ULONG64 Prcb;
  2672. ULONG Data;
  2673. if ((Status = m_Target->
  2674. GetProcessorSystemDataOffset(Processor, DEBUG_DATA_KPRCB_OFFSET,
  2675. &Prcb)) != S_OK)
  2676. {
  2677. return Status;
  2678. }
  2679. if ((Status = m_Target->
  2680. ReadAllVirtual(m_Target->m_ProcessHead,
  2681. Prcb + m_Target->m_KdDebuggerData.OffsetPrcbCpuType,
  2682. &Data, sizeof(Data))) != S_OK)
  2683. {
  2684. return Status;
  2685. }
  2686. Id->X86.Family = Data & 0xf;
  2687. Id->X86.Model = (Data >> 24) & 0xf;
  2688. Id->X86.Stepping = (Data >> 16) & 0xf;
  2689. if ((Status = m_Target->
  2690. ReadAllVirtual(m_Target->m_ProcessHead, Prcb +
  2691. m_Target->m_KdDebuggerData.OffsetPrcbVendorString,
  2692. Id->X86.VendorString, X86_VENDOR_STRING_SIZE)) != S_OK)
  2693. {
  2694. return Status;
  2695. }
  2696. return S_OK;
  2697. }
  2698. HRESULT
  2699. X86MachineInfo::GetAlternateTriageDumpDataRanges(ULONG64 PrcbBase,
  2700. ULONG64 ThreadBase,
  2701. PADDR_RANGE Ranges)
  2702. {
  2703. PADDR_RANGE Range = Ranges;
  2704. if (m_Target->ReadPointer(m_Target->m_ProcessHead, this, PrcbBase +
  2705. m_Target->m_KdDebuggerData.OffsetPrcbDpcRoutine,
  2706. &Range->Base) == S_OK &&
  2707. Range->Base)
  2708. {
  2709. Range->Base = PAGE_ALIGN(this, Range->Base);
  2710. Range->Size = m_PageSize;
  2711. Range++;
  2712. }
  2713. else
  2714. {
  2715. Range->Base = 0;
  2716. }
  2717. return S_OK;
  2718. }
  2719. void
  2720. X86MachineInfo::KdGetSpecialRegistersFromContext(void)
  2721. {
  2722. DBG_ASSERT(m_ContextState >= MCTX_FULL);
  2723. m_Special.X86Special.KernelDr0 = m_Context.X86Nt5Context.Dr0;
  2724. m_Special.X86Special.KernelDr1 = m_Context.X86Nt5Context.Dr1;
  2725. m_Special.X86Special.KernelDr2 = m_Context.X86Nt5Context.Dr2;
  2726. m_Special.X86Special.KernelDr3 = m_Context.X86Nt5Context.Dr3;
  2727. m_Special.X86Special.KernelDr6 = m_Context.X86Nt5Context.Dr6;
  2728. m_Special.X86Special.KernelDr7 = m_Context.X86Nt5Context.Dr7;
  2729. }
  2730. void
  2731. X86MachineInfo::KdSetSpecialRegistersInContext(void)
  2732. {
  2733. DBG_ASSERT(m_ContextState >= MCTX_FULL);
  2734. m_Context.X86Nt5Context.Dr0 = m_Special.X86Special.KernelDr0;
  2735. m_Context.X86Nt5Context.Dr1 = m_Special.X86Special.KernelDr1;
  2736. m_Context.X86Nt5Context.Dr2 = m_Special.X86Special.KernelDr2;
  2737. m_Context.X86Nt5Context.Dr3 = m_Special.X86Special.KernelDr3;
  2738. m_Context.X86Nt5Context.Dr6 = m_Special.X86Special.KernelDr6;
  2739. m_Context.X86Nt5Context.Dr7 = m_Special.X86Special.KernelDr7;
  2740. }
  2741. ULONG
  2742. X86MachineInfo::GetIntReg(ULONG regnum)
  2743. {
  2744. switch (m_ContextState)
  2745. {
  2746. case MCTX_PC:
  2747. if (regnum == X86_EIP)
  2748. {
  2749. return m_Context.X86Nt5Context.Eip;
  2750. }
  2751. goto MctxContext;
  2752. case MCTX_DR67_REPORT:
  2753. switch (regnum)
  2754. {
  2755. case X86_DR6: return m_Context.X86Nt5Context.Dr6;
  2756. case X86_DR7: return m_Context.X86Nt5Context.Dr7;
  2757. }
  2758. goto MctxContext;
  2759. case MCTX_REPORT:
  2760. switch (regnum)
  2761. {
  2762. case X86_CS: return (USHORT)m_Context.X86Nt5Context.SegCs;
  2763. case X86_DS: return (USHORT)m_Context.X86Nt5Context.SegDs;
  2764. case X86_ES: return (USHORT)m_Context.X86Nt5Context.SegEs;
  2765. case X86_FS: return (USHORT)m_Context.X86Nt5Context.SegFs;
  2766. case X86_EIP: return m_Context.X86Nt5Context.Eip;
  2767. case X86_EFL: return m_Context.X86Nt5Context.EFlags;
  2768. case X86_DR6: return m_Context.X86Nt5Context.Dr6;
  2769. case X86_DR7: return m_Context.X86Nt5Context.Dr7;
  2770. }
  2771. // Fallthrough!
  2772. case MCTX_NONE:
  2773. MctxContext:
  2774. if (GetContextState(MCTX_CONTEXT) != S_OK)
  2775. {
  2776. return 0;
  2777. }
  2778. // Fallthrough!
  2779. case MCTX_CONTEXT:
  2780. switch (regnum)
  2781. {
  2782. case X86_CS: return (USHORT)m_Context.X86Nt5Context.SegCs;
  2783. case X86_DS: return (USHORT)m_Context.X86Nt5Context.SegDs;
  2784. case X86_ES: return (USHORT)m_Context.X86Nt5Context.SegEs;
  2785. case X86_FS: return (USHORT)m_Context.X86Nt5Context.SegFs;
  2786. case X86_EIP: return m_Context.X86Nt5Context.Eip;
  2787. case X86_EFL: return m_Context.X86Nt5Context.EFlags;
  2788. case X86_GS: return (USHORT)m_Context.X86Nt5Context.SegGs;
  2789. case X86_SS: return (USHORT)m_Context.X86Nt5Context.SegSs;
  2790. case X86_EDI: return m_Context.X86Nt5Context.Edi;
  2791. case X86_ESI: return m_Context.X86Nt5Context.Esi;
  2792. case X86_EBX: return m_Context.X86Nt5Context.Ebx;
  2793. case X86_EDX: return m_Context.X86Nt5Context.Edx;
  2794. case X86_ECX: return m_Context.X86Nt5Context.Ecx;
  2795. case X86_EAX: return m_Context.X86Nt5Context.Eax;
  2796. case X86_EBP: return m_Context.X86Nt5Context.Ebp;
  2797. case X86_ESP: return m_Context.X86Nt5Context.Esp;
  2798. case X86_FPCW:
  2799. return m_Context.X86Nt5Context.FloatSave.ControlWord & 0xffff;
  2800. case X86_FPSW:
  2801. return m_Context.X86Nt5Context.FloatSave.StatusWord & 0xffff;
  2802. case X86_FPTW:
  2803. return m_Context.X86Nt5Context.FloatSave.TagWord & 0xffff;
  2804. case X86_MXCSR:
  2805. return m_Context.X86Nt5Context.FxSave.MXCsr;
  2806. }
  2807. //
  2808. // The requested register is not in our current context, load up
  2809. // a complete context
  2810. //
  2811. if (GetContextState(MCTX_FULL) != S_OK)
  2812. {
  2813. return 0;
  2814. }
  2815. }
  2816. //
  2817. // We must have a complete context...
  2818. //
  2819. switch (regnum)
  2820. {
  2821. case X86_GS:
  2822. return (USHORT)m_Context.X86Nt5Context.SegGs;
  2823. case X86_FS:
  2824. return (USHORT)m_Context.X86Nt5Context.SegFs;
  2825. case X86_ES:
  2826. return (USHORT)m_Context.X86Nt5Context.SegEs;
  2827. case X86_DS:
  2828. return (USHORT)m_Context.X86Nt5Context.SegDs;
  2829. case X86_EDI:
  2830. return m_Context.X86Nt5Context.Edi;
  2831. case X86_ESI:
  2832. return m_Context.X86Nt5Context.Esi;
  2833. case X86_SI:
  2834. return(m_Context.X86Nt5Context.Esi & 0xffff);
  2835. case X86_DI:
  2836. return(m_Context.X86Nt5Context.Edi & 0xffff);
  2837. case X86_EBX:
  2838. return m_Context.X86Nt5Context.Ebx;
  2839. case X86_EDX:
  2840. return m_Context.X86Nt5Context.Edx;
  2841. case X86_ECX:
  2842. return m_Context.X86Nt5Context.Ecx;
  2843. case X86_EAX:
  2844. return m_Context.X86Nt5Context.Eax;
  2845. case X86_EBP:
  2846. return m_Context.X86Nt5Context.Ebp;
  2847. case X86_EIP:
  2848. return m_Context.X86Nt5Context.Eip;
  2849. case X86_CS:
  2850. return (USHORT)m_Context.X86Nt5Context.SegCs;
  2851. case X86_EFL:
  2852. return m_Context.X86Nt5Context.EFlags;
  2853. case X86_ESP:
  2854. return m_Context.X86Nt5Context.Esp;
  2855. case X86_SS:
  2856. return (USHORT)m_Context.X86Nt5Context.SegSs;
  2857. case X86_DR0:
  2858. return m_Context.X86Nt5Context.Dr0;
  2859. case X86_DR1:
  2860. return m_Context.X86Nt5Context.Dr1;
  2861. case X86_DR2:
  2862. return m_Context.X86Nt5Context.Dr2;
  2863. case X86_DR3:
  2864. return m_Context.X86Nt5Context.Dr3;
  2865. case X86_DR6:
  2866. return m_Context.X86Nt5Context.Dr6;
  2867. case X86_DR7:
  2868. return m_Context.X86Nt5Context.Dr7;
  2869. case X86_FPCW:
  2870. return m_Context.X86Nt5Context.FloatSave.ControlWord & 0xffff;
  2871. case X86_FPSW:
  2872. return m_Context.X86Nt5Context.FloatSave.StatusWord & 0xffff;
  2873. case X86_FPTW:
  2874. return m_Context.X86Nt5Context.FloatSave.TagWord & 0xffff;
  2875. case X86_MXCSR:
  2876. return m_Context.X86Nt5Context.FxSave.MXCsr;
  2877. }
  2878. if (IS_KERNEL_TARGET(m_Target))
  2879. {
  2880. switch(regnum)
  2881. {
  2882. case X86_CR0:
  2883. return m_Special.X86Special.Cr0;
  2884. case X86_CR2:
  2885. return m_Special.X86Special.Cr2;
  2886. case X86_CR3:
  2887. return m_Special.X86Special.Cr3;
  2888. case X86_CR4:
  2889. return m_Special.X86Special.Cr4;
  2890. case X86_GDTR:
  2891. return m_Special.X86Special.Gdtr.Base;
  2892. case X86_GDTL:
  2893. return (ULONG)m_Special.X86Special.Gdtr.Limit;
  2894. case X86_IDTR:
  2895. return m_Special.X86Special.Idtr.Base;
  2896. case X86_IDTL:
  2897. return (ULONG)m_Special.X86Special.Idtr.Limit;
  2898. case X86_TR:
  2899. return (ULONG)m_Special.X86Special.Tr;
  2900. case X86_LDTR:
  2901. return (ULONG)m_Special.X86Special.Ldtr;
  2902. }
  2903. }
  2904. ErrOut("X86MachineInfo::SetVal: "
  2905. "unknown register %lx requested\n", regnum);
  2906. return REG_ERROR;
  2907. }
  2908. PULONG64
  2909. X86MachineInfo::GetMmxRegSlot(ULONG regnum)
  2910. {
  2911. return (PULONG64)(m_Context.X86Nt5Context.FloatSave.RegisterArea +
  2912. GetMmxRegOffset(regnum - X86_MM_FIRST,
  2913. GetIntReg(X86_FPSW)) * 10);
  2914. }
  2915. void
  2916. X86MachineInfo::GetMmxReg(ULONG Reg, REGVAL* Val)
  2917. {
  2918. if (GetContextState(MCTX_CONTEXT) == S_OK)
  2919. {
  2920. Val->I64 = *(ULONG64 UNALIGNED *)GetMmxRegSlot(Reg);
  2921. }
  2922. }
  2923. void
  2924. X86MachineInfo::GetFloatReg(ULONG Reg, REGVAL* Val)
  2925. {
  2926. if (GetContextState(MCTX_CONTEXT) == S_OK)
  2927. {
  2928. memcpy(Val->F10, m_Context.X86Nt5Context.FloatSave.RegisterArea +
  2929. 10 * (Reg - X86_ST_FIRST), sizeof(Val->F10));
  2930. }
  2931. }