signals-s390x.c (4222B)
1#include <assert.h> 2#include <signal.h> 3#include <string.h> 4#include <sys/mman.h> 5#include <ucontext.h> 6#include <unistd.h> 7 8/* 9 * Various instructions that generate SIGILL and SIGSEGV. They could have been 10 * defined in a separate .s file, but this would complicate the build, so the 11 * inline asm is used instead. 12 */ 13 14void illegal_op(void); 15void after_illegal_op(void); 16asm(".globl\tillegal_op\n" 17 "illegal_op:\t.byte\t0x00,0x00\n" 18 "\t.globl\tafter_illegal_op\n" 19 "after_illegal_op:\tbr\t%r14"); 20 21void stg(void *dst, unsigned long src); 22asm(".globl\tstg\n" 23 "stg:\tstg\t%r3,0(%r2)\n" 24 "\tbr\t%r14"); 25 26void mvc_8(void *dst, void *src); 27asm(".globl\tmvc_8\n" 28 "mvc_8:\tmvc\t0(8,%r2),0(%r3)\n" 29 "\tbr\t%r14"); 30 31static void safe_puts(const char *s) 32{ 33 write(0, s, strlen(s)); 34 write(0, "\n", 1); 35} 36 37enum exception { 38 exception_operation, 39 exception_translation, 40 exception_protection, 41}; 42 43static struct { 44 int sig; 45 void *addr; 46 unsigned long psw_addr; 47 enum exception exception; 48} expected; 49 50static void handle_signal(int sig, siginfo_t *info, void *ucontext) 51{ 52 void *page; 53 int err; 54 55 if (sig != expected.sig) { 56 safe_puts("[ FAILED ] wrong signal"); 57 _exit(1); 58 } 59 60 if (info->si_addr != expected.addr) { 61 safe_puts("[ FAILED ] wrong si_addr"); 62 _exit(1); 63 } 64 65 if (((ucontext_t *)ucontext)->uc_mcontext.psw.addr != expected.psw_addr) { 66 safe_puts("[ FAILED ] wrong psw.addr"); 67 _exit(1); 68 } 69 70 switch (expected.exception) { 71 case exception_translation: 72 page = mmap(expected.addr, 4096, PROT_READ | PROT_WRITE, 73 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); 74 if (page != expected.addr) { 75 safe_puts("[ FAILED ] mmap() failed"); 76 _exit(1); 77 } 78 break; 79 case exception_protection: 80 err = mprotect(expected.addr, 4096, PROT_READ | PROT_WRITE); 81 if (err != 0) { 82 safe_puts("[ FAILED ] mprotect() failed"); 83 _exit(1); 84 } 85 break; 86 default: 87 break; 88 } 89} 90 91static void check_sigsegv(void *func, enum exception exception, 92 unsigned long val) 93{ 94 int prot; 95 unsigned long *page; 96 unsigned long *addr; 97 int err; 98 99 prot = exception == exception_translation ? PROT_NONE : PROT_READ; 100 page = mmap(NULL, 4096, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 101 assert(page != MAP_FAILED); 102 if (exception == exception_translation) { 103 /* Hopefully nothing will be mapped at this address. */ 104 err = munmap(page, 4096); 105 assert(err == 0); 106 } 107 addr = page + (val & 0x1ff); 108 109 expected.sig = SIGSEGV; 110 expected.addr = page; 111 expected.psw_addr = (unsigned long)func; 112 expected.exception = exception; 113 if (func == stg) { 114 stg(addr, val); 115 } else { 116 assert(func == mvc_8); 117 mvc_8(addr, &val); 118 } 119 assert(*addr == val); 120 121 err = munmap(page, 4096); 122 assert(err == 0); 123} 124 125int main(void) 126{ 127 struct sigaction act; 128 int err; 129 130 memset(&act, 0, sizeof(act)); 131 act.sa_sigaction = handle_signal; 132 act.sa_flags = SA_SIGINFO; 133 err = sigaction(SIGILL, &act, NULL); 134 assert(err == 0); 135 err = sigaction(SIGSEGV, &act, NULL); 136 assert(err == 0); 137 138 safe_puts("[ RUN ] Operation exception"); 139 expected.sig = SIGILL; 140 expected.addr = illegal_op; 141 expected.psw_addr = (unsigned long)after_illegal_op; 142 expected.exception = exception_operation; 143 illegal_op(); 144 safe_puts("[ OK ]"); 145 146 safe_puts("[ RUN ] Translation exception from stg"); 147 check_sigsegv(stg, exception_translation, 42); 148 safe_puts("[ OK ]"); 149 150 safe_puts("[ RUN ] Translation exception from mvc"); 151 check_sigsegv(mvc_8, exception_translation, 4242); 152 safe_puts("[ OK ]"); 153 154 safe_puts("[ RUN ] Protection exception from stg"); 155 check_sigsegv(stg, exception_protection, 424242); 156 safe_puts("[ OK ]"); 157 158 safe_puts("[ RUN ] Protection exception from mvc"); 159 check_sigsegv(mvc_8, exception_protection, 42424242); 160 safe_puts("[ OK ]"); 161 162 safe_puts("[ PASSED ]"); 163 164 _exit(0); 165}