diff options
Diffstat (limited to 'libc/sysdeps/linux/i386')
-rw-r--r-- | libc/sysdeps/linux/i386/clone.S | 123 |
1 files changed, 84 insertions, 39 deletions
diff --git a/libc/sysdeps/linux/i386/clone.S b/libc/sysdeps/linux/i386/clone.S index 93183d208..d18d4edc2 100644 --- a/libc/sysdeps/linux/i386/clone.S +++ b/libc/sysdeps/linux/i386/clone.S @@ -1,75 +1,122 @@ -/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997,98,99,2000,02 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@tamu.edu) The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ /* clone() is even more special than fork() as it mucks with stacks - and invokes a function in the right context after its all over. */ + and invokes a function in the right context after its all over. + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +*/ +#define _ERRNO_H 1 #include <bits/errno.h> #include <sys/syscall.h> -.text -.align 4 -.type __clone,@function -.globl __clone; +#define LINKAGE 4 +#define PTR_SIZE 4 +#define PARMS LINKAGE /* no space for saved regs */ +#define FUNC PARMS +#define STACK FUNC+4 +#define FLAGS STACK+PTR_SIZE +#define ARG FLAGS+4 +#define PTID ARG+PTR_SIZE +#define TLS PTID+PTR_SIZE +#define CTID TLS+PTR_SIZE + + + .text + .globl __clone; + .type __clone,@function; + .align 1<<4; + __clone: /* Sanity check arguments. */ - movl 4(%esp),%ecx /* no NULL function pointers */ - jecxz CLONE_ERROR_LABEL - - movl 8(%esp),%ecx /* no NULL stack pointers */ - jecxz CLONE_ERROR_LABEL + movl $-EINVAL,%eax + movl FUNC(%esp),%ecx /* no NULL function pointers */ +#ifdef __PIC__ + jecxz __syscall_error +#else + testl %ecx,%ecx + jz __syscall_error +#endif + movl STACK(%esp),%ecx /* no NULL stack pointers */ +#ifdef __PIC__ + jecxz __syscall_error +#else + testl %ecx,%ecx + jz __syscall_error +#endif /* Insert the argument onto the new stack. */ - subl $8,%ecx - movl 16(%esp),%eax /* no negative argument counts */ - movl %eax,4(%ecx) + subl $16,%ecx + movl ARG(%esp),%eax /* no negative argument counts */ + movl %eax,12(%ecx) /* Save the function pointer as the zeroth argument. It will be popped off in the child in the ebx frobbing below. */ - movl 4(%esp),%eax - movl %eax,0(%ecx) + movl FUNC(%esp),%eax + movl %eax,8(%ecx) + /* Don't leak any information. */ + movl $0,4(%ecx) + movl $0,(%ecx) /* Do the system call */ pushl %ebx - movl 16(%esp),%ebx + pushl %esi + pushl %edi + movl TLS+12(%esp),%esi + movl PTID+12(%esp),%edx + movl FLAGS+12(%esp),%ebx + movl CTID+12(%esp),%edi movl $__NR_clone,%eax int $0x80 + popl %edi + popl %esi popl %ebx test %eax,%eax - jl CLONE_ERROR_LABEL - jne CLONE_RETURN_LABEL + jl __syscall_error + jz .Lthread_start - /* Start thread */ +.Lpseudo_end: + ret + +.Lthread_start: subl %ebp,%ebp /* terminate the stack frame */ call *%ebx - pushl %eax - call _exit +#ifdef __PIC__ + call .Lhere +.Lhere: + popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-.Lhere], %ebx +#endif + movl %eax, %ebx + movl $__NR_exit, %eax + int $0x80 -CLONE_ERROR_LABEL: +__syscall_error: negl %eax pushl %eax #ifdef __PIC__ - call .Lhere -.Lhere: + call .Lthere +.Lthere: popl %ebx - addl $_GLOBAL_OFFSET_TABLE_+[.- .Lhere ], %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.- .Lthere ], %ebx call __errno_location@PLT #else call __errno_location @@ -79,9 +126,7 @@ CLONE_ERROR_LABEL: xorl %eax, %eax decl %eax -CLONE_RETURN_LABEL: - ret - -.globl clone; - clone = __clone +.Lsize: + .size __clone,.Lsize-__clone +.weak clone ; clone = __clone |