#include #include #include #include #include #include #include #include #include static int dnprintf(int fd, const char *fmt, ...) { va_list ap; #define BUFSIZE 1024 static char buf[BUFSIZE]; va_start(ap, fmt); vsnprintf(buf, BUFSIZE, fmt, ap); va_end(ap); return write(fd, buf, strnlen(buf, BUFSIZE)); } static void write_hex(int fd, void *p, unsigned int n) { while (n--) { unsigned int i = *(unsigned char *)p++; dnprintf(fd, "%02x", i & 0xff); } } static volatile sig_atomic_t done; static void handler(int sig, siginfo_t *info, void *ucontext) { ucontext_t *uc = ucontext; dnprintf(2, "%s: si_signo %2d, si_code %3d, si_addr 0x%08x, ", __func__, info->si_signo, info->si_code, info->si_addr); dnprintf(2, "uc_mcontext "); write_hex(2, &uc->uc_mcontext, sizeof(uc->uc_mcontext)); dnprintf(2, ", __glibc_reserved1 "); write_hex(2, &uc->__glibc_reserved1, sizeof(uc->__glibc_reserved1)); dnprintf(2, "\n"); switch (sig) { case SIGALRM: // Arrange for signal delivery on return from handler dnprintf(2, "%s: raise(SIGUSR1), raise(SIGUSR2)\n", __func__); raise(SIGUSR1); raise(SIGUSR2); break; case SIGUSR1: case SIGUSR2: // Nothing to do break; case SIGFPE: // Fix up divisor uc->uc_mcontext.gregs[2] = 1; // REG_D2 break; case SIGBUS: // Give up raise(SIGABRT); } done = 1; } int main(void) { sigset_t mask; sigfillset(&mask); struct sigaction sa = { .sa_sigaction = handler, .sa_mask = mask, .sa_flags = SA_SIGINFO, }; sigaction(SIGALRM, &sa, NULL); sigaction(SIGUSR1, &sa, NULL); sigaction(SIGUSR2, &sa, NULL); sigaction(SIGFPE, &sa, NULL); sigaction(SIGBUS, &sa, NULL); // Arrange for signal delivery on return from trap dnprintf(2, "%s: raise(SIGALRM)\n", __func__); raise(SIGALRM); // Signal delivery on return from interrupt dnprintf(2, "%s: alarm(2)\n", __func__); alarm(2); done = 0; while (!done) continue; // Signal delivery on return from exception dnprintf(2, "%s: divide by zero\n", __func__); asm("clrl %%d2 \n\ divsl %%d2,%%d1 \n\ " : : : "d1", "d2"); // Signal delivery on return from fault char pattern[] = "/tmp/sigXXXXXX"; int fd = mkstemp(pattern); if (fd == -1) return 1; unlink(pattern); volatile char *addr = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (addr == (char *)-1) return 2; dnprintf(2, "%s: read pointer %p\n", __func__, addr); *addr; }