1 /* Test if definedness of rflags values is correctly propagated in and out 2 of a signal handler. Note that actually only the propagation of the 3 overflow and sign flags is tested. 4 5 This test must use alarm(2) to trigger the signal and not kill(2) as other 6 tests do because in the latter case the signal is actually delivered after 7 the syscall finished. This means that Valgrind had to save a correct carry 8 flag value (indicating if the syscall succeeded) in the rflags. This save 9 operation unfortunately makes all rflags initialised (due to imprecise 10 simulation). */ 11 12 #include <assert.h> 13 #include <signal.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <unistd.h> 17 #include <sys/regset.h> 18 #include <sys/syscall.h> 19 #include <sys/ucontext.h> 20 21 #define OBIT(rflags) (!!((rflags) & (1 << 11))) 22 #define SBIT(rflags) (!!((rflags) & (1 << 7))) 23 24 static siginfo_t si; 25 static ucontext_t uc; 26 27 void break_out(void); 28 29 static void sighandler(int sig, siginfo_t *sip, void *arg) 30 { 31 ucontext_t *ucp = (ucontext_t *) arg; 32 33 si = *sip; 34 uc = *ucp; 35 36 /* Break out of the endless loop. */ 37 *(uintptr_t*)&ucp->uc_mcontext.gregs[REG_RIP] = (uintptr_t)break_out; 38 } 39 40 int main(void) 41 { 42 struct sigaction sa; 43 long rflags; 44 int x1; 45 46 /* Uninitialised, but we know px[0] is 0x0. */ 47 int *px = malloc(sizeof(*px)); 48 x1 = px[0] + 1; 49 50 sa.sa_sigaction = sighandler; 51 sa.sa_flags = SA_SIGINFO; 52 if (sigfillset(&sa.sa_mask)) { 53 perror("sigfillset"); 54 return 1; 55 } 56 if (sigaction(SIGALRM, &sa, NULL)) { 57 perror("sigaction"); 58 return 1; 59 } 60 61 alarm(2); 62 63 __asm__ __volatile__( 64 /* Set overflow and sign flags. */ 65 "movl %[x1], %%edx\n" 66 "addl $0x7fffffff, %%edx\n" 67 68 /* Loopity loop, this is where the SIGALRM is triggered. */ 69 "1:\n" 70 "jmp 1b\n" 71 72 "break_out:\n" 73 "pushfq\n" 74 "popq %%rdx\n" 75 : "=d" (rflags) 76 : [x1] "m" (x1) 77 : "cc", "memory"); 78 79 /* Check that the overflow and sign flags are uninitialised. 80 81 Note: This actually fails because the rflags are only approximate 82 (always initialised) in the signal handler. */ 83 if (!OBIT(uc.uc_mcontext.gregs[REG_RFL]) || 84 !SBIT(uc.uc_mcontext.gregs[REG_RFL])) 85 assert(0); 86 87 /* Check that the overflow and sign flags are uninitialised. */ 88 if (!OBIT(rflags) || !SBIT(rflags)) 89 assert(0); 90 91 return 0; 92 } 93 94