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 );
135static void debug_backtrace_error_callback(
void* data,
const char* msg,
int errnum )
137 FrameInfo *fi = data;
140 debug_backtrace_syminfo_callback( data, fi->pc,
"??", 0, 0 );
146static int debug_backtrace_full_callback(
void* data, uintptr_t pc,
const char* file,
int line,
const char* func )
148 FrameInfo fi = { .data = data, .pc = pc, .file = file, .line = line, .func = func };
149 if (pc != 0 && ~pc != 0)
150 backtrace_syminfo( debug_bs, pc, debug_backtrace_syminfo_callback, debug_backtrace_error_callback, &fi );
158void debug_logBacktrace (
void) {
159 backtrace_full( debug_bs, 1, debug_backtrace_full_callback, NULL, NULL );
163static void debug_sigHandler(
int sig, siginfo_t *info,
void *unused )
165static void debug_sigHandler(
int sig )
173 LOGERR( _(
"Naev received %s!"),
175 debug_sigCodeToStr( info->si_signo, info->si_code )
177 debug_sigCodeToStr( sig, 0 )
181 debug_logBacktrace();
182 LOGERR( _(
"Report this to project maintainer with the backtrace.") );
200 debug_bs = backtrace_create_state( addr.dli_fname, 1, NULL, NULL );
204 const char *str = _(
"Unable to set up %s signal handler.");
205 struct sigaction so, sa = { .sa_handler = NULL, .sa_flags = SA_SIGINFO };
206 sa.sa_sigaction = debug_sigHandler;
207 sigemptyset(&sa.sa_mask);
209 sigaction(SIGSEGV, &sa, &so);
210 if (so.sa_handler == SIG_IGN)
211 DEBUG( str,
"SIGSEGV" );
212 sigaction(SIGFPE, &sa, &so);
213 if (so.sa_handler == SIG_IGN)
214 DEBUG( str,
"SIGFPE" );
215 sigaction(SIGABRT, &sa, &so);
216 if (so.sa_handler == SIG_IGN)
217 DEBUG( str,
"SIGABRT" );
219 signal( SIGSEGV, debug_sigHandler );
220 signal( SIGFPE, debug_sigHandler );
221 signal( SIGABRT, debug_sigHandler );
233 signal( SIGSEGV, SIG_DFL );
234 signal( SIGFPE, SIG_DFL );
235 signal( SIGABRT, 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.
static char buf[NEWS_MAX_LENGTH]