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