481 lines
11 KiB
C
481 lines
11 KiB
C
|
#include <windows.h>
|
||
|
#include <wtypes.h>
|
||
|
#include <wdbgexts.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <ntverp.h>
|
||
|
|
||
|
#include "tracelog.h"
|
||
|
#include "event.h"
|
||
|
|
||
|
void PrintTraceLogEntry(FILE *outfile, PTRACEENTRY TraceEntry);
|
||
|
|
||
|
void PrintTraceLogEntry(FILE *outfile, PTRACEENTRY TraceEntry);
|
||
|
|
||
|
EXT_API_VERSION ApiVersion = { 4, 0, EXT_API_VERSION_NUMBER, 0 };
|
||
|
WINDBG_EXTENSION_APIS ExtensionApis;
|
||
|
USHORT SavedMajorVersion;
|
||
|
USHORT SavedMinorVersion;
|
||
|
|
||
|
// ======================================================================
|
||
|
|
||
|
#define MAXREAD 3500
|
||
|
|
||
|
BOOL ReadMemoryEx(ULONG_PTR From, ULONG_PTR To, ULONG Size, PULONG OutBytesRead)
|
||
|
{
|
||
|
ULONG BytesRead;
|
||
|
ULONG TotalBytesRead = 0;
|
||
|
BOOL success;
|
||
|
|
||
|
// dprintf("ReadMemoryEx: reading %08x bytes from %08x to %08x\n", Size, From, To);
|
||
|
|
||
|
while (Size)
|
||
|
{
|
||
|
if (CheckControlC())
|
||
|
return 0;
|
||
|
if (Size > MAXREAD)
|
||
|
{
|
||
|
// dprintf("(reading %08x bytes from %08x to %08x)\n", MAXREAD, From, To);
|
||
|
success = ReadMemory((ULONG_PTR)From, (PVOID)To, MAXREAD, &BytesRead);
|
||
|
if (!success)
|
||
|
{
|
||
|
dprintf("Problem reading memory at %x for %x bytes\n", From, MAXREAD);
|
||
|
break;
|
||
|
}
|
||
|
TotalBytesRead += BytesRead;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// dprintf("(reading %08x bytes from %08x to %08x)\n", Size, From, To);
|
||
|
success = ReadMemory((ULONG_PTR)From, (PVOID)To, Size, &BytesRead);
|
||
|
if (!success)
|
||
|
{
|
||
|
dprintf("Problem reading memory at %x for %x bytes\n", From, Size);
|
||
|
break;
|
||
|
}
|
||
|
TotalBytesRead += BytesRead;
|
||
|
}
|
||
|
|
||
|
if (Size > MAXREAD)
|
||
|
{
|
||
|
Size -= MAXREAD;
|
||
|
From += MAXREAD;
|
||
|
To += MAXREAD;
|
||
|
}
|
||
|
else
|
||
|
Size = 0;
|
||
|
}
|
||
|
|
||
|
*OutBytesRead = TotalBytesRead;
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
// ======================================================================
|
||
|
|
||
|
ULONG_PTR GetTraceLogAddress(VOID)
|
||
|
{
|
||
|
ULONG_PTR TargetTraceLog;
|
||
|
PUCHAR symbol = "ATMLANE!TraceLog";
|
||
|
|
||
|
TargetTraceLog = (ULONG_PTR)GetExpression(symbol);
|
||
|
|
||
|
if ( !TargetTraceLog )
|
||
|
{
|
||
|
dprintf("Unable to resolve symbol \"%s\". Try .reload cmd.\n", symbol);
|
||
|
return 0;
|
||
|
}
|
||
|
return TargetTraceLog;
|
||
|
}
|
||
|
|
||
|
// ======================================================================
|
||
|
|
||
|
DllInit(
|
||
|
HANDLE hModule,
|
||
|
DWORD dwReason,
|
||
|
DWORD dwReserved
|
||
|
)
|
||
|
{
|
||
|
switch (dwReason) {
|
||
|
case DLL_THREAD_ATTACH:
|
||
|
break;
|
||
|
|
||
|
case DLL_THREAD_DETACH:
|
||
|
break;
|
||
|
|
||
|
case DLL_PROCESS_DETACH:
|
||
|
break;
|
||
|
|
||
|
case DLL_PROCESS_ATTACH:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// ======================================================================
|
||
|
|
||
|
VOID
|
||
|
WinDbgExtensionDllInit(
|
||
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
||
|
USHORT MajorVersion,
|
||
|
USHORT MinorVersion
|
||
|
)
|
||
|
{
|
||
|
ExtensionApis = *lpExtensionApis;
|
||
|
|
||
|
SavedMajorVersion = MajorVersion;
|
||
|
SavedMinorVersion = MinorVersion;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// ======================================================================
|
||
|
|
||
|
DECLARE_API( version )
|
||
|
{
|
||
|
#if DBG
|
||
|
PCHAR DebuggerType = "Checked";
|
||
|
#else
|
||
|
PCHAR DebuggerType = "Free";
|
||
|
#endif
|
||
|
|
||
|
dprintf("%s Extension dll for Build %d debugging %s kernel for Build %d\n",
|
||
|
DebuggerType,
|
||
|
VER_PRODUCTBUILD,
|
||
|
SavedMajorVersion == 0x0c ? "Checked" : "Free",
|
||
|
SavedMinorVersion
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// ======================================================================
|
||
|
|
||
|
VOID
|
||
|
CheckVersion(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
#if DBG
|
||
|
if ((SavedMajorVersion != 0x0c) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
|
||
|
dprintf("\r\n*** Extension DLL(%d Checked) does not match target system(%d %s)\r\n\r\n",
|
||
|
VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
|
||
|
}
|
||
|
#else
|
||
|
if ((SavedMajorVersion != 0x0f) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
|
||
|
dprintf("\r\n*** Extension DLL(%d Free) does not match target system(%d %s)\r\n\r\n",
|
||
|
VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// ======================================================================
|
||
|
|
||
|
LPEXT_API_VERSION
|
||
|
ExtensionApiVersion(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
return &ApiVersion;
|
||
|
}
|
||
|
|
||
|
// ======================================================================
|
||
|
|
||
|
DECLARE_API(dumplog)
|
||
|
{
|
||
|
ULONG_PTR TargetTraceLogAddress;
|
||
|
TRACELOG TargetTraceLog;
|
||
|
TRACELOG LocalTraceLog;
|
||
|
PUCHAR LocalLogStorage;
|
||
|
PTRACEENTRY TraceEntry;
|
||
|
PUCHAR CurString, NullPos;
|
||
|
UCHAR SaveChar;
|
||
|
ULONG LogLength;
|
||
|
ULONG bytesread, firstsize;
|
||
|
char * indexstr, *filenamestr;
|
||
|
ULONG index;
|
||
|
FILE * outfile;
|
||
|
|
||
|
filenamestr = strtok((char *)args, " ");
|
||
|
|
||
|
if (filenamestr == NULL)
|
||
|
{
|
||
|
dprintf("usage: dumplog <filename>\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
TargetTraceLogAddress = GetTraceLogAddress();
|
||
|
if (!TargetTraceLogAddress)
|
||
|
return;
|
||
|
|
||
|
// read trace log struct out of target's memory
|
||
|
|
||
|
if (!ReadMemoryEx( (ULONG_PTR)TargetTraceLogAddress, (ULONG_PTR)&TargetTraceLog,
|
||
|
sizeof(TRACELOG), &bytesread))
|
||
|
return;
|
||
|
|
||
|
#if 1
|
||
|
// display trace log vars
|
||
|
dprintf("TraceLog\n");
|
||
|
dprintf("\tStorage = 0x%08x\n", TargetTraceLog.Storage);
|
||
|
dprintf("\tSize = 0x%08x\n", TargetTraceLog.StorageSizeBytes);
|
||
|
dprintf("\tFirst = 0x%08x\n", TargetTraceLog.First);
|
||
|
dprintf("\tLast = 0x%08x\n", TargetTraceLog.Last);
|
||
|
dprintf("\tCurrent = 0x%08x\n", TargetTraceLog.Current);
|
||
|
#endif
|
||
|
|
||
|
// see if logging enabled (i.e. log has storage allocated
|
||
|
|
||
|
if (TargetTraceLog.Storage == NULL)
|
||
|
{
|
||
|
dprintf("Trace Log is disabled\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// alloc local memory for log
|
||
|
|
||
|
LocalLogStorage = (PUCHAR) malloc(TargetTraceLog.StorageSizeBytes);
|
||
|
if (LocalLogStorage == NULL)
|
||
|
{
|
||
|
dprintf("can't alloc %d bytes for local storage\n",
|
||
|
TargetTraceLog.StorageSizeBytes);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// open the output file
|
||
|
|
||
|
outfile = fopen(filenamestr, "wt");
|
||
|
if (outfile == NULL)
|
||
|
{
|
||
|
dprintf("open of file '%s' failed, errno = %d\n", filenamestr, errno);
|
||
|
free(LocalLogStorage);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// read the log out of target's memory
|
||
|
|
||
|
dprintf("reading log from target system, please wait...\n");
|
||
|
|
||
|
if (!ReadMemoryEx((ULONG_PTR)TargetTraceLog.Storage, (ULONG_PTR)LocalLogStorage,
|
||
|
TargetTraceLog.StorageSizeBytes, &bytesread))
|
||
|
{
|
||
|
fclose(outfile);
|
||
|
free(LocalLogStorage);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// convert addresses to local trace log
|
||
|
|
||
|
LocalTraceLog.Storage = LocalLogStorage;
|
||
|
LocalTraceLog.First = (PTRACEENTRY) LocalTraceLog.Storage;
|
||
|
LocalTraceLog.Last = LocalTraceLog.First +
|
||
|
(TargetTraceLog.Last - TargetTraceLog.First);
|
||
|
LocalTraceLog.Current = LocalTraceLog.First +
|
||
|
(TargetTraceLog.Current - TargetTraceLog.First);
|
||
|
|
||
|
|
||
|
// loop thru the trace log printing out the values
|
||
|
|
||
|
TraceEntry = LocalTraceLog.Current - 1;
|
||
|
|
||
|
dprintf("writing formatted log to file...\n");
|
||
|
|
||
|
for (;;)
|
||
|
{
|
||
|
if (TraceEntry < LocalTraceLog.First)
|
||
|
TraceEntry = LocalTraceLog.Last;
|
||
|
if (TraceEntry->EventId == 0 || TraceEntry == LocalTraceLog.Current)
|
||
|
{
|
||
|
dprintf("done.\n");
|
||
|
break;
|
||
|
}
|
||
|
PrintTraceLogEntry(outfile, TraceEntry);
|
||
|
TraceEntry--;
|
||
|
if (CheckControlC())
|
||
|
{
|
||
|
dprintf("Aborted before end of log.\n");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// cleanup
|
||
|
|
||
|
fclose(outfile);
|
||
|
free(LocalLogStorage);
|
||
|
}
|
||
|
|
||
|
// ======================================================================
|
||
|
|
||
|
DECLARE_API( help )
|
||
|
{
|
||
|
dprintf("ATMLANE driver kd extensions\n\n");
|
||
|
dprintf("\tdumplog <filename> - dumps & formats tracelog buffer to file\n");
|
||
|
}
|
||
|
|
||
|
// ======================================================================
|
||
|
|
||
|
void PrintTraceLogEntry(FILE *outfile, PTRACEENTRY TraceEntry)
|
||
|
{
|
||
|
ULONG params, i;
|
||
|
|
||
|
switch (TraceEntry->EventId)
|
||
|
{
|
||
|
|
||
|
case TL_MSENDPKTIN:
|
||
|
fprintf(outfile, "[% 10u] MSENDPKTIN: PktCnt %d\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_MSENDPKTBEGIN:
|
||
|
fprintf(outfile, "[% 10u] MSENDPKTBEGIN: Index %d Pkt %x\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0],
|
||
|
TraceEntry->Params[1]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_MSENDPKTEND:
|
||
|
fprintf(outfile, "[% 10u] MSENDPKTEND: Index %d Pkt %x Status %x\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0],
|
||
|
TraceEntry->Params[1],
|
||
|
TraceEntry->Params[2]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_MSENDPKTOUT:
|
||
|
fprintf(outfile, "[% 10u] MSENDPKTOUT\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_MSENDCOMPL:
|
||
|
fprintf(outfile, "[% 10u] MSENDCOMPL: Pkt %x Status %x\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0],
|
||
|
TraceEntry->Params[1]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_WRAPSEND:
|
||
|
fprintf(outfile, "[% 10u] WRAPSEND: From %x To %x Bcnt %d Len %d\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0],
|
||
|
TraceEntry->Params[1],
|
||
|
TraceEntry->Params[2],
|
||
|
TraceEntry->Params[3]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_UNWRAPSEND:
|
||
|
fprintf(outfile, "[% 10u] UNWRAPSEND: From %x To %x Bcnt %d Len %d\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0],
|
||
|
TraceEntry->Params[1],
|
||
|
TraceEntry->Params[2],
|
||
|
TraceEntry->Params[3]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_WRAPRECV:
|
||
|
fprintf(outfile, "[% 10u] WRAPRECV: From %x To %x Bcnt %d Len %d\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0],
|
||
|
TraceEntry->Params[1],
|
||
|
TraceEntry->Params[2],
|
||
|
TraceEntry->Params[3]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_UNWRAPRECV:
|
||
|
fprintf(outfile, "[% 10u] UNWRAPRECV: From %x To %x Bcnt %d Len %d\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0],
|
||
|
TraceEntry->Params[1],
|
||
|
TraceEntry->Params[2],
|
||
|
TraceEntry->Params[3]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_COSENDPACKET:
|
||
|
fprintf(outfile, "[% 10u] COSENDPKT: Pkt %x\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_COSENDCMPLTIN:
|
||
|
fprintf(outfile, "[% 10u] COSENDCMPLTIN: Pkt %x Status %x\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0],
|
||
|
TraceEntry->Params[1]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_COSENDCMPLTOUT:
|
||
|
fprintf(outfile, "[% 10u] COSENDCMPLTOUT: Pkt %x\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_CORECVPACKET:
|
||
|
fprintf(outfile, "[% 10u] CORECVPKT: Pkt %x Vc %x\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0],
|
||
|
TraceEntry->Params[1]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_CORETNPACKET:
|
||
|
fprintf(outfile, "[% 10u] CORETNPKT: Pkt %x\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_MINDPACKET:
|
||
|
fprintf(outfile, "[% 10u] MINDPKT: Pkt %x\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_MRETNPACKET:
|
||
|
fprintf(outfile, "[% 10u] MRETNPKT: Pkt %x\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case TL_NDISPACKET:
|
||
|
fprintf(outfile, "[% 10u] NDISPKT: %x Cnt %d Len %d Bufs %x %x %x %x %x\n",
|
||
|
TraceEntry->Time,
|
||
|
TraceEntry->Params[0],
|
||
|
TraceEntry->Params[1],
|
||
|
TraceEntry->Params[2],
|
||
|
TraceEntry->Params[3],
|
||
|
TraceEntry->Params[4],
|
||
|
TraceEntry->Params[5],
|
||
|
TraceEntry->Params[6],
|
||
|
TraceEntry->Params[7]
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
params = TL_GET_PARAM_COUNT(TraceEntry->EventId);
|
||
|
fprintf(outfile, "****: Unknown Event ID %d with %d Params: ",
|
||
|
TL_GET_EVENT(TraceEntry->EventId), params);
|
||
|
for (i = 0; i < params; i++)
|
||
|
fprintf(outfile, "%x ", TraceEntry->Params[i]);
|
||
|
fprintf(outfile, "\n");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// ======================================================================
|