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