#include <sys/syscall.h>
#include <err.h>
#include <signal.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifndef __amd64__
#error "amd64 only"
#endif
static uintptr_t int0x80_loc;
static int signo;
extern char after_int0x80[];
static void
sigill_action(int signo1, siginfo_t *si __unused, void *uctxv)
{
ucontext_t *uctx = uctxv;
signo = signo1;
int0x80_loc = uctx->uc_mcontext.mc_rip;
}
static int
fire(void)
{
int res;
res = SYS_getpid;
asm volatile(
".globl\tafter_int0x80\n"
"\tint\t$0x80\n"
"after_int0x80:"
: "+a" (res)
:
: "rdx", "memory", "cc");
return (res);
}
int
main(void)
{
struct sigaction sa;
char signame[SIG2STR_MAX];
int pid, res;
res = 0;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = sigill_action;
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGBUS, &sa, NULL) == -1)
err(1, "catching SIGBUS");
pid = fire();
atomic_signal_fence(memory_order_seq_cst);
if (int0x80_loc == 0) {
printf("int $0x80 does not raise SIGBUS\n");
if (pid == getpid())
printf("and syscall worked\n");
else
printf("but syscall did not worked\n");
res = 1;
} else {
sig2str(signo, signame);
printf("int $0x80 raises SIG%s\n", signame);
if (int0x80_loc == (uintptr_t)after_int0x80) {
printf("at expected location\n");
} else {
printf("not at expected location\n");
res = 1;
}
}
exit(res);
}