• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* 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 
13 static siginfo_t si;
14 static ucontext_t uc;
15 static float inhandler[8];
16 
sighandler(int sig,siginfo_t * sip,void * arg)17 static void sighandler(int sig, siginfo_t *sip, void *arg)
18 {
19    int i;
20    ucontext_t *ucp = (ucontext_t *) arg;
21 
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 
main(void)43 int 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 
54    sa.sa_sigaction = sighandler;
55    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 
111