Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2905 lines
80 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Register portions of X86 machine implementation.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000-2001.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. // XXX drewb - Temporary log to try and catch some
  10. // SET_OF_INVALID_CONTEXT bugchecks occurring randomly on x86.
  11. ULONG g_EspLog[64];
  12. PULONG g_EspLogCur = g_EspLog;
  13. // See Get/SetRegVal comments in machine.hpp.
  14. #define RegValError Do_not_use_GetSetRegVal_in_machine_implementations
  15. #define GetRegVal(index, val) RegValError
  16. #define GetRegVal32(index) RegValError
  17. #define GetRegVal64(index) RegValError
  18. #define SetRegVal(index, val) RegValError
  19. #define SetRegVal32(index, val) RegValError
  20. #define SetRegVal64(index, val) RegValError
  21. #define X86_RPL_MASK 3
  22. BOOL g_X86InCode16;
  23. BOOL g_X86InVm86;
  24. #define REGALL_SEGREG REGALL_EXTRA0
  25. #define REGALL_MMXREG REGALL_EXTRA1
  26. #define REGALL_DREG REGALL_EXTRA2
  27. REGALLDESC g_X86AllExtraDesc[] =
  28. {
  29. REGALL_SEGREG, "Segment registers",
  30. REGALL_MMXREG, "MMX registers",
  31. REGALL_DREG, "Debug registers and, in kernel, CR4",
  32. REGALL_XMMREG, "SSE XMM registers",
  33. 0, NULL,
  34. };
  35. #define REGALL_CREG REGALL_EXTRA4
  36. #define REGALL_DESC REGALL_EXTRA5
  37. REGALLDESC g_X86KernelExtraDesc[] =
  38. {
  39. REGALL_CREG, "CR0, CR2 and CR3",
  40. REGALL_DESC, "Descriptor and task state",
  41. 0, NULL,
  42. };
  43. char g_Gs[] = "gs";
  44. char g_Fs[] = "fs";
  45. char g_Es[] = "es";
  46. char g_Ds[] = "ds";
  47. char g_Edi[] = "edi";
  48. char g_Esi[] = "esi";
  49. char g_Ebx[] = "ebx";
  50. char g_Edx[] = "edx";
  51. char g_Ecx[] = "ecx";
  52. char g_Eax[] = "eax";
  53. char g_Ebp[] = "ebp";
  54. char g_Eip[] = "eip";
  55. char g_Cs[] = "cs";
  56. char g_Efl[] = "efl";
  57. char g_Esp[] = "esp";
  58. char g_Ss[] = "ss";
  59. char g_Dr0[] = "dr0";
  60. char g_Dr1[] = "dr1";
  61. char g_Dr2[] = "dr2";
  62. char g_Dr3[] = "dr3";
  63. char g_Dr6[] = "dr6";
  64. char g_Dr7[] = "dr7";
  65. char g_Cr0[] = "cr0";
  66. char g_Cr2[] = "cr2";
  67. char g_Cr3[] = "cr3";
  68. char g_Cr4[] = "cr4";
  69. char g_Gdtr[] = "gdtr";
  70. char g_Gdtl[] = "gdtl";
  71. char g_Idtr[] = "idtr";
  72. char g_Idtl[] = "idtl";
  73. char g_Tr[] = "tr";
  74. char g_Ldtr[] = "ldtr";
  75. char g_Di[] = "di";
  76. char g_Si[] = "si";
  77. char g_Bx[] = "bx";
  78. char g_Dx[] = "dx";
  79. char g_Cx[] = "cx";
  80. char g_Ax[] = "ax";
  81. char g_Bp[] = "bp";
  82. char g_Ip[] = "ip";
  83. char g_Fl[] = "fl";
  84. char g_Sp[] = "sp";
  85. char g_Bl[] = "bl";
  86. char g_Dl[] = "dl";
  87. char g_Cl[] = "cl";
  88. char g_Al[] = "al";
  89. char g_Bh[] = "bh";
  90. char g_Dh[] = "dh";
  91. char g_Ch[] = "ch";
  92. char g_Ah[] = "ah";
  93. char g_Iopl[] = "iopl";
  94. char g_Of[] = "of";
  95. char g_Df[] = "df";
  96. char g_If[] = "if";
  97. char g_Tf[] = "tf";
  98. char g_Sf[] = "sf";
  99. char g_Zf[] = "zf";
  100. char g_Af[] = "af";
  101. char g_Pf[] = "pf";
  102. char g_Cf[] = "cf";
  103. char g_Vip[] = "vip";
  104. char g_Vif[] = "vif";
  105. char g_Fpcw[] = "fpcw";
  106. char g_Fpsw[] = "fpsw";
  107. char g_Fptw[] = "fptw";
  108. char g_St0[] = "st0";
  109. char g_St1[] = "st1";
  110. char g_St2[] = "st2";
  111. char g_St3[] = "st3";
  112. char g_St4[] = "st4";
  113. char g_St5[] = "st5";
  114. char g_St6[] = "st6";
  115. char g_St7[] = "st7";
  116. char g_Mm0[] = "mm0";
  117. char g_Mm1[] = "mm1";
  118. char g_Mm2[] = "mm2";
  119. char g_Mm3[] = "mm3";
  120. char g_Mm4[] = "mm4";
  121. char g_Mm5[] = "mm5";
  122. char g_Mm6[] = "mm6";
  123. char g_Mm7[] = "mm7";
  124. char g_Mxcsr[] = "mxcsr";
  125. char g_Xmm0[] = "xmm0";
  126. char g_Xmm1[] = "xmm1";
  127. char g_Xmm2[] = "xmm2";
  128. char g_Xmm3[] = "xmm3";
  129. char g_Xmm4[] = "xmm4";
  130. char g_Xmm5[] = "xmm5";
  131. char g_Xmm6[] = "xmm6";
  132. char g_Xmm7[] = "xmm7";
  133. REGDEF g_X86Defs[] =
  134. {
  135. { g_Gs, X86_GS },
  136. { g_Fs, X86_FS },
  137. { g_Es, X86_ES },
  138. { g_Ds, X86_DS },
  139. { g_Edi, X86_EDI },
  140. { g_Esi, X86_ESI },
  141. { g_Ebx, X86_EBX },
  142. { g_Edx, X86_EDX },
  143. { g_Ecx, X86_ECX },
  144. { g_Eax, X86_EAX },
  145. { g_Ebp, X86_EBP },
  146. { g_Eip, X86_EIP },
  147. { g_Cs, X86_CS },
  148. { g_Efl, X86_EFL },
  149. { g_Esp, X86_ESP },
  150. { g_Ss, X86_SS },
  151. { g_Dr0, X86_DR0 },
  152. { g_Dr1, X86_DR1 },
  153. { g_Dr2, X86_DR2 },
  154. { g_Dr3, X86_DR3 },
  155. { g_Dr6, X86_DR6 },
  156. { g_Dr7, X86_DR7 },
  157. { g_Di, X86_DI },
  158. { g_Si, X86_SI },
  159. { g_Bx, X86_BX },
  160. { g_Dx, X86_DX },
  161. { g_Cx, X86_CX },
  162. { g_Ax, X86_AX },
  163. { g_Bp, X86_BP },
  164. { g_Ip, X86_IP },
  165. { g_Fl, X86_FL },
  166. { g_Sp, X86_SP },
  167. { g_Bl, X86_BL },
  168. { g_Dl, X86_DL },
  169. { g_Cl, X86_CL },
  170. { g_Al, X86_AL },
  171. { g_Bh, X86_BH },
  172. { g_Dh, X86_DH },
  173. { g_Ch, X86_CH },
  174. { g_Ah, X86_AH },
  175. { g_Fpcw, X86_FPCW },
  176. { g_Fpsw, X86_FPSW },
  177. { g_Fptw, X86_FPTW },
  178. { g_St0, X86_ST0 },
  179. { g_St1, X86_ST1 },
  180. { g_St2, X86_ST2 },
  181. { g_St3, X86_ST3 },
  182. { g_St4, X86_ST4 },
  183. { g_St5, X86_ST5 },
  184. { g_St6, X86_ST6 },
  185. { g_St7, X86_ST7 },
  186. { g_Mm0, X86_MM0 },
  187. { g_Mm1, X86_MM1 },
  188. { g_Mm2, X86_MM2 },
  189. { g_Mm3, X86_MM3 },
  190. { g_Mm4, X86_MM4 },
  191. { g_Mm5, X86_MM5 },
  192. { g_Mm6, X86_MM6 },
  193. { g_Mm7, X86_MM7 },
  194. { g_Mxcsr, X86_MXCSR},
  195. { g_Xmm0, X86_XMM0 },
  196. { g_Xmm1, X86_XMM1 },
  197. { g_Xmm2, X86_XMM2 },
  198. { g_Xmm3, X86_XMM3 },
  199. { g_Xmm4, X86_XMM4 },
  200. { g_Xmm5, X86_XMM5 },
  201. { g_Xmm6, X86_XMM6 },
  202. { g_Xmm7, X86_XMM7 },
  203. { g_Iopl, X86_IOPL },
  204. { g_Of, X86_OF },
  205. { g_Df, X86_DF },
  206. { g_If, X86_IF },
  207. { g_Tf, X86_TF },
  208. { g_Sf, X86_SF },
  209. { g_Zf, X86_ZF },
  210. { g_Af, X86_AF },
  211. { g_Pf, X86_PF },
  212. { g_Cf, X86_CF },
  213. { g_Vip, X86_VIP },
  214. { g_Vif, X86_VIF },
  215. { NULL, REG_ERROR },
  216. };
  217. REGDEF g_X86KernelReg[] =
  218. {
  219. { g_Cr0, X86_CR0 },
  220. { g_Cr2, X86_CR2 },
  221. { g_Cr3, X86_CR3 },
  222. { g_Cr4, X86_CR4 },
  223. { g_Gdtr, X86_GDTR },
  224. { g_Gdtl, X86_GDTL },
  225. { g_Idtr, X86_IDTR },
  226. { g_Idtl, X86_IDTL },
  227. { g_Tr, X86_TR },
  228. { g_Ldtr, X86_LDTR },
  229. { NULL, REG_ERROR },
  230. };
  231. REGSUBDEF g_X86SubDefs[] =
  232. {
  233. { X86_DI, X86_EDI, 0, 0xffff }, // DI register
  234. { X86_SI, X86_ESI, 0, 0xffff }, // SI register
  235. { X86_BX, X86_EBX, 0, 0xffff }, // BX register
  236. { X86_DX, X86_EDX, 0, 0xffff }, // DX register
  237. { X86_CX, X86_ECX, 0, 0xffff }, // CX register
  238. { X86_AX, X86_EAX, 0, 0xffff }, // AX register
  239. { X86_BP, X86_EBP, 0, 0xffff }, // BP register
  240. { X86_IP, X86_EIP, 0, 0xffff }, // IP register
  241. { X86_FL, X86_EFL, 0, 0xffff }, // FL register
  242. { X86_SP, X86_ESP, 0, 0xffff }, // SP register
  243. { X86_BL, X86_EBX, 0, 0xff }, // BL register
  244. { X86_DL, X86_EDX, 0, 0xff }, // DL register
  245. { X86_CL, X86_ECX, 0, 0xff }, // CL register
  246. { X86_AL, X86_EAX, 0, 0xff }, // AL register
  247. { X86_BH, X86_EBX, 8, 0xff }, // BH register
  248. { X86_DH, X86_EDX, 8, 0xff }, // DH register
  249. { X86_CH, X86_ECX, 8, 0xff }, // CH register
  250. { X86_AH, X86_EAX, 8, 0xff }, // AH register
  251. { X86_IOPL, X86_EFL,12, 3 }, // IOPL level value
  252. { X86_OF, X86_EFL,11, 1 }, // OF (overflow flag)
  253. { X86_DF, X86_EFL,10, 1 }, // DF (direction flag)
  254. { X86_IF, X86_EFL, 9, 1 }, // IF (interrupt enable flag)
  255. { X86_TF, X86_EFL, 8, 1 }, // TF (trace flag)
  256. { X86_SF, X86_EFL, 7, 1 }, // SF (sign flag)
  257. { X86_ZF, X86_EFL, 6, 1 }, // ZF (zero flag)
  258. { X86_AF, X86_EFL, 4, 1 }, // AF (aux carry flag)
  259. { X86_PF, X86_EFL, 2, 1 }, // PF (parity flag)
  260. { X86_CF, X86_EFL, 0, 1 }, // CF (carry flag)
  261. { X86_VIP, X86_EFL,20, 1 }, // VIP (virtual interrupt pending)
  262. { X86_VIF, X86_EFL,19, 1 }, // VIF (virtual interrupt flag)
  263. { REG_ERROR, REG_ERROR, 0, 0 }
  264. };
  265. RegisterGroup g_X86BaseGroup =
  266. {
  267. NULL, 0, g_X86Defs, g_X86SubDefs, g_X86AllExtraDesc
  268. };
  269. RegisterGroup g_X86KernelGroup =
  270. {
  271. NULL, 0, g_X86KernelReg, NULL, g_X86KernelExtraDesc
  272. };
  273. // First ExecTypes entry must be the actual processor type.
  274. ULONG g_X86ExecTypes[] =
  275. {
  276. IMAGE_FILE_MACHINE_I386
  277. };
  278. X86MachineInfo g_X86Machine;
  279. HRESULT
  280. X86MachineInfo::InitializeConstants(void)
  281. {
  282. m_FullName = "x86 compatible";
  283. m_AbbrevName = "x86";
  284. m_PageSize = X86_PAGE_SIZE;
  285. m_PageShift = X86_PAGE_SHIFT;
  286. m_NumExecTypes = 1;
  287. m_ExecTypes = g_X86ExecTypes;
  288. m_Ptr64 = FALSE;
  289. m_AllMask = REGALL_INT32 | REGALL_SEGREG,
  290. m_MaxDataBreakpoints = 4;
  291. m_SymPrefix = NULL;
  292. m_SupportsBranchTrace = FALSE;
  293. return MachineInfo::InitializeConstants();
  294. }
  295. HRESULT
  296. X86MachineInfo::InitializeForTarget(void)
  297. {
  298. m_Groups = &g_X86BaseGroup;
  299. g_X86BaseGroup.Next = NULL;
  300. if (IS_KERNEL_TARGET())
  301. {
  302. g_X86BaseGroup.Next = &g_X86KernelGroup;
  303. }
  304. m_OffsetPrcbProcessorState =
  305. FIELD_OFFSET(X86_PARTIAL_KPRCB, ProcessorState);
  306. m_OffsetPrcbNumber =
  307. FIELD_OFFSET(X86_PARTIAL_KPRCB, Number);
  308. m_TriagePrcbOffset = EXTEND64(X86_TRIAGE_PRCB_ADDRESS);
  309. if (g_SystemVersion > NT_SVER_NT4)
  310. {
  311. m_SizePrcb = X86_NT5_KPRCB_SIZE;
  312. }
  313. else
  314. {
  315. m_SizePrcb = X86_NT4_KPRCB_SIZE;
  316. }
  317. m_OffsetKThreadApcProcess =
  318. FIELD_OFFSET(CROSS_PLATFORM_THREAD, X86Thread.ApcState.Process);
  319. m_OffsetKThreadTeb =
  320. FIELD_OFFSET(CROSS_PLATFORM_THREAD, X86Thread.Teb);
  321. m_OffsetKThreadInitialStack =
  322. FIELD_OFFSET(CROSS_PLATFORM_THREAD, X86Thread.InitialStack);
  323. m_OffsetEprocessPeb = g_SystemVersion > NT_SVER_NT4 ?
  324. X86_PEB_IN_EPROCESS : X86_NT4_PEB_IN_EPROCESS;
  325. m_OffsetEprocessDirectoryTableBase =
  326. X86_DIRECTORY_TABLE_BASE_IN_EPROCESS;
  327. if (g_TargetBuildNumber > 2407)
  328. {
  329. m_OffsetKThreadNextProcessor = X86_NT51_KTHREAD_NEXTPROCESSOR_OFFSET;
  330. }
  331. else if (g_TargetBuildNumber > 2230)
  332. {
  333. m_OffsetKThreadNextProcessor = X86_2230_KTHREAD_NEXTPROCESSOR_OFFSET;
  334. }
  335. else
  336. {
  337. m_OffsetKThreadNextProcessor = X86_KTHREAD_NEXTPROCESSOR_OFFSET;
  338. }
  339. if (g_SystemVersion > NT_SVER_NT4)
  340. {
  341. m_SizeTargetContext = sizeof(X86_NT5_CONTEXT);
  342. m_OffsetTargetContextFlags =
  343. FIELD_OFFSET(X86_NT5_CONTEXT, ContextFlags);
  344. }
  345. else
  346. {
  347. m_SizeTargetContext = sizeof(X86_CONTEXT);
  348. m_OffsetTargetContextFlags =
  349. FIELD_OFFSET(X86_CONTEXT, ContextFlags);
  350. }
  351. m_SizeCanonicalContext = sizeof(X86_NT5_CONTEXT);
  352. m_SverCanonicalContext = NT_SVER_W2K;
  353. m_SizeControlReport = sizeof(X86_DBGKD_CONTROL_REPORT);
  354. if (g_TargetBuildNumber > 2407)
  355. {
  356. m_SizeEThread = X86_NT51_ETHREAD_SIZE;
  357. }
  358. else
  359. {
  360. m_SizeEThread = X86_ETHREAD_SIZE;
  361. }
  362. m_SizeEProcess = g_SystemVersion > NT_SVER_W2K ?
  363. X86_NT51_EPROCESS_SIZE : X86_NT5_EPROCESS_SIZE;
  364. m_OffsetSpecialRegisters = m_SizeTargetContext;
  365. m_SizeKspecialRegisters = sizeof(X86_KSPECIAL_REGISTERS);
  366. m_SizePartialKThread = sizeof(X86_THREAD);
  367. m_SharedUserDataOffset = IS_KERNEL_TARGET() ?
  368. EXTEND64(X86_KI_USER_SHARED_DATA) : MM_SHARED_USER_DATA_VA;
  369. return MachineInfo::InitializeForTarget();
  370. }
  371. HRESULT
  372. X86MachineInfo::InitializeForProcessor(void)
  373. {
  374. if (!strcmp(g_InitProcessorId.X86.VendorString, "GenuineIntel"))
  375. {
  376. // Branch trace support was added for the Pentium Pro.
  377. m_SupportsBranchTrace = g_InitProcessorId.X86.Family >= 6;
  378. }
  379. return MachineInfo::InitializeForProcessor();
  380. }
  381. void
  382. X86MachineInfo::
  383. InitializeContext(ULONG64 Pc,
  384. PDBGKD_ANY_CONTROL_REPORT ControlReport)
  385. {
  386. ULONG Pc32 = (ULONG)Pc;
  387. m_Context.X86Nt5Context.Eip = Pc32;
  388. m_ContextState = Pc32 ? MCTX_PC : MCTX_NONE;
  389. if (ControlReport != NULL)
  390. {
  391. BpOut("InitializeContext(%d) DR6 %X DR7 %X\n",
  392. g_RegContextProcessor, ControlReport->X86ControlReport.Dr6,
  393. ControlReport->X86ControlReport.Dr7);
  394. m_Context.X86Nt5Context.Dr6 = ControlReport->X86ControlReport.Dr6;
  395. m_Context.X86Nt5Context.Dr7 = ControlReport->X86ControlReport.Dr7;
  396. m_ContextState = MCTX_DR67_REPORT;
  397. if (ControlReport->X86ControlReport.ReportFlags &
  398. X86_REPORT_INCLUDES_SEGS)
  399. {
  400. //
  401. // This is for backwards compatibility - older kernels
  402. // won't pass these registers in the report record.
  403. //
  404. m_Context.X86Nt5Context.SegCs =
  405. ControlReport->X86ControlReport.SegCs;
  406. m_Context.X86Nt5Context.SegDs =
  407. ControlReport->X86ControlReport.SegDs;
  408. m_Context.X86Nt5Context.SegEs =
  409. ControlReport->X86ControlReport.SegEs;
  410. m_Context.X86Nt5Context.SegFs =
  411. ControlReport->X86ControlReport.SegFs;
  412. m_Context.X86Nt5Context.EFlags =
  413. ControlReport->X86ControlReport.EFlags;
  414. m_ContextState = MCTX_REPORT;
  415. }
  416. }
  417. if (!IS_CONTEXT_POSSIBLE())
  418. {
  419. g_X86InVm86 = FALSE;
  420. g_X86InCode16 = FALSE;
  421. }
  422. else
  423. {
  424. // Check whether we're currently in V86 mode or 16-bit code.
  425. g_X86InVm86 = X86_IS_VM86(GetIntReg(X86_EFL));
  426. if (IS_KERNEL_TARGET() && !g_X86InVm86)
  427. {
  428. if (ControlReport == NULL ||
  429. (ControlReport->X86ControlReport.ReportFlags &
  430. X86_REPORT_STANDARD_CS) == 0)
  431. {
  432. DESCRIPTOR64 Desc;
  433. if (GetSegRegDescriptor(SEGREG_CODE, &Desc) != S_OK)
  434. {
  435. WarnOut("CS descriptor lookup failed\n");
  436. g_X86InCode16 = FALSE;
  437. }
  438. else
  439. {
  440. g_X86InCode16 = (Desc.Flags & X86_DESC_DEFAULT_BIG) == 0;
  441. }
  442. }
  443. else
  444. {
  445. g_X86InCode16 = FALSE;
  446. // We're in a standard code segment so cache
  447. // a default descriptor for CS to avoid further
  448. // CS lookups.
  449. EmulateNtSelDescriptor(this, m_Context.X86Nt5Context.SegCs,
  450. &m_SegRegDesc[SEGREG_CODE]);
  451. }
  452. }
  453. }
  454. // Add instructions to cache only if we're in 32-bit flat mode.
  455. if (Pc32 && ControlReport != NULL &&
  456. !g_X86InVm86 && !g_X86InCode16)
  457. {
  458. CacheReportInstructions
  459. (Pc, ControlReport->X86ControlReport.InstructionCount,
  460. ControlReport->X86ControlReport.InstructionStream);
  461. }
  462. }
  463. HRESULT
  464. X86MachineInfo::KdGetContextState(ULONG State)
  465. {
  466. HRESULT Status;
  467. if (State >= MCTX_CONTEXT && m_ContextState < MCTX_CONTEXT)
  468. {
  469. Status = g_Target->GetContext(g_RegContextThread->Handle, &m_Context);
  470. if (Status != S_OK)
  471. {
  472. return Status;
  473. }
  474. // XXX drewb - Temporary log to try and catch some
  475. // SET_OF_INVALID_CONTEXT bugchecks occurring randomly on x86.
  476. *g_EspLogCur++ = g_RegContextProcessor | 0x80000000;
  477. *g_EspLogCur++ = m_Context.X86Nt5Context.Esp;
  478. if (g_EspLogCur >= g_EspLog + 64)
  479. {
  480. g_EspLogCur = g_EspLog;
  481. }
  482. m_ContextState = MCTX_CONTEXT;
  483. }
  484. if (State >= MCTX_FULL && m_ContextState < MCTX_FULL)
  485. {
  486. Status = g_Target->GetTargetSpecialRegisters
  487. (g_RegContextThread->Handle, (PCROSS_PLATFORM_KSPECIAL_REGISTERS)
  488. &m_SpecialRegContext);
  489. if (Status != S_OK)
  490. {
  491. return Status;
  492. }
  493. Status = g_Target->GetTargetSegRegDescriptors
  494. (g_RegContextThread->Handle, 0, SEGREG_COUNT, m_SegRegDesc);
  495. if (Status != S_OK)
  496. {
  497. return Status;
  498. }
  499. m_ContextState = MCTX_FULL;
  500. KdSetSpecialRegistersInContext();
  501. BpOut("GetContextState(%d) DR6 %X DR7 %X DR0 %X\n",
  502. g_RegContextProcessor, m_SpecialRegContext.KernelDr6,
  503. m_SpecialRegContext.KernelDr7, m_SpecialRegContext.KernelDr0);
  504. }
  505. return S_OK;
  506. }
  507. HRESULT
  508. X86MachineInfo::KdSetContext(void)
  509. {
  510. HRESULT Status;
  511. // XXX drewb - Temporary log to try and catch some
  512. // SET_OF_INVALID_CONTEXT bugchecks occurring randomly on x86.
  513. *g_EspLogCur++ = g_RegContextProcessor | 0xC0000000;
  514. *g_EspLogCur++ = m_Context.X86Nt5Context.Esp;
  515. if (g_EspLogCur >= g_EspLog + 64)
  516. {
  517. g_EspLogCur = g_EspLog;
  518. }
  519. Status = g_Target->SetContext(g_RegContextThread->Handle, &m_Context);
  520. if (Status != S_OK)
  521. {
  522. return Status;
  523. }
  524. KdGetSpecialRegistersFromContext();
  525. Status = g_Target->SetTargetSpecialRegisters
  526. (g_RegContextThread->Handle, (PCROSS_PLATFORM_KSPECIAL_REGISTERS)
  527. &m_SpecialRegContext);
  528. if (Status != S_OK)
  529. {
  530. return Status;
  531. }
  532. BpOut("SetContext(%d) DR6 %X DR7 %X DR0 %X\n",
  533. g_RegContextProcessor, m_SpecialRegContext.KernelDr6,
  534. m_SpecialRegContext.KernelDr7, m_SpecialRegContext.KernelDr0);
  535. return S_OK;
  536. }
  537. HRESULT
  538. X86MachineInfo::ConvertContextFrom(PCROSS_PLATFORM_CONTEXT Context,
  539. ULONG FromSver, ULONG FromSize, PVOID From)
  540. {
  541. if (FromSver <= NT_SVER_NT4)
  542. {
  543. if (FromSize < sizeof(X86_CONTEXT))
  544. {
  545. return E_INVALIDARG;
  546. }
  547. memcpy(Context, From, sizeof(X86_CONTEXT));
  548. ZeroMemory(Context->X86Nt5Context.ExtendedRegisters,
  549. sizeof(Context->X86Nt5Context.ExtendedRegisters));
  550. }
  551. else if (FromSize >= sizeof(X86_NT5_CONTEXT))
  552. {
  553. memcpy(Context, From, sizeof(X86_NT5_CONTEXT));
  554. }
  555. else
  556. {
  557. return E_INVALIDARG;
  558. }
  559. return S_OK;
  560. }
  561. HRESULT
  562. X86MachineInfo::ConvertContextTo(PCROSS_PLATFORM_CONTEXT Context,
  563. ULONG ToSver, ULONG ToSize, PVOID To)
  564. {
  565. if (ToSver <= NT_SVER_NT4)
  566. {
  567. if (ToSize < sizeof(X86_CONTEXT))
  568. {
  569. return E_INVALIDARG;
  570. }
  571. memcpy(To, Context, sizeof(X86_CONTEXT));
  572. }
  573. else if (ToSize >= sizeof(X86_NT5_CONTEXT))
  574. {
  575. memcpy(To, Context, sizeof(X86_NT5_CONTEXT));
  576. }
  577. else
  578. {
  579. return E_INVALIDARG;
  580. }
  581. return S_OK;
  582. }
  583. void
  584. X86MachineInfo::InitializeContextFlags(PCROSS_PLATFORM_CONTEXT Context,
  585. ULONG Version)
  586. {
  587. ULONG ContextFlags;
  588. ContextFlags = VDMCONTEXT_CONTROL | VDMCONTEXT_INTEGER |
  589. VDMCONTEXT_SEGMENTS | VDMCONTEXT_FLOATING_POINT;
  590. if (IS_USER_TARGET())
  591. {
  592. ContextFlags |= VDMCONTEXT_DEBUG_REGISTERS;
  593. }
  594. if (Version <= NT_SVER_NT4)
  595. {
  596. Context->X86Context.ContextFlags = ContextFlags;
  597. }
  598. else
  599. {
  600. Context->X86Nt5Context.ContextFlags = ContextFlags |
  601. VDMCONTEXT_EXTENDED_REGISTERS;
  602. }
  603. }
  604. HRESULT
  605. X86MachineInfo::GetContextFromThreadStack(ULONG64 ThreadBase,
  606. PCROSS_PLATFORM_THREAD Thread,
  607. PCROSS_PLATFORM_CONTEXT Context,
  608. PDEBUG_STACK_FRAME Frame,
  609. PULONG RunningOnProc)
  610. {
  611. HRESULT Status;
  612. UCHAR Proc;
  613. //
  614. // Check to see if the thread is currently running.
  615. //
  616. if (Thread->X86Thread.State == 2)
  617. {
  618. if ((Status = g_Target->ReadAllVirtual
  619. (ThreadBase + m_OffsetKThreadNextProcessor,
  620. &Proc, sizeof(Proc))) != S_OK)
  621. {
  622. return Status;
  623. }
  624. *RunningOnProc = Proc;
  625. return S_FALSE;
  626. }
  627. //
  628. // The thread isn't running so read its stored context information.
  629. //
  630. X86_KSWITCHFRAME SwitchFrame;
  631. if ((Status = g_Target->ReadAllVirtual(Thread->X86Thread.KernelStack,
  632. &SwitchFrame,
  633. sizeof(SwitchFrame))) != S_OK)
  634. {
  635. return Status;
  636. }
  637. Frame->InstructionOffset = EXTEND64(SwitchFrame.RetAddr);
  638. Frame->StackOffset =
  639. Thread->X86Thread.KernelStack + sizeof(SwitchFrame);
  640. if ((Status = g_Target->ReadPointer(this, Frame->StackOffset,
  641. &Frame->FrameOffset)) != S_OK)
  642. {
  643. return Status;
  644. }
  645. Context->X86Context.Ebp = (ULONG)Frame->FrameOffset;
  646. Context->X86Context.Esp = (ULONG)Frame->StackOffset;
  647. // Fill the segments in from current information
  648. // instead of just leaving them blank.
  649. Context->X86Context.SegSs = GetIntReg(X86_SS);
  650. Context->X86Context.SegCs = GetIntReg(X86_CS);
  651. Context->X86Context.Eip = (ULONG)Frame->InstructionOffset;
  652. return S_OK;
  653. }
  654. HRESULT
  655. X86MachineInfo::GetExdiContext(IUnknown* Exdi, PEXDI_CONTEXT Context)
  656. {
  657. // Always ask for everything.
  658. Context->X86Context.RegGroupSelection.fSegmentRegs = TRUE;
  659. Context->X86Context.RegGroupSelection.fControlRegs = TRUE;
  660. Context->X86Context.RegGroupSelection.fIntegerRegs = TRUE;
  661. Context->X86Context.RegGroupSelection.fFloatingPointRegs = TRUE;
  662. Context->X86Context.RegGroupSelection.fDebugRegs = TRUE;
  663. return ((IeXdiX86Context*)Exdi)->GetContext(&Context->X86Context);
  664. }
  665. HRESULT
  666. X86MachineInfo::SetExdiContext(IUnknown* Exdi, PEXDI_CONTEXT Context)
  667. {
  668. // Don't change the existing group selections on the assumption
  669. // that there was a full get prior to any modifications so
  670. // all groups are valid.
  671. return ((IeXdiX86Context*)Exdi)->SetContext(Context->X86Context);
  672. }
  673. void
  674. X86MachineInfo::ConvertExdiContextFromContext(PCROSS_PLATFORM_CONTEXT Context,
  675. PEXDI_CONTEXT ExdiContext)
  676. {
  677. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_SEGMENTS)
  678. {
  679. ExdiContext->X86Context.SegGs = (USHORT)Context->X86Nt5Context.SegGs;
  680. ExdiContext->X86Context.SegFs = (USHORT)Context->X86Nt5Context.SegFs;
  681. ExdiContext->X86Context.SegEs = (USHORT)Context->X86Nt5Context.SegEs;
  682. ExdiContext->X86Context.SegDs = (USHORT)Context->X86Nt5Context.SegDs;
  683. }
  684. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_CONTROL)
  685. {
  686. ExdiContext->X86Context.Ebp = Context->X86Nt5Context.Ebp;
  687. ExdiContext->X86Context.Eip = Context->X86Nt5Context.Eip;
  688. ExdiContext->X86Context.SegCs = (USHORT)Context->X86Nt5Context.SegCs;
  689. ExdiContext->X86Context.EFlags = Context->X86Nt5Context.EFlags;
  690. ExdiContext->X86Context.Esp = Context->X86Nt5Context.Esp;
  691. ExdiContext->X86Context.SegSs = (USHORT)Context->X86Nt5Context.SegSs;
  692. }
  693. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_INTEGER)
  694. {
  695. ExdiContext->X86Context.Eax = Context->X86Nt5Context.Eax;
  696. ExdiContext->X86Context.Ebx = Context->X86Nt5Context.Ebx;
  697. ExdiContext->X86Context.Ecx = Context->X86Nt5Context.Ecx;
  698. ExdiContext->X86Context.Edx = Context->X86Nt5Context.Edx;
  699. ExdiContext->X86Context.Esi = Context->X86Nt5Context.Esi;
  700. ExdiContext->X86Context.Edi = Context->X86Nt5Context.Edi;
  701. }
  702. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_FLOATING_POINT)
  703. {
  704. C_ASSERT(sizeof(X86_FLOATING_SAVE_AREA) ==
  705. FIELD_OFFSET(CONTEXT_X86, Dr0) -
  706. FIELD_OFFSET(CONTEXT_X86, ControlWord));
  707. memcpy(&ExdiContext->X86Context.ControlWord,
  708. &Context->X86Nt5Context.FloatSave,
  709. sizeof(X86_FLOATING_SAVE_AREA));
  710. }
  711. if (Context->X86Nt5Context.ContextFlags & VDMCONTEXT_DEBUG_REGISTERS)
  712. {
  713. ExdiContext->X86Context.Dr0 = Context->X86Nt5Context.Dr0;
  714. ExdiContext->X86Context.Dr1 = Context->X86Nt5Context.Dr1;
  715. ExdiContext->X86Context.Dr2 = Context->X86Nt5Context.Dr2;
  716. ExdiContext->X86Context.Dr3 = Context->X86Nt5Context.Dr3;
  717. ExdiContext->X86Context.Dr6 = Context->X86Nt5Context.Dr6;
  718. ExdiContext->X86Context.Dr7 = Context->X86Nt5Context.Dr7;
  719. }
  720. }
  721. void
  722. X86MachineInfo::ConvertExdiContextToContext(PEXDI_CONTEXT ExdiContext,
  723. PCROSS_PLATFORM_CONTEXT Context)
  724. {
  725. Context->X86Nt5Context.SegCs = ExdiContext->X86Context.SegCs;
  726. Context->X86Nt5Context.SegSs = ExdiContext->X86Context.SegSs;
  727. Context->X86Nt5Context.SegGs = ExdiContext->X86Context.SegGs;
  728. Context->X86Nt5Context.SegFs = ExdiContext->X86Context.SegFs;
  729. Context->X86Nt5Context.SegEs = ExdiContext->X86Context.SegEs;
  730. Context->X86Nt5Context.SegDs = ExdiContext->X86Context.SegDs;
  731. Context->X86Nt5Context.EFlags = ExdiContext->X86Context.EFlags;
  732. Context->X86Nt5Context.Ebp = ExdiContext->X86Context.Ebp;
  733. Context->X86Nt5Context.Eip = ExdiContext->X86Context.Eip;
  734. Context->X86Nt5Context.Esp = ExdiContext->X86Context.Esp;
  735. Context->X86Nt5Context.Eax = ExdiContext->X86Context.Eax;
  736. Context->X86Nt5Context.Ebx = ExdiContext->X86Context.Ebx;
  737. Context->X86Nt5Context.Ecx = ExdiContext->X86Context.Ecx;
  738. Context->X86Nt5Context.Edx = ExdiContext->X86Context.Edx;
  739. Context->X86Nt5Context.Esi = ExdiContext->X86Context.Esi;
  740. Context->X86Nt5Context.Edi = ExdiContext->X86Context.Edi;
  741. C_ASSERT(sizeof(X86_FLOATING_SAVE_AREA) ==
  742. FIELD_OFFSET(CONTEXT_X86, Dr0) -
  743. FIELD_OFFSET(CONTEXT_X86, ControlWord));
  744. memcpy(&Context->X86Nt5Context.FloatSave,
  745. &ExdiContext->X86Context.ControlWord,
  746. sizeof(X86_FLOATING_SAVE_AREA));
  747. Context->X86Nt5Context.Dr0 = ExdiContext->X86Context.Dr0;
  748. Context->X86Nt5Context.Dr1 = ExdiContext->X86Context.Dr1;
  749. Context->X86Nt5Context.Dr2 = ExdiContext->X86Context.Dr2;
  750. Context->X86Nt5Context.Dr3 = ExdiContext->X86Context.Dr3;
  751. Context->X86Nt5Context.Dr6 = ExdiContext->X86Context.Dr6;
  752. Context->X86Nt5Context.Dr7 = ExdiContext->X86Context.Dr7;
  753. }
  754. void
  755. X86MachineInfo::ConvertExdiContextToSegDescs(PEXDI_CONTEXT ExdiContext,
  756. ULONG Start, ULONG Count,
  757. PDESCRIPTOR64 Descs)
  758. {
  759. // XXX drewb - Temporary hack to report boot-time 16-bit
  760. // segment state. The new x86 context should report
  761. // segment descriptors.
  762. while (Count-- > 0)
  763. {
  764. ULONG Type;
  765. if (Start == SEGREG_CODE)
  766. {
  767. Descs->Base = EXTEND64(0xffff0000);
  768. Type = 0x13;
  769. }
  770. else
  771. {
  772. Descs->Base = 0;
  773. Type = 0x1b;
  774. }
  775. Descs->Limit = 0xfffff;
  776. Descs->Flags = X86_DESC_PRESENT | Type;
  777. Descs++;
  778. Start++;
  779. }
  780. }
  781. void
  782. X86MachineInfo::ConvertExdiContextFromSpecial
  783. (PCROSS_PLATFORM_KSPECIAL_REGISTERS Special,
  784. PEXDI_CONTEXT ExdiContext)
  785. {
  786. // XXX drewb - Implement when the new x86 context is
  787. // available and provides the appropriate information.
  788. }
  789. void
  790. X86MachineInfo::ConvertExdiContextToSpecial
  791. (PEXDI_CONTEXT ExdiContext,
  792. PCROSS_PLATFORM_KSPECIAL_REGISTERS Special)
  793. {
  794. // XXX drewb - Implement when the new x86 context is
  795. // available and provides the appropriate information.
  796. }
  797. int
  798. X86MachineInfo::GetType(ULONG regnum)
  799. {
  800. if (regnum >= X86_MM_FIRST && regnum <= X86_MM_LAST)
  801. {
  802. return REGVAL_INT64;
  803. }
  804. else if (regnum >= X86_XMM_FIRST && regnum <= X86_XMM_LAST)
  805. {
  806. return REGVAL_VECTOR128;
  807. }
  808. else if (regnum >= X86_ST_FIRST && regnum <= X86_ST_LAST)
  809. {
  810. return REGVAL_FLOAT10;
  811. }
  812. else if (regnum < X86_FLAGBASE)
  813. {
  814. return REGVAL_INT32;
  815. }
  816. else
  817. {
  818. return REGVAL_SUB32;
  819. }
  820. }
  821. /*** X86GetVal - get register value
  822. *
  823. * Purpose:
  824. * Return the value of the specified register.
  825. *
  826. * Input:
  827. * regnum - register specification
  828. *
  829. * Returns:
  830. * Value of register.
  831. *
  832. *************************************************************************/
  833. BOOL
  834. X86MachineInfo::GetVal (
  835. ULONG regnum,
  836. REGVAL *val
  837. )
  838. {
  839. if (regnum >= X86_MM_FIRST && regnum <= X86_MM_LAST)
  840. {
  841. val->type = REGVAL_VECTOR64;
  842. GetMmxReg(regnum, val);
  843. }
  844. else if (regnum >= X86_XMM_FIRST && regnum <= X86_XMM_LAST)
  845. {
  846. if (GetContextState(MCTX_CONTEXT) != S_OK)
  847. {
  848. return FALSE;
  849. }
  850. val->type = REGVAL_VECTOR128;
  851. memcpy(val->bytes, m_Context.X86Nt5Context.FxSave.Reserved3 +
  852. (regnum - X86_XMM_FIRST) * 16, 16);
  853. }
  854. else if (regnum >= X86_ST_FIRST && regnum <= X86_ST_LAST)
  855. {
  856. val->type = REGVAL_FLOAT10;
  857. GetFloatReg(regnum, val);
  858. }
  859. else if (regnum < X86_FLAGBASE)
  860. {
  861. val->type = REGVAL_INT32;
  862. val->i64 = (ULONG64)(LONG64)(LONG)GetIntReg(regnum);
  863. }
  864. else
  865. {
  866. ErrOut("X86MachineInfo::GetVal: "
  867. "unknown register %lx requested\n", regnum);
  868. return FALSE;
  869. }
  870. return TRUE;
  871. }
  872. /*** X86SetVal - set register value
  873. *
  874. * Purpose:
  875. * Set the value of the specified register.
  876. *
  877. * Input:
  878. * regnum - register specification
  879. * val - new register value
  880. *
  881. * Output:
  882. * None.
  883. *
  884. * Notes:
  885. *
  886. *************************************************************************/
  887. BOOL
  888. X86MachineInfo::SetVal (ULONG regnum, REGVAL *val)
  889. {
  890. if (m_ContextIsReadOnly)
  891. {
  892. return FALSE;
  893. }
  894. if (regnum >= X86_FLAGBASE)
  895. {
  896. return FALSE;
  897. }
  898. // Optimize away some common cases where registers are
  899. // set to their current value.
  900. if ((m_ContextState >= MCTX_PC && regnum == X86_EIP &&
  901. val->i32 == m_Context.X86Nt5Context.Eip) ||
  902. (((m_ContextState >= MCTX_DR67_REPORT &&
  903. m_ContextState <= MCTX_REPORT) ||
  904. m_ContextState >= MCTX_FULL) && regnum == X86_DR7 &&
  905. val->i32 == m_Context.X86Nt5Context.Dr7))
  906. {
  907. return TRUE;
  908. }
  909. if (GetContextState(MCTX_DIRTY) != S_OK)
  910. {
  911. return FALSE;
  912. }
  913. if (regnum >= X86_MM_FIRST && regnum <= X86_MM_LAST)
  914. {
  915. *(ULONG64 UNALIGNED *)GetMmxRegSlot(regnum) = val->i64;
  916. goto Notify;
  917. }
  918. else if (regnum >= X86_XMM_FIRST && regnum <= X86_XMM_LAST)
  919. {
  920. memcpy(m_Context.X86Nt5Context.FxSave.Reserved3 +
  921. (regnum - X86_XMM_FIRST) * 16, val->bytes, 16);
  922. goto Notify;
  923. }
  924. else if (regnum >= X86_ST_FIRST && regnum <= X86_ST_LAST)
  925. {
  926. memcpy(m_Context.X86Nt5Context.FloatSave.RegisterArea +
  927. 10 * (regnum - X86_ST_FIRST), val->f10, sizeof(val->f10));
  928. goto Notify;
  929. }
  930. BOOL Recognized;
  931. Recognized = TRUE;
  932. switch (regnum)
  933. {
  934. case X86_GS:
  935. m_Context.X86Nt5Context.SegGs = val->i16;
  936. m_SegRegDesc[SEGREG_GS].Flags = SEGDESC_INVALID;
  937. break;
  938. case X86_FS:
  939. m_Context.X86Nt5Context.SegFs = val->i16;
  940. m_SegRegDesc[SEGREG_FS].Flags = SEGDESC_INVALID;
  941. break;
  942. case X86_ES:
  943. m_Context.X86Nt5Context.SegEs = val->i16;
  944. m_SegRegDesc[SEGREG_ES].Flags = SEGDESC_INVALID;
  945. break;
  946. case X86_DS:
  947. m_Context.X86Nt5Context.SegDs = val->i16;
  948. m_SegRegDesc[SEGREG_DATA].Flags = SEGDESC_INVALID;
  949. break;
  950. case X86_EDI:
  951. m_Context.X86Nt5Context.Edi = val->i32;
  952. break;
  953. case X86_ESI:
  954. m_Context.X86Nt5Context.Esi = val->i32;
  955. break;
  956. case X86_EBX:
  957. m_Context.X86Nt5Context.Ebx = val->i32;
  958. break;
  959. case X86_EDX:
  960. m_Context.X86Nt5Context.Edx = val->i32;
  961. break;
  962. case X86_ECX:
  963. m_Context.X86Nt5Context.Ecx = val->i32;
  964. break;
  965. case X86_EAX:
  966. m_Context.X86Nt5Context.Eax = val->i32;
  967. break;
  968. case X86_EBP:
  969. m_Context.X86Nt5Context.Ebp = val->i32;
  970. break;
  971. case X86_EIP:
  972. m_Context.X86Nt5Context.Eip = val->i32;
  973. break;
  974. case X86_CS:
  975. m_Context.X86Nt5Context.SegCs = val->i16;
  976. m_SegRegDesc[SEGREG_CODE].Flags = SEGDESC_INVALID;
  977. break;
  978. case X86_EFL:
  979. if (IS_KERNEL_TARGET())
  980. {
  981. // leave TF clear
  982. m_Context.X86Nt5Context.EFlags = val->i32 & ~0x100;
  983. }
  984. else
  985. {
  986. // allow TF set
  987. m_Context.X86Nt5Context.EFlags = val->i32;
  988. }
  989. break;
  990. case X86_ESP:
  991. m_Context.X86Nt5Context.Esp = val->i32;
  992. break;
  993. case X86_SS:
  994. m_Context.X86Nt5Context.SegSs = val->i16;
  995. m_SegRegDesc[SEGREG_STACK].Flags = SEGDESC_INVALID;
  996. break;
  997. case X86_DR0:
  998. m_Context.X86Nt5Context.Dr0 = val->i32;
  999. break;
  1000. case X86_DR1:
  1001. m_Context.X86Nt5Context.Dr1 = val->i32;
  1002. break;
  1003. case X86_DR2:
  1004. m_Context.X86Nt5Context.Dr2 = val->i32;
  1005. break;
  1006. case X86_DR3:
  1007. m_Context.X86Nt5Context.Dr3 = val->i32;
  1008. break;
  1009. case X86_DR6:
  1010. m_Context.X86Nt5Context.Dr6 = val->i32;
  1011. break;
  1012. case X86_DR7:
  1013. m_Context.X86Nt5Context.Dr7 = val->i32;
  1014. break;
  1015. case X86_FPCW:
  1016. m_Context.X86Nt5Context.FloatSave.ControlWord =
  1017. (m_Context.X86Nt5Context.FloatSave.ControlWord & 0xffff0000) |
  1018. (val->i32 & 0xffff);
  1019. break;
  1020. case X86_FPSW:
  1021. m_Context.X86Nt5Context.FloatSave.StatusWord =
  1022. (m_Context.X86Nt5Context.FloatSave.StatusWord & 0xffff0000) |
  1023. (val->i32 & 0xffff);
  1024. break;
  1025. case X86_FPTW:
  1026. m_Context.X86Nt5Context.FloatSave.TagWord =
  1027. (m_Context.X86Nt5Context.FloatSave.TagWord & 0xffff0000) |
  1028. (val->i32 & 0xffff);
  1029. break;
  1030. case X86_MXCSR:
  1031. m_Context.X86Nt5Context.FxSave.MXCsr = val->i32;
  1032. break;
  1033. default:
  1034. Recognized = FALSE;
  1035. break;
  1036. }
  1037. if (!Recognized && IS_KERNEL_TARGET())
  1038. {
  1039. Recognized = TRUE;
  1040. switch(regnum)
  1041. {
  1042. case X86_CR0:
  1043. m_SpecialRegContext.Cr0 = val->i32;
  1044. break;
  1045. case X86_CR2:
  1046. m_SpecialRegContext.Cr2 = val->i32;
  1047. break;
  1048. case X86_CR3:
  1049. m_SpecialRegContext.Cr3 = val->i32;
  1050. break;
  1051. case X86_CR4:
  1052. m_SpecialRegContext.Cr4 = val->i32;
  1053. break;
  1054. case X86_GDTR:
  1055. m_SpecialRegContext.Gdtr.Base = val->i32;
  1056. break;
  1057. case X86_GDTL:
  1058. m_SpecialRegContext.Gdtr.Limit = (USHORT)val->i32;
  1059. break;
  1060. case X86_IDTR:
  1061. m_SpecialRegContext.Idtr.Base = val->i32;
  1062. break;
  1063. case X86_IDTL:
  1064. m_SpecialRegContext.Idtr.Limit = (USHORT)val->i32;
  1065. break;
  1066. case X86_TR:
  1067. m_SpecialRegContext.Tr = (USHORT)val->i32;
  1068. break;
  1069. case X86_LDTR:
  1070. m_SpecialRegContext.Ldtr = (USHORT)val->i32;
  1071. break;
  1072. default:
  1073. Recognized = FALSE;
  1074. break;
  1075. }
  1076. }
  1077. if (!Recognized)
  1078. {
  1079. ErrOut("X86MachineInfo::SetVal: "
  1080. "unknown register %lx requested\n", regnum);
  1081. return FALSE;
  1082. }
  1083. Notify:
  1084. NotifyChangeDebuggeeState(DEBUG_CDS_REGISTERS,
  1085. RegCountFromIndex(regnum));
  1086. return TRUE;
  1087. }
  1088. void
  1089. X86MachineInfo::GetPC (PADDR Address)
  1090. {
  1091. FormAddr(SEGREG_CODE, EXTEND64(GetIntReg(X86_EIP)),
  1092. FORM_CODE | FORM_SEGREG | X86_FORM_VM86(GetIntReg(X86_EFL)),
  1093. Address);
  1094. }
  1095. void
  1096. X86MachineInfo::SetPC (PADDR paddr)
  1097. {
  1098. REGVAL val;
  1099. // We set the EIP to the offset (the non-translated value),
  1100. // because we may not be in "flat" mode !!!
  1101. val.type = REGVAL_INT32;
  1102. val.i32 = (ULONG)Off(*paddr);
  1103. SetVal(X86_EIP, &val);
  1104. }
  1105. void
  1106. X86MachineInfo::GetFP(PADDR Addr)
  1107. {
  1108. FormAddr(SEGREG_STACK, EXTEND64(GetIntReg(X86_EBP)),
  1109. FORM_SEGREG | X86_FORM_VM86(GetIntReg(X86_EFL)), Addr);
  1110. }
  1111. void
  1112. X86MachineInfo::GetSP(PADDR Addr)
  1113. {
  1114. FormAddr(SEGREG_STACK, EXTEND64(GetIntReg(X86_ESP)),
  1115. FORM_SEGREG | X86_FORM_VM86(GetIntReg(X86_EFL)), Addr);
  1116. }
  1117. ULONG64
  1118. X86MachineInfo::GetArgReg(void)
  1119. {
  1120. return (ULONG64)(LONG64)(LONG)GetIntReg(X86_EAX);
  1121. }
  1122. ULONG
  1123. X86MachineInfo::GetSegRegNum(ULONG SegReg)
  1124. {
  1125. switch(SegReg)
  1126. {
  1127. case SEGREG_CODE:
  1128. return X86_CS;
  1129. case SEGREG_DATA:
  1130. return X86_DS;
  1131. case SEGREG_STACK:
  1132. return X86_SS;
  1133. case SEGREG_ES:
  1134. return X86_ES;
  1135. case SEGREG_FS:
  1136. return X86_FS;
  1137. case SEGREG_GS:
  1138. return X86_GS;
  1139. case SEGREG_LDT:
  1140. return X86_LDTR;
  1141. }
  1142. return 0;
  1143. }
  1144. HRESULT
  1145. X86MachineInfo::GetSegRegDescriptor(ULONG SegReg, PDESCRIPTOR64 Desc)
  1146. {
  1147. if (SegReg == SEGREG_GDT)
  1148. {
  1149. Desc->Base = EXTEND64(GetIntReg(X86_GDTR));
  1150. Desc->Limit = GetIntReg(X86_GDTL);
  1151. Desc->Flags = 0;
  1152. return S_OK;
  1153. }
  1154. // Check and see if we already have a cached descriptor.
  1155. if (m_SegRegDesc[SegReg].Flags != SEGDESC_INVALID)
  1156. {
  1157. *Desc = m_SegRegDesc[SegReg];
  1158. return S_OK;
  1159. }
  1160. HRESULT Status;
  1161. // Attempt to retrieve segment descriptors directly.
  1162. if ((Status = GetContextState(MCTX_FULL)) != S_OK)
  1163. {
  1164. return Status;
  1165. }
  1166. // Check and see if we now have a cached descriptor.
  1167. if (m_SegRegDesc[SegReg].Flags != SEGDESC_INVALID)
  1168. {
  1169. *Desc = m_SegRegDesc[SegReg];
  1170. return S_OK;
  1171. }
  1172. //
  1173. // Direct information is not available so look things up
  1174. // in the descriptor tables.
  1175. //
  1176. ULONG RegNum = GetSegRegNum(SegReg);
  1177. if (RegNum == 0)
  1178. {
  1179. return E_INVALIDARG;
  1180. }
  1181. // Do a quick sanity test to prevent bad values
  1182. // from causing problems.
  1183. ULONG Selector = GetIntReg(RegNum);
  1184. if (SegReg == SEGREG_LDT && (Selector & 4))
  1185. {
  1186. // The ldtr selector says that it's an LDT selector,
  1187. // which is invalid. An LDT selector should always
  1188. // reference the GDT.
  1189. ErrOut("Invalid LDTR contents: %04X\n", Selector);
  1190. return E_FAIL;
  1191. }
  1192. return g_Target->GetSelDescriptor(this, g_RegContextThread->Handle,
  1193. Selector, Desc);
  1194. }
  1195. /*** X86OutputAll - output all registers and present instruction
  1196. *
  1197. * Purpose:
  1198. * To output the current register state of the processor.
  1199. * All integer registers are output as well as processor status
  1200. * registers. Important flag fields are also output separately.
  1201. *
  1202. * Input:
  1203. * Mask - Which information to display.
  1204. *
  1205. * Output:
  1206. * None.
  1207. *
  1208. *************************************************************************/
  1209. void
  1210. X86MachineInfo::OutputAll(ULONG Mask, ULONG OutMask)
  1211. {
  1212. if (GetContextState(MCTX_FULL) != S_OK)
  1213. {
  1214. ErrOut("Unable to retrieve register information\n");
  1215. return;
  1216. }
  1217. if (Mask & (REGALL_INT32 | REGALL_INT64))
  1218. {
  1219. ULONG efl;
  1220. MaskOut(OutMask, "eax=%08lx ebx=%08lx ecx=%08lx "
  1221. "edx=%08lx esi=%08lx edi=%08lx\n",
  1222. GetIntReg(X86_EAX),
  1223. GetIntReg(X86_EBX),
  1224. GetIntReg(X86_ECX),
  1225. GetIntReg(X86_EDX),
  1226. GetIntReg(X86_ESI),
  1227. GetIntReg(X86_EDI));
  1228. efl = GetIntReg(X86_EFL);
  1229. MaskOut(OutMask, "eip=%08lx esp=%08lx ebp=%08lx iopl=%1lx "
  1230. "%s %s %s %s %s %s %s %s %s %s\n",
  1231. GetIntReg(X86_EIP),
  1232. GetIntReg(X86_ESP),
  1233. GetIntReg(X86_EBP),
  1234. ((efl >> X86_SHIFT_FLAGIOPL) & X86_BIT_FLAGIOPL),
  1235. (efl & X86_BIT_FLAGVIP) ? "vip" : " ",
  1236. (efl & X86_BIT_FLAGVIF) ? "vif" : " ",
  1237. (efl & X86_BIT_FLAGOF) ? "ov" : "nv",
  1238. (efl & X86_BIT_FLAGDF) ? "dn" : "up",
  1239. (efl & X86_BIT_FLAGIF) ? "ei" : "di",
  1240. (efl & X86_BIT_FLAGSF) ? "ng" : "pl",
  1241. (efl & X86_BIT_FLAGZF) ? "zr" : "nz",
  1242. (efl & X86_BIT_FLAGAF) ? "ac" : "na",
  1243. (efl & X86_BIT_FLAGPF) ? "po" : "pe",
  1244. (efl & X86_BIT_FLAGCF) ? "cy" : "nc");
  1245. }
  1246. if (Mask & REGALL_SEGREG)
  1247. {
  1248. MaskOut(OutMask, "cs=%04lx ss=%04lx ds=%04lx es=%04lx fs=%04lx "
  1249. "gs=%04lx efl=%08lx\n",
  1250. GetIntReg(X86_CS),
  1251. GetIntReg(X86_SS),
  1252. GetIntReg(X86_DS),
  1253. GetIntReg(X86_ES),
  1254. GetIntReg(X86_FS),
  1255. GetIntReg(X86_GS),
  1256. GetIntReg(X86_EFL));
  1257. }
  1258. if (Mask & REGALL_FLOAT)
  1259. {
  1260. ULONG i;
  1261. REGVAL val;
  1262. char buf[32];
  1263. MaskOut(OutMask, "fpcw=%04X fpsw=%04X fptw=%04X\n",
  1264. GetIntReg(X86_FPCW),
  1265. GetIntReg(X86_FPSW),
  1266. GetIntReg(X86_FPTW));
  1267. for (i = X86_ST_FIRST; i <= X86_ST_LAST; i++)
  1268. {
  1269. GetFloatReg(i, &val);
  1270. _uldtoa((_ULDOUBLE *)&val.f10, sizeof(buf), buf);
  1271. MaskOut(OutMask, "st%d=%s ", i - X86_ST_FIRST, buf);
  1272. i++;
  1273. GetFloatReg(i, &val);
  1274. _uldtoa((_ULDOUBLE *)&val.f10, sizeof(buf), buf);
  1275. MaskOut(OutMask, "st%d=%s\n", i - X86_ST_FIRST, buf);
  1276. }
  1277. }
  1278. if (Mask & REGALL_MMXREG)
  1279. {
  1280. ULONG i;
  1281. REGVAL val;
  1282. for (i = X86_MM_FIRST; i <= X86_MM_LAST; i++)
  1283. {
  1284. GetMmxReg(i, &val);
  1285. MaskOut(OutMask, "mm%d=%08x%08x ",
  1286. i - X86_MM_FIRST,
  1287. val.i64Parts.high, val.i64Parts.low);
  1288. i++;
  1289. GetMmxReg(i, &val);
  1290. MaskOut(OutMask, "mm%d=%08x%08x\n",
  1291. i - X86_MM_FIRST,
  1292. val.i64Parts.high, val.i64Parts.low);
  1293. }
  1294. }
  1295. if (Mask & REGALL_XMMREG)
  1296. {
  1297. ULONG i;
  1298. REGVAL Val;
  1299. for (i = X86_XMM_FIRST; i <= X86_XMM_LAST; i++)
  1300. {
  1301. GetVal(i, &Val);
  1302. MaskOut(OutMask, "xmm%d=%hg %hg %hg %hg\n", i - X86_XMM_FIRST,
  1303. *(float *)&Val.bytes[3 * sizeof(float)],
  1304. *(float *)&Val.bytes[2 * sizeof(float)],
  1305. *(float *)&Val.bytes[1 * sizeof(float)],
  1306. *(float *)&Val.bytes[0 * sizeof(float)]);
  1307. }
  1308. }
  1309. if (Mask & REGALL_CREG)
  1310. {
  1311. MaskOut(OutMask, "cr0=%08lx cr2=%08lx cr3=%08lx\n",
  1312. GetIntReg(X86_CR0),
  1313. GetIntReg(X86_CR2),
  1314. GetIntReg(X86_CR3));
  1315. }
  1316. if (Mask & REGALL_DREG)
  1317. {
  1318. MaskOut(OutMask, "dr0=%08lx dr1=%08lx dr2=%08lx\n",
  1319. GetIntReg(X86_DR0),
  1320. GetIntReg(X86_DR1),
  1321. GetIntReg(X86_DR2));
  1322. MaskOut(OutMask, "dr3=%08lx dr6=%08lx dr7=%08lx",
  1323. GetIntReg(X86_DR3),
  1324. GetIntReg(X86_DR6),
  1325. GetIntReg(X86_DR7));
  1326. if (IS_USER_TARGET())
  1327. {
  1328. MaskOut(OutMask, "\n");
  1329. }
  1330. else
  1331. {
  1332. MaskOut(OutMask, " cr4=%08lx\n", GetIntReg(X86_CR4));
  1333. }
  1334. }
  1335. if (Mask & REGALL_DESC)
  1336. {
  1337. MaskOut(OutMask, "gdtr=%08lx gdtl=%04lx idtr=%08lx idtl=%04lx "
  1338. "tr=%04lx ldtr=%04x\n",
  1339. GetIntReg(X86_GDTR),
  1340. GetIntReg(X86_GDTL),
  1341. GetIntReg(X86_IDTR),
  1342. GetIntReg(X86_IDTL),
  1343. GetIntReg(X86_TR),
  1344. GetIntReg(X86_LDTR));
  1345. }
  1346. }
  1347. TRACEMODE
  1348. X86MachineInfo::GetTraceMode (void)
  1349. {
  1350. if (IS_KERNEL_TARGET())
  1351. {
  1352. return m_TraceMode;
  1353. }
  1354. else
  1355. {
  1356. return ((GetIntReg(X86_EFL) & X86_BIT_FLAGTF) != 0) ?
  1357. TRACE_INSTRUCTION : TRACE_NONE;
  1358. }
  1359. }
  1360. void
  1361. X86MachineInfo::SetTraceMode (TRACEMODE Mode)
  1362. {
  1363. DBG_ASSERT(Mode == TRACE_NONE ||
  1364. Mode == TRACE_INSTRUCTION ||
  1365. (IS_KERNEL_TARGET() && m_SupportsBranchTrace &&
  1366. Mode == TRACE_TAKEN_BRANCH));
  1367. if (IS_KERNEL_TARGET())
  1368. {
  1369. m_TraceMode = Mode;
  1370. }
  1371. else
  1372. {
  1373. ULONG Efl = GetIntReg(X86_EFL);
  1374. switch (Mode)
  1375. {
  1376. case TRACE_NONE:
  1377. Efl &= ~X86_BIT_FLAGTF;
  1378. break;
  1379. case TRACE_INSTRUCTION:
  1380. Efl |= X86_BIT_FLAGTF;
  1381. break;
  1382. }
  1383. SetReg32(X86_EFL, Efl);
  1384. }
  1385. }
  1386. BOOL
  1387. X86MachineInfo::IsStepStatusSupported(ULONG Status)
  1388. {
  1389. switch(Status)
  1390. {
  1391. case DEBUG_STATUS_STEP_INTO:
  1392. case DEBUG_STATUS_STEP_OVER:
  1393. return TRUE;
  1394. case DEBUG_STATUS_STEP_BRANCH:
  1395. return IS_KERNEL_TARGET() && m_SupportsBranchTrace;
  1396. default:
  1397. return FALSE;
  1398. }
  1399. }
  1400. void
  1401. X86MachineInfo::KdUpdateControlSet
  1402. (PDBGKD_ANY_CONTROL_SET ControlSet)
  1403. {
  1404. TRACEMODE TraceMode = GetTraceMode();
  1405. ULONG64 DebugCtlMsr;
  1406. ControlSet->X86ControlSet.TraceFlag = TraceMode != TRACE_NONE;
  1407. ControlSet->X86ControlSet.Dr7 = GetIntReg(X86_DR7);
  1408. if (TraceMode != TRACE_NONE && m_SupportsBranchTrace &&
  1409. NT_SUCCESS(DbgKdReadMsr(X86_MSR_DEBUG_CTL, &DebugCtlMsr)))
  1410. {
  1411. DebugCtlMsr |= X86_DEBUG_CTL_LAST_BRANCH_RECORD;
  1412. if (TraceMode == TRACE_TAKEN_BRANCH)
  1413. {
  1414. DebugCtlMsr |= X86_DEBUG_CTL_BRANCH_TRACE;
  1415. }
  1416. DbgKdWriteMsr(X86_MSR_DEBUG_CTL, DebugCtlMsr);
  1417. }
  1418. BpOut("UpdateControlSet(%d) trace %d, DR7 %X\n",
  1419. g_RegContextProcessor, ControlSet->X86ControlSet.TraceFlag,
  1420. ControlSet->X86ControlSet.Dr7);
  1421. if (!g_WatchFunctions.IsStarted() && g_WatchBeginCurFunc != 1)
  1422. {
  1423. ControlSet->X86ControlSet.CurrentSymbolStart = 0;
  1424. ControlSet->X86ControlSet.CurrentSymbolEnd = 0;
  1425. }
  1426. else
  1427. {
  1428. ControlSet->X86ControlSet.CurrentSymbolStart =
  1429. (ULONG)g_WatchBeginCurFunc;
  1430. ControlSet->X86ControlSet.CurrentSymbolEnd =
  1431. (ULONG)g_WatchEndCurFunc;
  1432. }
  1433. }
  1434. void
  1435. X86MachineInfo::KdSaveProcessorState(void)
  1436. {
  1437. MachineInfo::KdSaveProcessorState();
  1438. m_SavedSpecialRegContext = m_SpecialRegContext;
  1439. }
  1440. void
  1441. X86MachineInfo::KdRestoreProcessorState(void)
  1442. {
  1443. MachineInfo::KdRestoreProcessorState();
  1444. m_SpecialRegContext = m_SavedSpecialRegContext;
  1445. }
  1446. ULONG
  1447. X86MachineInfo::ExecutingMachine(void)
  1448. {
  1449. return IMAGE_FILE_MACHINE_I386;
  1450. }
  1451. HRESULT
  1452. X86MachineInfo::SetPageDirectory(ULONG Idx, ULONG64 PageDir,
  1453. PULONG NextIdx)
  1454. {
  1455. HRESULT Status;
  1456. *NextIdx = PAGE_DIR_COUNT;
  1457. if (PageDir == 0)
  1458. {
  1459. if (g_ActualSystemVersion > XBOX_SVER_START &&
  1460. g_ActualSystemVersion < XBOX_SVER_END)
  1461. {
  1462. // XBox has only one page directory in CR3 for everything.
  1463. // The process doesn't have a dirbase entry.
  1464. PageDir = GetReg32(X86_CR3);
  1465. if (PageDir == 0)
  1466. {
  1467. // Register retrieval failure.
  1468. return E_FAIL;
  1469. }
  1470. }
  1471. else
  1472. {
  1473. // Assume NT structures.
  1474. if ((Status = g_Target->ReadImplicitProcessInfoPointer
  1475. (m_OffsetEprocessDirectoryTableBase, &PageDir)) != S_OK)
  1476. {
  1477. return Status;
  1478. }
  1479. }
  1480. if (g_ImplicitProcessDataIsDefault &&
  1481. !IS_LOCAL_KERNEL_TARGET())
  1482. {
  1483. // Verify that the process dirbase matches the CR3 setting
  1484. // as a sanity check.
  1485. ULONG Cr3 = GetReg32(X86_CR3);
  1486. if (Cr3 && Cr3 != (ULONG)PageDir)
  1487. {
  1488. WarnOut("WARNING: Process directory table base %08X "
  1489. "doesn't match CR3 %08X\n",
  1490. (ULONG)PageDir, Cr3);
  1491. }
  1492. }
  1493. }
  1494. // Sanitize the value.
  1495. if (KdDebuggerData.PaeEnabled)
  1496. {
  1497. PageDir &= X86_PDBR_MASK;
  1498. }
  1499. else
  1500. {
  1501. PageDir &= X86_VALID_PFN_MASK;
  1502. }
  1503. // There is only one page directory so update all the slots.
  1504. m_PageDirectories[PAGE_DIR_USER] = PageDir;
  1505. m_PageDirectories[PAGE_DIR_SESSION] = PageDir;
  1506. m_PageDirectories[PAGE_DIR_KERNEL] = PageDir;
  1507. return S_OK;
  1508. }
  1509. #define X86_PAGE_FILE_INDEX(Entry) \
  1510. (((ULONG)(Entry) >> 1) & MAX_PAGING_FILE_MASK)
  1511. #define X86_PAGE_FILE_OFFSET(Entry) \
  1512. (((Entry) >> 12) << X86_PAGE_SHIFT)
  1513. HRESULT
  1514. X86MachineInfo::GetVirtualTranslationPhysicalOffsets(ULONG64 Virt,
  1515. PULONG64 Offsets,
  1516. ULONG OffsetsSize,
  1517. PULONG Levels,
  1518. PULONG PfIndex,
  1519. PULONG64 LastVal)
  1520. {
  1521. ULONG64 Addr;
  1522. HRESULT Status;
  1523. *Levels = 0;
  1524. if (m_Translating)
  1525. {
  1526. return E_UNEXPECTED;
  1527. }
  1528. m_Translating = TRUE;
  1529. //
  1530. // throw away top 32 bits on X86.
  1531. //
  1532. Virt &= 0x00000000FFFFFFFF;
  1533. //
  1534. // Reset the page directory in case it was 0
  1535. //
  1536. if (m_PageDirectories[PAGE_DIR_SINGLE] == 0)
  1537. {
  1538. if ((Status = SetDefaultPageDirectories(1 << PAGE_DIR_SINGLE)) != S_OK)
  1539. {
  1540. m_Translating = FALSE;
  1541. return Status;
  1542. }
  1543. }
  1544. KdOut("X86VtoP: Virt %s, pagedir %s\n",
  1545. FormatAddr64(Virt),
  1546. FormatDisp64(m_PageDirectories[PAGE_DIR_SINGLE]));
  1547. (*Levels)++;
  1548. if (Offsets != NULL && OffsetsSize > 0)
  1549. {
  1550. *Offsets++ = m_PageDirectories[PAGE_DIR_SINGLE];
  1551. OffsetsSize--;
  1552. }
  1553. // This routine uses the fact that the PFN shift is the same
  1554. // as the page shift to simplify some expressions.
  1555. C_ASSERT(X86_VALID_PFN_SHIFT == X86_PAGE_SHIFT);
  1556. if (KdDebuggerData.PaeEnabled)
  1557. {
  1558. ULONG64 Pdpe;
  1559. ULONG64 Entry;
  1560. KdOut(" x86VtoP: PaeEnabled\n");
  1561. // Read the Page Directory Pointer entry.
  1562. Pdpe = ((Virt >> X86_PDPE_SHIFT) * sizeof(Entry)) +
  1563. m_PageDirectories[PAGE_DIR_SINGLE];
  1564. KdOut("X86VtoP: PAE PDPE %s\n", FormatAddr64(Pdpe));
  1565. (*Levels)++;
  1566. if (Offsets != NULL && OffsetsSize > 0)
  1567. {
  1568. *Offsets++ = Pdpe;
  1569. OffsetsSize--;
  1570. }
  1571. if ((Status = g_Target->
  1572. ReadAllPhysical(Pdpe, &Entry, sizeof(Entry))) != S_OK)
  1573. {
  1574. KdOut("X86VtoP: PAE PDPE read error 0x%X\n", Status);
  1575. m_Translating = FALSE;
  1576. return Status;
  1577. }
  1578. // Read the Page Directory entry.
  1579. Addr = (((Virt >> X86_PDE_SHIFT_PAE) & X86_PDE_MASK_PAE) *
  1580. sizeof(Entry)) + (Entry & X86_VALID_PFN_MASK_PAE);
  1581. KdOut("X86VtoP: PAE PDE %s\n", FormatAddr64(Addr));
  1582. (*Levels)++;
  1583. if (Offsets != NULL && OffsetsSize > 0)
  1584. {
  1585. *Offsets++ = Addr;
  1586. OffsetsSize--;
  1587. }
  1588. if ((Status = g_Target->
  1589. ReadAllPhysical(Addr, &Entry, sizeof(Entry))) != S_OK)
  1590. {
  1591. KdOut("X86VtoP: PAE PDE read error 0x%X\n", Status);
  1592. m_Translating = FALSE;
  1593. return Status;
  1594. }
  1595. // Check for a large page. Large pages can
  1596. // never be paged out so also check for the present bit.
  1597. if ((Entry & (X86_LARGE_PAGE_MASK | 1)) == (X86_LARGE_PAGE_MASK | 1))
  1598. {
  1599. //
  1600. // If we have a large page and this is a summary dump, then
  1601. // the page may span multiple physical pages that may -- because
  1602. // of how the summary dump is written -- not be included in the
  1603. // dump. Fixup the large page address to its corresponding small
  1604. // page address.
  1605. //
  1606. if (g_DumpType == DTYPE_KERNEL_SUMMARY32)
  1607. {
  1608. ULONG SpannedPages;
  1609. SpannedPages = (ULONG)
  1610. ((Virt & (X86_LARGE_PAGE_SIZE_PAE - 1)) >> X86_PAGE_SHIFT);
  1611. *LastVal = ((Entry & ~(X86_LARGE_PAGE_SIZE_PAE - 1)) |
  1612. (SpannedPages << X86_PAGE_SHIFT) |
  1613. (Virt & (X86_PAGE_SIZE - 1)));
  1614. }
  1615. else
  1616. {
  1617. *LastVal = ((Entry & ~(X86_LARGE_PAGE_SIZE_PAE - 1)) |
  1618. (Virt & (X86_LARGE_PAGE_SIZE_PAE - 1)));
  1619. }
  1620. KdOut("X86VtoP: PAE Large page mapped phys %s\n",
  1621. FormatAddr64(*LastVal));
  1622. (*Levels)++;
  1623. if (Offsets != NULL && OffsetsSize > 0)
  1624. {
  1625. *Offsets++ = *LastVal;
  1626. OffsetsSize--;
  1627. }
  1628. m_Translating = FALSE;
  1629. return S_OK;
  1630. }
  1631. // Read the Page Table entry.
  1632. if (Entry == 0)
  1633. {
  1634. KdOut("X86VtoP: PAE zero PDE\n");
  1635. m_Translating = FALSE;
  1636. return HR_PAGE_NOT_AVAILABLE;
  1637. }
  1638. else if (!(Entry & 1))
  1639. {
  1640. Addr = (((Virt >> X86_PTE_SHIFT) & X86_PTE_MASK_PAE) *
  1641. sizeof(Entry)) + X86_PAGE_FILE_OFFSET(Entry);
  1642. KdOut("X86VtoP: pagefile PAE PTE %d:%s\n",
  1643. X86_PAGE_FILE_INDEX(Entry), FormatAddr64(Addr));
  1644. if ((Status = g_Target->
  1645. ReadPageFile(X86_PAGE_FILE_INDEX(Entry), Addr,
  1646. &Entry, sizeof(Entry))) != S_OK)
  1647. {
  1648. KdOut("X86VtoP: PAE PDE not present, 0x%X\n", Status);
  1649. m_Translating = FALSE;
  1650. return Status;
  1651. }
  1652. }
  1653. else
  1654. {
  1655. Addr = (((Virt >> X86_PTE_SHIFT) & X86_PTE_MASK_PAE) *
  1656. sizeof(Entry)) + (Entry & X86_VALID_PFN_MASK_PAE);
  1657. KdOut("X86VtoP: PAE PTE %s\n", FormatAddr64(Addr));
  1658. (*Levels)++;
  1659. if (Offsets != NULL && OffsetsSize > 0)
  1660. {
  1661. *Offsets++ = Addr;
  1662. OffsetsSize--;
  1663. }
  1664. if ((Status = g_Target->
  1665. ReadAllPhysical(Addr, &Entry, sizeof(Entry))) != S_OK)
  1666. {
  1667. KdOut("X86VtoP: PAE PTE read error 0x%X\n", Status);
  1668. m_Translating = FALSE;
  1669. return Status;
  1670. }
  1671. }
  1672. if (!(Entry & 0x1) &&
  1673. ((Entry & X86_MM_PTE_PROTOTYPE_MASK) ||
  1674. !(Entry & X86_MM_PTE_TRANSITION_MASK)))
  1675. {
  1676. if (Entry == 0)
  1677. {
  1678. KdOut("X86VtoP: PAE zero PTE\n");
  1679. Status = HR_PAGE_NOT_AVAILABLE;
  1680. }
  1681. else if (Entry & X86_MM_PTE_PROTOTYPE_MASK)
  1682. {
  1683. KdOut("X86VtoP: PAE prototype PTE\n");
  1684. Status = HR_PAGE_NOT_AVAILABLE;
  1685. }
  1686. else
  1687. {
  1688. *PfIndex = X86_PAGE_FILE_INDEX(Entry);
  1689. *LastVal = (Virt & (X86_PAGE_SIZE - 1)) +
  1690. X86_PAGE_FILE_OFFSET(Entry);
  1691. KdOut("X86VtoP: PAE PTE not present, pagefile %d:%s\n",
  1692. *PfIndex, FormatAddr64(*LastVal));
  1693. Status = HR_PAGE_IN_PAGE_FILE;
  1694. }
  1695. m_Translating = FALSE;
  1696. return Status;
  1697. }
  1698. *LastVal = ((Entry & X86_VALID_PFN_MASK_PAE) |
  1699. (Virt & (X86_PAGE_SIZE - 1)));
  1700. KdOut("X86VtoP: PAE Mapped phys %s\n", FormatAddr64(*LastVal));
  1701. (*Levels)++;
  1702. if (Offsets != NULL && OffsetsSize > 0)
  1703. {
  1704. *Offsets++ = *LastVal;
  1705. OffsetsSize--;
  1706. }
  1707. m_Translating = FALSE;
  1708. return S_OK;
  1709. }
  1710. else
  1711. {
  1712. ULONG Entry;
  1713. // Read the Page Directory entry.
  1714. Addr = ((Virt >> X86_PDE_SHIFT) * sizeof(Entry)) +
  1715. m_PageDirectories[PAGE_DIR_SINGLE];
  1716. KdOut("X86VtoP: PDE %s\n", FormatDisp64(Addr));
  1717. (*Levels)++;
  1718. if (Offsets != NULL && OffsetsSize > 0)
  1719. {
  1720. *Offsets++ = Addr;
  1721. OffsetsSize--;
  1722. }
  1723. if ((Status = g_Target->
  1724. ReadAllPhysical(Addr, &Entry, sizeof(Entry))) != S_OK)
  1725. {
  1726. KdOut("X86VtoP: PDE read error 0x%X\n", Status);
  1727. m_Translating = FALSE;
  1728. return Status;
  1729. }
  1730. // Check for a large page. Large pages can
  1731. // never be paged out so also check for the present bit.
  1732. if ((Entry & (X86_LARGE_PAGE_MASK | 1)) == (X86_LARGE_PAGE_MASK | 1))
  1733. {
  1734. *LastVal = ((Entry & ~(X86_LARGE_PAGE_SIZE - 1)) |
  1735. (Virt & (X86_LARGE_PAGE_SIZE - 1)));
  1736. KdOut("X86VtoP: Large page mapped phys %s\n",
  1737. FormatAddr64(*LastVal));
  1738. (*Levels)++;
  1739. if (Offsets != NULL && OffsetsSize > 0)
  1740. {
  1741. *Offsets++ = *LastVal;
  1742. OffsetsSize--;
  1743. }
  1744. m_Translating = FALSE;
  1745. return S_OK;
  1746. }
  1747. // Read the Page Table entry.
  1748. if (Entry == 0)
  1749. {
  1750. KdOut("X86VtoP: PAE zero PDE\n");
  1751. m_Translating = FALSE;
  1752. return HR_PAGE_NOT_AVAILABLE;
  1753. }
  1754. else if (!(Entry & 1))
  1755. {
  1756. Addr = (((Virt >> X86_PTE_SHIFT) & X86_PTE_MASK) *
  1757. sizeof(Entry)) + X86_PAGE_FILE_OFFSET(Entry);
  1758. KdOut("X86VtoP: pagefile PTE %d:%s\n",
  1759. X86_PAGE_FILE_INDEX(Entry), FormatAddr64(Addr));
  1760. if ((Status = g_Target->
  1761. ReadPageFile(X86_PAGE_FILE_INDEX(Entry), Addr,
  1762. &Entry, sizeof(Entry))) != S_OK)
  1763. {
  1764. KdOut("X86VtoP: PDE not present, 0x%X\n", Status);
  1765. m_Translating = FALSE;
  1766. return Status;
  1767. }
  1768. }
  1769. else
  1770. {
  1771. Addr = (((Virt >> X86_PTE_SHIFT) & X86_PTE_MASK) *
  1772. sizeof(Entry)) + (Entry & X86_VALID_PFN_MASK);
  1773. KdOut("X86VtoP: PTE %s\n", FormatAddr64(Addr));
  1774. (*Levels)++;
  1775. if (Offsets != NULL && OffsetsSize > 0)
  1776. {
  1777. *Offsets++ = Addr;
  1778. OffsetsSize--;
  1779. }
  1780. if ((Status = g_Target->
  1781. ReadAllPhysical(Addr, &Entry, sizeof(Entry))) != S_OK)
  1782. {
  1783. KdOut("X86VtoP: PTE read error 0x%X\n", Status);
  1784. m_Translating = FALSE;
  1785. return Status;
  1786. }
  1787. }
  1788. if (!(Entry & 0x1) &&
  1789. ((Entry & X86_MM_PTE_PROTOTYPE_MASK) ||
  1790. !(Entry & X86_MM_PTE_TRANSITION_MASK)))
  1791. {
  1792. if (Entry == 0)
  1793. {
  1794. KdOut("X86VtoP: zero PTE\n");
  1795. Status = HR_PAGE_NOT_AVAILABLE;
  1796. }
  1797. else if (Entry & X86_MM_PTE_PROTOTYPE_MASK)
  1798. {
  1799. KdOut("X86VtoP: prototype PTE\n");
  1800. Status = HR_PAGE_NOT_AVAILABLE;
  1801. }
  1802. else
  1803. {
  1804. *PfIndex = X86_PAGE_FILE_INDEX(Entry);
  1805. *LastVal = (Virt & (X86_PAGE_SIZE - 1)) +
  1806. X86_PAGE_FILE_OFFSET(Entry);
  1807. KdOut("X86VtoP: PTE not present, pagefile %d:%s\n",
  1808. *PfIndex, FormatAddr64(*LastVal));
  1809. Status = HR_PAGE_IN_PAGE_FILE;
  1810. }
  1811. m_Translating = FALSE;
  1812. return Status;
  1813. }
  1814. *LastVal = ((Entry & X86_VALID_PFN_MASK) |
  1815. (Virt & (X86_PAGE_SIZE - 1)));
  1816. KdOut("X86VtoP: Mapped phys %s\n", FormatAddr64(*LastVal));
  1817. (*Levels)++;
  1818. if (Offsets != NULL && OffsetsSize > 0)
  1819. {
  1820. *Offsets++ = *LastVal;
  1821. OffsetsSize--;
  1822. }
  1823. m_Translating = FALSE;
  1824. return S_OK;
  1825. }
  1826. }
  1827. HRESULT
  1828. X86MachineInfo::GetBaseTranslationVirtualOffset(PULONG64 Offset)
  1829. {
  1830. if (KdDebuggerData.PaeEnabled)
  1831. {
  1832. *Offset = EXTEND64(X86_BASE_VIRT_PAE);
  1833. }
  1834. else
  1835. {
  1836. *Offset = EXTEND64(X86_BASE_VIRT);
  1837. }
  1838. return S_OK;
  1839. }
  1840. BOOL
  1841. X86MachineInfo::DisplayTrapFrame(ULONG64 FrameAddress,
  1842. PCROSS_PLATFORM_CONTEXT Context)
  1843. {
  1844. X86_KTRAP_FRAME TrapContents;
  1845. CHAR Buffer[200];
  1846. DESCRIPTOR64 Descriptor={0};
  1847. ULONG Esp;
  1848. ULONG64 DisasmAddr;
  1849. ULONG Temp, SegSs, res;
  1850. ULONG EFlags;
  1851. #define Preg(S,R) dprintf("%s=%08lx ",S, TrapContents.R);
  1852. if (g_Target->ReadVirtual(FrameAddress, &TrapContents,
  1853. sizeof(TrapContents), &res) != S_OK)
  1854. {
  1855. dprintf("Unable to read trap frame contents\n");
  1856. return FALSE;
  1857. }
  1858. Preg("eax", Eax);
  1859. Preg("ebx", Ebx);
  1860. Preg("ecx", Ecx);
  1861. Preg("edx", Edx);
  1862. Preg("esi", Esi);
  1863. Preg("edi", Edi);
  1864. dprintf("\n");
  1865. //
  1866. // Figure out ESP
  1867. //
  1868. if (((TrapContents.SegCs & 1) != 0 /*KernelMode*/) ||
  1869. (TrapContents.EFlags & X86_EFLAGS_V86_MASK) ||
  1870. FrameAddress == 0)
  1871. {
  1872. // User-mode frame, real value of Esp is in HardwareEsp
  1873. Esp = TrapContents.HardwareEsp;
  1874. }
  1875. else
  1876. {
  1877. //
  1878. // We ignore if Esp has been edited for now, and we will print a
  1879. // separate line indicating this later.
  1880. //
  1881. // Calculate kernel Esp
  1882. //
  1883. Esp = (ULONG)FrameAddress + FIELD_OFFSET(X86_KTRAP_FRAME, HardwareEsp);
  1884. }
  1885. EFlags = TrapContents.EFlags;
  1886. dprintf("eip=%08lx esp=%08lx ebp=%08lx iopl=%1lx "
  1887. "%s %s %s %s %s %s %s %s\n",
  1888. TrapContents.Eip,
  1889. Esp,
  1890. TrapContents.Ebp,
  1891. ((EFlags >> 12) & 3),
  1892. (EFlags & 0x800) ? "ov" : "nv",
  1893. (EFlags & 0x400) ? "dn" : "up",
  1894. (EFlags & 0x200) ? "ei" : "di",
  1895. (EFlags & 0x80) ? "ng" : "pl",
  1896. (EFlags & 0x40) ? "zr" : "nz",
  1897. (EFlags & 0x10) ? "ac" : "na",
  1898. (EFlags & 0x4) ? "po" : "pe",
  1899. (EFlags & 0x1) ? "cy" : "nc");
  1900. // Check whether P5 Virtual Mode Extensions are enabled, for display
  1901. // of new EFlags values.
  1902. if ( GetIntReg(X86_CR4) != 0)
  1903. {
  1904. dprintf("vip=%1lx vif=%1lx\n",
  1905. (EFlags & 0x00100000L) >> 20,
  1906. (EFlags & 0x00080000L) >> 19);
  1907. }
  1908. //
  1909. // Find correct SS
  1910. //
  1911. if (EFlags & X86_EFLAGS_V86_MASK)
  1912. {
  1913. SegSs = (USHORT)(TrapContents.HardwareSegSs & 0xffff);
  1914. }
  1915. else if ((TrapContents.SegCs & X86_MODE_MASK) != 0 /*KernelMode*/)
  1916. {
  1917. //
  1918. // It's user mode. The HardwareSegSs contains R3 data selector.
  1919. //
  1920. SegSs = (USHORT)(TrapContents.HardwareSegSs | X86_RPL_MASK) & 0xffff;
  1921. }
  1922. else
  1923. {
  1924. SegSs = X86_KGDT_R0_DATA;
  1925. }
  1926. dprintf("cs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x"
  1927. " efl=%08lx\n",
  1928. (USHORT)(TrapContents.SegCs & 0xffff),
  1929. (USHORT)(SegSs & 0xffff),
  1930. (USHORT)(TrapContents.SegDs & 0xffff),
  1931. (USHORT)(TrapContents.SegEs & 0xffff),
  1932. (USHORT)(TrapContents.SegFs & 0xffff),
  1933. (USHORT)(TrapContents.SegGs & 0xffff),
  1934. EFlags);
  1935. //
  1936. // Check to see if Esp has been edited, and dump new value if it has
  1937. //
  1938. if ( (!(EFlags & X86_EFLAGS_V86_MASK)) &&
  1939. ((TrapContents.SegCs & X86_MODE_MASK) == 0 /*KernelMode*/))
  1940. {
  1941. if ((TrapContents.SegCs & X86_FRAME_EDITED) == 0)
  1942. {
  1943. dprintf("ESP EDITED! New esp=%08lx\n",TrapContents.TempEsp);
  1944. }
  1945. }
  1946. if (FrameAddress)
  1947. {
  1948. dprintf("ErrCode = %08lx\n", TrapContents.ErrCode);
  1949. }
  1950. if (EFlags & X86_EFLAGS_V86_MASK)
  1951. {
  1952. DisasmAddr = ((ULONG64)((USHORT)TrapContents.SegCs & 0xffff) << 4) +
  1953. (TrapContents.Eip & 0xffff);
  1954. }
  1955. else
  1956. {
  1957. g_Target->GetSelDescriptor(this,
  1958. g_CurrentProcess->CurrentThread->Handle,
  1959. (USHORT)TrapContents.SegCs, &Descriptor);
  1960. if (Descriptor.Flags & X86_DESC_DEFAULT_BIG)
  1961. {
  1962. DisasmAddr = EXTEND64(TrapContents.Eip);
  1963. }
  1964. else
  1965. {
  1966. DisasmAddr = TrapContents.Eip;// & 0xffff
  1967. }
  1968. }
  1969. ADDR tempAddr;
  1970. Type(tempAddr) = ADDR_FLAT | FLAT_COMPUTED;
  1971. Off(tempAddr) = Flat(tempAddr) = DisasmAddr;
  1972. if (Disassemble(&tempAddr, Buffer, FALSE))
  1973. {
  1974. dprintf("%s", Buffer);
  1975. }
  1976. else
  1977. {
  1978. dprintf("%08lx ???????????????\n", TrapContents.Eip);
  1979. }
  1980. dprintf("\n");
  1981. if (Context)
  1982. {
  1983. // Fill up the context struct
  1984. #define CPCXT(Fld) Context->X86Context.Fld = TrapContents.Fld
  1985. CPCXT(Ebp); CPCXT(Eip); CPCXT(Eax); CPCXT(Ecx); CPCXT(Edx);
  1986. CPCXT(Edi); CPCXT(Esi); CPCXT(Ebx);
  1987. CPCXT(SegCs); CPCXT(SegDs); CPCXT(SegEs); CPCXT(SegFs); CPCXT(SegGs);
  1988. CPCXT(EFlags);
  1989. #undef CPCXT
  1990. Context->X86Context.SegSs = SegSs;
  1991. Context->X86Context.Esp = Esp;
  1992. }
  1993. g_LastRegFrame.InstructionOffset = EXTEND64(TrapContents.Eip);
  1994. g_LastRegFrame.StackOffset = EXTEND64(Esp);
  1995. g_LastRegFrame.FrameOffset = EXTEND64(TrapContents.Ebp);
  1996. return TRUE;
  1997. #undef Preg
  1998. }
  1999. void
  2000. X86MachineInfo::ValidateCxr(PCROSS_PLATFORM_CONTEXT Context)
  2001. {
  2002. if (Context->X86Context.EFlags & X86_EFLAGS_V86_MASK)
  2003. {
  2004. Context->X86Context.SegSs &= 0xffff;
  2005. }
  2006. else if ((Context->X86Context.SegCs & X86_MODE_MASK))
  2007. {
  2008. //
  2009. // It's user mode. The HardwareSegSs contains R3 data selector.
  2010. //
  2011. Context->X86Context.SegSs =
  2012. (USHORT)(Context->X86Context.SegSs | X86_RPL_MASK) & 0xffff;
  2013. }
  2014. else
  2015. {
  2016. Context->X86Context.SegSs = X86_KGDT_R0_DATA;
  2017. }
  2018. }
  2019. void
  2020. X86MachineInfo::OutputFunctionEntry(PVOID RawEntry)
  2021. {
  2022. PFPO_DATA FpoData = (PFPO_DATA)RawEntry;
  2023. dprintf("OffStart: %08x\n", FpoData->ulOffStart);
  2024. dprintf("ProcSize: 0x%x\n", FpoData->cbProcSize);
  2025. switch(FpoData->cbFrame)
  2026. {
  2027. case FRAME_FPO:
  2028. dprintf("Params: %d\n", FpoData->cdwParams);
  2029. dprintf("Locals: %d\n", FpoData->cdwLocals);
  2030. dprintf("Registers: %d\n", FpoData->cbRegs);
  2031. if (FpoData->fHasSEH)
  2032. {
  2033. dprintf("Has SEH\n");
  2034. }
  2035. if (FpoData->fUseBP)
  2036. {
  2037. dprintf("Uses EBP\n");
  2038. }
  2039. break;
  2040. case FRAME_NONFPO:
  2041. dprintf("Non-FPO\n");
  2042. break;
  2043. case FRAME_TRAP:
  2044. if (!IS_KERNEL_TARGET())
  2045. {
  2046. goto UnknownFpo;
  2047. }
  2048. dprintf("Params: %d\n", FpoData->cdwParams);
  2049. dprintf("Locals: %d\n", FpoData->cdwLocals);
  2050. dprintf("Trap frame\n");
  2051. break;
  2052. case FRAME_TSS:
  2053. if (!IS_KERNEL_TARGET())
  2054. {
  2055. goto UnknownFpo;
  2056. }
  2057. dprintf("Task gate\n");
  2058. break;
  2059. default:
  2060. UnknownFpo:
  2061. dprintf("Unknown FPO type\n");
  2062. break;
  2063. }
  2064. }
  2065. HRESULT
  2066. X86MachineInfo::ReadKernelProcessorId
  2067. (ULONG Processor, PDEBUG_PROCESSOR_IDENTIFICATION_ALL Id)
  2068. {
  2069. HRESULT Status;
  2070. ULONG64 Prcb, PrcbMember;
  2071. ULONG Data;
  2072. if ((Status = g_Target->
  2073. GetProcessorSystemDataOffset(Processor, DEBUG_DATA_KPRCB_OFFSET,
  2074. &Prcb)) != S_OK)
  2075. {
  2076. return Status;
  2077. }
  2078. if ((Status = g_Target->
  2079. ReadAllVirtual(Prcb + FIELD_OFFSET(X86_PARTIAL_KPRCB, CpuType),
  2080. &Data, sizeof(Data))) != S_OK)
  2081. {
  2082. return Status;
  2083. }
  2084. Id->X86.Family = Data & 0xf;
  2085. Id->X86.Model = (Data >> 24) & 0xf;
  2086. Id->X86.Stepping = (Data >> 16) & 0xf;
  2087. if (g_TargetBuildNumber >= 2474)
  2088. {
  2089. // XP
  2090. PrcbMember = X86_2474_KPRCB_VENDOR_STRING;
  2091. }
  2092. else if (g_TargetBuildNumber >= 2251)
  2093. {
  2094. // XP BETA1 and BETA 2
  2095. PrcbMember = X86_2251_KPRCB_VENDOR_STRING;
  2096. }
  2097. else if (g_TargetBuildNumber >= 2087)
  2098. {
  2099. // NT5
  2100. PrcbMember = X86_2087_KPRCB_VENDOR_STRING;
  2101. }
  2102. else
  2103. {
  2104. // NT4
  2105. PrcbMember = X86_1387_KPRCB_VENDOR_STRING;
  2106. }
  2107. if ((Status = g_Target->
  2108. ReadAllVirtual(Prcb + PrcbMember, Id->X86.VendorString,
  2109. X86_VENDOR_STRING_SIZE)) != S_OK)
  2110. {
  2111. return Status;
  2112. }
  2113. return S_OK;
  2114. }
  2115. void
  2116. X86MachineInfo::KdGetSpecialRegistersFromContext(void)
  2117. {
  2118. DBG_ASSERT(m_ContextState >= MCTX_FULL);
  2119. m_SpecialRegContext.KernelDr0 = m_Context.X86Nt5Context.Dr0;
  2120. m_SpecialRegContext.KernelDr1 = m_Context.X86Nt5Context.Dr1;
  2121. m_SpecialRegContext.KernelDr2 = m_Context.X86Nt5Context.Dr2;
  2122. m_SpecialRegContext.KernelDr3 = m_Context.X86Nt5Context.Dr3;
  2123. m_SpecialRegContext.KernelDr6 = m_Context.X86Nt5Context.Dr6;
  2124. m_SpecialRegContext.KernelDr7 = m_Context.X86Nt5Context.Dr7;
  2125. }
  2126. void
  2127. X86MachineInfo::KdSetSpecialRegistersInContext(void)
  2128. {
  2129. DBG_ASSERT(m_ContextState >= MCTX_FULL);
  2130. m_Context.X86Nt5Context.Dr0 = m_SpecialRegContext.KernelDr0;
  2131. m_Context.X86Nt5Context.Dr1 = m_SpecialRegContext.KernelDr1;
  2132. m_Context.X86Nt5Context.Dr2 = m_SpecialRegContext.KernelDr2;
  2133. m_Context.X86Nt5Context.Dr3 = m_SpecialRegContext.KernelDr3;
  2134. m_Context.X86Nt5Context.Dr6 = m_SpecialRegContext.KernelDr6;
  2135. m_Context.X86Nt5Context.Dr7 = m_SpecialRegContext.KernelDr7;
  2136. }
  2137. ULONG
  2138. X86MachineInfo::GetIntReg(ULONG regnum)
  2139. {
  2140. switch (m_ContextState)
  2141. {
  2142. case MCTX_PC:
  2143. if (regnum == X86_EIP)
  2144. {
  2145. return m_Context.X86Nt5Context.Eip;
  2146. }
  2147. goto MctxContext;
  2148. case MCTX_DR67_REPORT:
  2149. switch (regnum)
  2150. {
  2151. case X86_DR6: return m_Context.X86Nt5Context.Dr6;
  2152. case X86_DR7: return m_Context.X86Nt5Context.Dr7;
  2153. }
  2154. goto MctxContext;
  2155. case MCTX_REPORT:
  2156. switch (regnum)
  2157. {
  2158. case X86_CS: return (USHORT)m_Context.X86Nt5Context.SegCs;
  2159. case X86_DS: return (USHORT)m_Context.X86Nt5Context.SegDs;
  2160. case X86_ES: return (USHORT)m_Context.X86Nt5Context.SegEs;
  2161. case X86_FS: return (USHORT)m_Context.X86Nt5Context.SegFs;
  2162. case X86_EIP: return m_Context.X86Nt5Context.Eip;
  2163. case X86_EFL: return m_Context.X86Nt5Context.EFlags;
  2164. case X86_DR6: return m_Context.X86Nt5Context.Dr6;
  2165. case X86_DR7: return m_Context.X86Nt5Context.Dr7;
  2166. }
  2167. // Fallthrough!
  2168. case MCTX_NONE:
  2169. MctxContext:
  2170. if (GetContextState(MCTX_CONTEXT) != S_OK)
  2171. {
  2172. return 0;
  2173. }
  2174. // Fallthrough!
  2175. case MCTX_CONTEXT:
  2176. switch (regnum)
  2177. {
  2178. case X86_CS: return (USHORT)m_Context.X86Nt5Context.SegCs;
  2179. case X86_DS: return (USHORT)m_Context.X86Nt5Context.SegDs;
  2180. case X86_ES: return (USHORT)m_Context.X86Nt5Context.SegEs;
  2181. case X86_FS: return (USHORT)m_Context.X86Nt5Context.SegFs;
  2182. case X86_EIP: return m_Context.X86Nt5Context.Eip;
  2183. case X86_EFL: return m_Context.X86Nt5Context.EFlags;
  2184. case X86_GS: return (USHORT)m_Context.X86Nt5Context.SegGs;
  2185. case X86_SS: return (USHORT)m_Context.X86Nt5Context.SegSs;
  2186. case X86_EDI: return m_Context.X86Nt5Context.Edi;
  2187. case X86_ESI: return m_Context.X86Nt5Context.Esi;
  2188. case X86_EBX: return m_Context.X86Nt5Context.Ebx;
  2189. case X86_EDX: return m_Context.X86Nt5Context.Edx;
  2190. case X86_ECX: return m_Context.X86Nt5Context.Ecx;
  2191. case X86_EAX: return m_Context.X86Nt5Context.Eax;
  2192. case X86_EBP: return m_Context.X86Nt5Context.Ebp;
  2193. case X86_ESP: return m_Context.X86Nt5Context.Esp;
  2194. case X86_FPCW:
  2195. return m_Context.X86Nt5Context.FloatSave.ControlWord & 0xffff;
  2196. case X86_FPSW:
  2197. return m_Context.X86Nt5Context.FloatSave.StatusWord & 0xffff;
  2198. case X86_FPTW:
  2199. return m_Context.X86Nt5Context.FloatSave.TagWord & 0xffff;
  2200. case X86_MXCSR:
  2201. return m_Context.X86Nt5Context.FxSave.MXCsr;
  2202. }
  2203. //
  2204. // The requested register is not in our current context, load up
  2205. // a complete context
  2206. //
  2207. if (GetContextState(MCTX_FULL) != S_OK)
  2208. {
  2209. return 0;
  2210. }
  2211. }
  2212. //
  2213. // We must have a complete context...
  2214. //
  2215. switch (regnum)
  2216. {
  2217. case X86_GS:
  2218. return (USHORT)m_Context.X86Nt5Context.SegGs;
  2219. case X86_FS:
  2220. return (USHORT)m_Context.X86Nt5Context.SegFs;
  2221. case X86_ES:
  2222. return (USHORT)m_Context.X86Nt5Context.SegEs;
  2223. case X86_DS:
  2224. return (USHORT)m_Context.X86Nt5Context.SegDs;
  2225. case X86_EDI:
  2226. return m_Context.X86Nt5Context.Edi;
  2227. case X86_ESI:
  2228. return m_Context.X86Nt5Context.Esi;
  2229. case X86_SI:
  2230. return(m_Context.X86Nt5Context.Esi & 0xffff);
  2231. case X86_DI:
  2232. return(m_Context.X86Nt5Context.Edi & 0xffff);
  2233. case X86_EBX:
  2234. return m_Context.X86Nt5Context.Ebx;
  2235. case X86_EDX:
  2236. return m_Context.X86Nt5Context.Edx;
  2237. case X86_ECX:
  2238. return m_Context.X86Nt5Context.Ecx;
  2239. case X86_EAX:
  2240. return m_Context.X86Nt5Context.Eax;
  2241. case X86_EBP:
  2242. return m_Context.X86Nt5Context.Ebp;
  2243. case X86_EIP:
  2244. return m_Context.X86Nt5Context.Eip;
  2245. case X86_CS:
  2246. return (USHORT)m_Context.X86Nt5Context.SegCs;
  2247. case X86_EFL:
  2248. return m_Context.X86Nt5Context.EFlags;
  2249. case X86_ESP:
  2250. return m_Context.X86Nt5Context.Esp;
  2251. case X86_SS:
  2252. return (USHORT)m_Context.X86Nt5Context.SegSs;
  2253. case X86_DR0:
  2254. return m_Context.X86Nt5Context.Dr0;
  2255. case X86_DR1:
  2256. return m_Context.X86Nt5Context.Dr1;
  2257. case X86_DR2:
  2258. return m_Context.X86Nt5Context.Dr2;
  2259. case X86_DR3:
  2260. return m_Context.X86Nt5Context.Dr3;
  2261. case X86_DR6:
  2262. return m_Context.X86Nt5Context.Dr6;
  2263. case X86_DR7:
  2264. return m_Context.X86Nt5Context.Dr7;
  2265. case X86_FPCW:
  2266. return m_Context.X86Nt5Context.FloatSave.ControlWord & 0xffff;
  2267. case X86_FPSW:
  2268. return m_Context.X86Nt5Context.FloatSave.StatusWord & 0xffff;
  2269. case X86_FPTW:
  2270. return m_Context.X86Nt5Context.FloatSave.TagWord & 0xffff;
  2271. case X86_MXCSR:
  2272. return m_Context.X86Nt5Context.FxSave.MXCsr;
  2273. }
  2274. if (IS_KERNEL_TARGET())
  2275. {
  2276. switch(regnum)
  2277. {
  2278. case X86_CR0:
  2279. return m_SpecialRegContext.Cr0;
  2280. case X86_CR2:
  2281. return m_SpecialRegContext.Cr2;
  2282. case X86_CR3:
  2283. return m_SpecialRegContext.Cr3;
  2284. case X86_CR4:
  2285. return m_SpecialRegContext.Cr4;
  2286. case X86_GDTR:
  2287. return m_SpecialRegContext.Gdtr.Base;
  2288. case X86_GDTL:
  2289. return (ULONG)m_SpecialRegContext.Gdtr.Limit;
  2290. case X86_IDTR:
  2291. return m_SpecialRegContext.Idtr.Base;
  2292. case X86_IDTL:
  2293. return (ULONG)m_SpecialRegContext.Idtr.Limit;
  2294. case X86_TR:
  2295. return (ULONG)m_SpecialRegContext.Tr;
  2296. case X86_LDTR:
  2297. return (ULONG)m_SpecialRegContext.Ldtr;
  2298. }
  2299. }
  2300. ErrOut("X86MachineInfo::GetVal: "
  2301. "unknown register %lx requested\n", regnum);
  2302. return REG_ERROR;
  2303. }
  2304. PULONG64
  2305. X86MachineInfo::GetMmxRegSlot(ULONG regnum)
  2306. {
  2307. return (PULONG64)(m_Context.X86Nt5Context.FloatSave.RegisterArea +
  2308. GetMmxRegOffset(regnum - X86_MM_FIRST,
  2309. GetIntReg(X86_FPSW)) * 10);
  2310. }
  2311. void
  2312. X86MachineInfo::GetMmxReg(ULONG regnum, REGVAL *val)
  2313. {
  2314. if (GetContextState(MCTX_CONTEXT) == S_OK)
  2315. {
  2316. val->i64 = *(ULONG64 UNALIGNED *)GetMmxRegSlot(regnum);
  2317. }
  2318. }
  2319. void
  2320. X86MachineInfo::GetFloatReg(ULONG regnum, REGVAL *val)
  2321. {
  2322. if (GetContextState(MCTX_CONTEXT) == S_OK)
  2323. {
  2324. memcpy(val->f10, m_Context.X86Nt5Context.FloatSave.RegisterArea +
  2325. 10 * (regnum - X86_ST_FIRST), sizeof(val->f10));
  2326. }
  2327. }
  2328. // TSS
  2329. ULONG64
  2330. X86MachineInfo::Selector2Address(
  2331. USHORT TaskRegister
  2332. )
  2333. {
  2334. DESCRIPTOR64 desc;
  2335. //
  2336. // Lookup task register
  2337. //
  2338. if (g_Target->GetSelDescriptor
  2339. (this, g_CurrentProcess->CurrentThread->Handle,
  2340. TaskRegister, &desc) != S_OK)
  2341. {
  2342. //
  2343. // Can't do it.
  2344. //
  2345. return 0;
  2346. }
  2347. if (X86_DESC_TYPE(desc.Flags) != 9 &&
  2348. X86_DESC_TYPE(desc.Flags) != 0xb)
  2349. {
  2350. //
  2351. // not a 32bit task descriptor
  2352. //
  2353. return 0;
  2354. }
  2355. //
  2356. // Read in Task State Segment
  2357. //
  2358. return desc.Base;
  2359. }
  2360. HRESULT
  2361. X86MachineInfo::DumpTSS(void)
  2362. /*++
  2363. Routine Description:
  2364. Arguments:
  2365. args -
  2366. Return Value:
  2367. None
  2368. --*/
  2369. {
  2370. #define MAX_RING 3
  2371. ULONG taskRegister;
  2372. PUCHAR buf;
  2373. ULONG64 hostAddress;
  2374. BOOLEAN extendedDump;
  2375. ULONG i;
  2376. USHORT SegSs;
  2377. CHAR Buffer[200];
  2378. DESCRIPTOR64 Descriptor;
  2379. ULONG Esp;
  2380. ULONG64 DisasmAddr;
  2381. struct
  2382. {
  2383. // intel's TSS format
  2384. ULONG Previous;
  2385. struct
  2386. {
  2387. ULONG Esp;
  2388. ULONG Ss;
  2389. } Ring[MAX_RING];
  2390. ULONG Cr3;
  2391. ULONG Eip;
  2392. ULONG EFlags;
  2393. ULONG Eax;
  2394. ULONG Ecx;
  2395. ULONG Edx;
  2396. ULONG Ebx;
  2397. ULONG Esp;
  2398. ULONG Ebp;
  2399. ULONG Esi;
  2400. ULONG Edi;
  2401. ULONG Es;
  2402. ULONG Cs;
  2403. ULONG Ss;
  2404. ULONG Ds;
  2405. ULONG Fs;
  2406. ULONG Gs;
  2407. ULONG Ldt;
  2408. USHORT T;
  2409. USHORT IoMapBase;
  2410. } TSS;
  2411. buf = (PUCHAR)&TSS;
  2412. *buf = '\0';
  2413. taskRegister = (ULONG) GetExpression();
  2414. //
  2415. // If user specified a 2nd parameter, doesn't matter what it is,
  2416. // dump the portions of the TSS not covered by the trap frame dump.
  2417. //
  2418. if (*g_CurCmd)
  2419. {
  2420. extendedDump = TRUE;
  2421. g_CurCmd += strlen(g_CurCmd);
  2422. }
  2423. hostAddress = Selector2Address((USHORT)taskRegister);
  2424. if (!hostAddress)
  2425. {
  2426. ErrOut("unable to get Task State Segment address from selector %lX\n",
  2427. taskRegister);
  2428. return E_INVALIDARG;
  2429. }
  2430. if (g_Target->ReadVirtual(hostAddress, &TSS, sizeof(TSS), &i) != S_OK)
  2431. {
  2432. ErrOut("unable to read Task State Segment from host address %lx\n",
  2433. hostAddress);
  2434. return E_INVALIDARG;
  2435. }
  2436. //
  2437. // Display it.
  2438. //
  2439. if (extendedDump)
  2440. {
  2441. dprintf("\nTask State Segment (selector 0x%x) at 0x%p\n\n",
  2442. taskRegister,
  2443. hostAddress);
  2444. dprintf("Previous Task Link = %4x\n", TSS.Previous);
  2445. for (i = 0 ; i < MAX_RING ; i++)
  2446. {
  2447. dprintf("Esp%d = %8x SS%d = %4x\n",
  2448. i, TSS.Ring[i].Esp,
  2449. i, TSS.Ring[i].Ss);
  2450. }
  2451. dprintf("CR3 (PDBR) = %08x\n", TSS.Cr3);
  2452. dprintf("I/O Map Base Address = %4x, Debug Trap (T) = %s\n",
  2453. TSS.IoMapBase,
  2454. TSS.T == 0 ? "False" : "True");
  2455. dprintf("\nSaved General Purpose Registers\n\n");
  2456. }
  2457. dprintf("eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n",
  2458. TSS.Eax,
  2459. TSS.Ebx,
  2460. TSS.Ecx,
  2461. TSS.Edx,
  2462. TSS.Esi,
  2463. TSS.Edi);
  2464. Esp = TSS.Esp;
  2465. dprintf("eip=%08lx esp=%08lx ebp=%08lx iopl=%1lx "
  2466. "%s %s %s %s %s %s %s %s\n",
  2467. TSS.Eip,
  2468. Esp,
  2469. TSS.Ebp,
  2470. ((TSS.EFlags >> 12) & 3),
  2471. (TSS.EFlags & 0x800) ? "ov" : "nv",
  2472. (TSS.EFlags & 0x400) ? "dn" : "up",
  2473. (TSS.EFlags & 0x200) ? "ei" : "di",
  2474. (TSS.EFlags & 0x80) ? "ng" : "pl",
  2475. (TSS.EFlags & 0x40) ? "zr" : "nz",
  2476. (TSS.EFlags & 0x10) ? "ac" : "na",
  2477. (TSS.EFlags & 0x4) ? "po" : "pe",
  2478. (TSS.EFlags & 0x1) ? "cy" : "nc");
  2479. // Check whether P5 Virtual Mode Extensions are enabled, for display
  2480. // of new EFlags values.
  2481. if (GetIntReg(X86_CR4) != 0)
  2482. {
  2483. dprintf("vip=%1lx vif=%1lx\n",
  2484. (TSS.EFlags & 0x00100000L) >> 20,
  2485. (TSS.EFlags & 0x00080000L) >> 19);
  2486. }
  2487. //
  2488. // Find correct SS
  2489. //
  2490. if (TSS.EFlags & X86_EFLAGS_V86_MASK)
  2491. {
  2492. SegSs = (USHORT)(TSS.Ss & 0xffff);
  2493. }
  2494. else if ((TSS.Cs & X86_MODE_MASK) != 0)
  2495. {
  2496. //
  2497. // It's user mode. The HardwareSegSs contains R3 data selector.
  2498. //
  2499. SegSs = (USHORT)(TSS.Ss | X86_RPL_MASK) & 0xffff;
  2500. }
  2501. else
  2502. {
  2503. SegSs = X86_KGDT_R0_DATA;
  2504. }
  2505. dprintf("cs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x"
  2506. " efl=%08lx\n",
  2507. (USHORT)(TSS.Cs & 0xffff),
  2508. (USHORT)(SegSs & 0xffff),
  2509. (USHORT)(TSS.Ds & 0xffff),
  2510. (USHORT)(TSS.Es & 0xffff),
  2511. (USHORT)(TSS.Fs & 0xffff),
  2512. (USHORT)(TSS.Gs & 0xffff),
  2513. TSS.EFlags);
  2514. if (TSS.EFlags & X86_EFLAGS_V86_MASK)
  2515. {
  2516. DisasmAddr = ((ULONG)((USHORT)TSS.Cs & 0xffff) << 4) +
  2517. (TSS.Eip & 0xffff);
  2518. }
  2519. else
  2520. {
  2521. if (g_Target->GetSelDescriptor(this, g_EventThread->Handle,
  2522. TSS.Cs, &Descriptor) != S_OK)
  2523. {
  2524. ErrOut("Unable to get TSS CS descriptor\n");
  2525. return E_INVALIDARG;
  2526. }
  2527. if (Descriptor.Flags & X86_DESC_DEFAULT_BIG)
  2528. {
  2529. DisasmAddr = EXTEND64(TSS.Eip);
  2530. }
  2531. else
  2532. {
  2533. DisasmAddr = TSS.Eip & 0xffff;
  2534. }
  2535. }
  2536. ADDR tempAddr;
  2537. Type(tempAddr) = ADDR_FLAT | FLAT_COMPUTED;
  2538. Off(tempAddr) = Flat(tempAddr) = DisasmAddr;
  2539. if (Disassemble(&tempAddr, Buffer, FALSE))
  2540. {
  2541. dprintf(Buffer);
  2542. }
  2543. else
  2544. {
  2545. dprintf("%08lx ???????????????\n", TSS.Eip);
  2546. }
  2547. dprintf("\n");
  2548. X86_CONTEXT Context;
  2549. #define CPCXT(Fld) Context.Fld = TSS.Fld
  2550. CPCXT(Ebp); CPCXT(Eip); CPCXT(Eax); CPCXT(Ecx); CPCXT(Edx);
  2551. CPCXT(Edi); CPCXT(Esi); CPCXT(Ebx); CPCXT(Esp);
  2552. CPCXT(EFlags);
  2553. #undef CPCXT
  2554. Context.SegCs = TSS.Ss; Context.SegDs = TSS.Ds; Context.SegEs = TSS.Es;
  2555. Context.SegFs = TSS.Fs; Context.SegGs = TSS.Gs; Context.SegSs = SegSs;
  2556. g_LastRegFrame.InstructionOffset = EXTEND64(Context.Eip);
  2557. g_LastRegFrame.StackOffset = EXTEND64(Context.Esp);
  2558. g_LastRegFrame.FrameOffset = EXTEND64(Context.Ebp);
  2559. SetCurrentScope(&g_LastRegFrame, &Context, sizeof(X86_CONTEXT));
  2560. return S_OK;
  2561. }