]> Zhao Yanbai Git Server - minix.git/commitdiff
test57: test that state isn't corrupted after a signal handler being executed.
authorBen Gras <ben@minix3.org>
Wed, 4 Aug 2010 09:00:58 +0000 (09:00 +0000)
committerBen Gras <ben@minix3.org>
Wed, 4 Aug 2010 09:00:58 +0000 (09:00 +0000)
test/Makefile
test/run
test/test57.c [new file with mode: 0644]
test/test57loop.S [new file with mode: 0644]

index c76c30dfe529d549e8de97350dc31da7c1a3dcc5..f75f6e4c972cb1b49a37618563c9de888d8d45bb 100644 (file)
@@ -12,14 +12,14 @@ OBJ=        test1  test2  test3  test4  test5  test6  test7  test8  test9  \
        test30 test31 test32        test34 test35 test36 test37 test38 \
        test39 t10a t11a t11b test40 t40a t40b t40c t40d t40e t40f test41 \
        test42 test45 test47 test48 test49 test50 test51 test52 test53 \
-       test54 test55 test56
+       test54 test55 test56 
 
 BIGOBJ=  test20 test24
 ROOTOBJ= test11 test33 test43 test44 test46
 GCCOBJ=  test45-gcc test49-gcc 
 GCCFPUOBJ= test51-gcc test52-gcc
 
-all:   $(OBJ) $(BIGOBJ) $(GCCOBJ) $(GCCFPUOBJ) $(ROOTOBJ)
+all:   $(OBJ) $(BIGOBJ) $(GCCOBJ) $(GCCFPUOBJ) $(ROOTOBJ) test57
        chmod 755 *.sh run
 
 $(OBJ):
@@ -112,3 +112,5 @@ test52-gcc: test52.c
 test54: test54.c
 test55: test55.c
 test56: test56.c
+test57: test57.c test57loop.S
+       which $(GCC) >/dev/null && $(GCC) $(CFLAGS-GCC) -o $@ test57.c test57loop.S
index f272806a512d79a01843882711813c24e3c739fa..4f69c74cee77495befded9410d663f8d0dca3678 100755 (executable)
--- a/test/run
+++ b/test/run
@@ -14,7 +14,7 @@ badones=                      # list of tests that failed
 tests="   1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 \
          21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
          41 42 43 44 45 45-gcc 46 47 48 49 49-gcc 50 \
-         51 51-gcc 52 52-gcc 53 54 55 \
+         51 51-gcc 52 52-gcc 53 54 55 57 \
         sh1.sh sh2.sh"
 tests_no=`expr 0`
 
diff --git a/test/test57.c b/test/test57.c
new file mode 100644 (file)
index 0000000..873e087
--- /dev/null
@@ -0,0 +1,102 @@
+
+/* This test tests whether registers are correctly restored after a
+ * signal handler is executed. The assembly file (test57loop.S) puts
+ * 'random' values in the registers, and the C code checks whether
+ * these values are the same, before and after the signal handler.
+ */
+
+#define _POSIX_SOURCE 1
+
+#include <stdio.h>
+#include <signal.h>
+#include <err.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#define SIGNAL SIGUSR1
+
+volatile int remaining_invocations = 2, handler_level = 0;
+
+void check_context_loop(void);
+
+#define REGS 8 /* how many registers pusha and popa save. */
+
+#define ESP 3  /* where is esp saved? */
+
+unsigned long newstate[REGS], origstate[REGS];
+
+void handler(int signal)
+{
+       int st;
+       sigset_t set, oset;
+       handler_level++;
+       remaining_invocations--;
+       if(remaining_invocations < 1)
+               return;
+       sigemptyset(&set);
+       sigaddset(&set, SIGNAL);
+       sigprocmask(SIG_UNBLOCK, &set,  &oset);
+       wait(&st);
+       handler_level--;
+}
+
+int main(int argc, char *argv[])
+{
+       pid_t child_pid;
+
+       printf("Test 57 ");
+
+       if(signal(SIGNAL, handler) == SIG_ERR)
+               err(1, "signal");
+
+       fflush(NULL);
+
+       if((child_pid=fork()) < 0)
+               err(1, "fork");
+
+       if(child_pid == 0) {
+               pid_t ppid = 0;
+
+               /* Keep signaling the parent until
+                * it disappears.
+                */
+               while((ppid = getppid()) > 1) {
+                       if(kill(ppid, SIGNAL) < 0)
+                               err(1, "kill");
+                       sleep(1);
+               }
+
+               exit(0);
+       } else {
+               int i;
+               int err = 0;
+
+               check_context_loop();
+
+               /* correct 2nd esp for 'pusha' difference. */
+               newstate[ESP] += REGS*4;
+
+               for(i = 0; i < REGS; i++) {
+#if 0
+                       printf("%d %08lx %08lx diff  ",
+                               i, newstate[i], origstate[i]);
+#endif
+                       if(newstate[i] != origstate[i]) {
+                               fprintf(stderr, "reg %d changed; "
+                                       "found 0x%lx, expected 0x%lx\n",
+                                       i, newstate[i], origstate[i]);
+                               err = 1;
+                       }
+               }
+
+               if(!err) printf(" ok\n");
+
+               exit(err);
+       }
+
+       return 0;
+}
+
diff --git a/test/test57loop.S b/test/test57loop.S
new file mode 100644 (file)
index 0000000..1065ff6
--- /dev/null
@@ -0,0 +1,65 @@
+
+.globl _check_context_loop
+.globl _remaining_invocations
+.globl _origstate
+.globl _newstate
+
+#define JUNK 0xCC0FFEE0
+
+#define COPY(dest, offset)     \
+       mov     $dest, %ebp             ;       \
+       mov     4*offset(%esp), %ebx    ;       \
+       mov     %ebx, 4*offset(%ebp) ;
+
+/* Copy the result of a pusha to dest. */
+#define COPYA(dest) \
+       COPY(dest, 0); COPY(dest, 1); COPY(dest, 2); COPY(dest, 3); \
+       COPY(dest, 4); COPY(dest, 5); COPY(dest, 6); COPY(dest, 7); 
+
+.text
+/* void check_context_loop() */
+_check_context_loop:
+       /* Save original context so we can restore it. */
+       pusha
+
+       /* Put some junk in the registers.
+        * We want to junk the state, and junk it differently per reg,
+        * so it's likelier corruption is actually detected. We can't
+        * touch %esp but we can verify that it doesn't change from its
+        * current value.
+        */
+       mov     $JUNK+1, %eax
+       mov     $JUNK+2, %ebx
+       mov     $JUNK+3, %ecx
+       mov     $JUNK+4, %edx
+       mov     $JUNK+5, %ebp
+       mov     $JUNK+6, %esi
+       mov     $JUNK+7, %edi
+
+       /* Save the junked state so we can compare it. */
+       pusha
+cont:
+       /* Check if we're done. */
+       cmpl    $0, (_remaining_invocations)
+       jz      done
+
+       /* We're not done. */
+
+       /* Restart loop. */
+       jmp     cont
+
+done:
+       /* Save the junked, but should be unmodified state
+        * so we can copy it.
+        */
+       pusha
+       COPYA(_newstate);
+       popa
+
+       /* copy and restore junked state */
+       COPYA(_origstate);
+       popa
+
+       /* restore original state and return */
+       popa
+       ret