1 /* $NetBSD: search.c,v 1.16 2002/11/14 21:07:46 nathanw Exp $ */ 2 3 /* 4 * Copyright 1996 Matt Thomas <matt@3am-software.com> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by John Polstra. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Dynamic linker for ELF. 35 * 36 * John Polstra <jdp@polstra.com>. 37 */ 38 39 #include <err.h> 40 #include <errno.h> 41 #include <fcntl.h> 42 #include <stdarg.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <unistd.h> 47 #include <sys/types.h> 48 #include <sys/mman.h> 49 #include <sys/stat.h> 50 #include <dirent.h> 51 52 #include "debug.h" 53 #include "rtld.h" 54 55 /* 56 * Data declarations. 57 */ 58 Search_Path *_rtld_invalid_paths; 59 60 static Obj_Entry *_rtld_search_library_path __P((const char *, size_t, 61 const char *, size_t, int)); 62 63 static Obj_Entry * 64 _rtld_search_library_path(name, namelen, dir, dirlen, mode) 65 const char *name; 66 size_t namelen; 67 const char *dir; 68 size_t dirlen; 69 int mode; 70 { 71 char *pathname; 72 size_t pathnamelen; 73 Obj_Entry *obj; 74 Search_Path *sp; 75 76 pathnamelen = dirlen + 1 + namelen; 77 78 for (sp = _rtld_invalid_paths; sp != NULL; sp = sp->sp_next) { 79 if (sp->sp_pathlen == pathnamelen && 80 !memcmp(name, sp->sp_path + dirlen + 1, namelen) && 81 !memcmp(dir, sp->sp_path, dirlen)) { 82 return NULL; 83 } 84 } 85 86 pathname = xmalloc(pathnamelen + 1); 87 (void)strncpy(pathname, dir, dirlen); 88 pathname[dirlen] = '/'; 89 strcpy(pathname + dirlen + 1, name); 90 91 dbg((" Trying \"%s\"", pathname)); 92 obj = _rtld_load_object(pathname, mode); 93 if (obj == NULL) { 94 Search_Path *path; 95 96 path = NEW(Search_Path); 97 path->sp_pathlen = pathnamelen; 98 path->sp_path = pathname; 99 path->sp_next = _rtld_invalid_paths; 100 _rtld_invalid_paths = path; 101 } 102 return obj; 103 } 104 105 /* 106 * Find the library with the given name, and return its full pathname. 107 * The returned string is dynamically allocated. Generates an error 108 * message and returns NULL if the library cannot be found. 109 * 110 * If the second argument is non-NULL, then it refers to an already- 111 * loaded shared object, whose library search path will be searched. 112 */ 113 Obj_Entry * 114 _rtld_load_library(name, refobj, mode) 115 const char *name; 116 const Obj_Entry *refobj; 117 int mode; 118 { 119 char tmperror[512], *tmperrorp; 120 Search_Path *sp; 121 char *pathname; 122 int namelen; 123 Obj_Entry *obj; 124 125 if (strchr(name, '/') != NULL) { /* Hard coded pathname */ 126 if (name[0] != '/' && !_rtld_trust) { 127 _rtld_error( 128 "absolute pathname required for shared object \"%s\"", 129 name); 130 return NULL; 131 } 132 pathname = xstrdup(name); 133 goto found; 134 } 135 dbg((" Searching for \"%s\" (%p)", name, refobj)); 136 137 tmperrorp = _rtld_dlerror(); 138 if (tmperrorp != NULL) { 139 strncpy(tmperror, tmperrorp, sizeof tmperror); 140 tmperrorp = tmperror; 141 } 142 143 namelen = strlen(name); 144 145 for (sp = _rtld_paths; sp != NULL; sp = sp->sp_next) 146 if ((obj = _rtld_search_library_path(name, namelen, 147 sp->sp_path, sp->sp_pathlen, mode)) != NULL) 148 goto pathfound; 149 150 if (refobj != NULL) 151 for (sp = refobj->rpaths; sp != NULL; sp = sp->sp_next) 152 if ((obj = _rtld_search_library_path(name, 153 namelen, sp->sp_path, sp->sp_pathlen, mode)) != NULL) 154 goto pathfound; 155 156 for (sp = _rtld_default_paths; sp != NULL; sp = sp->sp_next) 157 if ((obj = _rtld_search_library_path(name, namelen, 158 sp->sp_path, sp->sp_pathlen, mode)) != NULL) 159 goto pathfound; 160 161 _rtld_error("Shared object \"%s\" not found", name); 162 return NULL; 163 164 pathfound: 165 /* 166 * Successfully found a library; restore the dlerror state as it was 167 * before _rtld_load_library() was called (any failed call to 168 * _rtld_search_library_path() will set the dlerror state, but if the 169 * library was eventually found, then the error state should not 170 * change. 171 */ 172 if (tmperrorp) 173 _rtld_error("%s", tmperror); 174 else 175 (void)_rtld_dlerror(); 176 return obj; 177 178 found: 179 obj = _rtld_load_object(pathname, mode); 180 if (obj == NULL) 181 free(pathname); 182 return obj; 183 } 184