1/* PLT trampolines.  ARM version.
2   Copyright (C) 2005-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/* ??? Needs more rearrangement for the LDM to handle thumb mode.  */
20#define NO_THUMB
21#include <sysdep.h>
22#include <libc-symbols.h>
23
24	.text
25	.globl _dl_runtime_resolve
26	.type _dl_runtime_resolve, #function
27	CFI_SECTIONS
28	cfi_startproc
29	.align 2
30_dl_runtime_resolve:
31	cfi_adjust_cfa_offset (4)
32	cfi_rel_offset (lr, 0)
33
34	@ we get called with
35	@ 	stack[0] contains the return address from this call
36	@	ip contains &GOT[n+3] (pointer to function)
37	@	lr points to &GOT[2]
38
39	@ Save arguments.  We save r4 to realign the stack.
40	push	{r0-r4}
41	cfi_adjust_cfa_offset (20)
42	cfi_rel_offset (r0, 0)
43	cfi_rel_offset (r1, 4)
44	cfi_rel_offset (r2, 8)
45	cfi_rel_offset (r3, 12)
46
47	@ get pointer to linker struct
48	ldr	r0, [lr, #-4]
49
50	@ prepare to call _dl_fixup()
51	@ change &GOT[n+3] into 8*n        NOTE: reloc are 8 bytes each
52	sub	r1, ip, lr
53	sub	r1, r1, #4
54	add	r1, r1, r1
55
56	@ call fixup routine
57	bl	_dl_fixup
58
59	@ save the return
60	mov	ip, r0
61
62	@ get arguments and return address back.  We restore r4
63	@ only to realign the stack.
64	pop	{r0-r4,lr}
65	cfi_adjust_cfa_offset (-24)
66
67	@ jump to the newly found address
68	BX(ip)
69
70	cfi_endproc
71	.size _dl_runtime_resolve, .-_dl_runtime_resolve
72
73#ifndef PROF
74	.globl _dl_runtime_profile
75	.type _dl_runtime_profile, #function
76	CFI_SECTIONS
77	cfi_startproc
78	.align 2
79_dl_runtime_profile:
80	cfi_adjust_cfa_offset (4)
81	cfi_rel_offset (lr, 0)
82
83	@ we get called with
84	@ 	stack[0] contains the return address from this call
85	@	ip contains &GOT[n+3] (pointer to function)
86	@	lr points to &GOT[2]
87
88	@ Stack layout:
89	@ 212 - saved lr
90	@ 208 - framesize returned from pltenter
91	@ 16 - La_arm_regs
92	@ 8 - Saved two arguments to _dl_profile_fixup
93	@ 4 - Saved result of _dl_profile_fixup
94	@ 0 - outgoing argument to _dl_profile_fixup
95	@ For now, we only save the general purpose registers.
96
97	sub	sp, sp, #196
98	cfi_adjust_cfa_offset (196)
99	stmia	sp, {r0-r3}
100	cfi_rel_offset (r0, 0)
101	cfi_rel_offset (r1, 4)
102	cfi_rel_offset (r2, 8)
103	cfi_rel_offset (r3, 12)
104
105	sub	sp, sp, #16
106	cfi_adjust_cfa_offset (16)
107
108	@ Save sp and lr.
109	add	r0, sp, #216
110	str	r0, [sp, #32]
111	ldr	r2, [sp, #212]
112	str	r2, [sp, #36]
113
114	@ get pointer to linker struct
115	ldr	r0, [lr, #-4]
116
117	@ prepare to call _dl_profile_fixup()
118	@ change &GOT[n+3] into 8*n        NOTE: reloc are 8 bytes each
119	sub	r1, ip, lr
120	sub	r1, r1, #4
121	add	r1, r1, r1
122
123	@ Save these two arguments for pltexit.
124	add	r3, sp, #8
125	stmia	r3!, {r0,r1}
126
127	@ Set up extra args for _dl_profile_fixup.
128	@ r2 and r3 are already loaded.
129	add	ip, sp, #208
130	str	ip, [sp, #0]
131
132	@ call profiling fixup routine
133	bl	_dl_profile_fixup
134
135	@ The address to call is now in r0.
136
137	@ Check whether we're wrapping this function.
138	ldr	ip, [sp, #208]
139	cmp	ip, #0
140	bge	1f
141	cfi_remember_state
142
143	@ save the return
144	mov	ip, r0
145
146	@ get arguments and return address back
147	add	sp, sp, #16
148	cfi_adjust_cfa_offset (-16)
149	ldmia	sp, {r0-r3,sp,lr}
150	cfi_adjust_cfa_offset (-200)
151
152	@ jump to the newly found address
153	BX(ip)
154
155	cfi_restore_state
1561:
157	@ The new frame size is in ip.
158
159	@ New stack layout:
160	@ 268 - saved r7
161	@ 264 - saved result of _dl_profile_fixup
162	@ 72 - La_arm_regs
163	@ 64 - Saved two arguments to _dl_profile_fixup
164	@ 0 - La_arm_retval
165	@ For now, we only save the general purpose registers.
166
167	@ Build the new frame.
168	str	r7, [sp, #212]
169	cfi_rel_offset (r7, 212)
170	sub	r7, sp, #56
171	cfi_def_cfa_register (r7)
172	cfi_adjust_cfa_offset (56)
173	sub	sp, sp, ip
174	bic	sp, sp, #7
175
176	@ Save the _dl_profile_fixup result around the call to memcpy.
177	str	r0, [r7, #264]
178
179	@ Copy the stack arguments.
180	mov	r0, sp
181	add	r1, r7, #272
182	mov	r2, ip
183	bl	memcpy
184
185	@ Call the function.
186	add	ip, r7, #72
187	ldmia	ip, {r0-r3}
188	ldr	ip, [r7, #264]
189	BLX(ip)
190	stmia	r7, {r0-r3}
191
192	@ Call pltexit.
193	add	ip, r7, #64
194	ldmia	ip, {r0,r1}
195	add	r2, r7, #72
196	add	r3, r7, #0
197	bl	_dl_audit_pltexit
198
199	@ Return to caller.
200	ldmia	r7, {r0-r3}
201	mov	sp, r7
202	cfi_def_cfa_register (sp)
203	ldr	r7, [sp, #268]
204	ldr	lr, [sp, #92]
205	add	sp, sp, #272
206	cfi_adjust_cfa_offset (-272)
207	BX(lr)
208
209	cfi_endproc
210	.size _dl_runtime_profile, .-_dl_runtime_profile
211#endif
212	.previous
213