windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/dbgext/strlog.cxx
2020-09-26 16:20:57 +08:00

634 lines
14 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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 )