1/* $NetBSD: symbol.c,v 1.58 2011/08/13 22:24:57 christos Exp $ */ 2 3/* 4 * Copyright 1996 John D. Polstra. 5 * Copyright 1996 Matt Thomas <matt@3am-software.com> 6 * Copyright 2002 Charles M. Hannum <root@ihack.net> 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by John Polstra. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35/* 36 * Dynamic linker for ELF. 37 * 38 * John Polstra <jdp@polstra.com>. 39 */ 40 41#include <sys/cdefs.h> 42#ifndef lint 43__RCSID("$NetBSD: symbol.c,v 1.58 2011/08/13 22:24:57 christos Exp $"); 44#endif /* not lint */ 45 46#include <err.h> 47#include <errno.h> 48#include <fcntl.h> 49#include <stdarg.h> 50#include <stdio.h> 51#include <stdlib.h> 52#include <string.h> 53#include <unistd.h> 54#include <sys/types.h> 55#include <sys/mman.h> 56#include <sys/bitops.h> 57#include <dirent.h> 58 59#include "debug.h" 60#include "rtld.h" 61 62typedef void (*fptr_t)(void); 63 64/* 65 * If the given object is already in the donelist, return true. Otherwise 66 * add the object to the list and return false. 67 */ 68static bool 69_rtld_donelist_check(DoneList *dlp, const Obj_Entry *obj) 70{ 71 unsigned int i; 72 73 for (i = 0; i < dlp->num_used; i++) 74 if (dlp->objs[i] == obj) 75 return true; 76 /* 77 * Our donelist allocation may not always be sufficient as we're not 78 * thread safe. We'll handle it properly anyway. 79 */ 80 if (dlp->num_used < dlp->num_alloc) 81 dlp->objs[dlp->num_used++] = obj; 82 return false; 83} 84 85static bool 86_rtld_is_exported(const Elf_Sym *def) 87{ 88 static const fptr_t _rtld_exports[] = { 89 (fptr_t)dlopen, 90 (fptr_t)dlclose, 91 (fptr_t)dlsym, 92 (fptr_t)dlvsym, 93 (fptr_t)dlerror, 94 (fptr_t)dladdr, 95 (fptr_t)dlinfo, 96 (fptr_t)dl_iterate_phdr, 97#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 98 (fptr_t)_rtld_tls_allocate, 99 (fptr_t)_rtld_tls_free, 100 (fptr_t)__tls_get_addr, 101#ifdef __i386__ 102 (fptr_t)___tls_get_addr, 103#endif 104#endif 105 NULL 106 }; 107 int i; 108 fptr_t value; 109 110 value = (fptr_t)(_rtld_objself.relocbase + def->st_value); 111 for (i = 0; _rtld_exports[i] != NULL; i++) { 112 if (value == _rtld_exports[i]) 113 return true; 114 } 115 return false; 116} 117 118/* 119 * Hash function for symbol table lookup. Don't even think about changing 120 * this. It is specified by the System V ABI. 121 */ 122unsigned long 123_rtld_elf_hash(const char *name) 124{ 125 const unsigned char *p = (const unsigned char *) name; 126 unsigned long h = 0; 127 unsigned long g; 128 unsigned long c; 129 130 for (; __predict_true((c = *p) != '\0'); p++) { 131 h <<= 4; 132 h += c; 133 if ((g = h & 0xf0000000) != 0) { 134 h ^= g; 135 h ^= g >> 24; 136 } 137 } 138 return (h); 139} 140 141const Elf_Sym * 142_rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist, 143 const Obj_Entry **defobj_out, u_int flags, const Ver_Entry *ventry, 144 DoneList *dlp) 145{ 146 const Elf_Sym *symp; 147 const Elf_Sym *def; 148 const Obj_Entry *defobj; 149 const Objlist_Entry *elm; 150 151 def = NULL; 152 defobj = NULL; 153 SIMPLEQ_FOREACH(elm, objlist, link) { 154 if (_rtld_donelist_check(dlp, elm->obj)) 155 continue; 156 rdbg(("search object %p (%s) for %s", elm->obj, elm->obj->path, 157 name)); 158 symp = _rtld_symlook_obj(name, hash, elm->obj, flags, ventry); 159 if (symp != NULL) { 160 if ((def == NULL) || 161 (ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 162 def = symp; 163 defobj = elm->obj; 164 if (ELF_ST_BIND(def->st_info) != STB_WEAK) 165 break; 166 } 167 } 168 } 169 if (def != NULL) 170 *defobj_out = defobj; 171 return def; 172} 173 174/* 175 * Search the symbol table of a shared object and all objects needed by it for 176 * a symbol of the given name. Search order is breadth-first. Returns a pointer 177 * to the symbol, or NULL if no definition was found. 178 */ 179const Elf_Sym * 180_rtld_symlook_needed(const char *name, unsigned long hash, 181 const Needed_Entry *needed, const Obj_Entry **defobj_out, u_int flags, 182 const Ver_Entry *ventry, DoneList *breadth, DoneList *depth) 183{ 184 const Elf_Sym *def, *def_w; 185 const Needed_Entry *n; 186 const Obj_Entry *obj, *defobj, *defobj1; 187 188 def = def_w = NULL; 189 defobj = NULL; 190 for (n = needed; n != NULL; n = n->next) { 191 if ((obj = n->obj) == NULL) 192 continue; 193 if (_rtld_donelist_check(breadth, obj)) 194 continue; 195 def = _rtld_symlook_obj(name, hash, obj, flags, ventry); 196 if (def == NULL) 197 continue; 198 defobj = obj; 199 if (ELF_ST_BIND(def->st_info) != STB_WEAK) { 200 *defobj_out = defobj; 201 202 return (def); 203 } 204 } 205 /* 206 * Either the symbol definition has not been found in directly needed 207 * objects, or the found symbol is weak. 208 */ 209 for (n = needed; n != NULL; n = n->next) { 210 if ((obj = n->obj) == NULL) 211 continue; 212 if (_rtld_donelist_check(depth, obj)) 213 continue; 214 def_w = _rtld_symlook_needed(name, hash, obj->needed, &defobj1, 215 flags, ventry, breadth, depth); 216 if (def_w == NULL) 217 continue; 218 if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) { 219 def = def_w; 220 defobj = defobj1; 221 if (ELF_ST_BIND(def_w->st_info) != STB_WEAK) 222 break; 223 } 224 } 225 if (def != NULL) 226 *defobj_out = defobj; 227 228 return def; 229} 230 231/* 232 * Search the symbol table of a single shared object for a symbol of 233 * the given name. Returns a pointer to the symbol, or NULL if no 234 * definition was found. 235 * 236 * The symbol's hash value is passed in for efficiency reasons; that 237 * eliminates many recomputations of the hash value. 238 */ 239const Elf_Sym * 240_rtld_symlook_obj(const char *name, unsigned long hash, 241 const Obj_Entry *obj, u_int flags, const Ver_Entry *ventry) 242{ 243 unsigned long symnum; 244 const Elf_Sym *vsymp = NULL; 245 Elf_Half verndx; 246 int vcount = 0; 247 248 for (symnum = obj->buckets[fast_remainder32(hash, obj->nbuckets, 249 obj->nbuckets_m, obj->nbuckets_s1, obj->nbuckets_s2)]; 250 symnum != ELF_SYM_UNDEFINED; 251 symnum = obj->chains[symnum]) { 252 const Elf_Sym *symp; 253 const char *strp; 254 255 assert(symnum < obj->nchains); 256 symp = obj->symtab + symnum; 257 strp = obj->strtab + symp->st_name; 258 rdbg(("check \"%s\" vs \"%s\" in %s", name, strp, obj->path)); 259 if (name[1] != strp[1] || strcmp(name, strp)) 260 continue; 261#ifdef __mips__ 262 if (symp->st_shndx == SHN_UNDEF) 263 continue; 264#else 265 /* 266 * XXX DANGER WILL ROBINSON! 267 * If we have a function pointer in the executable's 268 * data section, it points to the executable's PLT 269 * slot, and there is NO relocation emitted. To make 270 * the function pointer comparable to function pointers 271 * in shared libraries, we must resolve data references 272 * in the libraries to point to PLT slots in the 273 * executable, if they exist. 274 */ 275 if (symp->st_shndx == SHN_UNDEF && 276 ((flags & SYMLOOK_IN_PLT) || 277 symp->st_value == 0 || 278 ELF_ST_TYPE(symp->st_info) != STT_FUNC)) 279 continue; 280#endif 281 282 if (ventry == NULL) { 283 if (obj->versyms != NULL) { 284 verndx = VER_NDX(obj->versyms[symnum].vs_vers); 285 if (verndx > obj->vertabnum) { 286 _rtld_error("%s: symbol %s references " 287 "wrong version %d", obj->path, 288 &obj->strtab[symnum], verndx); 289 continue; 290 } 291 292 /* 293 * If we are not called from dlsym (i.e. this 294 * is a normal relocation from unversioned 295 * binary), accept the symbol immediately 296 * if it happens to have first version after 297 * this shared object became versioned. 298 * Otherwise, if symbol is versioned and not 299 * hidden, remember it. If it is the only 300 * symbol with this name exported by the shared 301 * object, it will be returned as a match at the 302 * end of the function. If symbol is global 303 * (verndx < 2) accept it unconditionally. 304 */ 305 if (!(flags & SYMLOOK_DLSYM) && 306 verndx == VER_NDX_GIVEN) { 307 return symp; 308 } else if (verndx >= VER_NDX_GIVEN) { 309 if (!(obj->versyms[symnum].vs_vers & VER_NDX_HIDDEN)) { 310 if (vsymp == NULL) 311 vsymp = symp; 312 vcount++; 313 } 314 continue; 315 } 316 } 317 return symp; 318 } else { 319 if (obj->versyms == NULL) { 320 if (_rtld_object_match_name(obj, ventry->name)){ 321 _rtld_error("%s: object %s should " 322 "provide version %s for symbol %s", 323 _rtld_objself.path, obj->path, 324 ventry->name, &obj->strtab[symnum]); 325 continue; 326 } 327 } else { 328 verndx = VER_NDX(obj->versyms[symnum].vs_vers); 329 if (verndx > obj->vertabnum) { 330 _rtld_error("%s: symbol %s references " 331 "wrong version %d", obj->path, 332 &obj->strtab[symnum], verndx); 333 continue; 334 } 335 if (obj->vertab[verndx].hash != ventry->hash || 336 strcmp(obj->vertab[verndx].name, ventry->name)) { 337 /* 338 * Version does not match. Look if this 339 * is a global symbol and if it is not 340 * hidden. If global symbol (verndx < 2) 341 * is available, use it. Do not return 342 * symbol if we are called by dlvsym, 343 * because dlvsym looks for a specific 344 * version and default one is not what 345 * dlvsym wants. 346 */ 347 if ((flags & SYMLOOK_DLSYM) || 348 (obj->versyms[symnum].vs_vers & VER_NDX_HIDDEN) || 349 (verndx >= VER_NDX_GIVEN)) 350 continue; 351 } 352 } 353 return symp; 354 } 355 } 356 if (vcount == 1) 357 return vsymp; 358 return NULL; 359} 360 361#ifdef COMBRELOC 362static const Obj_Entry *_rtld_last_refobj; 363 364/* 365 * Called when an object is freed. Reset the cached symbol look up if 366 * our last referencing or definition object just got unloaded. 367 */ 368void 369_rtld_combreloc_reset(const Obj_Entry *obj) 370{ 371 if (_rtld_last_refobj == obj) 372 _rtld_last_refobj = NULL; 373} 374#endif 375 376/* 377 * Given a symbol number in a referencing object, find the corresponding 378 * definition of the symbol. Returns a pointer to the symbol, or NULL if 379 * no definition was found. Returns a pointer to the Obj_Entry of the 380 * defining object via the reference parameter DEFOBJ_OUT. 381 */ 382const Elf_Sym * 383_rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj, 384 const Obj_Entry **defobj_out, u_int flags) 385{ 386 const Elf_Sym *ref; 387 const Elf_Sym *def; 388 const Obj_Entry *defobj; 389 const char *name; 390 unsigned long hash; 391 392#ifdef COMBRELOC 393 /* 394 * COMBRELOC combines multiple reloc sections and sorts them to make 395 * dynamic symbol lookup caching possible. 396 * 397 * So if the lookup we are doing is the same as the previous lookup 398 * return the cached results. 399 */ 400 static unsigned long last_symnum; 401 static const Obj_Entry *last_defobj; 402 static const Elf_Sym *last_def; 403 404 if (symnum == last_symnum && refobj == _rtld_last_refobj 405 && !(flags & SYMLOOK_IN_PLT)) { 406 *defobj_out = last_defobj; 407 return last_def; 408 } 409#endif 410 411 ref = refobj->symtab + symnum; 412 name = refobj->strtab + ref->st_name; 413 414 /* 415 * We don't have to do a full scale lookup if the symbol is local. 416 * We know it will bind to the instance in this load module; to 417 * which we already have a pointer (ie ref). 418 */ 419 if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) { 420 if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) { 421 _rtld_error("%s: Bogus symbol table entry %lu", 422 refobj->path, symnum); 423 } 424 425 hash = _rtld_elf_hash(name); 426 defobj = NULL; 427 def = _rtld_symlook_default(name, hash, refobj, &defobj, flags, 428 _rtld_fetch_ventry(refobj, symnum)); 429 } else { 430 rdbg(("STB_LOCAL symbol %s in %s", name, refobj->path)); 431 def = ref; 432 defobj = refobj; 433 } 434 435 /* 436 * If we found no definition and the reference is weak, treat the 437 * symbol as having the value zero. 438 */ 439 if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) { 440 rdbg((" returning _rtld_sym_zero@_rtld_objself")); 441 def = &_rtld_sym_zero; 442 defobj = &_rtld_objself; 443 } 444 445 if (def != NULL) { 446 *defobj_out = defobj; 447#ifdef COMBRELOC 448 if (!(flags & SYMLOOK_IN_PLT)) { 449 /* 450 * Cache the lookup arguments and results if this was 451 * non-PLT lookup. 452 */ 453 last_symnum = symnum; 454 _rtld_last_refobj = refobj; 455 last_def = def; 456 last_defobj = defobj; 457 } 458#endif 459 } else { 460 rdbg(("lookup failed")); 461 _rtld_error("%s: Undefined %ssymbol \"%s\" (symnum = %ld)", 462 refobj->path, (flags & SYMLOOK_IN_PLT) ? "PLT " : "", 463 name, symnum); 464 } 465 return def; 466} 467 468const Elf_Sym * 469_rtld_find_plt_symdef(unsigned long symnum, const Obj_Entry *obj, 470 const Obj_Entry **defobj, bool imm) 471{ 472 const Elf_Sym *def = _rtld_find_symdef(symnum, obj, defobj, 473 SYMLOOK_IN_PLT); 474 if (__predict_false(def == NULL)) 475 return NULL; 476 477 if (__predict_false(def == &_rtld_sym_zero)) { 478 /* tp is set during lazy binding. */ 479 if (imm) { 480 const Elf_Sym *ref = obj->symtab + symnum; 481 const char *name = obj->strtab + ref->st_name; 482 483 _rtld_error( 484 "%s: Trying to call undefined weak symbol `%s'", 485 obj->path, name); 486 return NULL; 487 } 488 } 489 return def; 490} 491 492/* 493 * Given a symbol name in a referencing object, find the corresponding 494 * definition of the symbol. Returns a pointer to the symbol, or NULL if 495 * no definition was found. Returns a pointer to the Obj_Entry of the 496 * defining object via the reference parameter DEFOBJ_OUT. 497 */ 498const Elf_Sym * 499_rtld_symlook_default(const char *name, unsigned long hash, 500 const Obj_Entry *refobj, const Obj_Entry **defobj_out, u_int flags, 501 const Ver_Entry *ventry) 502{ 503 const Elf_Sym *def; 504 const Elf_Sym *symp; 505 const Obj_Entry *obj; 506 const Obj_Entry *defobj; 507 const Objlist_Entry *elm; 508 def = NULL; 509 defobj = NULL; 510 DoneList donelist; 511 512 _rtld_donelist_init(&donelist); 513 514 /* Look first in the referencing object if linked symbolically. */ 515 if (refobj->symbolic && !_rtld_donelist_check(&donelist, refobj)) { 516 rdbg(("search referencing object for %s", name)); 517 symp = _rtld_symlook_obj(name, hash, refobj, flags, ventry); 518 if (symp != NULL) { 519 def = symp; 520 defobj = refobj; 521 } 522 } 523 524 /* Search all objects loaded at program start up. */ 525 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { 526 rdbg(("search _rtld_list_main for %s", name)); 527 symp = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, 528 flags, ventry, &donelist); 529 if (symp != NULL && 530 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 531 def = symp; 532 defobj = obj; 533 } 534 } 535 536 /* Search all RTLD_GLOBAL objects. */ 537 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { 538 rdbg(("search _rtld_list_global for %s", name)); 539 symp = _rtld_symlook_list(name, hash, &_rtld_list_global, 540 &obj, flags, ventry, &donelist); 541 if (symp != NULL && 542 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 543 def = symp; 544 defobj = obj; 545 } 546 } 547 548 /* Search all dlopened DAGs containing the referencing object. */ 549 SIMPLEQ_FOREACH(elm, &refobj->dldags, link) { 550 if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) 551 break; 552 rdbg(("search DAG with root %p (%s) for %s", elm->obj, 553 elm->obj->path, name)); 554 symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers, 555 &obj, flags, ventry, &donelist); 556 if (symp != NULL && 557 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 558 def = symp; 559 defobj = obj; 560 } 561 } 562 563 /* 564 * Search the dynamic linker itself, and possibly resolve the 565 * symbol from there. This is how the application links to 566 * dynamic linker services such as dlopen. Only the values listed 567 * in the "_rtld_exports" array can be resolved from the dynamic 568 * linker. 569 */ 570 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { 571 rdbg(("Search the dynamic linker itself.")); 572 symp = _rtld_symlook_obj(name, hash, &_rtld_objself, flags, 573 ventry); 574 if (symp != NULL && _rtld_is_exported(symp)) { 575 def = symp; 576 defobj = &_rtld_objself; 577 } 578 } 579 580 if (def != NULL) 581 *defobj_out = defobj; 582 return def; 583} 584