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.

369 lines
9.1 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. module.c
  5. Abstract:
  6. This module maintains the module (symbol) information for the pfmon application
  7. Author:
  8. Mark Lucovsky (markl) 27-Jan-1995
  9. Revision History:
  10. --*/
  11. #include "pfmonp.h"
  12. BOOL
  13. AddModule(
  14. LPDEBUG_EVENT DebugEvent
  15. )
  16. {
  17. PMODULE_INFO Module;
  18. LPVOID BaseAddress;
  19. HANDLE Handle;
  20. IMAGEHLP_MODULE ModuleInfo;
  21. if (DebugEvent->dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) {
  22. Handle = DebugEvent->u.CreateProcessInfo.hFile;
  23. BaseAddress = DebugEvent->u.CreateProcessInfo.lpBaseOfImage;
  24. }
  25. else {
  26. Handle = DebugEvent->u.LoadDll.hFile;
  27. BaseAddress = DebugEvent->u.LoadDll.lpBaseOfDll;
  28. }
  29. Module = FindModuleContainingAddress(BaseAddress);
  30. if (Module) {
  31. DeleteModule(Module);
  32. }
  33. Module = LocalAlloc(LMEM_ZEROINIT, sizeof( *Module ) );
  34. if (Module == NULL) {
  35. return FALSE;
  36. }
  37. Module->Handle = Handle;
  38. Module->BaseAddress = BaseAddress;
  39. if (!Module->Handle) {
  40. LocalFree(Module);
  41. return FALSE;
  42. }
  43. if (!SymLoadModule (hProcess,Handle,NULL,NULL,(DWORD_PTR)BaseAddress,0)) {
  44. LocalFree(Module);
  45. return FALSE;
  46. }
  47. ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
  48. if (!SymGetModuleInfo (hProcess, (DWORD_PTR)BaseAddress, &ModuleInfo)) {
  49. LocalFree(Module);
  50. return FALSE;
  51. }
  52. Module->VirtualSize = ModuleInfo.ImageSize;
  53. Module->ModuleName = _strdup(ModuleInfo.ModuleName);
  54. InsertTailList( &ModuleListHead, &Module->Entry );
  55. return TRUE;
  56. }
  57. BOOL
  58. DeleteModule(
  59. PMODULE_INFO Module
  60. )
  61. {
  62. CHAR Line[256];
  63. if ( Module ) {
  64. RemoveEntryList(&Module->Entry);
  65. sprintf(Line,"%16s Caused %6d faults had %6d Soft %6d Hard faulted VA's\n",
  66. Module->ModuleName ? Module->ModuleName : "Unknown",
  67. Module->NumberCausedFaults,
  68. Module->NumberFaultedSoftVas,
  69. Module->NumberFaultedHardVas
  70. );
  71. if ( !fLogOnly ) {
  72. fprintf(stdout,"%s",Line);
  73. }
  74. if ( LogFile ) {
  75. fprintf(LogFile,"%s",Line);
  76. }
  77. if (Module->ModuleName) {
  78. free (Module->ModuleName);
  79. }
  80. LocalFree(Module);
  81. }
  82. return TRUE;
  83. }
  84. PMODULE_INFO
  85. FindModuleContainingAddress(
  86. LPVOID Address
  87. )
  88. {
  89. PLIST_ENTRY Next;
  90. PMODULE_INFO Module;
  91. BOOL LazyLoadStatus;
  92. Next = ModuleListHead.Flink;
  93. while ( Next != &ModuleListHead ) {
  94. Module = CONTAINING_RECORD(Next,MODULE_INFO,Entry);
  95. if ( Address >= Module->BaseAddress &&
  96. Address < (LPVOID)((PUCHAR)(Module->BaseAddress)+Module->VirtualSize) ) {
  97. return Module;
  98. }
  99. Next = Next->Flink;
  100. }
  101. Module = NULL;
  102. //
  103. // if address is a kernel mode address and we have lazy loaded
  104. // kernel symbols, then try to load a kernel symbol file
  105. //
  106. if ( fKernel && (ULONG_PTR)Address >= SystemRangeStart && LazyModuleInformation ) {
  107. fKernel = FALSE;
  108. LazyLoadStatus = LazyLoad(Address);
  109. if ( LazyLoadStatus ) {
  110. Module = FindModuleContainingAddress(Address);
  111. }
  112. fKernel = TRUE;
  113. }
  114. return Module;
  115. }
  116. VOID
  117. SetSymbolSearchPath(
  118. VOID
  119. )
  120. {
  121. LPSTR lpSymPathEnv, lpAltSymPathEnv, lpSystemRootEnv;
  122. ULONG cbSymPath;
  123. DWORD dw;
  124. cbSymPath = 18;
  125. if (lpSymPathEnv = getenv("_NT_SYMBOL_PATH")) {
  126. cbSymPath += strlen(lpSymPathEnv) + 1;
  127. }
  128. if (lpAltSymPathEnv = getenv("_NT_ALT_SYMBOL_PATH")) {
  129. cbSymPath += strlen(lpAltSymPathEnv) + 1;
  130. }
  131. if (lpSystemRootEnv = getenv("SystemRoot")) {
  132. cbSymPath += strlen(lpSystemRootEnv) + 1;
  133. }
  134. SymbolSearchPath = LocalAlloc(LMEM_ZEROINIT,cbSymPath);
  135. if (!SymbolSearchPath) {
  136. return;
  137. }
  138. if (lpAltSymPathEnv) {
  139. dw = GetFileAttributes(lpAltSymPathEnv);
  140. if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY ) {
  141. strcat(SymbolSearchPath,lpAltSymPathEnv);
  142. strcat(SymbolSearchPath,";");
  143. }
  144. }
  145. if (lpSymPathEnv) {
  146. dw = GetFileAttributes(lpSymPathEnv);
  147. if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY ) {
  148. strcat(SymbolSearchPath,lpSymPathEnv);
  149. strcat(SymbolSearchPath,";");
  150. }
  151. }
  152. if (lpSystemRootEnv) {
  153. dw = GetFileAttributes(lpSystemRootEnv);
  154. if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY ) {
  155. strcat(SymbolSearchPath,lpSystemRootEnv);
  156. strcat(SymbolSearchPath,";");
  157. }
  158. }
  159. strcat(SymbolSearchPath,".;");
  160. }
  161. LONG
  162. AddKernelDrivers(VOID)
  163. /************************************************************\
  164. This function is used to load the symbol information for
  165. the system files that are loaded so that the page faults
  166. in the kernal can be displayed.
  167. Setting of the environmental variables are important for
  168. ensuring that the symbols load up correctly.
  169. returns: The success of the function
  170. \*************************************************************/
  171. {
  172. NTSTATUS status;
  173. PVOID pModuleInfo;
  174. ULONG lDataSize;
  175. ULONG lRetSize;
  176. PRTL_PROCESS_MODULES pModuleInformation;
  177. //First we need to get a list of all the modules currently
  178. //running
  179. //Allocate an initial sized buffer
  180. lDataSize = 1024 * 12;
  181. pModuleInfo = (PVOID) LocalAlloc (LMEM_FIXED, lDataSize);
  182. if (!pModuleInfo) {
  183. return ERROR_NOT_ENOUGH_MEMORY;
  184. }
  185. //Keep querying the system and incrementing the
  186. //size of the buffer until we can get all the information back
  187. do {
  188. //Query for modules loaded up
  189. status = NtQuerySystemInformation(SystemModuleInformation,
  190. pModuleInfo,
  191. lDataSize,
  192. &lRetSize);
  193. if (status == STATUS_INFO_LENGTH_MISMATCH) {
  194. LocalFree (pModuleInfo);
  195. lDataSize += 1024 * 4;
  196. pModuleInfo = (PVOID) LocalAlloc (LMEM_FIXED, lDataSize);
  197. }
  198. if (!pModuleInfo) {
  199. return ERROR_NOT_ENOUGH_MEMORY;
  200. }
  201. } while (status == STATUS_INFO_LENGTH_MISMATCH);
  202. LazyModuleInformation = (PRTL_PROCESS_MODULES) pModuleInfo;
  203. return 1;
  204. }
  205. BOOL
  206. LazyLoad(
  207. LPVOID Address
  208. )
  209. {
  210. PRTL_PROCESS_MODULES pModuleInformation;
  211. DWORD i;
  212. BYTE szImageFilePath[ MAX_PATH ];
  213. PMODULE_INFO Module;
  214. ULONG_PTR BaseAddress;
  215. HANDLE hFile;
  216. LPSTR szFileName;
  217. IMAGEHLP_MODULE ModuleInfo;
  218. pModuleInformation = (PRTL_PROCESS_MODULES) LazyModuleInformation;
  219. //Loop through all the items in the structure and
  220. //and add their symbols to the module structures kept by pfmon.
  221. for (i = 0; i < pModuleInformation->NumberOfModules; i += 1) {
  222. BaseAddress = (ULONG_PTR)pModuleInformation->Modules[i].ImageBase;
  223. //Only look at the kernel space modules
  224. if (BaseAddress >= SystemRangeStart) {
  225. if ( (ULONG_PTR)Address > BaseAddress &&
  226. (ULONG_PTR)Address <= BaseAddress+pModuleInformation->Modules[i].ImageSize ) {
  227. szFileName = pModuleInformation->Modules[i].FullPathName +
  228. pModuleInformation->Modules[i].OffsetToFileName;
  229. strcpy (szImageFilePath,
  230. pModuleInformation->Modules[i].FullPathName);
  231. hFile = FindExecutableImage (szFileName,
  232. SymbolSearchPath,
  233. (PCHAR) szImageFilePath );
  234. if (!hFile) {
  235. fprintf(stdout,"Failed to get Executable Image - ");
  236. return FALSE;
  237. }
  238. //Check to make sure this hasn't already been loaded
  239. Module = FindModuleContainingAddress((LPVOID)BaseAddress);
  240. if ( Module ) {
  241. fprintf(stdout,"Item has been loaded already: %s",szFileName);
  242. DeleteModule(Module);
  243. }
  244. //Now create the module record and fill in its fields
  245. Module = LocalAlloc(LMEM_ZEROINIT, sizeof( *Module ) );
  246. if (Module == NULL) {
  247. return FALSE;
  248. }
  249. Module->Handle = hFile;
  250. Module->BaseAddress = (LPVOID)BaseAddress;
  251. if (!SymLoadModule (hProcess, hFile, NULL, NULL, BaseAddress, 0)) {
  252. LocalFree(Module);
  253. fprintf(stdout, "Failed to load -- ");
  254. return FALSE;
  255. }
  256. ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
  257. if (!SymGetModuleInfo (hProcess, BaseAddress, &ModuleInfo)) {
  258. LocalFree(Module);
  259. fprintf(stdout, "Failed to load -- ");
  260. return FALSE;
  261. }
  262. Module->VirtualSize = ModuleInfo.ImageSize;
  263. fprintf(stdout, "Loaded %s, size %u\n", szImageFilePath, Module->VirtualSize);
  264. InsertTailList( &ModuleListHead, &Module->Entry );
  265. CloseHandle(hFile);
  266. return TRUE;
  267. }
  268. }
  269. }
  270. return FALSE;
  271. }