signals-s390x.c (abf7aee72ea66944a62962603e4c2381f5e473e7) | signals-s390x.c (1a75b14038bd77b0af7d2ddb0cf230b31f75623e) |
---|---|
1#include <assert.h> | 1#include <assert.h> |
2#include <execinfo.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 | 3#include <signal.h> 4#include <string.h> 5#include <sys/mman.h> 6#include <ucontext.h> 7#include <unistd.h> 8 9/* 10 * Various instructions that generate SIGILL and SIGSEGV. They could have been 11 * defined in a separate .s file, but this would complicate the build, so the 12 * inline asm is used instead. 13 */ 14 |
15#define DEFINE_ASM_FUNCTION(name, body) \ 16 asm(".globl " #name "\n" \ 17 #name ":\n" \ 18 ".cfi_startproc\n" \ 19 body "\n" \ 20 "br %r14\n" \ 21 ".cfi_endproc"); 22 |
|
14void illegal_op(void); | 23void 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"); | 24extern const char after_illegal_op; 25DEFINE_ASM_FUNCTION(illegal_op, 26 ".byte 0x00,0x00\n" 27 ".globl after_illegal_op\n" 28 "after_illegal_op:") |
20 21void stg(void *dst, unsigned long src); | 29 30void stg(void *dst, unsigned long src); |
22asm(".globl\tstg\n" 23 "stg:\tstg\t%r3,0(%r2)\n" 24 "\tbr\t%r14"); | 31DEFINE_ASM_FUNCTION(stg, "stg %r3,0(%r2)") |
25 26void mvc_8(void *dst, void *src); | 32 33void 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"); | 34DEFINE_ASM_FUNCTION(mvc_8, "mvc 0(8,%r2),0(%r3)") |
30 | 35 |
36extern const char return_from_main_1; 37 |
|
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, --- 5 unchanged lines hidden (view full) --- 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{ | 38static void safe_puts(const char *s) 39{ 40 write(0, s, strlen(s)); 41 write(0, "\n", 1); 42} 43 44enum exception { 45 exception_operation, --- 5 unchanged lines hidden (view full) --- 51 int sig; 52 void *addr; 53 unsigned long psw_addr; 54 enum exception exception; 55} expected; 56 57static void handle_signal(int sig, siginfo_t *info, void *ucontext) 58{ |
59 int err, i, n_frames; 60 void *frames[16]; |
|
52 void *page; | 61 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"); --- 19 unchanged lines hidden (view full) --- 81 if (err != 0) { 82 safe_puts("[ FAILED ] mprotect() failed"); 83 _exit(1); 84 } 85 break; 86 default: 87 break; 88 } | 62 63 if (sig != expected.sig) { 64 safe_puts("[ FAILED ] wrong signal"); 65 _exit(1); 66 } 67 68 if (info->si_addr != expected.addr) { 69 safe_puts("[ FAILED ] wrong si_addr"); --- 19 unchanged lines hidden (view full) --- 89 if (err != 0) { 90 safe_puts("[ FAILED ] mprotect() failed"); 91 _exit(1); 92 } 93 break; 94 default: 95 break; 96 } |
97 98 n_frames = backtrace(frames, sizeof(frames) / sizeof(frames[0])); 99 for (i = 0; i < n_frames; i++) { 100 if (frames[i] == &return_from_main_1) { 101 break; 102 } 103 } 104 if (i == n_frames) { 105 safe_puts("[ FAILED ] backtrace() is broken"); 106 _exit(1); 107 } |
|
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; --- 20 unchanged lines hidden (view full) --- 117 mvc_8(addr, &val); 118 } 119 assert(*addr == val); 120 121 err = munmap(page, 4096); 122 assert(err == 0); 123} 124 | 108} 109 110static void check_sigsegv(void *func, enum exception exception, 111 unsigned long val) 112{ 113 int prot; 114 unsigned long *page; 115 unsigned long *addr; --- 20 unchanged lines hidden (view full) --- 136 mvc_8(addr, &val); 137 } 138 assert(*addr == val); 139 140 err = munmap(page, 4096); 141 assert(err == 0); 142} 143 |
125int main(void) | 144int main_1(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; | 145{ 146 struct sigaction act; 147 int err; 148 149 memset(&act, 0, sizeof(act)); 150 act.sa_sigaction = handle_signal; 151 act.sa_flags = SA_SIGINFO; 152 err = sigaction(SIGILL, &act, NULL); 153 assert(err == 0); 154 err = sigaction(SIGSEGV, &act, NULL); 155 assert(err == 0); 156 157 safe_puts("[ RUN ] Operation exception"); 158 expected.sig = SIGILL; 159 expected.addr = illegal_op; |
141 expected.psw_addr = (unsigned long)after_illegal_op; | 160 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 --- 8 unchanged lines hidden (view full) --- 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} | 161 expected.exception = exception_operation; 162 illegal_op(); 163 safe_puts("[ OK ]"); 164 165 safe_puts("[ RUN ] Translation exception from stg"); 166 check_sigsegv(stg, exception_translation, 42); 167 safe_puts("[ OK ]"); 168 --- 8 unchanged lines hidden (view full) --- 177 safe_puts("[ RUN ] Protection exception from mvc"); 178 check_sigsegv(mvc_8, exception_protection, 42424242); 179 safe_puts("[ OK ]"); 180 181 safe_puts("[ PASSED ]"); 182 183 _exit(0); 184} |
185 186/* 187 * Define main() in assembly in order to test that unwinding from signal 188 * handlers until main() works. This way we can define a specific point that 189 * the unwinder should reach. This is also better than defining main() in C 190 * and using inline assembly to call main_1(), since it's not easy to get all 191 * the clobbers right. 192 */ 193 194DEFINE_ASM_FUNCTION(main, 195 "stmg %r14,%r15,112(%r15)\n" 196 ".cfi_offset 14,-48\n" 197 ".cfi_offset 15,-40\n" 198 "lay %r15,-160(%r15)\n" 199 ".cfi_def_cfa_offset 320\n" 200 "brasl %r14,main_1\n" 201 ".globl return_from_main_1\n" 202 "return_from_main_1:\n" 203 "lmg %r14,%r15,272(%r15)\n" 204 ".cfi_restore 15\n" 205 ".cfi_restore 14\n" 206 ".cfi_def_cfa_offset 160"); |
|