diff --git a/tools/testing/selftests/x86/sigreturn.c b/tools/testing/selftests/x86/sigreturn.c index 5d7961a5f7f6..60532fd824e4 100644 --- a/tools/testing/selftests/x86/sigreturn.c +++ b/tools/testing/selftests/x86/sigreturn.c @@ -101,9 +101,13 @@ asm (".pushsection .text\n\t" "mov %ss,%ecx\n\t" "int3\n\t" ".size int3, . - int3\n\t" + ".type int31, @function\n\t" + "int31:\n\t" + "int $0x31\n\t" ".align 4096, 0xcc\n\t" ".popsection"); extern char int3[4096]; +extern char int31[]; /* * At startup, we prepapre: @@ -296,6 +300,7 @@ static volatile sig_atomic_t sig_corrupt_final_ss; # define REG_IP REG_RIP # define REG_SP REG_RSP # define REG_CX REG_RCX +# define REG_AX REG_RAX struct selectors { unsigned short cs, gs, fs, ss; @@ -316,6 +321,7 @@ static unsigned short *csptr(ucontext_t *ctx) # define REG_IP REG_EIP # define REG_SP REG_ESP # define REG_CX REG_ECX +# define REG_AX REG_EAX static greg_t *ssptr(ucontext_t *ctx) { @@ -444,9 +450,12 @@ static void sigusr1(int sig, siginfo_t *info, void *ctx_void) *ssptr(ctx) = sig_ss; ctx->uc_mcontext.gregs[REG_IP] = - sig_cs == code16_sel ? 0 : (unsigned long)&int3; + sig_cs == code16_sel ? ((unsigned long)&int31 - + (unsigned long)&int3) | 0x100000000 : + (unsigned long)&int3; ctx->uc_mcontext.gregs[REG_SP] = (unsigned long)0x8badf00d5aadc0deULL; ctx->uc_mcontext.gregs[REG_CX] = 0; + ctx->uc_mcontext.gregs[REG_AX] = 0; #ifdef __i386__ /* @@ -515,6 +524,20 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void) sig_trapped = sig; } +static void sigsegv(int sig, siginfo_t *info, void *ctx_void) +{ + ucontext_t *ctx = (ucontext_t*)ctx_void; + + validate_signal_ss(sig, ctx); + + sig_err = ctx->uc_mcontext.gregs[REG_ERR]; + sig_trapno = ctx->uc_mcontext.gregs[REG_TRAPNO]; + printf("err=%x trapno=%x ax=%x ip=%llx\n", sig_err, sig_trapno, + (unsigned)ctx->uc_mcontext.gregs[REG_AX], + (unsigned long long)ctx->uc_mcontext.gregs[REG_IP]); + _exit(0); +} + #ifdef __x86_64__ /* Tests recovery if !UC_STRICT_RESTORE_SS */ static void sigusr2(int sig, siginfo_t *info, void *ctx_void) @@ -777,6 +800,7 @@ int main() sethandler(SIGUSR1, sigusr1, 0); sethandler(SIGTRAP, sigtrap, SA_ONSTACK); + sethandler(SIGSEGV, sigsegv, SA_ONSTACK); /* Easy cases: return to a 32-bit SS in each possible CS bitness. */ total_nerrs += test_valid_sigreturn(64, false, -1);