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 SymCache *cache; 331 int bytes = obj->dynsymcount * sizeof(SymCache); 332 int r = -1; 333 334 /* 335 * The dynamic loader may be called from a thread, we have 336 * limited amounts of stack available so we cannot use alloca(). 337 */ 338 if (obj != obj_rtld) { 339 cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, 340 -1, 0); 341 if (cache == MAP_FAILED) 342 cache = NULL; 343 } else 344 cache = NULL; 345 346 /* 347 * From the SVR4 PPC ABI: 348 * "The PowerPC family uses only the Elf32_Rela relocation 349 * entries with explicit addends." 350 */ 351 relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); 352 for (rela = obj->rela; rela < relalim; rela++) { 353 if (reloc_nonplt_object(obj_rtld, obj, rela, cache, flags, 354 lockstate) < 0) 355 goto done; 356 } 357 r = 0; 358 done: 359 if (cache) 360 munmap(cache, bytes); 361 return (r); 362 } 363 364 365 /* 366 * Initialise a PLT slot to the resolving trampoline 367 */ 368 static int 369 reloc_plt_object(Obj_Entry *obj, const Elf_Rela *rela) 370 { 371 Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 372 long reloff; 373 374 reloff = rela - obj->pltrela; 375 376 dbg(" reloc_plt_object: where=%p,reloff=%lx,glink=%#lx", (void *)where, 377 reloff, obj->glink); 378 379 #if !defined(_CALL_ELF) || _CALL_ELF == 1 380 /* Glink code is 3 instructions after the first 32k, 2 before */ 381 *where = (Elf_Addr)obj->glink + 32 + 382 8*((reloff < 0x8000) ? reloff : 0x8000) + 383 12*((reloff < 0x8000) ? 0 : (reloff - 0x8000)); 384 #else 385 /* 64-Bit ELF V2 ABI Specification, sec. 4.2.5.3. */ 386 *where = (Elf_Addr)obj->glink + 4*reloff + 32; 387 #endif 388 389 return (0); 390 } 391 392 /* 393 * Process the PLT relocations. 394 */ 395 int 396 reloc_plt(Obj_Entry *obj, int flags __unused, RtldLockState *lockstate __unused) 397 { 398 const Elf_Rela *relalim; 399 const Elf_Rela *rela; 400 401 if (obj->pltrelasize != 0) { 402 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 403 obj->pltrelasize); 404 for (rela = obj->pltrela; rela < relalim; rela++) { 405 406 #if defined(_CALL_ELF) && _CALL_ELF == 2 407 if (ELF_R_TYPE(rela->r_info) == R_PPC_IRELATIVE) { 408 dbg("ABI violation - found IRELATIVE in the PLT."); 409 obj->irelative = true; 410 continue; 411 } 412 #endif 413 /* 414 * PowerPC(64) .rela.plt is composed of an array of 415 * R_PPC_JMP_SLOT relocations. Unlike other platforms, 416 * this is the ONLY relocation type that is valid here. 417 */ 418 assert(ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT); 419 420 if (reloc_plt_object(obj, rela) < 0) { 421 return (-1); 422 } 423 } 424 } 425 426 return (0); 427 } 428 429 /* 430 * LD_BIND_NOW was set - force relocation for all jump slots 431 */ 432 int 433 reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate) 434 { 435 const Obj_Entry *defobj; 436 const Elf_Rela *relalim; 437 const Elf_Rela *rela; 438 const Elf_Sym *def; 439 Elf_Addr *where; 440 Elf_Addr target; 441 442 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 443 obj->pltrelasize); 444 for (rela = obj->pltrela; rela < relalim; rela++) { 445 /* This isn't actually a jump slot, ignore it. */ 446 if (ELF_R_TYPE(rela->r_info) == R_PPC_IRELATIVE) 447 continue; 448 assert(ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT); 449 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 450 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 451 SYMLOOK_IN_PLT | flags, NULL, lockstate); 452 if (def == NULL) { 453 dbg("reloc_jmpslots: sym not found"); 454 return (-1); 455 } 456 457 target = (Elf_Addr)(defobj->relocbase + def->st_value); 458 459 if (def == &sym_zero) { 460 /* Zero undefined weak symbols */ 461 #if !defined(_CALL_ELF) || _CALL_ELF == 1 462 bzero(where, sizeof(struct funcdesc)); 463 #else 464 *where = 0; 465 #endif 466 } else { 467 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 468 /* LD_BIND_NOW, ifunc in shared lib.*/ 469 obj->gnu_ifunc = true; 470 continue; 471 } 472 reloc_jmpslot(where, target, defobj, obj, 473 (const Elf_Rel *) rela); 474 } 475 } 476 477 obj->jmpslots_done = true; 478 479 return (0); 480 } 481 482 483 /* 484 * Update the value of a PLT jump slot. 485 */ 486 Elf_Addr 487 reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj __unused, 488 const Obj_Entry *obj __unused, const Elf_Rel *rel __unused) 489 { 490 491 /* 492 * At the PLT entry pointed at by `wherep', construct 493 * a direct transfer to the now fully resolved function 494 * address. 495 */ 496 497 #if !defined(_CALL_ELF) || _CALL_ELF == 1 498 dbg(" reloc_jmpslot: where=%p, target=%p (%#lx + %#lx)", 499 (void *)wherep, (void *)target, *(Elf_Addr *)target, 500 (Elf_Addr)defobj->relocbase); 501 502 if (ld_bind_not) 503 goto out; 504 505 /* 506 * For the trampoline, the second two elements of the function 507 * descriptor are unused, so we are fine replacing those at any time 508 * with the real ones with no thread safety implications. However, we 509 * need to make sure the main entry point pointer ([0]) is seen to be 510 * modified *after* the second two elements. This can't be done in 511 * general, since there are no barriers in the reading code, but put in 512 * some isyncs to at least make it a little better. 513 */ 514 memcpy(wherep, (void *)target, sizeof(struct funcdesc)); 515 wherep[2] = ((Elf_Addr *)target)[2]; 516 wherep[1] = ((Elf_Addr *)target)[1]; 517 __asm __volatile ("isync" : : : "memory"); 518 wherep[0] = ((Elf_Addr *)target)[0]; 519 __asm __volatile ("isync" : : : "memory"); 520 521 if (((struct funcdesc *)(wherep))->addr < (Elf_Addr)defobj->relocbase) { 522 /* 523 * It is possible (LD_BIND_NOW) that the function 524 * descriptor we are copying has not yet been relocated. 525 * If this happens, fix it. Don't worry about threading in 526 * this case since LD_BIND_NOW makes it irrelevant. 527 */ 528 529 ((struct funcdesc *)(wherep))->addr += 530 (Elf_Addr)defobj->relocbase; 531 ((struct funcdesc *)(wherep))->toc += 532 (Elf_Addr)defobj->relocbase; 533 } 534 #else 535 dbg(" reloc_jmpslot: where=%p, target=%p", (void *)wherep, 536 (void *)target); 537 538 assert(target >= (Elf_Addr)defobj->relocbase); 539 540 if (ld_bind_not) 541 goto out; 542 543 if (*wherep != target) 544 *wherep = target; 545 546 #endif 547 out: 548 549 return (target); 550 } 551 552 int 553 reloc_iresolve(Obj_Entry *obj, 554 struct Struct_RtldLockState *lockstate) 555 { 556 /* 557 * Since PLT slots on PowerPC64 are always R_PPC_JMP_SLOT, 558 * R_PPC_IRELATIVE is in RELA. 559 */ 560 #if !defined(_CALL_ELF) || _CALL_ELF == 1 561 (void)(obj); 562 (void)(lockstate); 563 /* XXX not implemented */ 564 return (0); 565 #else 566 const Elf_Rela *relalim; 567 const Elf_Rela *rela; 568 Elf_Addr *where, target, *ptr; 569 570 if (!obj->irelative) 571 return (0); 572 573 relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); 574 for (rela = obj->rela; rela < relalim; rela++) { 575 if (ELF_R_TYPE(rela->r_info) == R_PPC_IRELATIVE) { 576 ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend); 577 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 578 579 lock_release(rtld_bind_lock, lockstate); 580 target = call_ifunc_resolver(ptr); 581 wlock_acquire(rtld_bind_lock, lockstate); 582 583 *where = target; 584 } 585 } 586 /* 587 * XXX Remove me when lld is fixed! 588 * LLD currently makes illegal relocations in the PLT. 589 */ 590 relalim = (const Elf_Rela *)((const char *)obj->pltrela + obj->pltrelasize); 591 for (rela = obj->pltrela; rela < relalim; rela++) { 592 if (ELF_R_TYPE(rela->r_info) == R_PPC_IRELATIVE) { 593 ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend); 594 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 595 596 lock_release(rtld_bind_lock, lockstate); 597 target = call_ifunc_resolver(ptr); 598 wlock_acquire(rtld_bind_lock, lockstate); 599 600 *where = target; 601 } 602 } 603 604 obj->irelative = false; 605 return (0); 606 #endif 607 } 608 609 int 610 reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused, 611 struct Struct_RtldLockState *lockstate __unused) 612 { 613 #if !defined(_CALL_ELF) || _CALL_ELF == 1 614 _rtld_error("reloc_gnu_ifunc(): Not implemented!"); 615 /* XXX not implemented */ 616 return (-1); 617 #else 618 619 const Elf_Rela *relalim; 620 const Elf_Rela *rela; 621 Elf_Addr *where, target; 622 const Elf_Sym *def; 623 const Obj_Entry *defobj; 624 625 if (!obj->gnu_ifunc) 626 return (0); 627 relalim = (const Elf_Rela *)((const char *)obj->pltrela + obj->pltrelasize); 628 for (rela = obj->pltrela; rela < relalim; rela++) { 629 if (ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT) { 630 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 631 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 632 SYMLOOK_IN_PLT | flags, NULL, lockstate); 633 if (def == NULL) 634 return (-1); 635 if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC) 636 continue; 637 lock_release(rtld_bind_lock, lockstate); 638 target = (Elf_Addr)rtld_resolve_ifunc(defobj, def); 639 wlock_acquire(rtld_bind_lock, lockstate); 640 reloc_jmpslot(where, target, defobj, obj, 641 (const Elf_Rel *)rela); 642 } 643 } 644 obj->gnu_ifunc = false; 645 return (0); 646 #endif 647 } 648 649 int 650 reloc_iresolve_nonplt(Obj_Entry *obj __unused, 651 struct Struct_RtldLockState *lockstate __unused) 652 { 653 return (0); 654 } 655 656 void 657 init_pltgot(Obj_Entry *obj) 658 { 659 Elf_Addr *pltcall; 660 661 pltcall = obj->pltgot; 662 663 if (pltcall == NULL) { 664 return; 665 } 666 667 #if defined(_CALL_ELF) && _CALL_ELF == 2 668 pltcall[0] = (Elf_Addr)&_rtld_bind_start; 669 pltcall[1] = (Elf_Addr)obj; 670 #else 671 memcpy(pltcall, _rtld_bind_start, sizeof(struct funcdesc)); 672 pltcall[2] = (Elf_Addr)obj; 673 #endif 674 } 675 676 /* 677 * Actual values are 32 bit. 678 */ 679 u_long cpu_features; 680 u_long cpu_features2; 681 682 void 683 powerpc64_abi_variant_hook(Elf_Auxinfo** aux_info) 684 { 685 /* 686 * Since aux_info[] is easier to work with than aux, go ahead and 687 * initialize cpu_features / cpu_features2. 688 */ 689 cpu_features = -1UL; 690 cpu_features2 = -1UL; 691 if (aux_info[AT_HWCAP] != NULL) 692 cpu_features = (uint32_t)aux_info[AT_HWCAP]->a_un.a_val; 693 if (aux_info[AT_HWCAP2] != NULL) 694 cpu_features2 = (uint32_t)aux_info[AT_HWCAP2]->a_un.a_val; 695 } 696 697 void 698 ifunc_init(Elf_Auxinfo *aux_info[__min_size(AT_COUNT)] __unused) 699 { 700 701 } 702 703 void 704 allocate_initial_tls(Obj_Entry *list) 705 { 706 707 /* 708 * Fix the size of the static TLS block by using the maximum 709 * offset allocated so far and adding a bit for dynamic modules to 710 * use. 711 */ 712 713 tls_static_space = tls_last_offset + tls_last_size + 714 ld_static_tls_extra; 715 716 _tcb_set(allocate_tls(list, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN)); 717 } 718 719 void* 720 __tls_get_addr(tls_index* ti) 721 { 722 return (tls_get_addr_common(_tcb_get(), ti->ti_module, ti->ti_offset + 723 TLS_DTV_OFFSET)); 724 } 725 726 void 727 arch_fix_auxv(Elf_Auxinfo *aux, Elf_Auxinfo *aux_info[]) 728 { 729 Elf_Auxinfo *auxp; 730 731 for (auxp = aux; auxp->a_type != AT_NULL; auxp++) { 732 if (auxp->a_type == 23) /* AT_STACKPROT */ 733 return; 734 } 735 736 /* Remap from old-style auxv numbers. */ 737 aux_info[23] = aux_info[21]; /* AT_STACKPROT */ 738 aux_info[21] = aux_info[19]; /* AT_PAGESIZESLEN */ 739 aux_info[19] = aux_info[17]; /* AT_NCPUS */ 740 aux_info[17] = aux_info[15]; /* AT_CANARYLEN */ 741 aux_info[15] = aux_info[13]; /* AT_EXECPATH */ 742 aux_info[13] = NULL; /* AT_GID */ 743 744 aux_info[20] = aux_info[18]; /* AT_PAGESIZES */ 745 aux_info[18] = aux_info[16]; /* AT_OSRELDATE */ 746 aux_info[16] = aux_info[14]; /* AT_CANARY */ 747 aux_info[14] = NULL; /* AT_EGID */ 748 } 749