Update copyright dates with scripts/update-copyrights
[glibc.git] / sysdeps / unix / sysv / linux / i386 / clone3.S
blob41189d79c1c02c1e136b50a1cbbd98c8bd31f3ce
1 /* The clone3 syscall wrapper.  Linux/i386 version.
2    Copyright (C) 2021-2023 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
19 /* clone3() 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>
24 /* The userland implementation is:
25    int clone3 (struct clone_args *cl_args, size_t size,
26                int (*func)(void *arg), void *arg);
27    the kernel entry is:
28    int clone3 (struct clone_args *cl_args, size_t size);
30    The parameters are passed on stack from userland:
31    16(%esp)     arg
32    12(%esp)     func
33     8(%esp)     size
34     4(%esp)     cl_args
35      (%esp)     Return address
37    The kernel expects:
38    eax:         system call number
39    ebx:         cl_args
40    ecx:         size
41  */
43 #define CL_ARGS 4
44 #define SIZE    8
45 #define FUNC    12
46 #define ARG     16
48         .text
49 ENTRY (__clone3)
50         /* Sanity check arguments.  */
51         movl    $-EINVAL, %eax
52         movl    CL_ARGS(%esp), %ecx     /* No NULL cl_args pointer.  */
53         testl   %ecx, %ecx
54         jz      SYSCALL_ERROR_LABEL
55         /* Save the function pointer in EDX which is preserved by the
56            system call.  */
57         movl    FUNC(%esp), %edx        /* No NULL function pointer.  */
58         testl   %edx, %edx
59         jz      SYSCALL_ERROR_LABEL
61         /* Save EBX and ESI.  */
62         pushl   %ebx
63         cfi_adjust_cfa_offset (4)
64         pushl   %esi
65         cfi_adjust_cfa_offset (4)
67         /* Save the function argument in ESI which is preserved by the
68            system call.  */
69         movl    (ARG + 8)(%esp), %esi
71         /* Put cl_args in EBX.  */
72         movl    %ecx, %ebx
74         /* Put size in ECX.  */
75         movl    (SIZE + 8)(%esp), %ecx
77         /* Do the system call.  */
78         movl    $SYS_ify(clone3), %eax
80         /* End FDE now, because in the child the unwind info will be
81            wrong.  */
82         cfi_endproc
84         int     $0x80
85         test    %eax, %eax
86         /* No need to restore EBX and ESI in child.  */
87         jz      L(thread_start)
89         /* Restore EBX and ESI in parent.  */
90         pop     %esi
91         pop     %ebx
92         jl      SYSCALL_ERROR_LABEL
94         ret
96 L(thread_start):
97         cfi_startproc
98         /* Clearing frame pointer is insufficient, use CFI.  */
99         cfi_undefined (eip)
100         xorl    %ebp, %ebp      /* Terminate the stack frame.  */
102         /* Align stack to 16 bytes per the i386 psABI.  */
103         andl    $-16, %esp
105         /* The PUSH below will decrement stack pointer by 4 bytes.  */
106         subl    $12, %esp
108         /* Set up the argument for the function call.  */
109         pushl   %esi            /* Argument.  */
110         cfi_adjust_cfa_offset (4)
111         call    *%edx           /* Call function.  */
113         /* Call exit with return value from function call. */
114         movl    %eax, %ebx
115         movl    $SYS_ify(exit), %eax
116         ENTER_KERNEL
117         cfi_endproc
119         cfi_startproc
120 PSEUDO_END (__clone3)
122 libc_hidden_def (__clone3)
123 weak_alias (__clone3, clone3)