about summary refs log tree commit diff stats
path: root/src/os/emit_signals_linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/os/emit_signals_linux.c')
-rw-r--r--src/os/emit_signals_linux.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/os/emit_signals_linux.c b/src/os/emit_signals_linux.c
new file mode 100644
index 00000000..6df070d5
--- /dev/null
+++ b/src/os/emit_signals_linux.c
@@ -0,0 +1,144 @@
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#ifndef ANDROID
+#include <execinfo.h>
+#endif
+
+#include "box64context.h"
+#include "custommem.h"
+#include "debug.h"
+#include "elfloader.h"
+#include "emit_signals.h"
+#include "emu/x64emu_private.h"
+#include "regs.h"
+#include "signals.h"
+#include "x64emu.h"
+
+void my_sigactionhandler_oldcode(x64emu_t* emu, int32_t sig, int simple, siginfo_t* info, void * ucntx, int* old_code, void* cur_db, uintptr_t x64pc);
+void EmitSignal(x64emu_t* emu, int sig, void* addr, int code)
+{
+    siginfo_t info = { 0 };
+    info.si_signo = sig;
+    info.si_errno = (sig == SIGSEGV) ? 0x1234 : 0; // Mark as a sign this is a #GP(0) (like privileged instruction)
+    info.si_code = code;
+    if (sig == SIGSEGV && code == 0xbad0) {
+        info.si_errno = 0xbad0;
+        info.si_code = 0;
+    } else if (sig == SIGSEGV && code == 0xecec) {
+        info.si_errno = 0xecec;
+        info.si_code = SEGV_ACCERR;
+    } else if (sig == SIGSEGV && code == 0xb09d) {
+        info.si_errno = 0xb09d;
+        info.si_code = 0;
+    }
+    info.si_addr = addr;
+    const char* x64name = NULL;
+    const char* elfname = NULL;
+    if (BOX64ENV(log) > LOG_INFO || BOX64ENV(dynarec_dump) || BOX64ENV(showsegv)) {
+        x64name = getAddrFunctionName(R_RIP);
+        elfheader_t* elf = FindElfAddress(my_context, R_RIP);
+        if (elf)
+            elfname = ElfName(elf);
+        printf_log(LOG_NONE, "Emit Signal %d at IP=%p(%s / %s) / addr=%p, code=0x%x\n", sig, (void*)R_RIP, x64name ? x64name : "???", elfname ? elfname : "?", addr, code);
+        print_rolling_log(LOG_INFO);
+
+        if ((BOX64ENV(showbt) || sig == SIGABRT) && BOX64ENV(log) >= LOG_INFO) {
+            // show native bt
+            #define BT_BUF_SIZE 100
+            int nptrs;
+            void* buffer[BT_BUF_SIZE];
+            char** strings;
+
+            #ifndef ANDROID
+            nptrs = backtrace(buffer, BT_BUF_SIZE);
+            strings = backtrace_symbols(buffer, nptrs);
+            if (strings) {
+                for (int j = 0; j < nptrs; j++)
+                    printf_log(LOG_INFO, "NativeBT: %s\n", strings[j]);
+                free(strings);
+            } else
+                printf_log(LOG_INFO, "NativeBT: none (%d/%s)\n", errno, strerror(errno));
+            #endif
+            extern int my_backtrace_ip(x64emu_t * emu, void** buffer, int size); // in wrappedlibc
+            extern char** my_backtrace_symbols(x64emu_t * emu, uintptr_t * buffer, int size);
+            // save and set real RIP/RSP
+            nptrs = my_backtrace_ip(emu, buffer, BT_BUF_SIZE);
+            strings = my_backtrace_symbols(emu, (uintptr_t*)buffer, nptrs);
+            if (strings) {
+                for (int j = 0; j < nptrs; j++)
+                    printf_log(LOG_INFO, "EmulatedBT: %s\n", strings[j]);
+                free(strings);
+            } else
+                printf_log(LOG_INFO, "EmulatedBT: none\n");
+        }
+        printf_log(LOG_NONE, DumpCPURegs(emu, R_RIP, emu->segs[_CS] == 0x23));
+        printf_log(LOG_NONE, "Emu Stack: %p 0x%lx%s\n", emu->init_stack, emu->size_stack, emu->stack2free ? " owned" : "");
+        // if(!elf) {
+        //     FILE* f = fopen("/proc/self/maps", "r");
+        //     if(f) {
+        //         char line[1024];
+        //         while(!feof(f)) {
+        //             char* ret = fgets(line, sizeof(line), f);
+        //             printf_log(LOG_NONE, "\t%s", ret);
+        //         }
+        //         fclose(f);
+        //     }
+        // }
+        if (sig == SIGILL) {
+            uint8_t* mem = (uint8_t*)R_RIP;
+            printf_log(LOG_NONE, "SIGILL: Opcode at ip is %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n", mem[0], mem[1], mem[2], mem[3], mem[4], mem[5]);
+        }
+    }
+    my_sigactionhandler_oldcode(emu, sig, 0, &info, NULL, NULL, NULL, R_RIP);
+}
+
+void CheckExec(x64emu_t* emu, uintptr_t addr)
+{
+    if (box64_pagesize != 4096)
+        return; // disabling the test, 4K pagesize simlation isn't good enough for this
+    while ((getProtection_fast(addr) & (PROT_EXEC | PROT_READ)) != (PROT_EXEC | PROT_READ)) {
+        R_RIP = addr; // incase there is a slight difference
+        EmitSignal(emu, SIGSEGV, (void*)addr, 0xecec);
+    }
+}
+
+void EmitInterruption(x64emu_t* emu, int num, void* addr)
+{
+    siginfo_t info = { 0 };
+    info.si_signo = SIGSEGV;
+    info.si_errno = 0xdead;
+    info.si_code = num;
+    info.si_addr = NULL; // addr;
+    const char* x64name = NULL;
+    const char* elfname = NULL;
+    if (BOX64ENV(log) > LOG_INFO || BOX64ENV(dynarec_dump) || BOX64ENV(showsegv)) {
+        x64name = getAddrFunctionName(R_RIP);
+        elfheader_t* elf = FindElfAddress(my_context, R_RIP);
+        if (elf)
+            elfname = ElfName(elf);
+        printf_log(LOG_NONE, "Emit Interruption 0x%x at IP=%p(%s / %s) / addr=%p\n", num, (void*)R_RIP, x64name ? x64name : "???", elfname ? elfname : "?", addr);
+    }
+    my_sigactionhandler_oldcode(emu, SIGSEGV, 0, &info, NULL, NULL, NULL, R_RIP);
+}
+
+void EmitDiv0(x64emu_t* emu, void* addr, int code)
+{
+    siginfo_t info = { 0 };
+    info.si_signo = SIGSEGV;
+    info.si_errno = 0xcafe;
+    info.si_code = code;
+    info.si_addr = addr;
+    const char* x64name = NULL;
+    const char* elfname = NULL;
+    if (BOX64ENV(log) > LOG_INFO || BOX64ENV(dynarec_dump) || BOX64ENV(showsegv)) {
+        x64name = getAddrFunctionName(R_RIP);
+        elfheader_t* elf = FindElfAddress(my_context, R_RIP);
+        if (elf)
+            elfname = ElfName(elf);
+        printf_log(LOG_NONE, "Emit Divide by 0 at IP=%p(%s / %s) / addr=%p\n", (void*)R_RIP, x64name ? x64name : "???", elfname ? elfname : "?", addr);
+    }
+    my_sigactionhandler_oldcode(emu, SIGSEGV, 0, &info, NULL, NULL, NULL, R_RIP);
+}