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
sighandler(int sig,siginfo_t * sip,void * arg)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
main(void)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