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