diff --git a/core/win32/os_private.h b/core/win32/os_private.h index 9b5aae9dae2..a57ae4219f4 100644 --- a/core/win32/os_private.h +++ b/core/win32/os_private.h @@ -259,7 +259,11 @@ sys_param_addr(dcontext_t *dcontext, reg_t *param_base, int num) /* we force-inline get_mcontext() and so don't take it as a param */ priv_mcontext_t *mc = get_mcontext(dcontext); switch (num) { - case 0: return &mc->xcx; + /* The first arg was in rcx, but that's clobbered by OP_sysycall, so the wrapper + * copies it to r10. We need to use r10 as our own instru sometimes takes + * advantage of the dead rcx and clobbers it inside the wrapper (i#1901). + */ + case 0: return &mc->r10; case 1: return &mc->xdx; case 2: return &mc->r8; case 3: return &mc->r9; diff --git a/core/win32/syscall.c b/core/win32/syscall.c index 070f292e835..eaab6d2e3a8 100644 --- a/core/win32/syscall.c +++ b/core/win32/syscall.c @@ -1750,7 +1750,10 @@ presys_TerminateProcess(dcontext_t *dcontext, reg_t *param_base) /* FIXME: what if syscall returns w/ STATUS_PROCESS_IS_TERMINATING? */ os_terminate_wow64_write_args(true/*process*/, process_handle, exit_status); cleanup_and_terminate(dcontext, syscalls[SYS_TerminateProcess], - IF_X64_ELSE(mc->xcx, mc->xdx), + /* r10, which will go to rcx in cleanup_and_terminate + * and back to r10 in global_do_syscall_syscall (i#1901). + */ + IF_X64_ELSE(mc->r10, mc->xdx), mc->xdx, true /* entire process */, 0, 0); } return true; @@ -1829,7 +1832,10 @@ presys_TerminateThread(dcontext_t *dcontext, reg_t *param_base) KSTOP(num_exits_dir_syscall); os_terminate_wow64_write_args(false/*thread*/, thread_handle, exit_status); cleanup_and_terminate(dcontext, syscalls[SYS_TerminateThread], - IF_X64_ELSE(mc->xcx, mc->xdx), + /* r10, which will go to rcx in cleanup_and_terminate + * and back to r10 in global_do_syscall_syscall (i#1901). + */ + IF_X64_ELSE(mc->r10, mc->xdx), mc->xdx, exitproc, 0, 0); } } @@ -4474,8 +4480,7 @@ dr_syscall_invoke_another(void *drcontext) } # ifdef X64 else if (get_syscall_method() == SYSCALL_METHOD_SYSCALL) { - /* we could instead have sys_param_addr() use r10, like we do on linux */ - mc->r10 = mc->xcx; + /* sys_param_addr() is already using r10 */ } # endif }