From: Tom Hughes Date: Wed, 2 Nov 2005 16:15:55 +0000 (+0000) Subject: Split faultstatus into the platform independent tests and those X-Git-Tag: svn/VALGRIND_3_1_0~240 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3d2decfed8a0d14db9d48b94025914da37a64299;p=thirdparty%2Fvalgrind.git Split faultstatus into the platform independent tests and those which are x86 specific. The first three x86 specific ones should work on amd64 as well so I have added those as amd64 tests. Note that the x86/amd64 tests will still fail as VEX doesn't always trigger the right sort of signal for faulting instructions at the moment. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4992 --- diff --git a/none/tests/amd64/Makefile.am b/none/tests/amd64/Makefile.am index 06d60dea4e..7d0ab7f16a 100644 --- a/none/tests/amd64/Makefile.am +++ b/none/tests/amd64/Makefile.am @@ -5,6 +5,7 @@ CLEANFILES = $(addsuffix .c,$(INSN_TESTS)) INSN_TESTS=insn_mmx insn_sse insn_sse2 insn_fpu EXTRA_DIST = $(noinst_SCRIPTS) \ + faultstatus.vgtest faultstatus.stderr.exp \ $(addsuffix .stderr.exp,$(INSN_TESTS)) \ $(addsuffix .stdout.exp,$(INSN_TESTS)) \ $(addsuffix .vgtest,$(INSN_TESTS)) \ @@ -13,7 +14,7 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ smc1.stderr.exp smc1.stdout.exp smc1.vgtest check_PROGRAMS = \ - $(INSN_TESTS) looper jrcxz smc1 + faultstatus $(INSN_TESTS) looper jrcxz smc1 AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -g -I$(top_srcdir)/include AM_CXXFLAGS = $(AM_CFLAGS) diff --git a/none/tests/amd64/faultstatus.c b/none/tests/amd64/faultstatus.c new file mode 100644 index 0000000000..6337cacf9f --- /dev/null +++ b/none/tests/amd64/faultstatus.c @@ -0,0 +1,143 @@ +/* + Check that a fault signal handler gets the expected info + */ +#include +#include +#include +#include +#include +#include +#include + +struct test { + void (*test)(void); + int sig; + int code; + volatile void *addr; +}; + +static const struct test *cur_test; + +static int zero(); + +static jmp_buf escape; + +#define BADADDR ((int *)0x1234) + +#define FILESIZE (16*1024) +#define MAPSIZE (2*FILESIZE) + +static char volatile *volatile mapping; + +static int testsig(int sig, int want) +{ + if (sig != want) { + fprintf(stderr, " FAIL: expected signal %d, not %d\n", want, sig); + return 0; + } + return 1; +} + +static int testcode(int code, int want) +{ + if (code != want) { + fprintf(stderr, " FAIL: expected si_code==%d, not %d\n", want, code); + return 0; + } + return 1; +} + +static int testaddr(void *addr, volatile void *want) +{ + if (addr != want) { + fprintf(stderr, " FAIL: expected si_addr==%p, not %p\n", want, addr); + return 0; + } + return 1; + +} + +static void handler(int sig, siginfo_t *si, void *uc) +{ + int ok = 1; + + ok = ok && testsig(sig, cur_test->sig); + ok = ok && testcode(si->si_code, cur_test->code); + if (cur_test->addr) + ok = ok && testaddr(si->si_addr, cur_test->addr); + + if (ok) + fprintf(stderr, " PASS\n"); + + siglongjmp(escape, ok + 1); +} + + +extern char test1_ill; +static void test1() +{ + asm volatile("test1_ill: ud2"); +} + +static void test2() +{ + asm volatile ("int3"); +} + +static void test3() +{ + asm volatile ("int $0x10"); +} + +int main() +{ + int fd, i; + static const int sigs[] = { SIGSEGV, SIGILL, SIGBUS, SIGFPE, SIGTRAP }; + struct sigaction sa; + + sa.sa_sigaction = handler; + sa.sa_flags = SA_SIGINFO; + sigfillset(&sa.sa_mask); + + for(i = 0; i < sizeof(sigs)/sizeof(*sigs); i++) + sigaction(sigs[i], &sa, NULL); + + fd = open("faultstatus.tmp", O_CREAT|O_TRUNC|O_EXCL, 0600); + if (fd == -1) { + perror("tmpfile"); + exit(1); + } + unlink("faultstatus.tmp"); + ftruncate(fd, FILESIZE); + + mapping = mmap(0, MAPSIZE, PROT_READ, MAP_PRIVATE, fd, 0); + close(fd); + + { + const struct test tests[] = { +#define T(n, sig, code, addr) { test##n, sig, code, addr } + T(1, SIGILL, ILL_ILLOPN, &test1_ill), + + T(2, SIGTRAP, 128, 0), /* TRAP_BRKPT? */ + T(3, SIGSEGV, 128, 0), +#undef T + }; + + for(i = 0; i < sizeof(tests)/sizeof(*tests); i++) { + cur_test = &tests[i]; + + if (sigsetjmp(escape, 1) == 0) { + fprintf(stderr, "Test %d: ", i+1); + tests[i].test(); + fprintf(stderr, " FAIL: no fault, or handler returned\n"); + } + } + } + + return 0; +} + +static int zero() +{ + return 0; +} diff --git a/none/tests/amd64/faultstatus.stderr.exp b/none/tests/amd64/faultstatus.stderr.exp new file mode 100644 index 0000000000..b91b047b95 --- /dev/null +++ b/none/tests/amd64/faultstatus.stderr.exp @@ -0,0 +1,5 @@ + +Test 1: PASS +Test 2: PASS +Test 3: PASS + diff --git a/none/tests/amd64/faultstatus.vgtest b/none/tests/amd64/faultstatus.vgtest new file mode 100644 index 0000000000..d388f29c09 --- /dev/null +++ b/none/tests/amd64/faultstatus.vgtest @@ -0,0 +1 @@ +prog: faultstatus diff --git a/none/tests/faultstatus.c b/none/tests/faultstatus.c index 906120aa81..97d1f3741c 100644 --- a/none/tests/faultstatus.c +++ b/none/tests/faultstatus.c @@ -95,39 +95,6 @@ static void test4() (void)v; } -#ifdef __i386__ -extern char test5_ill; -static void test5() -{ - asm volatile("test5_ill: ud2"); -} - -static void test6() -{ - asm volatile ("int3"); -} - -static void test7() -{ - asm volatile ("int $0x10"); -} - -static void test8() -{ - volatile int a; - asm volatile ("add $1, %0;"/* set OF */ - "into" - : "=a" (a) : "0" (0x7fffffff) : "cc"); -} - -static void test9() -{ - static int limit[2] = { 0, 10 }; - - asm volatile ("bound %0, %1" : : "r" (11), "m" (limit[0])); -} -#endif /* __i386__ */ - int main() { int fd, i; @@ -159,18 +126,6 @@ int main() T(2, SIGSEGV, SEGV_ACCERR, mapping), T(3, SIGBUS, BUS_ADRERR, &mapping[FILESIZE+10]), T(4, SIGFPE, FPE_INTDIV, 0), -#ifdef __i386__ - T(5, SIGILL, ILL_ILLOPN, &test5_ill), - - T(6, SIGTRAP, 128, 0), /* TRAP_BRKPT? */ - T(7, SIGSEGV, 128, 0), - T(8, SIGSEGV, 128, 0), - - /* This is an expected failure - Valgrind - doesn't implement the BOUND instruction, - and so issues a SIGILL instead. */ - T(9, SIGSEGV, 128, 0), -#endif /* __i386__ */ #undef T }; diff --git a/none/tests/faultstatus.stderr.exp b/none/tests/faultstatus.stderr.exp index b214bde17f..af5744bfbe 100644 --- a/none/tests/faultstatus.stderr.exp +++ b/none/tests/faultstatus.stderr.exp @@ -3,11 +3,4 @@ Test 1: PASS Test 2: PASS Test 3: PASS Test 4: PASS -Test 5: PASS -Test 6: PASS -Test 7: PASS -Test 8: PASS -Test 9: disInstr: unhandled instruction bytes: 0x........ 0x........ 0x........ 0x........ - at 0x........: test9 (faultstatus.c:127) - FAIL: expected signal 11, not 4 diff --git a/none/tests/x86/Makefile.am b/none/tests/x86/Makefile.am index a8c9e7ec25..1af97badbf 100644 --- a/none/tests/x86/Makefile.am +++ b/none/tests/x86/Makefile.am @@ -9,6 +9,7 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ bt_literal.stderr.exp bt_literal.stdout.exp bt_literal.vgtest \ cpuid.stderr.exp cpuid.stdout.exp cpuid.vgtest \ cmpxchg8b.stderr.exp cmpxchg8b.stdout.exp cmpxchg8b.vgtest \ + faultstatus.vgtest faultstatus.stderr.exp \ fpu_lazy_eflags.stderr.exp fpu_lazy_eflags.stdout.exp \ fpu_lazy_eflags.vgtest \ fxtract.stdout.exp fxtract.stderr.exp fxtract.vgtest \ @@ -28,8 +29,8 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ yield.stderr.exp yield.stdout.exp yield.vgtest check_PROGRAMS = \ - badseg bt_everything bt_literal cmpxchg8b cpuid fpu_lazy_eflags \ - fxtract \ + badseg bt_everything bt_literal cmpxchg8b cpuid \ + faultstatus fpu_lazy_eflags fxtract \ getseg incdec_alt $(INSN_TESTS) \ lahf looper int pushpopseg sbbmisc \ seg_override sigcontext smc1 yield diff --git a/none/tests/x86/faultstatus.c b/none/tests/x86/faultstatus.c new file mode 100644 index 0000000000..5d39753f96 --- /dev/null +++ b/none/tests/x86/faultstatus.c @@ -0,0 +1,164 @@ +/* + Check that a fault signal handler gets the expected info + */ +#include +#include +#include +#include +#include +#include +#include + +struct test { + void (*test)(void); + int sig; + int code; + volatile void *addr; +}; + +static const struct test *cur_test; + +static int zero(); + +static jmp_buf escape; + +#define BADADDR ((int *)0x1234) + +#define FILESIZE (16*1024) +#define MAPSIZE (2*FILESIZE) + +static char volatile *volatile mapping; + +static int testsig(int sig, int want) +{ + if (sig != want) { + fprintf(stderr, " FAIL: expected signal %d, not %d\n", want, sig); + return 0; + } + return 1; +} + +static int testcode(int code, int want) +{ + if (code != want) { + fprintf(stderr, " FAIL: expected si_code==%d, not %d\n", want, code); + return 0; + } + return 1; +} + +static int testaddr(void *addr, volatile void *want) +{ + if (addr != want) { + fprintf(stderr, " FAIL: expected si_addr==%p, not %p\n", want, addr); + return 0; + } + return 1; + +} + +static void handler(int sig, siginfo_t *si, void *uc) +{ + int ok = 1; + + ok = ok && testsig(sig, cur_test->sig); + ok = ok && testcode(si->si_code, cur_test->code); + if (cur_test->addr) + ok = ok && testaddr(si->si_addr, cur_test->addr); + + if (ok) + fprintf(stderr, " PASS\n"); + + siglongjmp(escape, ok + 1); +} + + +extern char test1_ill; +static void test1() +{ + asm volatile("test1_ill: ud2"); +} + +static void test2() +{ + asm volatile ("int3"); +} + +static void test3() +{ + asm volatile ("int $0x10"); +} + +static void test4() +{ + volatile int a; + asm volatile ("add $1, %0;"/* set OF */ + "into" + : "=a" (a) : "0" (0x7fffffff) : "cc"); +} + +static void test5() +{ + static int limit[2] = { 0, 10 }; + + asm volatile ("bound %0, %1" : : "r" (11), "m" (limit[0])); +} + +int main() +{ + int fd, i; + static const int sigs[] = { SIGSEGV, SIGILL, SIGBUS, SIGFPE, SIGTRAP }; + struct sigaction sa; + + sa.sa_sigaction = handler; + sa.sa_flags = SA_SIGINFO; + sigfillset(&sa.sa_mask); + + for(i = 0; i < sizeof(sigs)/sizeof(*sigs); i++) + sigaction(sigs[i], &sa, NULL); + + fd = open("faultstatus.tmp", O_CREAT|O_TRUNC|O_EXCL, 0600); + if (fd == -1) { + perror("tmpfile"); + exit(1); + } + unlink("faultstatus.tmp"); + ftruncate(fd, FILESIZE); + + mapping = mmap(0, MAPSIZE, PROT_READ, MAP_PRIVATE, fd, 0); + close(fd); + + { + const struct test tests[] = { +#define T(n, sig, code, addr) { test##n, sig, code, addr } + T(1, SIGILL, ILL_ILLOPN, &test1_ill), + + T(2, SIGTRAP, 128, 0), /* TRAP_BRKPT? */ + T(3, SIGSEGV, 128, 0), + T(4, SIGSEGV, 128, 0), + + /* This is an expected failure - Valgrind + doesn't implement the BOUND instruction, + and so issues a SIGILL instead. */ + T(5, SIGSEGV, 128, 0), +#undef T + }; + + for(i = 0; i < sizeof(tests)/sizeof(*tests); i++) { + cur_test = &tests[i]; + + if (sigsetjmp(escape, 1) == 0) { + fprintf(stderr, "Test %d: ", i+1); + tests[i].test(); + fprintf(stderr, " FAIL: no fault, or handler returned\n"); + } + } + } + + return 0; +} + +static int zero() +{ + return 0; +} diff --git a/none/tests/x86/faultstatus.stderr.exp b/none/tests/x86/faultstatus.stderr.exp new file mode 100644 index 0000000000..bf574c88a6 --- /dev/null +++ b/none/tests/x86/faultstatus.stderr.exp @@ -0,0 +1,9 @@ + +Test 1: PASS +Test 2: PASS +Test 3: PASS +Test 4: PASS +Test 5: disInstr: unhandled instruction bytes: 0x........ 0x........ 0x........ 0x........ + at 0x........: test9 (faultstatus.c:127) + FAIL: expected signal 11, not 4 + diff --git a/none/tests/x86/faultstatus.vgtest b/none/tests/x86/faultstatus.vgtest new file mode 100644 index 0000000000..d388f29c09 --- /dev/null +++ b/none/tests/x86/faultstatus.vgtest @@ -0,0 +1 @@ +prog: faultstatus