1 /*- 2 * Copyright 1996, 1997, 1998, 1999 John D. Polstra. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 * $FreeBSD$ 26 */ 27 28 /* 29 * Dynamic linker for ELF. 30 * 31 * John Polstra <jdp@polstra.com>. 32 */ 33 34 #include <sys/param.h> 35 #include <sys/mman.h> 36 #include <sys/tls.h> 37 38 #include <machine/sysarch.h> 39 #include <machine/tls.h> 40 41 #include <dlfcn.h> 42 #include <err.h> 43 #include <errno.h> 44 #include <fcntl.h> 45 #include <stdarg.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <unistd.h> 50 51 #include "debug.h" 52 #include "rtld.h" 53 54 /* 55 * Process the special R_X86_64_COPY relocations in the main program. These 56 * copy data from a shared object into a region in the main program's BSS 57 * segment. 58 * 59 * Returns 0 on success, -1 on failure. 60 */ 61 int 62 do_copy_relocations(Obj_Entry *dstobj) 63 { 64 const Elf_Rela *relalim; 65 const Elf_Rela *rela; 66 67 assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */ 68 69 relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela + dstobj->relasize); 70 for (rela = dstobj->rela; rela < relalim; rela++) { 71 if (ELF_R_TYPE(rela->r_info) == R_X86_64_COPY) { 72 void *dstaddr; 73 const Elf_Sym *dstsym; 74 const char *name; 75 size_t size; 76 const void *srcaddr; 77 const Elf_Sym *srcsym; 78 const Obj_Entry *srcobj, *defobj; 79 SymLook req; 80 int res; 81 82 dstaddr = (void *) (dstobj->relocbase + rela->r_offset); 83 dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); 84 name = dstobj->strtab + dstsym->st_name; 85 size = dstsym->st_size; 86 symlook_init(&req, name); 87 req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info)); 88 req.flags = SYMLOOK_EARLY; 89 90 for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) { 91 res = symlook_obj(&req, srcobj); 92 if (res == 0) { 93 srcsym = req.sym_out; 94 defobj = req.defobj_out; 95 break; 96 } 97 } 98 99 if (srcobj == NULL) { 100 _rtld_error("Undefined symbol \"%s\" referenced from COPY" 101 " relocation in %s", name, dstobj->path); 102 return -1; 103 } 104 105 srcaddr = (const void *) (defobj->relocbase + srcsym->st_value); 106 memcpy(dstaddr, srcaddr, size); 107 } 108 } 109 110 return 0; 111 } 112 113 /* Initialize the special GOT entries. */ 114 void 115 init_pltgot(Obj_Entry *obj) 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 /* Process the non-PLT relocations. */ 124 int 125 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, 126 RtldLockState *lockstate) 127 { 128 const Elf_Rela *relalim; 129 const Elf_Rela *rela; 130 SymCache *cache; 131 int r = -1; 132 133 /* 134 * The dynamic loader may be called from a thread, we have 135 * limited amounts of stack available so we cannot use alloca(). 136 */ 137 if (obj != obj_rtld) { 138 cache = calloc(obj->dynsymcount, sizeof(SymCache)); 139 /* No need to check for NULL here */ 140 } else 141 cache = NULL; 142 143 relalim = (const Elf_Rela *) ((caddr_t) obj->rela + obj->relasize); 144 for (rela = obj->rela; rela < relalim; rela++) { 145 Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset); 146 Elf32_Addr *where32 = (Elf32_Addr *)where; 147 148 switch (ELF_R_TYPE(rela->r_info)) { 149 150 case R_X86_64_NONE: 151 break; 152 153 case R_X86_64_64: 154 { 155 const Elf_Sym *def; 156 const Obj_Entry *defobj; 157 158 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 159 flags, cache, lockstate); 160 if (def == NULL) 161 goto done; 162 163 *where = (Elf_Addr) (defobj->relocbase + def->st_value + rela->r_addend); 164 } 165 break; 166 167 case R_X86_64_PC32: 168 /* 169 * I don't think the dynamic linker should ever see this 170 * type of relocation. But the binutils-2.6 tools sometimes 171 * generate it. 172 */ 173 { 174 const Elf_Sym *def; 175 const Obj_Entry *defobj; 176 177 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 178 flags, cache, lockstate); 179 if (def == NULL) 180 goto done; 181 182 *where32 = (Elf32_Addr) (unsigned long) (defobj->relocbase + 183 def->st_value + rela->r_addend - (Elf_Addr) where); 184 } 185 break; 186 /* missing: R_X86_64_GOT32 R_X86_64_PLT32 */ 187 188 case R_X86_64_COPY: 189 /* 190 * These are deferred until all other relocations have 191 * been done. All we do here is make sure that the COPY 192 * relocation is not in a shared library. They are allowed 193 * only in executable files. 194 */ 195 if (!obj->mainprog) { 196 _rtld_error("%s: Unexpected R_X86_64_COPY relocation" 197 " in shared library", obj->path); 198 goto done; 199 } 200 break; 201 202 case R_X86_64_GLOB_DAT: 203 { 204 const Elf_Sym *def; 205 const Obj_Entry *defobj; 206 207 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 208 flags, cache, lockstate); 209 if (def == NULL) 210 goto done; 211 212 *where = (Elf_Addr) (defobj->relocbase + def->st_value); 213 } 214 break; 215 216 case R_X86_64_TPOFF64: 217 { 218 const Elf_Sym *def; 219 const Obj_Entry *defobj; 220 221 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 222 flags, cache, lockstate); 223 if (def == NULL) 224 goto done; 225 226 /* 227 * We lazily allocate offsets for static TLS as we 228 * see the first relocation that references the 229 * TLS block. This allows us to support (small 230 * amounts of) static TLS in dynamically loaded 231 * modules. If we run out of space, we generate an 232 * error. 233 */ 234 if (!defobj->tls_done) { 235 if (!allocate_tls_offset((Obj_Entry*) defobj)) { 236 _rtld_error("%s: No space available for static " 237 "Thread Local Storage", obj->path); 238 goto done; 239 } 240 } 241 242 *where = (Elf_Addr) (def->st_value - defobj->tlsoffset + 243 rela->r_addend); 244 } 245 break; 246 247 case R_X86_64_TPOFF32: 248 { 249 const Elf_Sym *def; 250 const Obj_Entry *defobj; 251 252 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 253 flags, cache, lockstate); 254 if (def == NULL) 255 goto done; 256 257 /* 258 * We lazily allocate offsets for static TLS as we 259 * see the first relocation that references the 260 * TLS block. This allows us to support (small 261 * amounts of) static TLS in dynamically loaded 262 * modules. If we run out of space, we generate an 263 * error. 264 */ 265 if (!defobj->tls_done) { 266 if (!allocate_tls_offset((Obj_Entry*) defobj)) { 267 _rtld_error("%s: No space available for static " 268 "Thread Local Storage", obj->path); 269 goto done; 270 } 271 } 272 273 *where32 = (Elf32_Addr) (def->st_value - 274 defobj->tlsoffset + 275 rela->r_addend); 276 } 277 break; 278 279 case R_X86_64_DTPMOD64: 280 { 281 const Elf_Sym *def; 282 const Obj_Entry *defobj; 283 284 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 285 flags, cache, lockstate); 286 if (def == NULL) 287 goto done; 288 289 *where += (Elf_Addr) defobj->tlsindex; 290 } 291 break; 292 293 case R_X86_64_DTPOFF64: 294 { 295 const Elf_Sym *def; 296 const Obj_Entry *defobj; 297 298 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 299 flags, cache, lockstate); 300 if (def == NULL) 301 goto done; 302 303 *where += (Elf_Addr) (def->st_value + rela->r_addend); 304 } 305 break; 306 307 case R_X86_64_DTPOFF32: 308 { 309 const Elf_Sym *def; 310 const Obj_Entry *defobj; 311 312 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 313 flags, cache, lockstate); 314 if (def == NULL) 315 goto done; 316 317 *where32 += (Elf32_Addr) (def->st_value + rela->r_addend); 318 } 319 break; 320 321 case R_X86_64_RELATIVE: 322 *where = (Elf_Addr)(obj->relocbase + rela->r_addend); 323 break; 324 325 /* missing: R_X86_64_GOTPCREL, R_X86_64_32, R_X86_64_32S, R_X86_64_16, R_X86_64_PC16, R_X86_64_8, R_X86_64_PC8 */ 326 327 default: 328 _rtld_error("%s: Unsupported relocation type %u" 329 " in non-PLT relocations\n", obj->path, 330 (unsigned int)ELF_R_TYPE(rela->r_info)); 331 goto done; 332 } 333 } 334 r = 0; 335 done: 336 if (cache != NULL) 337 free(cache); 338 return (r); 339 } 340 341 /* Process the PLT relocations. */ 342 int 343 reloc_plt(Obj_Entry *obj) 344 { 345 const Elf_Rela *relalim; 346 const Elf_Rela *rela; 347 348 relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize); 349 for (rela = obj->pltrela; rela < relalim; rela++) { 350 Elf_Addr *where; 351 352 switch(ELF_R_TYPE(rela->r_info)) { 353 case R_X86_64_JMP_SLOT: 354 /* Relocate the GOT slot pointing into the PLT. */ 355 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 356 *where += (Elf_Addr)obj->relocbase; 357 break; 358 359 case R_X86_64_IRELATIVE: 360 obj->irelative = true; 361 break; 362 363 default: 364 _rtld_error("Unknown relocation type %x in PLT", 365 (unsigned int)ELF_R_TYPE(rela->r_info)); 366 return (-1); 367 } 368 } 369 return 0; 370 } 371 372 /* Relocate the jump slots in an object. */ 373 int 374 reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate) 375 { 376 const Elf_Rela *relalim; 377 const Elf_Rela *rela; 378 379 if (obj->jmpslots_done) 380 return 0; 381 relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize); 382 for (rela = obj->pltrela; rela < relalim; rela++) { 383 Elf_Addr *where, target; 384 const Elf_Sym *def; 385 const Obj_Entry *defobj; 386 387 switch (ELF_R_TYPE(rela->r_info)) { 388 case R_X86_64_JMP_SLOT: 389 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 390 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 391 SYMLOOK_IN_PLT | flags, NULL, lockstate); 392 if (def == NULL) 393 return (-1); 394 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 395 obj->gnu_ifunc = true; 396 continue; 397 } 398 target = (Elf_Addr)(defobj->relocbase + def->st_value + rela->r_addend); 399 reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela); 400 break; 401 402 case R_X86_64_IRELATIVE: 403 break; 404 405 default: 406 _rtld_error("Unknown relocation type %x in PLT", 407 (unsigned int)ELF_R_TYPE(rela->r_info)); 408 return (-1); 409 } 410 } 411 obj->jmpslots_done = true; 412 return 0; 413 } 414 415 int 416 reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate) 417 { 418 const Elf_Rela *relalim; 419 const Elf_Rela *rela; 420 421 if (!obj->irelative) 422 return (0); 423 relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize); 424 for (rela = obj->pltrela; rela < relalim; rela++) { 425 Elf_Addr *where, target, *ptr; 426 427 switch (ELF_R_TYPE(rela->r_info)) { 428 case R_X86_64_JMP_SLOT: 429 break; 430 431 case R_X86_64_IRELATIVE: 432 ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend); 433 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 434 lock_release(rtld_bind_lock, lockstate); 435 target = ((Elf_Addr (*)(void))ptr)(); 436 wlock_acquire(rtld_bind_lock, lockstate); 437 *where = target; 438 break; 439 } 440 } 441 obj->irelative = false; 442 return (0); 443 } 444 445 int 446 reloc_gnu_ifunc(Obj_Entry *obj, int flags, RtldLockState *lockstate) 447 { 448 const Elf_Rela *relalim; 449 const Elf_Rela *rela; 450 451 if (!obj->gnu_ifunc) 452 return (0); 453 relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize); 454 for (rela = obj->pltrela; rela < relalim; rela++) { 455 Elf_Addr *where, target; 456 const Elf_Sym *def; 457 const Obj_Entry *defobj; 458 459 switch (ELF_R_TYPE(rela->r_info)) { 460 case R_X86_64_JMP_SLOT: 461 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 462 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 463 SYMLOOK_IN_PLT | flags, NULL, lockstate); 464 if (def == NULL) 465 return (-1); 466 if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC) 467 continue; 468 lock_release(rtld_bind_lock, lockstate); 469 target = (Elf_Addr)rtld_resolve_ifunc(defobj, def); 470 wlock_acquire(rtld_bind_lock, lockstate); 471 reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela); 472 break; 473 } 474 } 475 obj->gnu_ifunc = false; 476 return (0); 477 } 478 479 void *__tls_get_addr(tls_index *ti) 480 { 481 struct tls_tcb *tcb; 482 483 tcb = tls_get_tcb(); 484 return tls_get_addr_common((Elf_Addr **)&tcb->tcb_dtv, ti->ti_module, ti->ti_offset); 485 } 486 487 void * 488 __tls_get_addr_tcb(struct tls_tcb *tcb, tls_index *ti) 489 { 490 return tls_get_addr_common((Elf_Addr **)&tcb->tcb_dtv, ti->ti_module, ti->ti_offset); 491 } 492