1 /* Test if values in rax, rbx, rcx, rdx, rsi and rdi are correctly propagated 2 into and out of a signal handler and also check that the same applies for 3 uninitialised values and their origins. */ 4 5 #include <assert.h> 6 #include <signal.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <unistd.h> 10 #include <sys/regset.h> 11 #include <sys/syscall.h> 12 #include <sys/ucontext.h> 13 14 static siginfo_t si; 15 static ucontext_t uc; 16 /* x0 is always zero, but is visible to Valgrind as uninitialised. */ 17 static long x0; 18 19 void break_out(void); 20 21 static void sighandler(int sig, siginfo_t *sip, void *arg) 22 { 23 ucontext_t *ucp = (ucontext_t *) arg; 24 25 si = *sip; 26 uc = *ucp; 27 28 ucp->uc_mcontext.gregs[REG_RCX] = x0; 29 30 /* Break out of the endless loop. */ 31 *(uintptr_t*)&ucp->uc_mcontext.gregs[REG_RIP] = (uintptr_t)break_out; 32 } 33 34 int main(void) 35 { 36 struct sigaction sa; 37 long rax, rbx, rcx, rdx, rsi, rdi; 38 long y0; 39 40 /* Uninitialised, but we know px[0] is 0x0. */ 41 long *px = malloc(sizeof(*px)); 42 x0 = px[0]; 43 44 /* Uninitialised, but we know py[0] is 0x0. */ 45 long *py = malloc(sizeof(*py)); 46 y0 = py[0]; 47 48 sa.sa_sigaction = sighandler; 49 sa.sa_flags = SA_SIGINFO; 50 if (sigfillset(&sa.sa_mask)) { 51 perror("sigfillset"); 52 return 1; 53 } 54 if (sigaction(SIGALRM, &sa, NULL)) { 55 perror("sigaction"); 56 return 1; 57 } 58 59 alarm(2); 60 61 __asm__ __volatile__( 62 /* Set values in general purpose registers. */ 63 "movq $0xf0, %%rax\n" 64 "movq %[y0], %%rbx\n" 65 "movq $0xf1, %%rcx\n" 66 "movq $0xf2, %%rdx\n" 67 "movq $0xf3, %%rsi\n" 68 "movq $0xf4, %%rdi\n" 69 70 /* Loopity loop, this is where the SIGALRM is triggered. */ 71 "1:\n" 72 "jmp 1b\n" 73 74 "break_out:\n" 75 : "=a" (rax), "=b" (rbx), "=c" (rcx), "=d" (rdx), "=S" (rsi), 76 "=D" (rdi) 77 : [y0] "m" (y0) 78 : "cc", "memory"); 79 80 printf("Values in the signal handler:\n"); 81 printf(" rax=%#lx, rcx=%#lx, rdx=%#lx, rsi=%#lx, rdi=%#lx\n", 82 uc.uc_mcontext.gregs[REG_RAX], uc.uc_mcontext.gregs[REG_RCX], 83 uc.uc_mcontext.gregs[REG_RDX], uc.uc_mcontext.gregs[REG_RSI], 84 uc.uc_mcontext.gregs[REG_RDI]); 85 /* Check that rbx contains an uninitialised value (origin is py[0]). */ 86 if (uc.uc_mcontext.gregs[REG_RBX]) 87 assert(0); 88 89 printf("Values after the return from the signal handler:\n"); 90 printf(" rax=%#lx, rdx=%#lx, rsi=%#lx, rdi=%#lx\n", rax, rdx, rsi, rdi); 91 /* Check that rbx and rcx contain uninitialised values (origin is py[0] 92 and px[0], respectively). */ 93 if (rbx || rcx) 94 assert(0); 95 96 return 0; 97 } 98 99