1 /* $NetBSD: ppc_reloc.c,v 1.10 2001/09/10 06:09:41 mycroft Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (C) 1998 Tsubai Masanari 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/param.h> 33 #include <sys/mman.h> 34 #include <sys/sysctl.h> 35 36 #include <errno.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 #include <machine/cpu.h> 42 #include <machine/md_var.h> 43 44 #include "debug.h" 45 #include "rtld.h" 46 47 #if !defined(_CALL_ELF) || _CALL_ELF == 1 48 struct funcdesc { 49 Elf_Addr addr; 50 Elf_Addr toc; 51 Elf_Addr env; 52 }; 53 #endif 54 55 bool 56 arch_digest_dynamic(struct Struct_Obj_Entry *obj, const Elf_Dyn *dynp) 57 { 58 if (dynp->d_tag == DT_PPC64_GLINK) { 59 obj->glink = (Elf_Addr)(obj->relocbase + dynp->d_un.d_ptr); 60 return (true); 61 } 62 63 return (false); 64 } 65 66 /* 67 * Process the R_PPC_COPY relocations 68 */ 69 int 70 do_copy_relocations(Obj_Entry *dstobj) 71 { 72 const Elf_Rela *relalim; 73 const Elf_Rela *rela; 74 75 /* 76 * COPY relocs are invalid outside of the main program 77 */ 78 assert(dstobj->mainprog); 79 80 relalim = (const Elf_Rela *)((const char *) dstobj->rela + 81 dstobj->relasize); 82 for (rela = dstobj->rela; rela < relalim; rela++) { 83 void *dstaddr; 84 const Elf_Sym *dstsym; 85 const char *name; 86 size_t size; 87 const void *srcaddr; 88 const Elf_Sym *srcsym = NULL; 89 const Obj_Entry *srcobj, *defobj; 90 SymLook req; 91 int res; 92 93 if (ELF_R_TYPE(rela->r_info) != R_PPC_COPY) { 94 continue; 95 } 96 97 dstaddr = (void *)(dstobj->relocbase + rela->r_offset); 98 dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); 99 name = dstobj->strtab + dstsym->st_name; 100 size = dstsym->st_size; 101 symlook_init(&req, name); 102 req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info)); 103 req.flags = SYMLOOK_EARLY; 104 105 for (srcobj = globallist_next(dstobj); srcobj != NULL; 106 srcobj = globallist_next(srcobj)) { 107 res = symlook_obj(&req, srcobj); 108 if (res == 0) { 109 srcsym = req.sym_out; 110 defobj = req.defobj_out; 111 break; 112 } 113 } 114 115 if (srcobj == NULL) { 116 _rtld_error("Undefined symbol \"%s\" " 117 " referenced from COPY" 118 " relocation in %s", name, dstobj->path); 119 return (-1); 120 } 121 122 srcaddr = (const void *)(defobj->relocbase+srcsym->st_value); 123 memcpy(dstaddr, srcaddr, size); 124 dbg("copy_reloc: src=%p,dst=%p,size=%zd\n",srcaddr,dstaddr,size); 125 } 126 127 return (0); 128 } 129 130 131 /* 132 * Perform early relocation of the run-time linker image 133 */ 134 void 135 reloc_non_plt_self(Elf_Dyn *dynp, Elf_Addr relocbase) 136 { 137 const Elf_Rela *rela = NULL, *relalim; 138 Elf_Addr relasz = 0; 139 Elf_Addr *where; 140 141 /* 142 * Extract the rela/relasz values from the dynamic section 143 */ 144 for (; dynp->d_tag != DT_NULL; dynp++) { 145 switch (dynp->d_tag) { 146 case DT_RELA: 147 rela = (const Elf_Rela *)(relocbase+dynp->d_un.d_ptr); 148 break; 149 case DT_RELASZ: 150 relasz = dynp->d_un.d_val; 151 break; 152 } 153 } 154 155 /* 156 * Relocate these values 157 */ 158 relalim = (const Elf_Rela *)((const char *)rela + relasz); 159 for (; rela < relalim; rela++) { 160 where = (Elf_Addr *)(relocbase + rela->r_offset); 161 *where = (Elf_Addr)(relocbase + rela->r_addend); 162 } 163 } 164 165 166 /* 167 * Relocate a non-PLT object with addend. 168 */ 169 static int 170 reloc_nonplt_object(Obj_Entry *obj_rtld __unused, Obj_Entry *obj, 171 const Elf_Rela *rela, SymCache *cache, int flags, RtldLockState *lockstate) 172 { 173 const Elf_Sym *def = NULL; 174 const Obj_Entry *defobj; 175 Elf_Addr *where, symval = 0; 176 177 /* 178 * First, resolve symbol for relocations which 179 * reference symbols. 180 */ 181 switch (ELF_R_TYPE(rela->r_info)) { 182 183 case R_PPC64_UADDR64: /* doubleword64 S + A */ 184 case R_PPC64_ADDR64: 185 case R_PPC_GLOB_DAT: 186 case R_PPC64_DTPMOD64: 187 case R_PPC64_TPREL64: 188 case R_PPC64_DTPREL64: 189 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 190 flags, cache, lockstate); 191 if (def == NULL) { 192 return (-1); 193 } 194 /* 195 * If symbol is IFUNC, only perform relocation 196 * when caller allowed it by passing 197 * SYMLOOK_IFUNC flag. Skip the relocations 198 * otherwise. 199 * 200 * Also error out in case IFUNC relocations 201 * are specified for TLS, which cannot be 202 * usefully interpreted. 203 */ 204 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 205 switch (ELF_R_TYPE(rela->r_info)) { 206 case R_PPC64_UADDR64: 207 case R_PPC64_ADDR64: 208 case R_PPC_GLOB_DAT: 209 if ((flags & SYMLOOK_IFUNC) == 0) { 210 dbg("Non-PLT reference to IFUNC found!"); 211 obj->non_plt_gnu_ifunc = true; 212 return (0); 213 } 214 symval = (Elf_Addr)rtld_resolve_ifunc( 215 defobj, def); 216 break; 217 default: 218 _rtld_error("%s: IFUNC for TLS reloc", 219 obj->path); 220 return (-1); 221 } 222 } else { 223 if ((flags & SYMLOOK_IFUNC) != 0) 224 return (0); 225 symval = (Elf_Addr)defobj->relocbase + 226 def->st_value; 227 } 228 break; 229 default: 230 if ((flags & SYMLOOK_IFUNC) != 0) 231 return (0); 232 } 233 234 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 235 236 switch (ELF_R_TYPE(rela->r_info)) { 237 case R_PPC_NONE: 238 break; 239 case R_PPC64_UADDR64: 240 case R_PPC64_ADDR64: 241 case R_PPC_GLOB_DAT: 242 /* Don't issue write if unnecessary; avoid COW page fault */ 243 if (*where != symval + rela->r_addend) { 244 *where = symval + rela->r_addend; 245 } 246 break; 247 case R_PPC64_DTPMOD64: 248 *where = (Elf_Addr) defobj->tlsindex; 249 break; 250 case R_PPC64_TPREL64: 251 /* 252 * We lazily allocate offsets for static TLS as we 253 * see the first relocation that references the 254 * TLS block. This allows us to support (small 255 * amounts of) static TLS in dynamically loaded 256 * modules. If we run out of space, we generate an 257 * error. 258 */ 259 if (!defobj->tls_static) { 260 if (!allocate_tls_offset( 261 __DECONST(Obj_Entry *, defobj))) { 262 _rtld_error("%s: No space available for static " 263 "Thread Local Storage", obj->path); 264 return (-1); 265 } 266 } 267 268 *(Elf_Addr **)where = *where * sizeof(Elf_Addr) 269 + (Elf_Addr *)(def->st_value + rela->r_addend 270 + defobj->tlsoffset - TLS_TP_OFFSET - TLS_TCB_SIZE); 271 break; 272 case R_PPC64_DTPREL64: 273 *where += (Elf_Addr)(def->st_value + rela->r_addend 274 - TLS_DTV_OFFSET); 275 break; 276 case R_PPC_RELATIVE: /* doubleword64 B + A */ 277 symval = (Elf_Addr)(obj->relocbase + rela->r_addend); 278 279 /* As above, don't issue write unnecessarily */ 280 if (*where != symval) { 281 *where = symval; 282 } 283 break; 284 case R_PPC_COPY: 285 /* 286 * These are deferred until all other relocations 287 * have been done. All we do here is make sure 288 * that the COPY relocation is not in a shared 289 * library. They are allowed only in executable 290 * files. 291 */ 292 if (!obj->mainprog) { 293 _rtld_error("%s: Unexpected R_COPY " 294 " relocation in shared library", 295 obj->path); 296 return (-1); 297 } 298 break; 299 case R_PPC_IRELATIVE: 300 /* 301 * These will be handled by reloc_iresolve(). 302 */ 303 obj->irelative = true; 304 break; 305 case R_PPC_JMP_SLOT: 306 /* 307 * These will be handled by the plt/jmpslot routines 308 */ 309 break; 310 311 default: 312 _rtld_error("%s: Unsupported relocation type %ld" 313 " in non-PLT relocations\n", obj->path, 314 ELF_R_TYPE(rela->r_info)); 315 return (-1); 316 } 317 return (0); 318 } 319 320 321 /* 322 * Process non-PLT relocations 323 */ 324 int 325 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, 326 RtldLockState *lockstate) 327 { 328 const Elf_Rela *relalim; 329 const Elf_Rela *rela; 330 const Elf_Phdr *phdr; 331 SymCache *cache; 332 int bytes = obj->dynsymcount * sizeof(SymCache); 333 int r = -1; 334 335 /* 336 * The dynamic loader may be called from a thread, we have 337 * limited amounts of stack available so we cannot use alloca(). 338 */ 339 if (obj != obj_rtld) { 340 cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, 341 -1, 0); 342 if (cache == MAP_FAILED) 343 cache = NULL; 344 } else 345 cache = NULL; 346 347 /* 348 * From the SVR4 PPC ABI: 349 * "The PowerPC family uses only the Elf32_Rela relocation 350 * entries with explicit addends." 351 */ 352 relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); 353 for (rela = obj->rela; rela < relalim; rela++) { 354 if (reloc_nonplt_object(obj_rtld, obj, rela, cache, flags, 355 lockstate) < 0) 356 goto done; 357 } 358 r = 0; 359 done: 360 if (cache) 361 munmap(cache, bytes); 362 363 /* 364 * Synchronize icache for executable segments in case we made 365 * any changes. 366 */ 367 for (phdr = obj->phdr; phdr < obj->phdr + obj->phnum; phdr++) { 368 if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X) != 0) { 369 __syncicache(obj->relocbase + phdr->p_vaddr, 370 phdr->p_memsz); 371 } 372 } 373 374 return (r); 375 } 376 377 378 /* 379 * Initialise a PLT slot to the resolving trampoline 380 */ 381 static int 382 reloc_plt_object(Obj_Entry *obj, const Elf_Rela *rela) 383 { 384 Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 385 long reloff; 386 387 reloff = rela - obj->pltrela; 388 389 dbg(" reloc_plt_object: where=%p,reloff=%lx,glink=%#lx", (void *)where, 390 reloff, obj->glink); 391 392 #if !defined(_CALL_ELF) || _CALL_ELF == 1 393 /* Glink code is 3 instructions after the first 32k, 2 before */ 394 *where = (Elf_Addr)obj->glink + 32 + 395 8*((reloff < 0x8000) ? reloff : 0x8000) + 396 12*((reloff < 0x8000) ? 0 : (reloff - 0x8000)); 397 #else 398 /* 64-Bit ELF V2 ABI Specification, sec. 4.2.5.3. */ 399 *where = (Elf_Addr)obj->glink + 4*reloff + 32; 400 #endif 401 402 return (0); 403 } 404 405 /* 406 * Process the PLT relocations. 407 */ 408 int 409 reloc_plt(Obj_Entry *obj, int flags __unused, RtldLockState *lockstate __unused) 410 { 411 const Elf_Rela *relalim; 412 const Elf_Rela *rela; 413 414 if (obj->pltrelasize != 0) { 415 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 416 obj->pltrelasize); 417 for (rela = obj->pltrela; rela < relalim; rela++) { 418 419 #if defined(_CALL_ELF) && _CALL_ELF == 2 420 if (ELF_R_TYPE(rela->r_info) == R_PPC_IRELATIVE) { 421 dbg("ABI violation - found IRELATIVE in the PLT."); 422 obj->irelative = true; 423 continue; 424 } 425 #endif 426 /* 427 * PowerPC(64) .rela.plt is composed of an array of 428 * R_PPC_JMP_SLOT relocations. Unlike other platforms, 429 * this is the ONLY relocation type that is valid here. 430 */ 431 assert(ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT); 432 433 if (reloc_plt_object(obj, rela) < 0) { 434 return (-1); 435 } 436 } 437 } 438 439 return (0); 440 } 441 442 /* 443 * LD_BIND_NOW was set - force relocation for all jump slots 444 */ 445 int 446 reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate) 447 { 448 const Obj_Entry *defobj; 449 const Elf_Rela *relalim; 450 const Elf_Rela *rela; 451 const Elf_Sym *def; 452 Elf_Addr *where; 453 Elf_Addr target; 454 455 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 456 obj->pltrelasize); 457 for (rela = obj->pltrela; rela < relalim; rela++) { 458 /* This isn't actually a jump slot, ignore it. */ 459 if (ELF_R_TYPE(rela->r_info) == R_PPC_IRELATIVE) 460 continue; 461 assert(ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT); 462 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 463 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 464 SYMLOOK_IN_PLT | flags, NULL, lockstate); 465 if (def == NULL) { 466 dbg("reloc_jmpslots: sym not found"); 467 return (-1); 468 } 469 470 target = (Elf_Addr)(defobj->relocbase + def->st_value); 471 472 if (def == &sym_zero) { 473 /* Zero undefined weak symbols */ 474 #if !defined(_CALL_ELF) || _CALL_ELF == 1 475 bzero(where, sizeof(struct funcdesc)); 476 #else 477 *where = 0; 478 #endif 479 } else { 480 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 481 /* LD_BIND_NOW, ifunc in shared lib.*/ 482 obj->gnu_ifunc = true; 483 continue; 484 } 485 reloc_jmpslot(where, target, defobj, obj, 486 (const Elf_Rel *) rela); 487 } 488 } 489 490 obj->jmpslots_done = true; 491 492 return (0); 493 } 494 495 496 /* 497 * Update the value of a PLT jump slot. 498 */ 499 Elf_Addr 500 reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj __unused, 501 const Obj_Entry *obj __unused, const Elf_Rel *rel __unused) 502 { 503 504 /* 505 * At the PLT entry pointed at by `wherep', construct 506 * a direct transfer to the now fully resolved function 507 * address. 508 */ 509 510 #if !defined(_CALL_ELF) || _CALL_ELF == 1 511 dbg(" reloc_jmpslot: where=%p, target=%p (%#lx + %#lx)", 512 (void *)wherep, (void *)target, *(Elf_Addr *)target, 513 (Elf_Addr)defobj->relocbase); 514 515 if (ld_bind_not) 516 goto out; 517 518 /* 519 * For the trampoline, the second two elements of the function 520 * descriptor are unused, so we are fine replacing those at any time 521 * with the real ones with no thread safety implications. However, we 522 * need to make sure the main entry point pointer ([0]) is seen to be 523 * modified *after* the second two elements. This can't be done in 524 * general, since there are no barriers in the reading code, but put in 525 * some isyncs to at least make it a little better. 526 */ 527 memcpy(wherep, (void *)target, sizeof(struct funcdesc)); 528 wherep[2] = ((Elf_Addr *)target)[2]; 529 wherep[1] = ((Elf_Addr *)target)[1]; 530 __asm __volatile ("isync" : : : "memory"); 531 wherep[0] = ((Elf_Addr *)target)[0]; 532 __asm __volatile ("isync" : : : "memory"); 533 534 if (((struct funcdesc *)(wherep))->addr < (Elf_Addr)defobj->relocbase) { 535 /* 536 * It is possible (LD_BIND_NOW) that the function 537 * descriptor we are copying has not yet been relocated. 538 * If this happens, fix it. Don't worry about threading in 539 * this case since LD_BIND_NOW makes it irrelevant. 540 */ 541 542 ((struct funcdesc *)(wherep))->addr += 543 (Elf_Addr)defobj->relocbase; 544 ((struct funcdesc *)(wherep))->toc += 545 (Elf_Addr)defobj->relocbase; 546 } 547 #else 548 dbg(" reloc_jmpslot: where=%p, target=%p", (void *)wherep, 549 (void *)target); 550 551 assert(target >= (Elf_Addr)defobj->relocbase); 552 553 if (ld_bind_not) 554 goto out; 555 556 if (*wherep != target) 557 *wherep = target; 558 559 #endif 560 out: 561 562 return (target); 563 } 564 565 int 566 reloc_iresolve(Obj_Entry *obj, 567 struct Struct_RtldLockState *lockstate) 568 { 569 /* 570 * Since PLT slots on PowerPC64 are always R_PPC_JMP_SLOT, 571 * R_PPC_IRELATIVE is in RELA. 572 */ 573 #if !defined(_CALL_ELF) || _CALL_ELF == 1 574 (void)(obj); 575 (void)(lockstate); 576 /* XXX not implemented */ 577 return (0); 578 #else 579 const Elf_Rela *relalim; 580 const Elf_Rela *rela; 581 Elf_Addr *where, target, *ptr; 582 583 if (!obj->irelative) 584 return (0); 585 586 relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); 587 for (rela = obj->rela; rela < relalim; rela++) { 588 if (ELF_R_TYPE(rela->r_info) == R_PPC_IRELATIVE) { 589 ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend); 590 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 591 592 lock_release(rtld_bind_lock, lockstate); 593 target = call_ifunc_resolver(ptr); 594 wlock_acquire(rtld_bind_lock, lockstate); 595 596 *where = target; 597 } 598 } 599 /* 600 * XXX Remove me when lld is fixed! 601 * LLD currently makes illegal relocations in the PLT. 602 */ 603 relalim = (const Elf_Rela *)((const char *)obj->pltrela + obj->pltrelasize); 604 for (rela = obj->pltrela; rela < relalim; rela++) { 605 if (ELF_R_TYPE(rela->r_info) == R_PPC_IRELATIVE) { 606 ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend); 607 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 608 609 lock_release(rtld_bind_lock, lockstate); 610 target = call_ifunc_resolver(ptr); 611 wlock_acquire(rtld_bind_lock, lockstate); 612 613 *where = target; 614 } 615 } 616 617 obj->irelative = false; 618 return (0); 619 #endif 620 } 621 622 int 623 reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused, 624 struct Struct_RtldLockState *lockstate __unused) 625 { 626 #if !defined(_CALL_ELF) || _CALL_ELF == 1 627 _rtld_error("reloc_gnu_ifunc(): Not implemented!"); 628 /* XXX not implemented */ 629 return (-1); 630 #else 631 632 const Elf_Rela *relalim; 633 const Elf_Rela *rela; 634 Elf_Addr *where, target; 635 const Elf_Sym *def; 636 const Obj_Entry *defobj; 637 638 if (!obj->gnu_ifunc) 639 return (0); 640 relalim = (const Elf_Rela *)((const char *)obj->pltrela + obj->pltrelasize); 641 for (rela = obj->pltrela; rela < relalim; rela++) { 642 if (ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT) { 643 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 644 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 645 SYMLOOK_IN_PLT | flags, NULL, lockstate); 646 if (def == NULL) 647 return (-1); 648 if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC) 649 continue; 650 lock_release(rtld_bind_lock, lockstate); 651 target = (Elf_Addr)rtld_resolve_ifunc(defobj, def); 652 wlock_acquire(rtld_bind_lock, lockstate); 653 reloc_jmpslot(where, target, defobj, obj, 654 (const Elf_Rel *)rela); 655 } 656 } 657 obj->gnu_ifunc = false; 658 return (0); 659 #endif 660 } 661 662 int 663 reloc_iresolve_nonplt(Obj_Entry *obj __unused, 664 struct Struct_RtldLockState *lockstate __unused) 665 { 666 return (0); 667 } 668 669 void 670 init_pltgot(Obj_Entry *obj) 671 { 672 Elf_Addr *pltcall; 673 674 pltcall = obj->pltgot; 675 676 if (pltcall == NULL) { 677 return; 678 } 679 680 #if defined(_CALL_ELF) && _CALL_ELF == 2 681 pltcall[0] = (Elf_Addr)&_rtld_bind_start; 682 pltcall[1] = (Elf_Addr)obj; 683 #else 684 memcpy(pltcall, _rtld_bind_start, sizeof(struct funcdesc)); 685 pltcall[2] = (Elf_Addr)obj; 686 #endif 687 } 688 689 /* 690 * Actual values are 32 bit. 691 */ 692 u_long cpu_features; 693 u_long cpu_features2; 694 695 void 696 powerpc64_abi_variant_hook(Elf_Auxinfo** aux_info) 697 { 698 /* 699 * Since aux_info[] is easier to work with than aux, go ahead and 700 * initialize cpu_features / cpu_features2. 701 */ 702 cpu_features = -1UL; 703 cpu_features2 = -1UL; 704 if (aux_info[AT_HWCAP] != NULL) 705 cpu_features = (uint32_t)aux_info[AT_HWCAP]->a_un.a_val; 706 if (aux_info[AT_HWCAP2] != NULL) 707 cpu_features2 = (uint32_t)aux_info[AT_HWCAP2]->a_un.a_val; 708 } 709 710 void 711 ifunc_init(Elf_Auxinfo *aux_info[__min_size(AT_COUNT)] __unused) 712 { 713 714 } 715 716 void 717 allocate_initial_tls(Obj_Entry *list) 718 { 719 720 /* 721 * Fix the size of the static TLS block by using the maximum 722 * offset allocated so far and adding a bit for dynamic modules to 723 * use. 724 */ 725 726 tls_static_space = tls_last_offset + tls_last_size + 727 ld_static_tls_extra; 728 729 _tcb_set(allocate_tls(list, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN)); 730 } 731 732 void* 733 __tls_get_addr(tls_index* ti) 734 { 735 return (tls_get_addr_common(_tcb_get(), ti->ti_module, ti->ti_offset + 736 TLS_DTV_OFFSET)); 737 } 738 739 void 740 arch_fix_auxv(Elf_Auxinfo *aux, Elf_Auxinfo *aux_info[]) 741 { 742 Elf_Auxinfo *auxp; 743 744 for (auxp = aux; auxp->a_type != AT_NULL; auxp++) { 745 if (auxp->a_type == 23) /* AT_STACKPROT */ 746 return; 747 } 748 749 /* Remap from old-style auxv numbers. */ 750 aux_info[23] = aux_info[21]; /* AT_STACKPROT */ 751 aux_info[21] = aux_info[19]; /* AT_PAGESIZESLEN */ 752 aux_info[19] = aux_info[17]; /* AT_NCPUS */ 753 aux_info[17] = aux_info[15]; /* AT_CANARYLEN */ 754 aux_info[15] = aux_info[13]; /* AT_EXECPATH */ 755 aux_info[13] = NULL; /* AT_GID */ 756 757 aux_info[20] = aux_info[18]; /* AT_PAGESIZES */ 758 aux_info[18] = aux_info[16]; /* AT_OSRELDATE */ 759 aux_info[16] = aux_info[14]; /* AT_CANARY */ 760 aux_info[14] = NULL; /* AT_EGID */ 761 } 762