1/* PLT trampolines. PPC64 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#include <rtld-global-offsets.h> 21 22 23 .section ".text" 24/* On entry r0 contains the index of the PLT entry we need to fixup 25 and r11 contains the link_map (from PLT0+16). The link_map becomes 26 parm1 (r3) and the index (r0) need to be converted to an offset 27 (index * 24) in parm2 (r4). */ 28 29#define FRAME_SIZE (FRAME_MIN_SIZE+64) 30/* We need to save the registers used to pass parameters, ie. r3 thru 31 r10; Use local var space rather than the parameter save area, 32 because gcc as of 2010/05 doesn't allocate a proper stack frame for 33 a function that makes no calls except for __tls_get_addr and we 34 might be here resolving the __tls_get_addr call. */ 35 .hidden _dl_runtime_resolve 36#define INT_PARMS FRAME_MIN_SIZE 37ENTRY (_dl_runtime_resolve, 4) 38 stdu r1,-FRAME_SIZE(r1) 39 cfi_adjust_cfa_offset (FRAME_SIZE) 40 std r3,INT_PARMS+0(r1) 41 mr r3,r11 42 std r4,INT_PARMS+8(r1) 43 sldi r4,r0,1 44 std r5,INT_PARMS+16(r1) 45 add r4,r4,r0 46 std r6,INT_PARMS+24(r1) 47 sldi r4,r4,3 48 std r7,INT_PARMS+32(r1) 49 mflr r0 50 std r8,INT_PARMS+40(r1) 51/* Store the LR in the LR Save area. */ 52 std r0,FRAME_SIZE+FRAME_LR_SAVE(r1) 53 cfi_offset (lr, FRAME_LR_SAVE) 54 std r9,INT_PARMS+48(r1) 55 std r10,INT_PARMS+56(r1) 56 bl JUMPTARGET(_dl_fixup) 57#ifndef SHARED 58 nop 59#endif 60/* Put the registers back. */ 61 ld r0,FRAME_SIZE+FRAME_LR_SAVE(r1) 62 ld r10,INT_PARMS+56(r1) 63 ld r9,INT_PARMS+48(r1) 64 ld r8,INT_PARMS+40(r1) 65 ld r7,INT_PARMS+32(r1) 66 mtlr r0 67 ld r6,INT_PARMS+24(r1) 68 ld r5,INT_PARMS+16(r1) 69 ld r4,INT_PARMS+8(r1) 70/* Prepare for calling the function returned by fixup. */ 71 PPC64_LOAD_FUNCPTR r3 72 ld r3,INT_PARMS+0(r1) 73#if _CALL_ELF == 2 74/* Restore the caller's TOC in case we jump to a local entry point. */ 75 ld r2,FRAME_SIZE+FRAME_TOC_SAVE(r1) 76#endif 77/* Unwind the stack frame, and jump. */ 78 addi r1,r1,FRAME_SIZE 79 bctr 80END(_dl_runtime_resolve) 81#undef FRAME_SIZE 82#undef INT_PARMS 83 84 /* Stack layout: ELFv2 ABI. 85 +752 previous backchain 86 +744 spill_r31 87 +736 spill_r30 88 +720 v8 89 +704 v7 90 +688 v6 91 +672 v5 92 +656 v4 93 +640 v3 94 +624 v2 95 +608 v1 96 +600 fp10 97 ELFv1 ABI +592 fp9 98 +592 previous backchain +584 fp8 99 +584 spill_r31 +576 fp7 100 +576 spill_r30 +568 fp6 101 +560 v1 +560 fp5 102 +552 fp4 +552 fp4 103 +544 fp3 +544 fp3 104 +536 fp2 +536 fp2 105 +528 fp1 +528 fp1 106 +520 r4 +520 r4 107 +512 r3 +512 r3 108 return values 109 +504 free 110 +496 stackframe 111 +488 lr 112 +480 r1 113 +464 v13 114 +448 v12 115 +432 v11 116 +416 v10 117 +400 v9 118 +384 v8 119 +368 v7 120 +352 v6 121 +336 v5 122 +320 v4 123 +304 v3 124 +288 v2 125 * VMX Parms in V2-V13, V0-V1 are scratch 126 +284 vrsave 127 +280 free 128 +272 fp13 129 +264 fp12 130 +256 fp11 131 +248 fp10 132 +240 fp9 133 +232 fp8 134 +224 fp7 135 +216 fp6 136 +208 fp5 137 +200 fp4 138 +192 fp3 139 +184 fp2 140 +176 fp1 141 * FP Parms in FP1-FP13, FP0 is a scratch register 142 +168 r10 143 +160 r9 144 +152 r8 145 +144 r7 146 +136 r6 147 +128 r5 148 +120 r4 149 +112 r3 150 * Integer parms in R3-R10, R0 is scratch, R1 SP, R2 is TOC 151 +104 parm8 152 +96 parm7 153 +88 parm6 154 +80 parm5 155 +72 parm4 156 +64 parm3 157 +56 parm2 158 +48 parm1 159 * Parameter save area 160 * (v1 ABI: Allocated by the call, at least 8 double words) 161 +40 v1 ABI: TOC save area 162 +32 v1 ABI: Reserved for linker 163 +24 v1 ABI: Reserved for compiler / v2 ABI: TOC save area 164 +16 LR save area 165 +8 CR save area 166 r1+0 stack back chain 167 */ 168#if _CALL_ELF == 2 169# define FRAME_SIZE 752 170# define VR_RTN 608 171#else 172# define FRAME_SIZE 592 173# define VR_RTN 560 174#endif 175#define INT_RTN 512 176#define FPR_RTN 528 177#define STACK_FRAME 496 178#define CALLING_LR 488 179#define CALLING_SP 480 180#define INT_PARMS 112 181#define FPR_PARMS 176 182#define VR_PARMS 288 183#define VR_VRSAVE 284 184 .section ".toc","aw" 185.LC__dl_hwcap: 186# ifdef SHARED 187 .tc _rtld_local_ro[TC],_rtld_local_ro 188# else 189 .tc _dl_hwcap[TC],_dl_hwcap 190# endif 191 .section ".text" 192 193 .machine "altivec" 194/* On entry r0 contains the index of the PLT entry we need to fixup 195 and r11 contains the link_map (from PLT0+16). The link_map becomes 196 parm1 (r3) and the index (r0) needs to be converted to an offset 197 (index * 24) in parm2 (r4). */ 198#ifndef PROF 199 .hidden _dl_profile_resolve 200ENTRY (_dl_profile_resolve, 4) 201/* Spill r30, r31 to preserve the link_map* and reloc_addr, in case we 202 need to call _dl_audit_pltexit. */ 203 std r31,-8(r1) 204 std r30,-16(r1) 205/* We need to save the registers used to pass parameters, ie. r3 thru 206 r10; the registers are saved in a stack frame. */ 207 stdu r1,-FRAME_SIZE(r1) 208 cfi_adjust_cfa_offset (FRAME_SIZE) 209 cfi_offset(r31,-8) 210 cfi_offset(r30,-16) 211 std r3,INT_PARMS+0(r1) 212 mr r3,r11 213 std r4,INT_PARMS+8(r1) 214 sldi r4,r0,1 /* index * 2 */ 215 std r5,INT_PARMS+16(r1) 216 add r4,r4,r0 /* index * 3 */ 217 std r6,INT_PARMS+24(r1) 218 sldi r4,r4,3 /* index * 24 == PLT offset */ 219 mflr r5 220 std r7,INT_PARMS+32(r1) 221 std r8,INT_PARMS+40(r1) 222/* Store the LR in the LR Save area. */ 223 la r8,FRAME_SIZE(r1) 224 std r5,FRAME_SIZE+FRAME_LR_SAVE(r1) 225 cfi_offset (lr, FRAME_LR_SAVE) 226 std r5,CALLING_LR(r1) 227 std r9,INT_PARMS+48(r1) 228 std r10,INT_PARMS+56(r1) 229 std r8,CALLING_SP(r1) 230 addis r12,r2,.LC__dl_hwcap@toc@ha 231 ld r12,.LC__dl_hwcap@toc@l(r12) 232#ifdef SHARED 233 /* Load _rtld_local_ro._dl_hwcap. */ 234 ld r12,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET(r12) 235#else 236 /* Load extern _dl_hwcap. */ 237 ld r12,0(r12) 238#endif 239 andis. r0,r12,(PPC_FEATURE_HAS_ALTIVEC >> 16) 240 beq L(saveFP) 241 la r10,(VR_PARMS+0)(r1) 242 la r9,(VR_PARMS+16)(r1) 243 li r11,32 244 li r12,64 245 stvx v2,0,r10 246 stvx v3,0,r9 247 248 stvx v4,r11,r10 249 stvx v5,r11,r9 250 addi r11,r11,64 251 252 stvx v6,r12,r10 253 stvx v7,r12,r9 254 addi r12,r12,64 255 256 stvx v8,r11,r10 257 stvx v9,r11,r9 258 addi r11,r11,64 259 260 stvx v10,r12,r10 261 stvx v11,r12,r9 262 mfspr r0,VRSAVE 263 264 stvx v12,r11,r10 265 stvx v13,r11,r9 266L(saveFP): 267 stw r0,VR_VRSAVE(r1) 268/* Save floating registers. */ 269 stfd fp1,FPR_PARMS+0(r1) 270 stfd fp2,FPR_PARMS+8(r1) 271 stfd fp3,FPR_PARMS+16(r1) 272 stfd fp4,FPR_PARMS+24(r1) 273 stfd fp5,FPR_PARMS+32(r1) 274 stfd fp6,FPR_PARMS+40(r1) 275 stfd fp7,FPR_PARMS+48(r1) 276 stfd fp8,FPR_PARMS+56(r1) 277 stfd fp9,FPR_PARMS+64(r1) 278 stfd fp10,FPR_PARMS+72(r1) 279 stfd fp11,FPR_PARMS+80(r1) 280 li r0,-1 281 stfd fp12,FPR_PARMS+88(r1) 282 stfd fp13,FPR_PARMS+96(r1) 283/* Load the extra parameters. */ 284 addi r6,r1,INT_PARMS 285 addi r7,r1,STACK_FRAME 286/* Save link_map* and reloc_addr parms for later. */ 287 mr r31,r3 288 mr r30,r4 289 std r0,0(r7) 290 bl JUMPTARGET(_dl_profile_fixup) 291#ifndef SHARED 292 nop 293#endif 294/* Test *framesizep > 0 to see if need to do pltexit processing. */ 295 ld r0,STACK_FRAME(r1) 296/* Put the registers back. */ 297 lwz r12,VR_VRSAVE(r1) 298 cmpdi cr1,r0,0 299 cmpdi cr0,r12,0 300 bgt cr1,L(do_pltexit) 301 la r10,(VR_PARMS+0)(r1) 302 la r9,(VR_PARMS+16)(r1) 303/* VRSAVE must be non-zero if VMX is present and VRs are in use. */ 304 beq L(restoreFXR) 305 li r11,32 306 li r12,64 307 lvx v2,0,r10 308 lvx v3,0,r9 309 310 lvx v4,r11,r10 311 lvx v5,r11,r9 312 addi r11,r11,64 313 314 lvx v6,r12,r10 315 lvx v7,r12,r9 316 addi r12,r12,64 317 318 lvx v8,r11,r10 319 lvx v9,r11,r9 320 addi r11,r11,64 321 322 lvx v10,r12,r10 323 lvx v11,r12,r9 324 325 lvx v12,r11,r10 326 lvx v13,r11,r9 327L(restoreFXR): 328 ld r0,FRAME_SIZE+FRAME_LR_SAVE(r1) 329 ld r10,INT_PARMS+56(r1) 330 ld r9,INT_PARMS+48(r1) 331 ld r8,INT_PARMS+40(r1) 332 ld r7,INT_PARMS+32(r1) 333 mtlr r0 334 ld r6,INT_PARMS+24(r1) 335 ld r5,INT_PARMS+16(r1) 336 ld r4,INT_PARMS+8(r1) 337/* Prepare for calling the function returned by fixup. */ 338 PPC64_LOAD_FUNCPTR r3 339 ld r3,INT_PARMS+0(r1) 340#if _CALL_ELF == 2 341/* Restore the caller's TOC in case we jump to a local entry point. */ 342 ld r2,FRAME_SIZE+FRAME_TOC_SAVE(r1) 343#endif 344/* Load the floating point registers. */ 345 lfd fp1,FPR_PARMS+0(r1) 346 lfd fp2,FPR_PARMS+8(r1) 347 lfd fp3,FPR_PARMS+16(r1) 348 lfd fp4,FPR_PARMS+24(r1) 349 lfd fp5,FPR_PARMS+32(r1) 350 lfd fp6,FPR_PARMS+40(r1) 351 lfd fp7,FPR_PARMS+48(r1) 352 lfd fp8,FPR_PARMS+56(r1) 353 lfd fp9,FPR_PARMS+64(r1) 354 lfd fp10,FPR_PARMS+72(r1) 355 lfd fp11,FPR_PARMS+80(r1) 356 lfd fp12,FPR_PARMS+88(r1) 357 lfd fp13,FPR_PARMS+96(r1) 358/* Unwind the stack frame, and jump. */ 359 ld r31,FRAME_SIZE-8(r1) 360 ld r30,FRAME_SIZE-16(r1) 361 addi r1,r1,FRAME_SIZE 362 bctr 363 364L(do_pltexit): 365 la r10,(VR_PARMS+0)(r1) 366 la r9,(VR_PARMS+16)(r1) 367 beq L(restoreFXR2) 368 li r11,32 369 li r12,64 370 lvx v2,0,r10 371 lvx v3,0,r9 372 373 lvx v4,r11,r10 374 lvx v5,r11,r9 375 addi r11,r11,64 376 377 lvx v6,r12,r10 378 lvx v7,r12,r9 379 addi r12,r12,64 380 381 lvx v8,r11,r10 382 lvx v9,r11,r9 383 addi r11,r11,64 384 385 lvx v10,r12,r10 386 lvx v11,r12,r9 387 388 lvx v12,r11,r10 389 lvx v13,r11,r9 390L(restoreFXR2): 391 ld r0,FRAME_SIZE+FRAME_LR_SAVE(r1) 392 ld r10,INT_PARMS+56(r1) 393 ld r9,INT_PARMS+48(r1) 394 ld r8,INT_PARMS+40(r1) 395 ld r7,INT_PARMS+32(r1) 396 mtlr r0 397 ld r6,INT_PARMS+24(r1) 398 ld r5,INT_PARMS+16(r1) 399 ld r4,INT_PARMS+8(r1) 400/* Prepare for calling the function returned by fixup. */ 401 std r2,FRAME_TOC_SAVE(r1) 402 PPC64_LOAD_FUNCPTR r3 403 ld r3,INT_PARMS+0(r1) 404/* Load the floating point registers. */ 405 lfd fp1,FPR_PARMS+0(r1) 406 lfd fp2,FPR_PARMS+8(r1) 407 lfd fp3,FPR_PARMS+16(r1) 408 lfd fp4,FPR_PARMS+24(r1) 409 lfd fp5,FPR_PARMS+32(r1) 410 lfd fp6,FPR_PARMS+40(r1) 411 lfd fp7,FPR_PARMS+48(r1) 412 lfd fp8,FPR_PARMS+56(r1) 413 lfd fp9,FPR_PARMS+64(r1) 414 lfd fp10,FPR_PARMS+72(r1) 415 lfd fp11,FPR_PARMS+80(r1) 416 lfd fp12,FPR_PARMS+88(r1) 417 lfd fp13,FPR_PARMS+96(r1) 418/* Call the target function. */ 419 bctrl 420 ld r2,FRAME_TOC_SAVE(r1) 421 lwz r12,VR_VRSAVE(r1) 422/* But return here and store the return values. */ 423 std r3,INT_RTN(r1) 424 std r4,INT_RTN+8(r1) 425 stfd fp1,FPR_RTN+0(r1) 426 stfd fp2,FPR_RTN+8(r1) 427 cmpdi cr0,r12,0 428 la r10,VR_RTN(r1) 429 stfd fp3,FPR_RTN+16(r1) 430 stfd fp4,FPR_RTN+24(r1) 431#if _CALL_ELF == 2 432 la r12,VR_RTN+16(r1) 433 stfd fp5,FPR_RTN+32(r1) 434 stfd fp6,FPR_RTN+40(r1) 435 li r5,32 436 li r6,64 437 stfd fp7,FPR_RTN+48(r1) 438 stfd fp8,FPR_RTN+56(r1) 439 stfd fp9,FPR_RTN+64(r1) 440 stfd fp10,FPR_RTN+72(r1) 441#endif 442 mr r3,r31 443 mr r4,r30 444 beq L(callpltexit) 445 stvx v2,0,r10 446#if _CALL_ELF == 2 447 stvx v3,0,r12 448 stvx v4,r5,r10 449 stvx v5,r5,r12 450 addi r5,r5,64 451 stvx v6,r6,r10 452 stvx v7,r6,r12 453 stvx v8,r5,r10 454 stvx v9,r5,r12 455#endif 456L(callpltexit): 457 addi r5,r1,INT_PARMS 458 addi r6,r1,INT_RTN 459 bl JUMPTARGET(_dl_audit_pltexit) 460#ifndef SHARED 461 nop 462#endif 463/* Restore the return values from target function. */ 464 lwz r12,VR_VRSAVE(r1) 465 ld r3,INT_RTN(r1) 466 ld r4,INT_RTN+8(r1) 467 lfd fp1,FPR_RTN+0(r1) 468 lfd fp2,FPR_RTN+8(r1) 469 cmpdi cr0,r12,0 470 la r11,VR_RTN(r1) 471 lfd fp3,FPR_RTN+16(r1) 472 lfd fp4,FPR_RTN+24(r1) 473#if _CALL_ELF == 2 474 la r12,VR_RTN+16(r1) 475 lfd fp5,FPR_RTN+32(r1) 476 lfd fp6,FPR_RTN+40(r1) 477 li r30,32 478 li r31,64 479 lfd fp7,FPR_RTN+48(r1) 480 lfd fp8,FPR_RTN+56(r1) 481 lfd fp9,FPR_RTN+64(r1) 482 lfd fp10,FPR_RTN+72(r1) 483#endif 484 beq L(pltexitreturn) 485 lvx v2,0,r11 486#if _CALL_ELF == 2 487 lvx v3,0,r12 488 lvx v4,r30,r11 489 lvx v5,r30,r12 490 addi r30,r30,64 491 lvx v6,r31,r11 492 lvx v7,r31,r12 493 lvx v8,r30,r11 494 lvx v9,r30,r12 495#endif 496L(pltexitreturn): 497 ld r0,FRAME_SIZE+FRAME_LR_SAVE(r1) 498 ld r31,FRAME_SIZE-8(r1) 499 ld r30,FRAME_SIZE-16(r1) 500 mtlr r0 501 ld r1,0(r1) 502 blr 503END(_dl_profile_resolve) 504#endif 505