blob: 694a6b9ea2915ef474a360cbcff7f616b0db7780 [file] [log] [blame]
sewardj8eb8bab2015-07-21 14:44:28 +00001/* Test if x87 FP valus are correctly propagated in and out of a signal
2 handler and also check that the same applies for uninitialised values and
3 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
13static siginfo_t si;
14static ucontext_t uc;
15static float inhandler[8];
16
Elliott Hughesa0664b92017-04-18 17:46:52 -070017static void sighandler(int sig, siginfo_t *sip, void *arg)
sewardj8eb8bab2015-07-21 14:44:28 +000018{
19 int i;
Elliott Hughesa0664b92017-04-18 17:46:52 -070020 ucontext_t *ucp = (ucontext_t *) arg;
sewardj8eb8bab2015-07-21 14:44:28 +000021
22 si = *sip;
23 uc = *ucp;
24
25 /* Reset the FP stack so it's possible to push other values onto it. (It
26 is fully filled in main() before triggering the signal handler). Note
27 that VEX also clears all FP values when the finit instruction is
28 executed. This provides another level of validation that the restore
29 code is correct. */
30 __asm__ __volatile__(
31 "finit\n");
32
33 /* Convert 80b values in mcontext to 32b values in the inhandler array. */
34 for (i = 0; i < 8; i++) {
35 __asm__ __volatile__(
36 "fldt %[in]\n"
37 "fstps %[out]\n"
38 : [out] "=m" (inhandler[i])
39 : [in] "m" (*(char*)&ucp->uc_mcontext.fpregs.fp_reg_set.fpchip_state.st[i]));
40 }
41}
42
43int main(void)
44{
45 struct sigaction sa;
46 pid_t pid;
47 float out[8];
48 float x0;
49
50 /* Uninitialised, but we know px[0] is 0x0. */
51 float *px = malloc(sizeof(*px));
52 x0 = px[0];
53
Elliott Hughesa0664b92017-04-18 17:46:52 -070054 sa.sa_sigaction = sighandler;
sewardj8eb8bab2015-07-21 14:44:28 +000055 sa.sa_flags = SA_SIGINFO;
56 if (sigfillset(&sa.sa_mask)) {
57 perror("sigfillset");
58 return 1;
59 }
60 if (sigaction(SIGUSR1, &sa, NULL)) {
61 perror("sigaction");
62 return 1;
63 }
64
65 pid = getpid();
66
67 __asm__ __volatile__(
68 /* Set values in the FP stack. */
69 "flds %[x0]\n"
70 "fld1\n"
71 "flds %[x0]\n"
72 "fld1\n"
73 "flds %[x0]\n"
74 "fld1\n"
75 "flds %[x0]\n"
76 "fld1\n"
77
78 /* Trigger the signal handler. */
79 "syscall\n"
80 "fstps 0x00 + %[out]\n"
81 "fstps 0x04 + %[out]\n"
82 "fstps 0x08 + %[out]\n"
83 "fstps 0x0c + %[out]\n"
84 "fstps 0x10 + %[out]\n"
85 "fstps 0x14 + %[out]\n"
86 "fstps 0x18 + %[out]\n"
87 "fstps 0x1c + %[out]\n"
88 : [out] "=m" (out[0])
89 : "a" (SYS_kill), "D" (pid), "S" (SIGUSR1), [x0] "m" (x0)
90 : "rdx", "cc", "memory");
91
92 printf("Values in the signal handler:\n");
93 printf(" fp[0]=%f, fp[2]=%f, fp[4]=%f, fp[6]=%f\n",
94 inhandler[0], inhandler[2], inhandler[4], inhandler[6]);
95 /* Check that inhandler[1], inhandler[3], inhandler[5] and inhandler[7]
96 contain uninitialised values (origin is px[0]). */
97 if (inhandler[1] || inhandler[3] || inhandler[5] || inhandler[7])
98 assert(0);
99
100 printf("Values after the return from the signal handler:\n");
101 printf(" fp[0]=%f, fp[2]=%f, fp[4]=%f, fp[6]=%f\n",
102 out[0], out[2], out[4], out[6]);
103 /* Check that out[1], out[3], out[5] and out[7] contain uninitialised
104 values (origin is px[0]). */
105 if (out[1] || out[3] || out[5] || out[7])
106 assert(0);
107
108 return 0;
109}
110