• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Test if definedness of rflags values is correctly propagated in and out
2    of a signal handler.  Note that actually only the propagation of the
3    overflow and sign flags is tested.
4 
5    This test must use alarm(2) to trigger the signal and not kill(2) as other
6    tests do because in the latter case the signal is actually delivered after
7    the syscall finished.  This means that Valgrind had to save a correct carry
8    flag value (indicating if the syscall succeeded) in the rflags.  This save
9    operation unfortunately makes all rflags initialised (due to imprecise
10    simulation). */
11 
12 #include <assert.h>
13 #include <signal.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <sys/regset.h>
18 #include <sys/syscall.h>
19 #include <sys/ucontext.h>
20 
21 #define OBIT(rflags) (!!((rflags) & (1 << 11)))
22 #define SBIT(rflags) (!!((rflags) & (1 << 7)))
23 
24 static siginfo_t si;
25 static ucontext_t uc;
26 
27 void break_out(void);
28 
sighandler(int sig,siginfo_t * sip,void * arg)29 static void sighandler(int sig, siginfo_t *sip, void *arg)
30 {
31    ucontext_t *ucp = (ucontext_t *) arg;
32 
33    si = *sip;
34    uc = *ucp;
35 
36    /* Break out of the endless loop. */
37    *(uintptr_t*)&ucp->uc_mcontext.gregs[REG_RIP] = (uintptr_t)break_out;
38 }
39 
main(void)40 int main(void)
41 {
42    struct sigaction sa;
43    long rflags;
44    int x1;
45 
46    /* Uninitialised, but we know px[0] is 0x0. */
47    int *px = malloc(sizeof(*px));
48    x1 = px[0] + 1;
49 
50    sa.sa_sigaction = sighandler;
51    sa.sa_flags = SA_SIGINFO;
52    if (sigfillset(&sa.sa_mask)) {
53       perror("sigfillset");
54       return 1;
55    }
56    if (sigaction(SIGALRM, &sa, NULL)) {
57       perror("sigaction");
58       return 1;
59    }
60 
61    alarm(2);
62 
63    __asm__ __volatile__(
64       /* Set overflow and sign flags. */
65       "movl   %[x1], %%edx\n"
66       "addl   $0x7fffffff, %%edx\n"
67 
68       /* Loopity loop, this is where the SIGALRM is triggered. */
69       "1:\n"
70       "jmp    1b\n"
71 
72       "break_out:\n"
73       "pushfq\n"
74       "popq   %%rdx\n"
75       : "=d" (rflags)
76       : [x1] "m" (x1)
77       : "cc", "memory");
78 
79    /* Check that the overflow and sign flags are uninitialised.
80 
81       Note: This actually fails because the rflags are only approximate
82       (always initialised) in the signal handler. */
83    if (!OBIT(uc.uc_mcontext.gregs[REG_RFL]) ||
84        !SBIT(uc.uc_mcontext.gregs[REG_RFL]))
85       assert(0);
86 
87    /* Check that the overflow and sign flags are uninitialised. */
88    if (!OBIT(rflags) || !SBIT(rflags))
89       assert(0);
90 
91    return 0;
92 }
93 
94