reloc.c revision 214194
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: head/libexec/rtld-elf/ia64/reloc.c 214194 2010-10-22 04:43:04Z marcel $ 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 <machine/ia64_cpu.h> 37 38#include <dlfcn.h> 39#include <err.h> 40#include <errno.h> 41#include <fcntl.h> 42#include <stdarg.h> 43#include <stdio.h> 44#include <stdlib.h> 45#include <string.h> 46#include <unistd.h> 47 48#include "debug.h" 49#include "rtld.h" 50 51extern Elf_Dyn _DYNAMIC; 52 53/* 54 * Macros for loading/storing unaligned 64-bit values. These are 55 * needed because relocations can point to unaligned data. This 56 * occurs in the DWARF2 exception frame tables generated by the 57 * compiler, for instance. 58 * 59 * We don't use these when relocating jump slots and GOT entries, 60 * since they are guaranteed to be aligned. 61 * 62 * XXX dfr stub for now. 63 */ 64#define load64(p) (*(u_int64_t *) (p)) 65#define store64(p, v) (*(u_int64_t *) (p) = (v)) 66 67/* Allocate an @fptr. */ 68 69#define FPTR_CHUNK_SIZE 64 70 71struct fptr_chunk { 72 struct fptr fptrs[FPTR_CHUNK_SIZE]; 73}; 74 75static struct fptr_chunk first_chunk; 76static struct fptr_chunk *current_chunk = &first_chunk; 77static struct fptr *next_fptr = &first_chunk.fptrs[0]; 78static struct fptr *last_fptr = &first_chunk.fptrs[FPTR_CHUNK_SIZE]; 79 80/* 81 * We use static storage initially so that we don't have to call 82 * malloc during init_rtld(). 83 */ 84static struct fptr * 85alloc_fptr(Elf_Addr target, Elf_Addr gp) 86{ 87 struct fptr* fptr; 88 89 if (next_fptr == last_fptr) { 90 current_chunk = malloc(sizeof(struct fptr_chunk)); 91 next_fptr = ¤t_chunk->fptrs[0]; 92 last_fptr = ¤t_chunk->fptrs[FPTR_CHUNK_SIZE]; 93 } 94 fptr = next_fptr; 95 next_fptr++; 96 fptr->target = target; 97 fptr->gp = gp; 98 return fptr; 99} 100 101static struct fptr ** 102alloc_fptrs(Obj_Entry *obj, bool mapped) 103{ 104 struct fptr **fptrs; 105 size_t fbytes; 106 107 fbytes = obj->nchains * sizeof(struct fptr *); 108 109 /* 110 * Avoid malloc, if requested. Happens when relocating 111 * rtld itself on startup. 112 */ 113 if (mapped) { 114 fptrs = mmap(NULL, fbytes, PROT_READ|PROT_WRITE, 115 MAP_ANON, -1, 0); 116 if (fptrs == MAP_FAILED) 117 fptrs = NULL; 118 } else { 119 fptrs = malloc(fbytes); 120 if (fptrs != NULL) 121 memset(fptrs, 0, fbytes); 122 } 123 124 /* 125 * This assertion is necessary to guarantee function pointer 126 * uniqueness 127 */ 128 assert(fptrs != NULL); 129 130 return (obj->priv = fptrs); 131} 132 133static void 134free_fptrs(Obj_Entry *obj, bool mapped) 135{ 136 struct fptr **fptrs; 137 size_t fbytes; 138 139 fptrs = obj->priv; 140 if (fptrs == NULL) 141 return; 142 143 fbytes = obj->nchains * sizeof(struct fptr *); 144 if (mapped) 145 munmap(fptrs, fbytes); 146 else 147 free(fptrs); 148 obj->priv = NULL; 149} 150 151/* Relocate a non-PLT object with addend. */ 152static int 153reloc_non_plt_obj(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela, 154 SymCache *cache) 155{ 156 struct fptr **fptrs; 157 Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset); 158 159 switch (ELF_R_TYPE(rela->r_info)) { 160 case R_IA_64_REL64LSB: 161 /* 162 * We handle rtld's relocations in rtld_start.S 163 */ 164 if (obj != obj_rtld) 165 store64(where, 166 load64(where) + (Elf_Addr) obj->relocbase); 167 break; 168 169 case R_IA_64_DIR64LSB: { 170 const Elf_Sym *def; 171 const Obj_Entry *defobj; 172 Elf_Addr target; 173 174 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 175 false, cache); 176 if (def == NULL) 177 return -1; 178 179 target = (def->st_shndx != SHN_UNDEF) 180 ? (Elf_Addr)(defobj->relocbase + def->st_value) : 0; 181 store64(where, target + rela->r_addend); 182 break; 183 } 184 185 case R_IA_64_FPTR64LSB: { 186 /* 187 * We have to make sure that all @fptr references to 188 * the same function are identical so that code can 189 * compare function pointers. 190 */ 191 const Elf_Sym *def; 192 const Obj_Entry *defobj; 193 struct fptr *fptr = 0; 194 Elf_Addr target, gp; 195 int sym_index; 196 197 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 198 true, cache); 199 if (def == NULL) { 200 /* 201 * XXX r_debug_state is problematic and find_symdef() 202 * returns NULL for it. This probably has something to 203 * do with symbol versioning (r_debug_state is in the 204 * symbol map). If we return -1 in that case we abort 205 * relocating rtld, which typically is fatal. So, for 206 * now just skip the symbol when we're relocating 207 * rtld. We don't care about r_debug_state unless we 208 * are being debugged. 209 */ 210 if (obj != obj_rtld) 211 return -1; 212 break; 213 } 214 215 if (def->st_shndx != SHN_UNDEF) { 216 target = (Elf_Addr)(defobj->relocbase + def->st_value); 217 gp = (Elf_Addr)defobj->pltgot; 218 219 /* rtld is allowed to reference itself only */ 220 assert(!obj->rtld || obj == defobj); 221 fptrs = defobj->priv; 222 if (fptrs == NULL) 223 fptrs = alloc_fptrs((Obj_Entry *) defobj, 224 obj->rtld); 225 226 sym_index = def - defobj->symtab; 227 228 /* 229 * Find the @fptr, using fptrs as a helper. 230 */ 231 if (fptrs) 232 fptr = fptrs[sym_index]; 233 if (!fptr) { 234 fptr = alloc_fptr(target, gp); 235 if (fptrs) 236 fptrs[sym_index] = fptr; 237 } 238 } else 239 fptr = NULL; 240 241 store64(where, (Elf_Addr)fptr); 242 break; 243 } 244 245 case R_IA_64_IPLTLSB: { 246 /* 247 * Relocation typically used to populate C++ virtual function 248 * tables. It creates a 128-bit function descriptor at the 249 * specified memory address. 250 */ 251 const Elf_Sym *def; 252 const Obj_Entry *defobj; 253 struct fptr *fptr; 254 Elf_Addr target, gp; 255 256 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 257 false, cache); 258 if (def == NULL) 259 return -1; 260 261 if (def->st_shndx != SHN_UNDEF) { 262 target = (Elf_Addr)(defobj->relocbase + def->st_value); 263 gp = (Elf_Addr)defobj->pltgot; 264 } else { 265 target = 0; 266 gp = 0; 267 } 268 269 fptr = (void*)where; 270 store64(&fptr->target, target); 271 store64(&fptr->gp, gp); 272 break; 273 } 274 275 case R_IA_64_DTPMOD64LSB: { 276 const Elf_Sym *def; 277 const Obj_Entry *defobj; 278 279 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 280 false, cache); 281 if (def == NULL) 282 return -1; 283 284 store64(where, defobj->tlsindex); 285 break; 286 } 287 288 case R_IA_64_DTPREL64LSB: { 289 const Elf_Sym *def; 290 const Obj_Entry *defobj; 291 292 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 293 false, cache); 294 if (def == NULL) 295 return -1; 296 297 store64(where, def->st_value + rela->r_addend); 298 break; 299 } 300 301 case R_IA_64_TPREL64LSB: { 302 const Elf_Sym *def; 303 const Obj_Entry *defobj; 304 305 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 306 false, cache); 307 if (def == NULL) 308 return -1; 309 310 /* 311 * We lazily allocate offsets for static TLS as we 312 * see the first relocation that references the 313 * TLS block. This allows us to support (small 314 * amounts of) static TLS in dynamically loaded 315 * modules. If we run out of space, we generate an 316 * error. 317 */ 318 if (!defobj->tls_done) { 319 if (!allocate_tls_offset((Obj_Entry*) defobj)) { 320 _rtld_error("%s: No space available for static " 321 "Thread Local Storage", obj->path); 322 return -1; 323 } 324 } 325 326 store64(where, defobj->tlsoffset + def->st_value + rela->r_addend); 327 break; 328 } 329 330 case R_IA_64_NONE: 331 break; 332 333 default: 334 _rtld_error("%s: Unsupported relocation type %u" 335 " in non-PLT relocations\n", obj->path, 336 (unsigned int)ELF_R_TYPE(rela->r_info)); 337 return -1; 338 } 339 340 return(0); 341} 342 343/* Process the non-PLT relocations. */ 344int 345reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) 346{ 347 const Elf_Rel *rellim; 348 const Elf_Rel *rel; 349 const Elf_Rela *relalim; 350 const Elf_Rela *rela; 351 SymCache *cache; 352 int bytes = obj->nchains * sizeof(SymCache); 353 int r = -1; 354 355 /* 356 * The dynamic loader may be called from a thread, we have 357 * limited amounts of stack available so we cannot use alloca(). 358 */ 359 cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); 360 if (cache == MAP_FAILED) 361 cache = NULL; 362 363 /* Perform relocations without addend if there are any: */ 364 rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize); 365 for (rel = obj->rel; obj->rel != NULL && rel < rellim; rel++) { 366 Elf_Rela locrela; 367 368 locrela.r_info = rel->r_info; 369 locrela.r_offset = rel->r_offset; 370 locrela.r_addend = 0; 371 if (reloc_non_plt_obj(obj_rtld, obj, &locrela, cache)) 372 goto done; 373 } 374 375 /* Perform relocations with addend if there are any: */ 376 relalim = (const Elf_Rela *) ((caddr_t) obj->rela + obj->relasize); 377 for (rela = obj->rela; obj->rela != NULL && rela < relalim; rela++) { 378 if (reloc_non_plt_obj(obj_rtld, obj, rela, cache)) 379 goto done; 380 } 381 382 r = 0; 383done: 384 if (cache) 385 munmap(cache, bytes); 386 387 /* 388 * Release temporarily mapped fptrs if relocating 389 * rtld object itself. A new table will be created 390 * in make_function_pointer using malloc when needed. 391 */ 392 if (obj->rtld && obj->priv) 393 free_fptrs(obj, true); 394 395 return (r); 396} 397 398/* Process the PLT relocations. */ 399int 400reloc_plt(Obj_Entry *obj) 401{ 402 /* All PLT relocations are the same kind: Elf_Rel or Elf_Rela. */ 403 if (obj->pltrelsize != 0) { 404 const Elf_Rel *rellim; 405 const Elf_Rel *rel; 406 407 rellim = (const Elf_Rel *) 408 ((char *)obj->pltrel + obj->pltrelsize); 409 for (rel = obj->pltrel; rel < rellim; rel++) { 410 Elf_Addr *where; 411 412 assert(ELF_R_TYPE(rel->r_info) == R_IA_64_IPLTLSB); 413 414 /* Relocate the @fptr pointing into the PLT. */ 415 where = (Elf_Addr *)(obj->relocbase + rel->r_offset); 416 *where += (Elf_Addr)obj->relocbase; 417 } 418 } else { 419 const Elf_Rela *relalim; 420 const Elf_Rela *rela; 421 422 relalim = (const Elf_Rela *) 423 ((char *)obj->pltrela + obj->pltrelasize); 424 for (rela = obj->pltrela; rela < relalim; rela++) { 425 Elf_Addr *where; 426 427 assert(ELF_R_TYPE(rela->r_info) == R_IA_64_IPLTLSB); 428 429 /* Relocate the @fptr pointing into the PLT. */ 430 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 431 *where += (Elf_Addr)obj->relocbase; 432 } 433 } 434 return 0; 435} 436 437/* Relocate the jump slots in an object. */ 438int 439reloc_jmpslots(Obj_Entry *obj) 440{ 441 if (obj->jmpslots_done) 442 return 0; 443 /* All PLT relocations are the same kind: Elf_Rel or Elf_Rela. */ 444 if (obj->pltrelsize != 0) { 445 const Elf_Rel *rellim; 446 const Elf_Rel *rel; 447 448 rellim = (const Elf_Rel *) 449 ((char *)obj->pltrel + obj->pltrelsize); 450 for (rel = obj->pltrel; rel < rellim; rel++) { 451 Elf_Addr *where; 452 const Elf_Sym *def; 453 const Obj_Entry *defobj; 454 455 assert(ELF_R_TYPE(rel->r_info) == R_IA_64_IPLTLSB); 456 where = (Elf_Addr *)(obj->relocbase + rel->r_offset); 457 def = find_symdef(ELF_R_SYM(rel->r_info), obj, 458 &defobj, true, NULL); 459 if (def == NULL) 460 return -1; 461 reloc_jmpslot(where, 462 (Elf_Addr)(defobj->relocbase 463 + def->st_value), 464 defobj, obj, rel); 465 } 466 } else { 467 const Elf_Rela *relalim; 468 const Elf_Rela *rela; 469 470 relalim = (const Elf_Rela *) 471 ((char *)obj->pltrela + obj->pltrelasize); 472 for (rela = obj->pltrela; rela < relalim; rela++) { 473 Elf_Addr *where; 474 const Elf_Sym *def; 475 const Obj_Entry *defobj; 476 477 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 478 def = find_symdef(ELF_R_SYM(rela->r_info), obj, 479 &defobj, true, NULL); 480 if (def == NULL) 481 return -1; 482 reloc_jmpslot(where, 483 (Elf_Addr)(defobj->relocbase 484 + def->st_value), 485 defobj, obj, (Elf_Rel *)rela); 486 } 487 } 488 obj->jmpslots_done = true; 489 return 0; 490} 491 492/* Fixup the jump slot at "where" to transfer control to "target". */ 493Elf_Addr 494reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *obj, 495 const Obj_Entry *refobj, const Elf_Rel *rel) 496{ 497 Elf_Addr stubaddr; 498 499 dbg(" reloc_jmpslot: where=%p, target=%p, gp=%p", 500 (void *)where, (void *)target, (void *)obj->pltgot); 501 stubaddr = *where; 502 if (stubaddr != target) { 503 504 /* 505 * Point this @fptr directly at the target. Update the 506 * gp value first so that we don't break another cpu 507 * which is currently executing the PLT entry. 508 */ 509 where[1] = (Elf_Addr) obj->pltgot; 510 ia64_mf(); 511 where[0] = target; 512 ia64_mf(); 513 } 514 515 /* 516 * The caller needs an @fptr for the adjusted entry. The PLT 517 * entry serves this purpose nicely. 518 */ 519 return (Elf_Addr) where; 520} 521 522/* 523 * XXX ia64 doesn't seem to have copy relocations. 524 * 525 * Returns 0 on success, -1 on failure. 526 */ 527int 528do_copy_relocations(Obj_Entry *dstobj) 529{ 530 531 return 0; 532} 533 534/* 535 * Return the @fptr representing a given function symbol. 536 */ 537void * 538make_function_pointer(const Elf_Sym *sym, const Obj_Entry *obj) 539{ 540 struct fptr **fptrs = obj->priv; 541 int index = sym - obj->symtab; 542 543 if (!fptrs) { 544 /* 545 * This should only happen for something like 546 * dlsym("dlopen"). Actually, I'm not sure it can ever 547 * happen. 548 */ 549 fptrs = alloc_fptrs((Obj_Entry *) obj, false); 550 } 551 if (!fptrs[index]) { 552 Elf_Addr target, gp; 553 target = (Elf_Addr) (obj->relocbase + sym->st_value); 554 gp = (Elf_Addr) obj->pltgot; 555 fptrs[index] = alloc_fptr(target, gp); 556 } 557 return fptrs[index]; 558} 559 560void 561call_initfini_pointer(const Obj_Entry *obj, Elf_Addr target) 562{ 563 struct fptr fptr; 564 565 fptr.gp = (Elf_Addr) obj->pltgot; 566 fptr.target = target; 567 dbg(" initfini: target=%p, gp=%p", 568 (void *) fptr.target, (void *) fptr.gp); 569 ((InitFunc) &fptr)(); 570} 571 572/* Initialize the special PLT entries. */ 573void 574init_pltgot(Obj_Entry *obj) 575{ 576 const Elf_Dyn *dynp; 577 Elf_Addr *pltres = 0; 578 579 /* 580 * When there are no PLT relocations, the DT_IA_64_PLT_RESERVE entry 581 * is bogus. Do not setup the BOR pointers in that case. An example 582 * of where this happens is /usr/lib/libxpg4.so.3. 583 */ 584 if (obj->pltrelasize == 0 && obj->pltrelsize == 0) 585 return; 586 587 /* 588 * Find the PLT RESERVE section. 589 */ 590 for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; dynp++) { 591 if (dynp->d_tag == DT_IA_64_PLT_RESERVE) 592 pltres = (u_int64_t *) 593 (obj->relocbase + dynp->d_un.d_ptr); 594 } 595 if (!pltres) 596 errx(1, "Can't find DT_IA_64_PLT_RESERVE entry"); 597 598 /* 599 * The PLT RESERVE section is used to get values to pass to 600 * _rtld_bind when lazy binding. 601 */ 602 pltres[0] = (Elf_Addr) obj; 603 pltres[1] = FPTR_TARGET(_rtld_bind_start); 604 pltres[2] = FPTR_GP(_rtld_bind_start); 605} 606 607void 608allocate_initial_tls(Obj_Entry *list) 609{ 610 void *tpval; 611 612 /* 613 * Fix the size of the static TLS block by using the maximum 614 * offset allocated so far and adding a bit for dynamic modules to 615 * use. 616 */ 617 tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA; 618 619 tpval = allocate_tls(list, NULL, TLS_TCB_SIZE, 16); 620 __asm __volatile("mov r13 = %0" :: "r"(tpval)); 621} 622 623void *__tls_get_addr(unsigned long module, unsigned long offset) 624{ 625 register Elf_Addr** tp __asm__("r13"); 626 627 return tls_get_addr_common(tp, module, offset); 628} 629