1 /* $NetBSD: symbol.c,v 1.42 2007/02/23 01:16:32 matt 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.42 2007/02/23 01:16:32 matt 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 <dirent.h> 57 58 #include "debug.h" 59 #include "rtld.h" 60 61 typedef void (*fptr_t)(void); 62 63 static bool 64 _rtld_is_exported(const Elf_Sym *def) 65 { 66 static fptr_t _rtld_exports[] = { 67 (fptr_t)dlopen, 68 (fptr_t)dlclose, 69 (fptr_t)dlsym, 70 (fptr_t)dlerror, 71 (fptr_t)dladdr, 72 NULL 73 }; 74 int i; 75 fptr_t value; 76 77 value = (fptr_t)(_rtld_objself.relocbase + def->st_value); 78 for (i = 0; _rtld_exports[i] != NULL; i++) { 79 if (value == _rtld_exports[i]) 80 return true; 81 } 82 return false; 83 } 84 85 /* 86 * Hash function for symbol table lookup. Don't even think about changing 87 * this. It is specified by the System V ABI. 88 */ 89 unsigned long 90 _rtld_elf_hash(const char *name) 91 { 92 const unsigned char *p = (const unsigned char *) name; 93 unsigned long h = 0; 94 unsigned long g; 95 unsigned long c; 96 97 for (; __predict_true((c = *p) != '\0'); p++) { 98 h <<= 4; 99 h += c; 100 if ((g = h & 0xf0000000) != 0) { 101 h ^= g; 102 h ^= g >> 24; 103 } 104 } 105 return (h); 106 } 107 108 const Elf_Sym * 109 _rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist, 110 const Obj_Entry **defobj_out, bool in_plt) 111 { 112 const Elf_Sym *symp; 113 const Elf_Sym *def; 114 const Obj_Entry *defobj; 115 const Objlist_Entry *elm; 116 117 def = NULL; 118 defobj = NULL; 119 SIMPLEQ_FOREACH(elm, objlist, link) { 120 rdbg(("search object %p (%s)", elm->obj, elm->obj->path)); 121 if ((symp = _rtld_symlook_obj(name, hash, elm->obj, in_plt)) 122 != NULL) { 123 if ((def == NULL) || 124 (ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 125 def = symp; 126 defobj = elm->obj; 127 if (ELF_ST_BIND(def->st_info) != STB_WEAK) 128 break; 129 } 130 } 131 } 132 if (def != NULL) 133 *defobj_out = defobj; 134 return def; 135 } 136 137 /* 138 * Search the symbol table of a single shared object for a symbol of 139 * the given name. Returns a pointer to the symbol, or NULL if no 140 * definition was found. 141 * 142 * The symbol's hash value is passed in for efficiency reasons; that 143 * eliminates many recomputations of the hash value. 144 */ 145 const Elf_Sym * 146 _rtld_symlook_obj(const char *name, unsigned long hash, 147 const Obj_Entry *obj, bool in_plt) 148 { 149 unsigned long symnum; 150 151 for (symnum = obj->buckets[hash % obj->nbuckets]; 152 symnum != ELF_SYM_UNDEFINED; 153 symnum = obj->chains[symnum]) { 154 const Elf_Sym *symp; 155 const char *strp; 156 157 assert(symnum < obj->nchains); 158 symp = obj->symtab + symnum; 159 strp = obj->strtab + symp->st_name; 160 rdbg(("check \"%s\" vs \"%s\" in %p", name, strp, obj)); 161 if (name[1] == strp[1] && !strcmp(name, strp)) { 162 if (symp->st_shndx != SHN_UNDEF) 163 return symp; 164 #ifndef __mips__ 165 /* 166 * XXX DANGER WILL ROBINSON! 167 * If we have a function pointer in the executable's 168 * data section, it points to the executable's PLT 169 * slot, and there is NO relocation emitted. To make 170 * the function pointer comparable to function pointers 171 * in shared libraries, we must resolve data references 172 * in the libraries to point to PLT slots in the 173 * executable, if they exist. 174 */ 175 else if (!in_plt && symp->st_value != 0 && 176 ELF_ST_TYPE(symp->st_info) == STT_FUNC) 177 return symp; 178 #endif 179 else 180 return NULL; 181 } 182 } 183 184 return NULL; 185 } 186 187 /* 188 * Given a symbol number in a referencing object, find the corresponding 189 * definition of the symbol. Returns a pointer to the symbol, or NULL if 190 * no definition was found. Returns a pointer to the Obj_Entry of the 191 * defining object via the reference parameter DEFOBJ_OUT. 192 */ 193 const Elf_Sym * 194 _rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj, 195 const Obj_Entry **defobj_out, bool in_plt) 196 { 197 const Elf_Sym *ref; 198 const Elf_Sym *def; 199 const Obj_Entry *defobj; 200 const char *name; 201 unsigned long hash; 202 203 #ifdef COMBRELOC 204 /* 205 * COMBRELOC combines multiple reloc sections and sorts them to make 206 * dynamic symbol lookup caching possible. 207 * 208 * So if the lookup we are doing is the same as the previous lookup 209 * return the cached results. 210 */ 211 static unsigned long last_symnum; 212 static const Elf_Sym *last_def; 213 static const Obj_Entry *last_refobj; 214 static const Obj_Entry *last_defobj; 215 216 if (symnum == last_symnum && refobj == last_refobj 217 && in_plt == false) { 218 *defobj_out = last_defobj; 219 return last_def; 220 } 221 #endif 222 223 ref = refobj->symtab + symnum; 224 name = refobj->strtab + ref->st_name; 225 226 /* 227 * We don't have to do a full scale lookup if the symbol is local. 228 * We know it will bind to the instance in this load module; to 229 * which we already have a pointer (ie ref). 230 */ 231 if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) { 232 if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) { 233 _rtld_error("%s: Bogus symbol table entry %lu", 234 refobj->path, symnum); 235 } 236 237 hash = _rtld_elf_hash(name); 238 defobj = NULL; 239 def = _rtld_symlook_default(name, hash, refobj, &defobj, in_plt); 240 } else { 241 rdbg(("STB_LOCAL symbol %s in %s", name, refobj->path)); 242 def = ref; 243 defobj = refobj; 244 } 245 246 /* 247 * If we found no definition and the reference is weak, treat the 248 * symbol as having the value zero. 249 */ 250 if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) { 251 rdbg((" returning _rtld_sym_zero@_rtld_objmain")); 252 def = &_rtld_sym_zero; 253 defobj = _rtld_objmain; 254 } 255 256 if (def != NULL) { 257 *defobj_out = defobj; 258 #ifdef COMBRELOC 259 if (in_plt == false) { 260 /* 261 * Cache the lookup arguments and results if this was 262 * non-PLT lookup. 263 */ 264 last_symnum = symnum; 265 last_refobj = refobj; 266 last_def = def; 267 last_defobj = defobj; 268 } 269 #endif 270 } else { 271 rdbg(("lookup failed")); 272 _rtld_error("%s: Undefined %ssymbol \"%s\" (symnum = %ld)", 273 refobj->path, in_plt ? "PLT " : "", name, symnum); 274 } 275 return def; 276 } 277 278 /* 279 * Given a symbol name in a referencing object, find the corresponding 280 * definition of the symbol. Returns a pointer to the symbol, or NULL if 281 * no definition was found. Returns a pointer to the Obj_Entry of the 282 * defining object via the reference parameter DEFOBJ_OUT. 283 */ 284 const Elf_Sym * 285 _rtld_symlook_default(const char *name, unsigned long hash, 286 const Obj_Entry *refobj, const Obj_Entry **defobj_out, bool in_plt) 287 { 288 const Elf_Sym *def; 289 const Elf_Sym *symp; 290 const Obj_Entry *obj; 291 const Obj_Entry *defobj; 292 const Objlist_Entry *elm; 293 def = NULL; 294 defobj = NULL; 295 296 /* Look first in the referencing object if linked symbolically. */ 297 if (refobj->symbolic) { 298 rdbg(("search referencing object")); 299 symp = _rtld_symlook_obj(name, hash, refobj, in_plt); 300 if (symp != NULL) { 301 def = symp; 302 defobj = refobj; 303 } 304 } 305 306 /* Search all objects loaded at program start up. */ 307 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { 308 rdbg(("search _rtld_list_main")); 309 symp = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, 310 in_plt); 311 if (symp != NULL && 312 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 313 def = symp; 314 defobj = obj; 315 } 316 } 317 318 /* Search all RTLD_GLOBAL objects. */ 319 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { 320 rdbg(("search _rtld_list_global")); 321 symp = _rtld_symlook_list(name, hash, &_rtld_list_global, 322 &obj, in_plt); 323 if (symp != NULL && 324 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 325 def = symp; 326 defobj = obj; 327 } 328 } 329 330 /* Search all dlopened DAGs containing the referencing object. */ 331 SIMPLEQ_FOREACH(elm, &refobj->dldags, link) { 332 if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) 333 break; 334 rdbg(("search DAG with root %p (%s)", elm->obj, 335 elm->obj->path)); 336 symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers, 337 &obj, in_plt); 338 if (symp != NULL && 339 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 340 def = symp; 341 defobj = obj; 342 } 343 } 344 345 /* 346 * Search the dynamic linker itself, and possibly resolve the 347 * symbol from there. This is how the application links to 348 * dynamic linker services such as dlopen. Only the values listed 349 * in the "_rtld_exports" array can be resolved from the dynamic 350 * linker. 351 */ 352 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { 353 rdbg(("Search the dynamic linker itself.")); 354 symp = _rtld_symlook_obj(name, hash, &_rtld_objself, in_plt); 355 if (symp != NULL && _rtld_is_exported(symp)) { 356 def = symp; 357 defobj = &_rtld_objself; 358 } 359 } 360 361 if (def != NULL) 362 *defobj_out = defobj; 363 return def; 364 } 365