|
@@ -53,12 +53,17 @@ void __attribute__((weak)) syscall_wrapper_after_syscalldb(void)
|
|
|
* child thread can _not_ use parent stack. So return right after syscall
|
|
|
* instruction as if syscall_wrapper is executed.
|
|
|
*/
|
|
|
-static void fixup_child_context(struct shim_context * context)
|
|
|
+static void fixup_child_context(struct shim_regs * regs)
|
|
|
{
|
|
|
- if (context->ret_ip == &syscall_wrapper_after_syscalldb) {
|
|
|
- context->sp += RED_ZONE_SIZE;
|
|
|
- context->regs->rflags = context->regs->r11;
|
|
|
- context->ret_ip = (void*)context->regs->rcx;
|
|
|
+ if (regs->rip == (unsigned long)&syscall_wrapper_after_syscalldb) {
|
|
|
+ /*
|
|
|
+ * we don't need to emulate stack pointer change because %rsp is
|
|
|
+ * initialized to new child user stack passed to clone() system call.
|
|
|
+ * See the caller of fixup_child_context().
|
|
|
+ */
|
|
|
+ /* regs->rsp += RED_ZONE_SIZE; */
|
|
|
+ regs->rflags = regs->r11;
|
|
|
+ regs->rip = regs->rcx;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -142,7 +147,6 @@ int clone_implementation_wrapper(struct clone_args * arg)
|
|
|
}
|
|
|
|
|
|
void * stack = arg->stack;
|
|
|
- void * return_pc = arg->return_pc;
|
|
|
|
|
|
struct shim_vma_val vma;
|
|
|
lookup_vma(ALIGN_DOWN(stack), &vma);
|
|
@@ -161,13 +165,12 @@ int clone_implementation_wrapper(struct clone_args * arg)
|
|
|
//user_stack_addr[0] ==> user provided function address
|
|
|
//user_stack_addr[1] ==> arguments to user provided function.
|
|
|
|
|
|
- debug("child swapping stack to %p return %p: %d\n",
|
|
|
- stack, return_pc, my_thread->tid);
|
|
|
+ debug("child swapping stack to %p return 0x%lx: %d\n",
|
|
|
+ stack, regs.rip, my_thread->tid);
|
|
|
|
|
|
tcb->context.regs = ®s;
|
|
|
- tcb->context.sp = stack;
|
|
|
- tcb->context.ret_ip = return_pc;
|
|
|
- fixup_child_context(&tcb->context);
|
|
|
+ fixup_child_context(tcb->context.regs);
|
|
|
+ tcb->context.regs->rsp = (unsigned long)stack;
|
|
|
|
|
|
restore_context(&tcb->context);
|
|
|
return 0;
|
|
@@ -319,6 +322,7 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
|
|
|
if (!(flags & CLONE_VM)) {
|
|
|
__libc_tcb_t * tcb;
|
|
|
shim_tcb_t * old_shim_tcb = NULL;
|
|
|
+ void * parent_stack = NULL;
|
|
|
|
|
|
if (thread->tcb) {
|
|
|
tcb = thread->tcb;
|
|
@@ -334,8 +338,8 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
|
|
|
lookup_vma(ALIGN_DOWN(user_stack_addr), &vma);
|
|
|
thread->stack_top = vma.addr + vma.length;
|
|
|
thread->stack_red = thread->stack = vma.addr;
|
|
|
- tcb->shim_tcb.context.sp = user_stack_addr;
|
|
|
- tcb->shim_tcb.context.ret_ip = shim_get_tls()->context.ret_ip;
|
|
|
+ parent_stack = (void *)tcb->shim_tcb.context.regs->rsp;
|
|
|
+ tcb->shim_tcb.context.regs->rsp = (unsigned long)user_stack_addr;
|
|
|
}
|
|
|
|
|
|
thread->is_alive = true;
|
|
@@ -346,6 +350,8 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
|
|
|
ret = do_migrate_process(&migrate_fork, NULL, NULL, thread);
|
|
|
if (old_shim_tcb)
|
|
|
memcpy(&tcb->shim_tcb, old_shim_tcb, sizeof(tcb->shim_tcb));
|
|
|
+ if (parent_stack)
|
|
|
+ tcb->shim_tcb.context.regs->rsp = (unsigned long)parent_stack;
|
|
|
if (ret < 0)
|
|
|
goto failed;
|
|
|
|
|
@@ -384,7 +390,6 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
|
|
|
new_args.thread = thread;
|
|
|
new_args.parent = self;
|
|
|
new_args.stack = user_stack_addr;
|
|
|
- new_args.return_pc = shim_get_tls()->context.ret_ip;
|
|
|
|
|
|
// Invoke DkThreadCreate to spawn off a child process using the actual
|
|
|
// "clone" system call. DkThreadCreate allocates a stack for the child
|