|
|
@ -24,9 +24,11 @@ Crash handler, called from system |
|
|
|
================ |
|
|
|
================ |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
#if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP || XASH_CRASHHANDLER == CRASHHANDLER_WIN32 |
|
|
|
#if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP || XASH_CRASHHANDLER == CRASHHANDLER_WIN32 |
|
|
|
|
|
|
|
|
|
|
|
#if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP |
|
|
|
#if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP |
|
|
|
|
|
|
|
|
|
|
|
#pragma comment( lib, "dbghelp" ) |
|
|
|
#pragma comment( lib, "dbghelp" ) |
|
|
|
#pragma comment( lib, "psapi" ) |
|
|
|
|
|
|
|
#include <winnt.h> |
|
|
|
#include <winnt.h> |
|
|
|
#include <dbghelp.h> |
|
|
|
#include <dbghelp.h> |
|
|
|
#include <psapi.h> |
|
|
|
#include <psapi.h> |
|
|
@ -35,7 +37,7 @@ Crash handler, called from system |
|
|
|
typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; |
|
|
|
typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
int ModuleName( HANDLE process, char *name, void *address, int len ) |
|
|
|
static int Sys_ModuleName( HANDLE process, char *name, void *address, int len ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
DWORD_PTR baseAddress = 0; |
|
|
|
DWORD_PTR baseAddress = 0; |
|
|
|
static HMODULE *moduleArray; |
|
|
|
static HMODULE *moduleArray; |
|
|
@ -53,16 +55,13 @@ int ModuleName( HANDLE process, char *name, void *address, int len ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
moduleArrayBytes = (LPBYTE)LocalAlloc( LPTR, bytesRequired ); |
|
|
|
moduleArrayBytes = (LPBYTE)LocalAlloc( LPTR, bytesRequired ); |
|
|
|
|
|
|
|
|
|
|
|
if ( moduleArrayBytes ) |
|
|
|
if( moduleArrayBytes && EnumProcessModules( process, (HMODULE *)moduleArrayBytes, bytesRequired, &bytesRequired ) ) |
|
|
|
{ |
|
|
|
|
|
|
|
if( EnumProcessModules( process, (HMODULE *)moduleArrayBytes, bytesRequired, &bytesRequired ) ) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
moduleCount = bytesRequired / sizeof( HMODULE ); |
|
|
|
moduleCount = bytesRequired / sizeof( HMODULE ); |
|
|
|
moduleArray = (HMODULE *)moduleArrayBytes; |
|
|
|
moduleArray = (HMODULE *)moduleArrayBytes; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( i = 0; i < moduleCount; i++ ) |
|
|
|
for( i = 0; i < moduleCount; i++ ) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -75,7 +74,8 @@ int ModuleName( HANDLE process, char *name, void *address, int len ) |
|
|
|
} |
|
|
|
} |
|
|
|
return Q_snprintf( name, len, "???" ); |
|
|
|
return Q_snprintf( name, len, "???" ); |
|
|
|
} |
|
|
|
} |
|
|
|
static void stack_trace( PEXCEPTION_POINTERS pInfo ) |
|
|
|
|
|
|
|
|
|
|
|
static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char message[1024]; |
|
|
|
char message[1024]; |
|
|
|
int len = 0; |
|
|
|
int len = 0; |
|
|
@ -90,6 +90,7 @@ static void stack_trace( PEXCEPTION_POINTERS pInfo ) |
|
|
|
DWORD image; |
|
|
|
DWORD image; |
|
|
|
|
|
|
|
|
|
|
|
memcpy( &context, pInfo->ContextRecord, sizeof( CONTEXT )); |
|
|
|
memcpy( &context, pInfo->ContextRecord, sizeof( CONTEXT )); |
|
|
|
|
|
|
|
|
|
|
|
options = SymGetOptions(); |
|
|
|
options = SymGetOptions(); |
|
|
|
options |= SYMOPT_DEBUG; |
|
|
|
options |= SYMOPT_DEBUG; |
|
|
|
options |= SYMOPT_LOAD_LINES; |
|
|
|
options |= SYMOPT_LOAD_LINES; |
|
|
@ -97,8 +98,6 @@ static void stack_trace( PEXCEPTION_POINTERS pInfo ) |
|
|
|
|
|
|
|
|
|
|
|
SymInitialize( process, NULL, TRUE ); |
|
|
|
SymInitialize( process, NULL, TRUE ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ZeroMemory( &stackframe, sizeof( STACKFRAME64 )); |
|
|
|
ZeroMemory( &stackframe, sizeof( STACKFRAME64 )); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef _M_IX86 |
|
|
|
#ifdef _M_IX86 |
|
|
@ -127,19 +126,25 @@ static void stack_trace( PEXCEPTION_POINTERS pInfo ) |
|
|
|
stackframe.AddrBStore.Mode = AddrModeFlat; |
|
|
|
stackframe.AddrBStore.Mode = AddrModeFlat; |
|
|
|
stackframe.AddrStack.Offset = context.IntSp; |
|
|
|
stackframe.AddrStack.Offset = context.IntSp; |
|
|
|
stackframe.AddrStack.Mode = AddrModeFlat; |
|
|
|
stackframe.AddrStack.Mode = AddrModeFlat; |
|
|
|
|
|
|
|
#elif |
|
|
|
|
|
|
|
#error |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
len += Q_snprintf( message + len, 1024 - len, "Sys_Crash: address %p, code %p\n", pInfo->ExceptionRecord->ExceptionAddress, (void*)pInfo->ExceptionRecord->ExceptionCode ); |
|
|
|
len += Q_snprintf( message + len, 1024 - len, "Sys_Crash: address %p, code %p\n", |
|
|
|
|
|
|
|
pInfo->ExceptionRecord->ExceptionAddress, (void*)pInfo->ExceptionRecord->ExceptionCode ); |
|
|
|
if( SymGetLineFromAddr64( process, (DWORD64)pInfo->ExceptionRecord->ExceptionAddress, &dline, &line ) ) |
|
|
|
if( SymGetLineFromAddr64( process, (DWORD64)pInfo->ExceptionRecord->ExceptionAddress, &dline, &line ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
len += Q_snprintf(message + len, 1024 - len,"Exception: %s:%d:%d\n", (char*)line.FileName, (int)line.LineNumber, (int)dline); |
|
|
|
len += Q_snprintf(message + len, 1024 - len, "Exception: %s:%d:%d\n", |
|
|
|
|
|
|
|
(char*)line.FileName, (int)line.LineNumber, (int)dline); |
|
|
|
} |
|
|
|
} |
|
|
|
if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) ) |
|
|
|
if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
len += Q_snprintf(message + len, 1024 - len,"PC: %s:%d:%d\n", (char*)line.FileName, (int)line.LineNumber, (int)dline); |
|
|
|
len += Q_snprintf(message + len, 1024 - len,"PC: %s:%d:%d\n", |
|
|
|
|
|
|
|
(char*)line.FileName, (int)line.LineNumber, (int)dline); |
|
|
|
} |
|
|
|
} |
|
|
|
if( SymGetLineFromAddr64( process, stackframe.AddrFrame.Offset, &dline, &line ) ) |
|
|
|
if( SymGetLineFromAddr64( process, stackframe.AddrFrame.Offset, &dline, &line ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
len += Q_snprintf(message + len, 1024 - len,"Frame: %s:%d:%d\n", (char*)line.FileName, (int)line.LineNumber, (int)dline); |
|
|
|
len += Q_snprintf(message + len, 1024 - len,"Frame: %s:%d:%d\n", |
|
|
|
|
|
|
|
(char*)line.FileName, (int)line.LineNumber, (int)dline); |
|
|
|
} |
|
|
|
} |
|
|
|
for( i = 0; i < 25; i++ ) |
|
|
|
for( i = 0; i < 25; i++ ) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -149,39 +154,43 @@ static void stack_trace( PEXCEPTION_POINTERS pInfo ) |
|
|
|
image, process, thread, |
|
|
|
image, process, thread, |
|
|
|
&stackframe, &context, NULL, |
|
|
|
&stackframe, &context, NULL, |
|
|
|
SymFunctionTableAccess64, SymGetModuleBase64, NULL); |
|
|
|
SymFunctionTableAccess64, SymGetModuleBase64, NULL); |
|
|
|
|
|
|
|
|
|
|
|
DWORD64 displacement = 0; |
|
|
|
DWORD64 displacement = 0; |
|
|
|
|
|
|
|
|
|
|
|
if( !result ) |
|
|
|
if( !result ) |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
symbol->SizeOfStruct = sizeof(SYMBOL_INFO); |
|
|
|
symbol->SizeOfStruct = sizeof(SYMBOL_INFO); |
|
|
|
symbol->MaxNameLen = MAX_SYM_NAME; |
|
|
|
symbol->MaxNameLen = MAX_SYM_NAME; |
|
|
|
|
|
|
|
|
|
|
|
len += Q_snprintf( message + len, 1024 - len, "% 2d %p", i, (void*)stackframe.AddrPC.Offset ); |
|
|
|
len += Q_snprintf( message + len, 1024 - len, "% 2d %p", |
|
|
|
|
|
|
|
i, (void*)stackframe.AddrPC.Offset ); |
|
|
|
if( SymFromAddr( process, stackframe.AddrPC.Offset, &displacement, symbol ) ) |
|
|
|
if( SymFromAddr( process, stackframe.AddrPC.Offset, &displacement, symbol ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
len += Q_snprintf( message + len, 1024 - len, " %s ", symbol->Name ); |
|
|
|
len += Q_snprintf( message + len, 1024 - len, " %s ", symbol->Name ); |
|
|
|
} |
|
|
|
} |
|
|
|
if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) ) |
|
|
|
if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
len += Q_snprintf(message + len, 1024 - len,"(%s:%d:%d) ", (char*)line.FileName, (int)line.LineNumber, (int)dline); |
|
|
|
len += Q_snprintf(message + len, 1024 - len,"(%s:%d:%d) ", |
|
|
|
|
|
|
|
(char*)line.FileName, (int)line.LineNumber, (int)dline); |
|
|
|
} |
|
|
|
} |
|
|
|
len += Q_snprintf( message + len, 1024 - len, "("); |
|
|
|
len += Q_snprintf( message + len, 1024 - len, "("); |
|
|
|
len += ModuleName( process, message + len, (void*)stackframe.AddrPC.Offset, 1024 - len ); |
|
|
|
len += Sys_ModuleName( process, message + len, (void*)stackframe.AddrPC.Offset, 1024 - len ); |
|
|
|
len += Q_snprintf( message + len, 1024 - len, ")\n"); |
|
|
|
len += Q_snprintf( message + len, 1024 - len, ")\n"); |
|
|
|
} |
|
|
|
} |
|
|
|
#ifdef XASH_SDL |
|
|
|
|
|
|
|
|
|
|
|
#if XASH_SDL >= 2 |
|
|
|
if( host.type != HOST_DEDICATED ) // let system to restart server automaticly
|
|
|
|
if( host.type != HOST_DEDICATED ) // let system to restart server automaticly
|
|
|
|
SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, "Sys_Crash", message, host.hWnd ); |
|
|
|
SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, "Sys_Crash", message, host.hWnd ); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
Sys_PrintLog( message ); |
|
|
|
Sys_PrintLog( message ); |
|
|
|
|
|
|
|
|
|
|
|
SymCleanup( process ); |
|
|
|
SymCleanup( process ); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif //DBGHELP
|
|
|
|
#endif /* XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP */ |
|
|
|
|
|
|
|
|
|
|
|
LPTOP_LEVEL_EXCEPTION_FILTER oldFilter; |
|
|
|
LPTOP_LEVEL_EXCEPTION_FILTER oldFilter; |
|
|
|
long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo ) |
|
|
|
static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// save config
|
|
|
|
// save config
|
|
|
|
if( host.status != HOST_CRASHED ) |
|
|
|
if( host.status != HOST_CRASHED ) |
|
|
@ -190,7 +199,7 @@ long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo ) |
|
|
|
host.crashed = true; |
|
|
|
host.crashed = true; |
|
|
|
|
|
|
|
|
|
|
|
#if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP |
|
|
|
#if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP |
|
|
|
stack_trace( pInfo ); |
|
|
|
Sys_StackTrace( pInfo ); |
|
|
|
#else |
|
|
|
#else |
|
|
|
Sys_Warn( "Sys_Crash: call %p at address %p", pInfo->ExceptionRecord->ExceptionAddress, pInfo->ExceptionRecord->ExceptionCode ); |
|
|
|
Sys_Warn( "Sys_Crash: call %p at address %p", pInfo->ExceptionRecord->ExceptionAddress, pInfo->ExceptionRecord->ExceptionCode ); |
|
|
|
#endif |
|
|
|
#endif |
|
|
@ -233,13 +242,14 @@ void Sys_RestoreCrashHandler( void ) |
|
|
|
|
|
|
|
|
|
|
|
#include "library.h" |
|
|
|
#include "library.h" |
|
|
|
|
|
|
|
|
|
|
|
#if XASH_FREEBSD || XASH_NETBSD || XASH_ANDROID || XASH_LINUX |
|
|
|
#if XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX |
|
|
|
#define HAVE_UCONTEXT_H 1 |
|
|
|
#define HAVE_UCONTEXT_H 1 |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_UCONTEXT_H |
|
|
|
#ifdef HAVE_UCONTEXT_H |
|
|
|
#include <ucontext.h> |
|
|
|
#include <ucontext.h> |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#include <signal.h> |
|
|
|
#include <signal.h> |
|
|
|
#include <sys/mman.h> |
|
|
|
#include <sys/mman.h> |
|
|
|
|
|
|
|
|
|
|
@ -261,7 +271,7 @@ static int d_dladdr( void *sym, Dl_info *info ) |
|
|
|
#define dladdr d_dladdr |
|
|
|
#define dladdr d_dladdr |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
int printframe( char *buf, int len, int i, void *addr ) |
|
|
|
static int Sys_PrintFrame( char *buf, int len, int i, void *addr ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Dl_info dlinfo; |
|
|
|
Dl_info dlinfo; |
|
|
|
if( len <= 0 ) |
|
|
|
if( len <= 0 ) |
|
|
@ -281,10 +291,11 @@ int printframe( char *buf, int len, int i, void *addr ) |
|
|
|
|
|
|
|
|
|
|
|
struct sigaction oldFilter; |
|
|
|
struct sigaction oldFilter; |
|
|
|
|
|
|
|
|
|
|
|
#define STACK_BACKTRACE_STR_LEN 17 |
|
|
|
|
|
|
|
#define STACK_BACKTRACE_STR "Stack backtrace:\n" |
|
|
|
#define STACK_BACKTRACE_STR "Stack backtrace:\n" |
|
|
|
#define STACK_DUMP_STR_LEN 12 |
|
|
|
|
|
|
|
#define STACK_DUMP_STR "Stack dump:\n" |
|
|
|
#define STACK_DUMP_STR "Stack dump:\n" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define STACK_BACKTRACE_STR_LEN (sizeof( STACK_BACKTRACE_STR ) - 1) |
|
|
|
|
|
|
|
#define STACK_DUMP_STR_LEN (sizeof( STACK_DUMP_STR ) - 1) |
|
|
|
#define ALIGN( x, y ) (((uintptr_t) (x) + ((y)-1)) & ~((y)-1)) |
|
|
|
#define ALIGN( x, y ) (((uintptr_t) (x) + ((y)-1)) & ~((y)-1)) |
|
|
|
|
|
|
|
|
|
|
|
static void Sys_Crash( int signal, siginfo_t *si, void *context) |
|
|
|
static void Sys_Crash( int signal, siginfo_t *si, void *context) |
|
|
@ -356,7 +367,7 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context) |
|
|
|
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr ); |
|
|
|
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr ); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
write( 2, message, len ); |
|
|
|
write( STDERR_FILENO, message, len ); |
|
|
|
|
|
|
|
|
|
|
|
// flush buffers before writing directly to descriptors
|
|
|
|
// flush buffers before writing directly to descriptors
|
|
|
|
fflush( stdout ); |
|
|
|
fflush( stdout ); |
|
|
@ -370,9 +381,9 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context) |
|
|
|
{ |
|
|
|
{ |
|
|
|
size_t pagesize = sysconf( _SC_PAGESIZE ); |
|
|
|
size_t pagesize = sysconf( _SC_PAGESIZE ); |
|
|
|
// try to print backtrace
|
|
|
|
// try to print backtrace
|
|
|
|
write( 2, STACK_BACKTRACE_STR, STACK_BACKTRACE_STR_LEN ); |
|
|
|
write( STDERR_FILENO, STACK_BACKTRACE_STR, STACK_BACKTRACE_STR_LEN ); |
|
|
|
write( logfd, STACK_BACKTRACE_STR, STACK_BACKTRACE_STR_LEN ); |
|
|
|
write( logfd, STACK_BACKTRACE_STR, STACK_BACKTRACE_STR_LEN ); |
|
|
|
strncpy( message + len, STACK_BACKTRACE_STR, sizeof( message ) - len ); |
|
|
|
Q_strncpy( message + len, STACK_BACKTRACE_STR, sizeof( message ) - len ); |
|
|
|
len += STACK_BACKTRACE_STR_LEN; |
|
|
|
len += STACK_BACKTRACE_STR_LEN; |
|
|
|
|
|
|
|
|
|
|
|
// false on success, true on failure
|
|
|
|
// false on success, true on failure
|
|
|
@ -384,8 +395,8 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context) |
|
|
|
|
|
|
|
|
|
|
|
do |
|
|
|
do |
|
|
|
{ |
|
|
|
{ |
|
|
|
int line = printframe( message + len, sizeof( message ) - len, ++i, pc); |
|
|
|
int line = Sys_PrintFrame( message + len, sizeof( message ) - len, ++i, pc); |
|
|
|
write( 2, message + len, line ); |
|
|
|
write( STDERR_FILENO, message + len, line ); |
|
|
|
write( logfd, message + len, line ); |
|
|
|
write( logfd, message + len, line ); |
|
|
|
len += line; |
|
|
|
len += line; |
|
|
|
//if( !dladdr(bp,0) ) break; // only when bp is in module
|
|
|
|
//if( !dladdr(bp,0) ) break; // only when bp is in module
|
|
|
@ -399,17 +410,17 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context) |
|
|
|
while( bp && i < 128 ); |
|
|
|
while( bp && i < 128 ); |
|
|
|
|
|
|
|
|
|
|
|
// try to print stack
|
|
|
|
// try to print stack
|
|
|
|
write( 2, STACK_DUMP_STR, STACK_DUMP_STR_LEN ); |
|
|
|
write( STDERR_FILENO, STACK_DUMP_STR, STACK_DUMP_STR_LEN ); |
|
|
|
write( logfd, STACK_DUMP_STR, STACK_DUMP_STR_LEN ); |
|
|
|
write( logfd, STACK_DUMP_STR, STACK_DUMP_STR_LEN ); |
|
|
|
strncpy( message + len, STACK_DUMP_STR, sizeof( message ) - len ); |
|
|
|
Q_strncpy( message + len, STACK_DUMP_STR, sizeof( message ) - len ); |
|
|
|
len += STACK_DUMP_STR_LEN; |
|
|
|
len += STACK_DUMP_STR_LEN; |
|
|
|
|
|
|
|
|
|
|
|
if( !try_allow_read( sp, pagesize ) ) |
|
|
|
if( !try_allow_read( sp, pagesize ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
for( i = 0; i < 32; i++ ) |
|
|
|
for( i = 0; i < 32; i++ ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int line = printframe( message + len, sizeof( message ) - len, i, sp[i] ); |
|
|
|
int line = Sys_PrintFrame( message + len, sizeof( message ) - len, i, sp[i] ); |
|
|
|
write( 2, message + len, line ); |
|
|
|
write( STDERR_FILENO, message + len, line ); |
|
|
|
write( logfd, message + len, line ); |
|
|
|
write( logfd, message + len, line ); |
|
|
|
len += line; |
|
|
|
len += line; |
|
|
|
} |
|
|
|
} |
|
|
|