From 83fc90c8c3456bbbcbdd9c7a9773767aa2f997e9 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Wed, 4 Aug 2010 09:00:58 +0000 Subject: [PATCH] test57: test that state isn't corrupted after a signal handler being executed. --- test/Makefile | 6 ++- test/run | 2 +- test/test57.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++ test/test57loop.S | 65 +++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 test/test57.c create mode 100644 test/test57loop.S diff --git a/test/Makefile b/test/Makefile index c76c30dfe..f75f6e4c9 100644 --- a/test/Makefile +++ b/test/Makefile @@ -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 diff --git a/test/run b/test/run index f272806a5..4f69c74ce 100755 --- 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 index 000000000..873e08774 --- /dev/null +++ b/test/test57.c @@ -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 +#include +#include +#include +#include + +#include +#include + +#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 index 000000000..1065ff67c --- /dev/null +++ b/test/test57loop.S @@ -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 -- 2.44.0