mirror of
https://github.com/SWG-Source/src.git
synced 2026-08-01 01:16:03 -04:00
attempt to remove (hopefully) unnecessary solaris and windows files; fix a couple potential leaks
This commit is contained in:
@@ -129,6 +129,8 @@ void DebugMonitor::install(void)
|
||||
if (tcgetattr(inputFd, &terminalAttributes) != 0)
|
||||
{
|
||||
DEBUG_WARNING(true, ("DebugMonitor: tcgetattr failed [%s].", strerror(errno)));
|
||||
fclose(s_ttyOutputFile);
|
||||
fclose(s_ttyInputFile);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,670 +0,0 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DebugHelp.cpp
|
||||
// copyright 2000 Verant Interactive
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDebug/FirstSharedDebug.h"
|
||||
#include "sharedDebug/DebugHelp.h"
|
||||
|
||||
#include "sharedFoundation/WindowsWrapper.h"
|
||||
|
||||
#include <dbghelp.h>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
|
||||
// ======================================================================
|
||||
// This was done to keep the header file from having to include <windows.h> or <dbghelp.h>
|
||||
|
||||
namespace DebugHelpNamespace
|
||||
{
|
||||
static HINSTANCE library;
|
||||
static HANDLE process;
|
||||
|
||||
struct CallbackData
|
||||
{
|
||||
const char *name;
|
||||
bool loaded;
|
||||
};
|
||||
|
||||
typedef DWORD (__stdcall *SymSetOptionsFP)(IN DWORD SymOptions);
|
||||
typedef BOOL (__stdcall *SymInitializeFP)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess);
|
||||
typedef BOOL (__stdcall *SymCleanupFP)(IN HANDLE hProcess);
|
||||
|
||||
typedef BOOL (__stdcall *StackWalk64FP)(DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
|
||||
typedef BOOL (__stdcall *SymGetModuleInfo64FP)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PIMAGEHLP_MODULE64 ModuleInfo);
|
||||
typedef DWORD64 (__stdcall *SymLoadModule64FP)(IN HANDLE hProcess, IN HANDLE hFile, IN PSTR ImageName, IN PSTR ModuleName, IN DWORD64 BaseOfDll, IN DWORD SizeOfDll);
|
||||
typedef BOOL (__stdcall *SymGetSymFromAddr64FP)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol);
|
||||
typedef BOOL (__stdcall *SymGetLineFromAddr64FP)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line);
|
||||
typedef PVOID (__stdcall *SymFunctionTableAccess64FP)(HANDLE hProcess, DWORD64 AddrBase);
|
||||
typedef DWORD64 (__stdcall *SymGetModuleBase64FP)(IN HANDLE hProcess, IN DWORD64 dwAddr);
|
||||
typedef BOOL (__stdcall *SymEnumerateModules64FP)(HANDLE hProcess, PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback, PVOID UserContext);
|
||||
typedef BOOL (__stdcall *EnumerateLoadedModules64FP)(IN HANDLE hProcess, IN PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback, IN PVOID UserContext);
|
||||
typedef BOOL (__stdcall *MiniDumpWriteDumpFP)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
|
||||
|
||||
static SymSetOptionsFP symSetOptions;
|
||||
static SymInitializeFP symInitialize;
|
||||
static SymCleanupFP symCleanup;
|
||||
static StackWalk64FP stackWalk64;
|
||||
static SymGetModuleInfo64FP symGetModuleInfo64;
|
||||
static SymLoadModule64FP symLoadModule64;
|
||||
static SymGetSymFromAddr64FP symGetSymFromAddr64;
|
||||
static SymGetLineFromAddr64FP symGetLineFromAddr64;
|
||||
static SymFunctionTableAccess64FP symFunctionTableAccess64;
|
||||
static SymGetModuleBase64FP symGetModuleBase64;
|
||||
static SymEnumerateModules64FP symEnumerateModules64;
|
||||
static EnumerateLoadedModules64FP enumerateLoadedModules64;
|
||||
static MiniDumpWriteDumpFP miniDumpWriteDump;
|
||||
static CRITICAL_SECTION criticalSection;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
//BOOL CALLBACK loadSymbolsForDllCallback(PTSTR ModuleName, DWORD64 ModuleBase, ULONG ModuleSize, PVOID UserContext);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
|
||||
typedef unsigned long int ub4; /* unsigned 4-byte quantities */
|
||||
typedef unsigned char ub1; /* unsigned 1-byte quantities */
|
||||
|
||||
#define hashsize(n) ((ub4)1<<(n))
|
||||
#define hashmask(n) (hashsize(n)-1)
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------
|
||||
mix -- mix 3 32-bit values reversibly.
|
||||
For every delta with one or two bits set, and the deltas of all three
|
||||
high bits or all three low bits, whether the original value of a,b,c
|
||||
is almost all zero or is uniformly distributed,
|
||||
* If mix() is run forward or backward, at least 32 bits in a,b,c
|
||||
have at least 1/4 probability of changing.
|
||||
* If mix() is run forward, every bit of c will change between 1/3 and
|
||||
2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
|
||||
mix() was built out of 36 single-cycle latency instructions in a
|
||||
structure that could supported 2x parallelism, like so:
|
||||
a -= b;
|
||||
a -= c; x = (c>>13);
|
||||
b -= c; a ^= x;
|
||||
b -= a; x = (a<<8);
|
||||
c -= a; b ^= x;
|
||||
c -= b; x = (b>>13);
|
||||
...
|
||||
Unfortunately, superscalar Pentiums and Sparcs can't take advantage
|
||||
of that parallelism. They've also turned some of those single-cycle
|
||||
latency instructions into multi-cycle latency instructions. Still,
|
||||
this is the fastest good hash I could find. There were about 2^^68
|
||||
to choose from. I only looked at a billion or so.
|
||||
--------------------------------------------------------------------
|
||||
*/
|
||||
#define mix(a,b,c) \
|
||||
{ \
|
||||
a -= b; a -= c; a ^= (c>>13); \
|
||||
b -= c; b -= a; b ^= (a<<8); \
|
||||
c -= a; c -= b; c ^= (b>>13); \
|
||||
a -= b; a -= c; a ^= (c>>12); \
|
||||
b -= c; b -= a; b ^= (a<<16); \
|
||||
c -= a; c -= b; c ^= (b>>5); \
|
||||
a -= b; a -= c; a ^= (c>>3); \
|
||||
b -= c; b -= a; b ^= (a<<10); \
|
||||
c -= a; c -= b; c ^= (b>>15); \
|
||||
}
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------
|
||||
hash() -- hash a variable-length key into a 32-bit value
|
||||
k : the key (the unaligned variable-length array of bytes)
|
||||
len : the length of the key, counting by bytes
|
||||
initval : can be any 4-byte value
|
||||
Returns a 32-bit value. Every bit of the key affects every bit of
|
||||
the return value. Every 1-bit and 2-bit delta achieves avalanche.
|
||||
About 6*len+35 instructions.
|
||||
|
||||
The best hash table sizes are powers of 2. There is no need to do
|
||||
mod a prime (mod is sooo slow!). If you need less than 32 bits,
|
||||
use a bitmask. For example, if you need only 10 bits, do
|
||||
h = (h & hashmask(10));
|
||||
In which case, the hash table should have hashsize(10) elements.
|
||||
|
||||
If you are hashing n strings (ub1 **)k, do it like this:
|
||||
for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
|
||||
|
||||
By Bob Jenkins, 1996. [email protected]. You may use this
|
||||
code any way you wish, private, educational, or commercial. It's free.
|
||||
|
||||
See http://burtleburtle.net/bob/hash/evahash.html
|
||||
Use for hash table lookup, or anything where one collision in 2^^32 is
|
||||
acceptable. Do NOT use for cryptographic purposes.
|
||||
--------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// k; /* the key */
|
||||
// length; /* the length of the key */
|
||||
// initval; /* the previous hash, or an arbitrary value */
|
||||
#if 0
|
||||
static ub4 hash(ub1 *k, const ub4 length, const ub4 initval)
|
||||
{
|
||||
ub4 a, b, c, len;
|
||||
|
||||
/* Set up the internal state */
|
||||
len = length;
|
||||
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
|
||||
c = initval; /* the previous hash value */
|
||||
|
||||
/*---------------------------------------- handle most of the key */
|
||||
while (len >= 12)
|
||||
{
|
||||
a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
|
||||
b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
|
||||
c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
|
||||
mix(a,b,c);
|
||||
k += 12; len -= 12;
|
||||
}
|
||||
|
||||
/*------------------------------------- handle the last 11 bytes */
|
||||
c += length;
|
||||
switch(len) /* all the case statements fall through */
|
||||
{
|
||||
case 11: c+=((ub4)k[10]<<24);
|
||||
case 10: c+=((ub4)k[9]<<16);
|
||||
case 9 : c+=((ub4)k[8]<<8);
|
||||
/* the first byte of c is reserved for the length */
|
||||
case 8 : b+=((ub4)k[7]<<24);
|
||||
case 7 : b+=((ub4)k[6]<<16);
|
||||
case 6 : b+=((ub4)k[5]<<8);
|
||||
case 5 : b+=k[4];
|
||||
case 4 : a+=((ub4)k[3]<<24);
|
||||
case 3 : a+=((ub4)k[2]<<16);
|
||||
case 2 : a+=((ub4)k[1]<<8);
|
||||
case 1 : a+=k[0];
|
||||
/* case 0: nothing left to add */
|
||||
}
|
||||
mix(a,b,c);
|
||||
/*-------------------------------------------- report the result */
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
// version optimized for 4 byte input.
|
||||
static ub4 hash_DWORD(const DWORD in, const ub4 initval)
|
||||
{
|
||||
ub1 *const k = (ub1 *)∈
|
||||
ub4 a, b, c, len;
|
||||
|
||||
/* Set up the internal state */
|
||||
len = 4;
|
||||
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
|
||||
c = initval; /* the previous hash value */
|
||||
|
||||
/*------------------------------------- handle the last 11 bytes */
|
||||
c += 4;
|
||||
a+=((ub4)k[3]<<24);
|
||||
a+=((ub4)k[2]<<16);
|
||||
a+=((ub4)k[1]<<8);
|
||||
a+=k[0];
|
||||
|
||||
mix(a,b,c);
|
||||
|
||||
/*-------------------------------------------- report the result */
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
struct BaseAddressLookup
|
||||
{
|
||||
DWORD64 keyAddress; // key
|
||||
DWORD64 baseAddress; // value
|
||||
};
|
||||
|
||||
static BaseAddressLookup * s_baseAddressCache;
|
||||
static inline unsigned _baseAddressCachePageBits() { return 8; }
|
||||
static inline unsigned _baseAddressCacheBits() { return _baseAddressCachePageBits() + 12; }
|
||||
static inline unsigned _baseAddressCacheSize() { return 1 << (_baseAddressCacheBits()); }
|
||||
static inline unsigned _baseAddressCacheElements() { return _baseAddressCacheSize() / sizeof(*s_baseAddressCache); }
|
||||
static inline unsigned _baseAddressCacheMask() { return _baseAddressCacheElements() - 1; }
|
||||
|
||||
static int s_baseAddressCacheMisses;
|
||||
static int s_baseAddressCacheHits;
|
||||
|
||||
static int s_baseAddressElements;
|
||||
static int s_baseAddressUsed;
|
||||
|
||||
/*
|
||||
static void _baseAddressCacheAnalyze()
|
||||
{
|
||||
s_baseAddressElements=0;
|
||||
s_baseAddressUsed=0;
|
||||
|
||||
unsigned i;
|
||||
const unsigned count = _baseAddressCacheElements();
|
||||
for (i=0;i<count;i++)
|
||||
{
|
||||
const BaseAddressLookup *lookup = s_baseAddressCache + i;
|
||||
s_baseAddressElements++;
|
||||
if (lookup->baseAddress)
|
||||
{
|
||||
s_baseAddressUsed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static DWORD64 _baseAddressLookup(DWORD64 addr)
|
||||
{
|
||||
BaseAddressLookup *lookup;
|
||||
|
||||
unsigned long bits = _baseAddressCacheBits();
|
||||
|
||||
DWORD *addr32 = (DWORD *)&addr;
|
||||
unsigned long hash32 = hash_DWORD(addr32[0], addr32[1]);
|
||||
unsigned long hash = (hash32>>(32-bits)) ^ hash32;
|
||||
|
||||
unsigned long mask = _baseAddressCacheMask();
|
||||
|
||||
unsigned long index = hash & mask;
|
||||
lookup = s_baseAddressCache + index;
|
||||
if (lookup->keyAddress==addr)
|
||||
{
|
||||
s_baseAddressCacheHits++;
|
||||
//DEBUG_FATAL(symGetModuleBase64(process, addr) != lookup->baseAddress, ("Cache failure.\n"));
|
||||
return lookup->baseAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_baseAddressCacheMisses++;
|
||||
|
||||
DWORD64 baseAddress = symGetModuleBase64(process, addr);
|
||||
|
||||
lookup->keyAddress=addr;
|
||||
lookup->baseAddress=baseAddress;
|
||||
|
||||
return baseAddress;
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD64 __stdcall getModuleBase(HANDLE hProcess, DWORD64 dwAddr)
|
||||
{
|
||||
UNREF(hProcess);
|
||||
DEBUG_FATAL(hProcess!=process, ("Wrong process handle for module base lookup.\n"));
|
||||
return _baseAddressLookup(dwAddr);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
struct FunctionTableLookup
|
||||
{
|
||||
DWORD64 keyAddress; // key
|
||||
PVOID functionTable; // value
|
||||
};
|
||||
|
||||
static FunctionTableLookup * s_functionTableCache;
|
||||
static inline unsigned _functionTableCachePageBits() { return 4; }
|
||||
static inline unsigned _functionTableCacheBits() { return _functionTableCachePageBits() + 12; }
|
||||
static inline unsigned _functionTableCacheSize() { return 1 << (_functionTableCacheBits()); }
|
||||
static inline unsigned _functionTableCacheElements() { return _functionTableCacheSize() / sizeof(*s_functionTableCache); }
|
||||
static inline unsigned _functionTableCacheMask() { return _functionTableCacheElements() - 1; }
|
||||
|
||||
static int s_functionTableCacheMisses;
|
||||
static int s_functionTableCacheHits;
|
||||
|
||||
|
||||
static PVOID _functionTableLookup(DWORD64 addr)
|
||||
{
|
||||
FunctionTableLookup *lookup;
|
||||
|
||||
unsigned long bits = _functionTableCacheBits();
|
||||
|
||||
DWORD *addr32 = (DWORD *)&addr;
|
||||
unsigned long hash32 = hash_DWORD(addr32[0], addr32[1]);
|
||||
unsigned long hash = (hash32>>(32-bits)) ^ hash32;
|
||||
|
||||
unsigned long mask = _functionTableCacheMask();
|
||||
|
||||
unsigned long index = hash & mask;
|
||||
lookup = s_functionTableCache + index;
|
||||
if (lookup->keyAddress==addr)
|
||||
{
|
||||
s_functionTableCacheHits++;
|
||||
//DEBUG_FATAL(symFunctionTableAccess64(process, addr) != lookup->functionTable, ("Cache failure.\n"));
|
||||
return lookup->functionTable;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_functionTableCacheMisses++;
|
||||
PVOID functionTable = symFunctionTableAccess64(process, addr);
|
||||
lookup->keyAddress=addr;
|
||||
lookup->functionTable=functionTable;
|
||||
|
||||
return functionTable;
|
||||
}
|
||||
}
|
||||
|
||||
static PVOID __stdcall functionTableAccess(HANDLE hProcess, DWORD64 dwAddr)
|
||||
{
|
||||
UNREF(hProcess);
|
||||
DEBUG_FATAL(hProcess!=process, ("Wrong process handle for module base lookup.\n"));
|
||||
return _functionTableLookup(DWORD(dwAddr));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
}
|
||||
using namespace DebugHelpNamespace;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
BOOL CALLBACK loadSymbolsForDllCallback(PSTR ModuleName, DWORD64 ModuleBase, ULONG ModuleSize, PVOID UserContext)
|
||||
{
|
||||
if (!library)
|
||||
return false;
|
||||
|
||||
CallbackData *callbackData = reinterpret_cast<CallbackData *>(UserContext);
|
||||
|
||||
// see if this is the right file module and if we can load its symbol information
|
||||
if (_stricmp(ModuleName, callbackData->name) == 0 && symLoadModule64(process, NULL, ModuleName, 0, ModuleBase, ModuleSize) != 0)
|
||||
{
|
||||
callbackData->loaded = true;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void DebugHelp::install()
|
||||
{
|
||||
DEBUG_FATAL(library, ("DebugHelp already installed"));
|
||||
|
||||
library = LoadLibrary("dbghelp_6.3.17.0.dll");
|
||||
if (library)
|
||||
{
|
||||
process = GetCurrentProcess();
|
||||
|
||||
#define GPA(a, b) a = reinterpret_cast<b##FP>(GetProcAddress(library, #b)); DEBUG_FATAL(!a, ("GetProcAddress failed for " #b))
|
||||
GPA(symSetOptions, SymSetOptions);
|
||||
GPA(symInitialize, SymInitialize);
|
||||
GPA(symCleanup, SymCleanup);
|
||||
GPA(stackWalk64, StackWalk64);
|
||||
GPA(symGetModuleInfo64, SymGetModuleInfo64);
|
||||
GPA(symLoadModule64, SymLoadModule64);
|
||||
GPA(symGetSymFromAddr64, SymGetSymFromAddr64);
|
||||
GPA(symGetLineFromAddr64, SymGetLineFromAddr64);
|
||||
GPA(symFunctionTableAccess64, SymFunctionTableAccess64);
|
||||
GPA(symGetModuleBase64, SymGetModuleBase64);
|
||||
GPA(symEnumerateModules64, SymEnumerateModules64);
|
||||
GPA(enumerateLoadedModules64, EnumerateLoadedModules64);
|
||||
GPA(miniDumpWriteDump, MiniDumpWriteDump);
|
||||
#undef GPA
|
||||
|
||||
IGNORE_RETURN(symSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES));
|
||||
|
||||
// get the path to the executable
|
||||
char executableDirectory[MAX_PATH * 2];
|
||||
const DWORD result = GetModuleFileName(NULL, executableDirectory, sizeof(executableDirectory));
|
||||
FATAL(result == 0, ("GetModuleFileName failed"));
|
||||
char * const slash = strrchr(executableDirectory, '\\');
|
||||
DEBUG_FATAL(!slash, ("Executable path does not contain a slash"));
|
||||
*slash = '\0';
|
||||
|
||||
const BOOL result1 = symInitialize(process, executableDirectory, TRUE);
|
||||
UNREF(result1);
|
||||
DEBUG_FATAL(!result1, ("SymInitialize failed"));
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
s_baseAddressCache = (BaseAddressLookup *)VirtualAlloc(0, _baseAddressCacheSize(), MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
s_functionTableCache = (FunctionTableLookup *)VirtualAlloc(0, _functionTableCacheSize(), MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// Initialize the critical section one time only.
|
||||
InitializeCriticalSection(&criticalSection);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DebugHelp::remove()
|
||||
{
|
||||
if (s_baseAddressCache)
|
||||
{
|
||||
VirtualFree(s_baseAddressCache, 0, MEM_RELEASE);
|
||||
s_baseAddressCache=0;
|
||||
}
|
||||
|
||||
if (s_functionTableCache)
|
||||
{
|
||||
VirtualFree(s_functionTableCache, 0, MEM_RELEASE);
|
||||
s_functionTableCache=0;
|
||||
}
|
||||
|
||||
if (library)
|
||||
{
|
||||
IGNORE_RETURN(symCleanup(process));
|
||||
IGNORE_RETURN(FreeLibrary(library));
|
||||
library = NULL;
|
||||
process = NULL;
|
||||
symSetOptions = NULL;
|
||||
symInitialize = NULL;
|
||||
symCleanup = NULL;
|
||||
stackWalk64 = NULL;
|
||||
symGetModuleInfo64 = NULL;
|
||||
symLoadModule64 = NULL;
|
||||
symGetSymFromAddr64 = NULL;
|
||||
symGetLineFromAddr64 = NULL;
|
||||
symFunctionTableAccess64 = NULL;
|
||||
symGetModuleBase64 = NULL;
|
||||
symEnumerateModules64 = NULL;
|
||||
enumerateLoadedModules64 = NULL;
|
||||
}
|
||||
|
||||
// Release resources used by the critical section object.
|
||||
DeleteCriticalSection(&criticalSection);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DebugHelp::loadSymbolsForDll(const char *name)
|
||||
{
|
||||
if (!library)
|
||||
return false;
|
||||
|
||||
CallbackData callbackData = { name, false };
|
||||
enumerateLoadedModules64(process, (PENUMLOADED_MODULES_CALLBACK64)loadSymbolsForDllCallback, reinterpret_cast<void *>(&callbackData));
|
||||
return callbackData.loaded;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
#pragma warning (disable: 4740 4748)
|
||||
void DebugHelp::getCallStack(uint32 *callStack, int sizeOfCallStack)
|
||||
{
|
||||
{
|
||||
for (int i = 0; i < sizeOfCallStack; ++i)
|
||||
callStack[i] = 0;
|
||||
}
|
||||
|
||||
if (!library)
|
||||
return;
|
||||
|
||||
CONTEXT context;
|
||||
Zero(context);
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
|
||||
// GetThreadContext returns invalid data when called from within the same thread
|
||||
//if (!GetThreadContext(GetCurrentThread(), &context))
|
||||
// return;
|
||||
|
||||
EnterCriticalSection(&criticalSection);
|
||||
__asm
|
||||
{
|
||||
call GetEIP
|
||||
GetEIP:
|
||||
pop eax
|
||||
mov context.Eip, eax
|
||||
mov context.Esp, esp
|
||||
mov context.Ebp, ebp
|
||||
}
|
||||
LeaveCriticalSection(&criticalSection);
|
||||
|
||||
STACKFRAME64 stackFrame;
|
||||
Zero(stackFrame);
|
||||
stackFrame.AddrPC.Mode = AddrModeFlat;
|
||||
stackFrame.AddrPC.Offset = context.Eip;
|
||||
stackFrame.AddrStack.Offset = context.Esp;
|
||||
stackFrame.AddrStack.Mode = AddrModeFlat;
|
||||
stackFrame.AddrFrame.Offset = context.Ebp;
|
||||
stackFrame.AddrFrame.Mode = AddrModeFlat;
|
||||
|
||||
for (int i = 0; i < sizeOfCallStack; ++i, ++callStack)
|
||||
{
|
||||
if (stackWalk64(IMAGE_FILE_MACHINE_I386, process, process, &stackFrame, &context, NULL, functionTableAccess, getModuleBase, NULL))
|
||||
{
|
||||
const DWORD64 Offset = stackFrame.AddrPC.Offset;
|
||||
*callStack = DWORD(Offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DebugHelp::reportCallStack(int const maxStackDepth)
|
||||
{
|
||||
// look up the call stack information
|
||||
int const callStackOffset = 2;
|
||||
int const callStackSize = callStackOffset + maxStackDepth;
|
||||
uint32 * callStack = static_cast<uint32 *>(_alloca((callStackOffset + maxStackDepth) * sizeof(uint32)));
|
||||
getCallStack(callStack, callStackOffset + maxStackDepth);
|
||||
|
||||
// look up the caller's file and line
|
||||
if (callStack[callStackOffset])
|
||||
{
|
||||
char lib[4 * 1024] = { '\0' };
|
||||
char file[4 * 1024] = { '\0' };
|
||||
int line = 0;
|
||||
for (int i = callStackOffset; i < callStackSize; ++i)
|
||||
{
|
||||
if (callStack[i])
|
||||
{
|
||||
if (lookupAddress(callStack[i], lib, file, sizeof(file), line))
|
||||
REPORT_LOG(true, ("\t%s(%d) : caller %d\n", file, line, i-callStackOffset));
|
||||
else
|
||||
REPORT_LOG(true, ("\tunknown(0x%08X) : caller %d\n", static_cast<int>(callStack[i]), i-callStackOffset));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DebugHelp::lookupAddress(uint32 address, char *libName, char *fileName, int fileNameLength, int &line)
|
||||
{
|
||||
UNREF(libName);
|
||||
|
||||
if (!library)
|
||||
return false;
|
||||
|
||||
// make sure the image is loaded
|
||||
IMAGEHLP_MODULE64 imageHelpModule;
|
||||
Zero(imageHelpModule);
|
||||
imageHelpModule.SizeOfStruct = sizeof(imageHelpModule);
|
||||
if (!symGetModuleInfo64(process, address, &imageHelpModule))
|
||||
return false;
|
||||
|
||||
// look up the symbol
|
||||
const int MaxNameLength = 256;
|
||||
char buffer[sizeof(IMAGEHLP_SYMBOL64) + MaxNameLength];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
IMAGEHLP_SYMBOL64 *imageHelpSymbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(buffer);
|
||||
imageHelpSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||
imageHelpSymbol->Address = address;
|
||||
imageHelpSymbol->MaxNameLength = MaxNameLength;
|
||||
{
|
||||
DWORD64 displacement = 0;
|
||||
if (!symGetSymFromAddr64(process, address, &displacement, imageHelpSymbol))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// look up the source file name and line number
|
||||
IMAGEHLP_LINE64 imageHelpLine;
|
||||
Zero(imageHelpLine);
|
||||
imageHelpLine.SizeOfStruct = sizeof(imageHelpLine);
|
||||
{
|
||||
DWORD displacement = 0;
|
||||
if (!symGetLineFromAddr64(process, address, &displacement, &imageHelpLine))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// return the results
|
||||
strncpy(fileName, imageHelpLine.FileName, static_cast<uint>(fileNameLength));
|
||||
line = static_cast<int>(imageHelpLine.LineNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DebugHelp::writeMiniDump(char const *miniDumpFileName, PEXCEPTION_POINTERS exceptionPointers)
|
||||
{
|
||||
if (!miniDumpWriteDump)
|
||||
return false;
|
||||
|
||||
char buffer[256];
|
||||
if (!miniDumpFileName)
|
||||
{
|
||||
// get the program name
|
||||
char programName[512];
|
||||
DWORD result = GetModuleFileName(NULL, programName, sizeof(programName));
|
||||
if (result == 0)
|
||||
return false;
|
||||
|
||||
// get the file name without the path
|
||||
const char *shortProgramName = strrchr(programName, '\\');
|
||||
if (shortProgramName)
|
||||
++shortProgramName;
|
||||
else
|
||||
shortProgramName = programName;
|
||||
|
||||
// lop off the extension
|
||||
char *dot = const_cast<char *>(strchr(shortProgramName, '.'));
|
||||
if (dot)
|
||||
*dot = '\0';
|
||||
|
||||
// create a reasonable minidump filename
|
||||
snprintf(buffer, sizeof(buffer), "%s_%d.mdmp", shortProgramName, static_cast<int>(GetCurrentProcessId()));
|
||||
miniDumpFileName = buffer;
|
||||
}
|
||||
|
||||
// create the file
|
||||
HANDLE const file = CreateFile(miniDumpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
|
||||
if (file == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
// create the exception information
|
||||
MINIDUMP_EXCEPTION_INFORMATION exceptionInformationData;
|
||||
MINIDUMP_EXCEPTION_INFORMATION *exceptionInformation = 0;
|
||||
if (exceptionPointers)
|
||||
{
|
||||
exceptionInformationData.ThreadId = GetCurrentThreadId();
|
||||
exceptionInformationData.ExceptionPointers = exceptionPointers;
|
||||
exceptionInformationData.ClientPointers = true;
|
||||
exceptionInformation = &exceptionInformationData;
|
||||
}
|
||||
|
||||
// @todo make the minidump style modifiable
|
||||
BOOL const result = miniDumpWriteDump(process, GetCurrentProcessId(), file, MiniDumpNormal, exceptionInformation, NULL, NULL);
|
||||
|
||||
// close the file
|
||||
CloseHandle(file);
|
||||
|
||||
return result ? true : false;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -1,35 +0,0 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DebugHelp.h
|
||||
// copyright 2000 Verant Interactive
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef DEBUG_HELP_H
|
||||
#define DEBUG_HELP_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
typedef unsigned long uint32;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class DebugHelp
|
||||
{
|
||||
public:
|
||||
|
||||
static void install();
|
||||
static void remove();
|
||||
|
||||
static bool loadSymbolsForDll(const char *name);
|
||||
|
||||
static void getCallStack(uint32 *callStack, int sizeOfCallStack);
|
||||
static void reportCallStack(int const maxStackDepth = 4);
|
||||
static bool lookupAddress(uint32 address, char *libName, char *fileName, int fileNameLength, int &line);
|
||||
|
||||
static bool writeMiniDump(char const *miniDumpFileName=0, PEXCEPTION_POINTERS exceptionPointers=0);
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -1,321 +0,0 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DebugMonitor.cpp
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
// copyright 2001-2004 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDebug/FirstSharedDebug.h"
|
||||
#include "sharedDebug/DebugMonitor.h"
|
||||
|
||||
#if PRODUCTION == 0
|
||||
|
||||
#include "sharedDebug/DebugFlags.h"
|
||||
#include "sharedFoundation/ConfigFile.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DebugMonitorNamespace
|
||||
{
|
||||
typedef void (*ChangedWindowCallback)(int x, int y, int width, int height);
|
||||
|
||||
typedef bool (*InstallFunction)(int x, int y, int width, int height);
|
||||
typedef void (*RemoveFunction)();
|
||||
typedef void (*ShowFunction)();
|
||||
typedef void (*HideFunction)();
|
||||
typedef void (*SetChangedWindowCallback)(ChangedWindowCallback);
|
||||
typedef void (*SetBehindWindowFunction)(HWND window);
|
||||
typedef void (*ClearScreenFunction)();
|
||||
typedef void (*ClearToCursorFunction)();
|
||||
typedef void (*GotoXYFunction)(int x, int y);
|
||||
typedef void (*PrintFunction)(const char *string);
|
||||
|
||||
void changedWindowCallback(int x, int y, int width, int height);
|
||||
|
||||
HINSTANCE dll;
|
||||
HKEY registryKey = HKEY_CLASSES_ROOT;
|
||||
RemoveFunction removeFunction;
|
||||
ShowFunction showFunction;
|
||||
HideFunction hideFunction;
|
||||
SetBehindWindowFunction setBehindWindowFunction;
|
||||
ClearScreenFunction clearScreenFunction;
|
||||
ClearToCursorFunction clearToCursorFunction;
|
||||
GotoXYFunction gotoXYFunction;
|
||||
PrintFunction printFunction;
|
||||
|
||||
bool noClear;
|
||||
|
||||
int GetRegistryValue(char const * name, int defaultValue)
|
||||
{
|
||||
int value;
|
||||
DWORD type = 0;
|
||||
DWORD size = sizeof(DWORD);
|
||||
LONG result = RegQueryValueEx(registryKey, name, NULL, &type, reinterpret_cast<LPBYTE>(&value), &size);
|
||||
if (result != ERROR_SUCCESS || type != REG_DWORD && size != sizeof(int))
|
||||
value = defaultValue;
|
||||
return value;
|
||||
}
|
||||
|
||||
void SetRegistryValue(char const * name, int value)
|
||||
{
|
||||
RegSetValueEx(registryKey, name, NULL, REG_DWORD, reinterpret_cast<const LPBYTE>(&value), sizeof(int));
|
||||
}
|
||||
}
|
||||
using namespace DebugMonitorNamespace;
|
||||
|
||||
// ======================================================================
|
||||
// Install the debug monitor subsystem
|
||||
//
|
||||
// Remarks:
|
||||
//
|
||||
// This routine will first attempt to install the selected debug monitor.
|
||||
|
||||
void DebugMonitor::install()
|
||||
{
|
||||
dll = LoadLibrary("debugWindow.dll");
|
||||
if (dll)
|
||||
{
|
||||
InstallFunction installFunction = reinterpret_cast<InstallFunction>(GetProcAddress(dll, "install"));
|
||||
|
||||
RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Sony Online Entertainment\\DebugWindow", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, ®istryKey, NULL);
|
||||
|
||||
int const x = ConfigFile::getKeyInt("SharedDebug", "debugWindowX", GetRegistryValue("x", 0));
|
||||
int const y = ConfigFile::getKeyInt("SharedDebug", "debugWindowY", GetRegistryValue("y", 0));
|
||||
int const width = ConfigFile::getKeyInt("SharedDebug", "debugWindowWidth", GetRegistryValue("width", 80));
|
||||
int const height = ConfigFile::getKeyInt("SharedDebug", "debugWindowHeight", GetRegistryValue("height", 50));
|
||||
|
||||
if (installFunction && installFunction(x, y, width, height))
|
||||
{
|
||||
showFunction = reinterpret_cast<ShowFunction>(GetProcAddress(dll, "showWindow"));
|
||||
hideFunction = reinterpret_cast<ShowFunction>(GetProcAddress(dll, "hideWindow"));
|
||||
removeFunction = reinterpret_cast<RemoveFunction>(GetProcAddress(dll, "remove"));
|
||||
setBehindWindowFunction = reinterpret_cast<SetBehindWindowFunction>(GetProcAddress(dll, "setBehindWindow"));
|
||||
clearScreenFunction = reinterpret_cast<ClearScreenFunction>(GetProcAddress(dll, "clearScreen"));
|
||||
clearToCursorFunction = reinterpret_cast<ClearToCursorFunction>(GetProcAddress(dll, "clearToCursor"));
|
||||
gotoXYFunction = reinterpret_cast<GotoXYFunction>(GetProcAddress(dll, "gotoXY"));
|
||||
printFunction = reinterpret_cast<PrintFunction>(GetProcAddress(dll, "print"));
|
||||
|
||||
SetChangedWindowCallback setChangedWindowCallback = reinterpret_cast<SetChangedWindowCallback>(GetProcAddress(dll, "setChangedWindowCallback"));
|
||||
if (setChangedWindowCallback)
|
||||
(*setChangedWindowCallback)(changedWindowCallback);
|
||||
|
||||
DebugFlags::registerFlag(noClear, "SharedDebug", "noDebugMonitorClear");
|
||||
|
||||
if (ConfigFile::getKeyBool("SharedDebug", "debugWindow", false))
|
||||
show();
|
||||
}
|
||||
else
|
||||
{
|
||||
installFunction = NULL;
|
||||
const BOOL result = FreeLibrary(dll);
|
||||
dll = NULL;
|
||||
UNREF(result);
|
||||
DEBUG_FATAL(!result, ("FreeLibrary failed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Remove the debug monitor subsystem.
|
||||
*/
|
||||
|
||||
void DebugMonitor::remove()
|
||||
{
|
||||
if (removeFunction)
|
||||
removeFunction();
|
||||
|
||||
removeFunction = NULL;
|
||||
setBehindWindowFunction = NULL;
|
||||
clearScreenFunction = NULL;
|
||||
clearToCursorFunction = NULL;
|
||||
gotoXYFunction = NULL;
|
||||
printFunction = NULL;
|
||||
|
||||
if (dll)
|
||||
{
|
||||
const BOOL result = FreeLibrary(dll);
|
||||
UNREF(result);
|
||||
DEBUG_FATAL(!result, ("FreeLibrary failed"));
|
||||
dll = NULL;
|
||||
|
||||
if (registryKey != HKEY_CLASSES_ROOT)
|
||||
{
|
||||
RegCloseKey(registryKey);
|
||||
registryKey = HKEY_CLASSES_ROOT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DebugMonitorNamespace::changedWindowCallback(int const x, int const y, int const width, int const height)
|
||||
{
|
||||
SetRegistryValue("x", x);
|
||||
SetRegistryValue("y", y);
|
||||
SetRegistryValue("width", width);
|
||||
SetRegistryValue("height", height);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DebugMonitor::show()
|
||||
{
|
||||
if (showFunction)
|
||||
(*showFunction)();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DebugMonitor::hide()
|
||||
{
|
||||
if (hideFunction)
|
||||
(*hideFunction)();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Set the debug window's z-order.
|
||||
*/
|
||||
|
||||
void DebugMonitor::setBehindWindow(HWND window)
|
||||
{
|
||||
if (setBehindWindowFunction)
|
||||
setBehindWindowFunction(window);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Clear the debug monitor and home the cursor.
|
||||
*
|
||||
* If the mono monitor is not installed, this routine does nothing.
|
||||
*
|
||||
* This routine will clear the contents of the debug monitor, reset the screen
|
||||
* offset to 0, and move the cursor to the upper left corner of the screen.
|
||||
*
|
||||
* @see DebugMonitor::home(), DebugMonitor::clearToCursor()
|
||||
*/
|
||||
|
||||
void DebugMonitor::clearScreen()
|
||||
{
|
||||
if (noClear)
|
||||
return;
|
||||
|
||||
if (clearScreenFunction)
|
||||
clearScreenFunction();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Clear the debug monitor to the current cursor position and home the cursor.
|
||||
*
|
||||
* If the debug monitor is not installed, this routine does nothing.
|
||||
*
|
||||
* This routine will clear the contents of the debug monitor only up to the
|
||||
* cursor position. If the cursor is not very far down on the screen,
|
||||
* this routine may be significantly more efficient clearing the screen.
|
||||
*
|
||||
* It will also move the cursor to the upper left corner of the screen.
|
||||
*
|
||||
* @see DebugMonitor::clearScreen(), DebugMonitor::home()
|
||||
*/
|
||||
|
||||
void DebugMonitor::clearToCursor()
|
||||
{
|
||||
if (clearToCursorFunction)
|
||||
clearToCursorFunction();
|
||||
else
|
||||
clearScreen();
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
// Move the cursor to the upper left hand corner of the mono monitor screen
|
||||
//
|
||||
// Remarks:
|
||||
//
|
||||
// If the debug monitor is not installed, this routine does nothing.
|
||||
//
|
||||
// All printing happens at the cursor position.
|
||||
//
|
||||
// This routine is identical to calling gotoXY(0,0);
|
||||
//
|
||||
// See Also:
|
||||
//
|
||||
// DebugMonitor::gotoXY()
|
||||
|
||||
void DebugMonitor::home()
|
||||
{
|
||||
gotoXY(0,0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Position the cursor on the debug monitor screen.
|
||||
*
|
||||
* If the debug monitor is not installed, this routine does nothing.
|
||||
*
|
||||
* All printing happens at the cursor position.
|
||||
*
|
||||
* @param x New X position for the cursor
|
||||
* @param y New Y position for the cursor
|
||||
*/
|
||||
|
||||
void DebugMonitor::gotoXY(int x, int y)
|
||||
{
|
||||
if (gotoXYFunction)
|
||||
gotoXYFunction(x, y);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Display a string on the debug monitor.
|
||||
*
|
||||
* If the debug monitor is not installed, this routine does nothing.
|
||||
*
|
||||
* Printing occurs from the cursor position.
|
||||
*
|
||||
* Newline characters '\n' will cause the cursor position to advance to the
|
||||
* beginning of the next line. If the cursor is already on the last line of
|
||||
* the screen, the screen will scroll up one line and the cursor will move to
|
||||
* the beginning of the last line.
|
||||
*
|
||||
* The backspace character '\b' will cause the cursor to move one character
|
||||
* backwards. If at the beginning of the line, the cursor will move to the
|
||||
* end of the previous line. If already on the first line of the screen, the
|
||||
* cursor position and screen contents will be unchanged.
|
||||
*
|
||||
* All other characters are placed directly into the text frame buffer.
|
||||
* After each character, the cursor will be logically advanced one
|
||||
* character forward. If the cursor was on the last column, it will advance
|
||||
* to the next line. If the cursor was already on the last line, the screen
|
||||
* will be scrolled up one line and the cursor will move to the beginning of
|
||||
* the last line.
|
||||
*
|
||||
* @param string String to display on the debug monitor
|
||||
*/
|
||||
|
||||
void DebugMonitor::print(const char *string)
|
||||
{
|
||||
if (printFunction)
|
||||
printFunction(string);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Ensure all changes to the DebugMonitor have taken effect by the time
|
||||
* this function returns.
|
||||
*
|
||||
* Note: some platforms may do nothing here. The Win32 platform does not
|
||||
* require flushing. The Linux platform does. Call it assuming
|
||||
* that it is needed. It will be a no-op when not required.
|
||||
*/
|
||||
|
||||
void DebugMonitor::flushOutput()
|
||||
{
|
||||
// Win32 debug monitors don't need to do anything here.
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -1,48 +0,0 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DebugMonitor.h
|
||||
//
|
||||
// Portions copyright 1998 Bootprint Entertainment
|
||||
// Portions copyright 2002-2004 Sony Online Entertainment
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DebugMonitor_H
|
||||
#define INCLUDED_DebugMonitor_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/Production.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#if PRODUCTION == 0
|
||||
|
||||
class DebugMonitor
|
||||
{
|
||||
public:
|
||||
|
||||
static void install();
|
||||
static void remove();
|
||||
|
||||
static void setBehindWindow(HWND window);
|
||||
|
||||
static void show();
|
||||
static void hide();
|
||||
|
||||
static void clearScreen();
|
||||
static void clearToCursor();
|
||||
|
||||
static void home();
|
||||
static void gotoXY(int x, int y);
|
||||
static void print(const char *string);
|
||||
|
||||
static void flushOutput();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -1,8 +0,0 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FirstDebug.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "shareddebug/FirstSharedDebug.h"
|
||||
@@ -1,105 +0,0 @@
|
||||
//
|
||||
// PerformanceTimer.cpp
|
||||
// Copyright 2000-2004 Sony Online Entertainment
|
||||
//
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
#include "shareddebug/FirstSharedDebug.h"
|
||||
#include "shareddebug/PerformanceTimer.h"
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
__int64 PerformanceTimer::ms_frequency;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void PerformanceTimer::install()
|
||||
{
|
||||
BOOL result = QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER *>(&ms_frequency));
|
||||
FATAL(!result, ("PerformanceTimer::install QPF failed"));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
PerformanceTimer::PerformanceTimer() :
|
||||
m_startTime (0),
|
||||
m_stopTime (0)
|
||||
{
|
||||
DEBUG_FATAL (ms_frequency == 0.f, ("PerformanceTimer not installed"));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
PerformanceTimer::~PerformanceTimer()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void PerformanceTimer::start()
|
||||
{
|
||||
//-- get the current time
|
||||
BOOL result = QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&m_startTime));
|
||||
DEBUG_FATAL(!result, ("PerformanceTimer::start QPC failed"));
|
||||
UNREF (result);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void PerformanceTimer::resume()
|
||||
{
|
||||
__int64 delta = m_stopTime - m_startTime;
|
||||
start();
|
||||
m_startTime -= delta;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void PerformanceTimer::stop ()
|
||||
{
|
||||
//-- get the current time
|
||||
BOOL result = QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&m_stopTime));
|
||||
DEBUG_FATAL(!result, ("PerformanceTimer::stop QPC failed"));
|
||||
UNREF (result);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
float PerformanceTimer::getElapsedTime() const
|
||||
{
|
||||
return static_cast<float> (m_stopTime - m_startTime) / static_cast<float> (ms_frequency);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
float PerformanceTimer::getSplitTime() const
|
||||
{
|
||||
__int64 currentTime;
|
||||
BOOL result = QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(¤tTime));
|
||||
UNREF(result);
|
||||
DEBUG_FATAL(!result, ("PerformanceTimer::getSplitTime QPC failed"));
|
||||
|
||||
return static_cast<float> (currentTime - m_startTime) / static_cast<float> (ms_frequency);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void PerformanceTimer::logElapsedTime(const char* string) const
|
||||
{
|
||||
UNREF (string);
|
||||
|
||||
#ifdef _DEBUG
|
||||
static char buffer [1000];
|
||||
sprintf (buffer, "%s : %1.5f seconds\n", string ? string : "null", getElapsedTime());
|
||||
DEBUG_REPORT_LOG_PRINT (true, ("%s", buffer));
|
||||
DEBUG_OUTPUT_CHANNEL("Foundation\\PerformanceTimer", ("%s", buffer));
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
//
|
||||
// PerformanceTimer.h
|
||||
// Copyright 2000-2004 Sony Online Entertainment
|
||||
//
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
#ifndef INCLUDED_PerformanceTimer_H
|
||||
#define INCLUDED_PerformanceTimer_H
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
class PerformanceTimer
|
||||
{
|
||||
public:
|
||||
|
||||
static void install();
|
||||
|
||||
public:
|
||||
|
||||
DLLEXPORT PerformanceTimer();
|
||||
DLLEXPORT ~PerformanceTimer();
|
||||
|
||||
void DLLEXPORT start();
|
||||
void DLLEXPORT resume();
|
||||
void DLLEXPORT stop();
|
||||
|
||||
float DLLEXPORT getElapsedTime() const;
|
||||
float getSplitTime() const; // Get the time since the timer was started without stopping the timer.
|
||||
void logElapsedTime(const char* string) const;
|
||||
|
||||
private:
|
||||
|
||||
PerformanceTimer(PerformanceTimer const &);
|
||||
PerformanceTimer & operator=(PerformanceTimer const &);
|
||||
|
||||
private:
|
||||
|
||||
static __int64 ms_frequency;
|
||||
|
||||
private:
|
||||
|
||||
__int64 m_startTime;
|
||||
__int64 m_stopTime;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
@@ -1,90 +0,0 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// ProfilerTimer.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "shareddebug/FirstSharedDebug.h"
|
||||
#include "shareddebug/ProfilerTimer.h"
|
||||
|
||||
#include "shareddebug/DebugFlags.h"
|
||||
#include "sharedFoundation/WindowsWrapper.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace ProfilerTimerNamespace
|
||||
{
|
||||
ProfilerTimer::Type ms_qpcFrequency;
|
||||
float ms_floatQpcFrequency;
|
||||
__int64 ms_rdtsc;
|
||||
__int64 ms_qpc;
|
||||
bool ms_useRdtsc;
|
||||
|
||||
}
|
||||
using namespace ProfilerTimerNamespace;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
static __int64 __declspec(naked) __stdcall readTimeStampCounter()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
rdtsc;
|
||||
ret;
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void ProfilerTimer::install()
|
||||
{
|
||||
IGNORE_RETURN(QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&ms_qpc)));
|
||||
ms_rdtsc = readTimeStampCounter();
|
||||
|
||||
IGNORE_RETURN(QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER *>(&ms_qpcFrequency)));
|
||||
ms_floatQpcFrequency = static_cast<float>(ms_qpcFrequency);
|
||||
|
||||
DebugFlags::registerFlag(ms_useRdtsc, "SharedDebug/Profiler", "useRdtsc");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void ProfilerTimer::getTime(Type &time)
|
||||
{
|
||||
if (ms_useRdtsc)
|
||||
time = readTimeStampCounter();
|
||||
else
|
||||
IGNORE_RETURN(QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&time)));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void ProfilerTimer::getCalibratedTime(Type &time, Type &frequency)
|
||||
{
|
||||
if (ms_useRdtsc)
|
||||
{
|
||||
__int64 qpc;
|
||||
IGNORE_RETURN(QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&qpc)));
|
||||
__int64 rdtsc = readTimeStampCounter();
|
||||
|
||||
float const t = static_cast<float>(qpc - ms_qpc) / ms_floatQpcFrequency;
|
||||
frequency = static_cast<__int64>(static_cast<float>(rdtsc - ms_rdtsc) / t);
|
||||
|
||||
time = rdtsc;
|
||||
ms_qpc = qpc;
|
||||
ms_rdtsc = time;
|
||||
}
|
||||
else
|
||||
{
|
||||
IGNORE_RETURN(QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&time)));
|
||||
frequency = ms_qpcFrequency;
|
||||
}
|
||||
}
|
||||
|
||||
void ProfilerTimer::getFrequency(Type &frequency)
|
||||
{
|
||||
frequency = ms_qpcFrequency;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -1,29 +0,0 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// ProfilerTimer.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_ProfilerTimer_H
|
||||
#define INCLUDED_ProfilerTimer_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class ProfilerTimer
|
||||
{
|
||||
public:
|
||||
|
||||
typedef __int64 Type;
|
||||
|
||||
public:
|
||||
|
||||
static void install();
|
||||
static void getTime(Type &time);
|
||||
static void getCalibratedTime(Type &time, Type &frequency);
|
||||
static void getFrequency(Type &frequency);
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -1,142 +0,0 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// VTune.cpp
|
||||
// Copyright 2000-01, Sony Online Entertainment Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDebug/FirstSharedDebug.h"
|
||||
#include "sharedDebug/VTune.h"
|
||||
|
||||
#if PRODUCTION == 0
|
||||
|
||||
#include "sharedDebug/DebugFlags.h"
|
||||
|
||||
#include <vtune/vtuneapi.h>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
HMODULE VTune::ms_module;
|
||||
VTune::PauseFunction VTune::ms_pauseFunction;
|
||||
VTune::ResumeFunction VTune::ms_resumeFunction;
|
||||
VTune::State VTune::ms_state;
|
||||
bool VTune::ms_resumeNextFrame;
|
||||
bool VTune::ms_pauseNextFrame;
|
||||
bool VTune::ms_debugReport;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void VTune::install()
|
||||
{
|
||||
DEBUG_FATAL(ms_module, ("vtune already installed"));
|
||||
|
||||
ms_module = LoadLibrary("VTuneAPI");
|
||||
if (!ms_module)
|
||||
return;
|
||||
|
||||
ms_pauseFunction = reinterpret_cast<PauseFunction>(GetProcAddress(ms_module, "VTPause"));
|
||||
ms_resumeFunction = reinterpret_cast<PauseFunction>(GetProcAddress(ms_module, "VTResume"));
|
||||
ms_state = S_default;
|
||||
|
||||
#if PRODUCTION == 0
|
||||
DebugFlags::registerFlag(ms_debugReport, "SharedDebug", "vtuneState", debugReport);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void VTune::remove()
|
||||
{
|
||||
if (ms_module)
|
||||
{
|
||||
FreeLibrary(ms_module);
|
||||
ms_pauseFunction = 0;
|
||||
ms_resumeFunction = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void VTune::debugReport()
|
||||
{
|
||||
switch (ms_state)
|
||||
{
|
||||
case S_default:
|
||||
REPORT_PRINT(true, ("Vtune state unknown\n"));
|
||||
break;
|
||||
|
||||
case S_sampling:
|
||||
REPORT_PRINT(true, ("Vtune is sampling\n"));
|
||||
break;
|
||||
|
||||
case S_paused:
|
||||
REPORT_PRINT(true, ("Vtune is NOT sampling\n"));
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_FATAL(true, ("bad case"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void VTune::resume()
|
||||
{
|
||||
if (ms_module && ms_resumeFunction)
|
||||
{
|
||||
MessageBeep(MB_OK);
|
||||
(*ms_resumeFunction)();
|
||||
ms_state = S_sampling;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void VTune::pause()
|
||||
{
|
||||
if (ms_module && ms_pauseFunction)
|
||||
{
|
||||
(*ms_pauseFunction)();
|
||||
MessageBeep(MB_ICONEXCLAMATION);
|
||||
ms_state = S_paused;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void VTune::pauseNextFrame()
|
||||
{
|
||||
ms_pauseNextFrame = true;
|
||||
ms_resumeNextFrame = false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void VTune::resumeNextFrame()
|
||||
{
|
||||
ms_pauseNextFrame = false;
|
||||
ms_resumeNextFrame = true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void VTune::beginFrame()
|
||||
{
|
||||
if (ms_pauseNextFrame)
|
||||
{
|
||||
pause();
|
||||
ms_pauseNextFrame = false;
|
||||
}
|
||||
|
||||
if (ms_resumeNextFrame)
|
||||
{
|
||||
resume();
|
||||
ms_resumeNextFrame = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif // PRODUCTION == 0
|
||||
@@ -1,65 +0,0 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// VTune.h
|
||||
// Copyright 2000-01, Sony Online Entertainment Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_VTune_H
|
||||
#define INCLUDED_VTune_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/Production.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#if PRODUCTION == 0
|
||||
|
||||
class VTune
|
||||
{
|
||||
public:
|
||||
|
||||
static void install();
|
||||
|
||||
static void resume();
|
||||
static void pause();
|
||||
|
||||
static void resumeNextFrame();
|
||||
static void pauseNextFrame();
|
||||
static void beginFrame();
|
||||
|
||||
private:
|
||||
|
||||
static void remove();
|
||||
static void debugReport();
|
||||
|
||||
private:
|
||||
|
||||
enum State
|
||||
{
|
||||
S_default,
|
||||
S_sampling,
|
||||
S_paused
|
||||
};
|
||||
|
||||
typedef void (__cdecl *PauseFunction)(void);
|
||||
typedef void (__cdecl *ResumeFunction)(void);
|
||||
|
||||
private:
|
||||
|
||||
static HMODULE ms_module;
|
||||
static PauseFunction ms_pauseFunction;
|
||||
static ResumeFunction ms_resumeFunction;
|
||||
static State ms_state;
|
||||
static bool ms_resumeNextFrame;
|
||||
static bool ms_pauseNextFrame;
|
||||
static bool ms_debugReport;
|
||||
};
|
||||
|
||||
#endif // PRODUCTION == 0
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user