1/* PLT trampolines.  i386 version.
2   Copyright (C) 2004-2021 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#include <link-defines.h>
21
22	.text
23	.globl _dl_runtime_resolve
24	.type _dl_runtime_resolve, @function
25	cfi_startproc
26	.align 16
27_dl_runtime_resolve:
28	cfi_adjust_cfa_offset (8)
29	_CET_ENDBR
30	pushl %eax		# Preserve registers otherwise clobbered.
31	cfi_adjust_cfa_offset (4)
32	pushl %ecx
33	cfi_adjust_cfa_offset (4)
34	pushl %edx
35	cfi_adjust_cfa_offset (4)
36	movl 16(%esp), %edx	# Copy args pushed by PLT in register.  Note
37	movl 12(%esp), %eax	# that `fixup' takes its parameters in regs.
38	call _dl_fixup		# Call resolver.
39	popl %edx		# Get register content back.
40	cfi_adjust_cfa_offset (-4)
41	movl (%esp), %ecx
42	movl %eax, (%esp)	# Store the function address.
43	movl 4(%esp), %eax
44	ret $12			# Jump to function address.
45	cfi_endproc
46	.size _dl_runtime_resolve, .-_dl_runtime_resolve
47
48# The SHSTK compatible version.
49	.text
50	.globl _dl_runtime_resolve_shstk
51	.type _dl_runtime_resolve_shstk, @function
52	cfi_startproc
53	.align 16
54_dl_runtime_resolve_shstk:
55	cfi_adjust_cfa_offset (8)
56	_CET_ENDBR
57	pushl %eax		# Preserve registers otherwise clobbered.
58	cfi_adjust_cfa_offset (4)
59	pushl %edx
60	cfi_adjust_cfa_offset (4)
61	movl 12(%esp), %edx	# Copy args pushed by PLT in register.  Note
62	movl 8(%esp), %eax	# that `fixup' takes its parameters in regs.
63	call _dl_fixup		# Call resolver.
64	movl (%esp), %edx	# Get register content back.
65	movl %eax, %ecx		# Store the function address.
66	movl 4(%esp), %eax	# Get register content back.
67	addl $16, %esp		# Adjust stack: PLT1 + PLT2 + %eax + %edx
68	cfi_adjust_cfa_offset (-16)
69	jmp *%ecx		# Jump to function address.
70	cfi_endproc
71	.size _dl_runtime_resolve_shstk, .-_dl_runtime_resolve_shstk
72
73#ifndef PROF
74# The SHSTK compatible version.
75	.globl _dl_runtime_profile_shstk
76	.type _dl_runtime_profile_shstk, @function
77	cfi_startproc
78	.align 16
79_dl_runtime_profile_shstk:
80	cfi_adjust_cfa_offset (8)
81	_CET_ENDBR
82	pushl %esp
83	cfi_adjust_cfa_offset (4)
84	addl $8, (%esp)		# Account for the pushed PLT data
85	pushl %ebp
86	cfi_adjust_cfa_offset (4)
87	pushl %eax		# Preserve registers otherwise clobbered.
88	cfi_adjust_cfa_offset (4)
89	pushl %ecx
90	cfi_adjust_cfa_offset (4)
91	pushl %edx
92	cfi_adjust_cfa_offset (4)
93	movl %esp, %ecx
94	subl $8, %esp
95	cfi_adjust_cfa_offset (8)
96	movl $-1, 4(%esp)
97	leal 4(%esp), %edx
98	movl %edx, (%esp)
99	pushl %ecx		# Address of the register structure
100	cfi_adjust_cfa_offset (4)
101	movl 40(%esp), %ecx	# Load return address
102	movl 36(%esp), %edx	# Copy args pushed by PLT in register.  Note
103	movl 32(%esp), %eax	# that `fixup' takes its parameters in regs.
104	call _dl_profile_fixup	# Call resolver.
105	cfi_adjust_cfa_offset (-8)
106	movl (%esp), %edx
107	testl %edx, %edx
108	jns 1f
109	movl 4(%esp), %edx	# Get register content back.
110	movl %eax, %ecx		# Store the function address.
111	movl 12(%esp), %eax	# Get register content back.
112	# Adjust stack: PLT1 + PLT2 + %esp + %ebp + %eax + %ecx + %edx
113	# + free.
114	addl $32, %esp
115	cfi_adjust_cfa_offset (-32)
116	jmp *%ecx		# Jump to function address.
117	cfi_endproc
118	.size _dl_runtime_profile_shstk, .-_dl_runtime_profile_shstk
119
120	.globl _dl_runtime_profile
121	.type _dl_runtime_profile, @function
122	cfi_startproc
123	.align 16
124_dl_runtime_profile:
125	cfi_adjust_cfa_offset (8)
126	_CET_ENDBR
127	pushl %esp
128	cfi_adjust_cfa_offset (4)
129	addl $8, (%esp)		# Account for the pushed PLT data
130	pushl %ebp
131	cfi_adjust_cfa_offset (4)
132	pushl %eax		# Preserve registers otherwise clobbered.
133	cfi_adjust_cfa_offset (4)
134	pushl %ecx
135	cfi_adjust_cfa_offset (4)
136	pushl %edx
137	cfi_adjust_cfa_offset (4)
138	movl %esp, %ecx
139	subl $8, %esp
140	cfi_adjust_cfa_offset (8)
141	movl $-1, 4(%esp)
142	leal 4(%esp), %edx
143	movl %edx, (%esp)
144	pushl %ecx		# Address of the register structure
145	cfi_adjust_cfa_offset (4)
146	movl 40(%esp), %ecx	# Load return address
147	movl 36(%esp), %edx	# Copy args pushed by PLT in register.  Note
148	movl 32(%esp), %eax	# that `fixup' takes its parameters in regs.
149	call _dl_profile_fixup	# Call resolver.
150	cfi_adjust_cfa_offset (-8)
151	movl (%esp), %edx
152	testl %edx, %edx
153	jns 1f
154	popl %edx
155	cfi_adjust_cfa_offset (-4)
156	popl %edx		# Get register content back.
157	cfi_adjust_cfa_offset (-4)
158	movl (%esp), %ecx
159	movl %eax, (%esp)	# Store the function address.
160	movl 4(%esp), %eax
161	ret $20			# Jump to function address.
162
163	/*
164	    +32     return address
165	    +28     PLT1
166	    +24     PLT2
167	    +20     %esp
168	    +16     %ebp
169	    +12     %eax
170	    +8      %ecx
171	    +4      %edx
172	   %esp     free
173	*/
174	cfi_adjust_cfa_offset (8)
1751:	movl %ebx, (%esp)
176	cfi_rel_offset (ebx, 0)
177	movl %edx, %ebx		# This is the frame buffer size
178	pushl %edi
179	cfi_adjust_cfa_offset (4)
180	cfi_rel_offset (edi, 0)
181	pushl %esi
182	cfi_adjust_cfa_offset (4)
183	cfi_rel_offset (esi, 0)
184	leal 44(%esp), %esi
185	movl %ebx, %ecx
186	orl $4, %ebx		# Increase frame size if necessary to align
187				# stack for the function call
188	andl $~3, %ebx
189	movl %esp, %edi
190	subl %ebx, %edi
191	movl %esp, %ebx
192	cfi_def_cfa_register (ebx)
193	movl %edi, %esp
194	shrl $2, %ecx
195	rep
196	movsl
197	movl (%ebx), %esi
198	cfi_restore (esi)
199	movl 4(%ebx), %edi
200	cfi_restore (edi)
201	/*
202	   %ebx+40  return address
203	   %ebx+36  PLT1
204	   %ebx+32  PLT2
205	   %ebx+28  %esp
206	   %ebx+24  %ebp
207	   %ebx+20  %eax
208	   %ebx+16  %ecx
209	   %ebx+12  %edx
210	   %ebx+8   %ebx
211	   %ebx+4   free
212	   %ebx     free
213	   %esp     copied stack frame
214	*/
215	movl %eax, (%ebx)
216	movl 12(%ebx), %edx
217	movl 16(%ebx), %ecx
218	movl 20(%ebx), %eax
219	call *(%ebx)
220	movl %ebx, %esp
221	cfi_def_cfa_register (esp)
222	movl 8(%esp), %ebx
223	cfi_restore (ebx)
224	/*
225	    +40     return address
226	    +36     PLT1
227	    +32     PLT2
228	    +28     %esp
229	    +24     %ebp
230	    +20     %eax
231	    +16     %ecx
232	    +12     %edx
233	    +8      free
234	    +4      free
235	   %esp     free
236	*/
237#if LONG_DOUBLE_SIZE != 12
238# error "long double size must be 12 bytes"
239#endif
240	# Allocate space for La_i86_retval and subtract 12 free bytes.
241	subl $(LRV_SIZE - 12), %esp
242	cfi_adjust_cfa_offset (LRV_SIZE - 12)
243	movl %eax, LRV_EAX_OFFSET(%esp)
244	movl %edx, LRV_EDX_OFFSET(%esp)
245	fstpt LRV_ST0_OFFSET(%esp)
246	fstpt LRV_ST1_OFFSET(%esp)
247	pushl %esp
248	cfi_adjust_cfa_offset (4)
249	# Address of La_i86_regs area.
250	leal (LRV_SIZE + 4)(%esp), %ecx
251	# PLT2
252	movl (LRV_SIZE + 4 + LR_SIZE)(%esp), %eax
253	# PLT1
254	movl (LRV_SIZE + 4 + LR_SIZE + 4)(%esp), %edx
255	call _dl_audit_pltexit
256	movl LRV_EAX_OFFSET(%esp), %eax
257	movl LRV_EDX_OFFSET(%esp), %edx
258	fldt LRV_ST1_OFFSET(%esp)
259	fldt LRV_ST0_OFFSET(%esp)
260	# Restore stack before return.
261	addl $(LRV_SIZE + 4 + LR_SIZE + 4), %esp
262	cfi_adjust_cfa_offset (-(LRV_SIZE + 4 + LR_SIZE + 4))
263	ret
264	cfi_endproc
265	.size _dl_runtime_profile, .-_dl_runtime_profile
266#endif
267