Browse Source

engine: crashhandler: clean up code

pull/2/head
Alibek Omarov 3 years ago
parent
commit
08e72bad35
  1. 109
      engine/common/crashhandler.c

109
engine/common/crashhandler.c

@ -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;
@ -44,27 +46,24 @@ int ModuleName( HANDLE process, char *name, void *address, int len )
DWORD bytesRequired; DWORD bytesRequired;
int i; int i;
if(len < 3) if( len < 3 )
return 0; return 0;
if ( !moduleArray && EnumProcessModules( process, NULL, 0, &bytesRequired ) ) if( !moduleArray && EnumProcessModules( process, NULL, 0, &bytesRequired ) )
{ {
if ( bytesRequired ) if ( bytesRequired )
{ {
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 );
{ moduleArray = (HMODULE *)moduleArrayBytes;
moduleCount = bytesRequired / sizeof( HMODULE );
moduleArray = (HMODULE *)moduleArrayBytes;
}
} }
} }
} }
for( i = 0; i<moduleCount; i++ ) for( i = 0; i < moduleCount; i++ )
{ {
MODULEINFO info; MODULEINFO info;
GetModuleInformation( process, moduleArray[i], &info, sizeof(MODULEINFO) ); GetModuleInformation( process, moduleArray[i], &info, sizeof(MODULEINFO) );
@ -73,9 +72,10 @@ int ModuleName( HANDLE process, char *name, void *address, int len )
( (DWORD64)address < (DWORD64)info.lpBaseOfDll + (DWORD64)info.SizeOfImage ) ) ( (DWORD64)address < (DWORD64)info.lpBaseOfDll + (DWORD64)info.SizeOfImage ) )
return GetModuleBaseName( process, moduleArray[i], name, len ); return GetModuleBaseName( process, moduleArray[i], name, 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;
@ -89,7 +89,8 @@ static void stack_trace( PEXCEPTION_POINTERS pInfo )
STACKFRAME64 stackframe; STACKFRAME64 stackframe;
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,9 +98,7 @@ 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
image = IMAGE_FILE_MACHINE_I386; image = IMAGE_FILE_MACHINE_I386;
@ -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);
SymCleanup(process); Sys_PrintLog( message );
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 )
@ -271,7 +281,7 @@ int printframe( char *buf, int len, int i, void *addr )
{ {
if( dlinfo.dli_sname ) if( dlinfo.dli_sname )
return Q_snprintf( buf, len, "%2d: %p <%s+%lu> (%s)\n", i, addr, dlinfo.dli_sname, return Q_snprintf( buf, len, "%2d: %p <%s+%lu> (%s)\n", i, addr, dlinfo.dli_sname,
(unsigned long)addr - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname ); // print symbol, module and address (unsigned long)addr - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname ); // print symbol, module and address
else else
return Q_snprintf( buf, len, "%2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address return Q_snprintf( buf, len, "%2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address
} }
@ -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 "Stack dump:\n"
#define STACK_DUMP_STR_LEN 12
#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;
} }

Loading…
Cancel
Save