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 <stdlib.h> 33 34 #include "debug.h" 35 #include "rtld.h" 36 #include "rtld_printf.h" 37 38 /* 39 * It is possible for the compiler to emit relocations for unaligned data. 40 * We handle this situation with these inlines. 41 */ 42 #define RELOC_ALIGNED_P(x) \ 43 (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0) 44 45 /* 46 * This is not the correct prototype, but we only need it for 47 * a function pointer to a simple asm function. 48 */ 49 void *_rtld_tlsdesc_static(void *); 50 void *_rtld_tlsdesc_undef(void *); 51 void *_rtld_tlsdesc_dynamic(void *); 52 53 void _exit(int); 54 55 void 56 init_pltgot(Obj_Entry *obj) 57 { 58 59 if (obj->pltgot != NULL) { 60 obj->pltgot[1] = (Elf_Addr) obj; 61 obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; 62 } 63 } 64 65 int 66 do_copy_relocations(Obj_Entry *dstobj) 67 { 68 const Obj_Entry *srcobj, *defobj; 69 const Elf_Rela *relalim; 70 const Elf_Rela *rela; 71 const Elf_Sym *srcsym; 72 const Elf_Sym *dstsym; 73 const void *srcaddr; 74 const char *name; 75 void *dstaddr; 76 SymLook req; 77 size_t size; 78 int res; 79 80 /* 81 * COPY relocs are invalid outside of the main program 82 */ 83 assert(dstobj->mainprog); 84 85 relalim = (const Elf_Rela *)((const char *)dstobj->rela + 86 dstobj->relasize); 87 for (rela = dstobj->rela; rela < relalim; rela++) { 88 if (ELF_R_TYPE(rela->r_info) != R_AARCH64_COPY) 89 continue; 90 91 dstaddr = (void *)(dstobj->relocbase + rela->r_offset); 92 dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); 93 name = dstobj->strtab + dstsym->st_name; 94 size = dstsym->st_size; 95 96 symlook_init(&req, name); 97 req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info)); 98 req.flags = SYMLOOK_EARLY; 99 100 for (srcobj = globallist_next(dstobj); srcobj != NULL; 101 srcobj = globallist_next(srcobj)) { 102 res = symlook_obj(&req, srcobj); 103 if (res == 0) { 104 srcsym = req.sym_out; 105 defobj = req.defobj_out; 106 break; 107 } 108 } 109 if (srcobj == NULL) { 110 _rtld_error("Undefined symbol \"%s\" referenced from " 111 "COPY relocation in %s", name, dstobj->path); 112 return (-1); 113 } 114 115 srcaddr = (const void *)(defobj->relocbase + srcsym->st_value); 116 memcpy(dstaddr, srcaddr, size); 117 } 118 119 return (0); 120 } 121 122 struct tls_data { 123 Elf_Addr dtv_gen; 124 int tls_index; 125 Elf_Addr tls_offs; 126 }; 127 128 static Elf_Addr 129 reloc_tlsdesc_alloc(int tlsindex, Elf_Addr tlsoffs) 130 { 131 struct tls_data *tlsdesc; 132 133 tlsdesc = xmalloc(sizeof(struct tls_data)); 134 tlsdesc->dtv_gen = tls_dtv_generation; 135 tlsdesc->tls_index = tlsindex; 136 tlsdesc->tls_offs = tlsoffs; 137 138 return ((Elf_Addr)tlsdesc); 139 } 140 141 static void 142 reloc_tlsdesc(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *where, 143 int flags, RtldLockState *lockstate) 144 { 145 const Elf_Sym *def; 146 const Obj_Entry *defobj; 147 Elf_Addr offs; 148 149 150 offs = 0; 151 if (ELF_R_SYM(rela->r_info) != 0) { 152 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, flags, 153 NULL, lockstate); 154 if (def == NULL) 155 rtld_die(); 156 offs = def->st_value; 157 obj = defobj; 158 if (def->st_shndx == SHN_UNDEF) { 159 /* Weak undefined thread variable */ 160 where[0] = (Elf_Addr)_rtld_tlsdesc_undef; 161 where[1] = rela->r_addend; 162 return; 163 } 164 } 165 offs += rela->r_addend; 166 167 if (obj->tlsoffset != 0) { 168 /* Variable is in initialy allocated TLS segment */ 169 where[0] = (Elf_Addr)_rtld_tlsdesc_static; 170 where[1] = obj->tlsoffset + offs; 171 } else { 172 /* TLS offest is unknown at load time, use dynamic resolving */ 173 where[0] = (Elf_Addr)_rtld_tlsdesc_dynamic; 174 where[1] = reloc_tlsdesc_alloc(obj->tlsindex, offs); 175 } 176 } 177 178 /* 179 * Process the PLT relocations. 180 */ 181 int 182 reloc_plt(Obj_Entry *obj, int flags, RtldLockState *lockstate) 183 { 184 const Elf_Rela *relalim; 185 const Elf_Rela *rela; 186 187 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 188 obj->pltrelasize); 189 for (rela = obj->pltrela; rela < relalim; rela++) { 190 Elf_Addr *where; 191 192 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 193 194 switch(ELF_R_TYPE(rela->r_info)) { 195 case R_AARCH64_JUMP_SLOT: 196 *where += (Elf_Addr)obj->relocbase; 197 break; 198 case R_AARCH64_TLSDESC: 199 reloc_tlsdesc(obj, rela, where, SYMLOOK_IN_PLT | flags, 200 lockstate); 201 break; 202 case R_AARCH64_IRELATIVE: 203 obj->irelative = true; 204 break; 205 case R_AARCH64_NONE: 206 break; 207 default: 208 _rtld_error("Unknown relocation type %u in PLT", 209 (unsigned int)ELF_R_TYPE(rela->r_info)); 210 return (-1); 211 } 212 } 213 214 return (0); 215 } 216 217 /* 218 * LD_BIND_NOW was set - force relocation for all jump slots 219 */ 220 int 221 reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate) 222 { 223 const Obj_Entry *defobj; 224 const Elf_Rela *relalim; 225 const Elf_Rela *rela; 226 const Elf_Sym *def; 227 228 if (obj->jmpslots_done) 229 return (0); 230 231 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 232 obj->pltrelasize); 233 for (rela = obj->pltrela; rela < relalim; rela++) { 234 Elf_Addr *where, target; 235 236 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 237 switch(ELF_R_TYPE(rela->r_info)) { 238 case R_AARCH64_JUMP_SLOT: 239 def = find_symdef(ELF_R_SYM(rela->r_info), obj, 240 &defobj, SYMLOOK_IN_PLT | flags, NULL, lockstate); 241 if (def == NULL) 242 return (-1); 243 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 244 obj->gnu_ifunc = true; 245 continue; 246 } 247 target = (Elf_Addr)(defobj->relocbase + def->st_value); 248 reloc_jmpslot(where, target, defobj, obj, 249 (const Elf_Rel *)rela); 250 break; 251 } 252 } 253 obj->jmpslots_done = true; 254 255 return (0); 256 } 257 258 static void 259 reloc_iresolve_one(Obj_Entry *obj, const Elf_Rela *rela, 260 RtldLockState *lockstate) 261 { 262 Elf_Addr *where, target, *ptr; 263 264 ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend); 265 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 266 lock_release(rtld_bind_lock, lockstate); 267 target = call_ifunc_resolver(ptr); 268 wlock_acquire(rtld_bind_lock, lockstate); 269 *where = target; 270 } 271 272 int 273 reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate) 274 { 275 const Elf_Rela *relalim; 276 const Elf_Rela *rela; 277 278 if (!obj->irelative) 279 return (0); 280 obj->irelative = false; 281 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 282 obj->pltrelasize); 283 for (rela = obj->pltrela; rela < relalim; rela++) { 284 if (ELF_R_TYPE(rela->r_info) == R_AARCH64_IRELATIVE) 285 reloc_iresolve_one(obj, rela, lockstate); 286 } 287 return (0); 288 } 289 290 int 291 reloc_iresolve_nonplt(Obj_Entry *obj, struct Struct_RtldLockState *lockstate) 292 { 293 const Elf_Rela *relalim; 294 const Elf_Rela *rela; 295 296 if (!obj->irelative_nonplt) 297 return (0); 298 obj->irelative_nonplt = false; 299 relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); 300 for (rela = obj->rela; rela < relalim; rela++) { 301 if (ELF_R_TYPE(rela->r_info) == R_AARCH64_IRELATIVE) 302 reloc_iresolve_one(obj, rela, lockstate); 303 } 304 return (0); 305 } 306 307 int 308 reloc_gnu_ifunc(Obj_Entry *obj, int flags, 309 struct Struct_RtldLockState *lockstate) 310 { 311 const Elf_Rela *relalim; 312 const Elf_Rela *rela; 313 Elf_Addr *where, target; 314 const Elf_Sym *def; 315 const Obj_Entry *defobj; 316 317 if (!obj->gnu_ifunc) 318 return (0); 319 relalim = (const Elf_Rela *)((const char *)obj->pltrela + obj->pltrelasize); 320 for (rela = obj->pltrela; rela < relalim; rela++) { 321 if (ELF_R_TYPE(rela->r_info) == R_AARCH64_JUMP_SLOT) { 322 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 323 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 324 SYMLOOK_IN_PLT | flags, NULL, lockstate); 325 if (def == NULL) 326 return (-1); 327 if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC) 328 continue; 329 lock_release(rtld_bind_lock, lockstate); 330 target = (Elf_Addr)rtld_resolve_ifunc(defobj, def); 331 wlock_acquire(rtld_bind_lock, lockstate); 332 reloc_jmpslot(where, target, defobj, obj, 333 (const Elf_Rel *)rela); 334 } 335 } 336 obj->gnu_ifunc = false; 337 return (0); 338 } 339 340 Elf_Addr 341 reloc_jmpslot(Elf_Addr *where, Elf_Addr target, 342 const Obj_Entry *defobj __unused, const Obj_Entry *obj __unused, 343 const Elf_Rel *rel) 344 { 345 346 assert(ELF_R_TYPE(rel->r_info) == R_AARCH64_JUMP_SLOT || 347 ELF_R_TYPE(rel->r_info) == R_AARCH64_IRELATIVE); 348 349 if (*where != target && !ld_bind_not) 350 *where = target; 351 return (target); 352 } 353 354 void 355 ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused) 356 { 357 358 } 359 360 /* 361 * Process non-PLT relocations 362 */ 363 int 364 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, 365 RtldLockState *lockstate) 366 { 367 const Obj_Entry *defobj; 368 const Elf_Rela *relalim; 369 const Elf_Rela *rela; 370 const Elf_Sym *def; 371 SymCache *cache; 372 Elf_Addr *where, symval; 373 374 /* 375 * The dynamic loader may be called from a thread, we have 376 * limited amounts of stack available so we cannot use alloca(). 377 */ 378 if (obj == obj_rtld) 379 cache = NULL; 380 else 381 cache = calloc(obj->dynsymcount, sizeof(SymCache)); 382 /* No need to check for NULL here */ 383 384 relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); 385 for (rela = obj->rela; rela < relalim; rela++) { 386 /* 387 * First, resolve symbol for relocations which 388 * reference symbols. 389 */ 390 switch (ELF_R_TYPE(rela->r_info)) { 391 case R_AARCH64_ABS64: 392 case R_AARCH64_GLOB_DAT: 393 case R_AARCH64_TLS_TPREL64: 394 case R_AARCH64_TLS_DTPREL64: 395 case R_AARCH64_TLS_DTPMOD64: 396 def = find_symdef(ELF_R_SYM(rela->r_info), obj, 397 &defobj, flags, cache, lockstate); 398 if (def == NULL) 399 return (-1); 400 /* 401 * If symbol is IFUNC, only perform relocation 402 * when caller allowed it by passing 403 * SYMLOOK_IFUNC flag. Skip the relocations 404 * otherwise. 405 * 406 * Also error out in case IFUNC relocations 407 * are specified for TLS, which cannot be 408 * usefully interpreted. 409 */ 410 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 411 switch (ELF_R_TYPE(rela->r_info)) { 412 case R_AARCH64_ABS64: 413 case R_AARCH64_GLOB_DAT: 414 if ((flags & SYMLOOK_IFUNC) == 0) { 415 obj->non_plt_gnu_ifunc = true; 416 continue; 417 } 418 symval = (Elf_Addr)rtld_resolve_ifunc( 419 defobj, def); 420 break; 421 default: 422 _rtld_error("%s: IFUNC for TLS reloc", 423 obj->path); 424 return (-1); 425 } 426 } else { 427 if ((flags & SYMLOOK_IFUNC) != 0) 428 continue; 429 symval = (Elf_Addr)defobj->relocbase + 430 def->st_value; 431 } 432 break; 433 default: 434 if ((flags & SYMLOOK_IFUNC) != 0) 435 continue; 436 } 437 438 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 439 440 switch (ELF_R_TYPE(rela->r_info)) { 441 case R_AARCH64_ABS64: 442 case R_AARCH64_GLOB_DAT: 443 *where = symval + rela->r_addend; 444 break; 445 case R_AARCH64_COPY: 446 /* 447 * These are deferred until all other relocations have 448 * been done. All we do here is make sure that the 449 * COPY relocation is not in a shared library. They 450 * are allowed only in executable files. 451 */ 452 if (!obj->mainprog) { 453 _rtld_error("%s: Unexpected R_AARCH64_COPY " 454 "relocation in shared library", obj->path); 455 return (-1); 456 } 457 break; 458 case R_AARCH64_TLSDESC: 459 reloc_tlsdesc(obj, rela, where, flags, lockstate); 460 break; 461 case R_AARCH64_TLS_TPREL64: 462 /* 463 * We lazily allocate offsets for static TLS as we 464 * see the first relocation that references the 465 * TLS block. This allows us to support (small 466 * amounts of) static TLS in dynamically loaded 467 * modules. If we run out of space, we generate an 468 * error. 469 */ 470 if (!defobj->tls_static) { 471 if (!allocate_tls_offset( 472 __DECONST(Obj_Entry *, defobj))) { 473 _rtld_error( 474 "%s: No space available for static " 475 "Thread Local Storage", obj->path); 476 return (-1); 477 } 478 } 479 *where = def->st_value + rela->r_addend + 480 defobj->tlsoffset; 481 break; 482 483 /* 484 * !!! BEWARE !!! 485 * ARM ELF ABI defines TLS_DTPMOD64 as 1029, and TLS_DTPREL64 486 * as 1028. But actual bfd linker and the glibc RTLD linker 487 * treats TLS_DTPMOD64 as 1028 and TLS_DTPREL64 1029. 488 */ 489 case R_AARCH64_TLS_DTPREL64: /* efectively is TLS_DTPMOD64 */ 490 *where += (Elf_Addr)defobj->tlsindex; 491 break; 492 case R_AARCH64_TLS_DTPMOD64: /* efectively is TLS_DTPREL64 */ 493 *where += (Elf_Addr)(def->st_value + rela->r_addend); 494 break; 495 case R_AARCH64_RELATIVE: 496 *where = (Elf_Addr)(obj->relocbase + rela->r_addend); 497 break; 498 case R_AARCH64_NONE: 499 break; 500 case R_AARCH64_IRELATIVE: 501 obj->irelative_nonplt = true; 502 break; 503 default: 504 rtld_printf("%s: Unhandled relocation %lu\n", 505 obj->path, ELF_R_TYPE(rela->r_info)); 506 return (-1); 507 } 508 } 509 510 return (0); 511 } 512 513 void 514 allocate_initial_tls(Obj_Entry *objs) 515 { 516 517 /* 518 * Fix the size of the static TLS block by using the maximum 519 * offset allocated so far and adding a bit for dynamic modules to 520 * use. 521 */ 522 tls_static_space = tls_last_offset + tls_last_size + 523 ld_static_tls_extra; 524 525 _tcb_set(allocate_tls(objs, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN)); 526 } 527 528 void * 529 __tls_get_addr(tls_index* ti) 530 { 531 uintptr_t **dtvp; 532 533 dtvp = &_tcb_get()->tcb_dtv; 534 return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset)); 535 } 536