1 /* $NetBSD: symbol.c,v 1.53 2010/04/05 14:01:26 joerg 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.53 2010/04/05 14:01:26 joerg 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 62 typedef 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 */ 68 static 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 85 static 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)dlerror, 93 (fptr_t)dladdr, 94 (fptr_t)dlinfo, 95 NULL 96 }; 97 int i; 98 fptr_t value; 99 100 value = (fptr_t)(_rtld_objself.relocbase + def->st_value); 101 for (i = 0; _rtld_exports[i] != NULL; i++) { 102 if (value == _rtld_exports[i]) 103 return true; 104 } 105 return false; 106 } 107 108 /* 109 * Hash function for symbol table lookup. Don't even think about changing 110 * this. It is specified by the System V ABI. 111 */ 112 unsigned long 113 _rtld_elf_hash(const char *name) 114 { 115 const unsigned char *p = (const unsigned char *) name; 116 unsigned long h = 0; 117 unsigned long g; 118 unsigned long c; 119 120 for (; __predict_true((c = *p) != '\0'); p++) { 121 h <<= 4; 122 h += c; 123 if ((g = h & 0xf0000000) != 0) { 124 h ^= g; 125 h ^= g >> 24; 126 } 127 } 128 return (h); 129 } 130 131 const Elf_Sym * 132 _rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist, 133 const Obj_Entry **defobj_out, bool in_plt, DoneList *dlp) 134 { 135 const Elf_Sym *symp; 136 const Elf_Sym *def; 137 const Obj_Entry *defobj; 138 const Objlist_Entry *elm; 139 140 def = NULL; 141 defobj = NULL; 142 SIMPLEQ_FOREACH(elm, objlist, link) { 143 if (_rtld_donelist_check(dlp, elm->obj)) 144 continue; 145 rdbg(("search object %p (%s) for %s", elm->obj, elm->obj->path, 146 name)); 147 if ((symp = _rtld_symlook_obj(name, hash, elm->obj, in_plt)) 148 != NULL) { 149 if ((def == NULL) || 150 (ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 151 def = symp; 152 defobj = elm->obj; 153 if (ELF_ST_BIND(def->st_info) != STB_WEAK) 154 break; 155 } 156 } 157 } 158 if (def != NULL) 159 *defobj_out = defobj; 160 return def; 161 } 162 163 /* 164 * Search the symbol table of a shared object and all objects needed by it for 165 * a symbol of the given name. Search order is breadth-first. Returns a pointer 166 * to the symbol, or NULL if no definition was found. 167 */ 168 const Elf_Sym * 169 _rtld_symlook_needed(const char *name, unsigned long hash, 170 const Needed_Entry *needed, const Obj_Entry **defobj_out, bool inplt, 171 DoneList *breadth, DoneList *depth) 172 { 173 const Elf_Sym *def, *def_w; 174 const Needed_Entry *n; 175 const Obj_Entry *obj, *defobj, *defobj1; 176 177 def = def_w = NULL; 178 defobj = NULL; 179 for (n = needed; n != NULL; n = n->next) { 180 if ((obj = n->obj) == NULL) 181 continue; 182 if (_rtld_donelist_check(breadth, obj)) 183 continue; 184 if ((def = _rtld_symlook_obj(name, hash, obj, inplt)) == NULL) 185 continue; 186 defobj = obj; 187 if (ELF_ST_BIND(def->st_info) != STB_WEAK) { 188 *defobj_out = defobj; 189 190 return (def); 191 } 192 } 193 /* 194 * Either the symbol definition has not been found in directly needed 195 * objects, or the found symbol is weak. 196 */ 197 for (n = needed; n != NULL; n = n->next) { 198 if ((obj = n->obj) == NULL) 199 continue; 200 if (_rtld_donelist_check(depth, obj)) 201 continue; 202 def_w = _rtld_symlook_needed(name, hash, obj->needed, &defobj1, 203 inplt, breadth, depth); 204 if (def_w == NULL) 205 continue; 206 if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) { 207 def = def_w; 208 defobj = defobj1; 209 if (ELF_ST_BIND(def_w->st_info) != STB_WEAK) 210 break; 211 } 212 } 213 if (def != NULL) 214 *defobj_out = defobj; 215 216 return def; 217 } 218 219 /* 220 * Search the symbol table of a single shared object for a symbol of 221 * the given name. Returns a pointer to the symbol, or NULL if no 222 * definition was found. 223 * 224 * The symbol's hash value is passed in for efficiency reasons; that 225 * eliminates many recomputations of the hash value. 226 */ 227 const Elf_Sym * 228 _rtld_symlook_obj(const char *name, unsigned long hash, 229 const Obj_Entry *obj, bool in_plt) 230 { 231 unsigned long symnum; 232 233 for (symnum = obj->buckets[fast_remainder32(hash, obj->nbuckets, 234 obj->nbuckets_m, obj->nbuckets_s1, obj->nbuckets_s2)]; 235 symnum != ELF_SYM_UNDEFINED; 236 symnum = obj->chains[symnum]) { 237 const Elf_Sym *symp; 238 const char *strp; 239 240 assert(symnum < obj->nchains); 241 symp = obj->symtab + symnum; 242 strp = obj->strtab + symp->st_name; 243 rdbg(("check \"%s\" vs \"%s\" in %p", name, strp, obj)); 244 if (name[1] == strp[1] && !strcmp(name, strp)) { 245 if (symp->st_shndx != SHN_UNDEF) 246 return symp; 247 #ifndef __mips__ 248 /* 249 * XXX DANGER WILL ROBINSON! 250 * If we have a function pointer in the executable's 251 * data section, it points to the executable's PLT 252 * slot, and there is NO relocation emitted. To make 253 * the function pointer comparable to function pointers 254 * in shared libraries, we must resolve data references 255 * in the libraries to point to PLT slots in the 256 * executable, if they exist. 257 */ 258 else if (!in_plt && symp->st_value != 0 && 259 ELF_ST_TYPE(symp->st_info) == STT_FUNC) 260 return symp; 261 #endif 262 else 263 return NULL; 264 } 265 } 266 267 return NULL; 268 } 269 270 #ifdef COMBRELOC 271 static const Obj_Entry *_rtld_last_refobj; 272 273 /* 274 * Called when an object is freed. Reset the cached symbol look up if 275 * our last referencing or definition object just got unloaded. 276 */ 277 void 278 _rtld_combreloc_reset(const Obj_Entry *obj) 279 { 280 if (_rtld_last_refobj == obj) 281 _rtld_last_refobj = NULL; 282 } 283 #endif 284 285 /* 286 * Given a symbol number in a referencing object, find the corresponding 287 * definition of the symbol. Returns a pointer to the symbol, or NULL if 288 * no definition was found. Returns a pointer to the Obj_Entry of the 289 * defining object via the reference parameter DEFOBJ_OUT. 290 */ 291 const Elf_Sym * 292 _rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj, 293 const Obj_Entry **defobj_out, bool in_plt) 294 { 295 const Elf_Sym *ref; 296 const Elf_Sym *def; 297 const Obj_Entry *defobj; 298 const char *name; 299 unsigned long hash; 300 301 #ifdef COMBRELOC 302 /* 303 * COMBRELOC combines multiple reloc sections and sorts them to make 304 * dynamic symbol lookup caching possible. 305 * 306 * So if the lookup we are doing is the same as the previous lookup 307 * return the cached results. 308 */ 309 static unsigned long last_symnum; 310 static const Obj_Entry *last_defobj; 311 static const Elf_Sym *last_def; 312 313 if (symnum == last_symnum && refobj == _rtld_last_refobj 314 && in_plt == false) { 315 *defobj_out = last_defobj; 316 return last_def; 317 } 318 #endif 319 320 ref = refobj->symtab + symnum; 321 name = refobj->strtab + ref->st_name; 322 323 /* 324 * We don't have to do a full scale lookup if the symbol is local. 325 * We know it will bind to the instance in this load module; to 326 * which we already have a pointer (ie ref). 327 */ 328 if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) { 329 if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) { 330 _rtld_error("%s: Bogus symbol table entry %lu", 331 refobj->path, symnum); 332 } 333 334 hash = _rtld_elf_hash(name); 335 defobj = NULL; 336 def = _rtld_symlook_default(name, hash, refobj, &defobj, in_plt); 337 } else { 338 rdbg(("STB_LOCAL symbol %s in %s", name, refobj->path)); 339 def = ref; 340 defobj = refobj; 341 } 342 343 /* 344 * If we found no definition and the reference is weak, treat the 345 * symbol as having the value zero. 346 */ 347 if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) { 348 rdbg((" returning _rtld_sym_zero@_rtld_objself")); 349 def = &_rtld_sym_zero; 350 defobj = &_rtld_objself; 351 } 352 353 if (def != NULL) { 354 *defobj_out = defobj; 355 #ifdef COMBRELOC 356 if (in_plt == false) { 357 /* 358 * Cache the lookup arguments and results if this was 359 * non-PLT lookup. 360 */ 361 last_symnum = symnum; 362 _rtld_last_refobj = refobj; 363 last_def = def; 364 last_defobj = defobj; 365 } 366 #endif 367 } else { 368 rdbg(("lookup failed")); 369 _rtld_error("%s: Undefined %ssymbol \"%s\" (symnum = %ld)", 370 refobj->path, in_plt ? "PLT " : "", name, symnum); 371 } 372 return def; 373 } 374 375 const Elf_Sym * 376 _rtld_find_plt_symdef(unsigned long symnum, const Obj_Entry *obj, 377 const Obj_Entry **defobj, bool imm) 378 { 379 const Elf_Sym *def = _rtld_find_symdef(symnum, obj, defobj, true); 380 if (__predict_false(def == NULL)) 381 return NULL; 382 383 if (__predict_false(def == &_rtld_sym_zero)) { 384 /* tp is set during lazy binding. */ 385 if (imm) { 386 const Elf_Sym *ref = obj->symtab + symnum; 387 const char *name = obj->strtab + ref->st_name; 388 389 _rtld_error( 390 "%s: Trying to call undefined weak symbol `%s'", 391 obj->path, name); 392 return NULL; 393 } 394 } 395 return def; 396 } 397 398 /* 399 * Given a symbol name in a referencing object, find the corresponding 400 * definition of the symbol. Returns a pointer to the symbol, or NULL if 401 * no definition was found. Returns a pointer to the Obj_Entry of the 402 * defining object via the reference parameter DEFOBJ_OUT. 403 */ 404 const Elf_Sym * 405 _rtld_symlook_default(const char *name, unsigned long hash, 406 const Obj_Entry *refobj, const Obj_Entry **defobj_out, bool in_plt) 407 { 408 const Elf_Sym *def; 409 const Elf_Sym *symp; 410 const Obj_Entry *obj; 411 const Obj_Entry *defobj; 412 const Objlist_Entry *elm; 413 def = NULL; 414 defobj = NULL; 415 DoneList donelist; 416 417 _rtld_donelist_init(&donelist); 418 419 /* Look first in the referencing object if linked symbolically. */ 420 if (refobj->symbolic && !_rtld_donelist_check(&donelist, refobj)) { 421 rdbg(("search referencing object for %s", name)); 422 symp = _rtld_symlook_obj(name, hash, refobj, in_plt); 423 if (symp != NULL) { 424 def = symp; 425 defobj = refobj; 426 } 427 } 428 429 /* Search all objects loaded at program start up. */ 430 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { 431 rdbg(("search _rtld_list_main for %s", name)); 432 symp = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, 433 in_plt, &donelist); 434 if (symp != NULL && 435 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 436 def = symp; 437 defobj = obj; 438 } 439 } 440 441 /* Search all RTLD_GLOBAL objects. */ 442 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { 443 rdbg(("search _rtld_list_global for %s", name)); 444 symp = _rtld_symlook_list(name, hash, &_rtld_list_global, 445 &obj, in_plt, &donelist); 446 if (symp != NULL && 447 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 448 def = symp; 449 defobj = obj; 450 } 451 } 452 453 /* Search all dlopened DAGs containing the referencing object. */ 454 SIMPLEQ_FOREACH(elm, &refobj->dldags, link) { 455 if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) 456 break; 457 rdbg(("search DAG with root %p (%s) for %s", elm->obj, 458 elm->obj->path, name)); 459 symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers, 460 &obj, in_plt, &donelist); 461 if (symp != NULL && 462 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 463 def = symp; 464 defobj = obj; 465 } 466 } 467 468 /* 469 * Search the dynamic linker itself, and possibly resolve the 470 * symbol from there. This is how the application links to 471 * dynamic linker services such as dlopen. Only the values listed 472 * in the "_rtld_exports" array can be resolved from the dynamic 473 * linker. 474 */ 475 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { 476 rdbg(("Search the dynamic linker itself.")); 477 symp = _rtld_symlook_obj(name, hash, &_rtld_objself, in_plt); 478 if (symp != NULL && _rtld_is_exported(symp)) { 479 def = symp; 480 defobj = &_rtld_objself; 481 } 482 } 483 484 if (def != NULL) 485 *defobj_out = defobj; 486 return def; 487 } 488