about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/dynarec/arm64/dynarec_arm64_00.c18
-rw-r--r--src/dynarec/dynarec_native_functions.c2
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_3.c14
-rw-r--r--src/emu/x64int3.c7
-rw-r--r--src/emu/x64run.c13
-rw-r--r--src/libtools/signals.c9
-rw-r--r--tests/ref21.txt4
-rwxr-xr-xtests/test21bin19088 -> 23696 bytes
-rw-r--r--tests/test21.c72
9 files changed, 121 insertions, 18 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c
index 5a638072..0ad91284 100644
--- a/src/dynarec/arm64/dynarec_arm64_00.c
+++ b/src/dynarec/arm64/dynarec_arm64_00.c
@@ -2385,7 +2385,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     //LDRx_U12(x3, x1, offsetof(box64context_t, signals[SIGTRAP]));
                     CMPSx_U12(x3, 0);
                     B_NEXT(cEQ);
-                    GETIP(ip);
+                    GETIP(addr);  // update RIP
                     STORE_XEMU_CALL(xRIP);
                     CALL(native_int3, -1);
                     LOAD_XEMU_CALL(xRIP);
@@ -2401,7 +2401,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 INST_NAME("INT 29/2c/2d");
                 // lets do nothing
                 MESSAGE(LOG_INFO, "INT 29/2c/2d Windows interruption\n");
-                GETIP(ip);
+                GETIP(ip);  // priviledged instruction, IP not updated
                 STORE_XEMU_CALL(xRIP);
                 MOV32w(x1, u8);
                 CALL(native_int, -1);
@@ -2422,10 +2422,20 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 MARK;
                 LOAD_XEMU_REM();
                 jump_to_epilog(dyn, 0, xRIP, ninst);
+            } else if(u8==0x03) {
+                INST_NAME("INT 3");
+                SETFLAGS(X_ALL, SF_SET_NODF);    // Hack to set flags in "don't care" state
+                GETIP(addr);
+                STORE_XEMU_CALL(xRIP);
+                CALL(native_int3, -1);
+                LOAD_XEMU_CALL(xRIP);
+                jump_to_epilog(dyn, 0, xRIP, ninst);
+                *need_epilog = 0;
+                *ok = 0;
             } else {
                 INST_NAME("INT n");
                 SETFLAGS(X_ALL, SF_SET_NODF);    // Hack to set flags in "don't care" state
-                GETIP(ip);
+                GETIP(ip);  // priviledged instruction, IP not updated
                 STORE_XEMU_CALL(xRIP);
                 CALL(native_int, -1);
                 LOAD_XEMU_CALL(xRIP);
@@ -2440,7 +2450,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             } else {
                 INST_NAME("INTO");
                 READFLAGS(X_OF);
-                GETIP(ip);
+                GETIP(addr);
                 TBZ_NEXT(wFlags, F_OF);
                 STORE_XEMU_CALL(xRIP);
                 CALL(native_int, -1);
diff --git a/src/dynarec/dynarec_native_functions.c b/src/dynarec/dynarec_native_functions.c
index 6a118dfa..376541d1 100644
--- a/src/dynarec/dynarec_native_functions.c
+++ b/src/dynarec/dynarec_native_functions.c
@@ -188,7 +188,7 @@ void native_singlestep(x64emu_t* emu)
 
 void native_int3(x64emu_t* emu)
 {
-    emit_signal(emu, SIGTRAP, (void*)R_RIP, 128);
+    emit_signal(emu, SIGTRAP, NULL, 3);
 }
 
 void native_div0(x64emu_t* emu)
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c
index 790d00bb..43ef69d7 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_3.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_3.c
@@ -442,7 +442,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 INST_NAME("INT 29/2c/2d");
                 // lets do nothing
                 MESSAGE(LOG_INFO, "INT 29/2c/2d Windows interruption\n");
-                GETIP(ip);
+                GETIP(ip);  // priviledged instruction, IP not updated
                 STORE_XEMU_CALL(x3);
                 MOV32w(x1, u8);
                 CALL(native_int, -1);
@@ -462,10 +462,20 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 MARK;
                 LOAD_XEMU_REM(x3);
                 jump_to_epilog(dyn, 0, xRIP, ninst);
+            } else if (u8==0x03) {
+                INST_NAME("INT 3");
+                SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
+                GETIP(addr);
+                STORE_XEMU_CALL(x3);
+                CALL(native_int3, -1);
+                LOAD_XEMU_CALL();
+                jump_to_epilog(dyn, 0, xRIP, ninst);
+                *need_epilog = 0;
+                *ok = 0;
             } else {
                 INST_NAME("INT n");
                 SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
-                GETIP(ip);
+                GETIP(ip);  // priviledged instruction, IP not updated
                 STORE_XEMU_CALL(x3);
                 CALL(native_priv, -1);
                 LOAD_XEMU_CALL();
diff --git a/src/emu/x64int3.c b/src/emu/x64int3.c
index 3dd818ed..14493647 100644
--- a/src/emu/x64int3.c
+++ b/src/emu/x64int3.c
@@ -364,9 +364,10 @@ void x64Int3(x64emu_t* emu, uintptr_t* addr)
         }
         return;
     }
-    if(!box64_ignoreint3 && my_context->signals[SIGTRAP])
-        emit_signal(emu, SIGTRAP, (void*)R_RIP, 128);
-    else {
+    if(!box64_ignoreint3 && my_context->signals[SIGTRAP]) {
+        R_RIP = *addr;  // update RIP
+        emit_signal(emu, SIGTRAP, NULL, 3);
+    } else {
         printf_log(LOG_DEBUG, "%04d|Warning, ignoring unsupported Int 3 call @%p\n", GetTID(), (void*)R_RIP);
         R_RIP = *addr;
     }
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index fecb1311..614bf91c 100644
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -1488,6 +1488,7 @@ x64emurun:
             STEP2;
             break;
         case 0xCC:                      /* INT 3 */
+            R_RIP = addr;   // update RIP
             #ifndef TEST_INTERPRETER
             x64Int3(emu, &addr);
             if(emu->quit) goto fini;    // R_RIP is up to date when returning from x64Int3
@@ -1511,6 +1512,7 @@ x64emurun:
                 printf_log(LOG_DEBUG, "INT 29 called => __fastfail(0x%x)\n", R_ECX);
                 emit_interruption(emu, 0x29, (void*)R_RIP);
             } else if (tmp8u==0x80) {
+                R_RIP = addr;
                 // 32bits syscall
                 #ifndef TEST_INTERPRETER
                 x86Syscall(emu);
@@ -1518,9 +1520,17 @@ x64emurun:
                 #else
                 test->notest = 1;
                 #endif
+            } else if (tmp8u==0x03) {
+                R_RIP = addr;
+                #ifndef TEST_INTERPRETER
+                emit_signal(emu, SIGTRAP, NULL, 3);
+                STEP2;
+                #else
+                test->notest = 1;
+                #endif
             } else {
                 #ifndef TEST_INTERPRETER
-                emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
+                emit_interruption(emu, tmp8u, (void*)R_RIP);
                 STEP2;
                 #else
                 test->notest = 1;
@@ -1533,6 +1543,7 @@ x64emurun:
                 goto fini;
             }
             emu->old_ip = R_RIP;
+            R_RIP = addr;
             #ifndef TEST_INTERPRETER
             CHECK_FLAGS(emu);
             if(ACCESS_FLAG(F_OF))
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index 7d052c29..e58081c1 100644
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -1164,11 +1164,9 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void
                 info2->si_signo = SIGTRAP;
                 sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 3;
                 sigcontext->uc_mcontext.gregs[X64_ERR] = 0;
-                sigcontext->uc_mcontext.gregs[X64_RIP]+=2;   // segfault after the INT
             } else if(int_n==0x04) {
                 sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 4;
                 sigcontext->uc_mcontext.gregs[X64_ERR] = 0;
-                sigcontext->uc_mcontext.gregs[X64_RIP]+=2;   // segfault after the INT
             } else if (int_n==0x29 || int_n==0x2c || int_n==0x2d) {
                 sigcontext->uc_mcontext.gregs[X64_ERR] = 0x02|(int_n<<3);
             } else {
@@ -1186,10 +1184,13 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void
             sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 19;
     } else if(sig==SIGILL)
         sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 6;
-    else if(sig==SIGTRAP)
+    else if(sig==SIGTRAP) {
+        info2->si_code = 128;
         sigcontext->uc_mcontext.gregs[X64_TRAPNO] = info->si_code;
+        sigcontext->uc_mcontext.gregs[X64_ERR] = 0;
+    }
     //TODO: SIGABRT generate what?
-    printf_log(LOG_DEBUG, "Signal %d: TRAPNO=%d, ERR=%d, RIP=%p\n", sig, sigcontext->uc_mcontext.gregs[X64_TRAPNO], sigcontext->uc_mcontext.gregs[X64_ERR],sigcontext->uc_mcontext.gregs[X64_RIP]);
+    printf_log(LOG_DEBUG, "Signal %d: si_addr=%p, TRAPNO=%d, ERR=%d, RIP=%p\n", sig, (void*)info2->si_addr, sigcontext->uc_mcontext.gregs[X64_TRAPNO], sigcontext->uc_mcontext.gregs[X64_ERR],sigcontext->uc_mcontext.gregs[X64_RIP]);
     // call the signal handler
     x64_ucontext_t sigcontext_copy = *sigcontext;
     // save old value from emu
diff --git a/tests/ref21.txt b/tests/ref21.txt
index 38e983ce..8fc221a0 100644
--- a/tests/ref21.txt
+++ b/tests/ref21.txt
@@ -1,2 +1,6 @@
 sig = 11
 got bad_ptr
+sig = 5
+si_addr: 0, si_code: 128, si_errno: 0, RIP offset: 1, TRAPERR=0 TRAPNO=3
+sig = 5
+si_addr: 0, si_code: 128, si_errno: 0, RIP offset: 2, TRAPERR=0 TRAPNO=3
diff --git a/tests/test21 b/tests/test21
index 71760a7d..934ebcb7 100755
--- a/tests/test21
+++ b/tests/test21
Binary files differdiff --git a/tests/test21.c b/tests/test21.c
index 803f0142..09bae72a 100644
--- a/tests/test21.c
+++ b/tests/test21.c
@@ -1,13 +1,19 @@
+#define __USE_GNU
 #include <signal.h>
 #include <setjmp.h>
 #include <stdio.h>
+#include <sys/mman.h>
+#include <sys/ucontext.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
 
 static jmp_buf context_buf;
 
 static void segv_handler(int sig)
 {
 	printf("sig = %d\n", sig);
-	longjmp(context_buf, 1);
+	siglongjmp(context_buf, 1);
 }
 
 void test()
@@ -20,11 +26,71 @@ void test()
 	}
 }
 
+void* exec_p = NULL;
+typedef void(*vFv_t)(void);
+#define X_IP		16
+#define X_TRAPNO 	20
+#define X_ERR		19
+static void segv_action(int sig, siginfo_t* info, ucontext_t* ucntx)
+{
+	printf("sig = %d\n", sig);
+	printf("si_addr: %zx, si_code: %d, si_errno: %d, RIP offset: %zd, TRAPERR=%d TRAPNO=%d\n", 
+		info->si_addr,
+		info->si_code,
+		info->si_errno,
+		((intptr_t)ucntx->uc_mcontext.gregs[X_IP])-((intptr_t)exec_p),
+		ucntx->uc_mcontext.gregs[X_ERR],
+		ucntx->uc_mcontext.gregs[X_TRAPNO]
+	);
+	siglongjmp(context_buf, 1);
+}
+
+static unsigned char buff_cc[] = { 0xcc, 0xc3 };
+static unsigned char buff_cd03[] = { 0xcd, 0x03, 0xc3 };
+static unsigned char buff_cd2d[] = { 0xcd, 0x2d, 0xc3 };
+void test_cc()
+{
+	memcpy(exec_p, buff_cc, sizeof(buff_cc));
+	if(!setjmp(context_buf)) {
+		vFv_t f = (vFv_t)exec_p;
+		f();
+	}
+	memcpy(exec_p, buff_cd03, sizeof(buff_cd03));
+	if(!setjmp(context_buf)) {
+		vFv_t f = (vFv_t)exec_p;
+		f();
+	}
+	/*memcpy(exec_p, buff_cd2d, sizeof(buff_cd2d));
+	if(!setjmp(context_buf)) {
+		vFv_t f = (vFv_t)exec_p;
+		f();
+	}*/
+}
+
 int main()
 {
-	if(signal(SIGSEGV, segv_handler) == SIG_ERR)
-		printf("Err = %m\n");
+	if(signal(SIGSEGV, segv_handler) == SIG_ERR) {
+		printf("signal: Err = %d\n", errno);
+		return -1;
+	}
 	//printf("handler = %p\n", segv_handler);
 	test();
+    struct sigaction action = {0};
+    action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
+    action.sa_sigaction = segv_action;
+    if(sigaction(SIGSEGV, &action, NULL)) {
+		printf("sigaction: Err = %d\n", errno);
+		return -2;
+	}
+    if(sigaction(SIGTRAP, &action, NULL)) {
+		printf("sigaction 2: Err = %d\n", errno);
+		return -2;
+	}
+	exec_p = mmap(NULL, 65536, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+	if(exec_p==MAP_FAILED) {
+		printf("mmap: Err = %d\n", errno);
+		return -3;
+	}
+	test_cc();
 	return 0;
 }