|
From: <sv...@va...> - 2012-10-19 14:45:46
|
petarj 2012-10-19 15:45:17 +0100 (Fri, 19 Oct 2012)
New Revision: 13059
Log:
Add a proper support for several MIPS instructions that generate SigFPE.
Add support to properly handle TEQ, ADD and SUB instructions that generate
exceptions on MIPS platforms. A SignalException test for MIPS32 has also been
added, so we can cover more cases.
This resolves:
none/tests/faultstatus
gdbserver_tests/mcsignopass
gdbserver_tests/mcsigpass
Added files:
trunk/none/tests/mips32/SignalException.c
trunk/none/tests/mips32/SignalException.stderr.exp
trunk/none/tests/mips32/SignalException.vgtest
Modified files:
trunk/coregrind/m_scheduler/scheduler.c
trunk/coregrind/m_signals.c
trunk/coregrind/pub_core_signals.h
trunk/none/tests/mips32/Makefile.am
Modified: trunk/coregrind/pub_core_signals.h (+1 -0)
===================================================================
--- trunk/coregrind/pub_core_signals.h 2012-10-19 04:20:37 +01:00 (rev 13058)
+++ trunk/coregrind/pub_core_signals.h 2012-10-19 15:45:17 +01:00 (rev 13059)
@@ -77,6 +77,7 @@
extern void VG_(synth_sigill) (ThreadId tid, Addr addr);
extern void VG_(synth_sigtrap) (ThreadId tid);
extern void VG_(synth_sigbus) (ThreadId tid);
+extern void VG_(synth_sigfpe) (ThreadId tid, UInt code);
/* Extend the stack to cover addr, if possible */
extern Bool VG_(extend_stack)(Addr addr, UInt maxsize);
Modified: trunk/coregrind/m_signals.c (+26 -21)
===================================================================
--- trunk/coregrind/m_signals.c 2012-10-19 04:20:37 +01:00 (rev 13058)
+++ trunk/coregrind/m_signals.c 2012-10-19 15:45:17 +01:00 (rev 13059)
@@ -1919,27 +1919,6 @@
info.si_signo = VKI_SIGTRAP;
info.si_code = VKI_TRAP_BRKPT; /* tjh: only ever called for a brkpt ins */
-# if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
- /* This is for teq on mips. Teq on mips for ins: 0xXXX1f4
- * cases VKI_SIGFPE not VKI_SIGTRAP
- */
- // JRS 2012-Jun-06: commented out until we know we need it
- // This isn't a clean solution; need something that avoids looking
- // at the guest code.
- //UInt *ins = (void*)(vgPlain_threads[tid].arch.vex.guest_PC-4);
- //UInt tcode = (((*ins) >> 6) & ((1 << 10) - 1));
- //if (tcode == VKI_BRK_OVERFLOW || tcode == VKI_BRK_DIVZERO) {
- // if (tcode == VKI_BRK_DIVZERO)
- // info.si_code = VKI_FPE_INTDIV;
- // else
- // info.si_code = VKI_FPE_INTOVF;
- // info.si_signo = VKI_SIGFPE;
- // info.si_errno = 0;
- // info.VKI_SIGINFO_si_addr
- // = (void*)(vgPlain_threads[tid].arch.vex.guest_PC-4);
- //}
-# endif
-
# if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
uc.uc_mcontext.trapno = 3; /* tjh: this is the x86 trap number
for a breakpoint trap... */
@@ -1962,6 +1941,32 @@
resume_scheduler(tid);
}
+// Synthesise a SIGFPE.
+void VG_(synth_sigfpe)(ThreadId tid, UInt code)
+{
+// Only tested on mips32
+#if !defined(VGA_mips32)
+ vg_assert(0);
+#else
+ vki_siginfo_t info;
+ struct vki_ucontext uc;
+
+ vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
+
+ VG_(memset)(&info, 0, sizeof(info));
+ VG_(memset)(&uc, 0, sizeof(uc));
+ info.si_signo = VKI_SIGFPE;
+ info.si_code = code;
+
+ if (VG_(gdbserver_report_signal) (VKI_SIGFPE, tid)) {
+ resume_scheduler(tid);
+ deliver_signal(tid, &info, &uc);
+ }
+ else
+ resume_scheduler(tid);
+#endif
+}
+
/* Make a signal pending for a thread, for later delivery.
VG_(poll_signals) will arrange for it to be delivered at the right
time.
Added: trunk/none/tests/mips32/SignalException.stderr.exp (+3 -0)
===================================================================
--- trunk/none/tests/mips32/SignalException.stderr.exp 2012-10-19 04:20:37 +01:00 (rev 13058)
+++ trunk/none/tests/mips32/SignalException.stderr.exp 2012-10-19 15:45:17 +01:00 (rev 13059)
@@ -0,0 +1,3 @@
+Test 1: PASS
+Test 2: PASS
+Test 3: PASS
Added: trunk/none/tests/mips32/SignalException.vgtest (+2 -0)
===================================================================
--- trunk/none/tests/mips32/SignalException.vgtest 2012-10-19 04:20:37 +01:00 (rev 13058)
+++ trunk/none/tests/mips32/SignalException.vgtest 2012-10-19 15:45:17 +01:00 (rev 13059)
@@ -0,0 +1,2 @@
+prog: SignalException
+vgopts: -q
Modified: trunk/none/tests/mips32/Makefile.am (+6 -4)
===================================================================
--- trunk/none/tests/mips32/Makefile.am 2012-10-19 04:20:37 +01:00 (rev 13058)
+++ trunk/none/tests/mips32/Makefile.am 2012-10-19 15:45:17 +01:00 (rev 13059)
@@ -6,18 +6,19 @@
EXTRA_DIST = \
branches.stdout.exp branches.stderr.exp branches.vgtest \
FPUarithmetic.stdout.exp FPUarithmetic.stdout.exp-mips32 \
- FPUarithmetic.stderr.exp FPUarithmetic.vgtest \
+ FPUarithmetic.stderr.exp FPUarithmetic.vgtest \
LoadStore.stdout.exp LoadStore.stdout.exp-BE LoadStore.stderr.exp \
LoadStore.vgtest \
LoadStore1.stdout.exp LoadStore1.stdout.exp-LE LoadStore1.stderr.exp \
LoadStore1.vgtest \
MemCpyTest.stdout.exp MemCpyTest.stderr.exp MemCpyTest.vgtest \
MIPS32int.stdout.exp MIPS32int.stdout.exp-BE MIPS32int.stdout.exp-mips32 \
- MIPS32int.stderr.exp MIPS32int.vgtest \
+ MIPS32int.stderr.exp MIPS32int.vgtest \
MoveIns.stdout.exp MoveIns.stdout.exp-BE MoveIns.stderr.exp MoveIns.vgtest \
round.stdout.exp round.stderr.exp round.vgtest \
vfp.stdout.exp vfp.stdout.exp-BE vfp.stdout.exp-mips32 vfp.stderr.exp \
- vfp.vgtest
+ vfp.vgtest \
+ SignalException.stderr.exp SignalException.vgtest
check_PROGRAMS = \
allexec \
@@ -29,7 +30,8 @@
MIPS32int \
MoveIns \
round \
- vfp
+ vfp \
+ SignalException
AM_CFLAGS += @FLAG_M32@
AM_CXXFLAGS += @FLAG_M32@
Modified: trunk/coregrind/m_scheduler/scheduler.c (+10 -0)
===================================================================
--- trunk/coregrind/m_scheduler/scheduler.c 2012-10-19 04:20:37 +01:00 (rev 13058)
+++ trunk/coregrind/m_scheduler/scheduler.c 2012-10-19 15:45:17 +01:00 (rev 13059)
@@ -201,6 +201,8 @@
case VEX_TRC_JMP_SIGTRAP: return "SIGTRAP";
case VEX_TRC_JMP_SIGSEGV: return "SIGSEGV";
case VEX_TRC_JMP_SIGBUS: return "SIGBUS";
+ case VEX_TRC_JMP_SIGFPE_INTOVF:
+ case VEX_TRC_JMP_SIGFPE_INTDIV: return "SIGFPE";
case VEX_TRC_JMP_EMWARN: return "EMWARN";
case VEX_TRC_JMP_EMFAIL: return "EMFAIL";
case VEX_TRC_JMP_CLIENTREQ: return "CLIENTREQ";
@@ -1425,6 +1427,14 @@
VG_(synth_sigbus)(tid);
break;
+ case VEX_TRC_JMP_SIGFPE_INTDIV:
+ VG_(synth_sigfpe)(tid, VKI_FPE_INTDIV);
+ break;
+
+ case VEX_TRC_JMP_SIGFPE_INTOVF:
+ VG_(synth_sigfpe)(tid, VKI_FPE_INTOVF);
+ break;
+
case VEX_TRC_JMP_NODECODE: {
Addr addr = VG_(get_IP)(tid);
Added: trunk/none/tests/mips32/SignalException.c (+104 -0)
===================================================================
--- trunk/none/tests/mips32/SignalException.c 2012-10-19 04:20:37 +01:00 (rev 13058)
+++ trunk/none/tests/mips32/SignalException.c 2012-10-19 15:45:17 +01:00 (rev 13059)
@@ -0,0 +1,104 @@
+/*
+ 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 <unistd.h>
+
+struct test {
+ void (*test)(void);
+ int sig;
+ int code;
+};
+
+static const struct test *curr_test;
+
+static jmp_buf escape;
+
+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 void handler(int sig, siginfo_t *si, void *uc)
+{
+ int ok = 1;
+
+ ok = ok && testsig(sig, curr_test->sig);
+ ok = ok && testcode(si->si_code, curr_test->code);
+
+ if (ok)
+ fprintf(stderr, " PASS\n");
+
+ siglongjmp(escape, ok + 1);
+}
+
+static void test1(void)
+{
+ __asm__ volatile("li $t0, 0x80000000\n\t"
+ "move $t1, $t0\n\t"
+ "add $a0, $t0, $t1\n\t"
+ : : : "t0", "t1", "a0", "cc", "memory");
+}
+
+static void test2()
+{
+ __asm__ volatile("li $t0, 0x7fffffff\n\t"
+ "addi $a0, $t0, 0x7fff\n\t"
+ : : : "t0", "a0", "cc", "memory");
+}
+
+static void test3(void)
+{
+ __asm__ volatile("li $t0, 0xffff0000\n\t"
+ "li $t1, 0x7fffffff\n\t"
+ "sub $a0, $t0, $t1\n\t"
+ : : : "t0", "t1", "a0", "cc", "memory");
+}
+
+int main()
+{
+ int i;
+ static const int sigs[] = { SIGFPE };
+ 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);
+
+ const struct test tests[] = {
+#define T(n, sig, code) { test##n, sig, code }
+ T(1, SIGFPE, FPE_INTOVF),
+ T(2, SIGFPE, FPE_INTOVF),
+ T(3, SIGFPE, FPE_INTOVF),
+#undef T
+ };
+
+ for(i = 0; i < sizeof(tests)/sizeof(*tests); i++) {
+ curr_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;
+}
|