diff --git a/stepmania/src/archutils/Unix/Backtrace.cpp b/stepmania/src/archutils/Unix/Backtrace.cpp index 23d00af129..49b0fa5a66 100644 --- a/stepmania/src/archutils/Unix/Backtrace.cpp +++ b/stepmania/src/archutils/Unix/Backtrace.cpp @@ -14,6 +14,14 @@ #if defined(BACKTRACE_METHOD_X86_LINUX) #include "LinuxThreadHelpers.h" +void GetSignalBacktraceContext( BacktraceContext *ctx, const ucontext_t *uc ) +{ + ctx->esp = (long) uc->uc_mcontext.gregs[REG_ESP]; + ctx->eip = (long) uc->uc_mcontext.gregs[REG_EIP]; + ctx->ebp = (long) uc->uc_mcontext.gregs[REG_EBP]; + ctx->pid = GetCurrentThreadId(); +} + void GetCurrentBacktraceContext( BacktraceContext *ctx ) { register void *esp __asm__ ("esp"); @@ -201,10 +209,6 @@ static void do_backtrace( const void **buf, size_t size, BacktraceContext *ctx ) { StackFrame *link; char *return_address; - - /* These are only relevant if the frame is a signal trampoline. */ - int signal; - sigcontext sig; }; StackFrame *frame = (StackFrame *) ctx->ebp; @@ -226,47 +230,10 @@ static void do_backtrace( const void **buf, size_t size, BacktraceContext *ctx ) //if( frame->return_address == (void*) CrashSignalHandler ) // continue; - /* - * The stack return stub is: - * - * 0x401139d8 : pop %eax 0x58 - * 0x401139d9 : mov $0x77,%eax 0xb8 0x77 0x00 0x00 0x00 - * 0x401139de : int $0x80 0xcd 0x80 - * - * This will be different if using realtime signals, as will the stack layout. - * - * If we detect this, it means this is a stack frame returning from a signal. - * Ignore the return_address and use the sigcontext instead. - */ - const char comp[] = { 0x58, 0xb8, 0x77, 0x0, 0x0, 0x0, 0xcd, 0x80 }; - bool is_signal_return = true; + if( frame->return_address ) + buf[i++] = frame->return_address; - /* Ugh. Linux 2.6 is putting the return address in a place that isn't listed - * as readable in /proc/pid/maps. This is probably brittle. */ - if( frame->return_address != (void*)0xffffe420 && - find_address(frame->return_address, readable_begin, readable_end) == -1) - is_signal_return = false; - - for( unsigned pos = 0; is_signal_return && pos < sizeof(comp); ++pos ) - if(frame->return_address[pos] != comp[pos]) - is_signal_return = false; - - void *to_add = NULL; - if( is_signal_return ) - { - /* Mark the signal trampoline. */ - if( i < size-1 ) - buf[i++] = BACKTRACE_SIGNAL_TRAMPOLINE; - - to_add = (void *) frame->sig.eip; - } - else - to_add = frame->return_address; - - if( i < size-1 && to_add ) - buf[i++] = to_add; - - /* frame always goes down. Make sure it doesn't go up; that could + /* frame always goes up. Make sure it doesn't go down; that could * cause an infinite loop. */ if( frame->link <= frame ) break; diff --git a/stepmania/src/archutils/Unix/Backtrace.h b/stepmania/src/archutils/Unix/Backtrace.h index b57692b71d..6519506b51 100644 --- a/stepmania/src/archutils/Unix/Backtrace.h +++ b/stepmania/src/archutils/Unix/Backtrace.h @@ -28,6 +28,11 @@ void GetBacktrace( const void **buf, size_t size, BacktraceContext *ctx = NULL ) int GetThreadBacktraceContext( int ThreadID, BacktraceContext *ctx ); void GetCurrentBacktraceContext( BacktraceContext *ctx ); +/* Set up a BacktraceContext to get a backtrace after receiving a signal, given + * a ucontext_t (see sigaction(2)). (This interface is UNIX-specific.) */ +#include +void GetSignalBacktraceContext( BacktraceContext *ctx, const ucontext_t *uc ); + #define BACKTRACE_METHOD_NOT_AVAILABLE ((void*) -1) #define BACKTRACE_SIGNAL_TRAMPOLINE ((void*) -2) diff --git a/stepmania/src/archutils/Unix/CrashHandler.cpp b/stepmania/src/archutils/Unix/CrashHandler.cpp index d6cc9a9e1c..77028796d0 100644 --- a/stepmania/src/archutils/Unix/CrashHandler.cpp +++ b/stepmania/src/archutils/Unix/CrashHandler.cpp @@ -226,7 +226,7 @@ const char *SignalName( int signo ) #endif } -void CrashSignalHandler( int signal ) +void CrashSignalHandler( int signal, siginfo_t *si, const ucontext_t *uc ) { if( g_pCrashHandlerArgv0 == NULL ) { @@ -236,6 +236,7 @@ void CrashSignalHandler( int signal ) /* Block SIGPIPE, so we get EPIPE. */ struct sigaction sa; + memset( &sa, 0, sizeof(sa) ); sa.sa_handler = SIG_IGN; if( sigaction( SIGPIPE, &sa, NULL ) != 0 ) { @@ -267,26 +268,11 @@ void CrashSignalHandler( int signal ) // RageThread::HaltAllThreads(); /* Do this early, so functions called below don't end up on the backtrace. */ + BacktraceContext ctx; + GetSignalBacktraceContext( &ctx, uc ); const void *BacktracePointers[BACKTRACE_MAX_SIZE]; - GetBacktrace( BacktracePointers, BACKTRACE_MAX_SIZE ); + GetBacktrace( BacktracePointers, BACKTRACE_MAX_SIZE, &ctx ); - /* If we have BACKTRACE_SIGNAL_TRAMPOLINE, remove it and everything before it. */ - for( int i = 0; BacktracePointers[i]; ++i ) - { - if( BacktracePointers[i] != BACKTRACE_SIGNAL_TRAMPOLINE ) - continue; - - ++i; - - /* Find the terminator. */ - int end = i; - while( BacktracePointers[end] ) - ++end; - - memmove( &BacktracePointers[0], &BacktracePointers[i], sizeof(void*) * end-i-1 ); - break; - } - /* We need to be very careful, since we're under crash conditions. Let's fork * a process and exec ourself to get a clean environment to work in. */ int fds[2]; diff --git a/stepmania/src/archutils/Unix/CrashHandler.h b/stepmania/src/archutils/Unix/CrashHandler.h index dae1e468b4..52a0d1571a 100644 --- a/stepmania/src/archutils/Unix/CrashHandler.h +++ b/stepmania/src/archutils/Unix/CrashHandler.h @@ -1,7 +1,9 @@ #ifndef CRASH_HANDLER_H #define CRASH_HANDLER_H -void CrashSignalHandler(int signal); +#include + +void CrashSignalHandler( int signal, siginfo_t *si, const ucontext_t *uc ); void CrashHandlerHandleArgs( int argc, char* argv[] ); void InitializeCrashHandler();