rtld.c revision 48543
1/*- 2 * Copyright 1996, 1997, 1998, 1999 John D. Polstra. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 * $Id: rtld.c,v 1.25 1999/06/25 04:50:06 jdp Exp $ 26 */ 27 28/* 29 * Dynamic linker for ELF. 30 * 31 * John Polstra <jdp@polstra.com>. 32 */ 33 34#ifndef __GNUC__ 35#error "GCC is needed to compile this file" 36#endif 37 38#include <sys/param.h> 39#include <sys/mman.h> 40 41#include <dlfcn.h> 42#include <err.h> 43#include <errno.h> 44#include <fcntl.h> 45#include <stdarg.h> 46#include <stdio.h> 47#include <stdlib.h> 48#include <string.h> 49#include <unistd.h> 50 51#include "debug.h" 52#include "rtld.h" 53 54/* 55 * Debugging support. 56 */ 57 58#define assert(cond) ((cond) ? (void) 0 :\ 59 (msg("oops: " __XSTRING(__LINE__) "\n"), abort())) 60#define msg(s) (write(1, s, strlen(s))) 61#define trace() msg("trace: " __XSTRING(__LINE__) "\n"); 62 63#define END_SYM "end" 64 65/* Types. */ 66typedef void (*func_ptr_type)(); 67 68/* 69 * Function declarations. 70 */ 71static const char *basename(const char *); 72static void call_fini_functions(Obj_Entry *); 73static void call_init_functions(Obj_Entry *); 74static void die(void); 75static void digest_dynamic(Obj_Entry *); 76static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t); 77static Obj_Entry *dlcheck(void *); 78static char *find_library(const char *, const Obj_Entry *); 79static const char *gethints(void); 80static void init_rtld(caddr_t); 81static bool is_exported(const Elf_Sym *); 82static void linkmap_add(Obj_Entry *); 83static void linkmap_delete(Obj_Entry *); 84static int load_needed_objects(Obj_Entry *); 85static int load_preload_objects(void); 86static Obj_Entry *load_object(char *); 87static Obj_Entry *obj_from_addr(const void *); 88static int relocate_objects(Obj_Entry *, bool); 89static void rtld_exit(void); 90static char *search_library_path(const char *, const char *); 91static void set_program_var(const char *, const void *); 92static void unref_object_dag(Obj_Entry *); 93static void trace_loaded_objects(Obj_Entry *obj); 94 95void r_debug_state(void); 96void xprintf(const char *, ...); 97 98/* 99 * Data declarations. 100 */ 101static char *error_message; /* Message for dlerror(), or NULL */ 102struct r_debug r_debug; /* for GDB; */ 103static bool trust; /* False for setuid and setgid programs */ 104static char *ld_bind_now; /* Environment variable for immediate binding */ 105static char *ld_debug; /* Environment variable for debugging */ 106static char *ld_library_path; /* Environment variable for search path */ 107static char *ld_preload; /* Environment variable for libraries to 108 load first */ 109static char *ld_tracing; /* Called from ldd to print libs */ 110static Obj_Entry **main_tail; /* Value of obj_tail after loading main and 111 its needed shared libraries */ 112static Obj_Entry *obj_list; /* Head of linked list of shared objects */ 113static Obj_Entry **obj_tail; /* Link field of last object in list */ 114static Obj_Entry *obj_main; /* The main program shared object */ 115static Obj_Entry obj_rtld; /* The dynamic linker shared object */ 116 117static Elf_Sym sym_zero; /* For resolving undefined weak refs. */ 118 119#define GDB_STATE(s) r_debug.r_state = s; r_debug_state(); 120 121extern Elf_Dyn _DYNAMIC; 122#pragma weak _DYNAMIC 123 124/* 125 * These are the functions the dynamic linker exports to application 126 * programs. They are the only symbols the dynamic linker is willing 127 * to export from itself. 128 */ 129static func_ptr_type exports[] = { 130 (func_ptr_type) &_rtld_error, 131 (func_ptr_type) &dlclose, 132 (func_ptr_type) &dlerror, 133 (func_ptr_type) &dlopen, 134 (func_ptr_type) &dlsym, 135 (func_ptr_type) &dladdr, 136 NULL 137}; 138 139/* 140 * Global declarations normally provided by crt1. The dynamic linker is 141 * not build with crt1, so we have to provide them ourselves. 142 */ 143char *__progname; 144char **environ; 145 146/* 147 * Main entry point for dynamic linking. The first argument is the 148 * stack pointer. The stack is expected to be laid out as described 149 * in the SVR4 ABI specification, Intel 386 Processor Supplement. 150 * Specifically, the stack pointer points to a word containing 151 * ARGC. Following that in the stack is a null-terminated sequence 152 * of pointers to argument strings. Then comes a null-terminated 153 * sequence of pointers to environment strings. Finally, there is a 154 * sequence of "auxiliary vector" entries. 155 * 156 * The second argument points to a place to store the dynamic linker's 157 * exit procedure pointer and the third to a place to store the main 158 * program's object. 159 * 160 * The return value is the main program's entry point. 161 */ 162func_ptr_type 163_rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) 164{ 165 Elf_Auxinfo *aux_info[AT_COUNT]; 166 int i; 167 int argc; 168 char **argv; 169 char **env; 170 Elf_Auxinfo *aux; 171 Elf_Auxinfo *auxp; 172 173 /* 174 * On entry, the dynamic linker itself has not been relocated yet. 175 * Be very careful not to reference any global data until after 176 * init_rtld has returned. It is OK to reference file-scope statics 177 * and string constants, and to call static and global functions. 178 */ 179 180 /* Find the auxiliary vector on the stack. */ 181 argc = *sp++; 182 argv = (char **) sp; 183 sp += argc + 1; /* Skip over arguments and NULL terminator */ 184 env = (char **) sp; 185 while (*sp++ != 0) /* Skip over environment, and NULL terminator */ 186 ; 187 aux = (Elf_Auxinfo *) sp; 188 189 /* Digest the auxiliary vector. */ 190 for (i = 0; i < AT_COUNT; i++) 191 aux_info[i] = NULL; 192 for (auxp = aux; auxp->a_type != AT_NULL; auxp++) { 193 if (auxp->a_type < AT_COUNT) 194 aux_info[auxp->a_type] = auxp; 195 } 196 197 /* Initialize and relocate ourselves. */ 198 assert(aux_info[AT_BASE] != NULL); 199 init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr); 200 201 __progname = obj_rtld.path; 202 environ = env; 203 204 trust = geteuid() == getuid() && getegid() == getgid(); 205 206 ld_bind_now = getenv("LD_BIND_NOW"); 207 if (trust) { 208 ld_debug = getenv("LD_DEBUG"); 209 ld_library_path = getenv("LD_LIBRARY_PATH"); 210 ld_preload = getenv("LD_PRELOAD"); 211 } 212 ld_tracing = getenv("LD_TRACE_LOADED_OBJECTS"); 213 214 if (ld_debug != NULL && *ld_debug != '\0') 215 debug = 1; 216 dbg("%s is initialized, base address = %p", __progname, 217 (caddr_t) aux_info[AT_BASE]->a_un.a_ptr); 218 dbg("RTLD dynamic = %p", obj_rtld.dynamic); 219 dbg("RTLD pltgot = %p", obj_rtld.pltgot); 220 221 /* 222 * Load the main program, or process its program header if it is 223 * already loaded. 224 */ 225 if (aux_info[AT_EXECFD] != NULL) { /* Load the main program. */ 226 int fd = aux_info[AT_EXECFD]->a_un.a_val; 227 dbg("loading main program"); 228 obj_main = map_object(fd); 229 close(fd); 230 if (obj_main == NULL) 231 die(); 232 } else { /* Main program already loaded. */ 233 const Elf_Phdr *phdr; 234 int phnum; 235 caddr_t entry; 236 237 dbg("processing main program's program header"); 238 assert(aux_info[AT_PHDR] != NULL); 239 phdr = (const Elf_Phdr *) aux_info[AT_PHDR]->a_un.a_ptr; 240 assert(aux_info[AT_PHNUM] != NULL); 241 phnum = aux_info[AT_PHNUM]->a_un.a_val; 242 assert(aux_info[AT_PHENT] != NULL); 243 assert(aux_info[AT_PHENT]->a_un.a_val == sizeof(Elf_Phdr)); 244 assert(aux_info[AT_ENTRY] != NULL); 245 entry = (caddr_t) aux_info[AT_ENTRY]->a_un.a_ptr; 246 obj_main = digest_phdr(phdr, phnum, entry); 247 } 248 249 obj_main->path = xstrdup(argv[0] ? argv[0] : "(null)"); 250 obj_main->mainprog = true; 251 digest_dynamic(obj_main); 252 253 linkmap_add(obj_main); 254 linkmap_add(&obj_rtld); 255 256 /* Link the main program into the list of objects. */ 257 *obj_tail = obj_main; 258 obj_tail = &obj_main->next; 259 obj_main->refcount++; 260 261 /* Initialize a fake symbol for resolving undefined weak references. */ 262 sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); 263 sym_zero.st_shndx = SHN_ABS; 264 265 dbg("loading LD_PRELOAD libraries"); 266 if (load_preload_objects() == -1) 267 die(); 268 269 dbg("loading needed objects"); 270 if (load_needed_objects(obj_main) == -1) 271 die(); 272 main_tail = obj_tail; 273 274 if (ld_tracing) { /* We're done */ 275 trace_loaded_objects(obj_main); 276 exit(0); 277 } 278 279 dbg("relocating objects"); 280 if (relocate_objects(obj_main, 281 ld_bind_now != NULL && *ld_bind_now != '\0') == -1) 282 die(); 283 284 dbg("doing copy relocations"); 285 if (do_copy_relocations(obj_main) == -1) 286 die(); 287 288 dbg("initializing key program variables"); 289 set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : ""); 290 set_program_var("environ", env); 291 292 r_debug_state(); /* say hello to gdb! */ 293 294 dbg("calling _init functions"); 295 call_init_functions(obj_main->next); 296 297 dbg("transferring control to program entry point = %p", obj_main->entry); 298 299 /* Return the exit procedure and the program entry point. */ 300 *exit_proc = rtld_exit; 301 *objp = obj_main; 302 return (func_ptr_type) obj_main->entry; 303} 304 305Elf_Addr 306_rtld_bind(const Obj_Entry *obj, Elf_Word reloff) 307{ 308 const Elf_Rel *rel; 309 const Elf_Sym *def; 310 const Obj_Entry *defobj; 311 Elf_Addr *where; 312 Elf_Addr target; 313 314 if (obj->pltrel) 315 rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff); 316 else 317 rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff); 318 319 where = (Elf_Addr *) (obj->relocbase + rel->r_offset); 320 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true); 321 if (def == NULL) 322 die(); 323 324 target = (Elf_Addr)(defobj->relocbase + def->st_value); 325 326 dbg("\"%s\" in \"%s\" ==> %p in \"%s\"", 327 defobj->strtab + def->st_name, basename(obj->path), 328 (void *)target, basename(defobj->path)); 329 330 reloc_jmpslot(where, target); 331 return target; 332} 333 334/* 335 * Error reporting function. Use it like printf. If formats the message 336 * into a buffer, and sets things up so that the next call to dlerror() 337 * will return the message. 338 */ 339void 340_rtld_error(const char *fmt, ...) 341{ 342 static char buf[512]; 343 va_list ap; 344 345 va_start(ap, fmt); 346 vsnprintf(buf, sizeof buf, fmt, ap); 347 error_message = buf; 348 va_end(ap); 349} 350 351static const char * 352basename(const char *name) 353{ 354 const char *p = strrchr(name, '/'); 355 return p != NULL ? p + 1 : name; 356} 357 358static void 359call_fini_functions(Obj_Entry *first) 360{ 361 Obj_Entry *obj; 362 363 for (obj = first; obj != NULL; obj = obj->next) 364 if (obj->fini != NULL) 365 (*obj->fini)(); 366} 367 368static void 369call_init_functions(Obj_Entry *first) 370{ 371 if (first != NULL) { 372 call_init_functions(first->next); 373 if (first->init != NULL) 374 (*first->init)(); 375 } 376} 377 378static void 379die(void) 380{ 381 const char *msg = dlerror(); 382 383 if (msg == NULL) 384 msg = "Fatal error"; 385 errx(1, "%s", msg); 386} 387 388/* 389 * Process a shared object's DYNAMIC section, and save the important 390 * information in its Obj_Entry structure. 391 */ 392static void 393digest_dynamic(Obj_Entry *obj) 394{ 395 const Elf_Dyn *dynp; 396 Needed_Entry **needed_tail = &obj->needed; 397 const Elf_Dyn *dyn_rpath = NULL; 398 int plttype = DT_REL; 399 400 for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; dynp++) { 401 switch (dynp->d_tag) { 402 403 case DT_REL: 404 obj->rel = (const Elf_Rel *) (obj->relocbase + dynp->d_un.d_ptr); 405 break; 406 407 case DT_RELSZ: 408 obj->relsize = dynp->d_un.d_val; 409 break; 410 411 case DT_RELENT: 412 assert(dynp->d_un.d_val == sizeof(Elf_Rel)); 413 break; 414 415 case DT_JMPREL: 416 obj->pltrel = (const Elf_Rel *) 417 (obj->relocbase + dynp->d_un.d_ptr); 418 break; 419 420 case DT_PLTRELSZ: 421 obj->pltrelsize = dynp->d_un.d_val; 422 break; 423 424 case DT_RELA: 425 obj->rela = (const Elf_Rela *) (obj->relocbase + dynp->d_un.d_ptr); 426 break; 427 428 case DT_RELASZ: 429 obj->relasize = dynp->d_un.d_val; 430 break; 431 432 case DT_RELAENT: 433 assert(dynp->d_un.d_val == sizeof(Elf_Rela)); 434 break; 435 436 case DT_PLTREL: 437 plttype = dynp->d_un.d_val; 438 assert(dynp->d_un.d_val == DT_REL || plttype == DT_RELA); 439 break; 440 441 case DT_SYMTAB: 442 obj->symtab = (const Elf_Sym *) 443 (obj->relocbase + dynp->d_un.d_ptr); 444 break; 445 446 case DT_SYMENT: 447 assert(dynp->d_un.d_val == sizeof(Elf_Sym)); 448 break; 449 450 case DT_STRTAB: 451 obj->strtab = (const char *) (obj->relocbase + dynp->d_un.d_ptr); 452 break; 453 454 case DT_STRSZ: 455 obj->strsize = dynp->d_un.d_val; 456 break; 457 458 case DT_HASH: 459 { 460 const Elf_Addr *hashtab = (const Elf_Addr *) 461 (obj->relocbase + dynp->d_un.d_ptr); 462 obj->nbuckets = hashtab[0]; 463 obj->nchains = hashtab[1]; 464 obj->buckets = hashtab + 2; 465 obj->chains = obj->buckets + obj->nbuckets; 466 } 467 break; 468 469 case DT_NEEDED: 470 if (!obj->rtld) { 471 Needed_Entry *nep = NEW(Needed_Entry); 472 nep->name = dynp->d_un.d_val; 473 nep->obj = NULL; 474 nep->next = NULL; 475 476 *needed_tail = nep; 477 needed_tail = &nep->next; 478 } 479 break; 480 481 case DT_PLTGOT: 482 obj->pltgot = (Elf_Addr *) (obj->relocbase + dynp->d_un.d_ptr); 483 break; 484 485 case DT_TEXTREL: 486 obj->textrel = true; 487 break; 488 489 case DT_SYMBOLIC: 490 obj->symbolic = true; 491 break; 492 493 case DT_RPATH: 494 /* 495 * We have to wait until later to process this, because we 496 * might not have gotten the address of the string table yet. 497 */ 498 dyn_rpath = dynp; 499 break; 500 501 case DT_SONAME: 502 /* Not used by the dynamic linker. */ 503 break; 504 505 case DT_INIT: 506 obj->init = (void (*)(void)) (obj->relocbase + dynp->d_un.d_ptr); 507 break; 508 509 case DT_FINI: 510 obj->fini = (void (*)(void)) (obj->relocbase + dynp->d_un.d_ptr); 511 break; 512 513 case DT_DEBUG: 514 /* XXX - not implemented yet */ 515 dbg("Filling in DT_DEBUG entry"); 516 ((Elf_Dyn*)dynp)->d_un.d_ptr = (Elf_Addr) &r_debug; 517 break; 518 519 default: 520 xprintf("Ignored d_tag %d\n",dynp->d_tag); 521 break; 522 } 523 } 524 525 obj->traced = false; 526 527 if (plttype == DT_RELA) { 528 obj->pltrela = (const Elf_Rela *) obj->pltrel; 529 obj->pltrel = NULL; 530 obj->pltrelasize = obj->pltrelsize; 531 obj->pltrelsize = 0; 532 } 533 534 if (dyn_rpath != NULL) 535 obj->rpath = obj->strtab + dyn_rpath->d_un.d_val; 536} 537 538/* 539 * Process a shared object's program header. This is used only for the 540 * main program, when the kernel has already loaded the main program 541 * into memory before calling the dynamic linker. It creates and 542 * returns an Obj_Entry structure. 543 */ 544static Obj_Entry * 545digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry) 546{ 547 Obj_Entry *obj = CNEW(Obj_Entry); 548 const Elf_Phdr *phlimit = phdr + phnum; 549 const Elf_Phdr *ph; 550 int nsegs = 0; 551 552 for (ph = phdr; ph < phlimit; ph++) { 553 switch (ph->p_type) { 554 555 case PT_PHDR: 556 assert((const Elf_Phdr *) ph->p_vaddr == phdr); 557 obj->phdr = (const Elf_Phdr *) ph->p_vaddr; 558 obj->phsize = ph->p_memsz; 559 break; 560 561 case PT_LOAD: 562 assert(nsegs < 2); 563 if (nsegs == 0) { /* First load segment */ 564 obj->vaddrbase = trunc_page(ph->p_vaddr); 565 obj->mapbase = (caddr_t) obj->vaddrbase; 566 obj->relocbase = obj->mapbase - obj->vaddrbase; 567 obj->textsize = round_page(ph->p_vaddr + ph->p_memsz) - 568 obj->vaddrbase; 569 } else { /* Last load segment */ 570 obj->mapsize = round_page(ph->p_vaddr + ph->p_memsz) - 571 obj->vaddrbase; 572 } 573 nsegs++; 574 break; 575 576 case PT_DYNAMIC: 577 obj->dynamic = (const Elf_Dyn *) ph->p_vaddr; 578 break; 579 } 580 } 581 assert(nsegs == 2); 582 583 obj->entry = entry; 584 return obj; 585} 586 587static Obj_Entry * 588dlcheck(void *handle) 589{ 590 Obj_Entry *obj; 591 592 for (obj = obj_list; obj != NULL; obj = obj->next) 593 if (obj == (Obj_Entry *) handle) 594 break; 595 596 if (obj == NULL || obj->dl_refcount == 0) { 597 _rtld_error("Invalid shared object handle %p", handle); 598 return NULL; 599 } 600 return obj; 601} 602 603/* 604 * Hash function for symbol table lookup. Don't even think about changing 605 * this. It is specified by the System V ABI. 606 */ 607unsigned long 608elf_hash(const char *name) 609{ 610 const unsigned char *p = (const unsigned char *) name; 611 unsigned long h = 0; 612 unsigned long g; 613 614 while (*p != '\0') { 615 h = (h << 4) + *p++; 616 if ((g = h & 0xf0000000) != 0) 617 h ^= g >> 24; 618 h &= ~g; 619 } 620 return h; 621} 622 623/* 624 * Find the library with the given name, and return its full pathname. 625 * The returned string is dynamically allocated. Generates an error 626 * message and returns NULL if the library cannot be found. 627 * 628 * If the second argument is non-NULL, then it refers to an already- 629 * loaded shared object, whose library search path will be searched. 630 * 631 * The search order is: 632 * LD_LIBRARY_PATH 633 * ldconfig hints 634 * rpath in the referencing file 635 * /usr/lib 636 */ 637static char * 638find_library(const char *name, const Obj_Entry *refobj) 639{ 640 char *pathname; 641 642 if (strchr(name, '/') != NULL) { /* Hard coded pathname */ 643 if (name[0] != '/' && !trust) { 644 _rtld_error("Absolute pathname required for shared object \"%s\"", 645 name); 646 return NULL; 647 } 648 return xstrdup(name); 649 } 650 651 dbg(" Searching for \"%s\"", name); 652 653 if ((refobj != NULL && 654 (pathname = search_library_path(name, refobj->rpath)) != NULL) || 655 (pathname = search_library_path(name, ld_library_path)) != NULL || 656 (pathname = search_library_path(name, gethints())) != NULL || 657 (pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL) 658 return pathname; 659 660 _rtld_error("Shared object \"%s\" not found", name); 661 return NULL; 662} 663 664/* 665 * Given a symbol number in a referencing object, find the corresponding 666 * definition of the symbol. Returns a pointer to the symbol, or NULL if 667 * no definition was found. Returns a pointer to the Obj_Entry of the 668 * defining object via the reference parameter DEFOBJ_OUT. 669 */ 670const Elf_Sym * 671find_symdef(unsigned long symnum, const Obj_Entry *refobj, 672 const Obj_Entry **defobj_out, bool in_plt) 673{ 674 const Elf_Sym *ref; 675 const Elf_Sym *strongdef; 676 const Elf_Sym *weakdef; 677 const Obj_Entry *obj; 678 const Obj_Entry *strongobj; 679 const Obj_Entry *weakobj; 680 const char *name; 681 unsigned long hash; 682 683 ref = refobj->symtab + symnum; 684 name = refobj->strtab + ref->st_name; 685 hash = elf_hash(name); 686 687 if (refobj->symbolic) { /* Look first in the referencing object */ 688 const Elf_Sym *def = symlook_obj(name, hash, refobj, in_plt); 689 if (def != NULL) { 690 *defobj_out = refobj; 691 return def; 692 } 693 } 694 695 /* 696 * Look in all loaded objects. Skip the referencing object, if 697 * we have already searched it. We keep track of the first weak 698 * definition and the first strong definition we encounter. If 699 * we find a strong definition we stop searching, because there 700 * won't be anything better than that. 701 */ 702 strongdef = weakdef = NULL; 703 strongobj = weakobj = NULL; 704 for (obj = obj_list; obj != NULL; obj = obj->next) { 705 if (obj != refobj || !refobj->symbolic) { 706 const Elf_Sym *def = symlook_obj(name, hash, obj, in_plt); 707 if (def != NULL) { 708 if (ELF_ST_BIND(def->st_info) == STB_WEAK) { 709 if (weakdef == NULL) { 710 weakdef = def; 711 weakobj = obj; 712 } 713 } else { 714 strongdef = def; 715 strongobj = obj; 716 break; /* We are done. */ 717 } 718 } 719 } 720 } 721 722 /* 723 * If we still don't have a strong definition, search the dynamic 724 * linker itself, and possibly resolve the symbol from there. 725 * This is how the application links to dynamic linker services 726 * such as dlopen. Only the values listed in the "exports" array 727 * can be resolved from the dynamic linker. 728 */ 729 if (strongdef == NULL) { 730 const Elf_Sym *def = symlook_obj(name, hash, &obj_rtld, in_plt); 731 if (def != NULL && is_exported(def)) { 732 if (ELF_ST_BIND(def->st_info) == STB_WEAK) { 733 if (weakdef == NULL) { 734 weakdef = def; 735 weakobj = &obj_rtld; 736 } 737 } else { 738 strongdef = def; 739 strongobj = &obj_rtld; 740 } 741 } 742 } 743 744 if (strongdef != NULL) { 745 *defobj_out = strongobj; 746 return strongdef; 747 } 748 if (weakdef != NULL) { 749 *defobj_out = weakobj; 750 return weakdef; 751 } 752 753 if (ELF_ST_BIND(ref->st_info) == STB_WEAK) { 754 *defobj_out = obj_main; 755 return &sym_zero; 756 } 757 758 _rtld_error("%s: Undefined symbol \"%s\"", refobj->path, name); 759 return NULL; 760} 761 762/* 763 * Return the search path from the ldconfig hints file, reading it if 764 * necessary. Returns NULL if there are problems with the hints file, 765 * or if the search path there is empty. 766 */ 767static const char * 768gethints(void) 769{ 770 static char *hints; 771 772 if (hints == NULL) { 773 int fd; 774 struct elfhints_hdr hdr; 775 char *p; 776 777 /* Keep from trying again in case the hints file is bad. */ 778 hints = ""; 779 780 if ((fd = open(_PATH_ELF_HINTS, O_RDONLY)) == -1) 781 return NULL; 782 if (read(fd, &hdr, sizeof hdr) != sizeof hdr || 783 hdr.magic != ELFHINTS_MAGIC || 784 hdr.version != 1) { 785 close(fd); 786 return NULL; 787 } 788 p = xmalloc(hdr.dirlistlen + 1); 789 if (lseek(fd, hdr.strtab + hdr.dirlist, SEEK_SET) == -1 || 790 read(fd, p, hdr.dirlistlen + 1) != hdr.dirlistlen + 1) { 791 free(p); 792 close(fd); 793 return NULL; 794 } 795 hints = p; 796 close(fd); 797 } 798 return hints[0] != '\0' ? hints : NULL; 799} 800 801/* 802 * Initialize the dynamic linker. The argument is the address at which 803 * the dynamic linker has been mapped into memory. The primary task of 804 * this function is to relocate the dynamic linker. 805 */ 806static void 807init_rtld(caddr_t mapbase) 808{ 809 /* 810 * Conjure up an Obj_Entry structure for the dynamic linker. 811 * 812 * The "path" member is supposed to be dynamically-allocated, but we 813 * aren't yet initialized sufficiently to do that. Below we will 814 * replace the static version with a dynamically-allocated copy. 815 */ 816 obj_rtld.path = "/usr/libexec/ld-elf.so.1"; 817 obj_rtld.rtld = true; 818 obj_rtld.mapbase = mapbase; 819#ifdef PIC 820 obj_rtld.relocbase = mapbase; 821#endif 822 if (&_DYNAMIC != 0) { 823 obj_rtld.dynamic = rtld_dynamic(&obj_rtld); 824 digest_dynamic(&obj_rtld); 825 assert(obj_rtld.needed == NULL); 826 assert(!obj_rtld.textrel); 827 828 /* 829 * Temporarily put the dynamic linker entry into the object list, so 830 * that symbols can be found. 831 */ 832 obj_list = &obj_rtld; 833 obj_tail = &obj_rtld.next; 834 835 relocate_objects(&obj_rtld, true); 836 } 837 838 /* Make the object list empty again. */ 839 obj_list = NULL; 840 obj_tail = &obj_list; 841 842 /* Replace the path with a dynamically allocated copy. */ 843 obj_rtld.path = xstrdup(obj_rtld.path); 844 845 r_debug.r_brk = r_debug_state; 846 r_debug.r_state = RT_CONSISTENT; 847} 848 849static bool 850is_exported(const Elf_Sym *def) 851{ 852 func_ptr_type value; 853 const func_ptr_type *p; 854 855 value = (func_ptr_type)(obj_rtld.relocbase + def->st_value); 856 for (p = exports; *p != NULL; p++) 857 if (*p == value) 858 return true; 859 return false; 860} 861 862/* 863 * Given a shared object, traverse its list of needed objects, and load 864 * each of them. Returns 0 on success. Generates an error message and 865 * returns -1 on failure. 866 */ 867static int 868load_needed_objects(Obj_Entry *first) 869{ 870 Obj_Entry *obj; 871 872 for (obj = first; obj != NULL; obj = obj->next) { 873 Needed_Entry *needed; 874 875 for (needed = obj->needed; needed != NULL; needed = needed->next) { 876 const char *name = obj->strtab + needed->name; 877 char *path = find_library(name, obj); 878 879 needed->obj = NULL; 880 if (path == NULL && !ld_tracing) 881 return -1; 882 883 if (path) { 884 needed->obj = load_object(path); 885 if (needed->obj == NULL && !ld_tracing) 886 return -1; /* XXX - cleanup */ 887 } 888 } 889 } 890 891 return 0; 892} 893 894static int 895load_preload_objects(void) 896{ 897 char *p = ld_preload; 898 899 if (p == NULL) 900 return NULL; 901 902 p += strspn(p, ":;"); 903 while (*p != '\0') { 904 size_t len = strcspn(p, ":;"); 905 char *path; 906 char savech; 907 908 savech = p[len]; 909 p[len] = '\0'; 910 if ((path = find_library(p, NULL)) == NULL) 911 return -1; 912 if (load_object(path) == NULL) 913 return -1; /* XXX - cleanup */ 914 p[len] = savech; 915 p += len; 916 p += strspn(p, ":;"); 917 } 918 return 0; 919} 920 921/* 922 * Load a shared object into memory, if it is not already loaded. The 923 * argument must be a string allocated on the heap. This function assumes 924 * responsibility for freeing it when necessary. 925 * 926 * Returns a pointer to the Obj_Entry for the object. Returns NULL 927 * on failure. 928 */ 929static Obj_Entry * 930load_object(char *path) 931{ 932 Obj_Entry *obj; 933 934 for (obj = obj_list->next; obj != NULL; obj = obj->next) 935 if (strcmp(obj->path, path) == 0) 936 break; 937 938 if (obj == NULL) { /* First use of this object, so we must map it in */ 939 int fd; 940 941 if ((fd = open(path, O_RDONLY)) == -1) { 942 _rtld_error("Cannot open \"%s\"", path); 943 return NULL; 944 } 945 obj = map_object(fd); 946 close(fd); 947 if (obj == NULL) { 948 free(path); 949 return NULL; 950 } 951 952 obj->path = path; 953 digest_dynamic(obj); 954 955 *obj_tail = obj; 956 obj_tail = &obj->next; 957 linkmap_add(obj); /* for GDB */ 958 959 dbg(" %p .. %p: %s", obj->mapbase, 960 obj->mapbase + obj->mapsize - 1, obj->path); 961 if (obj->textrel) 962 dbg(" WARNING: %s has impure text", obj->path); 963 } else 964 free(path); 965 966 obj->refcount++; 967 return obj; 968} 969 970static Obj_Entry * 971obj_from_addr(const void *addr) 972{ 973 unsigned long endhash; 974 Obj_Entry *obj; 975 976 endhash = elf_hash(END_SYM); 977 for (obj = obj_list; obj != NULL; obj = obj->next) { 978 const Elf_Sym *endsym; 979 980 if (addr < (void *) obj->mapbase) 981 continue; 982 if ((endsym = symlook_obj(END_SYM, endhash, obj, true)) == NULL) 983 continue; /* No "end" symbol?! */ 984 if (addr < (void *) (obj->relocbase + endsym->st_value)) 985 return obj; 986 } 987 return NULL; 988} 989 990/* 991 * Relocate newly-loaded shared objects. The argument is a pointer to 992 * the Obj_Entry for the first such object. All objects from the first 993 * to the end of the list of objects are relocated. Returns 0 on success, 994 * or -1 on failure. 995 */ 996static int 997relocate_objects(Obj_Entry *first, bool bind_now) 998{ 999 Obj_Entry *obj; 1000 1001 for (obj = first; obj != NULL; obj = obj->next) { 1002 if (obj != &obj_rtld) 1003 dbg("relocating \"%s\"", obj->path); 1004 if (obj->nbuckets == 0 || obj->nchains == 0 || obj->buckets == NULL || 1005 obj->symtab == NULL || obj->strtab == NULL) { 1006 _rtld_error("%s: Shared object has no run-time symbol table", 1007 obj->path); 1008 return -1; 1009 } 1010 1011 if (obj->textrel) { 1012 /* There are relocations to the write-protected text segment. */ 1013 if (mprotect(obj->mapbase, obj->textsize, 1014 PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { 1015 _rtld_error("%s: Cannot write-enable text segment: %s", 1016 obj->path, strerror(errno)); 1017 return -1; 1018 } 1019 } 1020 1021 /* Process the non-PLT relocations. */ 1022 if (reloc_non_plt(obj, &obj_rtld)) 1023 return -1; 1024 1025 if (obj->textrel) { /* Re-protected the text segment. */ 1026 if (mprotect(obj->mapbase, obj->textsize, 1027 PROT_READ|PROT_EXEC) == -1) { 1028 _rtld_error("%s: Cannot write-protect text segment: %s", 1029 obj->path, strerror(errno)); 1030 return -1; 1031 } 1032 } 1033 1034 /* Process the PLT relocations. */ 1035 if (reloc_plt(obj, bind_now)) 1036 return -1; 1037 1038 /* 1039 * Set up the magic number and version in the Obj_Entry. These 1040 * were checked in the crt1.o from the original ElfKit, so we 1041 * set them for backward compatibility. 1042 */ 1043 obj->magic = RTLD_MAGIC; 1044 obj->version = RTLD_VERSION; 1045 1046 /* Set the special PLT or GOT entries. */ 1047 init_pltgot(obj); 1048 } 1049 1050 return 0; 1051} 1052 1053/* 1054 * Cleanup procedure. It will be called (by the atexit mechanism) just 1055 * before the process exits. 1056 */ 1057static void 1058rtld_exit(void) 1059{ 1060 dbg("rtld_exit()"); 1061 call_fini_functions(obj_list->next); 1062} 1063 1064static char * 1065search_library_path(const char *name, const char *path) 1066{ 1067 size_t namelen = strlen(name); 1068 const char *p = path; 1069 1070 if (p == NULL) 1071 return NULL; 1072 1073 p += strspn(p, ":;"); 1074 while (*p != '\0') { 1075 size_t len = strcspn(p, ":;"); 1076 1077 if (*p == '/' || trust) { 1078 char *pathname; 1079 const char *dir = p; 1080 size_t dirlen = len; 1081 1082 pathname = xmalloc(dirlen + 1 + namelen + 1); 1083 strncpy(pathname, dir, dirlen); 1084 pathname[dirlen] = '/'; 1085 strcpy(pathname + dirlen + 1, name); 1086 1087 dbg(" Trying \"%s\"", pathname); 1088 if (access(pathname, F_OK) == 0) /* We found it */ 1089 return pathname; 1090 1091 free(pathname); 1092 } 1093 p += len; 1094 p += strspn(p, ":;"); 1095 } 1096 1097 return NULL; 1098} 1099 1100int 1101dlclose(void *handle) 1102{ 1103 Obj_Entry *root = dlcheck(handle); 1104 1105 if (root == NULL) 1106 return -1; 1107 1108 GDB_STATE(RT_DELETE); 1109 1110 root->dl_refcount--; 1111 unref_object_dag(root); 1112 if (root->refcount == 0) { /* We are finished with some objects. */ 1113 Obj_Entry *obj; 1114 Obj_Entry **linkp; 1115 1116 /* Finalize objects that are about to be unmapped. */ 1117 for (obj = obj_list->next; obj != NULL; obj = obj->next) 1118 if (obj->refcount == 0 && obj->fini != NULL) 1119 (*obj->fini)(); 1120 1121 /* Unmap all objects that are no longer referenced. */ 1122 linkp = &obj_list->next; 1123 while ((obj = *linkp) != NULL) { 1124 if (obj->refcount == 0) { 1125 munmap(obj->mapbase, obj->mapsize); 1126 free(obj->path); 1127 while (obj->needed != NULL) { 1128 Needed_Entry *needed = obj->needed; 1129 obj->needed = needed->next; 1130 free(needed); 1131 } 1132 linkmap_delete(obj); 1133 *linkp = obj->next; 1134 free(obj); 1135 } else 1136 linkp = &obj->next; 1137 } 1138 obj_tail = linkp; 1139 } 1140 1141 GDB_STATE(RT_CONSISTENT); 1142 1143 return 0; 1144} 1145 1146const char * 1147dlerror(void) 1148{ 1149 char *msg = error_message; 1150 error_message = NULL; 1151 return msg; 1152} 1153 1154void * 1155dlopen(const char *name, int mode) 1156{ 1157 Obj_Entry **old_obj_tail = obj_tail; 1158 Obj_Entry *obj = NULL; 1159 1160 GDB_STATE(RT_ADD); 1161 1162 if (name == NULL) { 1163 obj = obj_main; 1164 obj->refcount++; 1165 } else { 1166 char *path = find_library(name, obj_main); 1167 if (path != NULL) 1168 obj = load_object(path); 1169 } 1170 1171 if (obj) { 1172 obj->dl_refcount++; 1173 if (*old_obj_tail != NULL) { /* We loaded something new. */ 1174 assert(*old_obj_tail == obj); 1175 1176 /* XXX - Clean up properly after an error. */ 1177 if (load_needed_objects(obj) == -1) { 1178 obj->dl_refcount--; 1179 obj = NULL; 1180 } else if (relocate_objects(obj, mode == RTLD_NOW) == -1) { 1181 obj->dl_refcount--; 1182 obj = NULL; 1183 } else 1184 call_init_functions(obj); 1185 } 1186 } 1187 1188 GDB_STATE(RT_CONSISTENT); 1189 1190 return obj; 1191} 1192 1193void * 1194dlsym(void *handle, const char *name) 1195{ 1196 const Obj_Entry *obj; 1197 unsigned long hash; 1198 const Elf_Sym *def; 1199 1200 hash = elf_hash(name); 1201 def = NULL; 1202 1203 if (handle == NULL || handle == RTLD_NEXT) { 1204 void *retaddr; 1205 1206 retaddr = __builtin_return_address(0); /* __GNUC__ only */ 1207 if ((obj = obj_from_addr(retaddr)) == NULL) { 1208 _rtld_error("Cannot determine caller's shared object"); 1209 return NULL; 1210 } 1211 if (handle == NULL) /* Just the caller's shared object. */ 1212 def = symlook_obj(name, hash, obj, true); 1213 else { /* All the shared objects after the caller's */ 1214 while ((obj = obj->next) != NULL) 1215 if ((def = symlook_obj(name, hash, obj, true)) != NULL) 1216 break; 1217 } 1218 } else { 1219 if ((obj = dlcheck(handle)) == NULL) 1220 return NULL; 1221 1222 if (obj->mainprog) { 1223 /* Search main program and all libraries loaded by it. */ 1224 for ( ; obj != *main_tail; obj = obj->next) 1225 if ((def = symlook_obj(name, hash, obj, true)) != NULL) 1226 break; 1227 } else { 1228 /* 1229 * XXX - This isn't correct. The search should include the whole 1230 * DAG rooted at the given object. 1231 */ 1232 def = symlook_obj(name, hash, obj, true); 1233 } 1234 } 1235 1236 if (def != NULL) 1237 return obj->relocbase + def->st_value; 1238 1239 _rtld_error("Undefined symbol \"%s\"", name); 1240 return NULL; 1241} 1242 1243int 1244dladdr(const void *addr, Dl_info *info) 1245{ 1246 const Obj_Entry *obj; 1247 const Elf_Sym *def; 1248 void *symbol_addr; 1249 unsigned long symoffset; 1250 1251 obj = obj_from_addr(addr); 1252 if (obj == NULL) { 1253 _rtld_error("No shared object contains address"); 1254 return 0; 1255 } 1256 info->dli_fname = obj->path; 1257 info->dli_fbase = obj->mapbase; 1258 info->dli_saddr = (void *)0; 1259 info->dli_sname = NULL; 1260 1261 /* 1262 * Walk the symbol list looking for the symbol whose address is 1263 * closest to the address sent in. 1264 */ 1265 for (symoffset = 0; symoffset < obj->nchains; symoffset++) { 1266 def = obj->symtab + symoffset; 1267 1268 /* 1269 * For skip the symbol if st_shndx is either SHN_UNDEF or 1270 * SHN_COMMON. 1271 */ 1272 if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON) 1273 continue; 1274 1275 /* 1276 * If the symbol is greater than the specified address, or if it 1277 * is further away from addr than the current nearest symbol, 1278 * then reject it. 1279 */ 1280 symbol_addr = obj->relocbase + def->st_value; 1281 if (symbol_addr > addr || symbol_addr < info->dli_saddr) 1282 continue; 1283 1284 /* Update our idea of the nearest symbol. */ 1285 info->dli_sname = obj->strtab + def->st_name; 1286 info->dli_saddr = symbol_addr; 1287 1288 /* Exact match? */ 1289 if (info->dli_saddr == addr) 1290 break; 1291 } 1292 return 1; 1293} 1294 1295static void 1296linkmap_add(Obj_Entry *obj) 1297{ 1298 struct link_map *l = &obj->linkmap; 1299 struct link_map *prev; 1300 1301 obj->linkmap.l_name = obj->path; 1302 obj->linkmap.l_addr = obj->mapbase; 1303 obj->linkmap.l_ld = obj->dynamic; 1304#ifdef __mips__ 1305 /* GDB needs load offset on MIPS to use the symbols */ 1306 obj->linkmap.l_offs = obj->relocbase; 1307#endif 1308 1309 if (r_debug.r_map == NULL) { 1310 r_debug.r_map = l; 1311 return; 1312 } 1313 1314 /* 1315 * Scan to the end of the list, but not past the entry for the 1316 * dynamic linker, which we want to keep at the very end. 1317 */ 1318 for (prev = r_debug.r_map; 1319 prev->l_next != NULL && prev->l_next != &obj_rtld.linkmap; 1320 prev = prev->l_next) 1321 ; 1322 1323 /* Link in the new entry. */ 1324 l->l_prev = prev; 1325 l->l_next = prev->l_next; 1326 if (l->l_next != NULL) 1327 l->l_next->l_prev = l; 1328 prev->l_next = l; 1329} 1330 1331static void 1332linkmap_delete(Obj_Entry *obj) 1333{ 1334 struct link_map *l = &obj->linkmap; 1335 1336 if (l->l_prev == NULL) { 1337 if ((r_debug.r_map = l->l_next) != NULL) 1338 l->l_next->l_prev = NULL; 1339 return; 1340 } 1341 1342 if ((l->l_prev->l_next = l->l_next) != NULL) 1343 l->l_next->l_prev = l->l_prev; 1344} 1345 1346/* 1347 * Function for the debugger to set a breakpoint on to gain control. 1348 */ 1349void 1350r_debug_state(void) 1351{ 1352} 1353 1354/* 1355 * Set a pointer variable in the main program to the given value. This 1356 * is used to set key variables such as "environ" before any of the 1357 * init functions are called. 1358 */ 1359static void 1360set_program_var(const char *name, const void *value) 1361{ 1362 const Obj_Entry *obj; 1363 unsigned long hash; 1364 1365 hash = elf_hash(name); 1366 for (obj = obj_main; obj != NULL; obj = obj->next) { 1367 const Elf_Sym *def; 1368 1369 if ((def = symlook_obj(name, hash, obj, false)) != NULL) { 1370 const void **addr; 1371 1372 addr = (const void **)(obj->relocbase + def->st_value); 1373 dbg("\"%s\": *%p <-- %p", name, addr, value); 1374 *addr = value; 1375 break; 1376 } 1377 } 1378} 1379 1380/* 1381 * Search the symbol table of a single shared object for a symbol of 1382 * the given name. Returns a pointer to the symbol, or NULL if no 1383 * definition was found. 1384 * 1385 * The symbol's hash value is passed in for efficiency reasons; that 1386 * eliminates many recomputations of the hash value. 1387 */ 1388const Elf_Sym * 1389symlook_obj(const char *name, unsigned long hash, const Obj_Entry *obj, 1390 bool in_plt) 1391{ 1392 if (obj->buckets != NULL) { 1393 unsigned long symnum = obj->buckets[hash % obj->nbuckets]; 1394 1395 while (symnum != STN_UNDEF) { 1396 const Elf_Sym *symp; 1397 const char *strp; 1398 1399 assert(symnum < obj->nchains); 1400 symp = obj->symtab + symnum; 1401 assert(symp->st_name != 0); 1402 strp = obj->strtab + symp->st_name; 1403 1404 if (strcmp(name, strp) == 0) 1405 return symp->st_shndx != SHN_UNDEF || 1406 (!in_plt && symp->st_value != 0 && 1407 ELF_ST_TYPE(symp->st_info) == STT_FUNC) ? symp : NULL; 1408 1409 symnum = obj->chains[symnum]; 1410 } 1411 } 1412 return NULL; 1413} 1414 1415static void 1416trace_loaded_objects(Obj_Entry *obj) 1417{ 1418 char *fmt1, *fmt2, *fmt, *main_local; 1419 int c; 1420 1421 if ((main_local = getenv("LD_TRACE_LOADED_OBJECTS_PROGNAME")) == NULL) 1422 main_local = ""; 1423 1424 if ((fmt1 = getenv("LD_TRACE_LOADED_OBJECTS_FMT1")) == NULL) 1425 fmt1 = "\t%o => %p (%x)\n"; 1426 1427 if ((fmt2 = getenv("LD_TRACE_LOADED_OBJECTS_FMT2")) == NULL) 1428 fmt2 = "\t%o (%x)\n"; 1429 1430 for (; obj; obj = obj->next) { 1431 Needed_Entry *needed; 1432 char *name, *path; 1433 bool is_lib; 1434 1435 for (needed = obj->needed; needed; needed = needed->next) { 1436 if (needed->obj != NULL) { 1437 if (needed->obj->traced) 1438 continue; 1439 needed->obj->traced = true; 1440 path = needed->obj->path; 1441 } else 1442 path = "not found"; 1443 1444 name = (char *)obj->strtab + needed->name; 1445 is_lib = strncmp(name, "lib", 3) == 0; /* XXX - bogus */ 1446 1447 fmt = is_lib ? fmt1 : fmt2; 1448 while ((c = *fmt++) != '\0') { 1449 switch (c) { 1450 default: 1451 putchar(c); 1452 continue; 1453 case '\\': 1454 switch (c = *fmt) { 1455 case '\0': 1456 continue; 1457 case 'n': 1458 putchar('\n'); 1459 break; 1460 case 't': 1461 putchar('\t'); 1462 break; 1463 } 1464 break; 1465 case '%': 1466 switch (c = *fmt) { 1467 case '\0': 1468 continue; 1469 case '%': 1470 default: 1471 putchar(c); 1472 break; 1473 case 'A': 1474 printf("%s", main_local); 1475 break; 1476 case 'a': 1477 printf("%s", obj_main->path); 1478 break; 1479 case 'o': 1480 printf("%s", name); 1481 break; 1482#if 0 1483 case 'm': 1484 printf("%d", sodp->sod_major); 1485 break; 1486 case 'n': 1487 printf("%d", sodp->sod_minor); 1488 break; 1489#endif 1490 case 'p': 1491 printf("%s", path); 1492 break; 1493 case 'x': 1494 printf("%p", needed->obj ? needed->obj->mapbase : 0); 1495 break; 1496 } 1497 break; 1498 } 1499 ++fmt; 1500 } 1501 } 1502 } 1503} 1504 1505static void 1506unref_object_dag(Obj_Entry *root) 1507{ 1508 assert(root->refcount != 0); 1509 root->refcount--; 1510 if (root->refcount == 0) { 1511 const Needed_Entry *needed; 1512 1513 for (needed = root->needed; needed != NULL; needed = needed->next) 1514 unref_object_dag(needed->obj); 1515 } 1516} 1517 1518/* 1519 * Non-mallocing printf, for use by malloc itself. 1520 * XXX - This doesn't belong in this module. 1521 */ 1522void 1523xprintf(const char *fmt, ...) 1524{ 1525 char buf[256]; 1526 va_list ap; 1527 1528 va_start(ap, fmt); 1529 vsprintf(buf, fmt, ap); 1530 (void)write(1, buf, strlen(buf)); 1531 va_end(ap); 1532} 1533