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 (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. 27 */ 28 /* 29 * Copyright (c) 2012, Joyent, Inc. All rights reserved. 30 */ 31 32 /* 33 * Library processing 34 */ 35 #include <stdio.h> 36 #include <unistd.h> 37 #include <fcntl.h> 38 #include <string.h> 39 #include <limits.h> 40 #include <errno.h> 41 #include <debug.h> 42 #include <sys/sysmacros.h> 43 #include "msg.h" 44 #include "_libld.h" 45 46 /* 47 * Define a list index for "-L" processing. By default, "-L" search paths are 48 * inserted at the beginning of the associated search list. However, should a 49 * ";" be discovered in a LD_LIBRARY_PATH listing, then any new "-L" search 50 * paths are inserted following the ";". 51 */ 52 static Aliste Lidx = 0; 53 54 /* 55 * Function to handle -YL and -YU substitutions in LIBPATH. It's probably 56 * very unlikely that the link-editor will ever see this, as any use of these 57 * options is normally processed by the compiler driver first and the finished 58 * -YP string is sent to us. The fact that these two options are not even 59 * documented anymore makes it even more unlikely this processing will occur. 60 */ 61 static char * 62 compat_YL_YU(Ofl_desc *ofl, char *path, int index) 63 { 64 if (index == YLDIR) { 65 if (Llibdir) { 66 /* 67 * User supplied "-YL,libdir", this is the pathname that 68 * corresponds for compatibility to -YL (as defined in 69 * sgs/include/paths.h) 70 */ 71 DBG_CALL(Dbg_libs_ylu(ofl->ofl_lml, Llibdir, 72 path, index)); 73 return (Llibdir); 74 } 75 } else if (index == YUDIR) { 76 if (Ulibdir) { 77 /* 78 * User supplied "-YU,libdir", this is the pathname that 79 * corresponds for compatibility to -YU (as defined in 80 * sgs/include/paths.h) 81 */ 82 DBG_CALL(Dbg_libs_ylu(ofl->ofl_lml, Ulibdir, 83 path, index)); 84 return (Ulibdir); 85 } 86 } 87 return (path); 88 } 89 90 static char * 91 process_lib_path(Ofl_desc *ofl, APlist **apl, char *path, Boolean subsflag) 92 { 93 int i; 94 char *cp; 95 Boolean seenflg = FALSE; 96 char *dot = (char *)MSG_ORIG(MSG_STR_DOT); 97 98 for (i = YLDIR; i; i++) { 99 cp = strpbrk(path, MSG_ORIG(MSG_STR_PATHTOK)); 100 if (cp == NULL) { 101 if (*path == '\0') { 102 if (seenflg) 103 if (aplist_append(apl, (subsflag ? 104 compat_YL_YU(ofl, dot, i) : dot), 105 AL_CNT_OFL_LIBDIRS) == NULL) 106 return ((char *)S_ERROR); 107 108 } else if (aplist_append(apl, (subsflag ? 109 compat_YL_YU(ofl, path, i) : path), 110 AL_CNT_OFL_LIBDIRS) == NULL) { 111 return ((char *)S_ERROR); 112 } 113 return (cp); 114 } 115 116 if (*cp == ':') { 117 *cp = '\0'; 118 if (cp == path) { 119 if (aplist_append(apl, (subsflag ? 120 compat_YL_YU(ofl, dot, i) : dot), 121 AL_CNT_OFL_LIBDIRS) == NULL) 122 return ((char *)S_ERROR); 123 124 } else if (aplist_append(apl, (subsflag ? 125 compat_YL_YU(ofl, path, i) : path), 126 AL_CNT_OFL_LIBDIRS) == NULL) { 127 return ((char *)S_ERROR); 128 } 129 path = cp + 1; 130 seenflg = TRUE; 131 continue; 132 } 133 134 /* case ";" */ 135 136 if (cp != path) { 137 if (aplist_append(apl, (subsflag ? 138 compat_YL_YU(ofl, path, i) : path), 139 AL_CNT_OFL_LIBDIRS) == NULL) 140 return ((char *)S_ERROR); 141 } else { 142 if (seenflg) 143 if (aplist_append(apl, (subsflag ? 144 compat_YL_YU(ofl, dot, i) : dot), 145 AL_CNT_OFL_LIBDIRS) == NULL) 146 return ((char *)S_ERROR); 147 } 148 return (cp); 149 } 150 /* NOTREACHED */ 151 return (NULL); /* keep gcc happy */ 152 } 153 154 /* 155 * adds the indicated path to those to be searched for libraries. 156 */ 157 uintptr_t 158 ld_add_libdir(Ofl_desc *ofl, const char *path) 159 { 160 if (aplist_insert(&ofl->ofl_ulibdirs, path, 161 AL_CNT_OFL_LIBDIRS, Lidx++) == NULL) 162 return (S_ERROR); 163 164 /* 165 * As -l and -L options can be interspersed, print the library 166 * search paths each time a new path is added. 167 */ 168 DBG_CALL(Dbg_libs_update(ofl->ofl_lml, ofl->ofl_ulibdirs, 169 ofl->ofl_dlibdirs)); 170 return (1); 171 } 172 173 /* 174 * Process a required library. Combine the directory and filename, and then 175 * append either a `.so' or `.a' suffix and try opening the associated pathname. 176 */ 177 static uintptr_t 178 find_lib_name(const char *dir, const char *file, Ofl_desc *ofl, Rej_desc *rej, 179 ofl_flag_t flags) 180 { 181 int fd; 182 size_t dlen; 183 char *_path, path[PATH_MAX + 2]; 184 const char *_dir = dir; 185 uintptr_t open_ret; 186 187 /* 188 * Determine the size of the directory. The directory and filename are 189 * concatenated into the local buffer which is purposely larger than 190 * PATH_MAX. Should a pathname be created that exceeds the system 191 * limit, the open() will catch it, and a suitable rejection message is 192 * saved. 193 */ 194 if ((dlen = strlen(dir)) == 0) { 195 _dir = (char *)MSG_ORIG(MSG_STR_DOT); 196 dlen = 1; 197 } 198 dlen++; 199 200 /* 201 * If we are in dynamic mode try and open the associated shared object. 202 */ 203 if (ofl->ofl_flags & FLG_OF_DYNLIBS) { 204 (void) snprintf(path, (PATH_MAX + 2), MSG_ORIG(MSG_STR_LIB_SO), 205 _dir, file); 206 DBG_CALL(Dbg_libs_l(ofl->ofl_lml, file, path)); 207 if ((fd = open(path, O_RDONLY)) != -1) { 208 209 if ((_path = libld_malloc(strlen(path) + 1)) == NULL) 210 return (S_ERROR); 211 (void) strcpy(_path, path); 212 213 open_ret = ld_process_open(_path, &_path[dlen], &fd, 214 ofl, FLG_IF_NEEDED, rej, NULL); 215 if (fd != -1) 216 (void) close(fd); 217 if (open_ret != 0 && (flags & FLG_OF_ADEFLIB)) 218 ld_eprintf(ofl, ERR_WARNING, 219 MSG_INTL(MSG_ARG_ASSDEFLIB_FOUND), dir, 220 file); 221 return (open_ret); 222 223 } else if (errno != ENOENT) { 224 /* 225 * If the open() failed for anything other than the 226 * file not existing, record the error condition. 227 */ 228 rej->rej_type = SGS_REJ_STR; 229 rej->rej_str = strerror(errno); 230 rej->rej_name = strdup(path); 231 } 232 } 233 234 /* 235 * If we are not in dynamic mode, or a shared object could not be 236 * located, try and open the associated archive. 237 */ 238 (void) snprintf(path, (PATH_MAX + 2), MSG_ORIG(MSG_STR_LIB_A), 239 _dir, file); 240 DBG_CALL(Dbg_libs_l(ofl->ofl_lml, file, path)); 241 if ((fd = open(path, O_RDONLY)) != -1) { 242 243 if ((_path = libld_malloc(strlen(path) + 1)) == NULL) 244 return (S_ERROR); 245 (void) strcpy(_path, path); 246 247 open_ret = ld_process_open(_path, &_path[dlen], &fd, ofl, 248 FLG_IF_NEEDED, rej, NULL); 249 if (fd != -1) 250 (void) close(fd); 251 return (open_ret); 252 253 } else if (errno != ENOENT) { 254 /* 255 * If the open() failed for anything other than the 256 * file not existing, record the error condition. 257 */ 258 rej->rej_type = SGS_REJ_STR; 259 rej->rej_str = strerror(errno); 260 rej->rej_name = strdup(path); 261 } 262 263 return (0); 264 } 265 266 /* 267 * Take the abbreviated name of a library file (from -lfoo) and searches for the 268 * library. The search path rules are: 269 * 270 * o use any user supplied paths, i.e. LD_LIBRARY_PATH and -L, then 271 * 272 * o use the default directories, i.e. LIBPATH or -YP. 273 * 274 * If we are in dynamic mode and -Bstatic is not in effect, first look for a 275 * shared object with full name: path/libfoo.so; then [or else] look for an 276 * archive with name: path/libfoo.a. If no file is found, it's a fatal error, 277 * otherwise process the file appropriately depending on its type. 278 * 279 * If we end up using the default directories and -z assert-deflib has been 280 * turned on, then we pass that information down into find_lib_name which will 281 * warn appropriately if we find a shared object. 282 */ 283 uintptr_t 284 ld_find_library(const char *name, Ofl_desc *ofl) 285 { 286 Aliste idx; 287 char *path; 288 uintptr_t open_ret; 289 Rej_desc rej = { 0 }; 290 ofl_flag_t flags = 0; 291 292 /* 293 * Search for this file in any user defined directories. 294 */ 295 for (APLIST_TRAVERSE(ofl->ofl_ulibdirs, idx, path)) { 296 Rej_desc _rej = { 0 }; 297 298 if ((open_ret = find_lib_name(path, name, ofl, &_rej, 299 flags)) == 0) { 300 if (_rej.rej_type && (rej.rej_type == 0)) 301 rej = _rej; 302 continue; 303 } 304 return (open_ret); 305 } 306 307 if (ofl->ofl_flags & FLG_OF_ADEFLIB) { 308 flags |= FLG_OF_ADEFLIB; 309 for (APLIST_TRAVERSE(ofl->ofl_assdeflib, idx, path)) { 310 if (strncmp(name, path + MSG_STR_LIB_SIZE, 311 MAX(strlen(path + MSG_STR_LIB_SIZE) - 312 MSG_STR_SOEXT_SIZE, strlen(name))) == 0) { 313 flags &= ~FLG_OF_ADEFLIB; 314 break; 315 } 316 } 317 } 318 319 /* 320 * Finally try the default library search directories. 321 */ 322 for (APLIST_TRAVERSE(ofl->ofl_dlibdirs, idx, path)) { 323 Rej_desc _rej = { 0 }; 324 325 if ((open_ret = find_lib_name(path, name, ofl, &_rej, 326 flags)) == 0) { 327 if (_rej.rej_type && (rej.rej_type == 0)) 328 rej = _rej; 329 continue; 330 } 331 332 return (open_ret); 333 } 334 335 /* 336 * If we've got this far we haven't found a shared object or archive. 337 * If an object was found, but was rejected for some reason, print a 338 * diagnostic to that effect, otherwise generate a generic "not found" 339 * diagnostic. 340 */ 341 if (rej.rej_type) { 342 Conv_reject_desc_buf_t rej_buf; 343 344 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(reject[rej.rej_type]), 345 rej.rej_name ? rej.rej_name : MSG_INTL(MSG_STR_UNKNOWN), 346 conv_reject_desc(&rej, &rej_buf, ld_targ.t_m.m_mach)); 347 } else { 348 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_LIB_NOTFOUND), name); 349 } 350 351 return (0); 352 } 353 354 /* 355 * Inspect the LD_LIBRARY_PATH variable (if the -i options has not been 356 * specified), and set up the directory list from which to search for 357 * libraries. From the man page: 358 * 359 * LD_LIBRARY_PATH=dirlist1;dirlist2 360 * and 361 * ld ... -Lpath1 ... -Lpathn ... 362 * 363 * results in a search order of: 364 * 365 * dirlist1 path1 ... pathn dirlist2 LIBPATH 366 * 367 * If LD_LIBRARY_PATH has no `;' specified, the pathname(s) supplied are 368 * all taken as dirlist2. 369 */ 370 uintptr_t 371 ld_lib_setup(Ofl_desc *ofl) 372 { 373 char *path, *cp = NULL; 374 375 /* 376 * Determine whether an LD_LIBRARY_PATH setting is in effect. 377 */ 378 if (!(ofl->ofl_flags & FLG_OF_IGNENV)) { 379 #if defined(_ELF64) 380 if ((cp = getenv(MSG_ORIG(MSG_LD_LIBPATH_64))) == NULL) 381 #else 382 if ((cp = getenv(MSG_ORIG(MSG_LD_LIBPATH_32))) == NULL) 383 #endif 384 cp = getenv(MSG_ORIG(MSG_LD_LIBPATH)); 385 } 386 387 if (cp && cp[0]) { 388 if ((path = libld_malloc(strlen(cp) + 1)) == NULL) 389 return (S_ERROR); 390 (void) strcpy(path, cp); 391 DBG_CALL(Dbg_libs_path(ofl->ofl_lml, path, LA_SER_DEFAULT, 0)); 392 393 /* 394 * Process the first path string (anything up to a null or 395 * a `;'); 396 */ 397 path = process_lib_path(ofl, &ofl->ofl_ulibdirs, path, FALSE); 398 399 400 /* 401 * By default, -L paths are prepended to the library search 402 * path list, because Lidx == 0. If a ';' is seen within an 403 * LD_LIBRARY_PATH string, change the insert index so that -L 404 * paths are added following the ';'. 405 */ 406 if (path) { 407 Lidx = aplist_nitems(ofl->ofl_ulibdirs); 408 *path = '\0'; 409 ++path; 410 cp = process_lib_path(ofl, &ofl->ofl_ulibdirs, path, 411 FALSE); 412 if (cp == (char *)S_ERROR) 413 return (S_ERROR); 414 else if (cp) 415 ld_eprintf(ofl, ERR_WARNING, 416 MSG_INTL(MSG_LIB_MALFORM)); 417 } 418 } 419 420 /* 421 * Add the default LIBPATH or any -YP supplied path. 422 */ 423 DBG_CALL(Dbg_libs_yp(ofl->ofl_lml, Plibpath)); 424 cp = process_lib_path(ofl, &ofl->ofl_dlibdirs, Plibpath, TRUE); 425 if (cp == (char *)S_ERROR) 426 return (S_ERROR); 427 else if (cp) { 428 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_LIB_BADYP)); 429 return (S_ERROR); 430 } 431 DBG_CALL(Dbg_libs_init(ofl->ofl_lml, ofl->ofl_ulibdirs, 432 ofl->ofl_dlibdirs)); 433 return (1); 434 } 435