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