370 lines
9.1 KiB
C
370 lines
9.1 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1992 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
module.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module maintains the module (symbol) information for the pfmon application
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Mark Lucovsky (markl) 27-Jan-1995
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "pfmonp.h"
|
||
|
|
||
|
BOOL
|
||
|
AddModule(
|
||
|
LPDEBUG_EVENT DebugEvent
|
||
|
)
|
||
|
{
|
||
|
PMODULE_INFO Module;
|
||
|
LPVOID BaseAddress;
|
||
|
HANDLE Handle;
|
||
|
IMAGEHLP_MODULE ModuleInfo;
|
||
|
|
||
|
if (DebugEvent->dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) {
|
||
|
Handle = DebugEvent->u.CreateProcessInfo.hFile;
|
||
|
BaseAddress = DebugEvent->u.CreateProcessInfo.lpBaseOfImage;
|
||
|
}
|
||
|
else {
|
||
|
Handle = DebugEvent->u.LoadDll.hFile;
|
||
|
BaseAddress = DebugEvent->u.LoadDll.lpBaseOfDll;
|
||
|
}
|
||
|
|
||
|
Module = FindModuleContainingAddress(BaseAddress);
|
||
|
|
||
|
if (Module) {
|
||
|
DeleteModule(Module);
|
||
|
}
|
||
|
|
||
|
Module = LocalAlloc(LMEM_ZEROINIT, sizeof( *Module ) );
|
||
|
|
||
|
if (Module == NULL) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
Module->Handle = Handle;
|
||
|
Module->BaseAddress = BaseAddress;
|
||
|
|
||
|
if (!Module->Handle) {
|
||
|
LocalFree(Module);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!SymLoadModule (hProcess,Handle,NULL,NULL,(DWORD_PTR)BaseAddress,0)) {
|
||
|
LocalFree(Module);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
|
||
|
if (!SymGetModuleInfo (hProcess, (DWORD_PTR)BaseAddress, &ModuleInfo)) {
|
||
|
LocalFree(Module);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
Module->VirtualSize = ModuleInfo.ImageSize;
|
||
|
Module->ModuleName = _strdup(ModuleInfo.ModuleName);
|
||
|
|
||
|
InsertTailList( &ModuleListHead, &Module->Entry );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
DeleteModule(
|
||
|
PMODULE_INFO Module
|
||
|
)
|
||
|
{
|
||
|
CHAR Line[256];
|
||
|
|
||
|
if ( Module ) {
|
||
|
RemoveEntryList(&Module->Entry);
|
||
|
|
||
|
sprintf(Line,"%16s Caused %6d faults had %6d Soft %6d Hard faulted VA's\n",
|
||
|
Module->ModuleName ? Module->ModuleName : "Unknown",
|
||
|
Module->NumberCausedFaults,
|
||
|
Module->NumberFaultedSoftVas,
|
||
|
Module->NumberFaultedHardVas
|
||
|
);
|
||
|
|
||
|
if ( !fLogOnly ) {
|
||
|
fprintf(stdout,"%s",Line);
|
||
|
}
|
||
|
|
||
|
if ( LogFile ) {
|
||
|
fprintf(LogFile,"%s",Line);
|
||
|
}
|
||
|
|
||
|
if (Module->ModuleName) {
|
||
|
free (Module->ModuleName);
|
||
|
}
|
||
|
|
||
|
LocalFree(Module);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
PMODULE_INFO
|
||
|
FindModuleContainingAddress(
|
||
|
LPVOID Address
|
||
|
)
|
||
|
{
|
||
|
PLIST_ENTRY Next;
|
||
|
PMODULE_INFO Module;
|
||
|
BOOL LazyLoadStatus;
|
||
|
|
||
|
Next = ModuleListHead.Flink;
|
||
|
while ( Next != &ModuleListHead ) {
|
||
|
Module = CONTAINING_RECORD(Next,MODULE_INFO,Entry);
|
||
|
if ( Address >= Module->BaseAddress &&
|
||
|
Address < (LPVOID)((PUCHAR)(Module->BaseAddress)+Module->VirtualSize) ) {
|
||
|
return Module;
|
||
|
}
|
||
|
Next = Next->Flink;
|
||
|
}
|
||
|
|
||
|
Module = NULL;
|
||
|
|
||
|
//
|
||
|
// if address is a kernel mode address and we have lazy loaded
|
||
|
// kernel symbols, then try to load a kernel symbol file
|
||
|
//
|
||
|
|
||
|
if ( fKernel && (ULONG_PTR)Address >= SystemRangeStart && LazyModuleInformation ) {
|
||
|
fKernel = FALSE;
|
||
|
LazyLoadStatus = LazyLoad(Address);
|
||
|
|
||
|
if ( LazyLoadStatus ) {
|
||
|
Module = FindModuleContainingAddress(Address);
|
||
|
}
|
||
|
fKernel = TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
return Module;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
SetSymbolSearchPath(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
LPSTR lpSymPathEnv, lpAltSymPathEnv, lpSystemRootEnv;
|
||
|
ULONG cbSymPath;
|
||
|
DWORD dw;
|
||
|
|
||
|
cbSymPath = 18;
|
||
|
if (lpSymPathEnv = getenv("_NT_SYMBOL_PATH")) {
|
||
|
cbSymPath += strlen(lpSymPathEnv) + 1;
|
||
|
}
|
||
|
if (lpAltSymPathEnv = getenv("_NT_ALT_SYMBOL_PATH")) {
|
||
|
cbSymPath += strlen(lpAltSymPathEnv) + 1;
|
||
|
}
|
||
|
|
||
|
if (lpSystemRootEnv = getenv("SystemRoot")) {
|
||
|
cbSymPath += strlen(lpSystemRootEnv) + 1;
|
||
|
}
|
||
|
|
||
|
SymbolSearchPath = LocalAlloc(LMEM_ZEROINIT,cbSymPath);
|
||
|
if (!SymbolSearchPath) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (lpAltSymPathEnv) {
|
||
|
dw = GetFileAttributes(lpAltSymPathEnv);
|
||
|
if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY ) {
|
||
|
strcat(SymbolSearchPath,lpAltSymPathEnv);
|
||
|
strcat(SymbolSearchPath,";");
|
||
|
}
|
||
|
}
|
||
|
if (lpSymPathEnv) {
|
||
|
dw = GetFileAttributes(lpSymPathEnv);
|
||
|
if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY ) {
|
||
|
strcat(SymbolSearchPath,lpSymPathEnv);
|
||
|
strcat(SymbolSearchPath,";");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (lpSystemRootEnv) {
|
||
|
dw = GetFileAttributes(lpSystemRootEnv);
|
||
|
if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY ) {
|
||
|
strcat(SymbolSearchPath,lpSystemRootEnv);
|
||
|
strcat(SymbolSearchPath,";");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
strcat(SymbolSearchPath,".;");
|
||
|
}
|
||
|
|
||
|
|
||
|
LONG
|
||
|
AddKernelDrivers(VOID)
|
||
|
|
||
|
/************************************************************\
|
||
|
This function is used to load the symbol information for
|
||
|
the system files that are loaded so that the page faults
|
||
|
in the kernal can be displayed.
|
||
|
|
||
|
Setting of the environmental variables are important for
|
||
|
ensuring that the symbols load up correctly.
|
||
|
|
||
|
returns: The success of the function
|
||
|
\*************************************************************/
|
||
|
|
||
|
|
||
|
{
|
||
|
|
||
|
NTSTATUS status;
|
||
|
PVOID pModuleInfo;
|
||
|
ULONG lDataSize;
|
||
|
ULONG lRetSize;
|
||
|
PRTL_PROCESS_MODULES pModuleInformation;
|
||
|
|
||
|
|
||
|
//First we need to get a list of all the modules currently
|
||
|
//running
|
||
|
|
||
|
//Allocate an initial sized buffer
|
||
|
|
||
|
lDataSize = 1024 * 12;
|
||
|
pModuleInfo = (PVOID) LocalAlloc (LMEM_FIXED, lDataSize);
|
||
|
|
||
|
if (!pModuleInfo) {
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
|
||
|
//Keep querying the system and incrementing the
|
||
|
//size of the buffer until we can get all the information back
|
||
|
|
||
|
do {
|
||
|
//Query for modules loaded up
|
||
|
|
||
|
status = NtQuerySystemInformation(SystemModuleInformation,
|
||
|
pModuleInfo,
|
||
|
lDataSize,
|
||
|
&lRetSize);
|
||
|
|
||
|
|
||
|
if (status == STATUS_INFO_LENGTH_MISMATCH) {
|
||
|
LocalFree (pModuleInfo);
|
||
|
lDataSize += 1024 * 4;
|
||
|
pModuleInfo = (PVOID) LocalAlloc (LMEM_FIXED, lDataSize);
|
||
|
}
|
||
|
|
||
|
if (!pModuleInfo) {
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
|
||
|
} while (status == STATUS_INFO_LENGTH_MISMATCH);
|
||
|
|
||
|
LazyModuleInformation = (PRTL_PROCESS_MODULES) pModuleInfo;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
LazyLoad(
|
||
|
LPVOID Address
|
||
|
)
|
||
|
{
|
||
|
PRTL_PROCESS_MODULES pModuleInformation;
|
||
|
DWORD i;
|
||
|
BYTE szImageFilePath[ MAX_PATH ];
|
||
|
PMODULE_INFO Module;
|
||
|
ULONG_PTR BaseAddress;
|
||
|
HANDLE hFile;
|
||
|
LPSTR szFileName;
|
||
|
IMAGEHLP_MODULE ModuleInfo;
|
||
|
|
||
|
pModuleInformation = (PRTL_PROCESS_MODULES) LazyModuleInformation;
|
||
|
|
||
|
//Loop through all the items in the structure and
|
||
|
//and add their symbols to the module structures kept by pfmon.
|
||
|
|
||
|
for (i = 0; i < pModuleInformation->NumberOfModules; i += 1) {
|
||
|
|
||
|
BaseAddress = (ULONG_PTR)pModuleInformation->Modules[i].ImageBase;
|
||
|
|
||
|
//Only look at the kernel space modules
|
||
|
|
||
|
if (BaseAddress >= SystemRangeStart) {
|
||
|
|
||
|
if ( (ULONG_PTR)Address > BaseAddress &&
|
||
|
(ULONG_PTR)Address <= BaseAddress+pModuleInformation->Modules[i].ImageSize ) {
|
||
|
|
||
|
szFileName = pModuleInformation->Modules[i].FullPathName +
|
||
|
pModuleInformation->Modules[i].OffsetToFileName;
|
||
|
|
||
|
strcpy (szImageFilePath,
|
||
|
pModuleInformation->Modules[i].FullPathName);
|
||
|
|
||
|
hFile = FindExecutableImage (szFileName,
|
||
|
SymbolSearchPath,
|
||
|
(PCHAR) szImageFilePath );
|
||
|
|
||
|
if (!hFile) {
|
||
|
fprintf(stdout,"Failed to get Executable Image - ");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//Check to make sure this hasn't already been loaded
|
||
|
|
||
|
Module = FindModuleContainingAddress((LPVOID)BaseAddress);
|
||
|
|
||
|
if ( Module ) {
|
||
|
fprintf(stdout,"Item has been loaded already: %s",szFileName);
|
||
|
DeleteModule(Module);
|
||
|
}
|
||
|
|
||
|
//Now create the module record and fill in its fields
|
||
|
|
||
|
Module = LocalAlloc(LMEM_ZEROINIT, sizeof( *Module ) );
|
||
|
|
||
|
if (Module == NULL) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
Module->Handle = hFile;
|
||
|
Module->BaseAddress = (LPVOID)BaseAddress;
|
||
|
|
||
|
if (!SymLoadModule (hProcess, hFile, NULL, NULL, BaseAddress, 0)) {
|
||
|
LocalFree(Module);
|
||
|
fprintf(stdout, "Failed to load -- ");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
|
||
|
if (!SymGetModuleInfo (hProcess, BaseAddress, &ModuleInfo)) {
|
||
|
LocalFree(Module);
|
||
|
fprintf(stdout, "Failed to load -- ");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
Module->VirtualSize = ModuleInfo.ImageSize;
|
||
|
|
||
|
fprintf(stdout, "Loaded %s, size %u\n", szImageFilePath, Module->VirtualSize);
|
||
|
|
||
|
InsertTailList( &ModuleListHead, &Module->Entry );
|
||
|
|
||
|
CloseHandle(hFile);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|