|
|
/*++
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; }
|