sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 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 | |
| 13 | static siginfo_t si; |
| 14 | static ucontext_t uc; |
| 15 | /* x0 is always zero, but is visible to Valgrind as uninitialised. */ |
| 16 | static long x0; |
| 17 | |
| 18 | void break_out(void); |
| 19 | |
| 20 | static 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 | |
| 31 | int 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 | |