1 /* $NetBSD: rtld.c,v 1.5 1997/10/08 08:55:37 mrg Exp $ */ 2 3 /* 4 * Copyright 1996 John D. Polstra. 5 * Copyright 1996 Matt Thomas <matt@3am-software.com> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by John Polstra. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Dynamic linker for ELF. 36 * 37 * John Polstra <jdp@polstra.com>. 38 */ 39 40 #include <err.h> 41 #include <errno.h> 42 #include <fcntl.h> 43 #include <stdarg.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <unistd.h> 48 #include <sys/param.h> 49 #include <sys/mman.h> 50 #include <dirent.h> 51 52 #include <ctype.h> 53 54 #include <dlfcn.h> 55 #include "debug.h" 56 #include "rtld.h" 57 58 #include "sysident.h" 59 60 #ifndef RTLD_NOW 61 #define RTLD_NOW (RTLD_LAZY + 1) 62 #endif 63 64 /* 65 * Debugging support. 66 */ 67 68 typedef void (*funcptr)(void); 69 70 /* 71 * Function declarations. 72 */ 73 static void _rtld_init(caddr_t); 74 static void _rtld_exit(void); 75 76 /* 77 * Data declarations. 78 */ 79 static char *error_message; /* Message for dlopen(), or NULL */ 80 81 struct r_debug _rtld_debug; /* for GDB; */ 82 bool _rtld_trust; /* False for setuid and setgid programs */ 83 Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */ 84 Obj_Entry **_rtld_objtail; /* Link field of last object in list */ 85 Obj_Entry *_rtld_objmain; /* The main program shared object */ 86 Obj_Entry _rtld_objself; /* The dynamic linker shared object */ 87 char _rtld_path[] = _PATH_RTLD; 88 89 Search_Path *_rtld_paths; 90 /* 91 * Global declarations normally provided by crt0. 92 */ 93 char *__progname; 94 char **environ; 95 96 #ifdef OLD_GOT 97 extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; 98 #else 99 extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; 100 extern Elf_Dyn _DYNAMIC; 101 #endif 102 103 static void 104 _rtld_call_fini_functions( 105 Obj_Entry *first) 106 { 107 Obj_Entry *obj; 108 109 for (obj = first; obj != NULL; obj = obj->next) 110 if (obj->fini != NULL) 111 (*obj->fini)(); 112 } 113 114 static void 115 _rtld_call_init_functions( 116 Obj_Entry *first) 117 { 118 if (first != NULL) { 119 _rtld_call_init_functions(first->next); 120 if (first->init != NULL) 121 (*first->init)(); 122 } 123 } 124 125 /* 126 * Initialize the dynamic linker. The argument is the address at which 127 * the dynamic linker has been mapped into memory. The primary task of 128 * this function is to relocate the dynamic linker. 129 */ 130 static void 131 _rtld_init( 132 caddr_t mapbase) 133 { 134 _rtld_add_paths(&_rtld_paths, RTLD_DEFAULT_LIBRARY_PATH); 135 136 /* Conjure up an Obj_Entry structure for the dynamic linker. */ 137 138 _rtld_objself.path = _rtld_path; 139 _rtld_objself.rtld = true; 140 _rtld_objself.mapbase = mapbase; 141 _rtld_objself.relocbase = mapbase; 142 _rtld_objself.pltgot = NULL; 143 #ifdef OLD_GOT 144 _rtld_objself.dynamic = (Elf_Dyn *) _GLOBAL_OFFSET_TABLE_[0]; 145 #else 146 _rtld_objself.dynamic = &_DYNAMIC; 147 #endif 148 149 _rtld_digest_dynamic(&_rtld_objself); 150 #ifdef __alpha__ 151 /* XXX XXX XXX */ 152 _rtld_objself.pltgot = NULL; 153 #endif 154 assert(_rtld_objself.needed == NULL); 155 assert(!_rtld_objself.textrel); 156 157 /* Set up the _rtld_objlist pointer, so that rtld symbols can be found. */ 158 _rtld_objlist = &_rtld_objself; 159 160 _rtld_relocate_objects(&_rtld_objself, true); 161 162 /* Make the object list empty again. */ 163 _rtld_objlist = NULL; 164 _rtld_objtail = &_rtld_objlist; 165 166 _rtld_debug.r_brk = _rtld_debug_state; 167 _rtld_debug.r_state = RT_CONSISTENT; 168 } 169 170 /* 171 * Cleanup procedure. It will be called (by the atexit() mechanism) just 172 * before the process exits. 173 */ 174 static void 175 _rtld_exit(void) 176 { 177 dbg("rtld_exit()"); 178 179 _rtld_call_fini_functions(_rtld_objlist->next); 180 } 181 182 /* 183 * Main entry point for dynamic linking. The argument is the stack 184 * pointer. The stack is expected to be laid out as described in the 185 * SVR4 ABI specification, Intel 386 Processor Supplement. Specifically, 186 * the stack pointer points to a word containing ARGC. Following that 187 * in the stack is a null-terminated sequence of pointers to argument 188 * strings. Then comes a null-terminated sequence of pointers to 189 * environment strings. Finally, there is a sequence of "auxiliary 190 * vector" entries. 191 * 192 * This function returns the entry point for the main program in %eax, 193 * and the dynamic linker's exit procedure in %edx. We accomplish this 194 * by declaring the return value to have the 64-bit type "long long". 195 * Such values are returned with their most-significant 32 bits in %edx, 196 * and their least-significant 32 bits in %eax. 197 */ 198 Elf_Addr _rtld(Elf_Word *); 199 200 Elf_Addr 201 _rtld( 202 Elf_Word *sp) 203 { 204 const AuxInfo *aux_info[AUX_count]; 205 int i = 0; 206 char **env; 207 const AuxInfo *aux; 208 const AuxInfo *auxp; 209 Elf_Word * const osp = sp; 210 bool bind_now = 0; 211 const char *ld_bind_now; 212 const char **argv; 213 214 /* 215 * On entry, the dynamic linker itself has not been relocated yet. 216 * Be very careful not to reference any global data until after 217 * _rtld_init has returned. It is OK to reference file-scope statics 218 * and string constants, and to call static and global functions. 219 */ 220 /* Find the auxiliary vector on the stack. */ 221 /* first Elf_Word reserved to address of exit routine */ 222 #ifdef RTLD_DEBUG 223 xprintf("sp = %p, argc = %d, argv = %p <%s>\n", sp, sp[2], &sp[3], sp[3]); 224 xprintf("got is at %p, dynamic is at %p\n", _GLOBAL_OFFSET_TABLE_, &_DYNAMIC); 225 debug = 1; 226 xprintf("_ctype_ is %p\n", _ctype_); 227 #endif 228 229 sp += 2; /* skip over return argument space */ 230 argv = (const char **) &sp[1]; 231 sp += sp[0] + 2; /* Skip over argc, arguments, and NULL terminator */ 232 env = (char **) sp; 233 while (*sp++ != 0) { /* Skip over environment, and NULL terminator */ 234 #ifdef RTLD_DEBUG 235 xprintf("env[%d] = %p\n", i++, sp[-1]); 236 #endif 237 } 238 aux = (const AuxInfo *) sp; 239 240 /* Digest the auxiliary vector. */ 241 for (i = 0; i < AUX_count; ++i) 242 aux_info[i] = NULL; 243 for (auxp = aux; auxp->au_id != AUX_null; ++auxp) { 244 if (auxp->au_id < AUX_count) 245 aux_info[auxp->au_id] = auxp; 246 } 247 248 /* Initialize and relocate ourselves. */ 249 assert(aux_info[AUX_base] != NULL); 250 _rtld_init((caddr_t) aux_info[AUX_base]->au_v); 251 252 #ifdef RTLD_DEBUG 253 xprintf("_ctype_ is %p\n", _ctype_); 254 #endif 255 if (aux_info[AUX_debug] != NULL) /* Set debugging level */ 256 debug = aux_info[AUX_debug]->au_v; 257 258 __progname = _rtld_objself.path; 259 environ = env; 260 261 _rtld_trust = geteuid() == getuid() && getegid() == getgid(); 262 263 ld_bind_now = getenv("LD_BIND_NOW"); 264 if (ld_bind_now != NULL && *ld_bind_now != '\0') 265 bind_now = true; 266 if (_rtld_trust) { 267 const char *ld_debug = getenv("LD_DEBUG"); 268 if (ld_debug != NULL && *ld_debug != '\0') 269 debug = 1; 270 _rtld_add_paths(&_rtld_paths, getenv("LD_LIBRARY_PATH")); 271 } 272 273 dbg("%s is initialized, base address = %p", __progname, 274 (caddr_t) aux_info[AUX_base]->au_v); 275 276 /* 277 * Load the main program, or process its program header if it is 278 * already loaded. 279 */ 280 if (aux_info[AUX_execfd] != NULL) { /* Load the main program. */ 281 int fd = aux_info[AUX_execfd]->au_v; 282 dbg("loading main program"); 283 _rtld_objmain = _rtld_map_object(argv[0], fd); 284 close(fd); 285 if (_rtld_objmain == NULL) 286 _rtld_die(); 287 } else { /* Main program already loaded. */ 288 const Elf_Phdr *phdr; 289 int phnum; 290 caddr_t entry; 291 292 dbg("processing main program's program header"); 293 assert(aux_info[AUX_phdr] != NULL); 294 phdr = (const Elf_Phdr *) aux_info[AUX_phdr]->au_v; 295 assert(aux_info[AUX_phnum] != NULL); 296 phnum = aux_info[AUX_phnum]->au_v; 297 assert(aux_info[AUX_phent] != NULL); 298 assert(aux_info[AUX_phent]->au_v == sizeof(Elf_Phdr)); 299 assert(aux_info[AUX_entry] != NULL); 300 entry = (caddr_t) aux_info[AUX_entry]->au_v; 301 _rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry); 302 } 303 304 _rtld_objmain->path = xstrdup("main program"); 305 _rtld_objmain->mainprog = true; 306 _rtld_digest_dynamic(_rtld_objmain); 307 308 _rtld_linkmap_add(_rtld_objmain); 309 _rtld_linkmap_add(&_rtld_objself); 310 311 /* Link the main program into the list of objects. */ 312 *_rtld_objtail = _rtld_objmain; 313 _rtld_objtail = &_rtld_objmain->next; 314 ++_rtld_objmain->refcount; 315 316 dbg("loading needed objects"); 317 if (_rtld_load_needed_objects(_rtld_objmain) == -1) 318 _rtld_die(); 319 320 dbg("relocating objects"); 321 if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1) 322 _rtld_die(); 323 324 dbg("doing copy relocations"); 325 if (_rtld_do_copy_relocations(_rtld_objmain) == -1) 326 _rtld_die(); 327 328 dbg("calling _init functions"); 329 _rtld_call_init_functions(_rtld_objmain->next); 330 331 dbg("transferring control to program entry point = %p", 332 _rtld_objmain->entry); 333 334 /* Return with the entry point and the exit procedure in at the top of 335 * stack. 336 */ 337 338 _rtld_debug_state(); /* say hello to gdb! */ 339 340 ((void **) osp)[0] = _rtld_exit; 341 ((void **) osp)[1] = _rtld_objmain; 342 return (Elf_Addr) _rtld_objmain->entry; 343 } 344 345 void 346 _rtld_die( 347 void) 348 { 349 const char *msg = _rtld_dlerror(); 350 351 if (msg == NULL) 352 msg = "Fatal error"; 353 xerrx(1, "%s\n", msg); 354 } 355 356 static Obj_Entry * 357 _rtld_dlcheck( 358 void *handle) 359 { 360 Obj_Entry *obj; 361 362 for (obj = _rtld_objlist; obj != NULL; obj = obj->next) 363 if (obj == (Obj_Entry *) handle) 364 break; 365 366 if (obj == NULL || obj->dl_refcount == 0) { 367 xwarnx("Invalid shared object handle %p", handle); 368 return NULL; 369 } 370 return obj; 371 } 372 373 static void 374 _rtld_unref_object_dag( 375 Obj_Entry *root) 376 { 377 assert(root->refcount != 0); 378 --root->refcount; 379 if (root->refcount == 0) { 380 const Needed_Entry *needed; 381 382 for (needed = root->needed; needed != NULL; needed = needed->next) 383 _rtld_unref_object_dag(needed->obj); 384 } 385 } 386 387 int 388 _rtld_dlclose( 389 void *handle) 390 { 391 Obj_Entry *root = _rtld_dlcheck(handle); 392 393 if (root == NULL) 394 return -1; 395 396 _rtld_debug.r_state = RT_DELETE; 397 _rtld_debug_state(); 398 399 --root->dl_refcount; 400 _rtld_unref_object_dag(root); 401 if (root->refcount == 0) { /* We are finished with some objects. */ 402 Obj_Entry *obj; 403 Obj_Entry **linkp; 404 405 /* Finalize objects that are about to be unmapped. */ 406 for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next) 407 if (obj->refcount == 0 && obj->fini != NULL) 408 (*obj->fini)(); 409 410 /* Unmap all objects that are no longer referenced. */ 411 linkp = &_rtld_objlist->next; 412 while((obj = *linkp) != NULL) { 413 if (obj->refcount == 0) { 414 munmap(obj->mapbase, obj->mapsize); 415 free(obj->path); 416 while(obj->needed != NULL) { 417 Needed_Entry *needed = obj->needed; 418 obj->needed = needed->next; 419 free(needed); 420 } 421 _rtld_linkmap_delete(obj); 422 *linkp = obj->next; 423 free(obj); 424 } else 425 linkp = &obj->next; 426 } 427 } 428 429 _rtld_debug.r_state = RT_CONSISTENT; 430 _rtld_debug_state(); 431 432 return 0; 433 } 434 435 char * 436 _rtld_dlerror( 437 void) 438 { 439 char *msg = error_message; 440 error_message = NULL; 441 return msg; 442 } 443 444 void * 445 _rtld_dlopen( 446 const char *name, 447 int mode) 448 { 449 Obj_Entry **old_obj_tail = _rtld_objtail; 450 Obj_Entry *obj = NULL; 451 452 _rtld_debug.r_state = RT_ADD; 453 _rtld_debug_state(); 454 455 if (name == NULL) { 456 obj = _rtld_objmain; 457 } else { 458 char *path = _rtld_find_library(name, NULL); 459 if (path != NULL) 460 obj = _rtld_load_object(path); 461 } 462 463 if (obj != NULL) { 464 ++obj->dl_refcount; 465 if (*old_obj_tail != NULL) { /* We loaded something new. */ 466 assert(*old_obj_tail == obj); 467 468 /* FIXME - Clean up properly after an error. */ 469 if (_rtld_load_needed_objects(obj) == -1) { 470 --obj->dl_refcount; 471 obj = NULL; 472 } else if (_rtld_relocate_objects(obj, mode == RTLD_NOW) == -1) { 473 --obj->dl_refcount; 474 obj = NULL; 475 } else { 476 _rtld_call_init_functions(obj); 477 } 478 } 479 } 480 481 _rtld_debug.r_state = RT_CONSISTENT; 482 _rtld_debug_state(); 483 484 return obj; 485 } 486 487 void * 488 _rtld_dlsym( 489 void *handle, 490 const char *name) 491 { 492 const Obj_Entry *obj = _rtld_dlcheck(handle); 493 const Elf_Sym *def; 494 const Obj_Entry *defobj; 495 496 if (obj == NULL) 497 return NULL; 498 499 /* 500 * FIXME - This isn't correct. The search should include the whole 501 * DAG rooted at the given object. 502 */ 503 def = _rtld_find_symdef(_rtld_objlist, 0, name, obj, &defobj, false); 504 if (def != NULL) 505 return defobj->relocbase + def->st_value; 506 507 _rtld_error("Undefined symbol \"%s\"", name); 508 return NULL; 509 } 510 511 /* 512 * Error reporting function. Use it like printf. If formats the message 513 * into a buffer, and sets things up so that the next call to dlerror() 514 * will return the message. 515 */ 516 void 517 _rtld_error( 518 const char *fmt, ...) 519 { 520 static char buf[512]; 521 va_list ap; 522 523 va_start(ap, fmt); 524 xvsnprintf(buf, sizeof buf, fmt, ap); 525 error_message = buf; 526 va_end(ap); 527 } 528 529 void 530 _rtld_debug_state( 531 void) 532 { 533 /* do nothing */ 534 } 535 536 void 537 _rtld_linkmap_add( 538 Obj_Entry *obj) 539 { 540 struct link_map *l = &obj->linkmap; 541 struct link_map *prev; 542 543 obj->linkmap.l_name = obj->path; 544 obj->linkmap.l_addr = obj->mapbase; 545 obj->linkmap.l_ld = obj->dynamic; 546 547 if (_rtld_debug.r_map == NULL) { 548 _rtld_debug.r_map = l; 549 return; 550 } 551 552 for (prev = _rtld_debug.r_map; prev->l_next != NULL; prev = prev->l_next) 553 ; 554 l->l_prev = prev; 555 prev->l_next = l; 556 l->l_next = NULL; 557 } 558 559 void 560 _rtld_linkmap_delete( 561 Obj_Entry *obj) 562 { 563 struct link_map *l = &obj->linkmap; 564 565 if (l->l_prev == NULL) { 566 if ((_rtld_debug.r_map = l->l_next) != NULL) 567 l->l_next->l_prev = NULL; 568 return; 569 } 570 571 if ((l->l_prev->l_next = l->l_next) != NULL) 572 l->l_next->l_prev = l->l_prev; 573 } 574 575