158 lines
4.9 KiB
NASM
158 lines
4.9 KiB
NASM
; x64 POSIX vfork continuation. The parent enters the resume/wait syscall without
|
|
; a nested userspace return frame while the child owns the caller's stack.
|
|
|
|
INCLUDE syscall_nr.inc
|
|
|
|
VF_ReturnAddress EQU 0
|
|
VF_ParentRsp EQU 8
|
|
VF_Rbx EQU 16
|
|
VF_Rbp EQU 24
|
|
VF_Rsi EQU 32
|
|
VF_Rdi EQU 40
|
|
VF_R12 EQU 48
|
|
VF_R13 EQU 56
|
|
VF_R14 EQU 64
|
|
VF_R15 EQU 72
|
|
VF_Xmm6 EQU 80
|
|
VF_Xmm7 EQU 96
|
|
VF_Xmm8 EQU 112
|
|
VF_Xmm9 EQU 128
|
|
VF_Xmm10 EQU 144
|
|
VF_Xmm11 EQU 160
|
|
VF_Xmm12 EQU 176
|
|
VF_Xmm13 EQU 192
|
|
VF_Xmm14 EQU 208
|
|
VF_Xmm15 EQU 224
|
|
VF_Mxcsr EQU 240
|
|
VF_X87Control EQU 244
|
|
VF_ThreadHandle EQU 256
|
|
VF_PreviousSuspendCount EQU 264
|
|
VF_ContextSize EQU 280
|
|
VF_LocalSize EQU 312
|
|
|
|
EXTERN PosixVforkPrepare:PROC
|
|
EXTERN PosixVforkParentFinish:PROC
|
|
|
|
.CODE
|
|
|
|
PUBLIC vfork
|
|
vfork PROC EXPORT
|
|
sub rsp, VF_LocalSize
|
|
lea r10, [rsp + 32]
|
|
|
|
mov rax, [rsp + VF_LocalSize]
|
|
mov [r10 + VF_ReturnAddress], rax
|
|
lea rax, [rsp + VF_LocalSize + 8]
|
|
mov [r10 + VF_ParentRsp], rax
|
|
mov [r10 + VF_Rbx], rbx
|
|
mov [r10 + VF_Rbp], rbp
|
|
mov [r10 + VF_Rsi], rsi
|
|
mov [r10 + VF_Rdi], rdi
|
|
mov [r10 + VF_R12], r12
|
|
mov [r10 + VF_R13], r13
|
|
mov [r10 + VF_R14], r14
|
|
mov [r10 + VF_R15], r15
|
|
movdqu xmmword ptr [r10 + VF_Xmm6], xmm6
|
|
movdqu xmmword ptr [r10 + VF_Xmm7], xmm7
|
|
movdqu xmmword ptr [r10 + VF_Xmm8], xmm8
|
|
movdqu xmmword ptr [r10 + VF_Xmm9], xmm9
|
|
movdqu xmmword ptr [r10 + VF_Xmm10], xmm10
|
|
movdqu xmmword ptr [r10 + VF_Xmm11], xmm11
|
|
movdqu xmmword ptr [r10 + VF_Xmm12], xmm12
|
|
movdqu xmmword ptr [r10 + VF_Xmm13], xmm13
|
|
movdqu xmmword ptr [r10 + VF_Xmm14], xmm14
|
|
movdqu xmmword ptr [r10 + VF_Xmm15], xmm15
|
|
stmxcsr dword ptr [r10 + VF_Mxcsr]
|
|
fnstcw word ptr [r10 + VF_X87Control]
|
|
|
|
mov rcx, r10
|
|
call PosixVforkPrepare
|
|
test rax, rax
|
|
jnz vfork_wait
|
|
add rsp, VF_LocalSize
|
|
mov eax, -1
|
|
ret
|
|
|
|
vfork_wait:
|
|
; R12 deliberately holds the heap context across the kernel wait. The child
|
|
; restores the caller's original R12 in its independent native context.
|
|
mov r12, rax
|
|
mov ecx, dword ptr [r12 + VF_ThreadHandle]
|
|
lea rdx, [r12 + VF_PreviousSuspendCount]
|
|
mov eax, SYS_RESUME_THREAD_AND_WAIT
|
|
int 02Fh
|
|
mov r9d, eax
|
|
|
|
; The child may have overwritten every byte of the old vfork/helper frames.
|
|
; Rebuild only a synthetic return frame from the heap continuation.
|
|
mov r10, r12
|
|
mov r11, [r10 + VF_ParentRsp]
|
|
mov rax, [r10 + VF_ReturnAddress]
|
|
mov rsp, r11
|
|
sub rsp, 8
|
|
mov [rsp], rax
|
|
sub rsp, 40
|
|
|
|
ldmxcsr dword ptr [r10 + VF_Mxcsr]
|
|
fldcw word ptr [r10 + VF_X87Control]
|
|
movdqu xmm6, xmmword ptr [r10 + VF_Xmm6]
|
|
movdqu xmm7, xmmword ptr [r10 + VF_Xmm7]
|
|
movdqu xmm8, xmmword ptr [r10 + VF_Xmm8]
|
|
movdqu xmm9, xmmword ptr [r10 + VF_Xmm9]
|
|
movdqu xmm10, xmmword ptr [r10 + VF_Xmm10]
|
|
movdqu xmm11, xmmword ptr [r10 + VF_Xmm11]
|
|
movdqu xmm12, xmmword ptr [r10 + VF_Xmm12]
|
|
movdqu xmm13, xmmword ptr [r10 + VF_Xmm13]
|
|
movdqu xmm14, xmmword ptr [r10 + VF_Xmm14]
|
|
movdqu xmm15, xmmword ptr [r10 + VF_Xmm15]
|
|
mov rbx, [r10 + VF_Rbx]
|
|
mov rbp, [r10 + VF_Rbp]
|
|
mov rsi, [r10 + VF_Rsi]
|
|
mov rdi, [r10 + VF_Rdi]
|
|
mov r12, [r10 + VF_R12]
|
|
mov r13, [r10 + VF_R13]
|
|
mov r14, [r10 + VF_R14]
|
|
mov r15, [r10 + VF_R15]
|
|
|
|
mov rcx, r10
|
|
mov edx, r9d
|
|
call PosixVforkParentFinish
|
|
add rsp, 40
|
|
ret
|
|
vfork ENDP
|
|
|
|
PUBLIC PosixVforkEnterChild
|
|
PosixVforkEnterChild PROC
|
|
mov r10, rcx
|
|
mov r11, [r10 + VF_ParentRsp]
|
|
mov rax, [r10 + VF_ReturnAddress]
|
|
mov rsp, r11
|
|
sub rsp, 8
|
|
mov [rsp], rax
|
|
|
|
ldmxcsr dword ptr [r10 + VF_Mxcsr]
|
|
fldcw word ptr [r10 + VF_X87Control]
|
|
movdqu xmm6, xmmword ptr [r10 + VF_Xmm6]
|
|
movdqu xmm7, xmmword ptr [r10 + VF_Xmm7]
|
|
movdqu xmm8, xmmword ptr [r10 + VF_Xmm8]
|
|
movdqu xmm9, xmmword ptr [r10 + VF_Xmm9]
|
|
movdqu xmm10, xmmword ptr [r10 + VF_Xmm10]
|
|
movdqu xmm11, xmmword ptr [r10 + VF_Xmm11]
|
|
movdqu xmm12, xmmword ptr [r10 + VF_Xmm12]
|
|
movdqu xmm13, xmmword ptr [r10 + VF_Xmm13]
|
|
movdqu xmm14, xmmword ptr [r10 + VF_Xmm14]
|
|
movdqu xmm15, xmmword ptr [r10 + VF_Xmm15]
|
|
mov rbx, [r10 + VF_Rbx]
|
|
mov rbp, [r10 + VF_Rbp]
|
|
mov rsi, [r10 + VF_Rsi]
|
|
mov rdi, [r10 + VF_Rdi]
|
|
mov r12, [r10 + VF_R12]
|
|
mov r13, [r10 + VF_R13]
|
|
mov r14, [r10 + VF_R14]
|
|
mov r15, [r10 + VF_R15]
|
|
xor eax, eax
|
|
ret
|
|
PosixVforkEnterChild ENDP
|
|
|
|
END
|