Signal tracing support

This patch adds '-Xtrace:signals' command line option for tracing VM
signals.

Signed-off-by: Pekka Enberg <penberg@kernel.org>
diff --git a/include/vm/signal.h b/include/vm/signal.h
index 81e34a7..013a3b9 100644
--- a/include/vm/signal.h
+++ b/include/vm/signal.h
@@ -1,6 +1,8 @@
 #ifndef VM_SIGNAL_H
 #define VM_SIGNAL_H
 
+#include <stdbool.h>
+
 /*
  * Signal bottom half handler is called with the address of faulting
  * instruction as argument. The address that handler returns is the
@@ -28,4 +30,6 @@
 				       __builtin_frame_address(2),	\
 				       (unsigned char *)jit_addr)
 
+extern bool opt_trace_signals;
+
 #endif /* VM_SIGNAL_H */
diff --git a/jato.c b/jato.c
index b857949..8a67b00 100644
--- a/jato.c
+++ b/jato.c
@@ -833,6 +833,11 @@
 	opt_trace_compile = true;
 }
 
+static void handle_trace_signals(void)
+{
+	opt_trace_signals = true;
+}
+
 static void handle_trace_trampoline(void)
 {
 	opt_trace_magic_trampoline = true;
@@ -926,6 +931,7 @@
 	DEFINE_OPTION("Xtrace:itable",		handle_trace_itable),
 	DEFINE_OPTION("Xtrace:jit",		handle_trace_jit),
 	DEFINE_OPTION("Xtrace:liveness",	handle_trace_liveness),
+	DEFINE_OPTION("Xtrace:signals",		handle_trace_signals),
 	DEFINE_OPTION("Xtrace:trampoline",	handle_trace_trampoline),
 	DEFINE_OPTION("Xtrace:verifier",	handle_trace_verifier),
 	DEFINE_OPTION("Xtrace:vtable",		handle_trace_vtable),
diff --git a/sys/linux-x86/include/sys/signal.h b/sys/linux-x86/include/sys/signal.h
index 02ea369..2ab2eb5 100644
--- a/sys/linux-x86/include/sys/signal.h
+++ b/sys/linux-x86/include/sys/signal.h
@@ -15,5 +15,6 @@
 
 bool signal_from_native(void *ctx);
 struct compilation_unit *get_signal_source_cu(void *ctx);
+void trace_signal(int sig, siginfo_t *si, void *ctx);
 
 #endif
diff --git a/sys/linux-x86/signal.c b/sys/linux-x86/signal.c
index 8fdf2d5..0adee00 100644
--- a/sys/linux-x86/signal.c
+++ b/sys/linux-x86/signal.c
@@ -32,6 +32,9 @@
 #include "arch/stack-frame.h"
 
 #include "vm/signal.h"
+#include "vm/trace.h"
+
+#include <string.h>
 
 extern void signal_bh_trampoline(void *bh);
 
@@ -81,3 +84,11 @@
 
 	return 0;
 }
+
+void trace_signal(int sig, siginfo_t *si, void *ctx)
+{
+	ucontext_t *uc = ctx;
+
+	trace_printf("signal %2d: ip=0x%016x: %s\n", sig, (unsigned long) uc->uc_mcontext.gregs[REG_IP], strsignal(sig));
+	trace_flush();
+}
diff --git a/vm/signal.c b/vm/signal.c
index 9edba91..f15f69a 100644
--- a/vm/signal.c
+++ b/vm/signal.c
@@ -44,6 +44,8 @@
 #include <unistd.h>
 #include <stdio.h>
 
+bool opt_trace_signals;
+
 static unsigned long throw_arithmetic_exception(unsigned long src_addr)
 {
 	signal_new_exception(vm_java_lang_ArithmeticException,
@@ -77,6 +79,9 @@
 
 static void sigfpe_handler(int sig, siginfo_t *si, void *ctx)
 {
+	if (opt_trace_signals)
+		trace_signal(sig, si, ctx);
+
 	if (signal_from_native(ctx))
 		goto exit;
 
@@ -93,11 +98,17 @@
 
 static void sigill_handler(int sig, siginfo_t *si, void *ctx)
 {
+	if (opt_trace_signals)
+		trace_signal(sig, si, ctx);
+
 	print_backtrace_and_die(sig, si, ctx);
 }
 
 static void sigsegv_handler(int sig, siginfo_t *si, void *ctx)
 {
+	if (opt_trace_signals)
+		trace_signal(sig, si, ctx);
+
 	if (signal_from_native(ctx))
 		goto exit;
 
@@ -167,6 +178,9 @@
 {
 	struct vm_thread *this;
 
+	if (opt_trace_signals)
+		trace_signal(sig, si, ctx);
+
 	print_trace();
 
 	if (main_called)