31static struct backtrace_state *debug_bs = NULL;
32DebugFlags debug_flags;
41const char* debug_sigCodeToStr(
int sig,
int sig_code )
46 case SI_USER:
return _(
"SIGFPE (raised by program)");
49 case FPE_INTDIV:
return _(
"SIGFPE (integer divide by zero)");
52 case FPE_INTOVF:
return _(
"SIGFPE (integer overflow)");
55 case FPE_FLTDIV:
return _(
"SIGFPE (floating-point divide by zero)");
58 case FPE_FLTOVF:
return _(
"SIGFPE (floating-point overflow)");
61 case FPE_FLTUND:
return _(
"SIGFPE (floating-point underflow)");
64 case FPE_FLTRES:
return _(
"SIGFPE (floating-point inexact result)");
67 case FPE_FLTINV:
return _(
"SIGFPE (floating-point invalid operation)");
70 case FPE_FLTSUB:
return _(
"SIGFPE (subscript out of range)");
72 default:
return _(
"SIGFPE");
74 else if (sig == SIGSEGV)
77 case SI_USER:
return _(
"SIGSEGV (raised by program)");
80 case SEGV_MAPERR:
return _(
"SIGSEGV (address not mapped to object)");
83 case SEGV_ACCERR:
return _(
"SIGSEGV (invalid permissions for mapped object)");
85 default:
return _(
"SIGSEGV");
87 else if (sig == SIGABRT)
90 case SI_USER:
return _(
"SIGABRT (raised by program)");
92 default:
return _(
"SIGABRT");
97 return strsignal(sig);
100 static char buf[128];
101 snprintf( buf,
sizeof(buf), _(
"signal %d"), sig );
109typedef struct {
void* data; uintptr_t pc;
const char* file;
int line;
const char* func; } FrameInfo;
114static void debug_backtrace_syminfo_callback(
void* data, uintptr_t pc,
const char* symname, uintptr_t symval, uintptr_t symsize )
117 FrameInfo *fi = data;
119 dladdr( (
void*) pc, &addr );
120 uintptr_t offset = pc - (symval ? symval : (uintptr_t)addr.dli_fbase);
121 pc -= (uintptr_t) addr.dli_fbase;
122 symname = symname ? symname :
"??";
123 fi->func = fi->func ? fi->func : symname;
124 fi->file = fi->file ? fi->file :
"??";
125 addr.dli_fname = addr.dli_fname ? addr.dli_fname :
"??";
126 int width = snprintf( NULL, 0,
"%s at %s:%u", fi->func, fi->file, fi->line );
127 int pad =
MAX( 0, 80 - width );
128 LOGERR(
"[%#14"PRIxPTR
"] %s at %s:%u %*s| %s(%s+%#"PRIxPTR
")", pc, fi->func, fi->file, fi->line, pad,
"", addr.dli_fname, symval ? symname :
"", offset );
134static void debug_backtrace_error_callback(
void* data,
const char* msg,
int errnum )
136 FrameInfo *fi = data;
139 debug_backtrace_syminfo_callback( data, fi->pc,
"??", 0, 0 );
145static int debug_backtrace_full_callback(
void* data, uintptr_t pc,
const char* file,
int line,
const char* func )
147 FrameInfo fi = { .data = data, .pc = pc, .file = file, .line = line, .func = func };
148 if (pc != 0 && ~pc != 0)
149 backtrace_syminfo( debug_bs, pc, debug_backtrace_syminfo_callback, debug_backtrace_error_callback, &fi );
157void debug_logBacktrace (
void) {
158 backtrace_full( debug_bs, 1, debug_backtrace_full_callback, NULL, NULL );
162static void debug_sigHandler(
int sig, siginfo_t *info,
void *unused )
164static void debug_sigHandler(
int sig )
173 LOGERR( _(
"Naev received %s!"), debug_sigCodeToStr( info->si_signo, info->si_code ) );
175 LOGERR( _(
"Naev received %s!"), debug_sigCodeToStr( sig, 0 ) );
178 debug_logBacktrace();
179 LOGERR( _(
"Report this to project maintainer with the backtrace.") );
186static void debug_sigHandlerWarn(
int sig, siginfo_t *info,
void *unused )
188static void debug_sigHandlerWarn(
int sig )
196 WARN( _(
"Naev received %s!"),
198 debug_sigCodeToStr( info->si_signo, info->si_code )
200 debug_sigCodeToStr( sig, 0 )
204 debug_logBacktrace();
219 debug_bs = backtrace_create_state( addr.dli_fname, 1, NULL, NULL );
223 const char *str = _(
"Unable to set up %s signal handler.");
224 struct sigaction so, sa = { .sa_handler = NULL, .sa_flags = SA_SIGINFO };
225 sa.sa_sigaction = debug_sigHandler;
226 sigemptyset(&sa.sa_mask);
228 sigaction(SIGSEGV, &sa, &so);
229 if (so.sa_handler == SIG_IGN)
230 DEBUG( str,
"SIGSEGV" );
231 sigaction(SIGABRT, &sa, &so);
232 if (so.sa_handler == SIG_IGN)
233 DEBUG( str,
"SIGABRT" );
235 sa.sa_sigaction = debug_sigHandlerWarn;
236 sigaction(SIGFPE, &sa, &so);
237 if (so.sa_handler == SIG_IGN)
238 DEBUG( str,
"SIGFPE" );
240 signal( SIGSEGV, debug_sigHandler );
241 signal( SIGABRT, debug_sigHandler );
242 signal( SIGFPE, debug_sigHandlerWarn );
253 signal( SIGSEGV, SIG_DFL );
254 signal( SIGABRT, SIG_DFL );
255 signal( SIGFPE, SIG_DFL );
void debug_sigInit(void)
Sets up the back-tracing signal handler.
void debug_enableLeakSanitizer(void)
Does nothing. Calling this tells our debug scripts to stop tracing.
void debug_sigClose(void)
Closes the back-tracing signal handler.
Header file with generic functions and naev-specifics.