Blame sysdeps/unix/sysv/linux/i386/makecontext.S

Packit Service 82fcde
/* Create new context.
Packit Service 82fcde
   Copyright (C) 2001-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <sysdep.h>
Packit Service 82fcde
Packit Service 82fcde
#include "ucontext_i.h"
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
ENTRY(__makecontext)
Packit Service 82fcde
	movl	4(%esp), %eax
Packit Service 82fcde
Packit Service 82fcde
	/* Load the address of the function we are supposed to run.  */
Packit Service 82fcde
	movl	8(%esp), %ecx
Packit Service 82fcde
Packit Service 82fcde
	/* Compute the address of the stack.  The information comes from
Packit Service 82fcde
	   to us_stack element.  */
Packit Service 82fcde
	movl	oSS_SP(%eax), %edx
Packit Service 82fcde
	movl	%ecx, oEIP(%eax)
Packit Service 82fcde
	addl	oSS_SIZE(%eax), %edx
Packit Service 82fcde
Packit Service 82fcde
	/* Remember the number of parameters for the exit handler since
Packit Service 82fcde
	   it has to remove them.  We store the number in the EBX register
Packit Service 82fcde
	   which the function we will call must preserve.  */
Packit Service 82fcde
	movl	12(%esp), %ecx
Packit Service 82fcde
	movl	%ecx, oEBX(%eax)
Packit Service 82fcde
Packit Service 82fcde
	/* Make room on the new stack for the parameters.
Packit Service 82fcde
	   Room for the arguments, return address (== L(exitcode)) and
Packit Service 82fcde
	   oLINK pointer is needed.  One of the pointer sizes is subtracted
Packit Service 82fcde
	   after aligning the stack.  */
Packit Service 82fcde
	negl	%ecx
Packit Service 82fcde
	leal	-4(%edx,%ecx,4), %edx
Packit Service 82fcde
	negl	%ecx
Packit Service 82fcde
Packit Service 82fcde
	/* Align the stack.  */
Packit Service 82fcde
	andl	$0xfffffff0, %edx
Packit Service 82fcde
	subl	$4, %edx
Packit Service 82fcde
Packit Service 82fcde
	/* Store the future stack pointer.  */
Packit Service 82fcde
	movl	%edx, oESP(%eax)
Packit Service 82fcde
Packit Service 82fcde
	/* Put the next context on the new stack (from the uc_link
Packit Service 82fcde
	   element).  */
Packit Service 82fcde
	movl	oLINK(%eax), %eax
Packit Service 82fcde
	movl	%eax, 4(%edx,%ecx,4)
Packit Service 82fcde
Packit Service 82fcde
	/* Copy all the parameters.  */
Packit Service 82fcde
	jecxz	2f
Packit Service 82fcde
1:	movl	12(%esp,%ecx,4), %eax
Packit Service 82fcde
	movl	%eax, (%edx,%ecx,4)
Packit Service 82fcde
	decl	%ecx
Packit Service 82fcde
	jnz	1b
Packit Service 82fcde
2:
Packit Service 82fcde
Packit Service 82fcde
	/* If the function we call returns we must continue with the
Packit Service 82fcde
	   context which is given in the uc_link element.  To do this
Packit Service 82fcde
	   set the return address for the function the user provides
Packit Service 82fcde
	   to a little bit of helper code which does the magic (see
Packit Service 82fcde
	   below).  */
Packit Service 82fcde
#ifdef PIC
Packit Service 82fcde
	call	1f
Packit Service 82fcde
	cfi_adjust_cfa_offset (4)
Packit Service 82fcde
1:	popl	%ecx
Packit Service 82fcde
	cfi_adjust_cfa_offset (-4)
Packit Service 82fcde
	addl	$L(exitcode)-1b, %ecx
Packit Service 82fcde
	movl	%ecx, (%edx)
Packit Service 82fcde
#else
Packit Service 82fcde
	movl	$L(exitcode), (%edx)
Packit Service 82fcde
#endif
Packit Service 82fcde
	/* We need to terminate the FDE here instead of after ret because
Packit Service 82fcde
	   the unwinder looks at ra-1 for unwind information.  */
Packit Service 82fcde
	cfi_endproc
Packit Service 82fcde
Packit Service 82fcde
	/* 'makecontext' returns no value.  */
Packit Service 82fcde
	ret
Packit Service 82fcde
Packit Service 82fcde
	/* This is the helper code which gets called if a function which
Packit Service 82fcde
	   is registered with 'makecontext' returns.  In this case we
Packit Service 82fcde
	   have to install the context listed in the uc_link element of
Packit Service 82fcde
	   the context 'makecontext' manipulated at the time of the
Packit Service 82fcde
	   'makecontext' call.  If the pointer is NULL the process must
Packit Service 82fcde
	   terminate.  */
Packit Service 82fcde
L(exitcode):
Packit Service 82fcde
	/* This removes the parameters passed to the function given to
Packit Service 82fcde
	   'makecontext' from the stack.  EBX contains the number of
Packit Service 82fcde
	   parameters (see above).  */
Packit Service 82fcde
	leal	(%esp,%ebx,4), %esp
Packit Service 82fcde
Packit Service 82fcde
	cmpl	$0, (%esp)		/* Check the next context.  */
Packit Service 82fcde
	je	2f			/* If it is zero exit.  */
Packit Service 82fcde
Packit Service 82fcde
	call	HIDDEN_JUMPTARGET(__setcontext)
Packit Service 82fcde
	/* If this returns (which can happen if the syscall fails) we'll
Packit Service 82fcde
	   exit the program with the return error value (-1).  */
Packit Service 82fcde
	jmp L(call_exit)
Packit Service 82fcde
Packit Service 82fcde
2:
Packit Service 82fcde
	/* Exit with status 0.  */
Packit Service 82fcde
	xorl	%eax, %eax
Packit Service 82fcde
Packit Service 82fcde
L(call_exit):
Packit Service 82fcde
	/* Align the stack and pass the exit code (from %eax).  */
Packit Service 82fcde
	andl	$0xfffffff0, %esp
Packit Service 82fcde
	subl	$12, %esp
Packit Service 82fcde
	pushl	%eax
Packit Service 82fcde
Packit Service 82fcde
	call	HIDDEN_JUMPTARGET(exit)
Packit Service 82fcde
	/* The 'exit' call should never return.  In case it does cause
Packit Service 82fcde
	   the process to terminate.  */
Packit Service 82fcde
	hlt
Packit Service 82fcde
	cfi_startproc
Packit Service 82fcde
END(__makecontext)
Packit Service 82fcde
Packit Service 82fcde
weak_alias (__makecontext, makecontext)