/*++ Copyright (c) 1991 Microsoft Corporation Module Name: trace.c Abstract: This file contains code to dump the dpmi trace table Author: Neil Sandlin (neilsa) 1-Nov-1995 Revision History: --*/ #include #include #include HANDLE hCurrentProcess; // // Local constants // #define ReadDword(addr, value) ReadProcessMem( CurrentProcess, \ (LPVOID) addr, &value, \ sizeof(ULONG), NULL ) #define WriteDword(addr, value) WriteProcessMem( CurrentProcess, \ (LPVOID) addr, &value, \ sizeof(ULONG), NULL ) BOOL ReadMemExpression( LPSTR expr, LPVOID buffer, ULONG len ) { PVOID pMem; pMem = (PVOID)(*GetExpression)(expr); if (!pMem) { PRINTF("DPMI trace history not available\n"); return FALSE; } if (!ReadProcessMem(hCurrentProcess, pMem, buffer, len, NULL)) { PRINTF("Error reading memory\n"); return FALSE; } return TRUE; } VOID DumpTraceEntry( int index, DPMI_TRACE_ENTRY TraceEntry, ULONG Verbosity ) { PRINTF("%4x ",index); switch(TraceEntry.Type) { case DPMI_SET_PMODE_INT_HANDLER: PRINTF("SetPModeInt %.2x -> %.4x:%.8x", TraceEntry.v1, TraceEntry.v2, TraceEntry.v3); break; case DPMI_SET_FAULT_HANDLER: PRINTF("SetFault %.2x -> %.4x:%.8x", TraceEntry.v1, TraceEntry.v2, TraceEntry.v3); break; case DPMI_DISPATCH_INT: PRINTF("Dispatch Int %.2x ", TraceEntry.v1); break; case DPMI_HW_INT: PRINTF("Hw Int %.2x ", TraceEntry.v1); break; case DPMI_SW_INT: PRINTF("Sw Int %.2x ", TraceEntry.v1); break; case DPMI_FAULT: PRINTF("Fault %.2x ec=%.8x", TraceEntry.v1, TraceEntry.v2); break; case DPMI_DISPATCH_FAULT: PRINTF("Dispatch Flt %.2x ", TraceEntry.v1); break; case DPMI_FAULT_IRET: PRINTF("Fault Iret"); break; case DPMI_INT_IRET16: PRINTF("Int Iret16"); break; case DPMI_INT_IRET32: PRINTF("Int Iret32"); break; case DPMI_OP_EMULATION: PRINTF("Op Emulation"); break; default: PRINTF("Unknown Trace Entry : %d\n", TraceEntry.Type); return; } if (Verbosity) { PRINTF("\n"); PRINTF("eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n", TraceEntry.eax, TraceEntry.ebx, TraceEntry.ecx, TraceEntry.edx, TraceEntry.esi, TraceEntry.edi ); PRINTF("eip=%08lx esp=%08lx ebp=%08lx ", TraceEntry.eip, TraceEntry.esp, TraceEntry.ebp ); if ( TraceEntry.eflags & FLAG_OVERFLOW ) { PRINTF("ov "); } else { PRINTF("nv "); } if ( TraceEntry.eflags & FLAG_DIRECTION ) { PRINTF("dn "); } else { PRINTF("up "); } if ( TraceEntry.eflags & FLAG_INTERRUPT ) { PRINTF("ei "); } else { PRINTF("di "); } if ( TraceEntry.eflags & FLAG_SIGN ) { PRINTF("ng "); } else { PRINTF("pl "); } if ( TraceEntry.eflags & FLAG_ZERO ) { PRINTF("zr "); } else { PRINTF("nz "); } if ( TraceEntry.eflags & FLAG_AUXILLIARY ) { PRINTF("ac "); } else { PRINTF("na "); } if ( TraceEntry.eflags & FLAG_PARITY ) { PRINTF("po "); } else { PRINTF("pe "); } if ( TraceEntry.eflags & FLAG_CARRY ) { PRINTF("cy "); } else { PRINTF("nc "); } PRINTF("\n"); PRINTF("cs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x efl=%08lx\n", TraceEntry.cs, TraceEntry.ss, TraceEntry.ds, TraceEntry.es, TraceEntry.fs, TraceEntry.gs, TraceEntry.eflags ); } PRINTF("\n"); } VOID DumpTrace( IN HANDLE CurrentProcess, IN HANDLE CurrentThread, IN LPSTR ArgumentString, IN ULONG Verbosity ) /*++ Routine Description: This routine dumps the DPMI trace history buffer. Arguments: CurrentProcess -- Supplies a handle to the process to dump selectors for CurrentThread -- Supplies a handle to the thread to dump selectors for ArgumentString -- Supplies the arguments to the !sel command Return Value None. --*/ { PVOID pMem; BOOL bTrace; int TraceCount, TraceIndex, MaxEntries; int index; int Lines; int i; DPMI_TRACE_ENTRY TraceEntry; ULONG TraceTableBase; hCurrentProcess = CurrentProcess; TraceTableBase = (ULONG)(*GetExpression)("ntvdm!DpmiTraceTable"); if (!TraceTableBase) { PRINTF("DPMI trace history not available\n"); return; } if (!ReadMemExpression("ntvdm!bDpmiTraceOn", &bTrace, 4)) { return; } if (!bTrace) { PRINTF("Trace is not on\n"); return; } if (!ReadMemExpression("ntvdm!DpmiTraceCount", &TraceCount, 4)) { return; } if (!TraceCount) { PRINTF("Trace history buffer is empty\n"); return; } if (!ReadMemExpression("ntvdm!DpmiTraceIndex", &TraceIndex, 4)) { return; } if (!ReadMemExpression("ntvdm!DpmiMaxTraceEntries", &MaxEntries, 4)) { return; } PRINTF("TraceBuffer contains %d entries, current index=%d, max=%d\n", TraceCount, TraceIndex, MaxEntries); if ((TraceCount < 0) || (TraceCount > 2000) || (TraceIndex < 0) || (TraceIndex > 2000) || (MaxEntries < 0) || (MaxEntries > 2000)) { PRINTF("Trace buffer appears corrupt!\n"); return; } Lines = (int)(*GetExpression)(ArgumentString); if (!Lines) { if (Verbosity) { Lines = 12; } else { Lines = 50; } } if (Lines > TraceCount) { Lines = TraceCount; } index = TraceIndex - Lines; if (index<0) { index += MaxEntries; } for (i=0; i= MaxEntries) { index = 0; } } } VOID TraceControl( IN HANDLE CurrentProcess, IN HANDLE CurrentThread, IN LPSTR ArgumentString ) /*++ Routine Description: This routine dumps LDT selectors. The selectors are dumped from the user mode Ldt, rather than the system ldt. Arguments: CurrentProcess -- Supplies a handle to the process to dump selectors for CurrentThread -- Supplies a handle to the thread to dump selectors for ArgumentString -- Supplies the arguments to the !sel command Return Value None. --*/ { PVOID pMem; BOOL bTrace; int Count; hCurrentProcess = CurrentProcess; if (!ReadMemExpression("ntvdm!bDpmiTraceOn", &bTrace, 4)) { return; } pMem = (PVOID)(*GetExpression)("ntvdm!bDpmiTraceOn"); if (!pMem) { PRINTF("DPMI trace history not available\n"); return; } if (!ReadDword(pMem, bTrace)) { PRINTF("Error reading memory\n"); return; } if (!bTrace) { int Count = 0; bTrace = 1; WriteDword(pMem, bTrace); pMem = (PVOID)(*GetExpression)("ntvdm!bDpmiTraceCount"); WriteDword(pMem, Count); (*Print)("Trace is now on and reset\n"); } else { bTrace = 0; WriteDword(pMem, bTrace); (*Print)("Trace is now off\n"); } }