summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2014-11-23 09:34:39 -0800
committerAndy Lutomirski <luto@amacapital.net>2014-11-23 09:34:39 -0800
commit5655bd41ffedc002af69e3a8d1b0a168c22f2549 (patch)
tree5dfc9487318620d50ae8d4b8a95c6618a69ed229
parentcdf74c9634b42742f4b2c0f8bdb76ffb41d0201f (diff)
downloadmisc-tests-5655bd41ffedc002af69e3a8d1b0a168c22f2549.tar.gz
Handle SIGSEGV and decode traps
-rw-r--r--sigreturn.c41
1 files changed, 37 insertions, 4 deletions
diff --git a/sigreturn.c b/sigreturn.c
index 3bdd6fd..bbf13ce 100644
--- a/sigreturn.c
+++ b/sigreturn.c
@@ -124,7 +124,7 @@ static void setup_ldt(void)
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 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
{
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 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
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 @@ static int test_bad_iret(int cs_bits, unsigned short ss, int force_cs)
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 @@ int main()
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);