1121461Sharti/* $NetBSD: symbol.c,v 1.58 2011/08/13 22:24:57 christos Exp $ */ 2121461Sharti 3121461Sharti/* 4121461Sharti * Copyright 1996 John D. Polstra. 5121461Sharti * Copyright 1996 Matt Thomas <matt@3am-software.com> 6121461Sharti * Copyright 2002 Charles M. Hannum <root@ihack.net> 7121461Sharti * All rights reserved. 8121461Sharti * 9121461Sharti * Redistribution and use in source and binary forms, with or without 10121461Sharti * modification, are permitted provided that the following conditions 11121461Sharti * are met: 12121461Sharti * 1. Redistributions of source code must retain the above copyright 13121461Sharti * notice, this list of conditions and the following disclaimer. 14121461Sharti * 2. Redistributions in binary form must reproduce the above copyright 15121461Sharti * notice, this list of conditions and the following disclaimer in the 16121461Sharti * documentation and/or other materials provided with the distribution. 17121461Sharti * 3. All advertising materials mentioning features or use of this software 18121461Sharti * must display the following acknowledgement: 19121461Sharti * This product includes software developed by John Polstra. 20121461Sharti * 4. The name of the author may not be used to endorse or promote products 21121461Sharti * derived from this software without specific prior written permission. 22121461Sharti * 23121461Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24121461Sharti * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25121461Sharti * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26121461Sharti * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27121461Sharti * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28121461Sharti * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29121461Sharti * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30121461Sharti * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31121461Sharti * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32121461Sharti * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33121461Sharti */ 34121461Sharti 35121461Sharti/* 36121461Sharti * Dynamic linker for ELF. 37121461Sharti * 38121461Sharti * John Polstra <jdp@polstra.com>. 39121461Sharti */ 40121461Sharti 41121461Sharti#include <sys/cdefs.h> 42121461Sharti#ifndef lint 43121461Sharti__RCSID("$NetBSD: symbol.c,v 1.58 2011/08/13 22:24:57 christos Exp $"); 44121461Sharti#endif /* not lint */ 45121461Sharti 46121461Sharti#include <err.h> 47121461Sharti#include <errno.h> 48121461Sharti#include <fcntl.h> 49121461Sharti#include <stdarg.h> 50121461Sharti#include <stdio.h> 51121461Sharti#include <stdlib.h> 52121461Sharti#include <string.h> 53121461Sharti#include <unistd.h> 54121461Sharti#include <sys/types.h> 55121461Sharti#include <sys/mman.h> 56121461Sharti#include <sys/bitops.h> 57121461Sharti#include <dirent.h> 58121461Sharti 59121461Sharti#include "debug.h" 60121461Sharti#include "rtld.h" 61121461Sharti 62121461Shartitypedef void (*fptr_t)(void); 63121461Sharti 64121461Sharti/* 65121461Sharti * If the given object is already in the donelist, return true. Otherwise 66121461Sharti * add the object to the list and return false. 67121461Sharti */ 68121461Shartistatic bool 69121461Sharti_rtld_donelist_check(DoneList *dlp, const Obj_Entry *obj) 70121461Sharti{ 71121461Sharti unsigned int i; 72121461Sharti 73121461Sharti for (i = 0; i < dlp->num_used; i++) 74121461Sharti if (dlp->objs[i] == obj) 75121461Sharti return true; 76121461Sharti /* 77121461Sharti * Our donelist allocation may not always be sufficient as we're not 78121461Sharti * thread safe. We'll handle it properly anyway. 79121461Sharti */ 80121461Sharti if (dlp->num_used < dlp->num_alloc) 81121461Sharti dlp->objs[dlp->num_used++] = obj; 82121461Sharti return false; 83121461Sharti} 84121461Sharti 85121461Shartistatic bool 86121461Sharti_rtld_is_exported(const Elf_Sym *def) 87121461Sharti{ 88121461Sharti static const fptr_t _rtld_exports[] = { 89121461Sharti (fptr_t)dlopen, 90121461Sharti (fptr_t)dlclose, 91121461Sharti (fptr_t)dlsym, 92121461Sharti (fptr_t)dlvsym, 93121461Sharti (fptr_t)dlerror, 94121461Sharti (fptr_t)dladdr, 95121461Sharti (fptr_t)dlinfo, 96121461Sharti (fptr_t)dl_iterate_phdr, 97121461Sharti#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 98121461Sharti (fptr_t)_rtld_tls_allocate, 99121461Sharti (fptr_t)_rtld_tls_free, 100121461Sharti (fptr_t)__tls_get_addr, 101121461Sharti#ifdef __i386__ 102121461Sharti (fptr_t)___tls_get_addr, 103121461Sharti#endif 104121461Sharti#endif 105121461Sharti NULL 106121461Sharti }; 107121461Sharti int i; 108137199Sharti fptr_t value; 109137199Sharti 110121461Sharti value = (fptr_t)(_rtld_objself.relocbase + def->st_value); 111137199Sharti for (i = 0; _rtld_exports[i] != NULL; i++) { 112121461Sharti if (value == _rtld_exports[i]) 113121461Sharti return true; 114137199Sharti } 115121461Sharti return false; 116121461Sharti} 117137199Sharti 118121461Sharti/* 119121461Sharti * Hash function for symbol table lookup. Don't even think about changing 120121461Sharti * this. It is specified by the System V ABI. 121121461Sharti */ 122121461Shartiunsigned long 123121461Sharti_rtld_elf_hash(const char *name) 124121461Sharti{ 125121461Sharti const unsigned char *p = (const unsigned char *) name; 126121461Sharti unsigned long h = 0; 127121461Sharti unsigned long g; 128121461Sharti unsigned long c; 129121461Sharti 130121461Sharti for (; __predict_true((c = *p) != '\0'); p++) { 131121461Sharti h <<= 4; 132121461Sharti h += c; 133121461Sharti if ((g = h & 0xf0000000) != 0) { 134121461Sharti h ^= g; 135121461Sharti h ^= g >> 24; 136121461Sharti } 137121461Sharti } 138121461Sharti return (h); 139121461Sharti} 140121461Sharti 141121461Sharticonst Elf_Sym * 142121461Sharti_rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist, 143121461Sharti const Obj_Entry **defobj_out, u_int flags, const Ver_Entry *ventry, 144121461Sharti DoneList *dlp) 145121461Sharti{ 146121461Sharti const Elf_Sym *symp; 147121461Sharti const Elf_Sym *def; 148121461Sharti const Obj_Entry *defobj; 149121461Sharti const Objlist_Entry *elm; 150121461Sharti 151121461Sharti def = NULL; 152121461Sharti defobj = NULL; 153121461Sharti SIMPLEQ_FOREACH(elm, objlist, link) { 154121461Sharti if (_rtld_donelist_check(dlp, elm->obj)) 155121461Sharti continue; 156121461Sharti rdbg(("search object %p (%s) for %s", elm->obj, elm->obj->path, 157121461Sharti name)); 158121461Sharti symp = _rtld_symlook_obj(name, hash, elm->obj, flags, ventry); 159121461Sharti if (symp != NULL) { 160121461Sharti if ((def == NULL) || 161121461Sharti (ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 162121461Sharti def = symp; 163121461Sharti defobj = elm->obj; 164121461Sharti if (ELF_ST_BIND(def->st_info) != STB_WEAK) 165121461Sharti break; 166121461Sharti } 167121461Sharti } 168121461Sharti } 169121461Sharti if (def != NULL) 170121461Sharti *defobj_out = defobj; 171121461Sharti return def; 172121461Sharti} 173121461Sharti 174121461Sharti/* 175121461Sharti * Search the symbol table of a shared object and all objects needed by it for 176121461Sharti * a symbol of the given name. Search order is breadth-first. Returns a pointer 177121461Sharti * to the symbol, or NULL if no definition was found. 178121461Sharti */ 179121461Sharticonst Elf_Sym * 180121461Sharti_rtld_symlook_needed(const char *name, unsigned long hash, 181121461Sharti const Needed_Entry *needed, const Obj_Entry **defobj_out, u_int flags, 182121461Sharti const Ver_Entry *ventry, DoneList *breadth, DoneList *depth) 183121461Sharti{ 184121461Sharti const Elf_Sym *def, *def_w; 185121461Sharti const Needed_Entry *n; 186121461Sharti const Obj_Entry *obj, *defobj, *defobj1; 187121461Sharti 188121461Sharti def = def_w = NULL; 189121461Sharti defobj = NULL; 190121461Sharti for (n = needed; n != NULL; n = n->next) { 191121461Sharti if ((obj = n->obj) == NULL) 192121461Sharti continue; 193121461Sharti if (_rtld_donelist_check(breadth, obj)) 194121461Sharti continue; 195121461Sharti def = _rtld_symlook_obj(name, hash, obj, flags, ventry); 196121461Sharti if (def == NULL) 197121461Sharti continue; 198121461Sharti defobj = obj; 199121461Sharti if (ELF_ST_BIND(def->st_info) != STB_WEAK) { 200121461Sharti *defobj_out = defobj; 201121461Sharti 202121461Sharti return (def); 203121461Sharti } 204121461Sharti } 205121461Sharti /* 206121461Sharti * Either the symbol definition has not been found in directly needed 207121461Sharti * objects, or the found symbol is weak. 208121461Sharti */ 209121461Sharti for (n = needed; n != NULL; n = n->next) { 210121461Sharti if ((obj = n->obj) == NULL) 211121461Sharti continue; 212121461Sharti if (_rtld_donelist_check(depth, obj)) 213121461Sharti continue; 214121461Sharti def_w = _rtld_symlook_needed(name, hash, obj->needed, &defobj1, 215121461Sharti flags, ventry, breadth, depth); 216121461Sharti if (def_w == NULL) 217121461Sharti continue; 218121461Sharti if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) { 219121461Sharti def = def_w; 220121461Sharti defobj = defobj1; 221121461Sharti if (ELF_ST_BIND(def_w->st_info) != STB_WEAK) 222121461Sharti break; 223121461Sharti } 224121461Sharti } 225121461Sharti if (def != NULL) 226121461Sharti *defobj_out = defobj; 227121461Sharti 228121461Sharti return def; 229121461Sharti} 230121461Sharti 231121461Sharti/* 232121461Sharti * Search the symbol table of a single shared object for a symbol of 233121461Sharti * the given name. Returns a pointer to the symbol, or NULL if no 234121461Sharti * definition was found. 235121461Sharti * 236121461Sharti * The symbol's hash value is passed in for efficiency reasons; that 237121461Sharti * eliminates many recomputations of the hash value. 238121461Sharti */ 239121461Sharticonst Elf_Sym * 240121461Sharti_rtld_symlook_obj(const char *name, unsigned long hash, 241121461Sharti const Obj_Entry *obj, u_int flags, const Ver_Entry *ventry) 242121461Sharti{ 243121461Sharti unsigned long symnum; 244121461Sharti const Elf_Sym *vsymp = NULL; 245121461Sharti Elf_Half verndx; 246121461Sharti int vcount = 0; 247121461Sharti 248121461Sharti for (symnum = obj->buckets[fast_remainder32(hash, obj->nbuckets, 249121461Sharti obj->nbuckets_m, obj->nbuckets_s1, obj->nbuckets_s2)]; 250121461Sharti symnum != ELF_SYM_UNDEFINED; 251121461Sharti symnum = obj->chains[symnum]) { 252121461Sharti const Elf_Sym *symp; 253121461Sharti const char *strp; 254121461Sharti 255121461Sharti assert(symnum < obj->nchains); 256121461Sharti symp = obj->symtab + symnum; 257121461Sharti strp = obj->strtab + symp->st_name; 258121461Sharti rdbg(("check \"%s\" vs \"%s\" in %s", name, strp, obj->path)); 259121461Sharti if (name[1] != strp[1] || strcmp(name, strp)) 260121461Sharti continue; 261121461Sharti#ifdef __mips__ 262121461Sharti if (symp->st_shndx == SHN_UNDEF) 263121461Sharti continue; 264121461Sharti#else 265121461Sharti /* 266121461Sharti * XXX DANGER WILL ROBINSON! 267121461Sharti * If we have a function pointer in the executable's 268121461Sharti * data section, it points to the executable's PLT 269121461Sharti * slot, and there is NO relocation emitted. To make 270121461Sharti * the function pointer comparable to function pointers 271121461Sharti * in shared libraries, we must resolve data references 272121461Sharti * in the libraries to point to PLT slots in the 273121461Sharti * executable, if they exist. 274121461Sharti */ 275121461Sharti if (symp->st_shndx == SHN_UNDEF && 276121461Sharti ((flags & SYMLOOK_IN_PLT) || 277121461Sharti symp->st_value == 0 || 278121461Sharti ELF_ST_TYPE(symp->st_info) != STT_FUNC)) 279121461Sharti continue; 280121461Sharti#endif 281121461Sharti 282121461Sharti if (ventry == NULL) { 283121461Sharti if (obj->versyms != NULL) { 284121461Sharti verndx = VER_NDX(obj->versyms[symnum].vs_vers); 285121461Sharti if (verndx > obj->vertabnum) { 286121461Sharti _rtld_error("%s: symbol %s references " 287121461Sharti "wrong version %d", obj->path, 288121461Sharti &obj->strtab[symnum], verndx); 289121461Sharti continue; 290121461Sharti } 291121461Sharti 292121461Sharti /* 293121461Sharti * If we are not called from dlsym (i.e. this 294121461Sharti * is a normal relocation from unversioned 295121461Sharti * binary), accept the symbol immediately 296121461Sharti * if it happens to have first version after 297121461Sharti * this shared object became versioned. 298121461Sharti * Otherwise, if symbol is versioned and not 299121461Sharti * hidden, remember it. If it is the only 300121461Sharti * symbol with this name exported by the shared 301121461Sharti * object, it will be returned as a match at the 302121461Sharti * end of the function. If symbol is global 303121461Sharti * (verndx < 2) accept it unconditionally. 304121461Sharti */ 305121461Sharti if (!(flags & SYMLOOK_DLSYM) && 306121461Sharti verndx == VER_NDX_GIVEN) { 307121461Sharti return symp; 308121461Sharti } else if (verndx >= VER_NDX_GIVEN) { 309121461Sharti if (!(obj->versyms[symnum].vs_vers & VER_NDX_HIDDEN)) { 310121461Sharti if (vsymp == NULL) 311121461Sharti vsymp = symp; 312121461Sharti vcount++; 313121461Sharti } 314121461Sharti continue; 315121461Sharti } 316121461Sharti } 317121461Sharti return symp; 318121461Sharti } else { 319121461Sharti if (obj->versyms == NULL) { 320121461Sharti if (_rtld_object_match_name(obj, ventry->name)){ 321121461Sharti _rtld_error("%s: object %s should " 322121461Sharti "provide version %s for symbol %s", 323121461Sharti _rtld_objself.path, obj->path, 324121461Sharti ventry->name, &obj->strtab[symnum]); 325121461Sharti continue; 326121461Sharti } 327121461Sharti } else { 328121461Sharti verndx = VER_NDX(obj->versyms[symnum].vs_vers); 329121461Sharti if (verndx > obj->vertabnum) { 330121461Sharti _rtld_error("%s: symbol %s references " 331121461Sharti "wrong version %d", obj->path, 332121461Sharti &obj->strtab[symnum], verndx); 333121461Sharti continue; 334121461Sharti } 335121461Sharti if (obj->vertab[verndx].hash != ventry->hash || 336121461Sharti strcmp(obj->vertab[verndx].name, ventry->name)) { 337121461Sharti /* 338121461Sharti * Version does not match. Look if this 339121461Sharti * is a global symbol and if it is not 340121461Sharti * hidden. If global symbol (verndx < 2) 341121461Sharti * is available, use it. Do not return 342121461Sharti * symbol if we are called by dlvsym, 343121461Sharti * 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