634 lines
14 KiB
C++
634 lines
14 KiB
C++
/*++
|
||
|
||
Copyright (c) 1995-1998 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
strlog.cxx
|
||
|
||
Abstract:
|
||
|
||
CStringTraceLog support
|
||
|
||
Author:
|
||
|
||
George V. Reilly (GeorgeRe) 22-Jun-1998
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "inetdbgp.h"
|
||
|
||
|
||
/************************************************************
|
||
* Dump String Trace Logs
|
||
************************************************************/
|
||
|
||
|
||
// Dummy implementations so that we can link
|
||
CStringTraceLog::CStringTraceLog(
|
||
UINT cchEntrySize /* = 80 */,
|
||
UINT cLogSize /* = 100 */)
|
||
{}
|
||
|
||
|
||
|
||
CStringTraceLog::~CStringTraceLog()
|
||
{}
|
||
|
||
|
||
|
||
VOID
|
||
DumpStringTraceLog(
|
||
IN PSTR lpArgumentString,
|
||
IN BOOLEAN fReverse
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dumps the specified print trace log either forwards (fReverse == FALSE)
|
||
or backwards (fReverse == TRUE).
|
||
|
||
Arguments:
|
||
|
||
lpArgumentString - An expression specifying the print trace log to dump.
|
||
|
||
fReverse - The dump direction.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG_PTR stlLogAddress = 0;
|
||
ULONG_PTR entryAddress;
|
||
LONG numEntries;
|
||
CStringTraceLog stlHeader;
|
||
TRACE_LOG tlogHeader;
|
||
CStringTraceLog::CLogEntry logEntry;
|
||
LONG i;
|
||
DWORD offset;
|
||
PCHAR format;
|
||
LONG index;
|
||
LONG direction;
|
||
PSTR cmdName;
|
||
UCHAR symbol[MAX_PATH];
|
||
INT nVerbose = 0;
|
||
|
||
direction = fReverse ? -1 : 1;
|
||
cmdName = fReverse ? "rst" : "st";
|
||
|
||
//
|
||
// Skip leading blanks.
|
||
//
|
||
|
||
while( *lpArgumentString == ' ' ||
|
||
*lpArgumentString == '\t' ) {
|
||
lpArgumentString++;
|
||
}
|
||
|
||
if( *lpArgumentString == '\0' ) {
|
||
PrintUsage( cmdName );
|
||
return;
|
||
}
|
||
|
||
if ( *lpArgumentString == '-' )
|
||
{
|
||
lpArgumentString++;
|
||
|
||
if ( *lpArgumentString == 'h' )
|
||
{
|
||
PrintUsage( cmdName );
|
||
return;
|
||
}
|
||
|
||
if ( *lpArgumentString == 'l' ) {
|
||
lpArgumentString++;
|
||
if ('0' <= *lpArgumentString && *lpArgumentString <= '9' ) {
|
||
nVerbose = *lpArgumentString++ - '0';
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
while( *lpArgumentString == ' ' ||
|
||
*lpArgumentString == '\t' ) {
|
||
lpArgumentString++;
|
||
}
|
||
|
||
stlLogAddress = (ULONG_PTR)GetExpression( lpArgumentString );
|
||
|
||
if( stlLogAddress == 0 ) {
|
||
|
||
dprintf(
|
||
"inetdbg.%s: cannot evaluate \"%s\"\n",
|
||
cmdName,
|
||
lpArgumentString
|
||
);
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
//
|
||
// Skip to end of expression, then skip any blanks.
|
||
//
|
||
|
||
while( *lpArgumentString != ' ' &&
|
||
*lpArgumentString != '\t' &&
|
||
*lpArgumentString != '\0' ) {
|
||
lpArgumentString++;
|
||
}
|
||
|
||
//
|
||
// Read the log header, perform some sanity checks.
|
||
//
|
||
|
||
if( !ReadMemory(
|
||
stlLogAddress,
|
||
&stlHeader,
|
||
sizeof(stlHeader),
|
||
NULL
|
||
) ) {
|
||
|
||
dprintf(
|
||
"inetdbg.%s: cannot read memory @ %p\n",
|
||
cmdName,
|
||
(PVOID)stlLogAddress
|
||
);
|
||
|
||
return;
|
||
}
|
||
|
||
if( !ReadMemory(
|
||
stlHeader.m_ptlog,
|
||
&tlogHeader,
|
||
sizeof(tlogHeader),
|
||
NULL
|
||
) ) {
|
||
|
||
dprintf(
|
||
"inetdbg.%s: cannot read tracelog memory @ %p\n",
|
||
cmdName,
|
||
(PVOID)stlHeader.m_ptlog
|
||
);
|
||
|
||
return;
|
||
}
|
||
|
||
dprintf(
|
||
"inetdbg.%s: log @ %p:\n"
|
||
" String Trace Log Signature = %08lx (%s)\n"
|
||
" Trace Log Signature = %08lx (%s)\n"
|
||
" LogSize = %lu\n"
|
||
" NextEntry = %lu\n"
|
||
" EntrySize = %lu\n"
|
||
" LogBuffer = %p\n",
|
||
cmdName,
|
||
(PVOID)stlLogAddress,
|
||
stlHeader.m_Signature,
|
||
stlHeader.m_Signature == CStringTraceLog::SIGNATURE
|
||
? "OK"
|
||
: stlHeader.m_Signature == CStringTraceLog::SIGNATURE_X
|
||
? "FREED"
|
||
: "INVALID",
|
||
tlogHeader.Signature,
|
||
tlogHeader.Signature == TRACE_LOG_SIGNATURE
|
||
? "OK"
|
||
: tlogHeader.Signature == TRACE_LOG_SIGNATURE_X
|
||
? "FREED"
|
||
: "INVALID",
|
||
tlogHeader.LogSize,
|
||
tlogHeader.NextEntry,
|
||
tlogHeader.EntrySize,
|
||
tlogHeader.LogBuffer
|
||
);
|
||
|
||
if( tlogHeader.LogBuffer
|
||
> ( (PUCHAR)stlHeader.m_ptlog + sizeof(tlogHeader) ) )
|
||
{
|
||
dprintf(
|
||
" Extra Data @ %p\n",
|
||
(PVOID)( stlLogAddress + sizeof(tlogHeader) )
|
||
);
|
||
}
|
||
|
||
if( stlHeader.m_Signature != CStringTraceLog::SIGNATURE &&
|
||
stlHeader.m_Signature != CStringTraceLog::SIGNATURE_X ) {
|
||
|
||
dprintf(
|
||
"inetdbg.%s: log @ %p has invalid signature: %08lx\n",
|
||
cmdName,
|
||
(PVOID)stlLogAddress,
|
||
stlHeader.m_Signature
|
||
);
|
||
|
||
return;
|
||
}
|
||
|
||
if( (UINT) tlogHeader.EntrySize
|
||
!= sizeof(CStringTraceLog::CLogEntry) - CStringTraceLog::MAX_CCH + stlHeader.m_cch ) {
|
||
|
||
dprintf(
|
||
"inetdbg.%s: log @ %p is not a print trace log\n",
|
||
cmdName,
|
||
(PVOID)stlLogAddress
|
||
);
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
if( tlogHeader.NextEntry == -1 ) {
|
||
|
||
dprintf(
|
||
"inetdbg.%s: empty log @ %p\n",
|
||
cmdName,
|
||
(PVOID)stlLogAddress
|
||
);
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
//
|
||
// Calculate the starting address and number of entries.
|
||
//
|
||
|
||
if( fReverse ) {
|
||
if( tlogHeader.NextEntry < tlogHeader.LogSize ) {
|
||
numEntries = tlogHeader.NextEntry + 1;
|
||
index = tlogHeader.NextEntry;
|
||
} else {
|
||
numEntries = tlogHeader.LogSize;
|
||
index = tlogHeader.NextEntry % tlogHeader.LogSize;
|
||
}
|
||
} else {
|
||
if( tlogHeader.NextEntry < tlogHeader.LogSize ) {
|
||
numEntries = tlogHeader.NextEntry + 1;
|
||
index = 0;
|
||
} else {
|
||
numEntries = tlogHeader.LogSize;
|
||
index = ( tlogHeader.NextEntry + 1 ) % tlogHeader.LogSize;
|
||
}
|
||
}
|
||
|
||
entryAddress = (ULONG_PTR)tlogHeader.LogBuffer + (ULONG_PTR)( index * tlogHeader.EntrySize );
|
||
|
||
if( entryAddress >=
|
||
( (ULONG_PTR)tlogHeader.LogBuffer + (ULONG_PTR)( numEntries * tlogHeader.EntrySize ) ) ) {
|
||
|
||
dprintf(
|
||
"inetdbg.%s: log @ %p has invalid data\n",
|
||
cmdName,
|
||
(PVOID)stlLogAddress
|
||
);
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
//
|
||
// Dump the log, which is stored in a circular buffer.
|
||
//
|
||
|
||
for( ;
|
||
numEntries > 0 ;
|
||
index += direction,
|
||
numEntries--,
|
||
entryAddress += ( direction * tlogHeader.EntrySize ) )
|
||
{
|
||
|
||
if( CheckControlC() ) {
|
||
break;
|
||
}
|
||
|
||
if( index >= tlogHeader.LogSize ) {
|
||
index = 0;
|
||
entryAddress = (ULONG_PTR)tlogHeader.LogBuffer;
|
||
} else if( index < 0 ) {
|
||
index = tlogHeader.LogSize - 1;
|
||
entryAddress = (ULONG_PTR)tlogHeader.LogBuffer
|
||
+ (ULONG_PTR)( index * tlogHeader.EntrySize );
|
||
}
|
||
|
||
if( !ReadMemory(
|
||
entryAddress,
|
||
&logEntry,
|
||
tlogHeader.EntrySize,
|
||
NULL
|
||
) ) {
|
||
|
||
dprintf(
|
||
"inetdbg.%s: cannot read memory @ %p\n",
|
||
cmdName,
|
||
(ULONG_PTR)entryAddress
|
||
);
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
if (nVerbose == 0)
|
||
{
|
||
dprintf(
|
||
"%04x: %s\n",
|
||
logEntry.m_nThread,
|
||
logEntry.m_ach
|
||
);
|
||
} else if (nVerbose == 1) {
|
||
dprintf(
|
||
"\n%6d: Thread = %04x, TimeStamp = %04x %04x %04x %04x\n"
|
||
"%s\n",
|
||
index,
|
||
logEntry.m_nThread,
|
||
HIWORD(logEntry.m_liTimeStamp.HighPart),
|
||
LOWORD(logEntry.m_liTimeStamp.HighPart),
|
||
HIWORD(logEntry.m_liTimeStamp.LowPart),
|
||
LOWORD(logEntry.m_liTimeStamp.LowPart),
|
||
logEntry.m_ach
|
||
);
|
||
}
|
||
}
|
||
|
||
} // DumpStringTraceLog
|
||
|
||
|
||
DECLARE_API( st )
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called as an NTSD extension to format and dump
|
||
a print trace log.
|
||
|
||
Arguments:
|
||
|
||
hCurrentProcess - Supplies a handle to the current process (at the
|
||
time the extension was called).
|
||
|
||
hCurrentThread - Supplies a handle to the current thread (at the
|
||
time the extension was called).
|
||
|
||
CurrentPc - Supplies the current pc at the time the extension is
|
||
called.
|
||
|
||
lpExtensionApis - Supplies the address of the functions callable
|
||
by this extension.
|
||
|
||
lpArgumentString - Supplies the asciiz string that describes the
|
||
ansi string to be dumped.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
INIT_API();
|
||
DumpStringTraceLog( lpArgumentString, FALSE );
|
||
|
||
} // DECLARE_API( st )
|
||
|
||
|
||
DECLARE_API( rst )
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called as an NTSD extension to format and dump
|
||
a print trace log backwards.
|
||
|
||
Arguments:
|
||
|
||
hCurrentProcess - Supplies a handle to the current process (at the
|
||
time the extension was called).
|
||
|
||
hCurrentThread - Supplies a handle to the current thread (at the
|
||
time the extension was called).
|
||
|
||
CurrentPc - Supplies the current pc at the time the extension is
|
||
called.
|
||
|
||
lpExtensionApis - Supplies the address of the functions callable
|
||
by this extension.
|
||
|
||
lpArgumentString - Supplies the asciiz string that describes the
|
||
ansi string to be dumped.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
INIT_API();
|
||
DumpStringTraceLog( lpArgumentString, TRUE );
|
||
|
||
} // DECLARE_API( rst )
|
||
|
||
|
||
DECLARE_API( resetst )
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called as an NTSD extension to reset a print
|
||
trace log back to its initial state.
|
||
|
||
Arguments:
|
||
|
||
hCurrentProcess - Supplies a handle to the current process (at the
|
||
time the extension was called).
|
||
|
||
hCurrentThread - Supplies a handle to the current thread (at the
|
||
time the extension was called).
|
||
|
||
CurrentPc - Supplies the current pc at the time the extension is
|
||
called.
|
||
|
||
lpExtensionApis - Supplies the address of the functions callable
|
||
by this extension.
|
||
|
||
lpArgumentString - Supplies the asciiz string that describes the
|
||
ansi string to be dumped.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG_PTR stlLogAddress = 0;
|
||
CStringTraceLog stlHeader;
|
||
TRACE_LOG tlogHeader;
|
||
CStringTraceLog::CLogEntry logEntry;
|
||
|
||
INIT_API();
|
||
|
||
//
|
||
// Skip leading blanks.
|
||
//
|
||
|
||
while( *lpArgumentString == ' ' ||
|
||
*lpArgumentString == '\t' ) {
|
||
lpArgumentString++;
|
||
}
|
||
|
||
if( *lpArgumentString == '\0' ) {
|
||
PrintUsage( "resetst" );
|
||
return;
|
||
}
|
||
|
||
stlLogAddress = GetExpression( lpArgumentString );
|
||
|
||
if( stlLogAddress == 0 ) {
|
||
|
||
dprintf(
|
||
"inetdbg.resetst: cannot evaluate \"%s\"\n",
|
||
lpArgumentString
|
||
);
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
//
|
||
// Read the log header, perform some sanity checks.
|
||
//
|
||
|
||
if( !ReadMemory(
|
||
stlLogAddress,
|
||
&stlHeader,
|
||
sizeof(stlHeader),
|
||
NULL
|
||
) ) {
|
||
|
||
dprintf(
|
||
"inetdbg.resetst: cannot read memory @ %p\n",
|
||
stlLogAddress
|
||
);
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
if( !ReadMemory(
|
||
stlHeader.m_ptlog,
|
||
&tlogHeader,
|
||
sizeof(tlogHeader),
|
||
NULL
|
||
) ) {
|
||
|
||
dprintf(
|
||
"inetdbg.resetst: cannot read tracelog memory @ %p\n",
|
||
(PVOID)stlHeader.m_ptlog
|
||
);
|
||
|
||
return;
|
||
}
|
||
|
||
dprintf(
|
||
"inetdbg.resetst: log @ %p:\n"
|
||
" String Trace Log Signature = %08lx (%s)\n"
|
||
" Trace Log Signature = %08lx (%s)\n"
|
||
" LogSize = %lu\n"
|
||
" NextEntry = %lu\n"
|
||
" EntrySize = %lu\n"
|
||
" LogBuffer = %08lp\n",
|
||
(PVOID) stlLogAddress,
|
||
stlHeader.m_Signature,
|
||
stlHeader.m_Signature == CStringTraceLog::SIGNATURE
|
||
? "OK"
|
||
: stlHeader.m_Signature == CStringTraceLog::SIGNATURE_X
|
||
? "FREED"
|
||
: "INVALID",
|
||
tlogHeader.Signature,
|
||
tlogHeader.Signature == TRACE_LOG_SIGNATURE
|
||
? "OK"
|
||
: tlogHeader.Signature == TRACE_LOG_SIGNATURE_X
|
||
? "FREED"
|
||
: "INVALID",
|
||
tlogHeader.LogSize,
|
||
tlogHeader.NextEntry,
|
||
tlogHeader.EntrySize,
|
||
tlogHeader.LogBuffer
|
||
);
|
||
|
||
if( tlogHeader.LogBuffer
|
||
> ( (PUCHAR)stlHeader.m_ptlog + sizeof(tlogHeader) ) )
|
||
{
|
||
dprintf(
|
||
" Extra Data @ %p\n",
|
||
(PVOID)( stlLogAddress + sizeof(tlogHeader) )
|
||
);
|
||
}
|
||
|
||
if( stlHeader.m_Signature != CStringTraceLog::SIGNATURE &&
|
||
stlHeader.m_Signature != CStringTraceLog::SIGNATURE_X ) {
|
||
|
||
dprintf(
|
||
"inetdbg.resetst: log @ %p has invalid signature %08lx:\n",
|
||
(PVOID) stlLogAddress,
|
||
stlHeader.m_Signature
|
||
);
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
if( (UINT) tlogHeader.EntrySize
|
||
!= sizeof(CStringTraceLog::CLogEntry) - CStringTraceLog::MAX_CCH + stlHeader.m_cch ) {
|
||
|
||
dprintf(
|
||
"inetdbg.resetst: log @ %p is not a print trace log\n",
|
||
(PVOID) stlLogAddress
|
||
);
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
//
|
||
// Reset it.
|
||
//
|
||
|
||
tlogHeader.NextEntry = -1;
|
||
|
||
if( !WriteMemory(
|
||
stlHeader.m_ptlog,
|
||
&tlogHeader,
|
||
sizeof(tlogHeader),
|
||
NULL
|
||
) ) {
|
||
|
||
dprintf(
|
||
"inetdbg.resetst: cannot write memory @ %p\n",
|
||
(PVOID) stlHeader.m_ptlog
|
||
);
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
dprintf(
|
||
"inetdbg.resetst: log @ %p reset\n",
|
||
(PVOID) stlHeader.m_ptlog
|
||
);
|
||
|
||
} // DECLARE_API( resetst )
|
||
|