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.

1024 lines
28 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. w64cpuex.c
  5. Abstract:
  6. Debugger extension DLL for debugging the CPU
  7. Author:
  8. 27-Sept-1999 BarryBo
  9. Revision History:
  10. --*/
  11. #define _WOW64CPUDBGAPI_
  12. #define DECLARE_CPU_DEBUGGER_INTERFACE
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <imagehlp.h>
  18. #include <ntsdexts.h>
  19. #include "ntosdef.h"
  20. #include "v86emul.h"
  21. #include "ia64.h"
  22. #include "wow64.h"
  23. #include "wow64cpu.h"
  24. #define MSCPU
  25. #include "threadst.h"
  26. #include "entrypt.h"
  27. #include "config.h"
  28. #include "instr.h"
  29. #include "compiler.h"
  30. #include "cpunotif.h"
  31. #include "cpuregs.h"
  32. /* Masks for bits 0 - 32. */
  33. #define BIT0 0x1
  34. #define BIT1 0x2
  35. #define BIT2 0x4
  36. #define BIT3 0x8
  37. #define BIT4 0x10
  38. #define BIT5 0x20
  39. #define BIT6 0x40
  40. #define BIT7 0x80
  41. #define BIT8 0x100
  42. #define BIT9 0x200
  43. #define BIT10 0x400
  44. #define BIT11 0x800
  45. #define BIT12 0x1000
  46. #define BIT13 0x2000
  47. #define BIT14 0x4000
  48. #define BIT15 0x8000
  49. #define BIT16 0x10000
  50. #define BIT17 0x20000
  51. #define BIT18 0x40000
  52. #define BIT19 0x80000
  53. #define BIT20 0x100000
  54. #define BIT21 0x200000
  55. #define BIT22 0x400000
  56. #define BIT23 0x800000
  57. #define BIT24 0x1000000
  58. #define BIT25 0x2000000
  59. #define BIT26 0x4000000
  60. #define BIT27 0x8000000
  61. #define BIT28 0x10000000
  62. #define BIT29 0x20000000
  63. #define BIT30 0x40000000
  64. #define BIT31 0x80000000
  65. BOOL AutoFlushFlag = TRUE;
  66. HANDLE Process;
  67. HANDLE Thread;
  68. PNTSD_OUTPUT_ROUTINE OutputRoutine;
  69. PNTSD_GET_SYMBOL GetSymbolRoutine;
  70. PNTSD_GET_EXPRESSION GetExpression;
  71. PWOW64GETCPUDATA CpuGetData;
  72. LPSTR ArgumentString;
  73. #define DEBUGGERPRINT (*OutputRoutine)
  74. #define GETSYMBOL (*GetSymbolRoutine)
  75. #define GETEXPRESSION (*GetExpression)
  76. #define CPUGETDATA (*CpuGetData)
  77. // Local copy of the current process/thread's CPU state
  78. PVOID RemoteCpuData;
  79. THREADSTATE LocalCpuContext;
  80. BOOL ContextFetched;
  81. BOOL ContextDirty;
  82. // Cached addresses of interesting symbols within the CPU
  83. HANDLE CachedProcess;
  84. ULONG_PTR pCompilerFlags;
  85. ULONG_PTR pTranslationCacheFlags;
  86. ULONG_PTR pDirtyMemoryAddr;
  87. ULONG_PTR pDirtyMemoryLength;
  88. ULONG GetEfl(VOID);
  89. VOID SetEfl(ULONG);
  90. //
  91. // Table mapping a byte to a 0 or 1, corresponding to the parity bit for
  92. // that byte.
  93. //
  94. CONST BYTE ParityBit[] = {
  95. 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
  96. 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
  97. 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
  98. 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
  99. 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
  100. 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
  101. 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
  102. 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
  103. 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
  104. 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
  105. 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
  106. 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
  107. 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
  108. 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
  109. 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
  110. 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
  111. };
  112. /*
  113. * Does a plain old GetExpression under a try-except
  114. */
  115. NTSTATUS
  116. TryGetExpr(
  117. PSTR Expression,
  118. PULONG_PTR pValue
  119. )
  120. {
  121. NTSTATUS Status = STATUS_SUCCESS;
  122. try {
  123. *pValue = GETEXPRESSION(Expression);
  124. } except(EXCEPTION_EXECUTE_HANDLER) {
  125. Status = GetExceptionCode();
  126. }
  127. return Status;
  128. }
  129. VOID
  130. InvalidateSymbolsIfNeeded(
  131. VOID
  132. )
  133. {
  134. if (CachedProcess == Process) {
  135. // The symbols match the current process
  136. return;
  137. }
  138. // else the symbols were for another process. Invalidate the cache.
  139. pCompilerFlags = 0;
  140. pTranslationCacheFlags = 0;
  141. pDirtyMemoryAddr = 0;
  142. pDirtyMemoryLength = 0;
  143. CachedProcess = Process;
  144. }
  145. DWORD
  146. GetCompilerFlags(void)
  147. {
  148. NTSTATUS Status;
  149. DWORD CompilerFlags;
  150. InvalidateSymbolsIfNeeded();
  151. if (!pCompilerFlags) {
  152. Status = TryGetExpr("CompilerFlags", (ULONG_PTR *)&pCompilerFlags);
  153. if (!NT_SUCCESS(Status) || !pCompilerFlags) {
  154. DEBUGGERPRINT("Unable to get address of CompilerFlags Status %x\n",
  155. Status
  156. );
  157. pCompilerFlags = 0;
  158. return 0xffffffff;
  159. }
  160. }
  161. Status = NtReadVirtualMemory(Process, (PVOID)pCompilerFlags, &CompilerFlags, sizeof(DWORD), NULL);
  162. if (!NT_SUCCESS(Status)) {
  163. DEBUGGERPRINT("Unable to read CompilerFlags Status %x\n", Status);
  164. return 0xffffffff;
  165. }
  166. return CompilerFlags;
  167. }
  168. void
  169. SetCompilerFlags(DWORD CompilerFlags)
  170. {
  171. NTSTATUS Status;
  172. InvalidateSymbolsIfNeeded();
  173. if (!pCompilerFlags) {
  174. Status = TryGetExpr("CompilerFlags", (ULONG_PTR *)&pCompilerFlags);
  175. if (!NT_SUCCESS(Status) || !pCompilerFlags) {
  176. DEBUGGERPRINT("Unable to get address of CompilerFlags Status %x\n",
  177. Status
  178. );
  179. pCompilerFlags = 0;
  180. return;
  181. }
  182. }
  183. Status = NtWriteVirtualMemory(Process, (PVOID)pCompilerFlags, &CompilerFlags, sizeof(DWORD), NULL);
  184. if (!NT_SUCCESS(Status)) {
  185. DEBUGGERPRINT("Unable to writes CompilerFlags Status %x\n", Status);
  186. return;
  187. }
  188. }
  189. NTSTATUS
  190. GetDirtyMemoryRange(PULONG DirtyMemoryAddr, PULONG DirtyMemoryLength)
  191. {
  192. NTSTATUS Status;
  193. ULONG DirtyMemoryEnd;
  194. InvalidateSymbolsIfNeeded();
  195. if (pDirtyMemoryLength == 0) {
  196. //
  197. // First call to CpuFlushInstructionCache() - need to set up
  198. // the global variables.
  199. //
  200. Status = TryGetExpr("DbgDirtyMemoryAddr", (ULONG_PTR *)&pDirtyMemoryAddr);
  201. if (!NT_SUCCESS(Status) || !pDirtyMemoryAddr) {
  202. DEBUGGERPRINT("Unable to get address of DbgDirtyMemoryAddr Status %x\n",
  203. Status
  204. );
  205. return Status;
  206. }
  207. Status = TryGetExpr("DbgDirtyMemoryLength", (ULONG_PTR *)&pDirtyMemoryLength);
  208. if (!NT_SUCCESS(Status) || !pDirtyMemoryLength) {
  209. DEBUGGERPRINT("Unable to get address of DbgDirtyMemoryLength Status %x\n",
  210. Status
  211. );
  212. return Status;
  213. }
  214. }
  215. Status = NtReadVirtualMemory(Process,
  216. (PVOID)pDirtyMemoryAddr,
  217. DirtyMemoryAddr,
  218. sizeof(ULONG),
  219. NULL
  220. );
  221. if (!NT_SUCCESS(Status)) {
  222. DEBUGGERPRINT("Unable to read pDirtyMemoryAddr %x Status %x\n",
  223. pDirtyMemoryAddr,
  224. Status
  225. );
  226. return Status;
  227. }
  228. Status = NtReadVirtualMemory(Process,
  229. (PVOID)pDirtyMemoryLength,
  230. DirtyMemoryLength,
  231. sizeof(ULONG),
  232. NULL
  233. );
  234. if (!NT_SUCCESS(Status)) {
  235. DEBUGGERPRINT("Unable to read pDirtyMemoryLength %x Status %x\n",
  236. pDirtyMemoryLength,
  237. Status
  238. );
  239. pDirtyMemoryLength = 0;
  240. return Status;
  241. }
  242. return Status;
  243. }
  244. void
  245. RemindUserToFlushTheCache(void)
  246. {
  247. NTSTATUS Status;
  248. DWORD TranslationCacheFlags;
  249. DWORD CompilerFlags;
  250. BOOLEAN fCacheFlushPending;
  251. //
  252. // Read the value of TranslationCacheFlags
  253. //
  254. if (!pTranslationCacheFlags) {
  255. Status = TryGetExpr("TranslationCacheFlags", (ULONG_PTR *)&pTranslationCacheFlags);
  256. if (!NT_SUCCESS(Status) || !pTranslationCacheFlags) {
  257. DEBUGGERPRINT("Unable to get address of TranslationCacheFlags Status %x\n",
  258. Status
  259. );
  260. return;
  261. }
  262. }
  263. Status = NtReadVirtualMemory(Process, (PVOID)pTranslationCacheFlags, &TranslationCacheFlags, sizeof(TranslationCacheFlags), NULL);
  264. if (!NT_SUCCESS(Status)) {
  265. DEBUGGERPRINT("Unable to read TranslationCacheFlags Status %x\n", Status);
  266. return;
  267. }
  268. //
  269. // Read the value of CompilerFlags
  270. //
  271. CompilerFlags = GetCompilerFlags();
  272. if (CompilerFlags == 0xffffffff) {
  273. //
  274. // Got an error getting the CompilerFlags value.
  275. //
  276. return;
  277. }
  278. //
  279. // Determine if the Translation Cache is going to be flushed next time
  280. // the CPU runs or not.
  281. //
  282. fCacheFlushPending =
  283. (LocalCpuContext.CpuNotify & CPUNOTIFY_MODECHANGE) ? TRUE : FALSE;
  284. if (!fCacheFlushPending && (LocalCpuContext.CpuNotify & CPUNOTIFY_DBGFLUSHTC)) {
  285. DWORD Addr, Length;
  286. Status = GetDirtyMemoryRange(&Addr, &Length);
  287. if (!NT_SUCCESS(Status)) {
  288. return;
  289. }
  290. if (Addr == 0 && Length == 0xffffffff) {
  291. //
  292. // Cache flush is pending because user asked for !flush
  293. //
  294. fCacheFlushPending = TRUE;
  295. }
  296. }
  297. //
  298. // Give the user some worldly advice
  299. //
  300. if (LocalCpuContext.CpuNotify & (CPUNOTIFY_TRACEFLAG|CPUNOTIFY_SLOWMODE)) {
  301. //
  302. // We need to be in slow mode to get logging to work.
  303. //
  304. if (CompilerFlags & COMPFL_FAST) {
  305. //
  306. // Cpu is set to generate fast code. Remedy that.
  307. //
  308. if (AutoFlushFlag) {
  309. SetCompilerFlags(COMPFL_SLOW);
  310. } else {
  311. DEBUGGERPRINT("CPU in fast mode. Use '!wx86e.code SLOW' to switch to slow mode.\n");
  312. }
  313. }
  314. if (!fCacheFlushPending && (TranslationCacheFlags & COMPFL_FAST)) {
  315. //
  316. // Translation Cache contains fast code. Rememdy that.
  317. //
  318. if (AutoFlushFlag) {
  319. LocalCpuContext.CpuNotify |= CPUNOTIFY_MODECHANGE;
  320. ContextDirty = TRUE;
  321. } else {
  322. DEBUGGERPRINT("Translation Cache contains fast code. Use '!wx86e.flush' to flush,\n");
  323. DEBUGGERPRINT("or the CPU will probably jump somewhere unexpected.\n");
  324. }
  325. }
  326. if (fCacheFlushPending && TranslationCacheFlags == COMPFL_SLOW) {
  327. //
  328. // If there is a cache flush pending due to a switch in
  329. // compilation modes, but the code in the cache is already
  330. // correct, undo the cache flush
  331. //
  332. LocalCpuContext.CpuNotify &= ~(ULONG)CPUNOTIFY_MODECHANGE;
  333. ContextDirty = TRUE;
  334. }
  335. } else {
  336. //
  337. // We can run in fast mode.
  338. //
  339. if (CompilerFlags & COMPFL_SLOW) {
  340. //
  341. // Cpu is set to generate slow code. Remedy that.
  342. //
  343. if (AutoFlushFlag) {
  344. SetCompilerFlags(COMPFL_FAST);
  345. } else {
  346. DEBUGGERPRINT("CPU in slow mode. Use '!wx86e.code FAST' to switch to fast mode.\n");
  347. }
  348. }
  349. if (!fCacheFlushPending && (TranslationCacheFlags & COMPFL_SLOW)) {
  350. //
  351. // Translation Cache contains slow code. Remedy that.
  352. //
  353. if (AutoFlushFlag) {
  354. LocalCpuContext.CpuNotify |= CPUNOTIFY_MODECHANGE;
  355. ContextDirty = TRUE;
  356. } else {
  357. DEBUGGERPRINT("Translation Cache contains slow code. Use '!wx86e.flush' to flush.\n");
  358. }
  359. }
  360. if (fCacheFlushPending && TranslationCacheFlags == COMPFL_FAST) {
  361. //
  362. // If there is a cache flush pending due to a switch in
  363. // compilation modes, but the code in the cache is already
  364. // correct, undo the cache flush
  365. //
  366. LocalCpuContext.CpuNotify &= ~(ULONG)CPUNOTIFY_MODECHANGE;
  367. ContextDirty = TRUE;
  368. }
  369. }
  370. }
  371. WOW64CPUDBGAPI VOID
  372. CpuDbgInitExtapi(
  373. HANDLE hArgProcess,
  374. HANDLE hArgThread,
  375. DWORD64 ArgCurrentPC,
  376. PNTSD_EXTENSION_APIS lpExtensionApis,
  377. PWOW64GETCPUDATA lpGetData
  378. )
  379. {
  380. Process = hArgProcess;
  381. Thread = hArgThread;
  382. OutputRoutine = lpExtensionApis->lpOutputRoutine;
  383. GetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
  384. GetExpression = lpExtensionApis->lpGetExpressionRoutine;
  385. CpuGetData = lpGetData;
  386. InvalidateSymbolsIfNeeded();
  387. ContextFetched = FALSE;
  388. ContextDirty = FALSE;
  389. }
  390. WOW64CPUDBGAPI BOOL
  391. CpuDbgGetRemoteContext(
  392. PVOID CpuData
  393. )
  394. {
  395. NTSTATUS Status;
  396. Status = NtReadVirtualMemory(Process,
  397. CpuData,
  398. &LocalCpuContext,
  399. sizeof(LocalCpuContext),
  400. NULL);
  401. if (!NT_SUCCESS(Status)) {
  402. DEBUGGERPRINT("CpuDbgGetRemoteContext: Error %x reading CPU data from %x\n", Status, CpuData);
  403. return FALSE;
  404. }
  405. ContextFetched = TRUE;
  406. RemoteCpuData = CpuData;
  407. return TRUE;
  408. }
  409. WOW64CPUDBGAPI BOOL
  410. CpuDbgSetRemoteContext(
  411. void
  412. )
  413. {
  414. NTSTATUS Status;
  415. if (!ContextDirty) {
  416. // Perf. optimization... don't update the remote context if
  417. // nothing has changed.
  418. return TRUE;
  419. }
  420. if (!ContextFetched) {
  421. DEBUGGERPRINT("CpuDbgSetRemoteContext: Remote context was never fetched!\n");
  422. return FALSE;
  423. }
  424. Status = NtWriteVirtualMemory(Process,
  425. RemoteCpuData,
  426. &LocalCpuContext,
  427. sizeof(LocalCpuContext),
  428. NULL);
  429. if (!NT_SUCCESS(Status)) {
  430. DEBUGGERPRINT("CpuDbgSetRemoteContext: Error %x writing CPU data to %x\n", Status, RemoteCpuData);
  431. return FALSE;
  432. }
  433. ContextDirty = FALSE;
  434. return TRUE;
  435. }
  436. WOW64CPUDBGAPI BOOL
  437. CpuDbgGetLocalContext(
  438. PCONTEXT32 Context
  439. )
  440. {
  441. ULONG ContextFlags = Context->ContextFlags;
  442. PTHREADSTATE cpu = &LocalCpuContext;
  443. if ((ContextFlags & CONTEXT_CONTROL_WX86) == CONTEXT_CONTROL_WX86) {
  444. Context->EFlags = GetEfl();
  445. Context->SegCs = CS;
  446. Context->Esp = esp;
  447. Context->SegSs = SS;
  448. Context->Ebp = ebp;
  449. Context->Eip = eip;
  450. //Context->Eip = cpu->eipReg.i4;
  451. }
  452. if ((ContextFlags & CONTEXT_SEGMENTS_WX86) == CONTEXT_SEGMENTS_WX86) {
  453. Context->SegGs = GS;
  454. Context->SegFs = FS;
  455. Context->SegEs = ES;
  456. Context->SegDs = DS;
  457. }
  458. if ((ContextFlags & CONTEXT_INTEGER_WX86) == CONTEXT_INTEGER_WX86) {
  459. Context->Eax = eax;
  460. Context->Ebx = ebx;
  461. Context->Ecx = ecx;
  462. Context->Edx = edx;
  463. Context->Edi = edi;
  464. Context->Esi = esi;
  465. }
  466. #if 0
  467. if ((ContextFlags & CONTEXT_FLOATING_POINT_WX86) == CONTEXT_FLOATING_POINT_WX86) {
  468. }
  469. if ((ContextFlags & CONTEXT_DEBUG_REGISTERS_WX86) == CONTEXT_DEBUG_REGISTERS_WX86) {
  470. }
  471. if ((ContextFlags & CONTEXT_EXTENDED_REGISTERS_WX86) == CONTEXT_EXTENDED_REGISTERS_WX86) {
  472. }
  473. #endif
  474. return TRUE;
  475. }
  476. WOW64CPUDBGAPI BOOL
  477. CpuDbgSetLocalContext(
  478. PCONTEXT32 Context
  479. )
  480. {
  481. ULONG ContextFlags = Context->ContextFlags;
  482. PTHREADSTATE cpu = &LocalCpuContext;
  483. if ((ContextFlags & CONTEXT_CONTROL_WX86) == CONTEXT_CONTROL_WX86) {
  484. //
  485. // i386 control registers are:
  486. // ebp, eip, cs, eflag, esp and ss
  487. //
  488. LocalCpuContext.GpRegs[GP_EBP].i4 = Context->Ebp;
  489. LocalCpuContext.eipReg.i4 = Context->Eip;
  490. LocalCpuContext.GpRegs[REG_CS].i4= KGDT_R3_CODE|3; // Force Reality
  491. SetEfl(Context->EFlags);
  492. LocalCpuContext.GpRegs[GP_ESP].i4 = Context->Esp;
  493. LocalCpuContext.GpRegs[REG_SS].i4 = KGDT_R3_DATA|3; // Force Reality
  494. ContextDirty = TRUE;
  495. }
  496. if ((ContextFlags & CONTEXT_INTEGER_WX86) == CONTEXT_INTEGER_WX86){
  497. //
  498. // i386 integer registers are:
  499. // edi, esi, ebx, edx, ecx, eax
  500. //
  501. LocalCpuContext.GpRegs[GP_EDI].i4 = Context->Edi;
  502. LocalCpuContext.GpRegs[GP_ESI].i4 = Context->Esi;
  503. LocalCpuContext.GpRegs[GP_EBX].i4 = Context->Ebx;
  504. LocalCpuContext.GpRegs[GP_EDX].i4 = Context->Edx;
  505. LocalCpuContext.GpRegs[GP_ECX].i4 = Context->Ecx;
  506. LocalCpuContext.GpRegs[GP_EAX].i4 = Context->Eax;
  507. ContextDirty = TRUE;
  508. }
  509. if ((ContextFlags & CONTEXT_SEGMENTS_WX86) == CONTEXT_SEGMENTS_WX86) {
  510. //
  511. // i386 segment registers are:
  512. // ds, es, fs, gs
  513. // And since they are a constant, force them to be the right values
  514. //
  515. LocalCpuContext.GpRegs[REG_DS].i4 = KGDT_R3_DATA|3;
  516. LocalCpuContext.GpRegs[REG_ES].i4 = KGDT_R3_DATA|3;
  517. LocalCpuContext.GpRegs[REG_FS].i4 = KGDT_R3_TEB|3;
  518. LocalCpuContext.GpRegs[REG_GS].i4 = KGDT_R3_DATA|3;
  519. ContextDirty = TRUE;
  520. }
  521. #if 0
  522. if ((ContextFlags & CONTEXT_FLOATING_POINT_WX86) == CONTEXT_FLOATING_POINT_WX86) {
  523. }
  524. if ((ContextFlags & CONTEXT_DEBUG_REGISTERS_WX86) == CONTEXT_DEBUG_REGISTERS_WX86) {
  525. }
  526. if ((ContextFlags & CONTEXT_EXTENDED_REGISTERS_WX86) == CONTEXT_EXTENDED_REGISTERS_WX86) {
  527. }
  528. #endif
  529. return TRUE;
  530. }
  531. WOW64CPUDBGAPI VOID
  532. CpuDbgFlushInstructionCache(
  533. PVOID Addr,
  534. DWORD Length
  535. )
  536. {
  537. NTSTATUS Status;
  538. ULONG DirtyMemoryEnd;
  539. ULONG DirtyMemoryAddr;
  540. ULONG DirtyMemoryLength;
  541. Status = GetDirtyMemoryRange(&DirtyMemoryAddr, &DirtyMemoryLength);
  542. if (!NT_SUCCESS(Status)) {
  543. return;
  544. }
  545. if (DirtyMemoryAddr == 0xffffffff) {
  546. DirtyMemoryEnd = 0;
  547. } else {
  548. DirtyMemoryEnd = DirtyMemoryAddr + DirtyMemoryLength;
  549. }
  550. if (PtrToUlong(Addr) < DirtyMemoryAddr) {
  551. //
  552. // The new address is before the start of the dirty range
  553. //
  554. DirtyMemoryLength += DirtyMemoryAddr-PtrToUlong(Addr);
  555. DirtyMemoryAddr = PtrToUlong(Addr);
  556. }
  557. if (PtrToUlong(Addr)+Length > DirtyMemoryEnd) {
  558. //
  559. // The range is too small - grow it
  560. //
  561. DirtyMemoryEnd = PtrToUlong(Addr)+Length;
  562. DirtyMemoryLength = DirtyMemoryEnd - DirtyMemoryAddr;
  563. }
  564. // Tell the CPU to call CpuFlushInstructionCache() next time it runs.
  565. //
  566. // The wow64 debugger extension guarantees that it will call
  567. // DbgCpuGetRemoteContext before this call, and will call
  568. // DbgCpuSetRemoteContext after this call, so we can flush out
  569. // our context then.
  570. //
  571. NtWriteVirtualMemory(Process, (PVOID)pDirtyMemoryAddr, &DirtyMemoryAddr, sizeof(ULONG), NULL);
  572. NtWriteVirtualMemory(Process, (PVOID)pDirtyMemoryLength, &DirtyMemoryLength, sizeof(ULONG), NULL);
  573. LocalCpuContext.CpuNotify |= CPUNOTIFY_DBGFLUSHTC;
  574. ContextDirty = TRUE;
  575. }
  576. VOID SetEax(ULONG ul) {
  577. LocalCpuContext.GpRegs[GP_EAX].i4 = ul;
  578. ContextDirty = TRUE;
  579. }
  580. VOID SetEbx(ULONG ul) {
  581. LocalCpuContext.GpRegs[GP_EBX].i4 = ul;
  582. ContextDirty = TRUE;
  583. }
  584. VOID SetEcx(ULONG ul) {
  585. LocalCpuContext.GpRegs[GP_ECX].i4 = ul;
  586. ContextDirty = TRUE;
  587. }
  588. VOID SetEdx(ULONG ul) {
  589. LocalCpuContext.GpRegs[GP_EDX].i4 = ul;
  590. ContextDirty = TRUE;
  591. }
  592. VOID SetEsi(ULONG ul) {
  593. LocalCpuContext.GpRegs[GP_ESI].i4 = ul;
  594. ContextDirty = TRUE;
  595. }
  596. VOID SetEdi(ULONG ul) {
  597. LocalCpuContext.GpRegs[GP_EDI].i4 = ul;
  598. ContextDirty = TRUE;
  599. }
  600. VOID SetEbp(ULONG ul) {
  601. LocalCpuContext.GpRegs[GP_EBP].i4 = ul;
  602. ContextDirty = TRUE;
  603. }
  604. VOID SetEsp(ULONG ul) {
  605. LocalCpuContext.GpRegs[GP_ESP].i4 = ul;
  606. ContextDirty = TRUE;
  607. }
  608. VOID SetEip(ULONG ul) {
  609. LocalCpuContext.eipReg.i4 = ul;
  610. ContextDirty = TRUE;
  611. }
  612. VOID SetEfl(ULONG ul) {
  613. LocalCpuContext.flag_cf = (ul & BIT0) ? 0x80000000 : 0;
  614. LocalCpuContext.flag_pf = (ul & BIT2) ? 0 : 1;
  615. LocalCpuContext.flag_aux= (ul & BIT4) ? 0x10 : 0;
  616. LocalCpuContext.flag_zf = (ul & BIT6) ? 0 : 1;
  617. LocalCpuContext.flag_sf = (ul & BIT7) ? 0x80000000 : 0;
  618. LocalCpuContext.flag_tf = (ul & BIT8) ? 1 : 0;
  619. LocalCpuContext.flag_df = (ul & BIT10) ? 1 : -1;
  620. LocalCpuContext.flag_of = (ul & BIT11) ? 0x80000000 : 0;
  621. // iopl, NT, RF, VM are ignored
  622. LocalCpuContext.flag_ac = (ul & BIT18);
  623. LocalCpuContext.CpuNotify &= ~CPUNOTIFY_TRACEFLAG;
  624. LocalCpuContext.CpuNotify |= LocalCpuContext.flag_tf;
  625. ContextDirty = TRUE;
  626. // If the single-step flag is set and the CPU is in fast mode, this
  627. // will flush the cache if autoflush is set, or else remind the user
  628. // if autoflush is clear.
  629. RemindUserToFlushTheCache();
  630. }
  631. ULONG GetEax(VOID) {
  632. return LocalCpuContext.GpRegs[GP_EAX].i4;
  633. }
  634. ULONG GetEbx(VOID) {
  635. return LocalCpuContext.GpRegs[GP_EBX].i4;
  636. }
  637. ULONG GetEcx(VOID) {
  638. return LocalCpuContext.GpRegs[GP_ECX].i4;
  639. }
  640. ULONG GetEdx(VOID) {
  641. return LocalCpuContext.GpRegs[GP_EDX].i4;
  642. }
  643. ULONG GetEsi(VOID) {
  644. return LocalCpuContext.GpRegs[GP_ESI].i4;
  645. }
  646. ULONG GetEdi(VOID) {
  647. return LocalCpuContext.GpRegs[GP_EDI].i4;
  648. }
  649. ULONG GetEsp(VOID) {
  650. return LocalCpuContext.GpRegs[GP_ESP].i4;
  651. }
  652. ULONG GetEbp(VOID) {
  653. return LocalCpuContext.GpRegs[GP_EBP].i4;
  654. }
  655. ULONG GetEip(VOID) {
  656. return LocalCpuContext.eipReg.i4;
  657. }
  658. ULONG GetEfl(VOID) {
  659. return (LocalCpuContext.flag_ac | // this is either 0 or 2^18
  660. // VM, RF, NT are all 0
  661. ((LocalCpuContext.flag_of & 0x80000000) ? (1 << 11) : 0) |
  662. ((LocalCpuContext.flag_df == -1) ? 0 : (1 << 10)) |
  663. 1 << 9 | // IF
  664. LocalCpuContext.flag_tf << 8 |
  665. ((LocalCpuContext.flag_sf & 0x80000000) ? (1 << 7) : 0) |
  666. ((LocalCpuContext.flag_zf) ? 0 : (1 << 6)) |
  667. ((LocalCpuContext.flag_aux & 0x10) ? (1 << 4) : 0) |
  668. ParityBit[LocalCpuContext.flag_pf & 0xff] << 2 |
  669. 0x2 |
  670. ((LocalCpuContext.flag_cf & 0x80000000) ? 1 : 0)
  671. );
  672. }
  673. CPUREGFUNCS CpuRegFuncs[] = {
  674. { "eax", SetEax, GetEax },
  675. { "ebx", SetEbx, GetEbx },
  676. { "ecx", SetEcx, GetEcx },
  677. { "edx", SetEdx, GetEdx },
  678. { "esi", SetEsi, GetEsi },
  679. { "edi", SetEdi, GetEdi },
  680. { "esp", SetEsp, GetEsp },
  681. { "ebp", SetEbp, GetEbp },
  682. { "eip", SetEip, GetEip },
  683. { "efl", SetEfl, GetEfl },
  684. { NULL, NULL, NULL}
  685. };
  686. WOW64CPUDBGAPI PCPUREGFUNCS
  687. CpuDbgGetRegisterFuncs(
  688. void
  689. )
  690. {
  691. return CpuRegFuncs;
  692. }
  693. #define DECLARE_EXTAPI(name) \
  694. VOID \
  695. name( \
  696. HANDLE hCurrentProcess, \
  697. HANDLE hCurrentThread, \
  698. DWORD64 dwCurrentPc, \
  699. PNTSD_EXTENSION_APIS lpExtensionApis, \
  700. LPSTR lpArgumentString \
  701. )
  702. #define INIT_EXTAPI \
  703. Process = hCurrentProcess; \
  704. Thread = hCurrentThread; \
  705. OutputRoutine = lpExtensionApis->lpOutputRoutine; \
  706. GetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine; \
  707. GetExpression = lpExtensionApis->lpGetExpressionRoutine; \
  708. ArgumentString = lpArgumentString;
  709. DECLARE_EXTAPI(help)
  710. {
  711. INIT_EXTAPI;
  712. DEBUGGERPRINT("WOW64 MS CPU debugger extensions:\n\n");
  713. DEBUGGERPRINT("epi [inteladdress] - dump an entrypt based on x86 address\n");
  714. DEBUGGERPRINT("epn [nativeaddress] - dump an entrypt based on a native address\n");
  715. DEBUGGERPRINT("dumpep - all entrypts\n");
  716. DEBUGGERPRINT("code [fast|slow] - set the CPU's code-gen mode\n");
  717. DEBUGGERPRINT("flush - flush the Translation Cache\n");
  718. DEBUGGERPRINT("autoflush - the debugger extension may auto-flush the TC\n");
  719. DEBUGGERPRINT("logeip - enable EIP logging\n");
  720. DEBUGGERPRINT("last - dump the last EIP values\n");
  721. DEBUGGERPRINT("callstack - dump the internal callstack cache\n");
  722. }
  723. DECLARE_EXTAPI(autoflush)
  724. {
  725. INIT_EXTAPI;
  726. if (AutoFlushFlag) {
  727. AutoFlushFlag = FALSE;
  728. DEBUGGERPRINT("autoflush is OFF - use !flush to flush the cache when needed.\n");
  729. } else {
  730. AutoFlushFlag = TRUE;
  731. DEBUGGERPRINT("autoflush is ON - The CPU Cache will be flushed automatically.\n");
  732. }
  733. }
  734. DECLARE_EXTAPI(code)
  735. {
  736. DWORD CompilerFlags;
  737. INIT_EXTAPI;
  738. CompilerFlags = GetCompilerFlags();
  739. if (CompilerFlags == 0xffffffff) {
  740. //
  741. // Got an error reading the CompilerFlags variable
  742. //
  743. return;
  744. }
  745. if (!ArgumentString) {
  746. PrintCurrentValue:
  747. DEBUGGERPRINT("CPU Compiler is in %s mode.\n",
  748. (CompilerFlags & COMPFL_SLOW) ? "SLOW" : "FAST");
  749. return;
  750. }
  751. // Skip over whitespace
  752. while (*ArgumentString && isspace(*ArgumentString)) {
  753. ArgumentString++;
  754. }
  755. if (!*ArgumentString) {
  756. goto PrintCurrentValue;
  757. }
  758. if (_stricmp(ArgumentString, "fast") == 0) {
  759. SetCompilerFlags(COMPFL_FAST);
  760. } else if (_stricmp(ArgumentString, "slow") == 0) {
  761. SetCompilerFlags(COMPFL_SLOW);
  762. } else {
  763. DEBUGGERPRINT("usage: !code [fast|slow]\n");
  764. }
  765. RemindUserToFlushTheCache();
  766. }
  767. DECLARE_EXTAPI(flush)
  768. {
  769. INIT_EXTAPI;
  770. if (!CpuDbgGetRemoteContext(CPUGETDATA(Process, Thread))) {
  771. return;
  772. }
  773. CpuDbgFlushInstructionCache(0, 0xffffffff);
  774. CpuDbgSetRemoteContext();
  775. DEBUGGERPRINT("CPU Translation Cache will flush next time CpuSimulate loops.\n");
  776. }
  777. DECLARE_EXTAPI(logeip)
  778. {
  779. ULONG CpuNotify;
  780. INIT_EXTAPI;
  781. if (!CpuDbgGetRemoteContext(CPUGETDATA(Process, Thread))) {
  782. return;
  783. }
  784. CpuNotify = LocalCpuContext.CpuNotify;
  785. if (CpuNotify & CPUNOTIFY_SLOWMODE) {
  786. CpuNotify &= ~CPUNOTIFY_SLOWMODE;
  787. } else {
  788. CpuNotify |= CPUNOTIFY_SLOWMODE;
  789. }
  790. LocalCpuContext.CpuNotify = CpuNotify;
  791. ContextDirty = TRUE;
  792. if (CpuDbgSetRemoteContext()) {
  793. DEBUGGERPRINT("EIP logging ");
  794. if (CpuNotify & CPUNOTIFY_SLOWMODE) {
  795. DEBUGGERPRINT("ON - use !last to see the EIP log.\n");
  796. } else {
  797. DEBUGGERPRINT("OFF.\n");
  798. }
  799. }
  800. }
  801. DECLARE_EXTAPI(last)
  802. {
  803. ULONG CpuNotify;
  804. DWORD64 n;
  805. char *pchCmd;
  806. DWORD64 EipOffset, i;
  807. INIT_EXTAPI;
  808. if (!CpuDbgGetRemoteContext(CPUGETDATA(Process, Thread))) {
  809. return;
  810. }
  811. // Parse out the optional number of instructions. Default is all
  812. // instructions in the log
  813. n = 0xffffffff;
  814. pchCmd = ArgumentString;
  815. while (*pchCmd && isspace(*pchCmd)) {
  816. pchCmd++;
  817. }
  818. if (*pchCmd) {
  819. NTSTATUS Status;
  820. Status = TryGetExpr(pchCmd, &n);
  821. if (!NT_SUCCESS(Status) || !n) {
  822. DEBUGGERPRINT("Invalid Length: '%s' Status %x\n",
  823. pchCmd,
  824. Status
  825. );
  826. return;
  827. }
  828. }
  829. CpuNotify = LocalCpuContext.CpuNotify;
  830. if (!(CpuNotify & CPUNOTIFY_SLOWMODE)) {
  831. DEBUGGERPRINT("Warning: logeip is not enabled. Log may be out-of-date.\n");
  832. }
  833. EipOffset = LocalCpuContext.eipLogIndex;
  834. if (n >= EIPLOGSIZE) {
  835. n = EIPLOGSIZE;
  836. } else {
  837. EipOffset -= n;
  838. }
  839. for (i = 0; i<n; ++i, ++EipOffset) {
  840. EipOffset %= EIPLOGSIZE;
  841. if (LocalCpuContext.eipLog[EipOffset] == 0) {
  842. break;
  843. }
  844. DEBUGGERPRINT("%x %x\n", i, LocalCpuContext.eipLog[EipOffset]);
  845. }
  846. }
  847. DECLARE_EXTAPI(callstack)
  848. /*++
  849. Routine Description:
  850. This routine dumps out the callstack for the thread.
  851. Arguments:
  852. none
  853. Return Value:
  854. None.
  855. --*/
  856. {
  857. ULONG i;
  858. INIT_EXTAPI;
  859. //
  860. // fetch the CpuContext for the current thread
  861. //
  862. if (!CpuDbgGetRemoteContext(CPUGETDATA(Process, Thread))) {
  863. return;
  864. }
  865. //
  866. // Dump out the call stack
  867. //
  868. DEBUGGERPRINT(" CallStackTimeStamp : %08lx\n", LocalCpuContext.CSTimestamp);
  869. DEBUGGERPRINT(" CallStackIndex : %08lx\n", LocalCpuContext.CSIndex);
  870. DEBUGGERPRINT(" -----------------------------\n");
  871. DEBUGGERPRINT(" Intel : Native\n");
  872. for (i = 0; i < CSSIZE; i++) {
  873. DEBUGGERPRINT(
  874. " %08lx : %08lx\n",
  875. LocalCpuContext.callStack[i].intelAddr,
  876. LocalCpuContext.callStack[i].nativeAddr
  877. );
  878. }
  879. }