31static struct backtrace_state *debug_bs = NULL;
32DebugFlags debug_flags;
41const char *debug_sigCodeToStr(
int sig,
int sig_code )
47 return _(
"SIGFPE (raised by program)" );
51 return _(
"SIGFPE (integer divide by zero)" );
55 return _(
"SIGFPE (integer overflow)" );
59 return _(
"SIGFPE (floating-point divide by zero)" );
63 return _(
"SIGFPE (floating-point overflow)" );
67 return _(
"SIGFPE (floating-point underflow)" );
71 return _(
"SIGFPE (floating-point inexact result)" );
75 return _(
"SIGFPE (floating-point invalid operation)" );
79 return _(
"SIGFPE (subscript out of range)" );
84 else if (sig == SIGSEGV)
88 return _(
"SIGSEGV (raised by program)" );
92 return _(
"SIGSEGV (address not mapped to object)" );
96 return _(
"SIGSEGV (invalid permissions for mapped object)" );
99 return _(
"SIGSEGV" );
101 else if (sig == SIGABRT)
105 return _(
"SIGABRT (raised by program)" );
108 return _(
"SIGABRT" );
113 return strsignal( sig );
116 static char buf[128];
117 snprintf( buf,
sizeof( buf ), _(
"signal %d" ), sig );
137static void debug_backtrace_syminfo_callback(
void *data, uintptr_t pc,
143 FrameInfo *fi = data;
144 Dl_info addr = { 0 };
145 dladdr( (
void *)pc, &addr );
146 uintptr_t offset = pc - ( symval ? symval : (uintptr_t)addr.dli_fbase );
147 pc -= (uintptr_t)addr.dli_fbase;
148 symname = symname ? symname :
"??";
149 fi->func = fi->func ? fi->func : symname;
150 fi->file = fi->file ? fi->file :
"??";
151 addr.dli_fname = addr.dli_fname ? addr.dli_fname :
"??";
152 int width = snprintf( NULL, 0,
"%s at %s:%u", fi->func, fi->file, fi->line );
153 int pad =
MAX( 0, 80 - width );
154 LOGERR(
"[%#14" PRIxPTR
"] %s at %s:%u %*s| %s(%s+%#" PRIxPTR
")", pc,
155 fi->func, fi->file, fi->line, pad,
"", addr.dli_fname,
156 symval ? symname :
"", offset );
163static void debug_backtrace_error_callback(
void *data,
const char *msg,
166 FrameInfo *fi = data;
169 debug_backtrace_syminfo_callback( data, fi->pc,
"??", 0, 0 );
175static int debug_backtrace_full_callback(
void *data, uintptr_t pc,
176 const char *file,
int line,
180 .data = data, .pc = pc, .file = file, .line = line, .func = func };
181 if (pc != 0 && ~pc != 0)
182 backtrace_syminfo( debug_bs, pc, debug_backtrace_syminfo_callback,
183 debug_backtrace_error_callback, &fi );
191static void debug_backtrace_full_error_callback(
void *data,
const char *msg,
202void debug_logBacktrace(
void )
204 backtrace_full( debug_bs, 1, debug_backtrace_full_callback,
205 debug_backtrace_full_error_callback, NULL );
209static void debug_sigHandler(
int sig, siginfo_t *info,
void *unused )
211static void debug_sigHandler(
int sig )
220 LOGERR( _(
"Naev received %s!" ),
221 debug_sigCodeToStr( info->si_signo, info->si_code ) );
223 LOGERR( _(
"Naev received %s!" ), debug_sigCodeToStr( sig, 0 ) );
226 debug_logBacktrace();
227 LOGERR( _(
"Report this to project maintainer with the backtrace." ) );
234static void debug_sigHandlerWarn(
int sig, siginfo_t *info,
void *unused )
236static void debug_sigHandlerWarn(
int sig )
244 WARN( _(
"Naev received %s!" ),
246 debug_sigCodeToStr( info->si_signo, info->si_code )
248 debug_sigCodeToStr( sig, 0 )
252 debug_logBacktrace();
262 Dl_info addr = { 0 };
270 backtrace_create_state( addr.dli_fname, 1, NULL, NULL );
274 const char *str = _(
"Unable to set up %s signal handler." );
275 struct sigaction so, sa = { .sa_handler = NULL, .sa_flags = SA_SIGINFO };
276 sa.sa_sigaction = debug_sigHandler;
277 sigemptyset( &sa.sa_mask );
279 sigaction( SIGSEGV, &sa, &so );
280 if (so.sa_handler == SIG_IGN)
281 DEBUG( str,
"SIGSEGV" );
282 sigaction( SIGABRT, &sa, &so );
283 if (so.sa_handler == SIG_IGN)
284 DEBUG( str,
"SIGABRT" );
286 sa.sa_sigaction = debug_sigHandlerWarn;
287 sigaction( SIGFPE, &sa, &so );
288 if (so.sa_handler == SIG_IGN)
289 DEBUG( str,
"SIGFPE" );
291 signal( SIGSEGV, debug_sigHandler );
292 signal( SIGABRT, debug_sigHandler );
293 signal( SIGFPE, debug_sigHandlerWarn );
304 signal( SIGSEGV, SIG_DFL );
305 signal( SIGABRT, SIG_DFL );
306 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.