1 | /* Create new context. |
2 | Copyright (C) 2001-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
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. |
9 | |
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. |
14 | |
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/>. */ |
18 | |
19 | #include <sysdep.h> |
20 | |
21 | #include "ucontext_i.h" |
22 | |
23 | |
24 | ENTRY(__makecontext) |
25 | movl 4(%esp), %eax |
26 | |
27 | /* Load the address of the function we are supposed to run. */ |
28 | movl 8(%esp), %ecx |
29 | |
30 | /* Compute the address of the stack. The information comes from |
31 | to us_stack element. */ |
32 | movl oSS_SP(%eax), %edx |
33 | movl %ecx, oEIP(%eax) |
34 | addl oSS_SIZE(%eax), %edx |
35 | |
36 | /* Remember the number of parameters for the exit handler since |
37 | it has to remove them. We store the number in the EBX register |
38 | which the function we will call must preserve. */ |
39 | movl 12(%esp), %ecx |
40 | movl %ecx, oEBX(%eax) |
41 | |
42 | /* Make room on the new stack for the parameters. |
43 | Room for the arguments, return address (== L(exitcode)) and |
44 | oLINK pointer is needed. One of the pointer sizes is subtracted |
45 | after aligning the stack. */ |
46 | negl %ecx |
47 | leal -4(%edx,%ecx,4), %edx |
48 | negl %ecx |
49 | |
50 | /* Align the stack. */ |
51 | andl $0xfffffff0, %edx |
52 | subl $4, %edx |
53 | |
54 | /* Store the future stack pointer. */ |
55 | movl %edx, oESP(%eax) |
56 | |
57 | /* Put the next context on the new stack (from the uc_link |
58 | element). */ |
59 | movl oLINK(%eax), %eax |
60 | movl %eax, 4(%edx,%ecx,4) |
61 | |
62 | /* Copy all the parameters. */ |
63 | jecxz 2f |
64 | 1: movl 12(%esp,%ecx,4), %eax |
65 | movl %eax, (%edx,%ecx,4) |
66 | decl %ecx |
67 | jnz 1b |
68 | 2: |
69 | |
70 | /* If the function we call returns we must continue with the |
71 | context which is given in the uc_link element. To do this |
72 | set the return address for the function the user provides |
73 | to a little bit of helper code which does the magic (see |
74 | below). */ |
75 | #ifdef PIC |
76 | call 1f |
77 | cfi_adjust_cfa_offset (4) |
78 | 1: popl %ecx |
79 | cfi_adjust_cfa_offset (-4) |
80 | addl $L(exitcode)-1b, %ecx |
81 | movl %ecx, (%edx) |
82 | #else |
83 | movl $L(exitcode), (%edx) |
84 | #endif |
85 | /* We need to terminate the FDE here instead of after ret because |
86 | the unwinder looks at ra-1 for unwind information. */ |
87 | cfi_endproc |
88 | |
89 | /* 'makecontext' returns no value. */ |
90 | ret |
91 | |
92 | /* This is the helper code which gets called if a function which |
93 | is registered with 'makecontext' returns. In this case we |
94 | have to install the context listed in the uc_link element of |
95 | the context 'makecontext' manipulated at the time of the |
96 | 'makecontext' call. If the pointer is NULL the process must |
97 | terminate. */ |
98 | L(exitcode): |
99 | /* This removes the parameters passed to the function given to |
100 | 'makecontext' from the stack. EBX contains the number of |
101 | parameters (see above). */ |
102 | leal (%esp,%ebx,4), %esp |
103 | |
104 | cmpl $0, (%esp) /* Check the next context. */ |
105 | je 2f /* If it is zero exit. */ |
106 | |
107 | call HIDDEN_JUMPTARGET(__setcontext) |
108 | /* If this returns (which can happen if the syscall fails) we'll |
109 | exit the program with the return error value (-1). */ |
110 | jmp L(call_exit) |
111 | |
112 | 2: |
113 | /* Exit with status 0. */ |
114 | xorl %eax, %eax |
115 | |
116 | L(call_exit): |
117 | /* Align the stack and pass the exit code (from %eax). */ |
118 | andl $0xfffffff0, %esp |
119 | subl $12, %esp |
120 | pushl %eax |
121 | |
122 | call HIDDEN_JUMPTARGET(exit) |
123 | /* The 'exit' call should never return. In case it does cause |
124 | the process to terminate. */ |
125 | hlt |
126 | cfi_startproc |
127 | END(__makecontext) |
128 | |
129 | weak_alias (__makecontext, makecontext) |
130 | |