1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1988 AT&T 24 * All Rights Reserved 25 * 26 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 /* 31 * Library processing 32 */ 33 #include <stdio.h> 34 #include <unistd.h> 35 #include <fcntl.h> 36 #include <string.h> 37 #include <limits.h> 38 #include <errno.h> 39 #include <debug.h> 40 #include "msg.h" 41 #include "_libld.h" 42 43 /* 44 * List of support libraries specified (-S option). 45 */ 46 static Listnode *insert_lib; 47 48 /* 49 * Function to handle -YL and -YU substitutions in LIBPATH. It's probably 50 * very unlikely that the link-editor will ever see this, as any use of these 51 * options is normally processed by the compiler driver first and the finished 52 * -YP string is sent to us. The fact that these two options are not even 53 * documented anymore makes it even more unlikely this processing will occur. 54 */ 55 static char * 56 compat_YL_YU(Ofl_desc *ofl, char *path, int index) 57 { 58 if (index == YLDIR) { 59 if (Llibdir) { 60 /* 61 * User supplied "-YL,libdir", this is the pathname that 62 * corresponds for compatibility to -YL (as defined in 63 * sgs/include/paths.h) 64 */ 65 DBG_CALL(Dbg_libs_ylu(ofl->ofl_lml, Llibdir, 66 path, index)); 67 return (Llibdir); 68 } 69 } else if (index == YUDIR) { 70 if (Ulibdir) { 71 /* 72 * User supplied "-YU,libdir", this is the pathname that 73 * corresponds for compatibility to -YU (as defined in 74 * sgs/include/paths.h) 75 */ 76 DBG_CALL(Dbg_libs_ylu(ofl->ofl_lml, Ulibdir, 77 path, index)); 78 return (Ulibdir); 79 } 80 } 81 return (path); 82 } 83 84 static char * 85 process_lib_path(Ofl_desc *ofl, List *list, char *path, Boolean subsflag) 86 { 87 int i; 88 char *cp; 89 Boolean seenflg = FALSE; 90 char *dot = (char *)MSG_ORIG(MSG_STR_DOT); 91 92 for (i = YLDIR; i; i++) { 93 cp = strpbrk(path, MSG_ORIG(MSG_STR_PATHTOK)); 94 if (cp == NULL) { 95 if (*path == '\0') { 96 if (seenflg) 97 if (list_appendc(list, subsflag ? 98 compat_YL_YU(ofl, dot, i) : dot) == 99 0) 100 return ((char *)S_ERROR); 101 } else 102 if (list_appendc(list, subsflag ? 103 compat_YL_YU(ofl, path, i) : path) == 0) 104 return ((char *)S_ERROR); 105 return (cp); 106 } 107 108 if (*cp == ':') { 109 *cp = '\0'; 110 if (cp == path) { 111 if (list_appendc(list, subsflag ? 112 compat_YL_YU(ofl, dot, i) : dot) == 0) 113 return ((char *)S_ERROR); 114 } else { 115 if (list_appendc(list, subsflag ? 116 compat_YL_YU(ofl, path, i) : path) == 0) 117 return ((char *)S_ERROR); 118 } 119 path = cp + 1; 120 seenflg = TRUE; 121 continue; 122 } 123 124 /* case ";" */ 125 126 if (cp != path) { 127 if (list_appendc(list, subsflag ? 128 compat_YL_YU(ofl, path, i) : path) == 0) 129 return ((char *)S_ERROR); 130 } else { 131 if (seenflg) 132 if (list_appendc(list, subsflag ? 133 compat_YL_YU(ofl, dot, i) : dot) == 0) 134 return ((char *)S_ERROR); 135 } 136 return (cp); 137 } 138 /* NOTREACHED */ 139 return (NULL); /* keep gcc happy */ 140 } 141 142 /* 143 * adds the indicated path to those to be searched for libraries. 144 */ 145 uintptr_t 146 ld_add_libdir(Ofl_desc *ofl, const char *path) 147 { 148 if (insert_lib == NULL) { 149 if (list_prependc(&ofl->ofl_ulibdirs, path) == 0) 150 return (S_ERROR); 151 insert_lib = ofl->ofl_ulibdirs.head; 152 } else 153 if ((insert_lib = list_insertc(&ofl->ofl_ulibdirs, path, 154 insert_lib)) == 0) 155 return (S_ERROR); 156 157 /* 158 * As -l and -L options can be interspersed, print the library 159 * search paths each time a new path is added. 160 */ 161 DBG_CALL(Dbg_libs_update(ofl->ofl_lml, &ofl->ofl_ulibdirs, 162 &ofl->ofl_dlibdirs)); 163 return (1); 164 } 165 166 /* 167 * Process a required library. Combine the directory and filename, and then 168 * append either a `.so' or `.a' suffix and try opening the associated pathname. 169 */ 170 static Ifl_desc * 171 find_lib_name(const char *dir, const char *file, Ofl_desc *ofl, Rej_desc *rej) 172 { 173 int fd; 174 size_t dlen; 175 char *_path, path[PATH_MAX + 2]; 176 const char *_dir = dir; 177 Ifl_desc *ifl; 178 179 /* 180 * Determine the size of the directory. The directory and filename are 181 * concatenated into the local buffer which is purposely larger than 182 * PATH_MAX. Should a pathname be created that exceeds the system 183 * limit, the open() will catch it, and a suitable rejection message is 184 * saved. 185 */ 186 if ((dlen = strlen(dir)) == 0) { 187 _dir = (char *)MSG_ORIG(MSG_STR_DOT); 188 dlen = 1; 189 } 190 dlen++; 191 192 /* 193 * If we are in dynamic mode try and open the associated shared object. 194 */ 195 if (ofl->ofl_flags & FLG_OF_DYNLIBS) { 196 (void) snprintf(path, (PATH_MAX + 2), MSG_ORIG(MSG_STR_LIB_SO), 197 _dir, file); 198 DBG_CALL(Dbg_libs_l(ofl->ofl_lml, file, path)); 199 if ((fd = open(path, O_RDONLY)) != -1) { 200 201 if ((_path = libld_malloc(strlen(path) + 1)) == 0) 202 return ((Ifl_desc *)S_ERROR); 203 (void) strcpy(_path, path); 204 205 ifl = ld_process_open(_path, &_path[dlen], &fd, ofl, 206 FLG_IF_NEEDED, rej); 207 if (fd != -1) 208 (void) close(fd); 209 return (ifl); 210 211 } else if (errno != ENOENT) { 212 /* 213 * If the open() failed for anything other than the 214 * file not existing, record the error condition. 215 */ 216 rej->rej_type = SGS_REJ_STR; 217 rej->rej_str = strerror(errno); 218 rej->rej_name = strdup(path); 219 } 220 } 221 222 /* 223 * If we are not in dynamic mode, or a shared object could not be 224 * located, try and open the associated archive. 225 */ 226 (void) snprintf(path, (PATH_MAX + 2), MSG_ORIG(MSG_STR_LIB_A), 227 _dir, file); 228 DBG_CALL(Dbg_libs_l(ofl->ofl_lml, file, path)); 229 if ((fd = open(path, O_RDONLY)) != -1) { 230 231 if ((_path = libld_malloc(strlen(path) + 1)) == 0) 232 return ((Ifl_desc *)S_ERROR); 233 (void) strcpy(_path, path); 234 235 ifl = ld_process_open(_path, &_path[dlen], &fd, ofl, 236 FLG_IF_NEEDED, rej); 237 if (fd != -1) 238 (void) close(fd); 239 return (ifl); 240 241 } else if (errno != ENOENT) { 242 /* 243 * If the open() failed for anything other than the 244 * file not existing, record the error condition. 245 */ 246 rej->rej_type = SGS_REJ_STR; 247 rej->rej_str = strerror(errno); 248 rej->rej_name = strdup(path); 249 } 250 251 return (NULL); 252 } 253 254 /* 255 * Take the abbreviated name of a library file (from -lfoo) and searches for the 256 * library. The search path rules are: 257 * 258 * o use any user supplied paths, i.e. LD_LIBRARY_PATH and -L, then 259 * 260 * o use the default directories, i.e. LIBPATH or -YP. 261 * 262 * If we are in dynamic mode and -Bstatic is not in effect, first look for a 263 * shared object with full name: path/libfoo.so; then [or else] look for an 264 * archive with name: path/libfoo.a. If no file is found, it's a fatal error, 265 * otherwise process the file appropriately depending on its type. 266 */ 267 uintptr_t 268 ld_find_library(const char *name, Ofl_desc *ofl) 269 { 270 Listnode *lnp; 271 char *path; 272 Ifl_desc *ifl = 0; 273 Rej_desc rej = { 0 }; 274 275 /* 276 * Search for this file in any user defined directories. 277 */ 278 for (LIST_TRAVERSE(&ofl->ofl_ulibdirs, lnp, path)) { 279 Rej_desc _rej = { 0 }; 280 281 if ((ifl = find_lib_name(path, name, ofl, &_rej)) == NULL) { 282 if (_rej.rej_type && (rej.rej_type == 0)) 283 rej = _rej; 284 continue; 285 } 286 return ((uintptr_t)ifl); 287 } 288 289 /* 290 * Finally try the default library search directories. 291 */ 292 for (LIST_TRAVERSE(&ofl->ofl_dlibdirs, lnp, path)) { 293 Rej_desc _rej = { 0 }; 294 295 if ((ifl = find_lib_name(path, name, ofl, &_rej)) == NULL) { 296 if (_rej.rej_type && (rej.rej_type == 0)) 297 rej = _rej; 298 continue; 299 } 300 return ((uintptr_t)ifl); 301 } 302 303 /* 304 * If we've got this far we haven't found a shared object or archive. 305 * If an object was found, but was rejected for some reason, print a 306 * diagnostic to that effect, otherwise generate a generic "not found" 307 * diagnostic. 308 */ 309 if (rej.rej_type) { 310 Conv_reject_desc_buf_t rej_buf; 311 312 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(reject[rej.rej_type]), 313 rej.rej_name ? rej.rej_name : MSG_INTL(MSG_STR_UNKNOWN), 314 conv_reject_desc(&rej, &rej_buf, ld_targ.t_m.m_mach)); 315 } else { 316 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_LIB_NOTFOUND), 317 name); 318 } 319 320 ofl->ofl_flags |= FLG_OF_FATAL; 321 return (0); 322 } 323 324 /* 325 * Inspect the LD_LIBRARY_PATH variable (if the -i options has not been 326 * specified), and set up the directory list from which to search for 327 * libraries. From the man page: 328 * 329 * LD_LIBRARY_PATH=dirlist1;dirlist2 330 * and 331 * ld ... -Lpath1 ... -Lpathn ... 332 * 333 * results in a search order of: 334 * 335 * dirlist1 path1 ... pathn dirlist2 LIBPATH 336 * 337 * If LD_LIBRARY_PATH has no `;' specified, the pathname(s) supplied are 338 * all taken as dirlist2. 339 */ 340 uintptr_t 341 ld_lib_setup(Ofl_desc *ofl) 342 { 343 char *path, *cp = NULL; 344 345 /* 346 * Determine whether an LD_LIBRARY_PATH setting is in effect. 347 */ 348 if (!(ofl->ofl_flags & FLG_OF_IGNENV)) { 349 #if defined(_ELF64) 350 if ((cp = getenv(MSG_ORIG(MSG_LD_LIBPATH_64))) == NULL) 351 #else 352 if ((cp = getenv(MSG_ORIG(MSG_LD_LIBPATH_32))) == NULL) 353 #endif 354 cp = getenv(MSG_ORIG(MSG_LD_LIBPATH)); 355 } 356 357 if ((cp != NULL) && (*cp != '\0')) { 358 if ((path = libld_malloc(strlen(cp) + 1)) == 0) 359 return (S_ERROR); 360 (void) strcpy(path, cp); 361 DBG_CALL(Dbg_libs_path(ofl->ofl_lml, path, LA_SER_DEFAULT, 0)); 362 363 /* 364 * Process the first path string (anything up to a null or 365 * a `;'); 366 */ 367 path = process_lib_path(ofl, &ofl->ofl_ulibdirs, path, FALSE); 368 369 370 /* 371 * If a `;' was seen then initialize the insert flag to the 372 * tail of this list. This is where any -L paths will be 373 * added (otherwise -L paths are prepended to this list). 374 * Continue to process the remaining path string. 375 */ 376 if (path) { 377 insert_lib = ofl->ofl_ulibdirs.tail; 378 *path = '\0'; 379 ++path; 380 cp = process_lib_path(ofl, &ofl->ofl_ulibdirs, path, 381 FALSE); 382 if (cp == (char *)S_ERROR) 383 return (S_ERROR); 384 else if (cp) 385 eprintf(ofl->ofl_lml, ERR_WARNING, 386 MSG_INTL(MSG_LIB_MALFORM)); 387 } 388 } 389 390 /* 391 * Add the default LIBPATH or any -YP supplied path. 392 */ 393 DBG_CALL(Dbg_libs_yp(ofl->ofl_lml, Plibpath)); 394 cp = process_lib_path(ofl, &ofl->ofl_dlibdirs, Plibpath, TRUE); 395 if (cp == (char *)S_ERROR) 396 return (S_ERROR); 397 else if (cp) { 398 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_LIB_BADYP)); 399 return (S_ERROR); 400 } 401 DBG_CALL(Dbg_libs_init(ofl->ofl_lml, &ofl->ofl_ulibdirs, 402 &ofl->ofl_dlibdirs)); 403 return (1); 404 } 405