• 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/syscall.h>
18 #include <sys/ucontext.h>
19 
20 #define OBIT(rflags) (!!((rflags) & (1 << 11)))
21 #define SBIT(rflags) (!!((rflags) & (1 << 7)))
22 
23 static siginfo_t si;
24 static ucontext_t uc;
25 
26 void break_out(void);
27 
sighandler(int sig,siginfo_t * sip,ucontext_t * ucp)28 static void sighandler(int sig, siginfo_t *sip, ucontext_t *ucp)
29 {
30    si = *sip;
31    uc = *ucp;
32 
33    /* Break out of the endless loop. */
34    *(uintptr_t*)&ucp->uc_mcontext.gregs[REG_RIP] = (uintptr_t)break_out;
35 }
36 
main(void)37 int main(void)
38 {
39    struct sigaction sa;
40    long rflags;
41    int x1;
42 
43    /* Uninitialised, but we know px[0] is 0x0. */
44    int *px = malloc(sizeof(*px));
45    x1 = px[0] + 1;
46 
47    sa.sa_handler = sighandler;
48    sa.sa_flags = SA_SIGINFO;
49    if (sigfillset(&sa.sa_mask)) {
50       perror("sigfillset");
51       return 1;
52    }
53    if (sigaction(SIGALRM, &sa, NULL)) {
54       perror("sigaction");
55       return 1;
56    }
57 
58    alarm(2);
59 
60    __asm__ __volatile__(
61       /* Set overflow and sign flags. */
62       "movl   %[x1], %%edx\n"
63       "addl   $0x7fffffff, %%edx\n"
64 
65       /* Loopity loop, this is where the SIGALRM is triggered. */
66       "1:\n"
67       "jmp    1b\n"
68 
69       "break_out:\n"
70       "pushfq\n"
71       "popq   %%rdx\n"
72       : "=d" (rflags)
73       : [x1] "m" (x1)
74       : "cc", "memory");
75 
76    /* Check that the overflow and sign flags are uninitialised.
77 
78       Note: This actually fails because the rflags are only approximate
79       (always initialised) in the signal handler. */
80    if (!OBIT(uc.uc_mcontext.gregs[REG_RFL]) ||
81        !SBIT(uc.uc_mcontext.gregs[REG_RFL]))
82       assert(0);
83 
84    /* Check that the overflow and sign flags are uninitialised. */
85    if (!OBIT(rflags) || !SBIT(rflags))
86       assert(0);
87 
88    return 0;
89 }
90 
91