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