about summary refs log tree commit diff stats
path: root/src/emu
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-12-14 22:51:31 +0100
committerptitSeb <sebastien.chev@gmail.com>2024-12-14 22:51:31 +0100
commit6a3c56c1312a98ce2cf04ca72c5c4889a93070b3 (patch)
tree852c43cbf5ac4bc394c812b5b6c8270a802ec491 /src/emu
parentd03c85da9045a67e178c98d94b607cc3cd8d22c0 (diff)
downloadbox64-6a3c56c1312a98ce2cf04ca72c5c4889a93070b3.tar.gz
box64-6a3c56c1312a98ce2cf04ca72c5c4889a93070b3.zip
[BOX32][WRAPPER] More fixes to libc and libX11 wrapping
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/x86syscall_32.c102
1 files changed, 98 insertions, 4 deletions
diff --git a/src/emu/x86syscall_32.c b/src/emu/x86syscall_32.c
index 2a118d65..20a149ba 100644
--- a/src/emu/x86syscall_32.c
+++ b/src/emu/x86syscall_32.c
@@ -37,6 +37,7 @@
 #include "x64tls.h"
 #include "box32.h"
 #include "converter32.h"
+#include "custommem.h"
 
 
 // Syscall table for x86_64 can be found 
@@ -54,7 +55,9 @@ static const scwrap_t syscallwrap[] = {
     //{ 4, __NR_write, 3 }, // same
     //{ 5, __NR_open, 3 },  // flags need transformation
     //{ 6, __NR_close, 1 },   // wrapped so SA_RESTART can be handled by libc
-    //{ 7, __NR_waitpid, 3 },
+    #ifdef __NR_waitpid
+    { 7, __NR_waitpid, 3 },
+    #endif
     //{ 10, __NR_unlink, 1 },
     //{ 12, __NR_chdir, 1 },
     //{ 13, __NR_time, 1 },
@@ -68,7 +71,9 @@ static const scwrap_t syscallwrap[] = {
     //{ 39, __NR_mkdir, 2 },
     //{ 40, __NR_rmdir, 1 },
     //{ 41, __NR_dup, 1 },
-    //{ 42, __NR_pipe, 1 },
+    #ifdef __NR_pipe
+    { 42, __NR_pipe, 1 },
+    #endif
     //{ 45, __NR_brk, 1 },
     //{ 47, __NR_getgid, 0 },
     //{ 49, __NR_geteuid, 0 },
@@ -124,7 +129,7 @@ static const scwrap_t syscallwrap[] = {
     //{ 162, __NR_nanosleep, 2 },
     //{ 164, __NR_setresuid, 3 },
     //{ 168, __NR_poll, 3 },    // wrapped to allow SA_RESTART wrapping by libc
-    //{ 172, __NR_prctl, 5 },
+    { 172, __NR_prctl, 5 },
     //{ 173, __NR_rt_sigreturn, 0 },
     //{ 175, __NR_rt_sigprocmask, 4 },
     //{ 179, __NR_rt_sigsuspend, 2 },
@@ -254,11 +259,25 @@ ssize_t my32_read(int fd, void* buf, size_t count);
 void* my32_mmap64(x64emu_t* emu, void *addr, size_t length, int prot, int flags, int fd, int64_t offset);
 int my32_munmap(x64emu_t* emu, void* addr, unsigned long length);
 int my32_sigaltstack(x64emu_t* emu, const i386_stack_t* ss, i386_stack_t* oss);
+pid_t my_vfork(x64emu_t* emu);
 
 #ifndef FUTEX_LOCK_PI2
 #define FUTEX_LOCK_PI2 13
 #endif
 
+static int clone32_fn(void* arg)
+{
+    x64emu_t *emu = (x64emu_t*)arg;
+    thread_set_emu(emu);
+    R_EAX = 0;
+    DynaRun(emu);
+    int ret = S_EAX;
+    FreeX64Emu(&emu);
+    my_context->stack_clone_used = 0;
+    return ret;
+}
+
+
 void EXPORT x86Syscall(x64emu_t *emu)
 {
     uint32_t s = R_EAX;
@@ -317,6 +336,20 @@ void EXPORT x86Syscall(x64emu_t *emu)
         case 6:  // sys_close
             S_EAX = close((int)R_EBX);
             break;
+#ifndef __NR_waitpid
+        case 7: //sys_waitpid
+            S_EAX = waitpid((pid_t)R_EBX, (int*)from_ptrv(R_ECX), S_EDX);
+            if(S_EAX==-1 && errno>0)
+                S_EAX = -errno;
+            break;
+#endif
+        #ifndef __NR_fork
+        case 42:
+            S_EAX = pipe(from_ptrv(R_EBX));
+            if(S_EAX==-1)
+                S_EAX = -errno;
+            break;
+        #endif
         case 90:    // old_mmap
             {
                 struct mmap_arg_struct *st = from_ptrv(R_EBX);
@@ -330,7 +363,61 @@ void EXPORT x86Syscall(x64emu_t *emu)
             if(S_EAX==-1 && errno>0)
                 S_EAX = -errno;
             break;
-        /*case 123:   // SYS_modify_ldt
+        case 120: // sys_clone
+            // x86 raw syscall is long clone(unsigned long flags, void *stack, int *parent_tid, unsigned long tls, int *child_tid);
+            // so flags=R_EBX, stack=R_ECX, parent_tid=R_EDX, child_tid=R_ESI, tls=R_EDI
+            if((R_EBX&~0xff)==0x4100) {
+                // this is a case of vfork...
+                S_RAX = my_vfork(emu);
+                if(S_RAX==-1)
+                    S_RAX = -errno;
+            } else {
+                if(R_ECX)
+                {
+                    void* stack_base = from_ptrv(R_ECX);
+                    int stack_size = 0;
+                    uintptr_t sp = R_ECX;
+                    if(!R_RSI) {
+                        // allocate a new stack...
+                        int currstack = 0;
+                        if((R_ESP>=(uintptr_t)emu->init_stack) && (R_ESP<=((uintptr_t)emu->init_stack+emu->size_stack)))
+                            currstack = 1;
+                        stack_size = (currstack && emu->size_stack)?emu->size_stack:(1024*1024);
+                        stack_base = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0);
+                        // copy value from old stack to new stack
+                        if(currstack) {
+                            memcpy(stack_base, emu->init_stack, stack_size);
+                            sp = (uintptr_t)emu->init_stack + R_ESP - (uintptr_t)stack_base;
+                        } else {
+                            int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_ESP);
+                            memcpy(stack_base+stack_size-size_to_copy, from_ptrv(R_ESP), size_to_copy);
+                            sp = (uintptr_t)stack_base+stack_size-size_to_copy;
+                        }
+                    }
+                    x64emu_t * newemu = NewX64Emu(emu->context, R_EIP, (uintptr_t)stack_base, stack_size, (R_ECX)?0:1);
+                    SetupX64Emu(newemu, emu);
+                    CloneEmu(newemu, emu);
+                    newemu->regs[_SP].q[0] = sp;  // setup new stack pointer
+                    void* mystack = NULL;
+                    if(my_context->stack_clone_used) {
+                        mystack = box_malloc(1024*1024);  // stack for own process... memory leak, but no practical way to remove it
+                    } else {
+                        if(!my_context->stack_clone)
+                            my_context->stack_clone = box_malloc(1024*1024);
+                        mystack = my_context->stack_clone;
+                        my_context->stack_clone_used = 1;
+                    }
+                    int64_t ret = clone(clone32_fn, (void*)((uintptr_t)mystack+1024*1024), R_EBX, newemu, R_EDX, R_EDI, R_ESI);
+                    S_RAX = ret;
+                }
+                else
+                    #ifdef NOALIGN
+                    S_RAX = syscall(__NR_clone, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
+                    #else
+                    S_RAX = syscall(__NR_clone, R_EBX, R_ECX, R_EDX, R_EDI, R_ESI);    // invert R_ESI/R_EDI on Aarch64 and most other
+                    #endif
+            }
+            break;        /*case 123:   // SYS_modify_ldt
             R_EAX = my32_modify_ldt(emu, R_EBX, (thread_area_t*)(uintptr_t)R_ECX, R_EDX);
             if(R_EAX==0xffffffff && errno>0)
                 R_EAX = (uint32_t)-errno;
@@ -469,6 +556,13 @@ uint32_t EXPORT my32_syscall(x64emu_t *emu, uint32_t s, ptr_t* b)
             return (uint32_t)close(i32(0));
         case 11: // execve
             return (uint32_t)my32_execve(emu, p(0), p(4), p(8));
+        #ifndef __NR_fork
+        case 42:
+            S_EAX = pipe(p(0));
+            if(S_EAX==-1)
+                S_EAX = -errno;
+            break;
+        #endif
         case 91:   // munmap
             return (uint32_t)my32_munmap(emu, p(0), u32(4));
 #if 0