| 1 | /* Copyright (C) 2001-2016 Free Software Foundation, Inc. | 
|---|
| 2 | This file is part of the GNU C Library. | 
|---|
| 3 |  | 
|---|
| 4 | The GNU C Library is free software; you can redistribute it and/or | 
|---|
| 5 | modify it under the terms of the GNU Lesser General Public | 
|---|
| 6 | License as published by the Free Software Foundation; either | 
|---|
| 7 | version 2.1 of the License, or (at your option) any later version. | 
|---|
| 8 |  | 
|---|
| 9 | The GNU C Library is distributed in the hope that it will be useful, | 
|---|
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
| 12 | Lesser General Public License for more details. | 
|---|
| 13 |  | 
|---|
| 14 | You should have received a copy of the GNU Lesser General Public | 
|---|
| 15 | License along with the GNU C Library; if not, see | 
|---|
| 16 | <http://www.gnu.org/licenses/>.  */ | 
|---|
| 17 |  | 
|---|
| 18 | /* clone() is even more special than fork() as it mucks with stacks | 
|---|
| 19 | and invokes a function in the right context after its all over.  */ | 
|---|
| 20 |  | 
|---|
| 21 | #include <sysdep.h> | 
|---|
| 22 | #define _ERRNO_H	1 | 
|---|
| 23 | #include <bits/errno.h> | 
|---|
| 24 | #include <asm-syntax.h> | 
|---|
| 25 |  | 
|---|
| 26 | #define CLONE_VM	0x00000100 | 
|---|
| 27 |  | 
|---|
| 28 | /* The userland implementation is: | 
|---|
| 29 | int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg), | 
|---|
| 30 | the kernel entry is: | 
|---|
| 31 | int clone (long flags, void *child_stack). | 
|---|
| 32 |  | 
|---|
| 33 | The parameters are passed in register and on the stack from userland: | 
|---|
| 34 | rdi: fn | 
|---|
| 35 | rsi: child_stack | 
|---|
| 36 | rdx:	flags | 
|---|
| 37 | rcx: arg | 
|---|
| 38 | r8d:	TID field in parent | 
|---|
| 39 | r9d: thread pointer | 
|---|
| 40 | %esp+8:	TID field in child | 
|---|
| 41 |  | 
|---|
| 42 | The kernel expects: | 
|---|
| 43 | rax: system call number | 
|---|
| 44 | rdi: flags | 
|---|
| 45 | rsi: child_stack | 
|---|
| 46 | rdx: TID field in parent | 
|---|
| 47 | r10: TID field in child | 
|---|
| 48 | r8:	thread pointer  */ | 
|---|
| 49 |  | 
|---|
| 50 |  | 
|---|
| 51 | .text | 
|---|
| 52 | ENTRY (__clone) | 
|---|
| 53 | /* Sanity check arguments.  */ | 
|---|
| 54 | movq	$-EINVAL,%rax | 
|---|
| 55 | testq	%rdi,%rdi		/* no NULL function pointers */ | 
|---|
| 56 | jz	SYSCALL_ERROR_LABEL | 
|---|
| 57 | testq	%rsi,%rsi		/* no NULL stack pointers */ | 
|---|
| 58 | jz	SYSCALL_ERROR_LABEL | 
|---|
| 59 |  | 
|---|
| 60 | /* Insert the argument onto the new stack.  */ | 
|---|
| 61 | subq	$16,%rsi | 
|---|
| 62 | movq	%rcx,8(%rsi) | 
|---|
| 63 |  | 
|---|
| 64 | /* Save the function pointer.  It will be popped off in the | 
|---|
| 65 | child in the ebx frobbing below.  */ | 
|---|
| 66 | movq	%rdi,0(%rsi) | 
|---|
| 67 |  | 
|---|
| 68 | /* Do the system call.  */ | 
|---|
| 69 | movq	%rdx, %rdi | 
|---|
| 70 | movq	%r8, %rdx | 
|---|
| 71 | movq	%r9, %r8 | 
|---|
| 72 | mov	8(%rsp), %R10_LP | 
|---|
| 73 | movl	$SYS_ify(clone),%eax | 
|---|
| 74 |  | 
|---|
| 75 | /* End FDE now, because in the child the unwind info will be | 
|---|
| 76 | wrong.  */ | 
|---|
| 77 | cfi_endproc; | 
|---|
| 78 | syscall | 
|---|
| 79 |  | 
|---|
| 80 | testq	%rax,%rax | 
|---|
| 81 | jl	SYSCALL_ERROR_LABEL | 
|---|
| 82 | jz	L(thread_start) | 
|---|
| 83 |  | 
|---|
| 84 | ret | 
|---|
| 85 |  | 
|---|
| 86 | L(thread_start): | 
|---|
| 87 | cfi_startproc; | 
|---|
| 88 | /* Clearing frame pointer is insufficient, use CFI.  */ | 
|---|
| 89 | cfi_undefined (rip); | 
|---|
| 90 | /* Clear the frame pointer.  The ABI suggests this be done, to mark | 
|---|
| 91 | the outermost frame obviously.  */ | 
|---|
| 92 | xorl	%ebp, %ebp | 
|---|
| 93 |  | 
|---|
| 94 | andq	$CLONE_VM, %rdi | 
|---|
| 95 | jne	1f | 
|---|
| 96 | movl	$SYS_ify(getpid), %eax | 
|---|
| 97 | syscall | 
|---|
| 98 | movl	%eax, %fs:PID | 
|---|
| 99 | movl	%eax, %fs:TID | 
|---|
| 100 | 1: | 
|---|
| 101 |  | 
|---|
| 102 | /* Set up arguments for the function call.  */ | 
|---|
| 103 | popq	%rax		/* Function to call.  */ | 
|---|
| 104 | popq	%rdi		/* Argument.  */ | 
|---|
| 105 | call	*%rax | 
|---|
| 106 | /* Call exit with return value from function call. */ | 
|---|
| 107 | movq	%rax, %rdi | 
|---|
| 108 | call	HIDDEN_JUMPTARGET (_exit) | 
|---|
| 109 | cfi_endproc; | 
|---|
| 110 |  | 
|---|
| 111 | cfi_startproc; | 
|---|
| 112 | PSEUDO_END (__clone) | 
|---|
| 113 |  | 
|---|
| 114 | libc_hidden_def (__clone) | 
|---|
| 115 | weak_alias (__clone, clone) | 
|---|
| 116 |  | 
|---|