mirror of https://github.com/lianthony/NT4.0
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.
4789 lines
129 KiB
4789 lines
129 KiB
/*** WST.C - Working Set Tuner Data Collection Program.
|
|
*
|
|
*
|
|
* Title:
|
|
*
|
|
* WST- Working Set Tuner Data Collection Program.
|
|
*
|
|
* Copyright (c) 1992-1994, Microsoft Corporation.
|
|
* Reza Baghai.
|
|
*
|
|
* THIS CODE NEEDS TO BE CLEANED UP!
|
|
* There is no reason to patch imports and the code will be much
|
|
* cleaner when this is removed. The call to PatchDll has been
|
|
* commented out already but I didn't have time to clean it up.
|
|
*
|
|
* Description:
|
|
*
|
|
* The Working Set Tuner tool is organized as follows:
|
|
*
|
|
* o WST.c ........ Tools main body
|
|
* o WST.h
|
|
* o WST.def
|
|
*
|
|
*
|
|
*
|
|
* Design/Implementation Notes
|
|
*
|
|
* The following defines can be used to control output of all the
|
|
* debugging information to the debugger via KdPrint() for the checked
|
|
* builds:
|
|
*
|
|
* (All debugging options are undefined for free/retail builds)
|
|
*
|
|
* PPC
|
|
* ---
|
|
*
|
|
* PPC experiences problems when reading symbols in CRTDLL.dll
|
|
*
|
|
* #ifdef INFODBG : Displays messages to indicate when data dumping/
|
|
* clearing operations are completed. It has no effect
|
|
* on timing. *DEFAULT*
|
|
*
|
|
* #ifdef SETUPDBG : Displays messages during memory management and
|
|
* symbol lookup operations. It has some affect
|
|
* on timing whenever a chuck of memory is committed.
|
|
*
|
|
* #ifdef C6 : Generate code using C6 compiler. C6 compiler
|
|
* calls _mcount() as the profiling routine where as
|
|
* C8 calls _penter().
|
|
*
|
|
*
|
|
*
|
|
*
|
|
* Modification History:
|
|
*
|
|
* 92.07.28 RezaB -- Created
|
|
* 94.02.08 a-honwah -- ported to MIPS and ALPHA
|
|
*
|
|
*/
|
|
|
|
|
|
char *VERSION = "2.1 (94.02.08)";
|
|
|
|
|
|
#if DBG
|
|
//
|
|
// Don't do anything for the checked builds, let it be controlled from the
|
|
// sources file.
|
|
//
|
|
#else
|
|
//
|
|
// Disable all debugging options.
|
|
//
|
|
#undef INFODBG
|
|
#undef SETUPDBG
|
|
#define SdPrint(_x_)
|
|
#define IdPrint(_x_)
|
|
#endif
|
|
|
|
#ifdef SETUPDBG
|
|
#define SdPrint(_x_) DbgPrint _x_
|
|
#else
|
|
#define SdPrint(_x_)
|
|
#endif
|
|
|
|
#ifdef INFODBG
|
|
#define IdPrint(_x_) DbgPrint _x_
|
|
#else
|
|
#define IdPrint(_x_)
|
|
#endif
|
|
|
|
|
|
|
|
/* * * * * * * * * * * * * I N C L U D E F I L E S * * * * * * * * * * */
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <ntcsrsrv.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <excpt.h>
|
|
|
|
#include <windows.h>
|
|
|
|
#include <imagehlp.h>
|
|
|
|
#include "wst.h"
|
|
#include "wstexp.h"
|
|
|
|
#ifdef MIPS
|
|
#define SaveAllRegs()
|
|
#define RestoreAllRegs()
|
|
extern void _asm(char *, ...);
|
|
#endif
|
|
|
|
#ifdef ALPHA
|
|
typedef double DWORDLONG;
|
|
void SaveAllRegs (DWORDLONG *pSaveRegs) ;
|
|
void RestoreAllRegs (DWORDLONG *pSaveRegs) ;
|
|
//void GetCaller (DWORD * pdwAddr, DWORD StackSize);
|
|
//void GetCalCaller (DWORD * pdwAddr, DWORD StackSize);
|
|
//void GetStubCaller (DWORD * pdwPrevAddr, DWORD StackSize);
|
|
void penter(void);
|
|
#endif
|
|
#if defined(_PPC_)
|
|
void SaveAllRegs (void ) ;
|
|
void RestoreAllRegs (void ) ;
|
|
void GetCalCaller (void );
|
|
void c_penter (ULONG , ULONG );
|
|
void penter(void);
|
|
#endif
|
|
|
|
void SetSymbolSearchPath (void);
|
|
LPSTR lpSymbolSearchPath = NULL;
|
|
#define NO_CALLER 10L
|
|
|
|
/* * * * * * * * * * G L O B A L D E C L A R A T I O N S * * * * * * * * */
|
|
|
|
#if defined(MIPS) || defined(ALPHA) || defined(_PPC_)
|
|
PATCHCODE PatchStub;
|
|
#endif
|
|
|
|
|
|
|
|
/* * * * * * * * * * F U N C T I O N P R O T O T Y P E S * * * * * * * * */
|
|
|
|
BOOLEAN WSTMain (IN PVOID DllHandle, ULONG Reason,
|
|
IN PCONTEXT Context OPTIONAL);
|
|
|
|
BOOLEAN WstDllInitializations (void);
|
|
|
|
void WstRecordInfo (DWORD dwAddress, DWORD dwPrevAddress);
|
|
|
|
void WstGetSymbols (PIMG pCurImg, PSZ pszImageName, PVOID pvImageBase,
|
|
ULONG ulCodeLength,
|
|
PIMAGE_COFF_SYMBOLS_HEADER DebugInfo);
|
|
|
|
void WstDllCleanups (void);
|
|
|
|
BOOL WstPatchDll (PCHAR pchPatchImports,
|
|
PCHAR pchPatchCallers,
|
|
PCHAR pchDllName,
|
|
PVOID pvImageBase);
|
|
|
|
INT WstUnprotectThunkFilter (PVOID pThunkAddress,
|
|
PEXCEPTION_POINTERS pXcptPtr);
|
|
|
|
INT WstAccessXcptFilter (ULONG ulXcptNo, PEXCEPTION_POINTERS pXcptPtr);
|
|
|
|
HANDLE WstInitWspFile (PIMG pImg);
|
|
|
|
void WstClearBitStrings (PIMG pImg);
|
|
|
|
void WstDumpData (PIMG pImg);
|
|
|
|
void WstRotateWsiMem (PIMG pImg);
|
|
|
|
void WstWriteTmiFile (PIMG pImg);
|
|
|
|
int WstCompare (PWSP, PWSP);
|
|
void WstSort (WSP wsp[], INT iLeft, INT iRight);
|
|
int WstBCompare (PDWORD, PWSP);
|
|
PWSP WstBSearch (DWORD dwAddr, WSP wspCur[], INT n);
|
|
void WstSwap (WSP wsp[], INT i, INT j);
|
|
|
|
int WstPszCompare (PNDX pndxVal1, PNDX pndxVal2);
|
|
void WstPszSort (NDX ndx[], INT iLeft, INT iRight);
|
|
int WstPszBCompare (PSTR psz, PNDX pndxVal2);
|
|
ULONG WstPszBSearch (PSTR psz, NDX ndx[], INT n);
|
|
void WstPszSwap (NDX ndx[], INT i, INT j);
|
|
|
|
DWORD WstDumpThread (PVOID pvArg);
|
|
DWORD WstClearThread (PVOID pvArg);
|
|
DWORD WstPauseThread (PVOID pvArg);
|
|
|
|
void WstDataOverFlow(void);
|
|
BOOL WstGetCoffDebugDirectory (PIMAGE_DEBUG_DIRECTORY *pDbgDir, ULONG ulDbgDirSz);
|
|
|
|
#ifdef BATCHING
|
|
BOOL WstOpenBatchFile (VOID);
|
|
#endif
|
|
|
|
#if defined(_PPC_)
|
|
//BOOL WINAPI _CRT_INIT(HINSTANCE, DWORD, LPVOID);
|
|
#endif
|
|
|
|
|
|
/* * * * * * * * * * * G L O B A L V A R I A B L E S * * * * * * * * * */
|
|
|
|
HANDLE hWspSec;
|
|
PULONG pulShared;
|
|
HANDLE hSharedSec;
|
|
|
|
PATCHDLLSEC aPatchDllSec [MAX_PATCHES];
|
|
int iPatchCnt = 0;
|
|
|
|
IMG aImg [MAX_IMAGES];
|
|
int iImgCnt;
|
|
|
|
HANDLE hGlobalSem;
|
|
HANDLE hLocalSem;
|
|
HANDLE hDoneEvent;
|
|
HANDLE hDumpEvent;
|
|
HANDLE hClearEvent;
|
|
HANDLE hPauseEvent;
|
|
HANDLE hDumpThread;
|
|
HANDLE hClearThread;
|
|
HANDLE hPauseThread;
|
|
DWORD DumpClientId;
|
|
DWORD ClearClientId;
|
|
DWORD PauseClientId;
|
|
PSZ pszBaseAppImageName;
|
|
PSZ pszFullAppImageName;
|
|
WSTSTATE WstState = NOT_STARTED;
|
|
char achPatchBuffer [PATCHFILESZ+1] = "???";
|
|
PULONG pulWsiBits;
|
|
PULONG pulWspBits;
|
|
PULONG pulCurWsiBits;
|
|
static UINT uiTimeSegs= 0;
|
|
ULONG ulSegSize;
|
|
ULONG ulSnaps = 0L;
|
|
ULONG ulBitCount = 0L;
|
|
LARGE_INTEGER liStart;
|
|
int iTimeInterval;
|
|
BOOL fInThread = FALSE;
|
|
ULONG ulThdStackSize = 16*PAGE_SIZE;
|
|
BOOL fPatchImage = FALSE;
|
|
SECURITY_DESCRIPTOR SecDescriptor;
|
|
LARGE_INTEGER liOverhead = {0L, 0L};
|
|
|
|
#ifdef BATCHING
|
|
HANDLE hBatchFile;
|
|
BOOL fBatch = TRUE;
|
|
#endif
|
|
|
|
|
|
|
|
/* * * * * * E X P O R T E D G L O B A L V A R I A B L E S * * * * * */
|
|
/* none */
|
|
|
|
|
|
|
|
|
|
|
|
/****************************** W S T M a i n *******************************
|
|
*
|
|
* WSTMain () -
|
|
* This is the DLL entry routine. It performs
|
|
* DLL's initializations and cleanup.
|
|
*
|
|
* ENTRY -none-
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN TRUE if successful
|
|
* FALSE otherwise.
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
BOOLEAN WSTMain (IN PVOID DllHandle,
|
|
ULONG Reason,
|
|
IN PCONTEXT Context OPTIONAL)
|
|
|
|
{
|
|
DllHandle; // avoid compiler warnings
|
|
Context; // avoid compiler warnings
|
|
|
|
|
|
if (Reason == DLL_PROCESS_ATTACH)
|
|
{
|
|
//
|
|
// Initialize the DLL data
|
|
//
|
|
#if defined(_PPC_LIBC)
|
|
if (!_CRT_INIT(DllHandle, Reason, Context))
|
|
return(FALSE);
|
|
#endif
|
|
KdPrint (("WST: DLL_PROCESS_ATTACH\n"));
|
|
WstDllInitializations ();
|
|
}
|
|
else if (Reason == DLL_PROCESS_DETACH) {
|
|
//
|
|
// Cleanup time
|
|
//
|
|
#if defined(_PPC_LIBC)
|
|
if (!_CRT_INIT(DllHandle, Reason, Context))
|
|
return(FALSE);
|
|
#endif
|
|
KdPrint (("WST: DLL_PROCESS_DETACH\n"));
|
|
WstDllCleanups ();
|
|
}
|
|
|
|
return (TRUE);
|
|
|
|
} /* WSTMain() */
|
|
|
|
/****************** W s t s t r d u p ****************************
|
|
*
|
|
* Wststrdup () -
|
|
* Allocate a memory and then duplicate a string
|
|
* It is here because we don't want to use strdup in crtdll.dll
|
|
*
|
|
* ENTRY LPSTR
|
|
*
|
|
* EXIT LPSTR
|
|
*
|
|
* RETURN NULL if failed
|
|
* LPSTR is success
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
LPSTR Wststrdup (LPTSTR lpInput)
|
|
{
|
|
HANDLE hMemoryHandle;
|
|
int StringLen;
|
|
LPSTR lpOutput = NULL;
|
|
LPSTR lpOutput1;
|
|
|
|
StringLen = strlen (lpInput) + 1;
|
|
|
|
hMemoryHandle = GlobalAlloc (GHND, StringLen);
|
|
if (!hMemoryHandle)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
lpOutput = GlobalLock (hMemoryHandle);
|
|
if (!lpOutput)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
lpOutput1 = lpOutput;
|
|
while (*lpOutput1++ = *lpInput++);
|
|
|
|
return (lpOutput);
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************** W s t D l l I n i t i a l i z a t i o n s ***************
|
|
*
|
|
* WstDllInitializations () -
|
|
* Performs the following initializations:
|
|
*
|
|
* o Create LOCAL semaphore (not named)
|
|
* o Create/Open global storage for WST data
|
|
* o Locate all the executables/DLLs in the address and
|
|
* grab all the symbols
|
|
* o Sort the symbol list
|
|
* o Set the profiling flag to TRUE
|
|
*
|
|
*
|
|
* ENTRY -none-
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN TRUE if successful
|
|
* FALSE otherwise.
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
BOOLEAN WstDllInitializations ()
|
|
{
|
|
DWORD dwAddr = 0L;
|
|
DWORD dwPrevAddr = 0L;
|
|
ANSI_STRING ObjName;
|
|
UNICODE_STRING UnicodeName;
|
|
OBJECT_ATTRIBUTES ObjAttributes;
|
|
PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;
|
|
PPEB Peb;
|
|
PSZ ImageName;
|
|
PLIST_ENTRY Next;
|
|
ULONG ExportSize;
|
|
ULONG DebugSize;
|
|
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
|
|
PIMAGE_DEBUG_DIRECTORY DebugDirectory;
|
|
PIMAGE_COFF_SYMBOLS_HEADER DebugInfo;
|
|
STRING ImageStringName;
|
|
LARGE_INTEGER AllocationSize;
|
|
ULONG ulViewSize;
|
|
LARGE_INTEGER liOffset = {0L, 0L};
|
|
HANDLE hIniFile;
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK iostatus;
|
|
char achTmpImageName [32];
|
|
PCHAR pchPatchExes = "";
|
|
PCHAR pchPatchImports = "";
|
|
PCHAR pchPatchCallers = "";
|
|
PCHAR pchTimeInterval = "";
|
|
PVOID ImageBase;
|
|
ULONG CodeLength;
|
|
LARGE_INTEGER liFreq;
|
|
PIMG pImg;
|
|
PIMAGE_NT_HEADERS pImageNtHeader;
|
|
ULONG ulDbgDirSz;
|
|
TCHAR atchProfObjsName[120] = PROFOBJSNAME;
|
|
PTEB pteb = NtCurrentTeb();
|
|
LARGE_INTEGER liStartTicks;
|
|
LARGE_INTEGER liEndTicks;
|
|
ULONG ulElapsed;
|
|
PCHAR pchEntry;
|
|
PIMAGE_SECTION_HEADER pSections;
|
|
PIMAGE_SECTION_HEADER pSectionTmp;
|
|
USHORT NumberOfSections;
|
|
USHORT i;
|
|
ULONG ulRegionSize;
|
|
ULONG ulOldProtect;
|
|
BOOL fFoundSymbols;
|
|
PIMAGE_DEBUG_INFORMATION pImageDbgInfo = NULL;
|
|
|
|
|
|
/*
|
|
***
|
|
*/
|
|
|
|
SetSymbolSearchPath();
|
|
|
|
// Create public share security descriptor for all the named objects
|
|
//
|
|
|
|
Status = RtlCreateSecurityDescriptor (
|
|
&SecDescriptor,
|
|
SECURITY_DESCRIPTOR_REVISION1
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"RtlCreateSecurityDescriptor falied - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
Status = RtlSetDaclSecurityDescriptor (
|
|
&SecDescriptor, // SecurityDescriptor
|
|
TRUE, // DaclPresent
|
|
NULL, // Dacl
|
|
FALSE // DaclDefaulted
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"RtlSetDaclSecurityDescriptor falied - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
/*
|
|
***
|
|
*/
|
|
|
|
// Initialization for GLOBAL semaphore creation (named)
|
|
//
|
|
RtlInitString (&ObjName, GLOBALSEMNAME);
|
|
Status = RtlAnsiStringToUnicodeString (&UnicodeName, &ObjName, TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"RtlAnsiStringToUnicodeString failed - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
InitializeObjectAttributes (&ObjAttributes,
|
|
&UnicodeName,
|
|
OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
&SecDescriptor);
|
|
|
|
// Create GLOBAL semaphore
|
|
//
|
|
Status = NtCreateSemaphore (&hGlobalSem,
|
|
SEMAPHORE_QUERY_STATE |
|
|
SEMAPHORE_MODIFY_STATE |
|
|
SYNCHRONIZE,
|
|
&ObjAttributes,
|
|
1L,
|
|
1L);
|
|
|
|
RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"GLOBAL semaphore creation falied - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
/*
|
|
***
|
|
*/
|
|
|
|
// Create LOCAL semaphore (not named - only for this process context)
|
|
//
|
|
Status = NtCreateSemaphore (&hLocalSem,
|
|
SEMAPHORE_QUERY_STATE |
|
|
SEMAPHORE_MODIFY_STATE |
|
|
SYNCHRONIZE,
|
|
NULL,
|
|
1L,
|
|
1L);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"LOCAL semaphore creation falied - 0x%lx\n",
|
|
Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
/*
|
|
***
|
|
*/
|
|
|
|
// Initialize for allocating shared memory
|
|
//
|
|
RtlInitString(&ObjName, SHAREDNAME);
|
|
Status = RtlAnsiStringToUnicodeString(&UnicodeName, &ObjName, TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"RtlAnsiStringToUnicodeString() failed - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
InitializeObjectAttributes(&ObjAttributes,
|
|
&UnicodeName,
|
|
OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
&SecDescriptor);
|
|
|
|
AllocationSize.HighPart = 0;
|
|
AllocationSize.LowPart = PAGE_SIZE;
|
|
|
|
// Create a read-write section
|
|
//
|
|
Status = NtCreateSection(&hSharedSec,
|
|
SECTION_MAP_READ | SECTION_MAP_WRITE,
|
|
&ObjAttributes,
|
|
&AllocationSize,
|
|
PAGE_READWRITE,
|
|
SEC_RESERVE,
|
|
NULL);
|
|
RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"NtCreateSection() failed - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
ulViewSize = AllocationSize.LowPart;
|
|
pulShared = NULL;
|
|
|
|
// Map the section - commit all
|
|
//
|
|
Status = NtMapViewOfSection (hSharedSec,
|
|
NtCurrentProcess(),
|
|
(PVOID *)&pulShared,
|
|
0L,
|
|
PAGE_SIZE,
|
|
NULL,
|
|
&ulViewSize,
|
|
ViewUnmap,
|
|
0L,
|
|
PAGE_READWRITE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"NtMapViewOfSection() failed - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
*pulShared = 0L;
|
|
|
|
/*
|
|
***
|
|
*/
|
|
|
|
// Find list of dlls that need to be patched..
|
|
//
|
|
|
|
#if 0
|
|
RtlInitString(&ObjName, WSTINIFILE);
|
|
Status = RtlAnsiStringToUnicodeString(&UnicodeName, &ObjName, TRUE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"RtlAnsiStringToUnicodeString() failed - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
InitializeObjectAttributes (&ObjAttributes,
|
|
&UnicodeName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
&SecDescriptor);
|
|
|
|
Status = NtOpenFile(&hIniFile, // DLL patch file handle
|
|
GENERIC_READ | SYNCHRONIZE, // Desired access
|
|
&ObjAttributes, // Object attributes
|
|
&iostatus, // Completion status
|
|
FILE_SHARE_READ, // Read share access
|
|
FILE_SEQUENTIAL_ONLY | // Open option
|
|
FILE_SYNCHRONOUS_IO_NONALERT);
|
|
|
|
RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"Error openning %s - 0x%lx\n", WSTINIFILE, Status));
|
|
return (FALSE);
|
|
}
|
|
#endif
|
|
|
|
|
|
hIniFile = CreateFile (
|
|
WSTINIFILE, // The filename
|
|
GENERIC_READ, // Desired access
|
|
FILE_SHARE_READ, // Shared Access
|
|
NULL, // Security Access
|
|
OPEN_EXISTING, // Read share access
|
|
FILE_ATTRIBUTE_NORMAL, // Open option
|
|
NULL); // No template file
|
|
|
|
if (hIniFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"Error openning %s - 0x%lx\n", WSTINIFILE, GetLastError()));
|
|
return (FALSE);
|
|
}
|
|
|
|
Status = NtReadFile(hIniFile, // DLL patch file handle
|
|
0L, // Event - optional
|
|
NULL, // Completion routine - optional
|
|
NULL, // Completion routine argument - optional
|
|
&iostatus, // Completion status
|
|
(PVOID)achPatchBuffer, // Buffer to receive data
|
|
PATCHFILESZ, // Bytes to read
|
|
&liOffset, // Byte offset - optional
|
|
0L); // Target process - optional
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"Error reading %s - 0x%lx\n", WSTINIFILE, Status));
|
|
return (FALSE);
|
|
}
|
|
else if (iostatus.Information >= PATCHFILESZ)
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"DLL patch buffer too small (%lu)\n", PATCHFILESZ));
|
|
return (FALSE);
|
|
}
|
|
else
|
|
{
|
|
achPatchBuffer [iostatus.Information] = '\0';
|
|
_strupr (achPatchBuffer);
|
|
|
|
if ( pchPatchExes = strstr (achPatchBuffer, PATCHEXELIST) )
|
|
{
|
|
if ( pchPatchImports = strstr (pchPatchExes, PATCHIMPORTLIST) )
|
|
{
|
|
*(pchPatchImports-1) = '\0';
|
|
if ( pchTimeInterval = strstr (pchPatchImports, TIMEINTERVALIST) )
|
|
{
|
|
*(pchTimeInterval-1) = '\0';
|
|
}
|
|
else
|
|
{
|
|
pchTimeInterval = "";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pchPatchImports = "";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pchPatchExes = "";
|
|
}
|
|
}
|
|
|
|
NtClose (hIniFile);
|
|
|
|
SdPrint (("WST: WstDllInitializations() - Patching info:\n"));
|
|
SdPrint (("WST: -- %s\n", pchPatchExes));
|
|
SdPrint (("WST: -- %s\n", pchPatchImports));
|
|
SdPrint (("WST: -- %s\n", pchPatchCallers));
|
|
SdPrint (("WST: -- %s\n", pchTimeInterval));
|
|
|
|
|
|
/*
|
|
***
|
|
*/
|
|
|
|
// Initialize for allocating global storage for WSPs
|
|
//
|
|
_ultoa ((ULONG)pteb->ClientId.UniqueProcess, atchProfObjsName+75, 10);
|
|
_ultoa ((ULONG)pteb->ClientId.UniqueThread, atchProfObjsName+95, 10);
|
|
strcat (atchProfObjsName, atchProfObjsName+75);
|
|
strcat (atchProfObjsName, atchProfObjsName+95);
|
|
|
|
SdPrint (("WST: DoDllInitializations() - %s\n", atchProfObjsName));
|
|
|
|
RtlInitString(&ObjName, atchProfObjsName);
|
|
Status = RtlAnsiStringToUnicodeString(&UnicodeName, &ObjName, TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"RtlAnsiStringToUnicodeString() failed - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
InitializeObjectAttributes (&ObjAttributes,
|
|
&UnicodeName,
|
|
OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
&SecDescriptor);
|
|
|
|
AllocationSize.HighPart = 0;
|
|
AllocationSize.LowPart = MEMSIZE;
|
|
|
|
// Create a read-write section
|
|
//
|
|
Status =NtCreateSection(&hWspSec,
|
|
SECTION_MAP_READ | SECTION_MAP_WRITE,
|
|
&ObjAttributes,
|
|
&AllocationSize,
|
|
PAGE_READWRITE,
|
|
SEC_RESERVE,
|
|
NULL);
|
|
|
|
RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"NtCreateSection() failed - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
ulViewSize = AllocationSize.LowPart;
|
|
pImg = &aImg[0];
|
|
pImg->pWsp = NULL;
|
|
|
|
// Map the section - commit the first 4 * COMMIT_SIZE pages
|
|
//
|
|
Status = NtMapViewOfSection(hWspSec,
|
|
NtCurrentProcess(),
|
|
(PVOID *)&(pImg->pWsp),
|
|
0L,
|
|
COMMIT_SIZE * 4,
|
|
NULL,
|
|
&ulViewSize,
|
|
ViewUnmap,
|
|
0L,
|
|
PAGE_READWRITE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"NtMapViewOfSection() failed - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
try // EXCEPT - to handle access violation exception.
|
|
{
|
|
//
|
|
// Locate all the executables/DLLs in the address and get their symbols
|
|
//
|
|
iPatchCnt = 0;
|
|
iImgCnt = 0;
|
|
Peb = NtCurrentPeb();
|
|
Next = Peb->Ldr->InMemoryOrderModuleList.Flink;
|
|
|
|
while ( Next != &Peb->Ldr->InMemoryOrderModuleList)
|
|
{
|
|
LdrDataTableEntry =
|
|
(PLDR_DATA_TABLE_ENTRY)
|
|
(CONTAINING_RECORD(Next,LDR_DATA_TABLE_ENTRY,InMemoryOrderLinks));
|
|
|
|
ImageBase = LdrDataTableEntry->DllBase;
|
|
if ( Peb->ImageBaseAddress == ImageBase )
|
|
{
|
|
|
|
RtlUnicodeStringToAnsiString (&ImageStringName,
|
|
&LdrDataTableEntry->BaseDllName,
|
|
TRUE);
|
|
ImageName = ImageStringName.Buffer;
|
|
pszBaseAppImageName = ImageStringName.Buffer;
|
|
|
|
RtlUnicodeStringToAnsiString (&ImageStringName,
|
|
&LdrDataTableEntry->FullDllName,
|
|
TRUE);
|
|
pszFullAppImageName = ImageStringName.Buffer;
|
|
//
|
|
// Skip the object directory name (if any)
|
|
//
|
|
if ( (pszFullAppImageName = strchr(pszFullAppImageName, ':')) )
|
|
{
|
|
pszFullAppImageName--;
|
|
}
|
|
else
|
|
{
|
|
pszFullAppImageName = pszBaseAppImageName;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ExportDirectory =
|
|
(PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData (
|
|
ImageBase,
|
|
TRUE,
|
|
IMAGE_DIRECTORY_ENTRY_EXPORT,
|
|
&ExportSize);
|
|
|
|
ImageName = (PSZ)((ULONG)ImageBase + ExportDirectory->Name);
|
|
}
|
|
|
|
pImageNtHeader = RtlImageNtHeader (ImageBase);
|
|
|
|
_strupr (strcpy (achTmpImageName, ImageName));
|
|
pchEntry = strstr (pchPatchExes, achTmpImageName);
|
|
if (pchEntry)
|
|
{
|
|
if (*(pchEntry-1) == ';')
|
|
{
|
|
pchEntry = NULL;
|
|
}
|
|
}
|
|
|
|
if ( strcmp (achTmpImageName, WSTDLL) )
|
|
{
|
|
if ( (iImgCnt == 0) && pchEntry )
|
|
{
|
|
fPatchImage = TRUE;
|
|
//
|
|
// Change protection of all the sections to read/write
|
|
//
|
|
NumberOfSections = pImageNtHeader->FileHeader.NumberOfSections;
|
|
pSections = (PIMAGE_SECTION_HEADER)((ULONG)pImageNtHeader
|
|
+ sizeof(IMAGE_NT_HEADERS));
|
|
for ( i=0; i<NumberOfSections; i++, pSections++)
|
|
{
|
|
|
|
SdPrint (("WST: WstDoDllInitializations() - Modifying "
|
|
"protection on %s section header\n",
|
|
pSections->Name));
|
|
|
|
pSectionTmp = pSections;
|
|
ulRegionSize = sizeof(IMAGE_SECTION_HEADER);
|
|
Status = NtProtectVirtualMemory(
|
|
NtCurrentProcess(),
|
|
&pSectionTmp,
|
|
&ulRegionSize,
|
|
PAGE_READWRITE,
|
|
&ulOldProtect
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDoDllInitializations() - "
|
|
"NtProtectVirtualMemory() set failed"
|
|
" - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
pSections->Characteristics &=
|
|
~(IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE);
|
|
pSections->Characteristics |=
|
|
(IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE);
|
|
|
|
pSectionTmp = pSections;
|
|
ulRegionSize = sizeof(IMAGE_SECTION_HEADER);
|
|
Status = NtProtectVirtualMemory(
|
|
NtCurrentProcess(),
|
|
&pSectionTmp,
|
|
&ulRegionSize,
|
|
ulOldProtect,
|
|
&ulOldProtect
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDoDllInitializations() - "
|
|
"NtProtectVirtualMemory() reset failed"
|
|
" - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fPatchImage)
|
|
{
|
|
//
|
|
// Locate the code range.
|
|
//
|
|
fFoundSymbols = FALSE;
|
|
pImageDbgInfo = MapDebugInformation (0L,
|
|
ImageName,
|
|
lpSymbolSearchPath,
|
|
(DWORD)ImageBase);
|
|
|
|
if (pImageDbgInfo == NULL)
|
|
{
|
|
IdPrint (("WST: DoDllInitializations() - "
|
|
"No symbols for %s\n", ImageName));
|
|
}
|
|
else if ( pImageDbgInfo->CoffSymbols == NULL )
|
|
{
|
|
IdPrint (("WST: DoDllInitializations() - "
|
|
"No coff symbols for %s\n", ImageName));
|
|
}
|
|
else
|
|
{
|
|
DebugInfo = pImageDbgInfo->CoffSymbols;
|
|
fFoundSymbols = TRUE;
|
|
}
|
|
|
|
pImg->pszName = Wststrdup (ImageName);
|
|
pImg->ulCodeStart = 0L;
|
|
pImg->ulCodeEnd = 0L;
|
|
pImg->iSymCnt = 0;
|
|
|
|
if (fFoundSymbols)
|
|
{
|
|
if (DebugInfo->LvaToFirstSymbol == 0L)
|
|
{
|
|
IdPrint (("WST: WstDllInitializations() - "
|
|
"Virtual Address to coff symbols not set for %s\n",
|
|
ImageName));
|
|
}
|
|
else
|
|
{
|
|
CodeLength = (DebugInfo->RvaToLastByteOfCode -
|
|
DebugInfo->RvaToFirstByteOfCode) - 1;
|
|
pImg->ulCodeStart = (ULONG)ImageBase +
|
|
DebugInfo->RvaToFirstByteOfCode;
|
|
pImg->ulCodeEnd = pImg->ulCodeStart + CodeLength;
|
|
WstGetSymbols (pImg, ImageName, ImageBase, CodeLength,
|
|
DebugInfo);
|
|
}
|
|
} // if fFoundSymbols
|
|
|
|
IdPrint (("WST: WstDllInitializations() - @ 0x%08lx "
|
|
"image #%d = %s ", (ULONG)ImageBase, iImgCnt,
|
|
ImageName));
|
|
//
|
|
// Do we need to patch this image?
|
|
//
|
|
//if ( WstPatchDll (pchPatchImports, pchPatchCallers,
|
|
// achTmpImageName, ImageBase) )
|
|
// {
|
|
// iPatchCnt++;
|
|
// }
|
|
pImg->pWsp[pImg->iSymCnt].pszSymbol = UNKNOWN_SYM;
|
|
pImg->pWsp[pImg->iSymCnt].ulFuncAddr = UNKNOWN_ADDR;
|
|
(pImg->iSymCnt)++;
|
|
|
|
//
|
|
// Set index table.
|
|
//
|
|
pImg->pNdx = (PNDX)(pImg->pWsp + pImg->iSymCnt);
|
|
for (i=0; i<pImg->iSymCnt; i++)
|
|
{
|
|
pImg->pNdx[i].pszSymbol = pImg->pWsp[i].pszSymbol;
|
|
pImg->pNdx[i].ulIndex = i;
|
|
}
|
|
|
|
//
|
|
// Set wsi.
|
|
//
|
|
pImg->pulWsi = pImg->pulWsiNxt = (PULONG)
|
|
(pImg->pNdx + pImg->iSymCnt);
|
|
RtlZeroMemory (pImg->pulWsi,
|
|
pImg->iSymCnt * MAX_SNAPS * sizeof(ULONG));
|
|
|
|
|
|
//
|
|
// Set wsp.
|
|
//
|
|
pImg->pulWsp = (PULONG)(pImg->pulWsi +
|
|
(pImg->iSymCnt * MAX_SNAPS));
|
|
RtlZeroMemory (pImg->pulWsp,
|
|
pImg->iSymCnt * MAX_SNAPS * sizeof(ULONG));
|
|
|
|
//
|
|
// Sort wsp & set code lengths
|
|
//
|
|
WstSort (pImg->pWsp, 0, pImg->iSymCnt-1);
|
|
for (i=0; i<pImg->iSymCnt-2; i++)
|
|
{
|
|
pImg->pWsp[i].ulCodeLength = pImg->pWsp[i+1].ulFuncAddr -
|
|
pImg->pWsp[i].ulFuncAddr;
|
|
}
|
|
//
|
|
// Last symbol length is set to be the same as length of
|
|
// (n-1)th symbol
|
|
//
|
|
if (i)
|
|
{
|
|
pImg->pWsp[i].ulCodeLength = pImg->pWsp[i-1].ulCodeLength;
|
|
}
|
|
//
|
|
// Handle case of having only one symbol (??? symbol)
|
|
//
|
|
else
|
|
{
|
|
pImg->pWsp[0].ulCodeLength = 0L;
|
|
}
|
|
|
|
//
|
|
// Sort index table
|
|
//
|
|
WstPszSort (pImg->pNdx, 0, pImg->iSymCnt-1);
|
|
|
|
SdPrint(("WST: (%ld) WSP=0x%08lx - NDX=0x%08lx "
|
|
"- wsi=0x%08lx - wsp=0x%08lx\n", pImg->iSymCnt,
|
|
pImg->pWsp, pImg->pNdx, pImg->pulWsi, pImg->pulWsp));
|
|
|
|
//
|
|
// Setup next pWsp
|
|
//
|
|
(pImg+1)->pWsp = (PWSP)(pImg->pulWsp +
|
|
(pImg->iSymCnt * MAX_SNAPS));
|
|
iImgCnt++;
|
|
pImg++;
|
|
|
|
if (iImgCnt == MAX_IMAGES)
|
|
{
|
|
KdPrint(("WST: WstDllInitialization() - Not enough "
|
|
"space allocated for all images\n"));
|
|
return (FALSE);
|
|
}
|
|
} // if fPatchImage
|
|
}
|
|
|
|
Next = Next->Flink;
|
|
} // if (Next != &Peb->Ldr->InMemoryOrderModuleList)
|
|
} // try
|
|
//
|
|
// + : transfer control to the handler (EXCEPTION_EXECUTE_HANDLER)
|
|
// 0 : continue search (EXCEPTION_CONTINUE_SEARCH)
|
|
// - : dismiss exception & continue (EXCEPTION_CONTINUE_EXECUTION)
|
|
//
|
|
except ( WstAccessXcptFilter (GetExceptionCode(), GetExceptionInformation()) )
|
|
{
|
|
//
|
|
// Should never get here since filter never returns
|
|
// EXCEPTION_EXECUTE_HANDLER.
|
|
//
|
|
KdPrint (("WST: WstDllInitializations() - *LOGIC ERROR* - "
|
|
"Inside the EXCEPT: (xcpt=0x%lx)\n", GetExceptionCode()));
|
|
}
|
|
/*
|
|
***
|
|
*/
|
|
|
|
//
|
|
// Get the frequency
|
|
//
|
|
NtQueryPerformanceCounter (&liStart, &liFreq);
|
|
|
|
iTimeInterval = atoi (pchTimeInterval+sizeof(TIMEINTERVALIST)+1);
|
|
if ( iTimeInterval == 0 )
|
|
{
|
|
//
|
|
// Use the default value
|
|
//
|
|
iTimeInterval = TIMESEG;
|
|
}
|
|
ulSegSize = iTimeInterval * (liFreq.LowPart / 1000);
|
|
|
|
#ifdef BATCHING
|
|
fBatch = WstOpenBatchFile();
|
|
#endif
|
|
|
|
SdPrint (("WST: Time interval: Millisecs=%d Ticks=%lu\n",
|
|
iTimeInterval, ulSegSize));
|
|
|
|
if (fPatchImage)
|
|
{
|
|
|
|
// Initialization for DONE event creation
|
|
//
|
|
RtlInitString (&ObjName, DONEEVENTNAME);
|
|
Status = RtlAnsiStringToUnicodeString (&UnicodeName, &ObjName, TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"RtlAnsiStringToUnicodeString failed - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
InitializeObjectAttributes (&ObjAttributes,
|
|
&UnicodeName,
|
|
OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
&SecDescriptor);
|
|
// Create DONE event
|
|
//
|
|
Status = NtCreateEvent (&hDoneEvent,
|
|
EVENT_QUERY_STATE |
|
|
EVENT_MODIFY_STATE |
|
|
SYNCHRONIZE,
|
|
&ObjAttributes,
|
|
NotificationEvent,
|
|
TRUE);
|
|
RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"DONE event creation falied - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
// Initialization for DUMP event creation
|
|
//
|
|
RtlInitString (&ObjName, DUMPEVENTNAME);
|
|
Status = RtlAnsiStringToUnicodeString (&UnicodeName, &ObjName, TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"RtlAnsiStringToUnicodeString failed - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
InitializeObjectAttributes (&ObjAttributes,
|
|
&UnicodeName,
|
|
OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
&SecDescriptor);
|
|
// Create DUMP event
|
|
//
|
|
Status = NtCreateEvent (&hDumpEvent,
|
|
EVENT_QUERY_STATE |
|
|
EVENT_MODIFY_STATE |
|
|
SYNCHRONIZE,
|
|
&ObjAttributes,
|
|
NotificationEvent,
|
|
FALSE);
|
|
RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"DUMP event creation falied - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
// Initialization for CLEAR event creation
|
|
//
|
|
RtlInitString (&ObjName, CLEAREVENTNAME);
|
|
Status = RtlAnsiStringToUnicodeString (&UnicodeName, &ObjName, TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"RtlAnsiStringToUnicodeString failed - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
InitializeObjectAttributes (&ObjAttributes,
|
|
&UnicodeName,
|
|
OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
&SecDescriptor);
|
|
|
|
// Create CLEAR event
|
|
//
|
|
Status = NtCreateEvent (&hClearEvent,
|
|
EVENT_QUERY_STATE |
|
|
EVENT_MODIFY_STATE |
|
|
SYNCHRONIZE,
|
|
&ObjAttributes,
|
|
NotificationEvent,
|
|
FALSE);
|
|
RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"CLEAR event creation falied - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
// Initialization for PAUSE event creation
|
|
//
|
|
RtlInitString (&ObjName, PAUSEEVENTNAME);
|
|
Status = RtlAnsiStringToUnicodeString (&UnicodeName, &ObjName, TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"RtlAnsiStringToUnicodeString failed - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
InitializeObjectAttributes (&ObjAttributes,
|
|
&UnicodeName,
|
|
OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
&SecDescriptor);
|
|
// Create PAUSE event
|
|
//
|
|
Status = NtCreateEvent (&hPauseEvent,
|
|
EVENT_QUERY_STATE |
|
|
EVENT_MODIFY_STATE |
|
|
SYNCHRONIZE,
|
|
&ObjAttributes,
|
|
NotificationEvent,
|
|
FALSE);
|
|
RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"PAUSE event creation falied - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Calculate excess overhead for WstRecordInfo
|
|
//
|
|
liOverhead.HighPart = 0L;
|
|
liOverhead.LowPart = 0xFFFFFFFF;
|
|
for (i=0; i < NUM_ITERATIONS; i++)
|
|
{
|
|
NtQueryPerformanceCounter (&liStartTicks, NULL);
|
|
//
|
|
WSTUSAGE(NtCurrentTeb()) = 0L;
|
|
|
|
#ifdef i386
|
|
_asm
|
|
{
|
|
push edi
|
|
mov edi, dword ptr [ebp+4]
|
|
mov dwAddr, edi
|
|
mov edi, dword ptr [ebp+8]
|
|
mov dwPrevAddr, edi
|
|
pop edi
|
|
}
|
|
#endif
|
|
|
|
#ifdef MIPS
|
|
{
|
|
ULONG ulRegS7; // s7 = address where RealRetAddr is saved on stack
|
|
ULONG ulRegS6; // s6 to save $v0
|
|
ULONG ulRegS8; // s8 to save $v1
|
|
ULONG ulRegA0; // a0
|
|
ULONG ulRegA1; // a1
|
|
ULONG ulRegA2; // a2
|
|
ULONG ulRegA3; // a3
|
|
ULONG ulRegT9; // t9 = caller's actual return address
|
|
// passed for CAP, but we must preserve it
|
|
PULONG UNALIGNED pulAddr;
|
|
|
|
_asm (".set noreorder ");
|
|
|
|
_asm ("or %t0, %a0, $0 ");
|
|
_asm ("sw %t0, 0(%0)", &ulRegA0 ); // Save org a0
|
|
_asm ("sw %a1, 0(%0)", &ulRegA1 ); // Save org a1
|
|
_asm ("sw %a2, 0(%0)", &ulRegA2 ); // Save org a2
|
|
_asm ("sw %a3, 0(%0)", &ulRegA3 ); // Save org a3
|
|
_asm ("sw %s6, 0(%0)", &ulRegS6 ); // Save org s6
|
|
_asm ("sw %s7, 0(%0)", &ulRegS7 ); // Save org s7
|
|
_asm ("sw %s8, 0(%0)", &ulRegS8 ); // Save org s8
|
|
_asm ("sw %t9, 0(%0)", &ulRegT9 ); // Save org t9
|
|
|
|
_asm (".set reorder ");
|
|
|
|
dwPrevAddr = NO_CALLER;
|
|
|
|
_asm (".set noreorder ");
|
|
_asm ("sw $31, (%0)", &dwAddr);
|
|
_asm (".set reorder ");
|
|
|
|
pulAddr = (PULONG UNALIGNED) dwAddr;
|
|
pulAddr -= 1;
|
|
|
|
if ((*pulAddr == 0x24001804) &&
|
|
(*(pulAddr + 6) == 0xfefe55aa) )
|
|
{
|
|
dwAddr = *(pulAddr + 2) & 0x0000ffff;
|
|
dwAddr = dwAddr << 16;
|
|
dwAddr |= *(pulAddr + 3) & 0x0000ffff;
|
|
// get the real return address
|
|
_asm (".set noreorder ");
|
|
_asm ("andi %t0, %t0, 0x00 "); // clear t0
|
|
//*_asm ("addiu %t0, %t0, STKSIZE "); // $t0 = offset from current sp to realRA
|
|
_asm ("addiu %t0, %t0, 0x48 "); // BUGBUG
|
|
_asm ("addiu %t0, %t0, 0x04 "); // this is where we store ra in
|
|
// our patched stub
|
|
_asm ("addu %s7, %sp, %t0 "); // $s7 = Adr of RealRetAddr
|
|
_asm ("lw %t0, (%s7) "); // $t0 = RealRetAddr
|
|
_asm ("sw %t0, (%0)", &dwPrevAddr);
|
|
_asm (".set reorder ");
|
|
|
|
}
|
|
}
|
|
#endif // ifdef MIPS
|
|
#ifdef ALPHA
|
|
{
|
|
PULONG UNALIGNED pulAddr;
|
|
DWORDLONG SaveRegisters [64] ;
|
|
|
|
SaveAllRegs (SaveRegisters);
|
|
// GetCalCaller (&dwAddr, 0x0220);
|
|
|
|
pulAddr = (PULONG UNALIGNED) dwAddr;
|
|
pulAddr -= 1;
|
|
|
|
RestoreAllRegs (SaveRegisters);
|
|
}
|
|
#else
|
|
SaveAllRegs ();
|
|
#if defined(_PPC_)
|
|
GetCalCaller();
|
|
#endif
|
|
RestoreAllRegs ();
|
|
#endif
|
|
WSTUSAGE(NtCurrentTeb()) = 0L;
|
|
Status = NtWaitForSingleObject (hLocalSem, FALSE, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitilizations() - "
|
|
"Wait for LOCAL semaphore failed - 0x%lx\n", Status));
|
|
}
|
|
liStart.QuadPart = liStart.QuadPart - liStart.QuadPart ;
|
|
liStart.QuadPart = liStart.QuadPart + liStart.QuadPart ;
|
|
liStart.QuadPart = liStart.QuadPart + liStart.QuadPart ;
|
|
|
|
Status = NtReleaseSemaphore (hLocalSem, 1, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllInitializations() - "
|
|
"Error releasing LOCAL semaphore - 0x%lx\n", Status));
|
|
}
|
|
WSTUSAGE(NtCurrentTeb()) = 0L;
|
|
//
|
|
NtQueryPerformanceCounter (&liEndTicks, NULL);
|
|
ulElapsed = liEndTicks.LowPart - liStartTicks.LowPart;
|
|
if (ulElapsed < liOverhead.LowPart)
|
|
{
|
|
liOverhead.LowPart = ulElapsed;
|
|
}
|
|
}
|
|
SdPrint (("WST: WstDllInitializations() - WstRecordInfo() overhead = %lu\n",
|
|
liOverhead.LowPart));
|
|
|
|
// Start monitor threads
|
|
//
|
|
hDumpThread = CreateThread (
|
|
NULL, // no security attribute
|
|
(DWORD)1024L, // initial stack size
|
|
(LPTHREAD_START_ROUTINE)WstDumpThread, // thread starting address
|
|
NULL, // no argument for the thread
|
|
(DWORD)0, // no creation flag
|
|
&DumpClientId); // address for thread id
|
|
hClearThread = CreateThread (
|
|
NULL, // no security attribute
|
|
(DWORD)1024L, // initial stack size
|
|
(LPTHREAD_START_ROUTINE)WstClearThread, // thread starting address
|
|
NULL, // no argument for the thread
|
|
(DWORD)0, // no creation flag
|
|
&ClearClientId); // address for thread id
|
|
hPauseThread = CreateThread (
|
|
NULL, // no security attribute
|
|
(DWORD)1024L, // initial stack size
|
|
(LPTHREAD_START_ROUTINE)WstPauseThread, // thread starting address
|
|
NULL, // no argument for the thread
|
|
(DWORD)0, // no creation flag
|
|
&PauseClientId); // address for thread id
|
|
|
|
NtQueryPerformanceCounter (&liStart, NULL);
|
|
WstState = STARTED;
|
|
}
|
|
|
|
return (TRUE);
|
|
|
|
} /* WstDllInitializations () */
|
|
|
|
|
|
|
|
|
|
|
|
/****************************** _ p e n t e r ******************************
|
|
*
|
|
* _penter() / _mcount() -
|
|
* This is the main profiling routine. This routine is called
|
|
* upon entry of each routine in the profiling DLL/EXE.
|
|
*
|
|
* ENTRY -none-
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN -none-
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* Compiling apps with -Gp option trashs EAX initially.
|
|
*
|
|
*/
|
|
#ifdef i386
|
|
void _CRTAPI1 _penter ()
|
|
#elif defined(MIPS)
|
|
void penter ()
|
|
#elif defined(ALPHA) || defined(_PPC_)
|
|
void c_penter (ULONG dwPrevious, ULONG dwCurrent)
|
|
#endif
|
|
{
|
|
DWORD dwAddr;
|
|
DWORD dwPrevAddr;
|
|
ULONG ulInWst ;
|
|
#if defined(MIPS) || defined(ALPHA) || defined(_PPC)
|
|
PULONG UNALIGNED pulAddr;
|
|
#endif
|
|
|
|
#ifdef MIPS
|
|
ULONG ulRegS7; // s7 = address where RealRetAddr is saved on stack
|
|
ULONG ulRegS6; // s6 to save $v0
|
|
ULONG ulRegS8; // s8 to save $v1
|
|
ULONG ulRegA0; // a0
|
|
ULONG ulRegA1; // a1
|
|
ULONG ulRegA2; // a2
|
|
ULONG ulRegA3; // a3
|
|
ULONG ulRegT9; // t9 = Caller's return address
|
|
// Passed for CAP, but we need to preserve it
|
|
#endif
|
|
#ifdef ALPHA
|
|
DWORDLONG SaveRegisters [64];
|
|
SaveAllRegs(SaveRegisters) ;
|
|
#endif
|
|
|
|
#ifdef MIPS
|
|
_asm (".set noreorder ");
|
|
|
|
_asm ("or %t0, %a0, $0 ");
|
|
_asm ("sw %t0, 0(%0)", &ulRegA0 ); // Save org a0
|
|
_asm ("sw %a1, 0(%0)", &ulRegA1 ); // Save org a1
|
|
_asm ("sw %a2, 0(%0)", &ulRegA2 ); // Save org a2
|
|
_asm ("sw %a3, 0(%0)", &ulRegA3 ); // Save org a3
|
|
_asm ("sw %s6, 0(%0)", &ulRegS6 ); // Save org s6
|
|
_asm ("sw %s7, 0(%0)", &ulRegS7 ); // Save org s7
|
|
_asm ("sw %s8, 0(%0)", &ulRegS8 ); // Save org s8
|
|
_asm ("sw %t9, 0(%0)", &ulRegT9 ); // Save t9
|
|
|
|
_asm (".set reorder ");
|
|
#endif MIPS
|
|
|
|
dwAddr = 0L;
|
|
dwPrevAddr = 0L;
|
|
ulInWst = WSTUSAGE(NtCurrentTeb());
|
|
|
|
if (WstState != STARTED)
|
|
{
|
|
goto Exit0;
|
|
}
|
|
else if (ulInWst)
|
|
{
|
|
goto Exit0;
|
|
}
|
|
|
|
|
|
//
|
|
// Put the address of the calling function into var dwAddr
|
|
//
|
|
#ifdef i386
|
|
_asm
|
|
{
|
|
push edi
|
|
mov edi, dword ptr [ebp+4]
|
|
mov dwAddr, edi
|
|
mov edi, dword ptr [ebp+8]
|
|
mov dwPrevAddr, edi
|
|
pop edi
|
|
}
|
|
#endif
|
|
|
|
#ifdef MIPS
|
|
|
|
|
|
dwPrevAddr = NO_CALLER;
|
|
|
|
_asm (".set noreorder ");
|
|
_asm ("sw $31, (%0)", &dwAddr);
|
|
_asm (".set reorder ");
|
|
|
|
pulAddr = (PULONG UNALIGNED) dwAddr;
|
|
pulAddr -= 1;
|
|
|
|
if ((*pulAddr == 0x24001804) &&
|
|
(*(pulAddr + 6) == 0xfefe55aa) )
|
|
{
|
|
// this is the stub that we patched earlier
|
|
// get the address that we will go after the penter function
|
|
dwAddr = *(pulAddr + 2) & 0x0000ffff;
|
|
dwAddr = dwAddr << 16;
|
|
dwAddr |= *(pulAddr + 3) & 0x0000ffff;
|
|
|
|
// get the real return address
|
|
_asm (".set noreorder ");
|
|
_asm ("andi %t0, %t0, 0x00 "); // clear t0
|
|
//*_asm ("addiu %t0, %t0, STKSIZE "); // $t0 = offset from current sp to realRA
|
|
_asm ("addiu %t0, %t0, 0x48 "); // BUGBUG
|
|
_asm ("addiu %t0, %t0, 0x04 "); // this is where we store ra in
|
|
// our patched stub
|
|
_asm ("addu %s7, %sp, %t0 "); // $s7 = Adr of RealRetAddr
|
|
_asm ("lw %t0, (%s7) "); // $t0 = RealRetAddr
|
|
_asm ("sw %t0, (%0)", &dwPrevAddr);
|
|
_asm (".set reorder ");
|
|
|
|
}
|
|
#endif
|
|
|
|
#ifdef ALPHA
|
|
dwPrevAddr = NO_CALLER;
|
|
dwAddr = dwCurrent;
|
|
// GetCaller (&dwAddr, 0x0220); // FIXFIX StackSize
|
|
|
|
// now check if we are calling from the stub we created
|
|
pulAddr = (PULONG UNALIGNED) dwAddr;
|
|
pulAddr -= 1;
|
|
|
|
if (*(pulAddr) == 0x681b4000 &&
|
|
(*(pulAddr + 1) == 0xa75e0008) &&
|
|
(*(pulAddr + 8) == 0xfefe55aa) )
|
|
{
|
|
|
|
// get the address that we will go after the penter function
|
|
dwAddr = *(pulAddr + 4) & 0x0000ffff;
|
|
if (*(pulAddr + 5) & 0x00008000)
|
|
{
|
|
// fix the address since we have to add one when
|
|
// we created our stub code
|
|
dwAddr -= 1;
|
|
}
|
|
dwAddr = dwAddr << 16;
|
|
dwAddr |= *(pulAddr + 5) & 0x0000ffff;
|
|
|
|
// get the caller to the stub
|
|
dwPrevAddr = dwPrevious;
|
|
// GetStubCaller (&dwPrevAddr, 0x0220); // FIXFIX StackSize
|
|
}
|
|
|
|
|
|
#endif
|
|
#if defined(_PPC_)
|
|
dwAddr = dwCurrent;
|
|
dwPrevAddr = dwPrevious;
|
|
#endif
|
|
|
|
|
|
//
|
|
// Call WstRecordInfo for this API
|
|
//
|
|
#ifdef i386
|
|
SaveAllRegs ();
|
|
#endif
|
|
|
|
WstRecordInfo (dwAddr, dwPrevAddr);
|
|
|
|
#ifdef i386
|
|
RestoreAllRegs ();
|
|
#endif
|
|
|
|
|
|
Exit0:
|
|
|
|
#ifdef MIPS
|
|
_asm (".set noreorder ");
|
|
|
|
_asm ("lw %a1, (%0)", &ulRegA1 ); // restore org $a1 (2)
|
|
_asm ("lw %a2, (%0)", &ulRegA2 ); // restore org $a2 (2)
|
|
_asm ("lw %a3, (%0)", &ulRegA3 ); // restore org $a3 (2)
|
|
_asm ("lw %s6, (%0)", &ulRegS6 ); // restore org $s6 (2)
|
|
_asm ("lw %s7, (%0)", &ulRegS7 ); // restore org $s7 (2)
|
|
_asm ("lw %s8, (%0)", &ulRegS8 ); // restore org $s8 (2)
|
|
_asm ("lw %t9, (%0)", &ulRegT9 ); // restore org $t9 (2)
|
|
_asm ("lw %a0, (%0)", &ulRegA0 ); // restore org $a0 (2)
|
|
|
|
_asm (".set reorder ");
|
|
#endif
|
|
|
|
#ifdef ALPHA
|
|
RestoreAllRegs (SaveRegisters);
|
|
#endif
|
|
|
|
return;
|
|
} /* _penter() / _mcount()*/
|
|
|
|
#ifdef C6
|
|
void _CRTAPI1 _penter ()
|
|
#else
|
|
void _CRTAPI1 _mcount ()
|
|
#endif
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/************************* W s t R e c o r d I n f o ************************
|
|
*
|
|
* WstRecordInfo (dwAddress) -
|
|
*
|
|
* ENTRY dwAddress - Address of the routine just called
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN -none-
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
void WstRecordInfo (DWORD dwAddress, DWORD dwPrevAddress)
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
INT x;
|
|
INT i, iIndex;
|
|
PWSP pwspTmp;
|
|
LARGE_INTEGER liNow, liTmp;
|
|
LARGE_INTEGER liElapsed;
|
|
ULONG ulIndex;
|
|
CHAR *pszSym;
|
|
|
|
#ifdef BATCHING
|
|
CHAR szBatchBuf[128];
|
|
DWORD dwCache;
|
|
DWORD dwHits;
|
|
DWORD dwBatch;
|
|
IO_STATUS_BLOCK ioStatus;
|
|
#endif
|
|
|
|
|
|
WSTUSAGE(NtCurrentTeb()) = 1;
|
|
|
|
//
|
|
// Wait for the semaphore object to suspend execution of other threads
|
|
//
|
|
Status = NtWaitForSingleObject (hLocalSem, FALSE, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstRecordInfo() - "
|
|
"Wait for LOCAL semaphore failed - 0x%lx\n", Status));
|
|
}
|
|
|
|
NtQueryPerformanceCounter(&liNow, NULL);
|
|
liElapsed.QuadPart = liNow.QuadPart - liStart.QuadPart ;
|
|
|
|
|
|
// SdPrint(("WST: WstRecordInfo() - Elapsed time: %ld\n", liElapsed.LowPart));
|
|
|
|
//
|
|
// WstBSearch is a binary find function that will return the address of
|
|
// the wsp record we want
|
|
//
|
|
|
|
// SdPrint(("WST: WstRecordInfo() - Preparing for WstBSearch of 0x%lx\n",
|
|
// dwAddress-5));
|
|
|
|
pwspTmp = NULL;
|
|
for (i=0; i<iImgCnt; i++)
|
|
{
|
|
if ( (dwAddress >= aImg[i].ulCodeStart) &&
|
|
(dwAddress < aImg[i].ulCodeEnd) )
|
|
{
|
|
#ifdef i386
|
|
pwspTmp = WstBSearch(dwAddress-5, aImg[i].pWsp, aImg[i].iSymCnt);
|
|
if (!pwspTmp)
|
|
{
|
|
//
|
|
// Is this a patched address?
|
|
//
|
|
pwspTmp = WstBSearch(dwAddress, aImg[i].pWsp, aImg[i].iSymCnt);
|
|
if (!pwspTmp)
|
|
{
|
|
pwspTmp = WstBSearch(UNKNOWN_ADDR, aImg[i].pWsp, aImg[i].iSymCnt);
|
|
}
|
|
else
|
|
{
|
|
dwAddress = dwPrevAddress;
|
|
dwPrevAddress = 0L;
|
|
}
|
|
}
|
|
#else
|
|
// the following works for both MIPS and ALPHA
|
|
|
|
pwspTmp = WstBSearch(dwAddress, aImg[i].pWsp, aImg[i].iSymCnt);
|
|
if (!pwspTmp)
|
|
{
|
|
// symbol not found
|
|
pwspTmp = WstBSearch(UNKNOWN_ADDR, aImg[i].pWsp, aImg[i].iSymCnt);
|
|
}
|
|
else if (dwPrevAddress != NO_CALLER)
|
|
{
|
|
// this is a patched address, get the RealReturnAddress
|
|
dwAddress = dwPrevAddress;
|
|
dwPrevAddress = 0L;
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
iIndex = i;
|
|
|
|
if (pwspTmp)
|
|
{
|
|
pszSym = pwspTmp->pszSymbol;
|
|
|
|
if (dwPrevAddress == 0L)
|
|
{
|
|
//
|
|
// If it is a patched address, search for the caller
|
|
//
|
|
for (i=0; i<iImgCnt; i++)
|
|
{
|
|
if ( (dwAddress >= aImg[i].ulCodeStart) &&
|
|
(dwAddress < aImg[i].ulCodeEnd) )
|
|
{
|
|
ulIndex = WstPszBSearch (pwspTmp->pszSymbol,
|
|
aImg[i].pNdx,
|
|
aImg[i].iSymCnt);
|
|
|
|
pwspTmp = &aImg[i].pWsp[ulIndex];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// SdPrint(("WST: WstRecordInfo() - Or'ing %40s @ 0x%lx\n",
|
|
// pwspTmp->pszSymbol, pwspTmp->ulFuncAddr));
|
|
pwspTmp->ulBitString |= 1;
|
|
}
|
|
else
|
|
{
|
|
// SdPrint (("WST: WstRecordInfo() - Completely bogus addr = 0x%08lx\n",
|
|
// dwAddress));
|
|
}
|
|
|
|
if (liElapsed.LowPart >= ulSegSize)
|
|
{
|
|
SdPrint(("WST: WstRecordInfo() - ulSegSize expired; "
|
|
"Preparing to shift the BitStrings\n"));
|
|
|
|
if (ulBitCount < 31)
|
|
{
|
|
for (i=0; i<iImgCnt; i++)
|
|
{
|
|
for (x=0; x < aImg[i].iSymCnt ; x++ )
|
|
{
|
|
aImg[i].pWsp[x].ulBitString <<= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
liElapsed.LowPart = 0L;
|
|
ulBitCount++;
|
|
NtQueryPerformanceCounter(&liStart, NULL);
|
|
liNow = liStart;
|
|
|
|
if(ulBitCount == 32)
|
|
{
|
|
SdPrint(("WST: WstRecordInfo() - Dump Bit Strings\n"));
|
|
for (i=0; i<iImgCnt; i++)
|
|
{
|
|
for (x=0; x < aImg[i].iSymCnt ; x++ )
|
|
{
|
|
aImg[i].pulWsiNxt[x] = aImg[i].pWsp[x].ulBitString;
|
|
aImg[i].pWsp[x].ulBitString = 0L;
|
|
}
|
|
aImg[i].pulWsiNxt += aImg[i].iSymCnt;
|
|
}
|
|
ulSnaps++;
|
|
ulBitCount = 0;
|
|
if (ulSnaps == MAX_SNAPS)
|
|
{
|
|
KdPrint (("WST: WstRecordInfo() - No more space available"
|
|
" for next time snap data!\n"));
|
|
//
|
|
// Dump and clear the data
|
|
//
|
|
WstDataOverFlow();
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef BATCHING
|
|
//
|
|
// The following code will get the current batching information
|
|
// if the DLL was compiled with the BATCHING variable set. You
|
|
// should not have this variable set if you are tuning GDI.
|
|
//
|
|
if(fBatch)
|
|
{
|
|
GdiGetCsInfo(&dwHits, &dwBatch, &dwCache);
|
|
|
|
if(dwHits)
|
|
GdiResetCsInfo();
|
|
|
|
if(dwBatch == 10)
|
|
GdiResetCsInfo();
|
|
|
|
while(*(pszSym++) != '_');
|
|
|
|
sprintf(szBatchBuf, "%s:%s,%ld,%ld,%ld\n",
|
|
aImg[iIndex].pszName, pszSym, dwHits, dwBatch, dwCache);
|
|
Status = NtWriteFile(hBatchFile,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&ioStatus,
|
|
szBatchBuf,
|
|
strlen(szBatchBuf),
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstRecodInfo() - "
|
|
"NtWriteFile() failed on hBatchFile - 0x%lx\n", Status));
|
|
}
|
|
}//Batching info
|
|
#endif
|
|
|
|
|
|
//
|
|
// We call NtQueryPerformanceCounter here to account for the overhead
|
|
// required for doing our work
|
|
//
|
|
NtQueryPerformanceCounter(&liTmp, NULL);
|
|
liElapsed.QuadPart = liTmp.QuadPart - liNow.QuadPart ;
|
|
liStart.QuadPart = liStart.QuadPart + liElapsed.QuadPart ;
|
|
liStart.QuadPart = liStart.QuadPart + liOverhead.QuadPart ;
|
|
|
|
//
|
|
// Release semaphore to continue execution of other threads
|
|
//
|
|
Status = NtReleaseSemaphore (hLocalSem, 1, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstRecordInfo () - "
|
|
"Error releasing LOCAL semaphore - 0x%lx\n", Status));
|
|
}
|
|
|
|
WSTUSAGE(NtCurrentTeb()) = 0L;
|
|
|
|
} /* WstRecordInfo () */
|
|
|
|
|
|
|
|
|
|
|
|
/******************** W s t C l e a r B i t S t r i n g *********************
|
|
*
|
|
* Function: WstClearBitStrings (pImg)
|
|
*
|
|
* Purpose: This function clears the BitString for each symbol.
|
|
*
|
|
* Parameters: pImg - Current image data structure pointer
|
|
*
|
|
* Returns: -none-
|
|
*
|
|
* History: 8-3-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
void WstClearBitStrings (PIMG pImg)
|
|
{
|
|
UINT uiLshft = 0;
|
|
INT x;
|
|
|
|
|
|
//
|
|
// Since we are completed with the profile, we need to create a
|
|
// DWORD out of the balance of the bitString. We do this by left
|
|
// shifting the bitstring by difference between the bitCount and
|
|
// 32.
|
|
//
|
|
if (ulBitCount < 32)
|
|
{
|
|
uiLshft =(UINT)(31 - ulBitCount);
|
|
for (x=0; x < pImg->iSymCnt; x++)
|
|
{
|
|
pImg->pWsp[x].ulBitString <<= uiLshft;
|
|
pImg->pulWsiNxt[x] = pImg->pWsp[x].ulBitString;
|
|
}
|
|
pImg->pulWsiNxt += pImg->iSymCnt;
|
|
}
|
|
|
|
|
|
} /* WstClearBitStrings () */
|
|
|
|
|
|
|
|
|
|
|
|
/*********************** W s t I n i t W s p F i l e ***********************
|
|
*
|
|
* Function: WstInitWspFile (pImg)
|
|
*
|
|
* Purpose: This function will create a WSP file and dump the header
|
|
* information for the file.
|
|
*
|
|
* Parameters: pImg - Current image data structure pointer
|
|
*
|
|
* Returns: Handle to the WSP file.
|
|
*
|
|
* History: 8-3-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
HANDLE WstInitWspFile (PIMG pImg)
|
|
{
|
|
CHAR szOutFile [256] = WSTROOT;
|
|
CHAR szModName [128];
|
|
CHAR szExt [5] = "WSP";
|
|
WSPHDR wsphdr;
|
|
DWORD dwBytesWritten;
|
|
BOOL fRet;
|
|
HANDLE hFile;
|
|
int iExt = 0;
|
|
|
|
|
|
|
|
//
|
|
// Prepare the filename path
|
|
//
|
|
strcat (szOutFile, pImg->pszName);
|
|
|
|
//
|
|
// Open the file for binary output.
|
|
//
|
|
pImg->fDumpAll = TRUE;
|
|
while (iExt < 256)
|
|
{
|
|
strcpy ((strchr(szOutFile,'.'))+1, szExt);
|
|
hFile = CreateFile ( szOutFile, // WSP file handle
|
|
GENERIC_WRITE |
|
|
GENERIC_READ, // Desired access
|
|
0L, // Read share access
|
|
NULL, // No EaBuffer
|
|
CREATE_NEW,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0); // EaBuffer length
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
IdPrint(("WST: WstInitWspFile() - WSP file name: %s\n",
|
|
szOutFile));
|
|
if (iExt != 0)
|
|
{
|
|
pImg->fDumpAll = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
iExt++;
|
|
sprintf (szExt, "W%02x", iExt);
|
|
}
|
|
if (iExt == 256)
|
|
{
|
|
KdPrint (("WST: WstInitWspFile() - "
|
|
"Error creating %s - 0x%lx\n", szOutFile,
|
|
GetLastError()));
|
|
return (hFile);
|
|
}
|
|
|
|
//
|
|
// Fill a WSP header structure
|
|
//
|
|
|
|
strcpy(szModName, pImg->pszName);
|
|
strcpy(strchr(szModName,'.'), "");
|
|
|
|
strcpy(wsphdr.chFileSignature, "WSP");
|
|
wsphdr.ulTimeStamp = 0L;
|
|
wsphdr.usId = 0;
|
|
wsphdr.usSetSymbols = pImg->usSetSymbols;
|
|
wsphdr.ulModNameLen = strlen(szModName);
|
|
wsphdr.ulSegSize = (ULONG)iTimeInterval;
|
|
wsphdr.ulOffset = wsphdr.ulModNameLen + (ULONG)sizeof(WSPHDR);
|
|
wsphdr.ulSnaps = ulSnaps;
|
|
|
|
//
|
|
// Write header and module name
|
|
//
|
|
fRet = WriteFile(hFile, // Wsp file handle
|
|
(PVOID)&wsphdr, // Buffer of data
|
|
(ULONG)sizeof(WSPHDR), // Bytes to write
|
|
&dwBytesWritten, // Bytes written
|
|
NULL);
|
|
|
|
if (!fRet)
|
|
{
|
|
KdPrint (("WST: WstInitWspFile() - "
|
|
"Error writing to %s - 0x%lx\n", szOutFile,
|
|
GetLastError));
|
|
return (NULL);
|
|
}
|
|
|
|
fRet = WriteFile (hFile, // Wsp file handle
|
|
(PVOID)szModName, // Buffer of data
|
|
(ULONG)strlen(szModName), // Bytes to write
|
|
&dwBytesWritten,
|
|
NULL);
|
|
if (!fRet)
|
|
{
|
|
KdPrint (("WST: WstInitWspFile() - "
|
|
"Error writing to %s - 0x%lx\n", szOutFile,
|
|
GetLastError()));
|
|
return (NULL);
|
|
}
|
|
|
|
return (hFile);
|
|
|
|
} /* WstInitWspFile () */
|
|
|
|
|
|
|
|
|
|
|
|
/************************** W s t D u m p D a t a **************************
|
|
*
|
|
* Function: WstDumpData (pImg)
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Parameters: pImg - Current image data structure pointer
|
|
*
|
|
* Returns: NONE
|
|
*
|
|
* History: 8-3-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
void WstDumpData (PIMG pImg)
|
|
{
|
|
INT x = 0;
|
|
DWORD dwBytesWritten;
|
|
BOOL fRet;
|
|
HANDLE hWspFile;
|
|
|
|
|
|
if ( !(hWspFile = WstInitWspFile(pImg)) )
|
|
{
|
|
KdPrint (("WST: WstDumpDate() - Error creating WSP file.\n"));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Write all the symbols with any bits set
|
|
//
|
|
for (x=0; x<pImg->iSymCnt; x++)
|
|
{
|
|
if (pImg->pWsp[x].ulBitString)
|
|
{
|
|
fRet = WriteFile(
|
|
hWspFile, // Wsp file handle
|
|
(PVOID)(pImg->pulWsp+(x*ulSnaps)), // Buffer of data
|
|
ulSnaps * sizeof(ULONG), // Bytes to write
|
|
&dwBytesWritten, // Bytes written
|
|
NULL); // Optional
|
|
if (!fRet)
|
|
{
|
|
KdPrint (("WST: WstDumpDate() - "
|
|
"Error writing to WSP file - 0x%lx\n",
|
|
GetLastError()));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Now write all the symbols with no bits set
|
|
//
|
|
if (pImg->fDumpAll)
|
|
{
|
|
for (x=0; x<pImg->iSymCnt; x++)
|
|
{
|
|
if (pImg->pWsp[x].ulBitString == 0L)
|
|
{
|
|
fRet = WriteFile(
|
|
hWspFile, // Wsp file handle
|
|
(PVOID)(pImg->pulWsp+(x*ulSnaps)), // Buffer of data
|
|
ulSnaps * sizeof(ULONG), // Bytes to write
|
|
&dwBytesWritten, // Bytes written
|
|
NULL); // Optional
|
|
if (!fRet)
|
|
{
|
|
KdPrint (("WST: WstDumpDate() - "
|
|
"Error writing to WSP file - 0x%lx\n",
|
|
GetLastError()));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fRet = CloseHandle(hWspFile);
|
|
if (!fRet)
|
|
{
|
|
KdPrint (("WST: WstDumpDate() - "
|
|
"Error closing %s - 0x%lx\n", "WSI file",
|
|
GetLastError()));
|
|
return;
|
|
}
|
|
|
|
} /* WstDumpData () */
|
|
|
|
|
|
|
|
|
|
|
|
/************************ W s t W r i t e T m i F i l e **********************
|
|
*
|
|
* Function: WstWriteTmiFile (pImg)
|
|
*
|
|
* Purpose: Write all the symbole info for the current image to its TMI
|
|
* file.
|
|
*
|
|
*
|
|
* Parameters: pImg - Current image data structure pointer
|
|
*
|
|
* Returns: -none-
|
|
*
|
|
* History: 8-5-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
void WstWriteTmiFile (PIMG pImg)
|
|
{
|
|
CHAR szOutFile [256] = WSTROOT;
|
|
CHAR szBuffer [256];
|
|
CHAR szExt [5] = "TMI";
|
|
HANDLE hTmiFile;
|
|
INT x;
|
|
DWORD dwBytesWritten;
|
|
BOOL fRet;
|
|
int iExt = 0;
|
|
PSZ pszSymbol;
|
|
|
|
|
|
//
|
|
// Prepare the filename path
|
|
//
|
|
strcat (szOutFile, pImg->pszName);
|
|
|
|
//
|
|
// Open the file for binary output.
|
|
//
|
|
pImg->fDumpAll = TRUE;
|
|
while (iExt < 256)
|
|
{
|
|
strcpy ((strchr(szOutFile,'.'))+1, szExt);
|
|
hTmiFile = CreateFile ( szOutFile, // TMI file handle
|
|
GENERIC_WRITE |
|
|
GENERIC_READ, // Desired access
|
|
0L, // Read share access
|
|
NULL, // No EaBuffer
|
|
CREATE_NEW,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0); // EaBuffer length
|
|
if (hTmiFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
IdPrint(("WST: WstWriteTmiFile() - TMI file name: %s\n",
|
|
szOutFile));
|
|
if (iExt != 0) {
|
|
pImg->fDumpAll = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
iExt++;
|
|
sprintf (szExt, "T%02x", iExt);
|
|
}
|
|
if (iExt == 256)
|
|
{
|
|
KdPrint (("WST: WstWriteTmiFile() - "
|
|
"Error creating %s - 0x%lx\n", szOutFile,
|
|
GetLastError()));
|
|
return;
|
|
}
|
|
|
|
sprintf(szBuffer, "/* %s for NT */\n"
|
|
"/* Total Symbols= %ld */\n"
|
|
"DO NOT DELETE\n"
|
|
"%d\n"
|
|
"TDFID = 0\n",
|
|
pImg->pszName,
|
|
pImg->fDumpAll ? pImg->iSymCnt : pImg->usSetSymbols,
|
|
iTimeInterval);
|
|
//
|
|
// Write header
|
|
//
|
|
fRet = WriteFile(hTmiFile, // Tmi file handle
|
|
(PVOID)szBuffer, // Buffer of data
|
|
(ULONG)strlen(szBuffer), // Bytes to write
|
|
&dwBytesWritten, // Bytes written
|
|
NULL);
|
|
|
|
if (!fRet)
|
|
{
|
|
KdPrint (("WST: WstWriteTmiFile() - "
|
|
"Error writing to %s - 0x%lx\n", szOutFile,
|
|
GetLastError));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Dump all the symbols with set bits.
|
|
//
|
|
for (x=0; x<pImg->iSymCnt ; x++)
|
|
{
|
|
if (pImg->pWsp[x].ulBitString)
|
|
{
|
|
#if 1
|
|
pszSymbol =
|
|
(pImg->pWsp[x].pszSymbol);
|
|
#else
|
|
pszSymbol = (*(pImg->pWsp[x].pszSymbol) == '_') ?
|
|
(pImg->pWsp[x].pszSymbol)+1 :
|
|
(pImg->pWsp[x].pszSymbol);
|
|
#endif
|
|
|
|
sprintf(szBuffer, "%ld 0000:%08lx 0x%lx %ld %s\n",
|
|
(LONG)x, pImg->pWsp[x].ulFuncAddr, (LONG) 0,
|
|
pImg->pWsp[x].ulCodeLength, pszSymbol);
|
|
//
|
|
// Write symbol line
|
|
//
|
|
fRet = WriteFile(hTmiFile, // Tmi file handle
|
|
(PVOID)szBuffer, // Buffer of data
|
|
(ULONG)strlen(szBuffer), // Bytes to write
|
|
&dwBytesWritten, // Bytes written
|
|
NULL);
|
|
|
|
if (!fRet)
|
|
{
|
|
KdPrint (("WST: WstWriteTmiFile() - "
|
|
"Error writing to %s - 0x%lx\n", szOutFile,
|
|
GetLastError));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Now dump all the symbols without any bits set.
|
|
//
|
|
if (pImg->fDumpAll)
|
|
{
|
|
for (x=0; x<pImg->iSymCnt ; x++ )
|
|
{
|
|
if (!pImg->pWsp[x].ulBitString)
|
|
{
|
|
#if 1
|
|
pszSymbol =
|
|
(pImg->pWsp[x].pszSymbol);
|
|
#else
|
|
pszSymbol = (*(pImg->pWsp[x].pszSymbol) == '_') ?
|
|
(pImg->pWsp[x].pszSymbol)+1 :
|
|
(pImg->pWsp[x].pszSymbol);
|
|
#endif
|
|
sprintf(szBuffer, "%ld 0000:%08lx 0x%lx %ld %s\n",
|
|
(LONG)x, pImg->pWsp[x].ulFuncAddr, (LONG) 0,
|
|
pImg->pWsp[x].ulCodeLength, pszSymbol);
|
|
//
|
|
// Write symbol line
|
|
//
|
|
fRet = WriteFile(hTmiFile, // Tmi file handle
|
|
(PVOID)szBuffer, // Buffer of data
|
|
(ULONG)strlen(szBuffer), // Bytes to write
|
|
&dwBytesWritten, // Bytes written
|
|
NULL);
|
|
|
|
if (!fRet)
|
|
{
|
|
KdPrint (("WST: WstWriteTmiFile() - "
|
|
"Error writing to %s - 0x%lx\n", szOutFile,
|
|
GetLastError));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fRet = CloseHandle(hTmiFile);
|
|
if (!fRet)
|
|
{
|
|
KdPrint (("WST: WstWriteTmiFile() - "
|
|
"Error closing %s - 0x%lx\n", szOutFile, GetLastError()));
|
|
return;
|
|
}
|
|
|
|
} /* WstWriteTmiFile () */
|
|
|
|
|
|
|
|
|
|
|
|
/*********************** W s t R o t a t e W s i M e m ***********************
|
|
*
|
|
* Function: WstRotateWsiMem (pImg)
|
|
*
|
|
* Purpose:
|
|
*
|
|
*
|
|
* Parameters: pImg - Current image data structure pointer
|
|
*
|
|
* Returns: -none-
|
|
*
|
|
* History: 8-5-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
void WstRotateWsiMem (PIMG pImg)
|
|
{
|
|
ULONG ulCurSnap;
|
|
ULONG ulOffset;
|
|
int x;
|
|
PULONG pulWsp;
|
|
|
|
|
|
pulWsp = pImg->pulWsp;
|
|
pImg->usSetSymbols = 0;
|
|
|
|
for (x=0; x<pImg->iSymCnt; x++)
|
|
{
|
|
ulOffset = 0L;
|
|
ulCurSnap = 0L;
|
|
pImg->pWsp[x].ulBitString = 0L;
|
|
|
|
while (ulCurSnap < ulSnaps)
|
|
{
|
|
|
|
ulOffset = (ULONG)x + ((ULONG)pImg->iSymCnt * ulCurSnap);
|
|
*pulWsp = *(pImg->pulWsi + ulOffset);
|
|
pImg->pWsp[x].ulBitString |= (*pulWsp);
|
|
pulWsp++;
|
|
ulCurSnap++;
|
|
}
|
|
|
|
if (pImg->pWsp[x].ulBitString)
|
|
{
|
|
SdPrint (("WST: WstRotateWsiMemSymbol() - set: %s\n",
|
|
pImg->pWsp[x].pszSymbol));
|
|
(pImg->usSetSymbols)++;
|
|
}
|
|
}
|
|
|
|
IdPrint (("WST: WstRotateWsiMem() - Number of set symbols = %d\n",
|
|
pImg->usSetSymbols));
|
|
|
|
} /* WstRotateWsiMwm () */
|
|
|
|
|
|
|
|
|
|
|
|
/*********************** W s t G e t S y m b o l s *************************
|
|
*
|
|
* WstGetSymbols (pCurWsp, pszImageName, pvImageBase, ulCodeLength, DebugInfo)
|
|
* This routine stores all the symbols for the current
|
|
* image into pCurWsp
|
|
*
|
|
* ENTRY upCurWsp - Pointer to current WSP structure
|
|
* pszImageName - Pointer to image name
|
|
* pvImageBase - Current image base address
|
|
* ulCodeLength - Current image code length
|
|
* DebugInfo - Pointer to the coff debug info structure
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN -none-
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
void WstGetSymbols (PIMG pCurImg,
|
|
PSZ pszImageName,
|
|
PVOID pvImageBase,
|
|
ULONG ulCodeLength,
|
|
PIMAGE_COFF_SYMBOLS_HEADER DebugInfo)
|
|
{
|
|
IMAGE_SYMBOL Symbol;
|
|
PIMAGE_SYMBOL SymbolEntry;
|
|
PUCHAR StringTable;
|
|
ULONG i;
|
|
char achTmp[9];
|
|
PWSP pCurWsp;
|
|
BOOL fOurSym;
|
|
PSZ ptchSymName;
|
|
|
|
|
|
pCurWsp = pCurImg->pWsp;
|
|
achTmp[8] = '\0';
|
|
|
|
//
|
|
// Crack the symbol table
|
|
//
|
|
SymbolEntry = (PIMAGE_SYMBOL)
|
|
((ULONG)DebugInfo + DebugInfo->LvaToFirstSymbol);
|
|
StringTable = (PUCHAR)((ULONG)DebugInfo + DebugInfo->LvaToFirstSymbol +
|
|
DebugInfo->NumberOfSymbols * (ULONG)IMAGE_SIZEOF_SYMBOL);
|
|
|
|
//
|
|
// Loop through all symbols in the symbol table.
|
|
//
|
|
for (i = 0; i < DebugInfo->NumberOfSymbols; i++)
|
|
{
|
|
//
|
|
// Skip thru aux symbols..
|
|
//
|
|
// while ( SymbolEntry->NumberOfAuxSymbols )
|
|
// {
|
|
// i = i + 1 + SymbolEntry->NumberOfAuxSymbols;
|
|
// SymbolEntry = (PIMAGE_SYMBOL)((ULONG)SymbolEntry +
|
|
// IMAGE_SIZEOF_SYMBOL +
|
|
// SymbolEntry->NumberOfAuxSymbols *
|
|
// IMAGE_SIZEOF_SYMBOL);
|
|
// }
|
|
RtlMoveMemory (&Symbol, SymbolEntry, IMAGE_SIZEOF_SYMBOL);
|
|
|
|
if (Symbol.SectionNumber == 1)
|
|
{ //code section
|
|
|
|
fOurSym = TRUE;
|
|
if ((Symbol.StorageClass != IMAGE_SYM_CLASS_EXTERNAL) &&
|
|
(Symbol.StorageClass != IMAGE_SYM_CLASS_STATIC) )
|
|
{
|
|
fOurSym = FALSE;
|
|
}
|
|
else if (Symbol.N.Name.Short)
|
|
{
|
|
if (Symbol.StorageClass == IMAGE_SYM_CLASS_STATIC)
|
|
{
|
|
if (*(PTCHAR)&(Symbol.N.Name.Short) == '.')
|
|
{
|
|
fOurSym = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fOurSym)
|
|
{
|
|
//
|
|
// This symbol is within the code.
|
|
//
|
|
pCurImg->iSymCnt++;
|
|
pCurWsp->ulBitString = 0L;
|
|
pCurWsp->ulFuncAddr = Symbol.Value + (ULONG)pvImageBase;
|
|
if (Symbol.N.Name.Short)
|
|
{
|
|
strncpy (achTmp, (PSZ)&(Symbol.N.Name.Short), 8);
|
|
#ifdef i386
|
|
// only need to strip leading underscore for i386.
|
|
// mips and alpha are ok.
|
|
if (achTmp[0] == '_')
|
|
{
|
|
pCurWsp->pszSymbol = Wststrdup (&achTmp[1]);
|
|
}
|
|
else
|
|
{
|
|
pCurWsp->pszSymbol = Wststrdup (achTmp);
|
|
}
|
|
#else
|
|
pCurWsp->pszSymbol = Wststrdup (achTmp);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
ptchSymName = (PSZ)&StringTable[Symbol.N.Name.Long];
|
|
#ifdef i386
|
|
// only need to strip leading underscore for i386.
|
|
// mips and alpha are ok.
|
|
if (*ptchSymName == '_')
|
|
{
|
|
ptchSymName++;
|
|
}
|
|
#endif
|
|
|
|
pCurWsp->pszSymbol = Wststrdup (ptchSymName);
|
|
}
|
|
|
|
//
|
|
// Remove @## at the end of symbol of stdcall routines.
|
|
//
|
|
// if ( (ptchHack = strrchr (pCurWsp->pszSymbol, '@')) ) {
|
|
// ptchHackTmp = ptchHack;
|
|
// while (isdigit(*++ptchHackTmp));
|
|
// if (*ptchHackTmp == '\0') {
|
|
// *ptchHack = '\0';
|
|
// }
|
|
// }
|
|
|
|
pCurWsp++;
|
|
}
|
|
}
|
|
SymbolEntry = (PIMAGE_SYMBOL)((ULONG)SymbolEntry + IMAGE_SIZEOF_SYMBOL);
|
|
}
|
|
|
|
} /* WstGetSymbols () */
|
|
|
|
|
|
|
|
|
|
|
|
/*********************** W s t D l l C l e a n u p s ***********************
|
|
*
|
|
* WstDllCleanups () -
|
|
* Dumps the end data, closes all semaphores and events, and
|
|
* closes DUMP, CLEAR & PAUSE thread handles.
|
|
*
|
|
* ENTRY -none-
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN -none-
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
void WstDllCleanups ()
|
|
{
|
|
NTSTATUS Status;
|
|
int i;
|
|
|
|
|
|
if (WstState != NOT_STARTED)
|
|
{
|
|
WstState = STOPPED;
|
|
|
|
IdPrint(("WST: WstDllCleanups() - Outputing data...\n"));
|
|
|
|
if (ulBitCount != 0L)
|
|
{
|
|
ulSnaps++;
|
|
}
|
|
|
|
//
|
|
// Get the GLOBAL semaphore.. (valid accross all process contexts)
|
|
//
|
|
Status = NtWaitForSingleObject (hGlobalSem, FALSE, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllCleanups() - "
|
|
"ERROR - Wait for GLOBAL semaphore failed - 0x%lx\n",
|
|
Status));
|
|
}
|
|
for (i=0; i<iImgCnt; i++)
|
|
{
|
|
WstClearBitStrings (&aImg[i]);
|
|
WstRotateWsiMem (&aImg[i]);
|
|
WstDumpData (&aImg[i]);
|
|
WstWriteTmiFile (&aImg[i]);
|
|
}
|
|
//
|
|
// Release the GLOBAL semaphore so other processes can dump data
|
|
//
|
|
Status = NtReleaseSemaphore (hGlobalSem, 1, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllCleanups() - "
|
|
"Error releasing GLOBAL semaphore - 0x%lx\n", Status));
|
|
}
|
|
|
|
IdPrint(("WST: WstDllCleanups() - ...Done.\n"));
|
|
}
|
|
|
|
if (fInThread)
|
|
{
|
|
(*pulShared)--;
|
|
fInThread = FALSE;
|
|
if ( (int)*pulShared <= 0L )
|
|
{
|
|
Status = NtSetEvent (hDoneEvent, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllCleanups() - "
|
|
"ERROR - Setting DONE event failed - 0x%lx\n", Status));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Unmap and close shared block section
|
|
//
|
|
Status = NtUnmapViewOfSection (NtCurrentProcess(), (PVOID)pulShared);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllCleanups() - "
|
|
"ERROR - NtUnmapViewOfSection() - 0x%lx\n", Status));
|
|
}
|
|
|
|
Status = NtClose(hSharedSec);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllCleanups() - "
|
|
"ERROR - NtClose() - 0x%lx\n", Status));
|
|
}
|
|
|
|
// Unmap and close WSP section
|
|
//
|
|
Status = NtUnmapViewOfSection (NtCurrentProcess(), (PVOID)aImg[0].pWsp);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllCleanups() - "
|
|
"ERROR - NtUnmapViewOfSection() - 0x%lx\n", Status));
|
|
}
|
|
|
|
Status = NtClose(hWspSec);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllCleanups() - "
|
|
"ERROR - NtClose() - 0x%lx\n", Status));
|
|
}
|
|
|
|
// Unmap and close patch dll sections
|
|
//
|
|
for (i=0; i<iPatchCnt; i++)
|
|
{
|
|
Status = NtUnmapViewOfSection (NtCurrentProcess(),
|
|
(PVOID)aPatchDllSec[i].pSec);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllCleanups() - "
|
|
"ERROR - NtUnmapViewOfSection() - 0x%lx\n", Status));
|
|
}
|
|
|
|
Status = NtClose (aPatchDllSec[i].hSec);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllCleanups() - "
|
|
"ERROR - NtClose() - 0x%lx\n", Status));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close GLOBAL semaphore
|
|
//
|
|
Status = NtClose (hGlobalSem);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllCleanups() - "
|
|
"ERROR - Could not close the GLOBAL semaphore - 0x%lx\n",
|
|
Status));
|
|
}
|
|
|
|
//
|
|
// Close LOCAL semaphore
|
|
//
|
|
Status = NtClose (hLocalSem);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDllCleanups() - "
|
|
"ERROR - Could not close the LOCAL semaphore - 0x%lx\n",
|
|
Status));
|
|
}
|
|
|
|
if (fPatchImage)
|
|
{
|
|
//
|
|
// Close all events
|
|
//
|
|
NtClose (hDoneEvent);
|
|
NtClose (hDumpEvent);
|
|
NtClose (hClearEvent);
|
|
NtClose (hPauseEvent);
|
|
|
|
//
|
|
// Close thread handles - threads are terminated during DLL detaching
|
|
// process.
|
|
//
|
|
CloseHandle (hDumpThread);
|
|
CloseHandle (hClearThread);
|
|
CloseHandle (hPauseThread);
|
|
|
|
#if 0
|
|
NtFreeVirtualMemory (NtCurrentProcess(),
|
|
(PVOID *)&pDumpStack,
|
|
&ulThdStackSize,
|
|
MEM_DECOMMIT);
|
|
|
|
NtFreeVirtualMemory (NtCurrentProcess(),
|
|
(PVOID *)&pClearStack,
|
|
&ulThdStackSize,
|
|
MEM_DECOMMIT);
|
|
|
|
NtFreeVirtualMemory (NtCurrentProcess(),
|
|
(PVOID *)&pPauseStack,
|
|
&ulThdStackSize,
|
|
MEM_DECOMMIT);
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
} /* WstDllCleanups () */
|
|
|
|
|
|
|
|
|
|
|
|
/**************** W s t U n p r o t e c t T h u n k F i l t e r ***************
|
|
*
|
|
* WstUnprotectThunkFilter (pThunkAddress, pXcptInfo) -
|
|
* Unprotects the thunk address to be able to write to it.
|
|
*
|
|
* ENTRY pThunkAddress - thunk address which caused the exception
|
|
* pXcptInfo - exception report record info pointer
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN EXCEPTIONR_CONTINUE_EXECUTION : if mem unprotected successfully
|
|
* EXCEPTION_CONTINUE_SEARCH : if non-access violation exception
|
|
* or cannot unprotect memory
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
INT WstUnprotectThunkFilter (PVOID pThunkAddress, PEXCEPTION_POINTERS pXcptInfo)
|
|
{
|
|
PVOID FaultAddress;
|
|
NTSTATUS Status;
|
|
PVOID ThunkBase;
|
|
ULONG RegionSize;
|
|
ULONG OldProtect;
|
|
|
|
|
|
//
|
|
// If we fault on the thunk attemting to write, then set protection to allow
|
|
// writes
|
|
//
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
FaultAddress = (PVOID)
|
|
(pXcptInfo->ExceptionRecord->ExceptionInformation[1] & ~0x3);
|
|
|
|
if ( pXcptInfo->ExceptionRecord->ExceptionCode ==
|
|
STATUS_ACCESS_VIOLATION )
|
|
{
|
|
|
|
if (pXcptInfo->ExceptionRecord->ExceptionInformation[0] &&
|
|
FaultAddress == pThunkAddress )
|
|
{
|
|
|
|
ThunkBase = (PVOID)
|
|
pXcptInfo->ExceptionRecord->ExceptionInformation[1];
|
|
|
|
RegionSize = sizeof(ULONG);
|
|
|
|
Status = NtProtectVirtualMemory(
|
|
NtCurrentProcess(),
|
|
&ThunkBase,
|
|
&RegionSize,
|
|
PAGE_READWRITE,
|
|
&OldProtect
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( NT_SUCCESS(Status) )
|
|
{
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
}
|
|
else
|
|
{
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
}
|
|
|
|
} /* WstUnprotectThunkFilter() */
|
|
|
|
|
|
|
|
|
|
|
|
/******************* W s t A c c e s s X c p t F i l t e r ******************
|
|
*
|
|
* WstAccessXcptFilter (ulXcptNo, pXcptInfoPtr) -
|
|
* Commits COMMIT_SIZE more pages of memory if exception is access
|
|
* violation.
|
|
*
|
|
* ENTRY ulXcptNo - exception number
|
|
* pXcptInfoPtr - exception report record info pointer
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN EXCEPTIONR_CONTINUE_EXECUTION : if access violation exception
|
|
* and mem committed successfully
|
|
* EXCEPTION_CONTINUE_SEARCH : if non-access violation exception
|
|
* or cannot commit more memory
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
INT WstAccessXcptFilter (ULONG ulXcptNo, PEXCEPTION_POINTERS pXcptPtr)
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG ulSize = COMMIT_SIZE;
|
|
PVOID pvMem = (PVOID)pXcptPtr->ExceptionRecord->ExceptionInformation[1];
|
|
|
|
|
|
if (ulXcptNo != EXCEPTION_ACCESS_VIOLATION)
|
|
{
|
|
return (EXCEPTION_CONTINUE_SEARCH);
|
|
}
|
|
else
|
|
{
|
|
Status = NtAllocateVirtualMemory (NtCurrentProcess(),
|
|
&pvMem,
|
|
0L,
|
|
&ulSize,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstAccessXcptFilter() - "
|
|
"Error committing more memory @ 0x%08lx - 0x%08lx "
|
|
"- TEB=0x%08lx\n", pvMem, Status, NtCurrentTeb()));
|
|
return (EXCEPTION_CONTINUE_SEARCH);
|
|
}
|
|
else
|
|
{
|
|
SdPrint (("WST: WstAccessXcptFilter() - "
|
|
"Committed %d more pages @ 0x%08lx - TEB=0x%08lx\n",
|
|
COMMIT_SIZE/PAGE_SIZE, pvMem, NtCurrentTeb()));
|
|
}
|
|
|
|
return (EXCEPTION_CONTINUE_EXECUTION);
|
|
}
|
|
|
|
} /* WstAccessXcptFilter () */
|
|
|
|
|
|
|
|
|
|
|
|
/*************************** W s t P a t c h D l l **************************
|
|
*
|
|
* WstPatchDll (pchPatchImports, pchPatchCallers, pchDllName, pvImageBase) -
|
|
* Patches all the imported entry points for the specified dll.
|
|
*
|
|
* ENTRY pchPatchImports - list of DLLs to patch all their imports
|
|
* pchPatchCallers - list of DLLs to patch all their callers
|
|
* pchDllName - name of dll to be patched
|
|
* pvImageBase - image base address
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN -none-
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
BOOL WstPatchDll (PCHAR pchPatchImports,
|
|
PCHAR pchPatchCallers,
|
|
PCHAR pchDllName,
|
|
PVOID pvImageBase)
|
|
{
|
|
NTSTATUS Status;
|
|
ANSI_STRING ObjName;
|
|
UNICODE_STRING UnicodeName;
|
|
OBJECT_ATTRIBUTES ObjAttributes;
|
|
char achPatchSecName[80] = PATCHSECNAME;
|
|
LARGE_INTEGER AllocationSize;
|
|
ULONG ulViewSize;
|
|
ULONG ulImportSize;
|
|
PIMAGE_IMPORT_DESCRIPTOR pImports;
|
|
PIMAGE_IMPORT_DESCRIPTOR pImportsTmp;
|
|
PIMAGE_THUNK_DATA ThunkNames;
|
|
ULONG ulNumThunks;
|
|
PVOID pvPatchSec;
|
|
PVOID pvPatchSecThunk;
|
|
BOOL bAllImports = FALSE;
|
|
BOOL bPatchAllImports = FALSE;
|
|
PCHAR pchName;
|
|
char achTmpImageName [256];
|
|
PCHAR pchEntry;
|
|
|
|
BOOL fCrtDllPatched = FALSE;
|
|
BOOL fKernel32Patched = FALSE;
|
|
|
|
#if defined(MIPS) || defined(ALPHA) || defined(_PPC_)
|
|
PULONG UNALIGNED pulAddr;
|
|
PPATCHCODE pPatchStub;
|
|
BOOL fAlreadyPatched = FALSE;
|
|
#endif
|
|
|
|
//
|
|
// Patch all the imports?
|
|
//
|
|
pchEntry = strstr (pchPatchImports, pchDllName);
|
|
if (pchEntry)
|
|
{
|
|
if (*(pchEntry-1) == ';')
|
|
{
|
|
pchEntry = NULL;
|
|
}
|
|
}
|
|
if (pchEntry)
|
|
{
|
|
bPatchAllImports = TRUE;
|
|
}
|
|
|
|
//
|
|
// Locate the import array for this image/dll
|
|
//
|
|
pImports = (PIMAGE_IMPORT_DESCRIPTOR)
|
|
RtlImageDirectoryEntryToData (
|
|
pvImageBase,
|
|
TRUE,
|
|
IMAGE_DIRECTORY_ENTRY_IMPORT,
|
|
&ulImportSize);
|
|
|
|
ulNumThunks = 0L;
|
|
pImportsTmp = pImports;
|
|
for (;pImportsTmp; pImportsTmp++)
|
|
{
|
|
if (!pImportsTmp->Name)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
strcpy (achTmpImageName,
|
|
(PUCHAR)((ULONG)pvImageBase+pImportsTmp->Name));
|
|
pchName = _strupr (achTmpImageName);
|
|
|
|
if ( (strcmp(pchName, CRTDLL) == 0) ||
|
|
(strcmp(pchName, CAIROCRT) == 0))
|
|
{
|
|
// We do not want to patch CRTDLL/CAIROCRT thunks since
|
|
// they included thunks that are data.
|
|
continue;
|
|
}
|
|
|
|
pchEntry = strstr (pchPatchCallers, pchName);
|
|
if (pchEntry)
|
|
{
|
|
if (*(pchEntry-1) == ';')
|
|
{
|
|
pchEntry = NULL;
|
|
}
|
|
}
|
|
|
|
if (strcmp(pchName, WSTDLL) && (bPatchAllImports || pchEntry))
|
|
{
|
|
ThunkNames = (PIMAGE_THUNK_DATA)
|
|
((ULONG)pvImageBase+(ULONG)pImportsTmp->FirstThunk);
|
|
|
|
while (ThunkNames->u1.AddressOfData)
|
|
{
|
|
ulNumThunks++;
|
|
ThunkNames++;
|
|
}
|
|
}
|
|
}
|
|
} // for (;pImportsTmp; pImportsTmp++)
|
|
|
|
if ( (ulNumThunks == 0L) ||
|
|
(!strcmp (pchDllName, CRTDLL)) ||
|
|
(!strcmp (pchDllName, KERNEL32)) )
|
|
{
|
|
IdPrint (("\n"));
|
|
return (FALSE);
|
|
}
|
|
else
|
|
{
|
|
IdPrint (("(patched)\n"));
|
|
//
|
|
// Allocate global storage for patch code for the current image
|
|
//
|
|
strcat (achPatchSecName, pchDllName);
|
|
RtlInitString(&ObjName, achPatchSecName);
|
|
Status = RtlAnsiStringToUnicodeString(&UnicodeName, &ObjName, TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstPatchDll() - "
|
|
"RtlAnsiStringToUnicodeString() failed - 0x%lx\n", Status));
|
|
}
|
|
|
|
InitializeObjectAttributes(&ObjAttributes,
|
|
&UnicodeName,
|
|
OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
&SecDescriptor);
|
|
|
|
AllocationSize.HighPart = 0;
|
|
AllocationSize.LowPart = ulNumThunks*sizeof(PATCHCODE);
|
|
|
|
// Create a read/write/execute section
|
|
//
|
|
Status = NtCreateSection(&aPatchDllSec[iPatchCnt].hSec,
|
|
SECTION_MAP_READ |
|
|
SECTION_MAP_WRITE |
|
|
SECTION_MAP_EXECUTE,
|
|
&ObjAttributes,
|
|
&AllocationSize,
|
|
PAGE_EXECUTE_READWRITE,
|
|
SEC_COMMIT,
|
|
NULL);
|
|
RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstPatchDll() - "
|
|
"NtCreateSection() failed - 0x%lx\n", Status));
|
|
}
|
|
|
|
ulViewSize = AllocationSize.LowPart;
|
|
aPatchDllSec[iPatchCnt].pSec = NULL;
|
|
|
|
// Map the section - commit all pages
|
|
//
|
|
Status = NtMapViewOfSection (aPatchDllSec[iPatchCnt].hSec,
|
|
NtCurrentProcess(),
|
|
(PVOID *)&aPatchDllSec[iPatchCnt].pSec,
|
|
0L,
|
|
AllocationSize.LowPart,
|
|
NULL,
|
|
&ulViewSize,
|
|
ViewUnmap,
|
|
0L,
|
|
PAGE_EXECUTE_READWRITE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstPatchDll() - "
|
|
"NtMapViewOfSection() failed - 0x%lx\n", Status));
|
|
}
|
|
|
|
//
|
|
// Munge the section and tables
|
|
//
|
|
pvPatchSec = aPatchDllSec[iPatchCnt].pSec;
|
|
for (;pImports; pImports++)
|
|
{
|
|
if (!pImports->Name)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
strcpy (achTmpImageName,
|
|
(PUCHAR)((ULONG)pvImageBase+pImports->Name));
|
|
pchName = _strupr (achTmpImageName);
|
|
pchEntry = strstr (pchPatchCallers, pchName);
|
|
if (pchEntry)
|
|
{
|
|
if (*(pchEntry-1) == ';')
|
|
{
|
|
pchEntry = NULL;
|
|
}
|
|
}
|
|
|
|
if ( (strcmp(pchName, CRTDLL) == 0) ||
|
|
(strcmp(pchName, CAIROCRT) == 0) )
|
|
{
|
|
// We do not want to patch CRTDLL/CAIROCRT thunks since
|
|
// they included thunks that are data.
|
|
continue;
|
|
}
|
|
|
|
#ifdef i386
|
|
if ( strcmp (pchName, WSTDLL) &&
|
|
(bPatchAllImports || pchEntry) )
|
|
{
|
|
|
|
IdPrint (("WST: ++ %s\n", pchName));
|
|
ThunkNames = (PIMAGE_THUNK_DATA)
|
|
((ULONG)pvImageBase+(ULONG)pImports->FirstThunk);
|
|
|
|
while (ThunkNames->u1.AddressOfData)
|
|
{
|
|
pvPatchSecThunk = pvPatchSec;
|
|
//
|
|
// mov eax, AddressOfData
|
|
// push eax
|
|
//
|
|
*(PBYTE)pvPatchSec = 0xb8;
|
|
((PBYTE)pvPatchSec)++;
|
|
*(PDWORD)pvPatchSec = (DWORD)
|
|
ThunkNames->u1.AddressOfData;
|
|
((PDWORD)pvPatchSec)++;
|
|
*(PBYTE)pvPatchSec = 0x50;
|
|
((PBYTE)pvPatchSec)++;
|
|
//
|
|
// mov eax, _penter
|
|
// jmp eax
|
|
//
|
|
*(PBYTE)pvPatchSec = 0xb8;
|
|
((PBYTE)pvPatchSec)++;
|
|
*(PDWORD)pvPatchSec = (DWORD)_penter;
|
|
((PDWORD)pvPatchSec)++;
|
|
*(PWORD)pvPatchSec = 0xe0ff;
|
|
((PWORD)pvPatchSec)++;
|
|
|
|
try
|
|
{
|
|
ThunkNames->u1.AddressOfData =
|
|
(PIMAGE_IMPORT_BY_NAME)pvPatchSecThunk;
|
|
}
|
|
except (WstUnprotectThunkFilter (
|
|
&(ThunkNames->u1.AddressOfData),
|
|
GetExceptionInformation()))
|
|
{
|
|
return (FALSE);
|
|
}
|
|
ThunkNames++;
|
|
}
|
|
} // end of stricmp (pchName, WSTDLL)...
|
|
#endif // ifdef i386
|
|
|
|
#ifdef MIPS
|
|
// Initialization of our stub
|
|
PatchStub.Addiu_sp_sp_imm = 0x27bdfff8;
|
|
PatchStub.Sw_ra_sp = 0xafbf0004;
|
|
PatchStub.Addiu_r0_r0 = 0x24001804;
|
|
PatchStub.Lw_ra_sp = 0x8fbf0004;
|
|
PatchStub.Lui_t0 = 0x3c080000;
|
|
PatchStub.Ori_t0 = 0x35080000;
|
|
PatchStub.Jr_t0 = 0x01000008;
|
|
PatchStub.Delay_Inst = 0x27bd0008;
|
|
PatchStub.OurSignature = STUB_SIGNATURE;
|
|
|
|
PatchStub.Lui_t0_ra = (((ULONG) &penter) & 0xffff0000) >> 16;
|
|
PatchStub.Lui_t0_ra |= 0x3c080000;
|
|
PatchStub.Ori_t0_ra = ((ULONG) &penter) & 0x0000ffff;
|
|
PatchStub.Ori_t0_ra |= 0x35080000;
|
|
PatchStub.Jalr_t0 |= 0x0100f809;
|
|
|
|
if ( _stricmp (pchName, WSTDLL) &&
|
|
(bPatchAllImports || pchEntry) )
|
|
{
|
|
IdPrint (("WST: -- %s\n", pchName));
|
|
ThunkNames = (PIMAGE_THUNK_DATA)
|
|
((ULONG)pvImageBase +
|
|
(ULONG)pImports->FirstThunk);
|
|
|
|
if ( !strcmp (pchName, CRTDLL))
|
|
{
|
|
fCrtDllPatched = TRUE;
|
|
}
|
|
if ( !strcmp (pchName, KERNEL32))
|
|
{
|
|
fKernel32Patched = TRUE;
|
|
}
|
|
|
|
//
|
|
// Are we already patched? If so set a flag.
|
|
// Check for our signature:
|
|
//
|
|
// addiu sp, sp, -8 (+ 0) 0x27bdfff8
|
|
// sw ra, 4(sp) (+ 1) 0xafbf0004
|
|
// lui t0, xxxx (+ 2) 0x3c08----
|
|
// ori t0, xxxx (+ 3) 0x3508----
|
|
// jalr t0 (+ 4) 0x0100f809
|
|
// addiu $0, $0, 0x1804 (+ 5) 0x24001804
|
|
// lw ra, 4(sp) (+ 6) 0x8fbf0004
|
|
// lui t0, xxxx (+ 7) 0x3c08----
|
|
// ori t0, t0, xxxx (+ 8) 0x3508----
|
|
// jr t0 (+ 9) 0x01000008
|
|
// addiu sp, sp, 8 (+ A) 0x27bd0008
|
|
// $(FEFE55AA) (+ B) 0xfefe55aa
|
|
|
|
pulAddr = (PULONG UNALIGNED) (ThunkNames->u1.AddressOfData);
|
|
|
|
if ( (*pulAddr == 0x27bdfff8) &&
|
|
(*(pulAddr + 1) == 0xafbf0004) &&
|
|
((*(pulAddr + 2) & 0xffff0000) == 0x3c080000) &&
|
|
((*(pulAddr + 3) & 0xffff0000) == 0x35080000) &&
|
|
(*(pulAddr + 4) == 0x0100f809) &&
|
|
(*(pulAddr + 5) == 0x24001804) &&
|
|
(*(pulAddr + 6) == 0x8fbf0004) &&
|
|
((*(pulAddr + 7) & 0xffff0000) == 0x3c080000) &&
|
|
((*(pulAddr + 8) & 0xffff0000) == 0x35080000) &&
|
|
(*(pulAddr + 9) == 0x01000008) &&
|
|
(*(pulAddr + 10) == 0x27bd0008) &&
|
|
(*(pulAddr + 11) == 0xfefe55aa) )
|
|
{
|
|
fAlreadyPatched = TRUE;
|
|
}
|
|
|
|
if ( !fAlreadyPatched )
|
|
{
|
|
while (ThunkNames->u1.AddressOfData)
|
|
{
|
|
pvPatchSecThunk = pvPatchSec;
|
|
|
|
//
|
|
// The goal here is to correctly emulate the same
|
|
// environment as what the compiler emits for
|
|
// every function call. The scenario for DLL is
|
|
// a little different than calling an internal
|
|
// function:
|
|
//
|
|
// a. jal Commnot!MemAlloc
|
|
// RetAddrX:
|
|
//
|
|
// b. The thunk will jump to the code so by the
|
|
// time we get to the code, only RetAddrX is
|
|
// set in $ra. _penter will not even be in
|
|
// the picture since the DLL was not compiled
|
|
// with -Gh.
|
|
//
|
|
// Therefore, the following code emulates the
|
|
// same code that get generated by the compiler.
|
|
//
|
|
// addiu sp, sp, -0x..
|
|
// sw ra, 4(sp)
|
|
// ... ...
|
|
// jal _penter <---- inserted code
|
|
// addiu $0, $0, 0x.. by -Gh
|
|
// ... ...
|
|
//
|
|
// This way by the time we enter the MemAlloc
|
|
// routine, $ra is set to somewhere in _penter
|
|
//
|
|
|
|
SdPrint(("WST: Patching [%s] Imports of [%s]\n",
|
|
pchName,
|
|
pchDllName));
|
|
|
|
{ // Move the stub into the shared memory
|
|
int i;
|
|
pPatchStub = &PatchStub;
|
|
for (i = 0; i < sizeof(PATCHCODE); i++)
|
|
{
|
|
(BYTE) *((PBYTE)pvPatchSec + i) =
|
|
*((PBYTE)pPatchStub + i);
|
|
}
|
|
}
|
|
|
|
pPatchStub = (PPATCHCODE) pvPatchSec;
|
|
(PBYTE) pvPatchSec += sizeof(PATCHCODE);
|
|
|
|
pPatchStub->Lui_t0 |= (DWORD)
|
|
((ULONG) ThunkNames->u1.AddressOfData &
|
|
0xffff0000) >> 16;
|
|
pPatchStub->Ori_t0 |= (DWORD)
|
|
ThunkNames->u1.AddressOfData & 0x0000ffff;
|
|
|
|
// Point the thunk to the PatchSec
|
|
try
|
|
{
|
|
ThunkNames->u1.AddressOfData =
|
|
(PIMAGE_IMPORT_BY_NAME)pvPatchSecThunk;
|
|
}
|
|
except (WstUnprotectThunkFilter (
|
|
&(ThunkNames->u1.AddressOfData),
|
|
GetExceptionInformation()))
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
ThunkNames++;
|
|
} // while (ThunkNames->u1.AddressOfData)
|
|
} // if ( !fAlreadyPatched )
|
|
|
|
if ( fAlreadyPatched )
|
|
{
|
|
IdPrint (("WST: -- %s\n", pchName));
|
|
}
|
|
else
|
|
{
|
|
IdPrint (("WST: ++ %s\n", pchName));
|
|
}
|
|
}
|
|
#endif // ifdef MIPS
|
|
#ifdef ALPHA
|
|
// Initialization of our stub
|
|
//
|
|
PatchStub.Lda_sp_sp_imm = 0x23defff0;
|
|
PatchStub.Stq_ra_sp = 0xb75e0008;
|
|
PatchStub.Stq_v0_sp = 0xb41e0000;
|
|
PatchStub.Ldah_t12_ra = (((ULONG) &penter) & 0xffff0000) >> 16;
|
|
PatchStub.Ldah_t12_ra |= 0x277f0000;
|
|
|
|
if (((ULONG) &penter) & 0x00008000)
|
|
{
|
|
// need to add one to the upper address because Lda
|
|
// will substract one from it.
|
|
PatchStub.Ldah_t12_ra += 1;
|
|
}
|
|
|
|
PatchStub.Lda_t12_ra = ((ULONG) &penter) & 0x0000ffff;
|
|
PatchStub.Lda_t12_ra |= 0x237b0000;
|
|
PatchStub.Jsr_t12 = 0x681b4000;
|
|
PatchStub.Ldq_ra_sp = 0xa75e0008;
|
|
PatchStub.Ldq_v0_sp = 0xa41e0000;
|
|
PatchStub.Lda_sp_sp = 0x23de0010;
|
|
PatchStub.Ldah_t12 = 0x277f0000;
|
|
PatchStub.Lda_t12 = 0x237b0000;
|
|
PatchStub.Jmp_t12 = 0x6bfb0000;
|
|
PatchStub.Bis_0 = 0x47ff041f;
|
|
PatchStub.OurSignature = STUB_SIGNATURE;
|
|
|
|
|
|
if ( _stricmp (pchName, WSTDLL) &&
|
|
(bPatchAllImports || pchEntry) )
|
|
{
|
|
IdPrint (("WST: -- %s\n", pchName));
|
|
ThunkNames = (PIMAGE_THUNK_DATA)
|
|
((ULONG)pvImageBase +
|
|
(ULONG)pImports->FirstThunk);
|
|
|
|
if ( !strcmp (pchName, CRTDLL))
|
|
{
|
|
fCrtDllPatched = TRUE;
|
|
}
|
|
if ( !strcmp (pchName, KERNEL32))
|
|
{
|
|
fKernel32Patched = TRUE;
|
|
}
|
|
|
|
//
|
|
// Are we already patched? If so set a flag.
|
|
// Check for our signature:
|
|
//
|
|
|
|
pulAddr = (PULONG UNALIGNED) (ThunkNames->u1.AddressOfData);
|
|
|
|
if ( (*pulAddr == 0x23defff0) &&
|
|
(*(pulAddr + 1) == 0xb75e0008) &&
|
|
(*(pulAddr + 2) == 0xb41e0008) &&
|
|
((*(pulAddr + 3) & 0xffff0000) == 0x277f0000) &&
|
|
((*(pulAddr + 4) & 0xffff0000) == 0x237b0000) &&
|
|
(*(pulAddr + 5) == 0x681b4000) &&
|
|
(*(pulAddr + 6) == 0xa75e0008) &&
|
|
(*(pulAddr + 7) == 0xa41e0000) &&
|
|
(*(pulAddr + 8) == 0x23de0010) &&
|
|
((*(pulAddr + 9) & 0xffff0000) == 0x277f0000) &&
|
|
((*(pulAddr + 10) & 0xffff0000) == 0x237b0000) &&
|
|
(*(pulAddr + 11) == 0x6bfb0000) &&
|
|
(*(pulAddr + 12) == 0x47ff041f) &&
|
|
(*(pulAddr + 13) == 0xfefe55aa) )
|
|
{
|
|
fAlreadyPatched = TRUE;
|
|
}
|
|
|
|
if ( !fAlreadyPatched )
|
|
{
|
|
while (ThunkNames->u1.AddressOfData)
|
|
{
|
|
pvPatchSecThunk = pvPatchSec;
|
|
|
|
SdPrint(("WST: Patching [%s] Imports of [%s]\n",
|
|
pchName,
|
|
pchDllName));
|
|
|
|
{ // Move the stub into the shared memory
|
|
int i;
|
|
pPatchStub = &PatchStub;
|
|
for (i = 0; i < sizeof(PATCHCODE); i++)
|
|
{
|
|
(BYTE) *((PBYTE)pvPatchSec + i) =
|
|
*((PBYTE)pPatchStub + i);
|
|
}
|
|
}
|
|
|
|
pPatchStub = (PPATCHCODE) pvPatchSec;
|
|
(PBYTE) pvPatchSec += sizeof(PATCHCODE);
|
|
|
|
// now move in the actual thunk address
|
|
pPatchStub->Ldah_t12 |= (DWORD)
|
|
((ULONG) ThunkNames->u1.AddressOfData &
|
|
0xffff0000) >> 16;
|
|
if ((ULONG) ThunkNames->u1.AddressOfData &
|
|
0x000008000)
|
|
{
|
|
pPatchStub->Ldah_t12 += 1;
|
|
}
|
|
|
|
pPatchStub->Lda_t12 |= (DWORD)
|
|
ThunkNames->u1.AddressOfData & 0x0000ffff;
|
|
|
|
// Point the thunk to the PatchSec
|
|
try
|
|
{
|
|
ThunkNames->u1.AddressOfData =
|
|
(PIMAGE_IMPORT_BY_NAME)pvPatchSecThunk;
|
|
}
|
|
except (WstUnprotectThunkFilter (
|
|
&(ThunkNames->u1.AddressOfData),
|
|
GetExceptionInformation()))
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
ThunkNames++;
|
|
} // while (ThunkNames->u1.AddressOfData)
|
|
} // if ( !fAlreadyPatched )
|
|
|
|
if ( fAlreadyPatched )
|
|
{
|
|
IdPrint (("WST: -- %s\n", pchName));
|
|
}
|
|
else
|
|
{
|
|
IdPrint (("WST: ++ %s\n", pchName));
|
|
}
|
|
}
|
|
#endif // ifdef ALPHA
|
|
#if defined(_PPC_) // after ALPHA
|
|
// Initialization of our stub
|
|
//
|
|
// PatchStub.Lda_sp_sp_imm = 0x23defff0;
|
|
// PatchStub.Stq_ra_sp = 0xb75e0008;
|
|
// PatchStub.Stq_v0_sp = 0xb41e0000;
|
|
// PatchStub.Ldah_t12_ra = (((ULONG) &penter) & 0xffff0000) >> 16;
|
|
// PatchStub.Ldah_t12_ra |= 0x277f0000;
|
|
|
|
if (((ULONG) &penter) & 0x00008000)
|
|
{
|
|
// need to add one to the upper address because Lda
|
|
// will substract one from it.
|
|
// PatchStub.Ldah_t12_ra += 1;
|
|
}
|
|
|
|
// PatchStub.Lda_t12_ra = ((ULONG) &penter) & 0x0000ffff;
|
|
// PatchStub.Lda_t12_ra |= 0x237b0000;
|
|
// PatchStub.Jsr_t12 = 0x681b4000;
|
|
// PatchStub.Ldq_ra_sp = 0xa75e0008;
|
|
// PatchStub.Ldq_v0_sp = 0xa41e0000;
|
|
// PatchStub.Lda_sp_sp = 0x23de0010;
|
|
// PatchStub.Ldah_t12 = 0x277f0000;
|
|
// PatchStub.Lda_t12 = 0x237b0000;
|
|
// PatchStub.Jmp_t12 = 0x6bfb0000;
|
|
// PatchStub.Bis_0 = 0x47ff041f;
|
|
// PatchStub.OurSignature = STUB_SIGNATURE;
|
|
|
|
|
|
if ( _stricmp (pchName, WSTDLL) &&
|
|
(bPatchAllImports || pchEntry) )
|
|
{
|
|
IdPrint (("WST: -- %s\n", pchName));
|
|
ThunkNames = (PIMAGE_THUNK_DATA)
|
|
((ULONG)pvImageBase +
|
|
(ULONG)pImports->FirstThunk);
|
|
|
|
if ( !strcmp (pchName, CRTDLL))
|
|
{
|
|
fCrtDllPatched = TRUE;
|
|
}
|
|
if ( !strcmp (pchName, KERNEL32))
|
|
{
|
|
fKernel32Patched = TRUE;
|
|
}
|
|
|
|
//
|
|
// Are we already patched? If so set a flag.
|
|
// Check for our signature:
|
|
//
|
|
|
|
pulAddr = (ULONG UNALIGNED *) (ThunkNames->u1.AddressOfData);
|
|
|
|
if (
|
|
// (*pulAddr == 0x23defff0) &&
|
|
// (*(pulAddr + 1) == 0xb75e0008) &&
|
|
// (*(pulAddr + 2) == 0xb41e0008) &&
|
|
// ((*(pulAddr + 3) & 0xffff0000) == 0x277f0000) &&
|
|
// ((*(pulAddr + 4) & 0xffff0000) == 0x237b0000) &&
|
|
// (*(pulAddr + 5) == 0x681b4000) &&
|
|
// (*(pulAddr + 6) == 0xa75e0008) &&
|
|
// (*(pulAddr + 7) == 0xa41e0000) &&
|
|
// (*(pulAddr + 8) == 0x23de0010) &&
|
|
// ((*(pulAddr + 9) & 0xffff0000) == 0x277f0000) &&
|
|
// ((*(pulAddr + 10) & 0xffff0000) == 0x237b0000) &&
|
|
// (*(pulAddr + 11) == 0x6bfb0000) &&
|
|
// (*(pulAddr + 12) == 0x47ff041f) &&
|
|
(*(pulAddr + 13) == 0xfefe55aa) )
|
|
{
|
|
fAlreadyPatched = TRUE;
|
|
}
|
|
|
|
if ( !fAlreadyPatched )
|
|
{
|
|
while (ThunkNames->u1.AddressOfData)
|
|
{
|
|
pvPatchSecThunk = pvPatchSec;
|
|
|
|
SdPrint(("WST: Patching [%s] Imports of [%s]\n",
|
|
pchName,
|
|
pchDllName));
|
|
|
|
{ // Move the stub into the shared memory
|
|
int i;
|
|
pPatchStub = &PatchStub;
|
|
for (i = 0; i < sizeof(PATCHCODE); i++)
|
|
{
|
|
(BYTE) *((PBYTE)pvPatchSec + i) =
|
|
*((PBYTE)pPatchStub + i);
|
|
}
|
|
}
|
|
|
|
pPatchStub = (PPATCHCODE) pvPatchSec;
|
|
(PBYTE) pvPatchSec += sizeof(PATCHCODE);
|
|
|
|
// now move in the actual thunk address
|
|
// jhs todo pPatchStub->Ldah_t12 |= (DWORD)
|
|
// ((ULONG) ThunkNames->u1.AddressOfData &
|
|
// 0xffff0000) >> 16;
|
|
if ((ULONG) ThunkNames->u1.AddressOfData &
|
|
0x000008000)
|
|
{
|
|
// jhs todo pPatchStub->Ldah_t12 += 1;
|
|
}
|
|
|
|
// jhs todo pPatchStub->Lda_t12 |= (DWORD)
|
|
// ThunkNames->u1.AddressOfData & 0x0000ffff;
|
|
|
|
// Point the thunk to the PatchSec
|
|
try
|
|
{
|
|
ThunkNames->u1.AddressOfData =
|
|
(PIMAGE_IMPORT_BY_NAME)pvPatchSecThunk;
|
|
}
|
|
except (WstUnprotectThunkFilter (
|
|
&(ThunkNames->u1.AddressOfData),
|
|
GetExceptionInformation()))
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
ThunkNames++;
|
|
} // while (ThunkNames->u1.AddressOfData)
|
|
} // if ( !fAlreadyPatched )
|
|
|
|
if ( fAlreadyPatched )
|
|
{
|
|
IdPrint (("WST: -- %s\n", pchName));
|
|
}
|
|
else
|
|
{
|
|
IdPrint (("WST: ++ %s\n", pchName));
|
|
}
|
|
}
|
|
#endif // ifdef PPC
|
|
|
|
}
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
} /* WstPatchDll () */
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
/******* S O R T / S E A R C H U T I L I T Y F U N C T I O N S *********/
|
|
/*****************************************************************************/
|
|
|
|
|
|
/************************* W s t C o m p a r e *****************************
|
|
*
|
|
* Function: WstCompare(PVOID val1,PVOID val2)
|
|
*
|
|
* Purpose: Compare values for qsort
|
|
*
|
|
*
|
|
* Parameters: PVOID
|
|
*
|
|
* Returns: -1 if val1 < val2
|
|
* 1 if val1 > val2
|
|
* 0 if val1 == val2
|
|
*
|
|
* History: 8-3-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
int WstCompare (PWSP val1, PWSP val2)
|
|
{
|
|
return (val1->ulFuncAddr < val2->ulFuncAddr ? -1:
|
|
val1->ulFuncAddr == val2->ulFuncAddr ? 0:
|
|
1);
|
|
|
|
} /* WstComapre () */
|
|
|
|
|
|
|
|
|
|
|
|
/*********************** W s t B C o m p a r e ********************************
|
|
*
|
|
* Function: WstBCompare(PDWORD pdwVal1, PVOID val2)
|
|
*
|
|
* Purpose: Compare values for Binary search
|
|
*
|
|
*
|
|
* Parameters: PVOID
|
|
*
|
|
* Returns: -1 if val1 < val2
|
|
* 1 if val1 > val2
|
|
* 0 if val1 == val2
|
|
*
|
|
* History: 8-3-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
int WstBCompare (PDWORD pdwVal1, PWSP val2)
|
|
{
|
|
#if defined(_X86_)
|
|
return (*pdwVal1 < val2->ulFuncAddr ? -1:
|
|
*pdwVal1 == val2->ulFuncAddr ? 0:
|
|
1);
|
|
#elif defined(_MIPS_) || defined(_ALPHA_)
|
|
int dwCompareCode = 0;
|
|
|
|
if (*pdwVal1 < val2->ulFuncAddr)
|
|
{
|
|
dwCompareCode = -1;
|
|
}
|
|
else if (*pdwVal1 >= val2->ulFuncAddr + val2->ulCodeLength)
|
|
{
|
|
dwCompareCode = 1;
|
|
}
|
|
return (dwCompareCode);
|
|
#elif defined(_PPC_)
|
|
if (*pdwVal1 == val2->ulFuncAddr + 12)
|
|
return 0;
|
|
if (*pdwVal1 > val2->ulFuncAddr + 12)
|
|
return 1;
|
|
else
|
|
return -1;
|
|
#endif
|
|
|
|
} /* WstBCompare () */
|
|
|
|
|
|
|
|
|
|
/*********************** W s t P s z C o m p a r e ********************************
|
|
*
|
|
* Function: WstPszCompare(PNDX pndxVal1, PNDX pndxVal2)
|
|
*
|
|
* Purpose: Compare values for qsort
|
|
*
|
|
*
|
|
* Parameters: PVOID
|
|
*
|
|
* Returns: -1 if val1 < val2
|
|
* 1 if val1 > val2
|
|
* 0 if val1 == val2
|
|
*
|
|
* History: 8-3-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
int WstPszCompare (PNDX pndxVal1, PNDX pndxVal2)
|
|
{
|
|
return (strcmp(pndxVal1->pszSymbol, pndxVal2->pszSymbol));
|
|
|
|
} /* WstPszCompare () */
|
|
|
|
|
|
|
|
|
|
|
|
/*********************** W s t P s z B C o m p a r e ********************************
|
|
*
|
|
* Function: WstPszBCompare(PSTR psz, PNDX pndx)
|
|
*
|
|
* Purpose: Compare values for Binary search
|
|
*
|
|
*
|
|
* Parameters: PVOID
|
|
*
|
|
* Returns: -1 if val1 < val2
|
|
* 1 if val1 > val2
|
|
* 0 if val1 == val2
|
|
*
|
|
* History: 8-3-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
int WstPszBCompare (PSTR psz, PNDX pndxVal2)
|
|
{
|
|
return (strcmp(psz, pndxVal2->pszSymbol));
|
|
|
|
} /* WstPszBCompare () */
|
|
|
|
|
|
|
|
|
|
|
|
/*********************** W s t P s z S o r t **************************************
|
|
*
|
|
* Function: WstPszSort(NDX ndx[], INT iLeft, INT iRight)
|
|
*
|
|
* Purpose: Sort NDX array for binary search
|
|
*
|
|
*
|
|
* Parameters: wsp[] Pointer to WSP array
|
|
* iLeft Left most index value for array
|
|
* iRight Rightmost index value for array
|
|
*
|
|
* Returns: NONE
|
|
*
|
|
* History: 8-4-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
void WstPszSort (NDX ndx[], INT iLeft, INT iRight)
|
|
{
|
|
INT i, iLast;
|
|
|
|
|
|
if (iLeft >= iRight)
|
|
{
|
|
return;
|
|
}
|
|
|
|
WstPszSwap(ndx, iLeft, (iLeft + iRight)/2);
|
|
iLast = iLeft;
|
|
for (i=iLeft+1; i <= iRight ; i++ )
|
|
{
|
|
if(WstPszCompare(&ndx[i], &ndx[iLeft]) < 0)
|
|
{
|
|
WstPszSwap(ndx, ++iLast, i);
|
|
}
|
|
}
|
|
|
|
WstPszSwap(ndx, iLeft, iLast);
|
|
WstPszSort(ndx, iLeft, iLast-1);
|
|
WstPszSort(ndx, iLast+1, iRight);
|
|
|
|
} /* WstPszSort () */
|
|
|
|
|
|
|
|
|
|
|
|
/*********************** W s t P s z S w a p *********************************
|
|
*
|
|
* Function: WstPszSwap(WSP wsp[], INT i, INT j)
|
|
*
|
|
* Purpose: Helper function for WstSort to swap WSP array values
|
|
*
|
|
*
|
|
* Parameters: wsp[] Pointer to WSP array
|
|
* i index value to swap to
|
|
* i index value to swap from
|
|
*
|
|
* Returns: NONE
|
|
*
|
|
* History: 8-4-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
void WstPszSwap (NDX ndx[], INT i, INT j)
|
|
{
|
|
NDX ndxTmp;
|
|
|
|
|
|
ndxTmp = ndx[i];
|
|
ndx[i] = ndx[j];
|
|
ndx[j] = ndxTmp;
|
|
|
|
} /* WstPszSwap () */
|
|
|
|
|
|
|
|
|
|
|
|
/*********************** W s t P s z B S e a r c h *******************************
|
|
*
|
|
* Function: WstPszBSearch(DWORD dwAddr, WSP wspCur[], INT n)
|
|
*
|
|
* Purpose: Binary search function for finding a match in the WSP array
|
|
*
|
|
*
|
|
* Parameters: dwAddr Address of calling function
|
|
* wspCur[]Pointer to WSP containg value to match with dwAddr
|
|
* n Number of elements in WSP array
|
|
*
|
|
* Returns: PWSP Pointer to matching WSP
|
|
*
|
|
* History: 8-5-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
ULONG WstPszBSearch (PSTR psz, NDX ndx[], INT n)
|
|
{
|
|
int i;
|
|
ULONG ulHigh = n;
|
|
ULONG ulLow = 0;
|
|
ULONG ulMid;
|
|
|
|
|
|
while(ulLow < ulHigh)
|
|
{
|
|
ulMid = ulLow + (ulHigh - ulLow) /2;
|
|
if((i = WstPszBCompare(psz, &ndx[ulMid])) < 0)
|
|
{
|
|
ulHigh = ulMid;
|
|
}
|
|
else if (i > 0)
|
|
{
|
|
ulLow = ulMid + 1;
|
|
}
|
|
else
|
|
{
|
|
return (ndx[ulMid].ulIndex);
|
|
}
|
|
}
|
|
|
|
return (0L);
|
|
|
|
} /* WstPszBSearch () */
|
|
|
|
|
|
|
|
|
|
|
|
/*********************** W s t S o r t **************************************
|
|
*
|
|
* Function: WstSort(WSP wsp[], INT iLeft, INT iRight)
|
|
*
|
|
* Purpose: Sort WSP array for binary search
|
|
*
|
|
*
|
|
* Parameters: wsp[] Pointer to WSP array
|
|
* iLeft Left most index value for array
|
|
* iRight Rightmost index value for array
|
|
*
|
|
* Returns: NONE
|
|
*
|
|
* History: 8-4-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
void WstSort (WSP wsp[], INT iLeft, INT iRight)
|
|
{
|
|
INT i, iLast;
|
|
|
|
|
|
if (iLeft >= iRight)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
WstSwap(wsp, iLeft, (iLeft + iRight)/2);
|
|
|
|
iLast = iLeft;
|
|
|
|
for (i=iLeft+1; i <= iRight ; i++ )
|
|
{
|
|
if(WstCompare(&wsp[i], &wsp[iLeft]) < 0)
|
|
{
|
|
if(!wsp[i].ulFuncAddr)
|
|
{
|
|
SdPrint(("WST: WstSort() - Error in symbol list ulFuncAddr: "
|
|
"0x%lx [%d]\n", wsp[i].ulFuncAddr, i));
|
|
}
|
|
WstSwap(wsp, ++iLast, i);
|
|
}
|
|
}
|
|
|
|
WstSwap(wsp, iLeft, iLast);
|
|
WstSort(wsp, iLeft, iLast-1);
|
|
WstSort(wsp, iLast+1, iRight);
|
|
|
|
} /* WstSort () */
|
|
|
|
|
|
|
|
|
|
|
|
/*********************** W s t S w a p **************************************
|
|
*
|
|
* Function: WstSwap(WSP wsp[], INT i, INT j)
|
|
*
|
|
* Purpose: Helper function for WstSort to swap WSP array values
|
|
*
|
|
*
|
|
* Parameters: wsp[] Pointer to WSP array
|
|
* i index value to swap to
|
|
* i index value to swap from
|
|
*
|
|
* Returns: NONE
|
|
*
|
|
* History: 8-4-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
void WstSwap (WSP wsp[], INT i, INT j)
|
|
{
|
|
WSP wspTmp;
|
|
|
|
|
|
wspTmp = wsp[i];
|
|
wsp[i] = wsp[j];
|
|
wsp[j] = wspTmp;
|
|
|
|
} /* WstSwap () */
|
|
|
|
|
|
|
|
|
|
|
|
/*********************** W s t B S e a r c h *******************************
|
|
*
|
|
* Function: WstBSearch(DWORD dwAddr, WSP wspCur[], INT n)
|
|
*
|
|
* Purpose: Binary search function for finding a match in the WSP array
|
|
*
|
|
*
|
|
* Parameters: dwAddr Address of calling function
|
|
* wspCur[]Pointer to WSP containg value to match with dwAddr
|
|
* n Number of elements in WSP array
|
|
*
|
|
* Returns: PWSP Pointer to matching WSP
|
|
*
|
|
* History: 8-5-92 Marklea - created
|
|
*
|
|
*/
|
|
|
|
PWSP WstBSearch (DWORD dwAddr, WSP wspCur[], INT n)
|
|
{
|
|
int i;
|
|
ULONG ulHigh = n;
|
|
ULONG ulLow = 0;
|
|
ULONG ulMid;
|
|
|
|
|
|
while(ulLow < ulHigh)
|
|
{
|
|
ulMid = ulLow + (ulHigh - ulLow) /2;
|
|
if((i = WstBCompare(&dwAddr, &wspCur[ulMid])) < 0)
|
|
{
|
|
ulHigh = ulMid;
|
|
}
|
|
else if (i > 0)
|
|
{
|
|
ulLow = ulMid + 1;
|
|
}
|
|
else
|
|
{
|
|
return (&wspCur[ulMid]);
|
|
}
|
|
|
|
}
|
|
|
|
return (NULL);
|
|
|
|
} /* WstBSearch () */
|
|
|
|
|
|
|
|
|
|
/************************** W s t D u m p t h r e a d ***********************
|
|
*
|
|
* WstDumpThread (pvArg) -
|
|
* This routine is executed as the DUMP notification thread.
|
|
* It will wait on an event before calling the dump routine.
|
|
*
|
|
* ENTRY pvArg - thread's single argument
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN 0
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* Leaves profiling turned off.
|
|
*
|
|
*/
|
|
|
|
DWORD WstDumpThread (PVOID pvArg)
|
|
{
|
|
NTSTATUS Status;
|
|
int i;
|
|
|
|
|
|
pvArg; // prevent compiler warnings
|
|
|
|
|
|
SdPrint (("WST: WstDumpThread() started.. TEB=0x%lx\n", NtCurrentTeb()));
|
|
|
|
for (;;)
|
|
{
|
|
//
|
|
// Wait for the DUMP event..
|
|
//
|
|
Status = NtWaitForSingleObject (hDumpEvent, FALSE, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDumpThread() - "
|
|
"ERROR - Wait for DUMP event failed - 0x%lx\n", Status));
|
|
}
|
|
Status = NtResetEvent (hDoneEvent, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDumpThread() - "
|
|
"ERROR - Resetting DONE event failed - 0x%lx\n", Status));
|
|
}
|
|
fInThread = TRUE;
|
|
(*pulShared)++;
|
|
if (WstState != NOT_STARTED)
|
|
{
|
|
|
|
IdPrint (("WST: Profiling stopped & DUMPing data... \n"));
|
|
|
|
// Stop profiling
|
|
//
|
|
WstState = NOT_STARTED;
|
|
|
|
// Dump the data
|
|
//
|
|
if (ulBitCount != 0L)
|
|
{
|
|
ulSnaps++;
|
|
}
|
|
|
|
//
|
|
// Get the GLOBAL semaphore.. (valid accross all process contexts)
|
|
//
|
|
Status = NtWaitForSingleObject (hGlobalSem, FALSE, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDumpThread() - "
|
|
"ERROR - Wait for GLOBAL semaphore failed - 0x%lx\n",
|
|
Status));
|
|
}
|
|
for (i=0; i<iImgCnt; i++)
|
|
{
|
|
WstClearBitStrings (&aImg[i]);
|
|
WstRotateWsiMem (&aImg[i]);
|
|
WstDumpData (&aImg[i]);
|
|
WstWriteTmiFile (&aImg[i]);
|
|
}
|
|
//
|
|
// Release the GLOBAL semaphore so other processes can dump data
|
|
//
|
|
Status = NtReleaseSemaphore (hGlobalSem, 1, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDumpThread() - "
|
|
"Error releasing GLOBAL semaphore - 0x%lx\n", Status));
|
|
}
|
|
|
|
IdPrint (("WST: ...data DUMPed & profiling stopped.\n"));
|
|
}
|
|
|
|
(*pulShared)--;
|
|
if ( *pulShared == 0L )
|
|
{
|
|
Status = NtSetEvent (hDoneEvent, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDumpThread() - "
|
|
"ERROR - Setting DONE event failed - 0x%lx\n",
|
|
Status));
|
|
}
|
|
}
|
|
|
|
fInThread = FALSE;
|
|
}
|
|
|
|
return 0;
|
|
|
|
} /* WstDumpThread () */
|
|
|
|
|
|
|
|
|
|
|
|
/************************ W s t C l e a r T h r e a d ***********************
|
|
*
|
|
* WstClearThread (hNotifyEvent) -
|
|
* This routine is executed as the CLEAR notification thread.
|
|
* It will wait on an event before calling the clear routine
|
|
* and restarting profiling.
|
|
*
|
|
* ENTRY pvArg - thread's single argument
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN -none-
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
DWORD WstClearThread (PVOID pvArg)
|
|
{
|
|
NTSTATUS Status;
|
|
int i;
|
|
|
|
|
|
pvArg; // prevent compiler warnings
|
|
|
|
|
|
SdPrint (("WST: WstClearThread() started.. TEB=0x%lx\n", NtCurrentTeb()));
|
|
|
|
for (;;)
|
|
{
|
|
//
|
|
// Wait for the CLEAR event..
|
|
//
|
|
Status = NtWaitForSingleObject (hClearEvent, FALSE, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstClearThread() - "
|
|
"Wait for CLEAR event failed - 0x%lx\n", Status));
|
|
}
|
|
Status = NtResetEvent (hDoneEvent, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstClearThread() - "
|
|
"ERROR - Resetting DONE event failed - 0x%lx\n", Status));
|
|
}
|
|
fInThread = TRUE;
|
|
(*pulShared)++;
|
|
|
|
IdPrint (("WST: Profiling stopped & CLEARing data...\n"));
|
|
|
|
// Stop profiling while clearing data
|
|
//
|
|
WstState = STOPPED;
|
|
|
|
// Clear WST info
|
|
//
|
|
ulBitCount = 0L;
|
|
ulSnaps = 0L;
|
|
|
|
for (i=0; i<iImgCnt; i++)
|
|
{
|
|
aImg[i].pulWsiNxt = aImg[i].pulWsi;
|
|
RtlZeroMemory (aImg[i].pulWsi,
|
|
aImg[i].iSymCnt * MAX_SNAPS * sizeof(ULONG));
|
|
RtlZeroMemory (aImg[i].pulWsp,
|
|
aImg[i].iSymCnt * MAX_SNAPS * sizeof(ULONG));
|
|
}
|
|
NtQueryPerformanceCounter (&liStart, NULL);
|
|
|
|
// Resume profiling
|
|
//
|
|
WstState = STARTED;
|
|
|
|
IdPrint (("WST: ...data is CLEARed & profiling restarted.\n"));
|
|
|
|
(*pulShared)--;
|
|
if ( *pulShared == 0L )
|
|
{
|
|
Status = NtSetEvent (hDoneEvent, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstClearThread() - "
|
|
"ERROR - Setting DONE event failed - 0x%lx\n",
|
|
Status));
|
|
}
|
|
}
|
|
|
|
fInThread = FALSE;
|
|
}
|
|
|
|
return 0;
|
|
|
|
} /* WstClearThread () */
|
|
|
|
|
|
|
|
|
|
|
|
/************************ W s t P a u s e T h r e a d ***********************
|
|
*
|
|
* WstPauseThread (hNotifyEvent) -
|
|
* This routine is executed as the PAUSE notification thread.
|
|
* It will wait on an event before pausing the profiling.
|
|
*
|
|
* ENTRY pvArg - thread's single argument
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN -none-
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
DWORD WstPauseThread (PVOID pvArg)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
|
|
pvArg; // prevent compiler warnings
|
|
|
|
|
|
SdPrint (("WST: WstPauseThread() started.. TEB=0x%lx\n", NtCurrentTeb()));
|
|
|
|
for (;;)
|
|
{
|
|
//
|
|
// Wait for the PASUE event..
|
|
//
|
|
Status = NtWaitForSingleObject (hPauseEvent, FALSE, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstPauseThread() - "
|
|
"Wait for PAUSE event failed - 0x%lx\n", Status));
|
|
}
|
|
Status = NtResetEvent (hDoneEvent, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstPauseThread() - "
|
|
"ERROR - Resetting DONE event failed - 0x%lx\n", Status));
|
|
}
|
|
fInThread = TRUE;
|
|
(*pulShared)++;
|
|
if (WstState == STARTED)
|
|
{
|
|
//
|
|
// Stop profiling
|
|
//
|
|
WstState = STOPPED;
|
|
|
|
IdPrint (("WST: Profiling stopped.\n"));
|
|
}
|
|
|
|
(*pulShared)--;
|
|
if ( *pulShared == 0L )
|
|
{
|
|
Status = NtSetEvent (hDoneEvent, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstPauseThread() - "
|
|
"ERROR - Setting DONE event failed - 0x%lx\n",
|
|
Status));
|
|
}
|
|
}
|
|
|
|
fInThread = FALSE;
|
|
}
|
|
|
|
return 0;
|
|
|
|
} /* WstPauseThread () */
|
|
|
|
|
|
|
|
/*********************** W s t D a t a O v e r F l o w **********************
|
|
*
|
|
* WstDataOverFlow () -
|
|
* This routine is called upon lack of space for storing next
|
|
* time snap data. It dumps and then clears the WST data.
|
|
*
|
|
* ENTRY -none-
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN -none-
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
void WstDataOverFlow(void)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Dump data
|
|
//
|
|
Status = NtResetEvent (hDoneEvent, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDataOverFlow() - "
|
|
"ERROR - Resetting DONE event failed - 0x%lx\n", Status));
|
|
}
|
|
Status = NtPulseEvent (hDumpEvent, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDataOverFlow() - NtPulseEvent() "
|
|
"failed for DUMP event - %lx\n", Status));
|
|
}
|
|
Status = NtWaitForSingleObject (hDoneEvent, FALSE, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDataOverFlow() - NtWaitForSingleObject() "
|
|
"failed for DONE event - %lx\n", Status));
|
|
}
|
|
|
|
//
|
|
// Clear data
|
|
//
|
|
Status = NtResetEvent (hDoneEvent, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDataOverFlow() - "
|
|
"ERROR - Resetting DONE event failed - 0x%lx\n", Status));
|
|
}
|
|
Status = NtPulseEvent (hClearEvent, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDataOverFlow() - NtPulseEvent() "
|
|
"failed for CLEAR event - %lx\n", Status));
|
|
}
|
|
//
|
|
// Wait for the DONE event..
|
|
//
|
|
Status = NtWaitForSingleObject (hDoneEvent, FALSE, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstDataOverFlow() - NtWaitForSingleObject() "
|
|
"failed for DONE event - %lx\n", Status));
|
|
}
|
|
} /* WstDataOverFlow() */
|
|
|
|
|
|
|
|
/************** W s t G e t C o f f D e b u g D i r e c t o r y *************
|
|
*
|
|
* WstGetCoffDebugDirectory (pDbgDir, ulDbgDirSz)
|
|
* Finds the coff debug directory. Cannot assume that the first
|
|
* debug directory if the coff one.
|
|
*
|
|
* ENTRY pDbgDir - Pointer to the first debug directory
|
|
* ulDbgDirSz - Size of all debug directories
|
|
*
|
|
* EXIT pDbgDir - Pointer to the coff debug directory (if any)
|
|
*
|
|
* RETURN TURE - If there is a coff debug directory
|
|
* FALSE - otherwise.
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
BOOL WstGetCoffDebugDirectory (PIMAGE_DEBUG_DIRECTORY *pDbgDir, ULONG ulDbgDirSz)
|
|
{
|
|
while (ulDbgDirSz > 0L)
|
|
{
|
|
if ((*pDbgDir)->Type == IMAGE_DEBUG_TYPE_COFF)
|
|
{
|
|
return (TRUE);
|
|
}
|
|
else
|
|
{
|
|
(*pDbgDir)++;
|
|
ulDbgDirSz -= sizeof (IMAGE_DEBUG_DIRECTORY);
|
|
}
|
|
}
|
|
return (FALSE);
|
|
|
|
} /* WstGetCoffDebugDirectory () */
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef BATCHING
|
|
|
|
BOOL WstOpenBatchFile(VOID)
|
|
{
|
|
NTSTATUS Status;
|
|
ANSI_STRING ObjName;
|
|
UNICODE_STRING UnicodeName;
|
|
OBJECT_ATTRIBUTES ObjAttributes;
|
|
IO_STATUS_BLOCK iostatus;
|
|
RtlInitString(&ObjName, "\\Device\\Harddisk0\\Partition1\\wst\\BATCH.TXT");
|
|
Status = RtlAnsiStringToUnicodeString(&UnicodeName, &ObjName, TRUE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstOpenBatchFile() - "
|
|
"RtlAnsiStringToUnicodeString() failed - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
|
|
InitializeObjectAttributes (&ObjAttributes,
|
|
&UnicodeName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
&SecDescriptor);
|
|
|
|
Status = NtCreateFile(&hBatchFile,
|
|
GENERIC_WRITE | SYNCHRONIZE, // Desired access
|
|
&ObjAttributes, // Object attributes
|
|
&iostatus, // Completion status
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_WRITE,
|
|
FILE_OVERWRITE_IF,
|
|
FILE_SEQUENTIAL_ONLY | // Open option
|
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
|
NULL,
|
|
0L);
|
|
|
|
RtlFreeUnicodeString (&UnicodeName); // HWC 11/93
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
KdPrint (("WST: WstOpenBatchFile() - "
|
|
"NtCreateFile() failed - 0x%lx\n", Status));
|
|
return (FALSE);
|
|
}
|
|
return(TRUE);
|
|
|
|
} /* WstOpenBatchFile () */
|
|
|
|
#endif
|
|
|
|
|
|
/******************* S e t S y m b o l S e a r c h P a t h ******************
|
|
*
|
|
* SetSymbolSearchPath ()
|
|
* Return complete search path for symbols files (.dbg)
|
|
*
|
|
* ENTRY -none-
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN -none-
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* "lpSymbolSearchPath" global LPSTR variable will point to the
|
|
* search path.
|
|
*/
|
|
#define FilePathLen 256
|
|
|
|
void SetSymbolSearchPath (void)
|
|
{
|
|
CHAR SymPath[FilePathLen];
|
|
CHAR AltSymPath[FilePathLen];
|
|
CHAR SysRootPath[FilePathLen];
|
|
LPSTR lpSymPathEnv=SymPath;
|
|
LPSTR lpAltSymPathEnv=AltSymPath;
|
|
LPSTR lpSystemRootEnv=SysRootPath;
|
|
ULONG cbSymPath;
|
|
DWORD dw;
|
|
HANDLE hMemoryHandle;
|
|
|
|
SymPath[0] = AltSymPath[0] = SysRootPath[0] = '\0';
|
|
|
|
cbSymPath = 18;
|
|
// if (lpSymPathEnv = getenv("_NT_SYMBOL_PATH"))
|
|
if (GetEnvironmentVariable("_NT_SYMBOL_PATH", SymPath, sizeof(SymPath)))
|
|
{
|
|
cbSymPath += strlen(lpSymPathEnv) + 1;
|
|
}
|
|
|
|
// if (lpAltSymPathEnv = getenv("_NT_ALT_SYMBOL_PATH"))
|
|
if (GetEnvironmentVariable("_NT_ALT_SYMBOL_PATH", AltSymPath, sizeof(AltSymPath)))
|
|
{
|
|
cbSymPath += strlen(lpAltSymPathEnv) + 1;
|
|
}
|
|
|
|
// if (lpSystemRootEnv = getenv("SystemRoot"))
|
|
if (GetEnvironmentVariable("SystemRoot", SysRootPath, sizeof(SysRootPath)))
|
|
{
|
|
cbSymPath += strlen(lpSystemRootEnv) + 1;
|
|
}
|
|
|
|
// lpSymbolSearchPath = (LPSTR)calloc(cbSymPath,1);
|
|
hMemoryHandle = GlobalAlloc (GHND, cbSymPath+1);
|
|
if (!hMemoryHandle)
|
|
{
|
|
return;
|
|
}
|
|
|
|
lpSymbolSearchPath = GlobalLock (hMemoryHandle);
|
|
if (!lpSymbolSearchPath)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
if (*lpAltSymPathEnv)
|
|
{
|
|
dw = GetFileAttributes(lpAltSymPathEnv);
|
|
if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY )
|
|
{
|
|
strcat(lpSymbolSearchPath,lpAltSymPathEnv);
|
|
strcat(lpSymbolSearchPath,";");
|
|
}
|
|
}
|
|
if (*lpSymPathEnv)
|
|
{
|
|
dw = GetFileAttributes(lpSymPathEnv);
|
|
if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY )
|
|
{
|
|
strcat(lpSymbolSearchPath,lpSymPathEnv);
|
|
strcat(lpSymbolSearchPath,";");
|
|
}
|
|
}
|
|
if (*lpSystemRootEnv)
|
|
{
|
|
dw = GetFileAttributes(lpSystemRootEnv);
|
|
if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY )
|
|
{
|
|
strcat(lpSymbolSearchPath,lpSystemRootEnv);
|
|
strcat(lpSymbolSearchPath,";");
|
|
}
|
|
}
|
|
|
|
strcat(lpSymbolSearchPath,".;");
|
|
|
|
} /* SetSymbolSearchPath () */
|
|
|
|
#ifdef i386
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: SaveAllRegs
|
|
//
|
|
// Synopsis: Save all regs.
|
|
//
|
|
// Arguments: nothing
|
|
//
|
|
// Returns: none
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
Naked void SaveAllRegs(void)
|
|
{
|
|
_asm
|
|
{
|
|
push ebp
|
|
mov ebp,esp ; Remember where we are during this stuff
|
|
; ebp = Original esp - 4
|
|
|
|
push eax ; Save all regs that we think we might
|
|
push ebx ; destroy
|
|
push ecx
|
|
push edx
|
|
push esi
|
|
push edi
|
|
pushfd
|
|
push ds
|
|
push es
|
|
push ss
|
|
push fs
|
|
push gs
|
|
|
|
mov eax,[ebp+4] ; Grab Return Address
|
|
push eax ; Put Return Address on Stack so we can RET
|
|
|
|
mov ebp,[ebp+0] ; Restore original ebp
|
|
|
|
//
|
|
// This is how the stack looks like before the RET statement
|
|
//
|
|
// +-----------+
|
|
// | Ret Addr | + 3ch CurrentEBP + 4
|
|
// +-----------+
|
|
// | Org ebp | + 38h CurrentEBP + 0
|
|
// +-----------+
|
|
// | eax | + 34h
|
|
// +-----------+
|
|
// | ebx | + 30h
|
|
// +-----------+
|
|
// | ecx | + 2ch
|
|
// +-----------+
|
|
// | edx | + 24h
|
|
// +-----------+
|
|
// | esi | + 20h
|
|
// +-----------+
|
|
// | edi | + 1ch
|
|
// +-----------+
|
|
// | eflags | + 18h
|
|
// +-----------+
|
|
// | ds | + 14h
|
|
// +-----------+
|
|
// | es | + 10h
|
|
// +-----------+
|
|
// | ss | + ch
|
|
// +-----------+
|
|
// | fs | + 8h
|
|
// +-----------+
|
|
// | gs | + 4h
|
|
// +-----------+
|
|
// | Ret Addr | ESP + 0h
|
|
// +-----------+
|
|
|
|
ret
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: RestoreAllRegs
|
|
//
|
|
// Synopsis: restore all regs
|
|
//
|
|
// Arguments: nothing
|
|
//
|
|
// Returns: none
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
Naked void RestoreAllRegs(void)
|
|
{
|
|
_asm
|
|
{
|
|
//
|
|
// This is how the stack looks like upon entering this routine
|
|
//
|
|
// +-----------+
|
|
// | Ret Addr | + 38h [ RetAddr for SaveAllRegs() ]
|
|
// +-----------+
|
|
// | Org ebp | + 34h
|
|
// +-----------+
|
|
// | eax | + 30h
|
|
// +-----------+
|
|
// | ebx | + 2Ch
|
|
// +-----------+
|
|
// | ecx | + 28h
|
|
// +-----------+
|
|
// | edx | + 24h
|
|
// +-----------+
|
|
// | esi | + 20h
|
|
// +-----------+
|
|
// | edi | + 1Ch
|
|
// +-----------+
|
|
// | eflags | + 18h
|
|
// +-----------+
|
|
// | ds | + 14h
|
|
// +-----------+
|
|
// | es | + 10h
|
|
// +-----------+
|
|
// | ss | + Ch
|
|
// +-----------+
|
|
// | fs | + 8h
|
|
// +-----------+
|
|
// | gs | + 4h
|
|
// +-----------+
|
|
// | Ret EIP | ESP + 0h [ RetAddr for RestoreAllRegs() ]
|
|
// +-----------+
|
|
//
|
|
|
|
|
|
push ebp ; Save a temporary copy of original BP
|
|
mov ebp,esp ; BP = Original SP + 4
|
|
|
|
//
|
|
// This is how the stack looks like NOW!
|
|
//
|
|
// +-----------+
|
|
// | Ret Addr | + 3Ch [ RetAddr for SaveAllRegs() ]
|
|
// +-----------+
|
|
// | Org ebp | + 38h [ EBP before SaveAllRegs() ]
|
|
// +-----------+
|
|
// | eax | + 34h
|
|
// +-----------+
|
|
// | ebx | + 30h
|
|
// +-----------+
|
|
// | ecx | + 2Ch
|
|
// +-----------+
|
|
// | edx | + 28h
|
|
// +-----------+
|
|
// | esi | + 24h
|
|
// +-----------+
|
|
// | edi | + 20h
|
|
// +-----------+
|
|
// | eflags | + 1Ch
|
|
// +-----------+
|
|
// | ds | + 18h
|
|
// +-----------+
|
|
// | es | + 14h
|
|
// +-----------+
|
|
// | ss | + 10h
|
|
// +-----------+
|
|
// | fs | + Ch
|
|
// +-----------+
|
|
// | gs | + 8h
|
|
// +-----------+
|
|
// | Ret EIP | ESP + 4h [ RetAddr for RestoreAllRegs() ]
|
|
// +-----------+
|
|
// | EBP | ESP + 0h or EBP + 0h
|
|
// +-----------+
|
|
//
|
|
|
|
pop eax ; Get Original EBP
|
|
mov [ebp+38h],eax ; Put it in the original EBP place
|
|
; This EBP is the EBP before calling
|
|
; RestoreAllRegs()
|
|
pop eax ; Get ret address for RestoreAllRegs()
|
|
mov [ebp+3Ch],eax ; Put Return Address on Stack
|
|
|
|
pop gs ; Restore all regs
|
|
pop fs
|
|
pop ss
|
|
pop es
|
|
pop ds
|
|
popfd
|
|
pop edi
|
|
pop esi
|
|
pop edx
|
|
pop ecx
|
|
pop ebx
|
|
pop eax
|
|
pop ebp
|
|
|
|
ret
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|