1*433d6423SLionel Sambuc
2*433d6423SLionel Sambuc /* This test tests whether registers are correctly restored after a
3*433d6423SLionel Sambuc * signal handler is executed. The assembly file (test57loop.S) puts
4*433d6423SLionel Sambuc * 'random' values in the registers, and the C code checks whether
5*433d6423SLionel Sambuc * these values are the same, before and after the signal handler.
6*433d6423SLionel Sambuc */
7*433d6423SLionel Sambuc
8*433d6423SLionel Sambuc #define _POSIX_SOURCE 1
9*433d6423SLionel Sambuc
10*433d6423SLionel Sambuc #include <stdio.h>
11*433d6423SLionel Sambuc #include <signal.h>
12*433d6423SLionel Sambuc #include <err.h>
13*433d6423SLionel Sambuc #include <stdlib.h>
14*433d6423SLionel Sambuc #include <unistd.h>
15*433d6423SLionel Sambuc
16*433d6423SLionel Sambuc #include <sys/types.h>
17*433d6423SLionel Sambuc #include <sys/wait.h>
18*433d6423SLionel Sambuc
19*433d6423SLionel Sambuc #define SIGNAL SIGUSR1
20*433d6423SLionel Sambuc
21*433d6423SLionel Sambuc volatile int remaining_invocations = 2, handler_level = 0;
22*433d6423SLionel Sambuc
23*433d6423SLionel Sambuc void check_context_loop(void);
24*433d6423SLionel Sambuc
25*433d6423SLionel Sambuc #define REGS 8 /* how many registers pusha and popa save. */
26*433d6423SLionel Sambuc
27*433d6423SLionel Sambuc #define ESP 3 /* where is esp saved? */
28*433d6423SLionel Sambuc
29*433d6423SLionel Sambuc unsigned long newstate[REGS], origstate[REGS];
30*433d6423SLionel Sambuc
handler(int signal)31*433d6423SLionel Sambuc static void handler(int signal)
32*433d6423SLionel Sambuc {
33*433d6423SLionel Sambuc int st;
34*433d6423SLionel Sambuc sigset_t set, oset;
35*433d6423SLionel Sambuc handler_level++;
36*433d6423SLionel Sambuc remaining_invocations--;
37*433d6423SLionel Sambuc if(remaining_invocations < 1)
38*433d6423SLionel Sambuc return;
39*433d6423SLionel Sambuc sigemptyset(&set);
40*433d6423SLionel Sambuc sigaddset(&set, SIGNAL);
41*433d6423SLionel Sambuc sigprocmask(SIG_UNBLOCK, &set, &oset);
42*433d6423SLionel Sambuc wait(&st);
43*433d6423SLionel Sambuc handler_level--;
44*433d6423SLionel Sambuc }
45*433d6423SLionel Sambuc
main(int argc,char * argv[])46*433d6423SLionel Sambuc int main(int argc, char *argv[])
47*433d6423SLionel Sambuc {
48*433d6423SLionel Sambuc pid_t child_pid;
49*433d6423SLionel Sambuc
50*433d6423SLionel Sambuc printf("Test 57 ");
51*433d6423SLionel Sambuc
52*433d6423SLionel Sambuc if(signal(SIGNAL, handler) == SIG_ERR)
53*433d6423SLionel Sambuc err(1, "signal");
54*433d6423SLionel Sambuc
55*433d6423SLionel Sambuc fflush(NULL);
56*433d6423SLionel Sambuc
57*433d6423SLionel Sambuc if((child_pid=fork()) < 0)
58*433d6423SLionel Sambuc err(1, "fork");
59*433d6423SLionel Sambuc
60*433d6423SLionel Sambuc if(child_pid == 0) {
61*433d6423SLionel Sambuc pid_t ppid = 0;
62*433d6423SLionel Sambuc
63*433d6423SLionel Sambuc /* Keep signaling the parent until
64*433d6423SLionel Sambuc * it disappears.
65*433d6423SLionel Sambuc */
66*433d6423SLionel Sambuc while((ppid = getppid()) > 1) {
67*433d6423SLionel Sambuc if(kill(ppid, SIGNAL) < 0)
68*433d6423SLionel Sambuc err(1, "kill");
69*433d6423SLionel Sambuc sleep(1);
70*433d6423SLionel Sambuc }
71*433d6423SLionel Sambuc
72*433d6423SLionel Sambuc exit(0);
73*433d6423SLionel Sambuc } else {
74*433d6423SLionel Sambuc int i;
75*433d6423SLionel Sambuc int err = 0;
76*433d6423SLionel Sambuc
77*433d6423SLionel Sambuc check_context_loop();
78*433d6423SLionel Sambuc
79*433d6423SLionel Sambuc /* correct 2nd esp for 'pusha' difference. */
80*433d6423SLionel Sambuc newstate[ESP] += REGS*4;
81*433d6423SLionel Sambuc
82*433d6423SLionel Sambuc for(i = 0; i < REGS; i++) {
83*433d6423SLionel Sambuc #if 0
84*433d6423SLionel Sambuc printf("%d %08lx %08lx diff ",
85*433d6423SLionel Sambuc i, newstate[i], origstate[i]);
86*433d6423SLionel Sambuc #endif
87*433d6423SLionel Sambuc if(newstate[i] != origstate[i]) {
88*433d6423SLionel Sambuc fprintf(stderr, "reg %d changed; "
89*433d6423SLionel Sambuc "found 0x%lx, expected 0x%lx\n",
90*433d6423SLionel Sambuc i, newstate[i], origstate[i]);
91*433d6423SLionel Sambuc err = 1;
92*433d6423SLionel Sambuc }
93*433d6423SLionel Sambuc }
94*433d6423SLionel Sambuc
95*433d6423SLionel Sambuc if(!err) printf("ok\n");
96*433d6423SLionel Sambuc
97*433d6423SLionel Sambuc exit(err);
98*433d6423SLionel Sambuc }
99*433d6423SLionel Sambuc
100*433d6423SLionel Sambuc return 0;
101*433d6423SLionel Sambuc }
102*433d6423SLionel Sambuc
103