windows-nt/Source/XPSP1/NT/base/fs/utils/ulib/memtrace/memtrace.c
2020-09-26 16:20:57 +08:00

226 lines
4.5 KiB
C

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
memtrace.c
Abstract:
This function contains an extension to NTSD that allows tracing of
memory usage when ULIB objects are compiled with the MEMLEAK flag
defined.
Author:
Barry Gilhuly (W-Barry) 25-July-91
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <ntsdexts.h>
#include <string.h>
#include "memtrace.h"
VOID
DumpToFile( char *OutString, ... )
{
DWORD bytes;
bytes = strlen( OutString );
WriteFile( hFile, OutString, bytes, &bytes, NULL );
return;
}
VOID
MemTrace(
HANDLE hCurrentProcess,
HANDLE hCurrentThread,
DWORD dwCurrentPc,
PNTSD_EXTENSION_APIS lpExtensionApis,
LPSTR lpArgumentString
)
/*++
Routine Description:
This function is called as an NTSD extension to format and dump
the current contents of the Mem list.
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
critical section to be dumped (e.g. ntdll!FastPebLock,
csrsrv!CsrProcessStructureLock...).
Return Value:
None.
--*/
{
DWORD AddrMem;
BOOL b;
DWORD i;
PMEM_BLOCK MemListNext;
MEM_BLOCK MemObject;
CHAR Symbol[64];
CHAR Buffer[ 128 ];
DWORD Displacement;
PNTSD_OUTPUT_ROUTINE lpOutputRoutine;
PNTSD_OUTPUT_ROUTINE lpAlternateOutputRoutine;
PNTSD_GET_EXPRESSION lpGetExpressionRoutine;
PNTSD_GET_SYMBOL lpGetSymbolRoutine;
UNREFERENCED_PARAMETER(hCurrentThread);
UNREFERENCED_PARAMETER(dwCurrentPc);
UNREFERENCED_PARAMETER(lpArgumentString);
lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
//
// Attempt to use the input string as a file name...
//
if( ( hFile = CreateFile( lpArgumentString,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
0
) ) == (HANDLE)-1 ) {
//
// Unable to open the file - send all output to the screen.
//
lpAlternateOutputRoutine = lpExtensionApis->lpOutputRoutine;
} else {
lpAlternateOutputRoutine = DumpToFile;
}
//
// Get the address of the head of the memleak list...
//
AddrMem = (lpGetExpressionRoutine)("Ulib!pmemHead");
if ( !AddrMem ) {
(lpOutputRoutine)( "Unable to find the head of the Mem List!\n" );
if( hFile != (HANDLE)-1 ) {
CloseHandle( hFile );
}
return;
}
if( !ReadProcessMemory(
hCurrentProcess,
(LPVOID)AddrMem,
&MemListNext,
sizeof( PMEM_BLOCK ),
NULL
) ) {
if( hFile != (HANDLE)-1 ) {
CloseHandle( hFile );
}
return;
}
//
// Traverse the list of Mem blocks stopping when the head hits the
// tail...At this point, the head of the list should be indicated
// by MemListHead and the tail by MemListTail. Since the first element
// in the list is a dummy entry, it can be skipped...
//
do {
if( !ReadProcessMemory(
hCurrentProcess,
(LPVOID)MemListNext,
&MemObject,
sizeof( MEM_BLOCK ),
NULL
) ) {
return;
}
if( MemObject.memsig != Signature ) {
//
// This is an unrecognized memory block - die...
//
(lpOutputRoutine)( "Invalid block found!\n" );
return;
}
//
// Display the stored info - First the File, Line and Size of the
// memory block allocated. Then the stack trace...
//
sprintf( Buffer, "File: %s, Line: %ld, Size: %ld\n", MemObject.file,
MemObject.line, MemObject.size
);
( lpAlternateOutputRoutine )( Buffer );
//
// This should dump the stack trace which was stored...
//
for( i = 0; ( i < MaxCallStack ) && ( MemObject.call[ i ] != 0 ); i++ ) {
(lpGetSymbolRoutine)( ( LPVOID )( MemObject.call[ i ] ),
Symbol,
&Displacement
);
sprintf( Buffer, "\t%s\n", Symbol );
( lpAlternateOutputRoutine )( Buffer );
}
( lpAlternateOutputRoutine )( "\n" );
} while( ( MemListNext = MemObject.pmemNext ) != NULL );
(lpOutputRoutine)( "\n...End of List...\n" );
if( hFile != (HANDLE)-1 ) {
( lpAlternateOutputRoutine )( "\n...End of List...\n" );
CloseHandle( hFile );
}
return;
}