• 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/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