mirror of https://github.com/tongzx/nt5src
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.
633 lines
14 KiB
633 lines
14 KiB
/*++
|
|
|
|
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 )
|
|
|