1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright 1996, 1997, 1998, 1999 John D. Polstra. 5 * All rights reserved. 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 ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* 29 * Dynamic linker for ELF. 30 * 31 * John Polstra <jdp@polstra.com>. 32 */ 33 34 #define _WANT_P_OSREL 35 #include <sys/param.h> 36 #include <sys/mman.h> 37 38 #include <machine/cpufunc.h> 39 #include <machine/specialreg.h> 40 #include <machine/sysarch.h> 41 42 #include <dlfcn.h> 43 #include <err.h> 44 #include <errno.h> 45 #include <fcntl.h> 46 #include <stdarg.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <unistd.h> 51 52 #include "debug.h" 53 #include "rtld.h" 54 #include "rtld_tls.h" 55 56 /* 57 * Process the special R_X86_64_COPY relocations in the main program. These 58 * copy data from a shared object into a region in the main program's BSS 59 * segment. 60 * 61 * Returns 0 on success, -1 on failure. 62 */ 63 int 64 do_copy_relocations(Obj_Entry *dstobj) 65 { 66 const Elf_Rela *relalim; 67 const Elf_Rela *rela; 68 69 assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */ 70 71 relalim = (const Elf_Rela *)((const char *)dstobj->rela + 72 dstobj->relasize); 73 for (rela = dstobj->rela; rela < relalim; rela++) { 74 if (ELF_R_TYPE(rela->r_info) == R_X86_64_COPY) { 75 void *dstaddr; 76 const Elf_Sym *dstsym; 77 const char *name; 78 size_t size; 79 const void *srcaddr; 80 const Elf_Sym *srcsym; 81 const Obj_Entry *srcobj, *defobj; 82 SymLook req; 83 int res; 84 85 dstaddr = (void *)(dstobj->relocbase + rela->r_offset); 86 dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); 87 name = dstobj->strtab + dstsym->st_name; 88 size = dstsym->st_size; 89 symlook_init(&req, name); 90 req.ventry = fetch_ventry(dstobj, 91 ELF_R_SYM(rela->r_info)); 92 req.flags = SYMLOOK_EARLY; 93 94 for (srcobj = globallist_next(dstobj); srcobj != NULL; 95 srcobj = globallist_next(srcobj)) { 96 res = symlook_obj(&req, srcobj); 97 if (res == 0) { 98 srcsym = req.sym_out; 99 defobj = req.defobj_out; 100 break; 101 } 102 } 103 104 if (srcobj == NULL) { 105 _rtld_error( 106 "Undefined symbol \"%s\" referenced from COPY relocation in %s", 107 name, dstobj->path); 108 return (-1); 109 } 110 111 srcaddr = (const void *)(defobj->relocbase + 112 srcsym->st_value); 113 memcpy(dstaddr, srcaddr, size); 114 } 115 } 116 117 return (0); 118 } 119 120 /* Initialize the special GOT entries. */ 121 void 122 init_pltgot(Obj_Entry *obj) 123 { 124 if (obj->pltgot != NULL) { 125 obj->pltgot[1] = (Elf_Addr)obj; 126 obj->pltgot[2] = (Elf_Addr)&_rtld_bind_start; 127 } 128 } 129 130 /* Process the non-PLT relocations. */ 131 int 132 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, 133 RtldLockState *lockstate) 134 { 135 const Elf_Rela *relalim; 136 const Elf_Rela *rela; 137 SymCache *cache; 138 const Elf_Sym *def; 139 const Obj_Entry *defobj; 140 Elf_Addr *where, symval; 141 Elf32_Addr *where32; 142 int r; 143 144 r = -1; 145 symval = 0; 146 def = NULL; 147 148 /* 149 * The dynamic loader may be called from a thread, we have 150 * limited amounts of stack available so we cannot use alloca(). 151 */ 152 if (obj != obj_rtld) { 153 cache = calloc(obj->dynsymcount, sizeof(SymCache)); 154 /* No need to check for NULL here */ 155 } else 156 cache = NULL; 157 158 relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); 159 for (rela = obj->rela; rela < relalim; rela++) { 160 /* 161 * First, resolve symbol for relocations which 162 * reference symbols. 163 */ 164 switch (ELF_R_TYPE(rela->r_info)) { 165 case R_X86_64_64: 166 case R_X86_64_PC32: 167 case R_X86_64_GLOB_DAT: 168 case R_X86_64_TPOFF64: 169 case R_X86_64_TPOFF32: 170 case R_X86_64_DTPMOD64: 171 case R_X86_64_DTPOFF64: 172 case R_X86_64_DTPOFF32: 173 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 174 flags, cache, lockstate); 175 if (def == NULL) 176 goto done; 177 178 /* 179 * If symbol is IFUNC, only perform relocation 180 * when caller allowed it by passing 181 * SYMLOOK_IFUNC flag. Skip the relocations 182 * otherwise. 183 * 184 * Also error out in case IFUNC relocations 185 * are specified for TLS, which cannot be 186 * usefully interpreted. 187 */ 188 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 189 switch (ELF_R_TYPE(rela->r_info)) { 190 case R_X86_64_64: 191 case R_X86_64_PC32: 192 case R_X86_64_GLOB_DAT: 193 if ((flags & SYMLOOK_IFUNC) == 0) { 194 obj->non_plt_gnu_ifunc = true; 195 continue; 196 } 197 symval = (Elf_Addr)rtld_resolve_ifunc( 198 defobj, def); 199 break; 200 case R_X86_64_TPOFF64: 201 case R_X86_64_TPOFF32: 202 case R_X86_64_DTPMOD64: 203 case R_X86_64_DTPOFF64: 204 case R_X86_64_DTPOFF32: 205 _rtld_error("%s: IFUNC for TLS reloc", 206 obj->path); 207 goto done; 208 } 209 } else { 210 if ((flags & SYMLOOK_IFUNC) != 0) 211 continue; 212 symval = (Elf_Addr)defobj->relocbase + 213 def->st_value; 214 } 215 break; 216 default: 217 if ((flags & SYMLOOK_IFUNC) != 0) 218 continue; 219 break; 220 } 221 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 222 where32 = (Elf32_Addr *)where; 223 224 switch (ELF_R_TYPE(rela->r_info)) { 225 case R_X86_64_NONE: 226 break; 227 case R_X86_64_64: 228 *where = symval + rela->r_addend; 229 break; 230 case R_X86_64_PC32: 231 /* 232 * I don't think the dynamic linker should 233 * ever see this type of relocation. But the 234 * binutils-2.6 tools sometimes generate it. 235 */ 236 *where32 = (Elf32_Addr)(unsigned long)(symval + 237 rela->r_addend - (Elf_Addr)where); 238 break; 239 /* missing: R_X86_64_GOT32 R_X86_64_PLT32 */ 240 case R_X86_64_COPY: 241 /* 242 * These are deferred until all other 243 * relocations have been done. All we do here 244 * is make sure that the COPY relocation is 245 * not in a shared library. They are allowed 246 * only in executable files. 247 */ 248 if (!obj->mainprog) { 249 _rtld_error( 250 "%s: Unexpected R_X86_64_COPY relocation in shared library", 251 obj->path); 252 goto done; 253 } 254 break; 255 case R_X86_64_GLOB_DAT: 256 *where = symval; 257 break; 258 case R_X86_64_TPOFF64: 259 /* 260 * We lazily allocate offsets for static TLS 261 * as we see the first relocation that 262 * references the TLS block. This allows us to 263 * support (small amounts of) static TLS in 264 * dynamically loaded modules. If we run out 265 * of space, we generate an error. 266 */ 267 if (!defobj->tls_static) { 268 if (!allocate_tls_offset(__DECONST(Obj_Entry *, 269 defobj))) { 270 _rtld_error( 271 "%s: No space available for static Thread Local Storage", 272 obj->path); 273 goto done; 274 } 275 } 276 *where = (Elf_Addr)(def->st_value - defobj->tlsoffset + 277 rela->r_addend); 278 break; 279 case R_X86_64_TPOFF32: 280 /* 281 * We lazily allocate offsets for static TLS 282 * as we see the first relocation that 283 * references the TLS block. This allows us to 284 * support (small amounts of) static TLS in 285 * dynamically loaded modules. If we run out 286 * of space, we generate an error. 287 */ 288 if (!defobj->tls_static) { 289 if (!allocate_tls_offset(__DECONST(Obj_Entry *, 290 defobj))) { 291 _rtld_error( 292 "%s: No space available for static Thread Local Storage", 293 obj->path); 294 goto done; 295 } 296 } 297 *where32 = (Elf32_Addr)(def->st_value - 298 defobj->tlsoffset + rela->r_addend); 299 break; 300 case R_X86_64_DTPMOD64: 301 *where += (Elf_Addr)defobj->tlsindex; 302 break; 303 case R_X86_64_DTPOFF64: 304 *where += (Elf_Addr)(def->st_value + rela->r_addend); 305 break; 306 case R_X86_64_DTPOFF32: 307 *where32 += (Elf32_Addr)(def->st_value + 308 rela->r_addend); 309 break; 310 case R_X86_64_RELATIVE: 311 *where = (Elf_Addr)(obj->relocbase + rela->r_addend); 312 break; 313 case R_X86_64_IRELATIVE: 314 obj->irelative_nonplt = true; 315 break; 316 317 /* 318 * missing: 319 * R_X86_64_GOTPCREL, R_X86_64_32, R_X86_64_32S, R_X86_64_16, 320 * R_X86_64_PC16, R_X86_64_8, R_X86_64_PC8 321 */ 322 default: 323 _rtld_error( 324 "%s: Unsupported relocation type %u in non-PLT relocations", 325 obj->path, (unsigned int)ELF_R_TYPE(rela->r_info)); 326 goto done; 327 } 328 } 329 r = 0; 330 done: 331 free(cache); 332 return (r); 333 } 334 335 /* Process the PLT relocations. */ 336 int 337 reloc_plt(Obj_Entry *obj, int flags __unused, RtldLockState *lockstate __unused) 338 { 339 const Elf_Rela *relalim; 340 const Elf_Rela *rela; 341 342 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 343 obj->pltrelasize); 344 for (rela = obj->pltrela; rela < relalim; rela++) { 345 Elf_Addr *where; 346 347 switch (ELF_R_TYPE(rela->r_info)) { 348 case R_X86_64_JMP_SLOT: 349 /* Relocate the GOT slot pointing into the PLT. */ 350 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 351 *where += (Elf_Addr)obj->relocbase; 352 break; 353 354 case R_X86_64_IRELATIVE: 355 obj->irelative = true; 356 break; 357 358 default: 359 _rtld_error("Unknown relocation type %x in PLT", 360 (unsigned int)ELF_R_TYPE(rela->r_info)); 361 return (-1); 362 } 363 } 364 return (0); 365 } 366 367 /* Relocate the jump slots in an object. */ 368 int 369 reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate) 370 { 371 const Elf_Rela *relalim; 372 const Elf_Rela *rela; 373 374 if (obj->jmpslots_done) 375 return (0); 376 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 377 obj->pltrelasize); 378 for (rela = obj->pltrela; rela < relalim; rela++) { 379 Elf_Addr *where, target; 380 const Elf_Sym *def; 381 const Obj_Entry *defobj; 382 383 switch (ELF_R_TYPE(rela->r_info)) { 384 case R_X86_64_JMP_SLOT: 385 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 386 def = find_symdef(ELF_R_SYM(rela->r_info), obj, 387 &defobj, SYMLOOK_IN_PLT | flags, NULL, lockstate); 388 if (def == NULL) 389 return (-1); 390 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 391 obj->gnu_ifunc = true; 392 continue; 393 } 394 target = (Elf_Addr)(defobj->relocbase + def->st_value + 395 rela->r_addend); 396 reloc_jmpslot(where, target, defobj, obj, 397 (const Elf_Rel *)rela); 398 break; 399 400 case R_X86_64_IRELATIVE: 401 break; 402 403 default: 404 _rtld_error("Unknown relocation type %x in PLT", 405 (unsigned int)ELF_R_TYPE(rela->r_info)); 406 return (-1); 407 } 408 } 409 obj->jmpslots_done = true; 410 return (0); 411 } 412 413 /* Fixup the jump slot at "where" to transfer control to "target". */ 414 Elf_Addr 415 reloc_jmpslot(Elf_Addr *where, Elf_Addr target, 416 const struct Struct_Obj_Entry *obj __unused, 417 const struct Struct_Obj_Entry *refobj __unused, const Elf_Rel *rel __unused) 418 { 419 dbg("reloc_jmpslot: *%p = %p", where, (void *)target); 420 if (!ld_bind_not) 421 *where = target; 422 return (target); 423 } 424 425 static void 426 reloc_iresolve_one(Obj_Entry *obj, const Elf_Rela *rela, 427 RtldLockState *lockstate) 428 { 429 Elf_Addr *where, target, *ptr; 430 431 ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend); 432 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 433 lock_release(rtld_bind_lock, lockstate); 434 target = call_ifunc_resolver(ptr); 435 wlock_acquire(rtld_bind_lock, lockstate); 436 *where = target; 437 } 438 439 int 440 reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate) 441 { 442 const Elf_Rela *relalim; 443 const Elf_Rela *rela; 444 445 if (!obj->irelative) 446 return (0); 447 obj->irelative = false; 448 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 449 obj->pltrelasize); 450 for (rela = obj->pltrela; rela < relalim; rela++) { 451 if (ELF_R_TYPE(rela->r_info) == R_X86_64_IRELATIVE) 452 reloc_iresolve_one(obj, rela, lockstate); 453 } 454 return (0); 455 } 456 457 int 458 reloc_iresolve_nonplt(Obj_Entry *obj, RtldLockState *lockstate) 459 { 460 const Elf_Rela *relalim; 461 const Elf_Rela *rela; 462 463 if (!obj->irelative_nonplt) 464 return (0); 465 obj->irelative_nonplt = false; 466 relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); 467 for (rela = obj->rela; rela < relalim; rela++) { 468 if (ELF_R_TYPE(rela->r_info) == R_X86_64_IRELATIVE) 469 reloc_iresolve_one(obj, rela, lockstate); 470 } 471 return (0); 472 } 473 474 int 475 reloc_gnu_ifunc(Obj_Entry *obj, int flags, RtldLockState *lockstate) 476 { 477 const Elf_Rela *relalim; 478 const Elf_Rela *rela; 479 480 if (!obj->gnu_ifunc) 481 return (0); 482 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 483 obj->pltrelasize); 484 for (rela = obj->pltrela; rela < relalim; rela++) { 485 Elf_Addr *where, target; 486 const Elf_Sym *def; 487 const Obj_Entry *defobj; 488 489 switch (ELF_R_TYPE(rela->r_info)) { 490 case R_X86_64_JMP_SLOT: 491 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 492 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 493 SYMLOOK_IN_PLT | flags, NULL, lockstate); 494 if (def == NULL) 495 return (-1); 496 if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC) 497 continue; 498 lock_release(rtld_bind_lock, lockstate); 499 target = (Elf_Addr)rtld_resolve_ifunc(defobj, def); 500 wlock_acquire(rtld_bind_lock, lockstate); 501 reloc_jmpslot(where, target, defobj, obj, 502 (const Elf_Rel *)rela); 503 break; 504 } 505 } 506 obj->gnu_ifunc = false; 507 return (0); 508 } 509 510 uint32_t cpu_feature, cpu_feature2, cpu_stdext_feature, cpu_stdext_feature2; 511 512 void 513 ifunc_init(Elf_Auxinfo *aux_info[__min_size(AT_COUNT)] __unused) 514 { 515 u_int p[4], cpu_high; 516 517 do_cpuid(1, p); 518 cpu_feature = p[3]; 519 cpu_feature2 = p[2]; 520 do_cpuid(0, p); 521 cpu_high = p[0]; 522 if (cpu_high >= 7) { 523 cpuid_count(7, 0, p); 524 cpu_stdext_feature = p[1]; 525 cpu_stdext_feature2 = p[2]; 526 } 527 } 528 529 int __getosreldate(void); 530 531 void 532 allocate_initial_tls(Obj_Entry *objs) 533 { 534 void *addr; 535 536 /* 537 * Fix the size of the static TLS block by using the maximum 538 * offset allocated so far and adding a bit for dynamic 539 * modules to use. 540 */ 541 tls_static_space = tls_last_offset + ld_static_tls_extra; 542 543 addr = allocate_tls(objs, 0, TLS_TCB_SIZE, TLS_TCB_ALIGN); 544 545 /* 546 * This does not use _tcb_set() as it calls amd64_set_fsbase() 547 * which is an ifunc and rtld must not use ifuncs. 548 */ 549 if (__getosreldate() >= P_OSREL_WRFSBASE && 550 (cpu_stdext_feature & CPUID_STDEXT_FSGSBASE) != 0) 551 wrfsbase((uintptr_t)addr); 552 else 553 sysarch(AMD64_SET_FSBASE, &addr); 554 } 555 556 void * 557 __tls_get_addr(tls_index *ti) 558 { 559 uintptr_t **dtvp; 560 561 dtvp = &_tcb_get()->tcb_dtv; 562 return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset)); 563 } 564 565 size_t 566 calculate_tls_offset(size_t prev_offset, size_t prev_size __unused, size_t size, 567 size_t align, size_t offset) 568 { 569 size_t res; 570 571 /* 572 * res is the smallest integer satisfying res - prev_offset >= size 573 * and (-res) % p_align = p_vaddr % p_align (= p_offset % p_align). 574 */ 575 res = prev_offset + size + align - 1; 576 res -= (res + offset) & (align - 1); 577 return (res); 578 } 579 580 size_t 581 calculate_first_tls_offset(size_t size, size_t align, size_t offset) 582 { 583 return (calculate_tls_offset(0, 0, size, align, offset)); 584 } 585