test57: test that state isn't corrupted after a signal handler being executed.

This commit is contained in:
Ben Gras 2010-08-04 09:00:58 +00:00
parent b43f3b6bfc
commit 83fc90c8c3
4 changed files with 172 additions and 3 deletions

View 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

View File

@ -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`

102
test/test57.c Normal file
View File

@ -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;
}

65
test/test57loop.S Normal file
View File

@ -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