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)) \
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)
--- /dev/null
+/*
+ Check that a fault signal handler gets the expected info
+ */
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+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;
+}
--- /dev/null
+
+Test 1: PASS
+Test 2: PASS
+Test 3: PASS
+
--- /dev/null
+prog: faultstatus
(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;
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
};
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
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 \
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
--- /dev/null
+/*
+ Check that a fault signal handler gets the expected info
+ */
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+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;
+}
--- /dev/null
+
+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
+
--- /dev/null
+prog: faultstatus