1/* PLT trampolines. hppa 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#include <sysdep.h>
20
21/* This code gets called via the .plt stub, and is used in
22 dl-runtime.c to call the `_dl_fixup' function and then redirect
23 to the address it returns. `_dl_fixup' takes two arguments, however
24 `_dl_profile_fixup' takes a number of parameters for use with
25 library auditing (LA).
26
27 WARNING: This template is also used by gcc's __cffc, and expects
28 that the "bl" for _dl_runtime_resolve exist at a particular offset.
29 Do not change this template without changing gcc, while the prefix
30 "bl" should fix everything so gcc finds the right spot, it will
31 slow down __cffc when it attempts to call fixup to resolve function
32 descriptor references. Please refer to gcc/gcc/config/pa/fptr.c
33
34 Enter with r19 = reloc offset, r20 = got-8, r21 = fixup ltp, r22 = fp. */
35
36 /* RELOCATION MARKER: bl to provide gcc's __cffc with fixup loc. */
37 .text
38 /* THIS CODE DOES NOT EXECUTE */
39 bl _dl_fixup, %r2
40 .text
41 .global _dl_runtime_resolve
42 .type _dl_runtime_resolve,@function
43 cfi_startproc
44 .align 4
45_dl_runtime_resolve:
46 .PROC
47 .CALLINFO FRAME=128,CALLS,SAVE_RP,ENTRY_GR=3
48 .ENTRY
49 /* SAVE_RP says we do */
50 stw %rp, -20(%sp)
51
52 /* Save static link register */
53 stw %r29,-16(%sp)
54 /* Save argument registers */
55 stw %r26,-36(%sp)
56 stw %r25,-40(%sp)
57 stw %r24,-44(%sp)
58 stw %r23,-48(%sp)
59
60 /* Build a call frame, and save structure pointer. */
61 copy %sp, %r1 /* Copy previous sp */
62 /* Save function result address (on entry) */
63 stwm %r28,128(%sp)
64 /* Fill in some frame info to follow ABI */
65 stw %r1,-4(%sp) /* Previous sp */
66 stw %r21,-32(%sp) /* PIC register value */
67
68 /* Save input floating point registers. This must be done
69 in the new frame since the previous frame doesn't have
70 enough space */
71 ldo -64(%sp),%r1
72 fstd,ma %fr4,-8(%r1)
73 fstd,ma %fr5,-8(%r1)
74 fstd,ma %fr6,-8(%r1)
75
76 /* Test PA_GP_RELOC bit. */
77 bb,>= %r19,31,2f /* branch if not reloc offset */
78 fstd,ma %fr7,-8(%r1)
79
80 /* Set up args to fixup func, needs only two arguments */
81 ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */
82 copy %r19,%r25 /* (2) reloc offset */
83
84 /* Call the real address resolver. */
853: bl _dl_fixup,%rp
86 copy %r21,%r19 /* set fixup func ltp */
87
88 /* While the linker will set a function pointer to NULL when it
89 encounters an undefined weak function, we need to dynamically
90 detect removed weak functions. The issue arises because a weak
91 __gmon_start__ function was added to shared executables to work
92 around issues in _init that are now resolved. The presence of
93 __gmon_start__ in every shared library breaks the linker
94 `--as-needed' option. This __gmon_start__ function does nothing
95 but removal is tricky. Depending on the binding, removal can
96 cause an application using it to fault. The call to _dl_fixup
97 returns NULL when a function isn't resolved. In order to help
98 with __gmon_start__ removal, we return directly to the caller
99 when _dl_fixup returns NULL. This check could be removed when
100 BZ 19170 is fixed. */
101 comib,= 0,%r28,1f
102
103 /* Load up the returned func descriptor */
104 copy %r28, %r22
105 copy %r29, %r19
106
107 /* Reload arguments fp args */
108 ldo -64(%sp),%r1
109 fldd,ma -8(%r1),%fr4
110 fldd,ma -8(%r1),%fr5
111 fldd,ma -8(%r1),%fr6
112 fldd,ma -8(%r1),%fr7
113
114 /* Adjust sp, and restore function result address*/
115 ldwm -128(%sp),%r28
116
117 /* Reload static link register */
118 ldw -16(%sp),%r29
119 /* Reload general args */
120 ldw -36(%sp),%r26
121 ldw -40(%sp),%r25
122 ldw -44(%sp),%r24
123 ldw -48(%sp),%r23
124
125 /* Jump to new function, but return to previous function */
126 bv %r0(%r22)
127 ldw -20(%sp),%rp
128
1291:
130 /* Return to previous function */
131 ldw -148(%sp),%rp
132 bv %r0(%rp)
133 ldo -128(%sp),%sp
134
1352:
136 /* Set up args for _dl_fix_reloc_arg. */
137 copy %r22,%r26 /* (1) function pointer */
138 depi 0,31,2,%r26 /* clear least significant bits */
139 ldw 8+4(%r20),%r25 /* (2) got[1] == struct link_map */
140
141 /* Save ltp and link map arg for _dl_fixup. */
142 stw %r21,-56(%sp) /* ltp */
143 stw %r25,-60(%sp) /* struct link map */
144
145 /* Find reloc offset. */
146 bl _dl_fix_reloc_arg,%rp
147 copy %r21,%r19 /* set func ltp */
148
149 /* Set up args for _dl_fixup. */
150 ldw -56(%sp),%r21 /* ltp */
151 ldw -60(%sp),%r26 /* (1) struct link map */
152 b 3b
153 copy %ret0,%r25 /* (2) reloc offset */
154 .EXIT
155 .PROCEND
156 cfi_endproc
157 .size _dl_runtime_resolve, . - _dl_runtime_resolve
158
159 .text
160 .global _dl_runtime_profile
161 .type _dl_runtime_profile,@function
162 cfi_startproc
163 .align 4
164_dl_runtime_profile:
165 .PROC
166 .CALLINFO FRAME=192,CALLS,SAVE_RP,ENTRY_GR=3
167 .ENTRY
168
169 /* SAVE_RP says we do */
170 stw %rp, -20(%sp)
171 /* Save static link register */
172 stw %r29,-16(%sp)
173
174 /* Build a call frame, and save structure pointer. */
175 copy %sp, %r1 /* Copy previous sp */
176 /* Save function result address (on entry) */
177 stwm %r28,192(%sp)
178 /* Fill in some frame info to follow ABI */
179 stw %r1,-4(%sp) /* Previous sp */
180 stw %r21,-32(%sp) /* PIC register value */
181
182 /* Create La_hppa_retval */
183 /* -140, lrv_r28
184 -136, lrv_r29
185 -132, 4 byte pad
186 -128, lr_fr4 (8 bytes) */
187
188 /* Create save space for _dl_profile_fixup arguments
189 -120, Saved reloc offset
190 -116, Saved struct link_map
191 -112, *framesizep */
192
193 /* Create La_hppa_regs */
194 /* 32-bit registers */
195 stw %r26,-108(%sp)
196 stw %r25,-104(%sp)
197 stw %r24,-100(%sp)
198 stw %r23,-96(%sp)
199 /* -92, 4 byte pad */
200 /* 64-bit floating point registers */
201 ldo -88(%sp),%r1
202 fstd,ma %fr4,8(%r1)
203 fstd,ma %fr5,8(%r1)
204 fstd,ma %fr6,8(%r1)
205 fstd,ma %fr7,8(%r1)
206
207 /* Test PA_GP_RELOC bit. */
208 bb,>= %r19,31,2f /* branch if not reloc offset */
209 /* 32-bit stack pointer */
210 stw %sp,-56(%sp)
211
212 /* Set up args to fixup func, needs five arguments */
213 ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */
214 stw %r26,-116(%sp) /* Save struct link_map */
215 copy %r19,%r25 /* (2) reloc offset */
216 stw %r25,-120(%sp) /* Save reloc offset */
217 copy %rp,%r24 /* (3) profile_fixup needs rp */
218 ldo -56(%sp),%r23 /* (4) La_hppa_regs */
219 ldo -112(%sp), %r1
220 stw %r1, -52(%sp) /* (5) long int *framesizep */
221
222 /* Call the real address resolver. */
2233: bl _dl_profile_fixup,%rp
224 copy %r21,%r19 /* set fixup func ltp */
225
226 /* Load up the returned function descriptor */
227 copy %r28, %r22
228 copy %r29, %r19
229
230 /* Restore gr/fr/sp/rp */
231 ldw -108(%sp),%r26
232 ldw -104(%sp),%r25
233 ldw -100(%sp),%r24
234 ldw -96(%sp),%r23
235 /* -92, 4 byte pad, skip */
236 ldo -88(%sp),%r1
237 fldd,ma 8(%r1),%fr4
238 fldd,ma 8(%r1),%fr5
239 fldd,ma 8(%r1),%fr6
240 fldd,ma 8(%r1),%fr7
241
242 /* Reload rp register -(192+20) without adjusting stack */
243 ldw -212(%sp),%rp
244
245 /* Reload static link register -(192+16) without adjusting stack */
246 ldw -208(%sp),%r29
247
248 /* *framesizep is >= 0 if we have to run pltexit */
249 ldw -112(%sp),%r28
250 cmpb,>>=,N %r0,%r28,L(cpe)
251
252 /* Adjust sp, and restore function result address*/
253 ldwm -192(%sp),%r28
254 /* Jump to new function, but return to previous function */
255 bv %r0(%r22)
256 ldw -20(%sp),%rp
257 /* NO RETURN */
258
259L(nf):
260 /* Call the returned function descriptor */
261 bv %r0(%r22)
262 nop
263 b,n L(cont)
264
265L(cpe):
266 /* We are going to call the resolved function, but we have a
267 stack frame in the middle. We use the value of framesize to
268 guess how much extra frame we need, and how much frame to
269 copy forward. */
270
271 /* Round to nearest multiple of 64 */
272 addi 63, %r28, %r28
273 depi 0, 27, 6, %r28
274
275 /* Calcualte start of stack copy */
276 ldo -192(%sp),%r2
277
278 /* Increate the stack by *framesizep */
279 copy %sp, %r1
280 add %sp, %r28, %sp
281 /* Save stack pointer */
282 stw %r1, -4(%sp)
283
284 /* Single byte copy of prevous stack onto newly allocated stack */
2851: ldb %r28(%r2), %r1
286 add %r28, %sp, %r26
287 stb %r1, 0(%r26)
288 addi,< -1,%r28,%r28
289 b,n 1b
290
291 /* Retore r28 and r27 and r2 already points at -192(%sp) */
292 ldw 0(%r2),%r28
293 ldw 84(%r2),%r26
294
295 /* Calculate address of L(cont) */
296 b,l L(nf),%r2
297 depwi 0,31,2,%r2
298L(cont):
299 /* Undo fake stack */
300 ldw -4(%sp),%r1
301 copy %r1, %sp
302
303 /* Arguments to _dl_audit_pltexit */
304 ldw -116(%sp), %r26 /* (1) got[1] == struct link_map */
305 ldw -120(%sp), %r25 /* (2) reloc offsets */
306 ldo -56(%sp), %r24 /* (3) *La_hppa_regs */
307 ldo -124(%sp), %r23 /* (4) *La_hppa_retval */
308
309 /* Fill *La_hppa_retval */
310 stw %r28,-140(%sp)
311 stw %r29,-136(%sp)
312 ldo -128(%sp), %r1
313 fstd %fr4,0(%r1)
314
315 /* Call _dl_audit_pltexit */
316 bl _dl_audit_pltexit,%rp
317 nop
318
319 /* Restore *La_hppa_retval */
320 ldw -140(%sp), %r28
321 ldw -136(%sp), %r29
322 ldo -128(%sp), %r1
323 fldd 0(%r1), %fr4
324
325 /* Unwind the stack */
326 ldo 192(%sp),%sp
327 /* Retore callers rp */
328 ldw -20(%sp),%rp
329 /* Return */
330 bv,n 0(%r2)
331
3322:
333 /* Set up args for _dl_fix_reloc_arg. */
334 copy %r22,%r26 /* (1) function pointer */
335 depi 0,31,2,%r26 /* clear least significant bits */
336 ldw 8+4(%r20),%r25 /* (2) got[1] == struct link_map */
337
338 /* Save ltp and link map arg for _dl_fixup. */
339 stw %r21,-92(%sp) /* ltp */
340 stw %r25,-116(%sp) /* struct link map */
341
342 /* Find reloc offset. */
343 bl _dl_fix_reloc_arg,%rp
344 copy %r21,%r19 /* set func ltp */
345
346 /* Restore fixup ltp. */
347 ldw -92(%sp),%r21 /* ltp */
348
349 /* Set up args to fixup func, needs five arguments */
350 ldw -116(%sp),%r26 /* (1) struct link map */
351 copy %ret0,%r25 /* (2) reloc offset */
352 stw %r25,-120(%sp) /* Save reloc offset */
353 ldw -212(%sp),%r24 /* (3) profile_fixup needs rp */
354 ldo -56(%sp),%r23 /* (4) La_hppa_regs */
355 ldo -112(%sp), %r1
356 b 3b
357 stw %r1, -52(%sp) /* (5) long int *framesizep */
358 .EXIT
359 .PROCEND
360 cfi_endproc
361 .size _dl_runtime_profile, . - _dl_runtime_profile
362

source code of glibc/sysdeps/hppa/dl-trampoline.S