1 /* $NetBSD: ldd.c,v 1.1 1996/12/16 19:59:56 cgd 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 #include <err.h> 35 #include <errno.h> 36 #include <fcntl.h> 37 #include <stdarg.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 #include <sys/types.h> 43 #include <sys/mman.h> 44 #include <dirent.h> 45 46 #include "debug.h" 47 #include "rtld.h" 48 49 /* 50 * Data declarations. 51 */ 52 const char *_rtld_error_message; /* Message for dlopen(), or NULL */ 53 bool _rtld_trust; /* False for setuid and setgid programs */ 54 Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */ 55 Obj_Entry **_rtld_objtail = &_rtld_objlist; 56 /* Link field of last object in list */ 57 Obj_Entry *_rtld_objmain; /* The main program shared object */ 58 59 Search_Path *_rtld_paths; 60 61 static void print_needed(Obj_Entry *); 62 63 64 /* 65 * Main entry point for dynamic linking. The argument is the stack 66 * pointer. The stack is expected to be laid out as described in the 67 * SVR4 ABI specification, Intel 386 Processor Supplement. Specifically, 68 * the stack pointer points to a word containing ARGC. Following that 69 * in the stack is a null-terminated sequence of pointers to argument 70 * strings. Then comes a null-terminated sequence of pointers to 71 * environment strings. Finally, there is a sequence of "auxiliary 72 * vector" entries. 73 * 74 * This function returns the entry point for the main program in %eax, 75 * and the dynamic linker's exit procedure in %edx. We accomplish this 76 * by declaring the return value to have the 64-bit type "long long". 77 * Such values are returned with their most-significant 32 bits in %edx, 78 * and their least-significant 32 bits in %eax. 79 */ 80 int 81 main( 82 int argc, 83 char **argv) 84 { 85 #ifdef DEBUG 86 debug = 1; 87 #endif 88 _rtld_add_paths(&_rtld_paths, RTLD_DEFAULT_LIBRARY_PATH); 89 90 91 _rtld_trust = geteuid() == getuid() && getegid() == getgid(); 92 93 if (_rtld_trust) { 94 _rtld_add_paths(&_rtld_paths, getenv("LD_LIBRARY_PATH")); 95 } 96 97 for (argc--, argv++; argc != 0; argc--, argv++) { 98 int fd = open(*argv, O_RDONLY); 99 if (fd == -1) { 100 warn("%s", *argv); 101 continue; 102 } 103 _rtld_objmain = _rtld_map_object(*argv, fd); 104 close(fd); 105 if (_rtld_objmain == NULL) { 106 warnx("%s", _rtld_error_message); 107 continue; 108 } 109 110 _rtld_objmain->path = *argv; 111 _rtld_objmain->mainprog = true; 112 _rtld_digest_dynamic(_rtld_objmain); 113 114 /* Link the main program into the list of objects. */ 115 *_rtld_objtail = _rtld_objmain; 116 _rtld_objtail = &_rtld_objmain->next; 117 ++_rtld_objmain->refcount; 118 119 (void) _rtld_load_needed_objects(_rtld_objmain); 120 121 printf("%s:\n", _rtld_objmain->path); 122 print_needed(_rtld_objmain); 123 124 while (_rtld_objlist != NULL) { 125 Obj_Entry *obj = _rtld_objlist; 126 _rtld_objlist = obj->next; 127 while (obj->rpaths != NULL) { 128 const Search_Path *rpath = obj->rpaths; 129 obj->rpaths = rpath->sp_next; 130 free((void *) rpath->sp_path); 131 free((void *) rpath); 132 } 133 while (obj->needed != NULL) { 134 const Needed_Entry *needed = obj->needed; 135 obj->needed = needed->next; 136 free((void *) needed); 137 } 138 (void) munmap(obj->relocbase, obj->mapsize); 139 free(obj->path); 140 free(obj); 141 } 142 143 _rtld_objmain = NULL; 144 _rtld_objtail = &_rtld_objlist; 145 } 146 return 0; 147 } 148 149 /* 150 * Error reporting function. Use it like printf. If formats the message 151 * into a buffer, and sets things up so that the next call to dlerror() 152 * will return the message. 153 */ 154 void 155 _rtld_error( 156 const char *fmt, ...) 157 { 158 static char buf[512]; 159 va_list ap; 160 va_start(ap, fmt); 161 xvsnprintf(buf, sizeof buf, fmt, ap); 162 _rtld_error_message = buf; 163 va_end(ap); 164 } 165 166 static void 167 print_needed( 168 Obj_Entry *obj) 169 { 170 const Needed_Entry *needed; 171 172 for (needed = obj->needed; needed != NULL; needed = needed->next) { 173 char libnamebuf[200]; 174 const char *libname = obj->strtab + needed->name, *cp; 175 if (strncmp(libname, "lib", 3) == 0 176 && (cp = strstr(libname, ".so")) != NULL) { 177 strcpy(libnamebuf, "-l"); 178 memcpy(&libnamebuf[2], libname + 3, cp - (libname + 3)); 179 strcpy(&libnamebuf[cp - (libname + 3) + 2], cp + 3); 180 libname = libnamebuf; 181 } 182 183 if (needed->obj != NULL) { 184 print_needed(needed->obj); 185 if (!needed->obj->printed) { 186 printf("\t %s => %s\n", libname, needed->obj->path); 187 needed->obj->printed = 1; 188 } 189 } else { 190 printf("\t %s => not found\n", libname); 191 } 192 } 193 } 194