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