test57: test that state isn't corrupted after a signal handler being executed.
This commit is contained in:
parent
b43f3b6bfc
commit
83fc90c8c3
@ -12,14 +12,14 @@ OBJ= test1 test2 test3 test4 test5 test6 test7 test8 test9 \
|
|||||||
test30 test31 test32 test34 test35 test36 test37 test38 \
|
test30 test31 test32 test34 test35 test36 test37 test38 \
|
||||||
test39 t10a t11a t11b test40 t40a t40b t40c t40d t40e t40f test41 \
|
test39 t10a t11a t11b test40 t40a t40b t40c t40d t40e t40f test41 \
|
||||||
test42 test45 test47 test48 test49 test50 test51 test52 test53 \
|
test42 test45 test47 test48 test49 test50 test51 test52 test53 \
|
||||||
test54 test55 test56
|
test54 test55 test56
|
||||||
|
|
||||||
BIGOBJ= test20 test24
|
BIGOBJ= test20 test24
|
||||||
ROOTOBJ= test11 test33 test43 test44 test46
|
ROOTOBJ= test11 test33 test43 test44 test46
|
||||||
GCCOBJ= test45-gcc test49-gcc
|
GCCOBJ= test45-gcc test49-gcc
|
||||||
GCCFPUOBJ= test51-gcc test52-gcc
|
GCCFPUOBJ= test51-gcc test52-gcc
|
||||||
|
|
||||||
all: $(OBJ) $(BIGOBJ) $(GCCOBJ) $(GCCFPUOBJ) $(ROOTOBJ)
|
all: $(OBJ) $(BIGOBJ) $(GCCOBJ) $(GCCFPUOBJ) $(ROOTOBJ) test57
|
||||||
chmod 755 *.sh run
|
chmod 755 *.sh run
|
||||||
|
|
||||||
$(OBJ):
|
$(OBJ):
|
||||||
@ -112,3 +112,5 @@ test52-gcc: test52.c
|
|||||||
test54: test54.c
|
test54: test54.c
|
||||||
test55: test55.c
|
test55: test55.c
|
||||||
test56: test56.c
|
test56: test56.c
|
||||||
|
test57: test57.c test57loop.S
|
||||||
|
which $(GCC) >/dev/null && $(GCC) $(CFLAGS-GCC) -o $@ test57.c test57loop.S
|
||||||
|
2
test/run
2
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 \
|
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 \
|
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 \
|
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"
|
sh1.sh sh2.sh"
|
||||||
tests_no=`expr 0`
|
tests_no=`expr 0`
|
||||||
|
|
||||||
|
102
test/test57.c
Normal file
102
test/test57.c
Normal 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
65
test/test57loop.S
Normal 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
|
Loading…
x
Reference in New Issue
Block a user