• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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