blob: d955118d7771cacd4ae3b4eb065eb59dd1c50871 [file] [log] [blame]
sewardj8eb8bab2015-07-21 14:44:28 +00001/* 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