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-NetBSD 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 * $FreeBSD$ 32 */ 33 34 #include <sys/param.h> 35 #include <sys/mman.h> 36 37 #include <errno.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 #include <machine/cpu.h> 43 #include <machine/md_var.h> 44 45 #include "debug.h" 46 #include "rtld.h" 47 48 #if !defined(_CALL_ELF) || _CALL_ELF == 1 49 struct funcdesc { 50 Elf_Addr addr; 51 Elf_Addr toc; 52 Elf_Addr env; 53 }; 54 #endif 55 56 /* 57 * Process the R_PPC_COPY relocations 58 */ 59 int 60 do_copy_relocations(Obj_Entry *dstobj) 61 { 62 const Elf_Rela *relalim; 63 const Elf_Rela *rela; 64 65 /* 66 * COPY relocs are invalid outside of the main program 67 */ 68 assert(dstobj->mainprog); 69 70 relalim = (const Elf_Rela *)((const char *) dstobj->rela + 71 dstobj->relasize); 72 for (rela = dstobj->rela; rela < relalim; rela++) { 73 void *dstaddr; 74 const Elf_Sym *dstsym; 75 const char *name; 76 size_t size; 77 const void *srcaddr; 78 const Elf_Sym *srcsym = NULL; 79 const Obj_Entry *srcobj, *defobj; 80 SymLook req; 81 int res; 82 83 if (ELF_R_TYPE(rela->r_info) != R_PPC_COPY) { 84 continue; 85 } 86 87 dstaddr = (void *)(dstobj->relocbase + rela->r_offset); 88 dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); 89 name = dstobj->strtab + dstsym->st_name; 90 size = dstsym->st_size; 91 symlook_init(&req, name); 92 req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info)); 93 req.flags = SYMLOOK_EARLY; 94 95 for (srcobj = globallist_next(dstobj); srcobj != NULL; 96 srcobj = globallist_next(srcobj)) { 97 res = symlook_obj(&req, srcobj); 98 if (res == 0) { 99 srcsym = req.sym_out; 100 defobj = req.defobj_out; 101 break; 102 } 103 } 104 105 if (srcobj == NULL) { 106 _rtld_error("Undefined symbol \"%s\" " 107 " referenced from COPY" 108 " relocation in %s", name, dstobj->path); 109 return (-1); 110 } 111 112 srcaddr = (const void *)(defobj->relocbase+srcsym->st_value); 113 memcpy(dstaddr, srcaddr, size); 114 dbg("copy_reloc: src=%p,dst=%p,size=%zd\n",srcaddr,dstaddr,size); 115 } 116 117 return (0); 118 } 119 120 121 /* 122 * Perform early relocation of the run-time linker image 123 */ 124 void 125 reloc_non_plt_self(Elf_Dyn *dynp, Elf_Addr relocbase) 126 { 127 const Elf_Rela *rela = NULL, *relalim; 128 Elf_Addr relasz = 0; 129 Elf_Addr *where; 130 131 /* 132 * Extract the rela/relasz values from the dynamic section 133 */ 134 for (; dynp->d_tag != DT_NULL; dynp++) { 135 switch (dynp->d_tag) { 136 case DT_RELA: 137 rela = (const Elf_Rela *)(relocbase+dynp->d_un.d_ptr); 138 break; 139 case DT_RELASZ: 140 relasz = dynp->d_un.d_val; 141 break; 142 } 143 } 144 145 /* 146 * Relocate these values 147 */ 148 relalim = (const Elf_Rela *)((const char *)rela + relasz); 149 for (; rela < relalim; rela++) { 150 where = (Elf_Addr *)(relocbase + rela->r_offset); 151 *where = (Elf_Addr)(relocbase + rela->r_addend); 152 } 153 } 154 155 156 /* 157 * Relocate a non-PLT object with addend. 158 */ 159 static int 160 reloc_nonplt_object(Obj_Entry *obj_rtld __unused, Obj_Entry *obj, 161 const Elf_Rela *rela, SymCache *cache, int flags, RtldLockState *lockstate) 162 { 163 Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 164 const Elf_Sym *def; 165 const Obj_Entry *defobj; 166 Elf_Addr tmp; 167 168 switch (ELF_R_TYPE(rela->r_info)) { 169 170 case R_PPC_NONE: 171 break; 172 173 case R_PPC64_UADDR64: /* doubleword64 S + A */ 174 case R_PPC64_ADDR64: 175 case R_PPC_GLOB_DAT: 176 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 177 flags, cache, lockstate); 178 if (def == NULL) { 179 return (-1); 180 } 181 182 tmp = (Elf_Addr)(defobj->relocbase + def->st_value + 183 rela->r_addend); 184 185 /* Don't issue write if unnecessary; avoid COW page fault */ 186 if (*where != tmp) { 187 *where = tmp; 188 } 189 break; 190 191 case R_PPC_RELATIVE: /* doubleword64 B + A */ 192 tmp = (Elf_Addr)(obj->relocbase + rela->r_addend); 193 194 /* As above, don't issue write unnecessarily */ 195 if (*where != tmp) { 196 *where = tmp; 197 } 198 break; 199 200 case R_PPC_COPY: 201 /* 202 * These are deferred until all other relocations 203 * have been done. All we do here is make sure 204 * that the COPY relocation is not in a shared 205 * library. They are allowed only in executable 206 * files. 207 */ 208 if (!obj->mainprog) { 209 _rtld_error("%s: Unexpected R_COPY " 210 " relocation in shared library", 211 obj->path); 212 return (-1); 213 } 214 break; 215 216 case R_PPC_JMP_SLOT: 217 /* 218 * These will be handled by the plt/jmpslot routines 219 */ 220 break; 221 222 case R_PPC64_DTPMOD64: 223 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 224 flags, cache, lockstate); 225 226 if (def == NULL) 227 return (-1); 228 229 *where = (Elf_Addr) defobj->tlsindex; 230 231 break; 232 233 case R_PPC64_TPREL64: 234 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 235 flags, cache, lockstate); 236 237 if (def == NULL) 238 return (-1); 239 240 /* 241 * We lazily allocate offsets for static TLS as we 242 * see the first relocation that references the 243 * TLS block. This allows us to support (small 244 * amounts of) static TLS in dynamically loaded 245 * modules. If we run out of space, we generate an 246 * error. 247 */ 248 if (!defobj->tls_done) { 249 if (!allocate_tls_offset( 250 __DECONST(Obj_Entry *, defobj))) { 251 _rtld_error("%s: No space available for static " 252 "Thread Local Storage", obj->path); 253 return (-1); 254 } 255 } 256 257 *(Elf_Addr **)where = *where * sizeof(Elf_Addr) 258 + (Elf_Addr *)(def->st_value + rela->r_addend 259 + defobj->tlsoffset - TLS_TP_OFFSET); 260 261 break; 262 263 case R_PPC64_DTPREL64: 264 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 265 flags, cache, lockstate); 266 267 if (def == NULL) 268 return (-1); 269 270 *where += (Elf_Addr)(def->st_value + rela->r_addend 271 - TLS_DTV_OFFSET); 272 273 break; 274 275 default: 276 _rtld_error("%s: Unsupported relocation type %ld" 277 " in non-PLT relocations\n", obj->path, 278 ELF_R_TYPE(rela->r_info)); 279 return (-1); 280 } 281 return (0); 282 } 283 284 285 /* 286 * Process non-PLT relocations 287 */ 288 int 289 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, 290 RtldLockState *lockstate) 291 { 292 const Elf_Rela *relalim; 293 const Elf_Rela *rela; 294 const Elf_Phdr *phdr; 295 SymCache *cache; 296 int bytes = obj->dynsymcount * sizeof(SymCache); 297 int r = -1; 298 299 if ((flags & SYMLOOK_IFUNC) != 0) 300 /* XXX not implemented */ 301 return (0); 302 303 /* 304 * The dynamic loader may be called from a thread, we have 305 * limited amounts of stack available so we cannot use alloca(). 306 */ 307 if (obj != obj_rtld) { 308 cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, 309 -1, 0); 310 if (cache == MAP_FAILED) 311 cache = NULL; 312 } else 313 cache = NULL; 314 315 /* 316 * From the SVR4 PPC ABI: 317 * "The PowerPC family uses only the Elf32_Rela relocation 318 * entries with explicit addends." 319 */ 320 relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); 321 for (rela = obj->rela; rela < relalim; rela++) { 322 if (reloc_nonplt_object(obj_rtld, obj, rela, cache, flags, 323 lockstate) < 0) 324 goto done; 325 } 326 r = 0; 327 done: 328 if (cache) 329 munmap(cache, bytes); 330 331 /* 332 * Synchronize icache for executable segments in case we made 333 * any changes. 334 */ 335 for (phdr = obj->phdr; 336 (const char *)phdr < (const char *)obj->phdr + obj->phsize; 337 phdr++) { 338 if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X) != 0) { 339 __syncicache(obj->relocbase + phdr->p_vaddr, 340 phdr->p_memsz); 341 } 342 } 343 344 return (r); 345 } 346 347 348 /* 349 * Initialise a PLT slot to the resolving trampoline 350 */ 351 static int 352 reloc_plt_object(Obj_Entry *obj, const Elf_Rela *rela) 353 { 354 Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 355 long reloff; 356 357 reloff = rela - obj->pltrela; 358 359 dbg(" reloc_plt_object: where=%p,reloff=%lx,glink=%#lx", (void *)where, 360 reloff, obj->glink); 361 362 #if !defined(_CALL_ELF) || _CALL_ELF == 1 363 /* Glink code is 3 instructions after the first 32k, 2 before */ 364 *where = (Elf_Addr)obj->glink + 32 + 365 8*((reloff < 0x8000) ? reloff : 0x8000) + 366 12*((reloff < 0x8000) ? 0 : (reloff - 0x8000)); 367 #else 368 *where = (Elf_Addr)obj->glink + 4*reloff + 32; 369 #endif 370 371 return (0); 372 } 373 374 375 /* 376 * Process the PLT relocations. 377 */ 378 int 379 reloc_plt(Obj_Entry *obj) 380 { 381 const Elf_Rela *relalim; 382 const Elf_Rela *rela; 383 384 if (obj->pltrelasize != 0) { 385 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 386 obj->pltrelasize); 387 for (rela = obj->pltrela; rela < relalim; rela++) { 388 assert(ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT); 389 390 if (reloc_plt_object(obj, rela) < 0) { 391 return (-1); 392 } 393 } 394 } 395 396 return (0); 397 } 398 399 400 /* 401 * LD_BIND_NOW was set - force relocation for all jump slots 402 */ 403 int 404 reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate) 405 { 406 const Obj_Entry *defobj; 407 const Elf_Rela *relalim; 408 const Elf_Rela *rela; 409 const Elf_Sym *def; 410 Elf_Addr *where; 411 Elf_Addr target; 412 413 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 414 obj->pltrelasize); 415 for (rela = obj->pltrela; rela < relalim; rela++) { 416 assert(ELF_R_TYPE(rela->r_info) == R_PPC_JMP_SLOT); 417 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 418 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 419 SYMLOOK_IN_PLT | flags, NULL, lockstate); 420 if (def == NULL) { 421 dbg("reloc_jmpslots: sym not found"); 422 return (-1); 423 } 424 425 target = (Elf_Addr)(defobj->relocbase + def->st_value); 426 427 if (def == &sym_zero) { 428 /* Zero undefined weak symbols */ 429 #if !defined(_CALL_ELF) || _CALL_ELF == 1 430 bzero(where, sizeof(struct funcdesc)); 431 #else 432 *where = 0; 433 #endif 434 } else { 435 reloc_jmpslot(where, target, defobj, obj, 436 (const Elf_Rel *) rela); 437 } 438 } 439 440 obj->jmpslots_done = true; 441 442 return (0); 443 } 444 445 446 /* 447 * Update the value of a PLT jump slot. 448 */ 449 Elf_Addr 450 reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj, 451 const Obj_Entry *obj __unused, const Elf_Rel *rel __unused) 452 { 453 454 /* 455 * At the PLT entry pointed at by `wherep', construct 456 * a direct transfer to the now fully resolved function 457 * address. 458 */ 459 460 #if !defined(_CALL_ELF) || _CALL_ELF == 1 461 dbg(" reloc_jmpslot: where=%p, target=%p (%#lx + %#lx)", 462 (void *)wherep, (void *)target, *(Elf_Addr *)target, 463 (Elf_Addr)defobj->relocbase); 464 465 if (ld_bind_not) 466 goto out; 467 468 /* 469 * For the trampoline, the second two elements of the function 470 * descriptor are unused, so we are fine replacing those at any time 471 * with the real ones with no thread safety implications. However, we 472 * need to make sure the main entry point pointer ([0]) is seen to be 473 * modified *after* the second two elements. This can't be done in 474 * general, since there are no barriers in the reading code, but put in 475 * some isyncs to at least make it a little better. 476 */ 477 memcpy(wherep, (void *)target, sizeof(struct funcdesc)); 478 wherep[2] = ((Elf_Addr *)target)[2]; 479 wherep[1] = ((Elf_Addr *)target)[1]; 480 __asm __volatile ("isync" : : : "memory"); 481 wherep[0] = ((Elf_Addr *)target)[0]; 482 __asm __volatile ("isync" : : : "memory"); 483 484 if (((struct funcdesc *)(wherep))->addr < (Elf_Addr)defobj->relocbase) { 485 /* 486 * It is possible (LD_BIND_NOW) that the function 487 * descriptor we are copying has not yet been relocated. 488 * If this happens, fix it. Don't worry about threading in 489 * this case since LD_BIND_NOW makes it irrelevant. 490 */ 491 492 ((struct funcdesc *)(wherep))->addr += 493 (Elf_Addr)defobj->relocbase; 494 ((struct funcdesc *)(wherep))->toc += 495 (Elf_Addr)defobj->relocbase; 496 } 497 out: 498 #else 499 dbg(" reloc_jmpslot: where=%p, target=%p", (void *)wherep, 500 (void *)target); 501 502 if (!ld_bind_not) 503 *wherep = target; 504 #endif 505 506 return (target); 507 } 508 509 int 510 reloc_iresolve(Obj_Entry *obj __unused, 511 struct Struct_RtldLockState *lockstate __unused) 512 { 513 514 /* XXX not implemented */ 515 return (0); 516 } 517 518 int 519 reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused, 520 struct Struct_RtldLockState *lockstate __unused) 521 { 522 523 /* XXX not implemented */ 524 return (0); 525 } 526 527 void 528 init_pltgot(Obj_Entry *obj) 529 { 530 Elf_Addr *pltcall; 531 532 pltcall = obj->pltgot; 533 534 if (pltcall == NULL) { 535 return; 536 } 537 538 #if defined(_CALL_ELF) && _CALL_ELF == 2 539 pltcall[0] = (Elf_Addr)&_rtld_bind_start; 540 pltcall[1] = (Elf_Addr)obj; 541 #else 542 memcpy(pltcall, _rtld_bind_start, sizeof(struct funcdesc)); 543 pltcall[2] = (Elf_Addr)obj; 544 #endif 545 } 546 547 void 548 ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused) 549 { 550 551 } 552 553 void 554 pre_init(void) 555 { 556 557 } 558 559 void 560 allocate_initial_tls(Obj_Entry *list) 561 { 562 Elf_Addr **tp; 563 564 /* 565 * Fix the size of the static TLS block by using the maximum 566 * offset allocated so far and adding a bit for dynamic modules to 567 * use. 568 */ 569 570 tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA; 571 572 tp = (Elf_Addr **)((char *)allocate_tls(list, NULL, TLS_TCB_SIZE, 16) 573 + TLS_TP_OFFSET + TLS_TCB_SIZE); 574 575 __asm __volatile("mr 13,%0" :: "r"(tp)); 576 } 577 578 void* 579 __tls_get_addr(tls_index* ti) 580 { 581 Elf_Addr **tp; 582 char *p; 583 584 __asm __volatile("mr %0,13" : "=r"(tp)); 585 p = tls_get_addr_common((Elf_Addr**)((Elf_Addr)tp - TLS_TP_OFFSET 586 - TLS_TCB_SIZE), ti->ti_module, ti->ti_offset); 587 588 return (p + TLS_DTV_OFFSET); 589 } 590