Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Invoke GDB on crash when NVC_GDB environment variable is set

  • Loading branch information...
commit 7d50e70ab9a7bd438293a5461018954498377177 1 parent c9583b8
@nickg authored
Showing with 53 additions and 2 deletions.
  1. +5 −1 src/nvc.c
  2. +47 −1 src/util.c
  3. +1 −0  src/util.h
View
6 src/nvc.c
@@ -411,9 +411,13 @@ static void version(void)
int main(int argc, char **argv)
{
term_init();
- register_trace_signal_handlers();
set_default_opts();
+ if (getenv("NVC_GDB") != NULL)
+ register_gdb_signal_handlers();
+ else
+ register_trace_signal_handlers();
+
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'v'},
View
48 src/util.c
@@ -417,6 +417,8 @@ static void bt_sighandler(int sig, siginfo_t *info, void *secret)
exit(EXIT_FAILURE);
}
+#endif // NO_STACK_TRACE
+
static bool is_debugger_running(void)
{
#if defined __APPLE__
@@ -491,7 +493,29 @@ static bool is_debugger_running(void)
#endif
}
-#endif // NO_STACK_TRACE
+static void gdb_sighandler(int sig, siginfo_t *info)
+{
+ char exe[256];
+ if (readlink("/proc/self/exe", exe, sizeof(exe)) < 0)
+ fatal_errno("readlink");
+
+ char pid[16];
+ snprintf(pid, sizeof(pid), "%d", getpid());
+
+ pid_t p = fork();
+ if (p == 0) {
+ execl("/usr/bin/gdb", "gdb", "-ex", "cont", exe, pid, NULL);
+ fatal_errno("execl");
+ }
+ else if (p < 0)
+ fatal_errno("fork");
+ else {
+ // Allow a little time for GDB to start before dropping
+ // into the default signal handler
+ sleep(1);
+ signal(sig, SIG_DFL);
+ }
+}
void register_trace_signal_handlers(void)
{
@@ -513,6 +537,28 @@ void register_trace_signal_handlers(void)
#endif // NO_STACK_TRACE
}
+void register_gdb_signal_handlers(void)
+{
+#ifdef __linux
+ if (is_debugger_running())
+ return;
+
+ struct sigaction sa;
+ sa.sa_sigaction = (void*)gdb_sighandler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART | SA_SIGINFO;
+
+ sigaction(SIGSEGV, &sa, NULL);
+ sigaction(SIGUSR1, &sa, NULL);
+ sigaction(SIGFPE, &sa, NULL);
+ sigaction(SIGBUS, &sa, NULL);
+ sigaction(SIGILL, &sa, NULL);
+ sigaction(SIGABRT, &sa, NULL);
+#else // __linux
+ register_trace_signal_handlers();
+#endif // __linux
+}
+
void write_u32(uint32_t u, FILE *f)
{
if (fwrite(&u, sizeof(uint32_t), 1, f) != 1)
View
1  src/util.h
@@ -67,6 +67,7 @@ void fmt_loc(FILE *f, const loc_t *loc);
void show_stacktrace(void);
void register_trace_signal_handlers(void);
+void register_gdb_signal_handlers(void);
void term_init(void);
Please sign in to comment.
Something went wrong with that request. Please try again.