]>
Commit | Line | Data |
---|---|---|
084442fc | 1 | /* PLT trampolines. hppa version. |
6d7e8eda | 2 | Copyright (C) 2005-2023 Free Software Foundation, Inc. |
084442fc CD |
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 | |
ab84e3ff | 16 | License along with the GNU C Library. If not, see |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
084442fc CD |
18 | |
19 | #include <sysdep.h> | |
20 | ||
21 | /* This code gets called via the .plt stub, and is used in | |
5556231d JM |
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 | |
0daa0500 | 25 | library auditing (LA). |
5556231d | 26 | |
084442fc CD |
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 | |
5556231d | 33 | |
1a044511 | 34 | Enter with r19 = reloc offset, r20 = got-8, r21 = fixup ltp, r22 = fp. */ |
084442fc | 35 | |
0daa0500 | 36 | /* RELOCATION MARKER: bl to provide gcc's __cffc with fixup loc. */ |
084442fc | 37 | .text |
0daa0500 | 38 | /* THIS CODE DOES NOT EXECUTE */ |
084442fc CD |
39 | bl _dl_fixup, %r2 |
40 | .text | |
084442fc CD |
41 | .global _dl_runtime_resolve |
42 | .type _dl_runtime_resolve,@function | |
0daa0500 CD |
43 | cfi_startproc |
44 | .align 4 | |
084442fc CD |
45 | _dl_runtime_resolve: |
46 | .PROC | |
47 | .CALLINFO FRAME=128,CALLS,SAVE_RP,ENTRY_GR=3 | |
48 | .ENTRY | |
49 | /* SAVE_RP says we do */ | |
0daa0500 | 50 | stw %rp, -20(%sp) |
084442fc CD |
51 | |
52 | /* Save static link register */ | |
53 | stw %r29,-16(%sp) | |
5abebba4 | 54 | /* Save argument registers */ |
084442fc CD |
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. */ | |
0daa0500 | 61 | copy %sp, %r1 /* Copy previous sp */ |
084442fc CD |
62 | /* Save function result address (on entry) */ |
63 | stwm %r28,128(%sp) | |
1a044511 | 64 | /* Fill in some frame info to follow ABI */ |
0daa0500 | 65 | stw %r1,-4(%sp) /* Previous sp */ |
084442fc | 66 | stw %r21,-32(%sp) /* PIC register value */ |
0daa0500 CD |
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 */ | |
1a044511 | 71 | ldo -64(%sp),%r1 |
0daa0500 CD |
72 | fstd,ma %fr4,-8(%r1) |
73 | fstd,ma %fr5,-8(%r1) | |
74 | fstd,ma %fr6,-8(%r1) | |
1a044511 JDA |
75 | |
76 | /* Test PA_GP_RELOC bit. */ | |
77 | bb,>= %r19,31,2f /* branch if not reloc offset */ | |
0daa0500 | 78 | fstd,ma %fr7,-8(%r1) |
084442fc | 79 | |
5abebba4 | 80 | /* Set up args to fixup func, needs only two arguments */ |
084442fc CD |
81 | ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */ |
82 | copy %r19,%r25 /* (2) reloc offset */ | |
83 | ||
5abebba4 | 84 | /* Call the real address resolver. */ |
1a044511 | 85 | 3: bl _dl_fixup,%rp |
084442fc CD |
86 | copy %r21,%r19 /* set fixup func ltp */ |
87 | ||
64a1daed JDA |
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. */ | |
1903b38c JDA |
101 | comib,= 0,%r28,1f |
102 | ||
084442fc | 103 | /* Load up the returned func descriptor */ |
0daa0500 CD |
104 | copy %r28, %r22 |
105 | copy %r29, %r19 | |
084442fc CD |
106 | |
107 | /* Reload arguments fp args */ | |
1a044511 | 108 | ldo -64(%sp),%r1 |
0daa0500 CD |
109 | fldd,ma -8(%r1),%fr4 |
110 | fldd,ma -8(%r1),%fr5 | |
111 | fldd,ma -8(%r1),%fr6 | |
112 | fldd,ma -8(%r1),%fr7 | |
084442fc CD |
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 | |
1903b38c JDA |
128 | |
129 | 1: | |
130 | /* Return to previous function */ | |
131 | ldw -148(%sp),%rp | |
132 | bv %r0(%rp) | |
133 | ldo -128(%sp),%sp | |
134 | ||
1a044511 JDA |
135 | 2: |
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 */ | |
084442fc CD |
154 | .EXIT |
155 | .PROCEND | |
0daa0500 | 156 | cfi_endproc |
084442fc CD |
157 | .size _dl_runtime_resolve, . - _dl_runtime_resolve |
158 | ||
084442fc | 159 | .text |
084442fc CD |
160 | .global _dl_runtime_profile |
161 | .type _dl_runtime_profile,@function | |
0daa0500 CD |
162 | cfi_startproc |
163 | .align 4 | |
084442fc CD |
164 | _dl_runtime_profile: |
165 | .PROC | |
0daa0500 | 166 | .CALLINFO FRAME=192,CALLS,SAVE_RP,ENTRY_GR=3 |
084442fc CD |
167 | .ENTRY |
168 | ||
169 | /* SAVE_RP says we do */ | |
0daa0500 | 170 | stw %rp, -20(%sp) |
084442fc CD |
171 | /* Save static link register */ |
172 | stw %r29,-16(%sp) | |
084442fc CD |
173 | |
174 | /* Build a call frame, and save structure pointer. */ | |
0daa0500 | 175 | copy %sp, %r1 /* Copy previous sp */ |
084442fc | 176 | /* Save function result address (on entry) */ |
0daa0500 | 177 | stwm %r28,192(%sp) |
1a044511 | 178 | /* Fill in some frame info to follow ABI */ |
0daa0500 | 179 | stw %r1,-4(%sp) /* Previous sp */ |
084442fc | 180 | stw %r21,-32(%sp) /* PIC register value */ |
0daa0500 CD |
181 | |
182 | /* Create La_hppa_retval */ | |
5556231d | 183 | /* -140, lrv_r28 |
0daa0500 | 184 | -136, lrv_r29 |
5556231d | 185 | -132, 4 byte pad |
0daa0500 CD |
186 | -128, lr_fr4 (8 bytes) */ |
187 | ||
188 | /* Create save space for _dl_profile_fixup arguments | |
5556231d JM |
189 | -120, Saved reloc offset |
190 | -116, Saved struct link_map | |
0daa0500 CD |
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) | |
0daa0500 | 206 | |
1a044511 JDA |
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) | |
084442fc | 211 | |
5abebba4 | 212 | /* Set up args to fixup func, needs five arguments */ |
084442fc | 213 | ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */ |
0daa0500 | 214 | stw %r26,-116(%sp) /* Save struct link_map */ |
084442fc | 215 | copy %r19,%r25 /* (2) reloc offset */ |
0daa0500 | 216 | stw %r25,-120(%sp) /* Save reloc offset */ |
084442fc | 217 | copy %rp,%r24 /* (3) profile_fixup needs rp */ |
0daa0500 CD |
218 | ldo -56(%sp),%r23 /* (4) La_hppa_regs */ |
219 | ldo -112(%sp), %r1 | |
084442fc CD |
220 | stw %r1, -52(%sp) /* (5) long int *framesizep */ |
221 | ||
5abebba4 | 222 | /* Call the real address resolver. */ |
1a044511 | 223 | 3: bl _dl_profile_fixup,%rp |
084442fc CD |
224 | copy %r21,%r19 /* set fixup func ltp */ |
225 | ||
0daa0500 CD |
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 | |
1a044511 JDA |
241 | |
242 | /* Reload rp register -(192+20) without adjusting stack */ | |
243 | ldw -212(%sp),%rp | |
0daa0500 CD |
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) | |
084442fc CD |
251 | |
252 | /* Adjust sp, and restore function result address*/ | |
0daa0500 | 253 | ldwm -192(%sp),%r28 |
084442fc CD |
254 | /* Jump to new function, but return to previous function */ |
255 | bv %r0(%r22) | |
256 | ldw -20(%sp),%rp | |
0daa0500 CD |
257 | /* NO RETURN */ |
258 | ||
259 | L(nf): | |
260 | /* Call the returned function descriptor */ | |
261 | bv %r0(%r22) | |
262 | nop | |
263 | b,n L(cont) | |
264 | ||
265 | L(cpe): | |
5556231d | 266 | /* We are going to call the resolved function, but we have a |
0daa0500 CD |
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 */ | |
285 | 1: 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 | |
298 | L(cont): | |
299 | /* Undo fake stack */ | |
300 | ldw -4(%sp),%r1 | |
301 | copy %r1, %sp | |
302 | ||
8c0664e2 | 303 | /* Arguments to _dl_audit_pltexit */ |
5556231d | 304 | ldw -116(%sp), %r26 /* (1) got[1] == struct link_map */ |
5abebba4 | 305 | ldw -120(%sp), %r25 /* (2) reloc offsets */ |
0daa0500 CD |
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 | ||
8c0664e2 AZ |
315 | /* Call _dl_audit_pltexit */ |
316 | bl _dl_audit_pltexit,%rp | |
0daa0500 CD |
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) | |
1a044511 JDA |
331 | |
332 | 2: | |
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 */ | |
084442fc CD |
358 | .EXIT |
359 | .PROCEND | |
186a83ab | 360 | cfi_endproc |
084442fc | 361 | .size _dl_runtime_profile, . - _dl_runtime_profile |