Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

574 lines
15 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
module.c
Abstract:
This module maintains the module (symbol) information for the callmon application
Author:
Mark Lucovsky (markl) 27-Jan-1995
Revision History:
--*/
#include "callmonp.h"
BOOL
AddModule(
LPDEBUG_EVENT DebugEvent
)
{
PMODULE_INFO Module;
LPVOID BaseAddress;
HANDLE Handle;
HANDLE hMappedFile;
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
DWORD ExportSize;
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;
}
hMappedFile = CreateFileMapping(Module->Handle,
NULL,
PAGE_READONLY,
0,
0,
NULL
);
if (!hMappedFile) {
LocalFree(Module);
return FALSE;
}
Module->MappedAddress = MapViewOfFile(hMappedFile,
FILE_MAP_READ,
0,
0,
0
);
CloseHandle(hMappedFile);
if (!Module->MappedAddress) {
LocalFree(Module);
return FALSE;
}
Module->FileHeader = ImageNtHeader( Module->MappedAddress );
Module->VirtualSize = Module->FileHeader->OptionalHeader.SizeOfImage;
ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData(
Module->MappedAddress,
FALSE,
IMAGE_DIRECTORY_ENTRY_EXPORT,
&ExportSize
);
if ( !ExportDirectory ) {
Module->ModuleName = "The Image";
}
else {
Module->ModuleName = (LPSTR) ImageRvaToVa(
Module->FileHeader,
Module->MappedAddress,
ExportDirectory->Name,
NULL
);
}
InsertTailList( &ModuleListHead, &Module->Entry );
return TRUE;
}
BOOL
DeleteModule(
PMODULE_INFO Module
)
{
CHAR Line[256];
if ( Module ) {
RemoveEntryList(&Module->Entry);
LocalFree(Module);
}
return TRUE;
}
PMODULE_INFO
FindModuleContainingAddress(
LPVOID Address
)
{
PLIST_ENTRY Next;
PMODULE_INFO Module;
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;
}
return NULL;
}
VOID
SetSymbolSearchPath( )
{
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 (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,".;");
}
BREAKPOINT_INFO Bp;
VOID
SetValidModuleFlags(
VOID
)
{
PLIST_ENTRY Next;
PMODULE_INFO Module;
//
// Now find user, kernel, gdi (and possibly ntdll.dll)
//
fNtDllValid = FALSE;
fWsock32Valid = FALSE;
fKernel32Valid = FALSE;
fUser32Valid = FALSE;
fGdi32Valid = FALSE;
fOle32Valid = FALSE;
Next = ModuleListHead.Flink;
while ( Next != &ModuleListHead ) {
Module = CONTAINING_RECORD(Next,MODULE_INFO,Entry);
if ( !_strnicmp(Module->ModuleName,"USER32.",7) ) {
fUser32Valid = TRUE;
}
if ( !_strnicmp(Module->ModuleName,"GDI32.",6) ) {
fGdi32Valid = TRUE;
}
if ( !_strnicmp(Module->ModuleName,"KERNEL32.",9) ) {
fKernel32Valid = TRUE;
}
if ( !_strnicmp(Module->ModuleName,"WSOCK32.",8) ) {
fWsock32Valid = TRUE;
}
if ( !_strnicmp(Module->ModuleName,"OLE32.",6) ) {
fOle32Valid = TRUE;
}
if ( !_strnicmp(Module->ModuleName,"NTDLL.",6) ) {
fNtDllValid = TRUE;
}
Next = Next->Flink;
}
if ( !fNtDllValid ) {
fNtDll = FALSE;
}
if ( !fKernel32Valid ) {
fKernel32 = FALSE;
}
if ( !fWsock32Valid ) {
fWsock32 = FALSE;
}
if ( !fUser32Valid ) {
fUser32 = FALSE;
}
if ( !fGdi32Valid ) {
fGdi32 = FALSE;
}
if ( !fOle32Valid ) {
fOle32 = FALSE;
}
}
VOID
InitializeBreakPoints(
PPROCESS_INFO Process
)
{
DWORD i;
PLIST_ENTRY Next;
PMODULE_INFO Module;
for(i=0;i<HASH_TABLE_SIZE;i++){
InitializeListHead(&HashTable[i]);
}
//
// Now find user, kernel, gdi (and possibly ntdll.dll)
//
Next = ModuleListHead.Flink;
while ( Next != &ModuleListHead ) {
Module = CONTAINING_RECORD(Next,MODULE_INFO,Entry);
if ( fUser32 && !_strnicmp(Module->ModuleName,"USER32.",7) ) {
AddBreakpointsForModule(Process,Module);
}
if ( fGdi32 && !_strnicmp(Module->ModuleName,"GDI32.",6) ) {
AddBreakpointsForModule(Process,Module);
}
if ( fKernel32 && !_strnicmp(Module->ModuleName,"KERNEL32.",9) ) {
AddBreakpointsForModule(Process,Module);
}
if ( fWsock32 && !_strnicmp(Module->ModuleName,"WSOCK32.",8) ) {
AddBreakpointsForModule(Process,Module);
}
if ( fOle32 && !_strnicmp(Module->ModuleName,"OLE32.",6) ) {
AddBreakpointsForModule(Process,Module);
}
if ( fNtDll && !_strnicmp(Module->ModuleName,"NTDLL.",6) ) {
AddBreakpointsForModule(Process,Module);
}
Next = Next->Flink;
}
}
VOID
AddBreakpointsForModule (
PPROCESS_INFO Process,
PMODULE_INFO ModInfo
)
{
DWORD ExportSize;
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry;
PULONG NameTableBase;
PUSHORT NameOrdinalTableBase;
DWORD i;
DWORD BreakPointIndex;
PULONG Addr;
PVOID ApiAddress;
PVOID ApiName;
ULONG ExportsBase;
ULONG FunctionEntrySize;
ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData(
ModInfo->MappedAddress,
FALSE,
IMAGE_DIRECTORY_ENTRY_EXPORT,
&ExportSize
);
if ( !ExportDirectory ) {
fprintf(stderr,"CALLMON: Export Directory not found\n");
ExitProcess(1);
}
ExportsBase = (ULONG)ImageDirectoryEntryToData(
ModInfo->MappedAddress,
TRUE,
IMAGE_DIRECTORY_ENTRY_EXPORT,
&ExportSize
) - (ULONG)ModInfo->MappedAddress;
ExportsBase += (ULONG)ModInfo->BaseAddress;
ModInfo->FunctionEntry = (PIMAGE_RUNTIME_FUNCTION_ENTRY)
ImageDirectoryEntryToData(ModInfo->MappedAddress,
FALSE,
IMAGE_DIRECTORY_ENTRY_EXCEPTION,
&FunctionEntrySize);
if (ModInfo->FunctionEntry) {
ModInfo->NumberOfFunctionEntries = FunctionEntrySize / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
} else {
ModInfo->NumberOfFunctionEntries = 0;
}
NameTableBase = (PULONG) ImageRvaToVa(
ModInfo->FileHeader,
ModInfo->MappedAddress,
(ULONG)ExportDirectory->AddressOfNames,
NULL
);
NameOrdinalTableBase = (PUSHORT) ImageRvaToVa(
ModInfo->FileHeader,
ModInfo->MappedAddress,
(ULONG)ExportDirectory->AddressOfNameOrdinals,
NULL
);
Addr = (PULONG) ImageRvaToVa(
ModInfo->FileHeader,
ModInfo->MappedAddress,
(ULONG)ExportDirectory->AddressOfFunctions,
NULL
);
ModInfo->ModuleName = (LPSTR) ImageRvaToVa(
ModInfo->FileHeader,
ModInfo->MappedAddress,
ExportDirectory->Name,
NULL
);
if ( !Addr || !NameOrdinalTableBase || !NameTableBase ) {
fprintf(stderr,"CALLMON: Export Directory not valid\n");
ExitProcess(1);
}
if ( NumberOfBreakpoints ) {
RegisteredBreakpoints = LocalReAlloc(
RegisteredBreakpoints,
(NumberOfBreakpoints + ExportDirectory->NumberOfNames)*sizeof(PBREAKPOINT_INFO),
LMEM_ZEROINIT | LMEM_MOVEABLE
);
}
else {
RegisteredBreakpoints = LocalAlloc(LMEM_ZEROINIT,ExportDirectory->NumberOfNames*sizeof(PBREAKPOINT_INFO));
}
for(i=0, BreakPointIndex = NumberOfBreakpoints;i<ExportDirectory->NumberOfNames;i++,BreakPointIndex++){
ApiAddress = (PULONG)((ULONG)ModInfo->BaseAddress + Addr[NameOrdinalTableBase[i]]);
if ((ULONG)ApiAddress > (ULONG)ExportsBase &&
(ULONG)ApiAddress < ((ULONG)ExportsBase + ExportSize)
) {
//
// Skip this... It's a forwarded reference
}
else {
ApiName = (PCHAR) ImageRvaToVa(
ModInfo->FileHeader,
ModInfo->MappedAddress,
NameTableBase[i],
NULL
);
if ( strcmp(ApiName,"UnhandledExceptionFilter") &&
strcmp(ApiName,"EnterCriticalSection") &&
strcmp(ApiName,"RtlEnterCriticalSection")) {
if ( RegisteredBreakpoints[BreakPointIndex] = CreateBreakpoint(ApiAddress,
Process,
ApiName,
ModInfo) ) {
NumberOfBreakpoints++;
}
}
}
}
}
PBREAKPOINT_INFO
FindBreakpoint(
LPVOID Address,
PPROCESS_INFO Process
)
{
PBREAKPOINT_INFO Breakpoint;
PLIST_ENTRY Next, Head;
Head = &HashTable[COMPUTE_HASH_INDEX(Address)];
Next = Head->Flink;
while (Next != Head) {
Breakpoint = CONTAINING_RECORD( Next, BREAKPOINT_INFO, Entry );
if (Breakpoint->Address == Address) {
return Breakpoint;
}
Next = Next->Flink;
}
return NULL;
}
PBREAKPOINT_INFO
CreateBreakpoint(
LPVOID Address,
PPROCESS_INFO Process,
PSZ FunctionName,
PMODULE_INFO ModInfo
)
{
PBREAKPOINT_INFO Breakpoint;
PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry;
Breakpoint = FindBreakpoint( Address, Process );
if (Breakpoint != NULL) {
return Breakpoint;
}
Breakpoint = LocalAlloc(LMEM_ZEROINIT,sizeof(*Breakpoint));
if (Breakpoint == NULL) {
return NULL;
}
if ((ModInfo->NumberOfFunctionEntries > 0) &&
(FunctionEntry = LookupFunctionEntry((ULONG)Address, ModInfo))) {
if (((ULONG)Address >= FunctionEntry->BeginAddress) &&
((ULONG)Address < FunctionEntry->PrologEndAddress)) {
Address = (LPVOID)FunctionEntry->PrologEndAddress;
}
}
Breakpoint->Address = Address;
Breakpoint->ApiName = FunctionName;
Breakpoint->ApiCount = 0;
Breakpoint->SavedInstructionValid = FALSE;
InsertTailList(&HashTable[COMPUTE_HASH_INDEX(Address)],&Breakpoint->Entry);
if ( fBreakPointsValid ) {
InstallBreakpoint( Process, Breakpoint );
}
return Breakpoint;
}
PIMAGE_RUNTIME_FUNCTION_ENTRY
LookupFunctionEntry (
ULONG Address,
PMODULE_INFO ModInfo
)
{
PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry;
PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionTable;
LONG High;
LONG Low;
LONG Middle;
//
// Initialize search indicies.
//
Low = 0;
High = ModInfo->NumberOfFunctionEntries - 1;
FunctionTable = ModInfo->FunctionEntry;
//
// Perform binary search on the function table for a function table
// entry that subsumes the specified PC.
//
while (High >= Low) {
//
// Compute next probe index and test entry. If the specified PC
// is greater than of equal to the beginning address and less
// than the ending address of the function table entry, then
// return the address of the function table entry. Otherwise,
// continue the search.
//
Middle = (Low + High) >> 1;
FunctionEntry = &FunctionTable[Middle];
if (Address < FunctionEntry->BeginAddress) {
High = Middle - 1;
} else if (Address >= FunctionEntry->EndAddress) {
Low = Middle + 1;
} else {
return FunctionEntry;
}
}
//
// A function table entry for the specified PC was not found.
//
return NULL;
}