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.

684 lines
16 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. trace.c
  5. Abstract:
  6. This file contains code to dump the ntvdm trace history log
  7. Author:
  8. Neil Sandlin (neilsa) 1-Nov-1995
  9. Revision History:
  10. --*/
  11. #include <precomp.h>
  12. #pragma hdrstop
  13. #include <dbgsvc.h>
  14. #include <dpmi.h>
  15. ULONG TimeIndex;
  16. ULONG TimerMode = 0;
  17. ULONG CpuSpeed = 0;
  18. BOOL bTriedToGetCpuSpeed = FALSE;
  19. #define CPUSPEED_PATH "Hardware\\Description\\System\\CentralProcessor\\0"
  20. #define CPUSPEED_VALUE "~MHz"
  21. VOID
  22. DumpTypeGeneric(
  23. VDM_TRACEENTRY te
  24. )
  25. {
  26. PRINTF("%.4x: %.4X %.8X", te.Type, te.wData, te.lData);
  27. }
  28. VOID
  29. DumpTypeKernel(
  30. VDM_TRACEENTRY te
  31. )
  32. {
  33. switch(te.Type&0xff) {
  34. case VDMTR_KERNEL_HW_INT:
  35. PRINTF("Hw Int %.2x ", te.wData);
  36. break;
  37. case VDMTR_KERNEL_OP_PM:
  38. case VDMTR_KERNEL_OP_V86:
  39. PRINTF("OpEm ");
  40. switch(te.wData&0xff) {
  41. case 0xec:
  42. PRINTF("INB");
  43. break;
  44. case 0xee:
  45. PRINTF("OUTB");
  46. break;
  47. case 0xfa:
  48. PRINTF("CLI");
  49. break;
  50. case 0xfb:
  51. PRINTF("STI");
  52. break;
  53. default:
  54. PRINTF(" %.2x ", te.wData);
  55. }
  56. break;
  57. default:
  58. PRINTF("Unknown : %d", te.Type&0xff);
  59. return;
  60. }
  61. }
  62. VOID
  63. DumpTypeDpmi(
  64. VDM_TRACEENTRY te
  65. )
  66. {
  67. //
  68. // Dpmi dispatch table entries
  69. //
  70. static char szDispatchEntries[MAX_DPMI_BOP_FUNC][40] = {
  71. "InitDosxRM",
  72. "InitDosx",
  73. "InitLDT",
  74. "GetFastBopAddress",
  75. "InitIDT",
  76. "InitExceptionHandlers",
  77. "InitApp",
  78. "TerminateApp",
  79. "InUse",
  80. "NoLongerInUse",
  81. "switch_to_protected_mode",
  82. "switch_to_real_mode",
  83. "SetAltRegs",
  84. "IntHandlerIret16",
  85. "IntHandlerIret32",
  86. "FaultHandlerIret16",
  87. "FaultHandlerIret32",
  88. "UnhandledExceptionHandler",
  89. "RMCallBackCall",
  90. "ReflectIntrToPM",
  91. "ReflectIntrToV86",
  92. "InitPmStackInfo",
  93. "VcdPmSvcCall32",
  94. "SetDescriptorEntry",
  95. "ResetLDTUserBase",
  96. "XlatInt21Call",
  97. "Int31"
  98. };
  99. switch(te.Type&0xff) {
  100. case DPMI_DISPATCH_INT:
  101. PRINTF("Dispatch Int %.2x ", te.wData);
  102. break;
  103. case DPMI_HW_INT:
  104. PRINTF("Hw Int %.2x ", te.wData);
  105. break;
  106. case DPMI_SW_INT:
  107. PRINTF("Sw Int %.2x ", te.wData);
  108. break;
  109. case DPMI_FAULT:
  110. PRINTF("Fault %.2x ec=%.8x", te.wData, te.lData);
  111. break;
  112. case DPMI_DISPATCH_FAULT:
  113. PRINTF("Dispatch Flt %.2x ", te.wData);
  114. break;
  115. case DPMI_FAULT_IRET:
  116. PRINTF("Fault Iret");
  117. break;
  118. case DPMI_INT_IRET16:
  119. PRINTF("Int Iret16");
  120. break;
  121. case DPMI_INT_IRET32:
  122. PRINTF("Int Iret32");
  123. break;
  124. case DPMI_OP_EMULATION:
  125. PRINTF("Op Emulation");
  126. break;
  127. case DPMI_DISPATCH_ENTRY:
  128. PRINTF("Dispatch(%d): ", te.wData);
  129. if (te.lData >= MAX_DPMI_BOP_FUNC) {
  130. PRINTF("Unknown (%d)", te.lData);
  131. } else {
  132. PRINTF("%s", szDispatchEntries[te.lData]);
  133. }
  134. break;
  135. case DPMI_DISPATCH_EXIT:
  136. PRINTF("Exit(%d): ", te.wData);
  137. if (te.lData >= MAX_DPMI_BOP_FUNC) {
  138. PRINTF("Unknown (%d)", te.lData);
  139. } else {
  140. PRINTF("%s", szDispatchEntries[te.lData]);
  141. }
  142. break;
  143. case DPMI_SWITCH_STACKS:
  144. PRINTF("switch stack -> %.4x:%.8x", te.wData, te.lData);
  145. break;
  146. case DPMI_GENERIC:
  147. PRINTF("Data: %.4x %.8x", te.wData, te.lData);
  148. break;
  149. case DPMI_IN_V86:
  150. PRINTF("in V86 mode");
  151. break;
  152. case DPMI_IN_PM:
  153. PRINTF("in protect mode");
  154. break;
  155. case DPMI_REFLECT_TO_PM:
  156. PRINTF("Reflect to PM");
  157. break;
  158. case DPMI_REFLECT_TO_V86:
  159. PRINTF("Reflect to V86");
  160. break;
  161. default:
  162. PRINTF("Unknown : %d", te.Type&0xff);
  163. return;
  164. }
  165. }
  166. VOID
  167. DumpTypeMonitor(
  168. VDM_TRACEENTRY te
  169. )
  170. {
  171. static char szMonitorEntries[][20] = {
  172. "Event IO",
  173. "Event String IO",
  174. "Event Mem Access",
  175. "Event Int Ack",
  176. "Event BOP",
  177. "Event Error",
  178. "Event Irq 13",
  179. "Cpu Simulate",
  180. "Cpu Unsimulate",
  181. };
  182. if ((te.Type&0xff) <= MONITOR_CPU_UNSIMULATE) {
  183. PRINTF("%s", szMonitorEntries[(te.Type&0xff)-1]);
  184. PRINTF(": %.4X %.8X", te.wData, te.lData);
  185. } else {
  186. DumpTypeGeneric(te);
  187. }
  188. }
  189. VOID
  190. DumpTimeInfo(
  191. VDM_TRACEENTRY te
  192. )
  193. {
  194. ULONG USecs = 0;
  195. switch(TimerMode) {
  196. case VDMTI_TIMER_TICK:
  197. PRINTF("%d.%.3d", TimeIndex/1000, TimeIndex%1000);
  198. PRINTF(" %.8X ", te.Time);
  199. break;
  200. case VDMTI_TIMER_PENTIUM:
  201. if (CpuSpeed) {
  202. USecs = TimeIndex / CpuSpeed;
  203. }
  204. PRINTF("%5d.%.3d", USecs/1000, USecs%1000);
  205. PRINTF(" %.8X ", te.Time);
  206. break;
  207. }
  208. }
  209. VOID
  210. DumpTraceEntry(
  211. int index,
  212. VDM_TRACEENTRY te,
  213. ULONG Verbosity
  214. )
  215. {
  216. PRINTF("%4x ",index);
  217. DumpTimeInfo(te);
  218. switch(te.Type & 0xff00) {
  219. case (VDMTR_TYPE_KERNEL):
  220. PRINTF("Krnl ");
  221. DumpTypeKernel(te);
  222. break;
  223. case (VDMTR_TYPE_DPMI):
  224. PRINTF("Dpmi ");
  225. DumpTypeDpmi(te);
  226. break;
  227. case (VDMTR_TYPE_DPMI_SF):
  228. PRINTF("Dpmi Set Fault Handler %.02X -> %.4X:%.8X", te.Type & 0xff, te.wData, te.lData);
  229. break;
  230. case (VDMTR_TYPE_DPMI_SI):
  231. PRINTF("Dpmi Set Int Handler %.02X -> %.4X:%.8X", te.Type & 0xff, te.wData, te.lData);
  232. break;
  233. case (VDMTR_TYPE_DEM):
  234. PRINTF("Dem ");
  235. switch(te.Type & 0xff) {
  236. case 1:
  237. PRINTF("Dispatch: %.4X %.8X", te.wData, te.lData);
  238. break;
  239. case 2:
  240. PRINTF("Exit: %.4X %.8X", te.wData, te.lData);
  241. break;
  242. default:
  243. DumpTypeGeneric(te);
  244. }
  245. break;
  246. case (VDMTR_TYPE_WOW):
  247. PRINTF("Wow ");
  248. DumpTypeGeneric(te);
  249. break;
  250. case (VDMTR_TYPE_VSBD):
  251. PRINTF("Vsbd ");
  252. DumpTypeGeneric(te);
  253. break;
  254. case (VDMTR_TYPE_DBG):
  255. PRINTF("Dbg ");
  256. DumpTypeGeneric(te);
  257. break;
  258. case (VDMTR_TYPE_MONITOR):
  259. PRINTF("Mon ");
  260. DumpTypeMonitor(te);
  261. break;
  262. default:
  263. PRINTF(" ");
  264. DumpTypeGeneric(te);
  265. }
  266. if (Verbosity) {
  267. PRINTF("\n");
  268. PRINTF("eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n",
  269. te.eax, te.ebx, te.ecx, te.edx, te.esi, te.edi );
  270. PRINTF("eip=%08lx esp=%08lx ebp=%08lx ",
  271. te.eip, te.esp, te.ebp );
  272. if ( te.eflags & FLAG_OVERFLOW ) {
  273. PRINTF("ov ");
  274. } else {
  275. PRINTF("nv ");
  276. }
  277. if ( te.eflags & FLAG_DIRECTION ) {
  278. PRINTF("dn ");
  279. } else {
  280. PRINTF("up ");
  281. }
  282. if ( te.eflags & FLAG_INTERRUPT ) {
  283. PRINTF("ei ");
  284. } else {
  285. PRINTF("di ");
  286. }
  287. if ( te.eflags & FLAG_SIGN ) {
  288. PRINTF("ng ");
  289. } else {
  290. PRINTF("pl ");
  291. }
  292. if ( te.eflags & FLAG_ZERO ) {
  293. PRINTF("zr ");
  294. } else {
  295. PRINTF("nz ");
  296. }
  297. if ( te.eflags & FLAG_AUXILLIARY ) {
  298. PRINTF("ac ");
  299. } else {
  300. PRINTF("na ");
  301. }
  302. if ( te.eflags & FLAG_PARITY ) {
  303. PRINTF("po ");
  304. } else {
  305. PRINTF("pe ");
  306. }
  307. if ( te.eflags & FLAG_CARRY ) {
  308. PRINTF("cy ");
  309. } else {
  310. PRINTF("nc ");
  311. }
  312. PRINTF("\n");
  313. PRINTF("cs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x efl=%08lx\n",
  314. te.cs, te.ss, te.ds, te.es, te.fs, te.gs, te.eflags );
  315. }
  316. TimeIndex += te.Time;
  317. PRINTF("\n");
  318. }
  319. VOID
  320. DumpTrace(
  321. IN ULONG Verbosity
  322. )
  323. /*++
  324. Routine Description:
  325. This routine dumps the DPMI trace history buffer.
  326. Arguments:
  327. Return Value
  328. None.
  329. --*/
  330. {
  331. PVOID pMem;
  332. ULONG TraceBase, TraceEnd, TraceCurrent;
  333. ULONG Lines;
  334. VDM_TRACEINFO TraceInfo;
  335. VDM_TRACEENTRY TraceEntry;
  336. ULONG Count = 0;
  337. ULONG EntryID;
  338. ULONG NumEntries;
  339. if (!ReadMemExpression("ntvdm!pVdmTraceInfo", &pMem, 4)) {
  340. return;
  341. }
  342. if (!READMEM(pMem, &TraceInfo, sizeof(VDM_TRACEINFO))) {
  343. PRINTF("Error reading memory for TraceInfo\n");
  344. return;
  345. }
  346. if (!TraceInfo.pTraceTable) {
  347. PRINTF("NTVDM trace history not available\n");
  348. return;
  349. }
  350. if (!CpuSpeed && !bTriedToGetCpuSpeed) {
  351. HKEY hKey;
  352. DWORD retCode;
  353. DWORD dwType, cbData = sizeof(ULONG);
  354. ULONG dwData;
  355. retCode = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  356. CPUSPEED_PATH,
  357. 0,
  358. KEY_EXECUTE, // Requesting read access.
  359. &hKey);
  360. if (!retCode) {
  361. retCode = RegQueryValueEx(hKey,
  362. CPUSPEED_VALUE,
  363. NULL,
  364. &dwType,
  365. (LPSTR)&dwData,
  366. &cbData);
  367. RegCloseKey(hKey);
  368. if (!retCode) {
  369. CpuSpeed = dwData;
  370. }
  371. }
  372. bTriedToGetCpuSpeed = TRUE;
  373. if (!CpuSpeed) {
  374. PRINTF("Error retrieving CPU speed\n");
  375. }
  376. }
  377. TimeIndex = 0;
  378. NumEntries = TraceInfo.NumPages*4096/sizeof(VDM_TRACEENTRY);
  379. TraceBase = (ULONG) TraceInfo.pTraceTable;
  380. TraceEnd = (ULONG) &TraceInfo.pTraceTable[NumEntries];
  381. TraceCurrent = (ULONG) &TraceInfo.pTraceTable[TraceInfo.CurrentEntry];
  382. if ((TraceBase & 0xfff) || (TraceEnd & 0xfff) ||
  383. (TraceCurrent & 0x3f) ||
  384. (TraceBase > TraceEnd) ||
  385. (TraceCurrent > TraceEnd) || (TraceCurrent < TraceBase)) {
  386. PRINTF("TraceBuffer=%.8X, end=%.8X, current=%.8X\n",
  387. TraceBase, TraceEnd, TraceCurrent);
  388. PRINTF("Trace buffer info appears corrupt!\n");
  389. return;
  390. }
  391. if (Verbosity) {
  392. Lines = 8;
  393. } else {
  394. Lines = 32;
  395. }
  396. EntryID = 1;
  397. if (GetNextToken()) {
  398. if (*lpArgumentString == '#') {
  399. lpArgumentString++;
  400. EntryID = EvaluateToken();
  401. if (EntryID > NumEntries) {
  402. PRINTF("Requested trace entry out of range - %X\n", EntryID);
  403. return;
  404. }
  405. }
  406. if (GetNextToken()) {
  407. Lines = (int)EXPRESSION(lpArgumentString);
  408. if (Lines > NumEntries) {
  409. PRINTF("Requested count too large - %d\n", Lines);
  410. return;
  411. }
  412. }
  413. }
  414. TraceCurrent = (ULONG) &TraceInfo.pTraceTable[(TraceInfo.CurrentEntry-(EntryID-1))%NumEntries];
  415. TimerMode = (UCHAR) TraceInfo.Flags & VDMTI_TIMER_MODE;
  416. switch(TimerMode) {
  417. case VDMTI_TIMER_TICK:
  418. PRINTF("deltaT is in MSec, Time is in Seconds\n");
  419. PRINTF("\n# Time DeltaT Event\n");
  420. break;
  421. case VDMTI_TIMER_PENTIUM:
  422. PRINTF("deltaT is at %d MHz, Time is in MSec\n", CpuSpeed);
  423. PRINTF("\nlog# Time DeltaT Event\n");
  424. break;
  425. default:
  426. PRINTF("\n# Event\n");
  427. }
  428. while (Lines--) {
  429. TraceCurrent -= sizeof(VDM_TRACEENTRY);
  430. if (TraceCurrent < TraceBase) {
  431. TraceCurrent = TraceEnd - sizeof(VDM_TRACEENTRY);
  432. }
  433. if (!READMEM((PVOID)TraceCurrent, &TraceEntry, sizeof(VDM_TRACEENTRY))) {
  434. PRINTF("Error reading memory at %.08X\n", pMem);
  435. return;
  436. }
  437. if (!TraceEntry.Type) {
  438. if (!Count) {
  439. if (EntryID == 1) {
  440. PRINTF("<Log is empty>\n");
  441. } else {
  442. PRINTF("<End of log>\n");
  443. }
  444. } else {
  445. PRINTF("<End of log>\n");
  446. }
  447. break;
  448. }
  449. //PRINTF("%.8x ", TraceCurrent);
  450. DumpTraceEntry(EntryID++, TraceEntry, Verbosity);
  451. ++Count;
  452. if (EntryID >= NumEntries) {
  453. PRINTF("<End of log>\n");
  454. break;
  455. }
  456. }
  457. }
  458. VOID
  459. lgr(
  460. CMD_ARGLIST
  461. )
  462. {
  463. CMD_INIT();
  464. DumpTrace(1);
  465. }
  466. VOID
  467. lg(
  468. CMD_ARGLIST
  469. )
  470. {
  471. CMD_INIT();
  472. DumpTrace(0);
  473. }
  474. VOID
  475. lgt(
  476. CMD_ARGLIST
  477. )
  478. {
  479. PVOID pMem;
  480. VDM_TRACEINFO TraceInfo;
  481. UCHAR DbgTimerMode;
  482. BOOL DbgTimerInitialized;
  483. ULONG NewTimerMode;
  484. CMD_INIT();
  485. if (!ReadMemExpression("ntvdmd!DbgTimerMode", &DbgTimerMode, sizeof(UCHAR))) {
  486. return;
  487. }
  488. if (!ReadMemExpression("ntvdmd!DbgTimerInitialized", &DbgTimerInitialized, sizeof(BOOL))) {
  489. return;
  490. }
  491. if (GetNextToken()) {
  492. NewTimerMode = EvaluateToken();
  493. switch(NewTimerMode) {
  494. case 0:
  495. PRINTF("Event log timer is now OFF\n");
  496. break;
  497. case VDMTI_TIMER_TICK:
  498. PRINTF("Event log timer resolution set to ~10msec (GetTickCount)\n");
  499. break;
  500. case VDMTI_TIMER_PERFCTR:
  501. PRINTF("Event log timer resolution set to 100nsec (QueryPerformanceCounter)\n");
  502. break;
  503. case VDMTI_TIMER_PENTIUM:
  504. PRINTF("Event log timer resolution set to pentium time stamp counter\n");
  505. break;
  506. default:
  507. PRINTF("Invalid selection - enter 0-3\n");
  508. return;
  509. }
  510. pMem = (PVOID)(*GetExpression)("ntvdmd!DbgTimerMode");
  511. if (!pMem) {
  512. PRINTF("Could not find symbol ntvdmd!DbgTimerMode\n");
  513. return;
  514. }
  515. if (!WRITEMEM((PVOID)pMem, &NewTimerMode, sizeof(UCHAR))) {
  516. PRINTF("Error writing memory\n");
  517. return;
  518. }
  519. pMem = (PVOID)(*GetExpression)("ntvdmd!DbgTimerInitialized");
  520. if (!pMem) {
  521. PRINTF("Could not find symbol ntvdmd!DbgTimerInitialized\n");
  522. return;
  523. }
  524. DbgTimerInitialized = FALSE;
  525. if (!WRITEMEM((PVOID)pMem, &DbgTimerInitialized, sizeof(UCHAR))) {
  526. PRINTF("Error writing memory\n");
  527. return;
  528. }
  529. } else {
  530. if (!ReadMemExpression("ntvdm!pVdmTraceInfo", &pMem, sizeof(LPVOID))) {
  531. return;
  532. }
  533. if (!READMEM(pMem, &TraceInfo, sizeof(VDM_TRACEINFO))) {
  534. PRINTF("Error reading memory for TraceInfo\n");
  535. return;
  536. }
  537. PRINTF("Timer has%sbeen initialized\n", DbgTimerInitialized ? " " : " not ");
  538. PRINTF("Requested timer resolution == %d\n", DbgTimerMode);
  539. PRINTF("Current timer resolution == %d\n", TraceInfo.Flags & VDMTI_TIMER_MODE);
  540. }
  541. }