2.9
[glibc/nacl-glibc.git] / sysdeps / unix / sysv / linux / x86_64 / clone.S
blobdb42f209c9fe4e827a816b753adf5b57fdf8849a
1 /* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
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.
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.
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
19 /* clone() is even more special than fork() as it mucks with stacks
20    and invokes a function in the right context after its all over.  */
22 #include <sysdep.h>
23 #define _ERRNO_H        1
24 #include <bits/errno.h>
25 #include <asm-syntax.h>
26 #include <bp-sym.h>
27 #include <bp-asm.h>
29 #define CLONE_VM        0x00000100
30 #define CLONE_THREAD    0x00010000
32 /* The userland implementation is:
33    int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg),
34    the kernel entry is:
35    int clone (long flags, void *child_stack).
37    The parameters are passed in register and on the stack from userland:
38    rdi: fn
39    rsi: child_stack
40    rdx: flags
41    rcx: arg
42    r8d: TID field in parent
43    r9d: thread pointer
44 %esp+8: TID field in child
46    The kernel expects:
47    rax: system call number
48    rdi: flags
49    rsi: child_stack
50    rdx: TID field in parent
51    r10: TID field in child
52    r8:  thread pointer  */
55         .text
56 ENTRY (BP_SYM (__clone))
57         /* Sanity check arguments.  */
58         movq    $-EINVAL,%rax
59         testq   %rdi,%rdi               /* no NULL function pointers */
60         jz      SYSCALL_ERROR_LABEL
61         testq   %rsi,%rsi               /* no NULL stack pointers */
62         jz      SYSCALL_ERROR_LABEL
64         /* Insert the argument onto the new stack.  */
65         subq    $16,%rsi
66         movq    %rcx,8(%rsi)
68         /* Save the function pointer.  It will be popped off in the
69            child in the ebx frobbing below.  */
70         movq    %rdi,0(%rsi)
72         /* Do the system call.  */
73         movq    %rdx, %rdi
74         movq    %r8, %rdx
75         movq    %r9, %r8
76         movq    8(%rsp), %r10
77         movl    $SYS_ify(clone),%eax
79         /* End FDE now, because in the child the unwind info will be
80            wrong.  */
81         cfi_endproc;
82         syscall
84         testq   %rax,%rax
85         jl      SYSCALL_ERROR_LABEL
86         jz      L(thread_start)
88 L(pseudo_end):
89         ret
91 L(thread_start):
92         cfi_startproc;
93         /* Clearing frame pointer is insufficient, use CFI.  */
94         cfi_undefined (rip);
95         /* Clear the frame pointer.  The ABI suggests this be done, to mark
96            the outermost frame obviously.  */
97         xorl    %ebp, %ebp
99 #ifdef RESET_PID
100         testq   $CLONE_THREAD, %rdi
101         jne     1f
102         testq   $CLONE_VM, %rdi
103         movl    $-1, %eax
104         jne     2f
105         movl    $SYS_ify(getpid), %eax
106         syscall
107 2:      movl    %eax, %fs:PID
108         movl    %eax, %fs:TID
110 #endif
112         /* Set up arguments for the function call.  */
113         popq    %rax            /* Function to call.  */
114         popq    %rdi            /* Argument.  */
115         call    *%rax
116         /* Call exit with return value from function call. */
117         movq    %rax, %rdi
118         call    HIDDEN_JUMPTARGET (_exit)
119         cfi_endproc;
121         cfi_startproc;
122 PSEUDO_END (BP_SYM (__clone))
124 weak_alias (BP_SYM (__clone), BP_SYM (clone))