Source code of Windows XP (NT5)
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.

225 lines
4.5 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. memtrace.c
  5. Abstract:
  6. This function contains an extension to NTSD that allows tracing of
  7. memory usage when ULIB objects are compiled with the MEMLEAK flag
  8. defined.
  9. Author:
  10. Barry Gilhuly (W-Barry) 25-July-91
  11. Revision History:
  12. --*/
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <ntsdexts.h>
  18. #include <string.h>
  19. #include "memtrace.h"
  20. VOID
  21. DumpToFile( char *OutString, ... )
  22. {
  23. DWORD bytes;
  24. bytes = strlen( OutString );
  25. WriteFile( hFile, OutString, bytes, &bytes, NULL );
  26. return;
  27. }
  28. VOID
  29. MemTrace(
  30. HANDLE hCurrentProcess,
  31. HANDLE hCurrentThread,
  32. DWORD dwCurrentPc,
  33. PNTSD_EXTENSION_APIS lpExtensionApis,
  34. LPSTR lpArgumentString
  35. )
  36. /*++
  37. Routine Description:
  38. This function is called as an NTSD extension to format and dump
  39. the current contents of the Mem list.
  40. Arguments:
  41. hCurrentProcess - Supplies a handle to the current process (at the
  42. time the extension was called).
  43. hCurrentThread - Supplies a handle to the current thread (at the
  44. time the extension was called).
  45. CurrentPc - Supplies the current pc at the time the extension is
  46. called.
  47. lpExtensionApis - Supplies the address of the functions callable
  48. by this extension.
  49. lpArgumentString - Supplies the asciiz string that describes the
  50. critical section to be dumped (e.g. ntdll!FastPebLock,
  51. csrsrv!CsrProcessStructureLock...).
  52. Return Value:
  53. None.
  54. --*/
  55. {
  56. DWORD AddrMem;
  57. BOOL b;
  58. DWORD i;
  59. PMEM_BLOCK MemListNext;
  60. MEM_BLOCK MemObject;
  61. CHAR Symbol[64];
  62. CHAR Buffer[ 128 ];
  63. DWORD Displacement;
  64. PNTSD_OUTPUT_ROUTINE lpOutputRoutine;
  65. PNTSD_OUTPUT_ROUTINE lpAlternateOutputRoutine;
  66. PNTSD_GET_EXPRESSION lpGetExpressionRoutine;
  67. PNTSD_GET_SYMBOL lpGetSymbolRoutine;
  68. UNREFERENCED_PARAMETER(hCurrentThread);
  69. UNREFERENCED_PARAMETER(dwCurrentPc);
  70. UNREFERENCED_PARAMETER(lpArgumentString);
  71. lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
  72. lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
  73. lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
  74. //
  75. // Attempt to use the input string as a file name...
  76. //
  77. if( ( hFile = CreateFile( lpArgumentString,
  78. GENERIC_WRITE,
  79. 0,
  80. NULL,
  81. CREATE_ALWAYS,
  82. FILE_ATTRIBUTE_NORMAL,
  83. 0
  84. ) ) == (HANDLE)-1 ) {
  85. //
  86. // Unable to open the file - send all output to the screen.
  87. //
  88. lpAlternateOutputRoutine = lpExtensionApis->lpOutputRoutine;
  89. } else {
  90. lpAlternateOutputRoutine = DumpToFile;
  91. }
  92. //
  93. // Get the address of the head of the memleak list...
  94. //
  95. AddrMem = (lpGetExpressionRoutine)("Ulib!pmemHead");
  96. if ( !AddrMem ) {
  97. (lpOutputRoutine)( "Unable to find the head of the Mem List!\n" );
  98. if( hFile != (HANDLE)-1 ) {
  99. CloseHandle( hFile );
  100. }
  101. return;
  102. }
  103. if( !ReadProcessMemory(
  104. hCurrentProcess,
  105. (LPVOID)AddrMem,
  106. &MemListNext,
  107. sizeof( PMEM_BLOCK ),
  108. NULL
  109. ) ) {
  110. if( hFile != (HANDLE)-1 ) {
  111. CloseHandle( hFile );
  112. }
  113. return;
  114. }
  115. //
  116. // Traverse the list of Mem blocks stopping when the head hits the
  117. // tail...At this point, the head of the list should be indicated
  118. // by MemListHead and the tail by MemListTail. Since the first element
  119. // in the list is a dummy entry, it can be skipped...
  120. //
  121. do {
  122. if( !ReadProcessMemory(
  123. hCurrentProcess,
  124. (LPVOID)MemListNext,
  125. &MemObject,
  126. sizeof( MEM_BLOCK ),
  127. NULL
  128. ) ) {
  129. return;
  130. }
  131. if( MemObject.memsig != Signature ) {
  132. //
  133. // This is an unrecognized memory block - die...
  134. //
  135. (lpOutputRoutine)( "Invalid block found!\n" );
  136. return;
  137. }
  138. //
  139. // Display the stored info - First the File, Line and Size of the
  140. // memory block allocated. Then the stack trace...
  141. //
  142. sprintf( Buffer, "File: %s, Line: %ld, Size: %ld\n", MemObject.file,
  143. MemObject.line, MemObject.size
  144. );
  145. ( lpAlternateOutputRoutine )( Buffer );
  146. //
  147. // This should dump the stack trace which was stored...
  148. //
  149. for( i = 0; ( i < MaxCallStack ) && ( MemObject.call[ i ] != 0 ); i++ ) {
  150. (lpGetSymbolRoutine)( ( LPVOID )( MemObject.call[ i ] ),
  151. Symbol,
  152. &Displacement
  153. );
  154. sprintf( Buffer, "\t%s\n", Symbol );
  155. ( lpAlternateOutputRoutine )( Buffer );
  156. }
  157. ( lpAlternateOutputRoutine )( "\n" );
  158. } while( ( MemListNext = MemObject.pmemNext ) != NULL );
  159. (lpOutputRoutine)( "\n...End of List...\n" );
  160. if( hFile != (HANDLE)-1 ) {
  161. ( lpAlternateOutputRoutine )( "\n...End of List...\n" );
  162. CloseHandle( hFile );
  163. }
  164. return;
  165. }