1 /*- 2 * Copyright (c) 2014-2015 The FreeBSD Foundation 3 * 4 * Portions of this software were developed by Andrew Turner 5 * under sponsorship from the FreeBSD Foundation. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/types.h> 30 31 #include <machine/sysarch.h> 32 33 #include <stdlib.h> 34 35 #include "debug.h" 36 #include "rtld.h" 37 #include "rtld_printf.h" 38 39 /* 40 * It is possible for the compiler to emit relocations for unaligned data. 41 * We handle this situation with these inlines. 42 */ 43 #define RELOC_ALIGNED_P(x) \ 44 (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0) 45 46 /* 47 * This is not the correct prototype, but we only need it for 48 * a function pointer to a simple asm function. 49 */ 50 void *_rtld_tlsdesc_static(void *); 51 void *_rtld_tlsdesc_undef(void *); 52 void *_rtld_tlsdesc_dynamic(void *); 53 54 void _exit(int); 55 56 bool 57 arch_digest_dynamic(struct Struct_Obj_Entry *obj, const Elf_Dyn *dynp) 58 { 59 if (dynp->d_tag == DT_AARCH64_VARIANT_PCS) { 60 obj->variant_pcs = true; 61 return (true); 62 } 63 64 return (false); 65 } 66 67 bool 68 arch_digest_note(struct Struct_Obj_Entry *obj __unused, const Elf_Note *note) 69 { 70 const char *note_name; 71 const uint32_t *note_data; 72 73 note_name = (const char *)(note + 1); 74 /* Only handle GNU notes */ 75 if (note->n_namesz != sizeof(ELF_NOTE_GNU) || 76 strncmp(note_name, ELF_NOTE_GNU, sizeof(ELF_NOTE_GNU)) != 0) 77 return (false); 78 79 /* Only handle GNU property notes */ 80 if (note->n_type != NT_GNU_PROPERTY_TYPE_0) 81 return (false); 82 83 /* 84 * note_data[0] - Type 85 * note_data[1] - Length 86 * note_data[2] - Data 87 * note_data[3] - Padding? 88 */ 89 note_data = (const uint32_t *)(note_name + note->n_namesz); 90 91 /* Only handle AArch64 feature notes */ 92 if (note_data[0] != GNU_PROPERTY_AARCH64_FEATURE_1_AND) 93 return (false); 94 95 /* We expect at least 4 bytes of data */ 96 if (note_data[1] < 4) 97 return (false); 98 99 /* TODO: Only guard if HWCAP2_BTI is set */ 100 if ((note_data[2] & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) != 0) { 101 struct arm64_guard_page_args guard; 102 103 guard.addr = (uintptr_t)obj->mapbase; 104 guard.len = obj->mapsize; 105 106 sysarch(ARM64_GUARD_PAGE, &guard); 107 } 108 109 return (true); 110 } 111 112 void 113 init_pltgot(Obj_Entry *obj) 114 { 115 116 if (obj->pltgot != NULL) { 117 obj->pltgot[1] = (Elf_Addr) obj; 118 obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; 119 } 120 } 121 122 int 123 do_copy_relocations(Obj_Entry *dstobj) 124 { 125 const Obj_Entry *srcobj, *defobj; 126 const Elf_Rela *relalim; 127 const Elf_Rela *rela; 128 const Elf_Sym *srcsym; 129 const Elf_Sym *dstsym; 130 const void *srcaddr; 131 const char *name; 132 void *dstaddr; 133 SymLook req; 134 size_t size; 135 int res; 136 137 /* 138 * COPY relocs are invalid outside of the main program 139 */ 140 assert(dstobj->mainprog); 141 142 relalim = (const Elf_Rela *)((const char *)dstobj->rela + 143 dstobj->relasize); 144 for (rela = dstobj->rela; rela < relalim; rela++) { 145 if (ELF_R_TYPE(rela->r_info) != R_AARCH64_COPY) 146 continue; 147 148 dstaddr = (void *)(dstobj->relocbase + rela->r_offset); 149 dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); 150 name = dstobj->strtab + dstsym->st_name; 151 size = dstsym->st_size; 152 153 symlook_init(&req, name); 154 req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info)); 155 req.flags = SYMLOOK_EARLY; 156 157 for (srcobj = globallist_next(dstobj); srcobj != NULL; 158 srcobj = globallist_next(srcobj)) { 159 res = symlook_obj(&req, srcobj); 160 if (res == 0) { 161 srcsym = req.sym_out; 162 defobj = req.defobj_out; 163 break; 164 } 165 } 166 if (srcobj == NULL) { 167 _rtld_error("Undefined symbol \"%s\" referenced from " 168 "COPY relocation in %s", name, dstobj->path); 169 return (-1); 170 } 171 172 srcaddr = (const void *)(defobj->relocbase + srcsym->st_value); 173 memcpy(dstaddr, srcaddr, size); 174 } 175 176 return (0); 177 } 178 179 struct tls_data { 180 Elf_Addr dtv_gen; 181 int tls_index; 182 Elf_Addr tls_offs; 183 }; 184 185 static struct tls_data * 186 reloc_tlsdesc_alloc(int tlsindex, Elf_Addr tlsoffs) 187 { 188 struct tls_data *tlsdesc; 189 190 tlsdesc = xmalloc(sizeof(struct tls_data)); 191 tlsdesc->dtv_gen = tls_dtv_generation; 192 tlsdesc->tls_index = tlsindex; 193 tlsdesc->tls_offs = tlsoffs; 194 195 return (tlsdesc); 196 } 197 198 struct tlsdesc_entry { 199 void *(*func)(void *); 200 union { 201 Elf_Ssize addend; 202 Elf_Size offset; 203 struct tls_data *data; 204 }; 205 }; 206 207 static void 208 reloc_tlsdesc(const Obj_Entry *obj, const Elf_Rela *rela, 209 struct tlsdesc_entry *where, int flags, RtldLockState *lockstate) 210 { 211 const Elf_Sym *def; 212 const Obj_Entry *defobj; 213 Elf_Addr offs; 214 215 offs = 0; 216 if (ELF_R_SYM(rela->r_info) != 0) { 217 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, flags, 218 NULL, lockstate); 219 if (def == NULL) 220 rtld_die(); 221 offs = def->st_value; 222 obj = defobj; 223 if (def->st_shndx == SHN_UNDEF) { 224 /* Weak undefined thread variable */ 225 where->func = _rtld_tlsdesc_undef; 226 where->addend = rela->r_addend; 227 return; 228 } 229 } 230 offs += rela->r_addend; 231 232 if (obj->tlsoffset != 0) { 233 /* Variable is in initialy allocated TLS segment */ 234 where->func = _rtld_tlsdesc_static; 235 where->offset = obj->tlsoffset + offs; 236 } else { 237 /* TLS offest is unknown at load time, use dynamic resolving */ 238 where->func = _rtld_tlsdesc_dynamic; 239 where->data = reloc_tlsdesc_alloc(obj->tlsindex, offs); 240 } 241 } 242 243 /* 244 * Process the PLT relocations. 245 */ 246 int 247 reloc_plt(Obj_Entry *obj, int flags, RtldLockState *lockstate) 248 { 249 const Obj_Entry *defobj; 250 const Elf_Rela *relalim; 251 const Elf_Rela *rela; 252 const Elf_Sym *def, *sym; 253 bool lazy; 254 255 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 256 obj->pltrelasize); 257 for (rela = obj->pltrela; rela < relalim; rela++) { 258 Elf_Addr *where, target; 259 260 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 261 262 switch(ELF_R_TYPE(rela->r_info)) { 263 case R_AARCH64_JUMP_SLOT: 264 lazy = true; 265 if (obj->variant_pcs) { 266 sym = &obj->symtab[ELF_R_SYM(rela->r_info)]; 267 /* 268 * Variant PCS functions don't follow the 269 * standard register convention. Because of 270 * this we can't use lazy relocation and 271 * need to set the target address. 272 */ 273 if ((sym->st_other & STO_AARCH64_VARIANT_PCS) != 274 0) 275 lazy = false; 276 } 277 if (lazy) { 278 *where += (Elf_Addr)obj->relocbase; 279 } else { 280 def = find_symdef(ELF_R_SYM(rela->r_info), obj, 281 &defobj, SYMLOOK_IN_PLT | flags, NULL, 282 lockstate); 283 if (def == NULL) 284 return (-1); 285 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC){ 286 obj->gnu_ifunc = true; 287 continue; 288 } 289 target = (Elf_Addr)(defobj->relocbase + 290 def->st_value); 291 /* 292 * Ignore ld_bind_not as it requires lazy 293 * binding 294 */ 295 *where = target; 296 } 297 break; 298 case R_AARCH64_TLSDESC: 299 reloc_tlsdesc(obj, rela, (struct tlsdesc_entry *)where, 300 SYMLOOK_IN_PLT | flags, lockstate); 301 break; 302 case R_AARCH64_IRELATIVE: 303 obj->irelative = true; 304 break; 305 case R_AARCH64_NONE: 306 break; 307 default: 308 _rtld_error("Unknown relocation type %u in PLT", 309 (unsigned int)ELF_R_TYPE(rela->r_info)); 310 return (-1); 311 } 312 } 313 314 return (0); 315 } 316 317 /* 318 * LD_BIND_NOW was set - force relocation for all jump slots 319 */ 320 int 321 reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate) 322 { 323 const Obj_Entry *defobj; 324 const Elf_Rela *relalim; 325 const Elf_Rela *rela; 326 const Elf_Sym *def; 327 328 if (obj->jmpslots_done) 329 return (0); 330 331 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 332 obj->pltrelasize); 333 for (rela = obj->pltrela; rela < relalim; rela++) { 334 Elf_Addr *where, target; 335 336 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 337 switch(ELF_R_TYPE(rela->r_info)) { 338 case R_AARCH64_JUMP_SLOT: 339 def = find_symdef(ELF_R_SYM(rela->r_info), obj, 340 &defobj, SYMLOOK_IN_PLT | flags, NULL, lockstate); 341 if (def == NULL) 342 return (-1); 343 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 344 obj->gnu_ifunc = true; 345 continue; 346 } 347 target = (Elf_Addr)(defobj->relocbase + def->st_value); 348 reloc_jmpslot(where, target, defobj, obj, 349 (const Elf_Rel *)rela); 350 break; 351 } 352 } 353 obj->jmpslots_done = true; 354 355 return (0); 356 } 357 358 static void 359 reloc_iresolve_one(Obj_Entry *obj, const Elf_Rela *rela, 360 RtldLockState *lockstate) 361 { 362 Elf_Addr *where, target, *ptr; 363 364 ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend); 365 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 366 lock_release(rtld_bind_lock, lockstate); 367 target = call_ifunc_resolver(ptr); 368 wlock_acquire(rtld_bind_lock, lockstate); 369 *where = target; 370 } 371 372 int 373 reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate) 374 { 375 const Elf_Rela *relalim; 376 const Elf_Rela *rela; 377 378 if (!obj->irelative) 379 return (0); 380 obj->irelative = false; 381 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 382 obj->pltrelasize); 383 for (rela = obj->pltrela; rela < relalim; rela++) { 384 if (ELF_R_TYPE(rela->r_info) == R_AARCH64_IRELATIVE) 385 reloc_iresolve_one(obj, rela, lockstate); 386 } 387 return (0); 388 } 389 390 int 391 reloc_iresolve_nonplt(Obj_Entry *obj, struct Struct_RtldLockState *lockstate) 392 { 393 const Elf_Rela *relalim; 394 const Elf_Rela *rela; 395 396 if (!obj->irelative_nonplt) 397 return (0); 398 obj->irelative_nonplt = false; 399 relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); 400 for (rela = obj->rela; rela < relalim; rela++) { 401 if (ELF_R_TYPE(rela->r_info) == R_AARCH64_IRELATIVE) 402 reloc_iresolve_one(obj, rela, lockstate); 403 } 404 return (0); 405 } 406 407 int 408 reloc_gnu_ifunc(Obj_Entry *obj, int flags, 409 struct Struct_RtldLockState *lockstate) 410 { 411 const Elf_Rela *relalim; 412 const Elf_Rela *rela; 413 Elf_Addr *where, target; 414 const Elf_Sym *def; 415 const Obj_Entry *defobj; 416 417 if (!obj->gnu_ifunc) 418 return (0); 419 relalim = (const Elf_Rela *)((const char *)obj->pltrela + obj->pltrelasize); 420 for (rela = obj->pltrela; rela < relalim; rela++) { 421 if (ELF_R_TYPE(rela->r_info) == R_AARCH64_JUMP_SLOT) { 422 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 423 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 424 SYMLOOK_IN_PLT | flags, NULL, lockstate); 425 if (def == NULL) 426 return (-1); 427 if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC) 428 continue; 429 lock_release(rtld_bind_lock, lockstate); 430 target = (Elf_Addr)rtld_resolve_ifunc(defobj, def); 431 wlock_acquire(rtld_bind_lock, lockstate); 432 reloc_jmpslot(where, target, defobj, obj, 433 (const Elf_Rel *)rela); 434 } 435 } 436 obj->gnu_ifunc = false; 437 return (0); 438 } 439 440 Elf_Addr 441 reloc_jmpslot(Elf_Addr *where, Elf_Addr target, 442 const Obj_Entry *defobj __unused, const Obj_Entry *obj __unused, 443 const Elf_Rel *rel) 444 { 445 446 assert(ELF_R_TYPE(rel->r_info) == R_AARCH64_JUMP_SLOT || 447 ELF_R_TYPE(rel->r_info) == R_AARCH64_IRELATIVE); 448 449 if (*where != target && !ld_bind_not) 450 *where = target; 451 return (target); 452 } 453 454 void 455 ifunc_init(Elf_Auxinfo *aux_info[__min_size(AT_COUNT)] __unused) 456 { 457 458 } 459 460 /* 461 * Process non-PLT relocations 462 */ 463 int 464 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, 465 RtldLockState *lockstate) 466 { 467 const Obj_Entry *defobj; 468 const Elf_Rela *relalim; 469 const Elf_Rela *rela; 470 const Elf_Sym *def; 471 SymCache *cache; 472 Elf_Addr *where, symval; 473 474 /* 475 * The dynamic loader may be called from a thread, we have 476 * limited amounts of stack available so we cannot use alloca(). 477 */ 478 if (obj == obj_rtld) 479 cache = NULL; 480 else 481 cache = calloc(obj->dynsymcount, sizeof(SymCache)); 482 /* No need to check for NULL here */ 483 484 relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); 485 for (rela = obj->rela; rela < relalim; rela++) { 486 /* 487 * First, resolve symbol for relocations which 488 * reference symbols. 489 */ 490 switch (ELF_R_TYPE(rela->r_info)) { 491 case R_AARCH64_ABS64: 492 case R_AARCH64_GLOB_DAT: 493 case R_AARCH64_TLS_TPREL64: 494 case R_AARCH64_TLS_DTPREL64: 495 case R_AARCH64_TLS_DTPMOD64: 496 def = find_symdef(ELF_R_SYM(rela->r_info), obj, 497 &defobj, flags, cache, lockstate); 498 if (def == NULL) 499 return (-1); 500 /* 501 * If symbol is IFUNC, only perform relocation 502 * when caller allowed it by passing 503 * SYMLOOK_IFUNC flag. Skip the relocations 504 * otherwise. 505 * 506 * Also error out in case IFUNC relocations 507 * are specified for TLS, which cannot be 508 * usefully interpreted. 509 */ 510 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 511 switch (ELF_R_TYPE(rela->r_info)) { 512 case R_AARCH64_ABS64: 513 case R_AARCH64_GLOB_DAT: 514 if ((flags & SYMLOOK_IFUNC) == 0) { 515 obj->non_plt_gnu_ifunc = true; 516 continue; 517 } 518 symval = (Elf_Addr)rtld_resolve_ifunc( 519 defobj, def); 520 break; 521 default: 522 _rtld_error("%s: IFUNC for TLS reloc", 523 obj->path); 524 return (-1); 525 } 526 } else { 527 if ((flags & SYMLOOK_IFUNC) != 0) 528 continue; 529 symval = (Elf_Addr)defobj->relocbase + 530 def->st_value; 531 } 532 break; 533 default: 534 if ((flags & SYMLOOK_IFUNC) != 0) 535 continue; 536 } 537 538 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 539 540 switch (ELF_R_TYPE(rela->r_info)) { 541 case R_AARCH64_ABS64: 542 case R_AARCH64_GLOB_DAT: 543 *where = symval + rela->r_addend; 544 break; 545 case R_AARCH64_COPY: 546 /* 547 * These are deferred until all other relocations have 548 * been done. All we do here is make sure that the 549 * COPY relocation is not in a shared library. They 550 * are allowed only in executable files. 551 */ 552 if (!obj->mainprog) { 553 _rtld_error("%s: Unexpected R_AARCH64_COPY " 554 "relocation in shared library", obj->path); 555 return (-1); 556 } 557 break; 558 case R_AARCH64_TLSDESC: 559 reloc_tlsdesc(obj, rela, (struct tlsdesc_entry *)where, 560 flags, lockstate); 561 break; 562 case R_AARCH64_TLS_TPREL64: 563 /* 564 * We lazily allocate offsets for static TLS as we 565 * see the first relocation that references the 566 * TLS block. This allows us to support (small 567 * amounts of) static TLS in dynamically loaded 568 * modules. If we run out of space, we generate an 569 * error. 570 */ 571 if (!defobj->tls_static) { 572 if (!allocate_tls_offset( 573 __DECONST(Obj_Entry *, defobj))) { 574 _rtld_error( 575 "%s: No space available for static " 576 "Thread Local Storage", obj->path); 577 return (-1); 578 } 579 } 580 *where = def->st_value + rela->r_addend + 581 defobj->tlsoffset; 582 break; 583 584 /* 585 * !!! BEWARE !!! 586 * ARM ELF ABI defines TLS_DTPMOD64 as 1029, and TLS_DTPREL64 587 * as 1028. But actual bfd linker and the glibc RTLD linker 588 * treats TLS_DTPMOD64 as 1028 and TLS_DTPREL64 1029. 589 */ 590 case R_AARCH64_TLS_DTPREL64: /* efectively is TLS_DTPMOD64 */ 591 *where += (Elf_Addr)defobj->tlsindex; 592 break; 593 case R_AARCH64_TLS_DTPMOD64: /* efectively is TLS_DTPREL64 */ 594 *where += (Elf_Addr)(def->st_value + rela->r_addend); 595 break; 596 case R_AARCH64_RELATIVE: 597 *where = (Elf_Addr)(obj->relocbase + rela->r_addend); 598 break; 599 case R_AARCH64_NONE: 600 break; 601 case R_AARCH64_IRELATIVE: 602 obj->irelative_nonplt = true; 603 break; 604 default: 605 rtld_printf("%s: Unhandled relocation %lu\n", 606 obj->path, ELF_R_TYPE(rela->r_info)); 607 return (-1); 608 } 609 } 610 611 return (0); 612 } 613 614 void 615 allocate_initial_tls(Obj_Entry *objs) 616 { 617 618 /* 619 * Fix the size of the static TLS block by using the maximum 620 * offset allocated so far and adding a bit for dynamic modules to 621 * use. 622 */ 623 tls_static_space = tls_last_offset + tls_last_size + 624 ld_static_tls_extra; 625 626 _tcb_set(allocate_tls(objs, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN)); 627 } 628 629 void * 630 __tls_get_addr(tls_index* ti) 631 { 632 uintptr_t **dtvp; 633 634 dtvp = &_tcb_get()->tcb_dtv; 635 return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset)); 636 } 637