18eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* Test if values in rax, rbx, rcx, rdx, rsi and rdi are correctly propagated 28eb8bab992e3998c33770b0cdb16059a8b918a06sewardj into and out of a signal handler and also check that the same applies for 38eb8bab992e3998c33770b0cdb16059a8b918a06sewardj uninitialised values and their origins. */ 48eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 58eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <assert.h> 68eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <signal.h> 78eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <stdio.h> 88eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <stdlib.h> 98eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <unistd.h> 10a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes#include <sys/regset.h> 118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <sys/syscall.h> 128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <sys/ucontext.h> 138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 148eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic siginfo_t si; 158eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic ucontext_t uc; 168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* x0 is always zero, but is visible to Valgrind as uninitialised. */ 178eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic long x0; 188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 198eb8bab992e3998c33770b0cdb16059a8b918a06sewardjvoid break_out(void); 208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 21a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughesstatic void sighandler(int sig, siginfo_t *sip, void *arg) 228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{ 23a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes ucontext_t *ucp = (ucontext_t *) arg; 24a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes 258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj si = *sip; 268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj uc = *ucp; 278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ucp->uc_mcontext.gregs[REG_RCX] = x0; 298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Break out of the endless loop. */ 318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj *(uintptr_t*)&ucp->uc_mcontext.gregs[REG_RIP] = (uintptr_t)break_out; 328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj} 338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 348eb8bab992e3998c33770b0cdb16059a8b918a06sewardjint main(void) 358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{ 368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj struct sigaction sa; 378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj long rax, rbx, rcx, rdx, rsi, rdi; 388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj long y0; 398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Uninitialised, but we know px[0] is 0x0. */ 418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj long *px = malloc(sizeof(*px)); 428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj x0 = px[0]; 438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Uninitialised, but we know py[0] is 0x0. */ 458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj long *py = malloc(sizeof(*py)); 468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj y0 = py[0]; 478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 48a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes sa.sa_sigaction = sighandler; 498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj sa.sa_flags = SA_SIGINFO; 508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (sigfillset(&sa.sa_mask)) { 518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj perror("sigfillset"); 528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return 1; 538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (sigaction(SIGALRM, &sa, NULL)) { 558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj perror("sigaction"); 568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return 1; 578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj alarm(2); 608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj __asm__ __volatile__( 628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Set values in general purpose registers. */ 638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "movq $0xf0, %%rax\n" 648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "movq %[y0], %%rbx\n" 658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "movq $0xf1, %%rcx\n" 668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "movq $0xf2, %%rdx\n" 678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "movq $0xf3, %%rsi\n" 688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "movq $0xf4, %%rdi\n" 698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Loopity loop, this is where the SIGALRM is triggered. */ 718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "1:\n" 728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "jmp 1b\n" 738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "break_out:\n" 758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj : "=a" (rax), "=b" (rbx), "=c" (rcx), "=d" (rdx), "=S" (rsi), 768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "=D" (rdi) 778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj : [y0] "m" (y0) 788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj : "cc", "memory"); 798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj printf("Values in the signal handler:\n"); 818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj printf(" rax=%#lx, rcx=%#lx, rdx=%#lx, rsi=%#lx, rdi=%#lx\n", 828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj uc.uc_mcontext.gregs[REG_RAX], uc.uc_mcontext.gregs[REG_RCX], 838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj uc.uc_mcontext.gregs[REG_RDX], uc.uc_mcontext.gregs[REG_RSI], 848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj uc.uc_mcontext.gregs[REG_RDI]); 858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Check that rbx contains an uninitialised value (origin is py[0]). */ 868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (uc.uc_mcontext.gregs[REG_RBX]) 878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj assert(0); 888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj printf("Values after the return from the signal handler:\n"); 908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj printf(" rax=%#lx, rdx=%#lx, rsi=%#lx, rdi=%#lx\n", rax, rdx, rsi, rdi); 918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Check that rbx and rcx contain uninitialised values (origin is py[0] 928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj and px[0], respectively). */ 938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (rbx || rcx) 948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj assert(0); 958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return 0; 978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj} 988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 99