Handle SIGSEGV and decode traps
diff --git a/sigreturn.c b/sigreturn.c
index 3bdd6fd..bbf13ce 100644
--- a/sigreturn.c
+++ b/sigreturn.c
@@ -124,7 +124,7 @@
 static gregset_t initial_regs, requested_regs, resulting_regs;
 
 static volatile unsigned short sig_cs, sig_ss;
-static volatile bool sig_trapped;
+static volatile sig_atomic_t sig_trapped, sig_err, sig_trapno;
 
 #ifdef __x86_64__
 # define REG_IP REG_RIP
@@ -184,6 +184,9 @@
 {
 	ucontext_t *ctx = (ucontext_t*)ctx_void;
 
+	sig_err = ctx->uc_mcontext.gregs[REG_ERR];
+	sig_trapno = ctx->uc_mcontext.gregs[REG_TRAPNO];
+
 	unsigned short ss;
 	asm ("mov %%ss,%0" : "=r" (ss));
 
@@ -197,7 +200,7 @@
 	memcpy(&resulting_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
 	memcpy(&ctx->uc_mcontext.gregs, &initial_regs, sizeof(gregset_t));
 
-	sig_trapped = true;
+	sig_trapped = sig;
 }
 
 static char altstack_data[SIGSTKSZ];
@@ -342,10 +345,39 @@
 	printf("[RUN]\t%d-bit CS (%hx), bogus SS (%hx)\n",
 	       cs_bits, sig_cs, sig_ss);
 
-	sig_trapped = false;
+	sig_trapped = 0;
 	raise(SIGUSR1);
 	if (sig_trapped) {
-		printf("[OK]\tGot SIGSEGV\n");
+		char errdesc[32] = "";
+		if (sig_err) {
+			const char *src = (sig_err & 1) ? " EXT" : "";
+			const char *table;
+			if ((sig_err & 0x6) == 0x0)
+				table = "GDT";
+			else if ((sig_err & 0x6) == 0x4)
+				table = "LDT";
+			else if ((sig_err & 0x6) == 0x2)
+				table = "IDT";
+			else
+				table = "???";
+
+			sprintf(errdesc, "%s%s index %d, ",
+				table, src, sig_err >> 3);
+		}
+
+		char trapname[32];
+		if (sig_trapno == 13)
+			strcpy(trapname, "GP");
+		else if (sig_trapno == 11)
+			strcpy(trapname, "NP");
+		else if (sig_trapno == 12)
+			strcpy(trapname, "SS");
+		else
+			sprintf(trapname, "%d", sig_trapno);
+
+		printf("[OK]\tGot #%s(0x%lx) (i.e. %s%s)\n",
+		       trapname, (unsigned long)sig_err,
+		       errdesc, strsignal(sig_trapped));
 		return 0;
 	} else {
 		printf("[FAIL]\tDid not get SIGSEGV\n");
@@ -381,6 +413,7 @@
 
 	clearhandler(SIGTRAP);
 	sethandler(SIGSEGV, sigtrap, SA_ONSTACK);
+	sethandler(SIGBUS, sigtrap, SA_ONSTACK);
 
 	test_bad_iret(64, (2 << 3) | 7, -1);
 	test_bad_iret(32, (2 << 3) | 7, -1);