about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-12-23 12:23:07 +0100
committerptitSeb <sebastien.chev@gmail.com>2024-12-23 12:23:18 +0100
commitac811324350c4a112d7e2102ecd1c6f0a362a204 (patch)
tree465dbb05cd910e83ec21f9f7a543f1a930dd99a3 /src
parent946da430388786a8237e2e7d17c7c2535246963f (diff)
downloadbox64-ac811324350c4a112d7e2102ecd1c6f0a362a204.tar.gz
box64-ac811324350c4a112d7e2102ecd1c6f0a362a204.zip
Try to improve clone syscal handling ([BOX32] too)
Diffstat (limited to 'src')
-rw-r--r--src/emu/x64syscall.c41
-rw-r--r--src/emu/x86syscall_32.c23
2 files changed, 37 insertions, 27 deletions
diff --git a/src/emu/x64syscall.c b/src/emu/x64syscall.c
index 3f21842c..ee3e7a8c 100644
--- a/src/emu/x64syscall.c
+++ b/src/emu/x64syscall.c
@@ -404,16 +404,28 @@ typedef struct old_utsname_s {
 //    int  xss;
 //};
 
+typedef struct clone_s {
+    x64emu_t* emu;
+    void* stack2free;
+} clone_t;
+
 static int clone_fn(void* arg)
 {
-    x64emu_t *emu = (x64emu_t*)arg;
+    clone_t* args = arg;
+    x64emu_t *emu = args->emu;
+    thread_forget_emu();
     thread_set_emu(emu);
     R_RAX = 0;
     DynaRun(emu);
     int ret = R_EAX;
     FreeX64Emu(&emu);
-    my_context->stack_clone_used = 0;
-    return ret;
+    void* stack2free = args->stack2free;
+    box_free(args);
+    if(my_context->stack_clone_used && !stack2free)
+        my_context->stack_clone_used = 0;
+    if(stack2free)
+        box_free(stack2free);   // this free the stack, so it will crash very soon!
+    _exit(ret);
 }
 
 void EXPORT x64Syscall(x64emu_t *emu)
@@ -589,37 +601,22 @@ void EXPORT x64Syscall(x64emu_t *emu)
                     void* stack_base = (void*)R_RSI;
                     int stack_size = 0;
                     uintptr_t sp = R_RSI;
-                    if(!R_RSI) {
-                        // allocate a new stack...
-                        int currstack = 0;
-                        if((R_RSP>=(uintptr_t)emu->init_stack) && (R_RSP<=((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_GROWSDOWN, -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_RSP - (uintptr_t)stack_base;
-                        } else {
-                            int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_RSP);
-                            memcpy(stack_base+stack_size-size_to_copy, (void*)R_RSP, size_to_copy);
-                            sp = (uintptr_t)stack_base+stack_size-size_to_copy;
-                        }
-                    }
                     x64emu_t * newemu = NewX64Emu(emu->context, R_RIP, (uintptr_t)stack_base, stack_size, (R_RSI)?0:1);
                     SetupX64Emu(newemu, emu);
                     CloneEmu(newemu, emu);
+                    clone_t* args = box_calloc(1, sizeof(clone_t));
                     newemu->regs[_SP].q[0] = sp;  // setup new stack pointer
+                    args->emu = newemu;
                     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
+                        args->stack2free = mystack = box_malloc(1024*1024);  // stack for own process...
                     } 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(clone_fn, (void*)((uintptr_t)mystack+1024*1024), R_RDI, newemu, R_RDX, R_R8, R_R10);
+                    int64_t ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), R_RDI, args, R_RDX, R_R8, R_R10);
                     S_RAX = ret;
                 }
                 else
diff --git a/src/emu/x86syscall_32.c b/src/emu/x86syscall_32.c
index da40783c..dc2bf76c 100644
--- a/src/emu/x86syscall_32.c
+++ b/src/emu/x86syscall_32.c
@@ -265,9 +265,15 @@ pid_t my_vfork(x64emu_t* emu);
 #define FUTEX_LOCK_PI2 13
 #endif
 
+typedef struct clone_s {
+    x64emu_t* emu;
+    void* stack2free;
+} clone_t;
+
 static int clone32_fn(void* arg)
 {
-    x64emu_t *emu = (x64emu_t*)arg;
+    clone_t* args = arg;
+    x64emu_t *emu = args->emu;
     printf_log(LOG_DEBUG, "%04d|New clone32_fn starting with emu=%p (R_ESP=%p)\n", GetTID(), arg, from_ptrv(R_ESP));
     thread_forget_emu();
     thread_set_emu(emu);
@@ -276,8 +282,13 @@ static int clone32_fn(void* arg)
     int ret = S_EAX;
     printf_log(LOG_DEBUG, "%04d|clone32_fn ending with ret=%d (emu=%p)\n", GetTID(), ret, arg);
     FreeX64Emu(&emu);
-    my_context->stack_clone_used = 0;
-    return ret;
+    void* stack2free = args->stack2free;
+    box_free(args);
+    if(my_context->stack_clone_used && !stack2free)
+        my_context->stack_clone_used = 0;
+    if(stack2free)
+        box_free(stack2free);   // this free the stack, so it will crash very soon!
+    _exit(ret);
 }
 
 
@@ -385,15 +396,17 @@ void EXPORT x86Syscall(x64emu_t *emu)
                     CloneEmu(newemu, emu);
                     newemu->regs[_SP].q[0] = sp;  // setup new stack pointer
                     void* mystack = NULL;
+                    clone_t* args = box_calloc(1, sizeof(clone_t));
+                    args->emu = newemu;
                     if(my_context->stack_clone_used) {
-                        mystack = box_malloc(1024*1024);  // stack for own process... memory leak, but no practical way to remove it
+                        args->stack2free = mystack = box_malloc(1024*1024);  // stack for own process...
                     } 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);
+                    int64_t ret = clone(clone32_fn, (void*)((uintptr_t)mystack+1024*1024), R_EBX, args, R_EDX, R_EDI, R_ESI);
                     S_RAX = ret;
                 }
                 else