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 * Copyright (c) 1988 AT&T 23 * All Rights Reserved 24 * 25 * 26 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 /* 32 * Print the list of shared objects required by a dynamic executable or shared 33 * object. 34 * 35 * usage is: ldd [-d | -r] [-c] [-e envar] [-i] [-f] [-L] [-l] [-s] 36 * [-U | -u] [-v] [-w] file(s) 37 * 38 * ldd opens the file and verifies the information in the elf header. 39 * If the file is a dynamic executable, we set up some environment variables 40 * and exec(2) the file. If the file is a shared object, we preload the 41 * file with a dynamic executable stub. The runtime linker (ld.so.1) actually 42 * provides the diagnostic output, according to the environment variables set. 43 * 44 * If neither -d nor -r is specified, we set only LD_TRACE_LOADED_OBJECTS_[AE]. 45 * The runtime linker will print the pathnames of all dynamic objects it 46 * loads, and then exit. Note that we distiguish between ELF and AOUT objects 47 * when setting this environment variable - AOUT executables cause the mapping 48 * of sbcp, the dependencies of which the user isn't interested in. 49 * 50 * If -d or -r is specified, we also set LD_WARN=1; the runtime linker will 51 * perform its normal relocations and issue warning messages for unresolved 52 * references. It will then exit. 53 * If -r is specified, we set LD_BIND_NOW=1, so that the runtime linker 54 * will perform all relocations, otherwise (under -d) the runtime linker 55 * will not perform PLT (function) type relocations. 56 * 57 * If -c is specified we also set LD_NOCONFIG=1, thus disabling any 58 * configuration file use. 59 * 60 * If -e is specified the associated environment variable is set for the 61 * child process that will produce ldd's diagnostics. 62 * 63 * If -i is specified, we set LD_INIT=1. The order of inititialization 64 * sections to be executed is printed. We also set LD_WARN=1. 65 * 66 * If -f is specified, we will run ldd as root on executables that have 67 * an unsercure runtime linker that does not live under the "/usr/lib" 68 * directory. By default we will not let this happen. 69 * 70 * If -l is specified it generates a warning for any auxiliary filter not found. 71 * Prior to 2.8 this forced any filters to load (all) their filtees. This is 72 * now the default, however missing auxiliary filters don't generate any error 73 * diagniostic. See also -L. 74 * 75 * If -L is specified we revert to lazy loading, thus any filtee or lazy 76 * dependency loading is deferred until relocations cause loading. Without 77 * this option we set LD_LOADFLTR=1, thus forcing any filters to load (all) 78 * their filtees, and LD_NOLAZYLOAD=1 thus forcing immediate processing of 79 * any lazy loaded dependencies. 80 * 81 * If -s is specified we also set LD_TRACE_SEARCH_PATH=1, thus enabling 82 * the runtime linker to indicate the search algorithm used. 83 * 84 * If -v is specified we also set LD_VERBOSE=1, thus enabling the runtime 85 * linker to indicate all object dependencies (not just the first object 86 * loaded) together with any versionig requirements. 87 * 88 * If -U or -u is specified unused dependencies are detected. -u causes 89 * LD_UNUSED=1 to be set, which causes dependencies that are unused within the 90 * process to be detected. -U causes LD_UNREF=1 to be set, which causes 91 * unreferenced objects, and unreferenced cyclic dependencies to be detected. 92 * These options assert that at least -d is set as relocation references are 93 * what determine an objects use. 94 * 95 * If -w is specified, no unresolved weak references are allowed. -w causes 96 * LD_NOUNRESWEAK=1 to be set. By default, an unresolved weak reference is 97 * allowed, and a "0" is written to the relocation offset. The -w option 98 * disables this default. Any weak references that can not be resolved result 99 * in relocation error messages. 100 */ 101 #include <fcntl.h> 102 #include <stdio.h> 103 #include <string.h> 104 #include <_libelf.h> 105 #include <stdlib.h> 106 #include <unistd.h> 107 #include <wait.h> 108 #include <locale.h> 109 #include <errno.h> 110 #include <signal.h> 111 #include "machdep.h" 112 #include "sgs.h" 113 #include "conv.h" 114 #include "a.out.h" 115 #include "msg.h" 116 117 static int elf_check(int, char *, char *, Elf *, int); 118 static int aout_check(int, char *, char *, int, int); 119 static int run(int, char *, char *, const char *, int); 120 121 122 /* 123 * Define all environment variable strings. The character following the "=" 124 * will be written to, to disable or enable the associated feature. 125 */ 126 static char bind[] = "LD_BIND_NOW= ", 127 load_elf[] = "LD_TRACE_LOADED_OBJECTS_E= ", 128 load_aout[] = "LD_TRACE_LOADED_OBJECTS_A= ", 129 path[] = "LD_TRACE_SEARCH_PATHS= ", 130 verb[] = "LD_VERBOSE= ", 131 warn[] = "LD_WARN= ", 132 conf[] = "LD_NOCONFIG= ", 133 fltr[] = "LD_LOADFLTR= ", 134 lazy[] = "LD_NOLAZYLOAD=1", 135 init[] = "LD_INIT= ", 136 uref[] = "LD_UNREF= ", 137 used[] = "LD_UNUSED= ", 138 weak[] = "LD_NOUNRESWEAK= "; 139 static char *load; 140 141 static const char *prefile_32, *prefile_64, *prefile; 142 static List eopts = { 0, 0 }; 143 144 /* 145 * Append an item to the specified list, and return a pointer to the list 146 * node created. 147 */ 148 Listnode * 149 list_append(List *lst, const void *item) 150 { 151 Listnode *lnp; 152 153 if ((lnp = malloc(sizeof (Listnode))) == (Listnode *)0) 154 return (0); 155 156 lnp->data = (void *)item; 157 lnp->next = NULL; 158 159 if (lst->head == NULL) 160 lst->tail = lst->head = lnp; 161 else { 162 lst->tail->next = lnp; 163 lst->tail = lst->tail->next; 164 } 165 return (lnp); 166 } 167 168 int 169 main(int argc, char **argv) 170 { 171 char *str, *cname = argv[0]; 172 173 Elf *elf; 174 int cflag = 0, dflag = 0, fflag = 0, iflag = 0, Lflag = 0; 175 int lflag = 0, rflag = 0, sflag = 0, Uflag = 0, uflag = 0; 176 int vflag = 0, wflag = 0, nfile, var, error = 0; 177 178 Listnode *lnp; 179 180 /* 181 * Establish locale. 182 */ 183 (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 184 (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 185 186 /* 187 * verify command line syntax and process arguments 188 */ 189 opterr = 0; /* disable getopt error mesg */ 190 191 while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_GETOPT))) != EOF) { 192 switch (var) { 193 case 'c' : /* enable config search */ 194 cflag = 1; 195 break; 196 case 'd' : /* perform data relocations */ 197 dflag = 1; 198 if (rflag) 199 error++; 200 break; 201 case 'e' : 202 if (list_append(&eopts, optarg) == 0) { 203 (void) fprintf(stderr, MSG_INTL(MSG_SYS_MALLOC), 204 cname); 205 exit(1); 206 } 207 break; 208 case 'f' : 209 fflag = 1; 210 break; 211 case 'L' : 212 Lflag = 1; 213 break; 214 case 'l' : 215 lflag = 1; 216 break; 217 case 'i' : /* print the order of .init */ 218 iflag = 1; 219 break; 220 case 'r' : /* perform all relocations */ 221 rflag = 1; 222 if (dflag) 223 error++; 224 break; 225 case 's' : /* enable search path output */ 226 sflag = 1; 227 break; 228 case 'U' : /* list unreferenced */ 229 Uflag = 1; /* dependencies */ 230 if (uflag) 231 error++; 232 break; 233 case 'u' : /* list unused dependencies */ 234 uflag = 1; 235 if (Uflag) 236 error++; 237 break; 238 case 'v' : /* enable verbose output */ 239 vflag = 1; 240 break; 241 case 'w' : /* disable unresolved weak */ 242 wflag = 1; /* references */ 243 break; 244 default : 245 error++; 246 break; 247 } 248 if (error) 249 break; 250 } 251 if (error) { 252 (void) fprintf(stderr, MSG_INTL(MSG_ARG_USAGE), cname); 253 exit(1); 254 } 255 256 /* 257 * Determine if any of the LD_PRELOAD family is already set in the 258 * environment, if so we'll continue to analyze each object with the 259 * appropriate setting. 260 */ 261 if (((prefile_32 = getenv(MSG_ORIG(MSG_LD_PRELOAD_32))) == NULL) || 262 (*prefile_32 == '\0')) { 263 prefile_32 = MSG_ORIG(MSG_STR_EMPTY); 264 } 265 if (((prefile_64 = getenv(MSG_ORIG(MSG_LD_PRELOAD_64))) == NULL) || 266 (*prefile_64 == '\0')) { 267 prefile_64 = MSG_ORIG(MSG_STR_EMPTY); 268 } 269 if (((prefile = getenv(MSG_ORIG(MSG_LD_PRELOAD))) == NULL) || 270 (*prefile == '\0')) { 271 prefile = MSG_ORIG(MSG_STR_EMPTY); 272 } 273 274 /* 275 * Determine if any environment requests are for the LD_PRELOAD family, 276 * and if so override any environment settings we've established above. 277 */ 278 for (LIST_TRAVERSE(&eopts, lnp, str)) { 279 if ((strncmp(str, MSG_ORIG(MSG_LD_PRELOAD_32), 280 MSG_LD_PRELOAD_32_SIZE)) == 0) { 281 str += MSG_LD_PRELOAD_32_SIZE; 282 if ((*str++ == '=') && (*str != '\0')) 283 prefile_32 = str; 284 continue; 285 } 286 if ((strncmp(str, MSG_ORIG(MSG_LD_PRELOAD_64), 287 MSG_LD_PRELOAD_64_SIZE)) == 0) { 288 str += MSG_LD_PRELOAD_64_SIZE; 289 if ((*str++ == '=') && (*str != '\0')) 290 prefile_64 = str; 291 continue; 292 } 293 if ((strncmp(str, MSG_ORIG(MSG_LD_PRELOAD), 294 MSG_LD_PRELOAD_SIZE)) == 0) { 295 str += MSG_LD_PRELOAD_SIZE; 296 if ((*str++ == '=') && (*str != '\0')) 297 prefile = str; 298 continue; 299 } 300 } 301 302 /* 303 * Set the appropriate relocation environment variables (Note unsetting 304 * the environment variables is done just in case the user already 305 * has these in their environment ... sort of thing the test folks 306 * would do :-) 307 */ 308 warn[sizeof (warn) - 2] = (dflag || rflag || Uflag || uflag) ? '1' : 309 '\0'; 310 bind[sizeof (bind) - 2] = (rflag) ? '1' : '\0'; 311 path[sizeof (path) - 2] = (sflag) ? '1' : '\0'; 312 verb[sizeof (verb) - 2] = (vflag) ? '1' : '\0'; 313 fltr[sizeof (fltr) - 2] = (Lflag) ? '\0' : (lflag) ? '2' : '1'; 314 init[sizeof (init) - 2] = (iflag) ? '1' : '\0'; 315 conf[sizeof (conf) - 2] = (cflag) ? '1' : '\0'; 316 lazy[sizeof (lazy) - 2] = (Lflag) ? '\0' : '1'; 317 uref[sizeof (uref) - 2] = (Uflag) ? '1' : '\0'; 318 used[sizeof (used) - 2] = (uflag) ? '1' : '\0'; 319 weak[sizeof (weak) - 2] = (wflag) ? '1' : '\0'; 320 321 /* 322 * coordinate libelf's version information 323 */ 324 if (elf_version(EV_CURRENT) == EV_NONE) { 325 (void) fprintf(stderr, MSG_INTL(MSG_ELF_LIBELF), cname, 326 EV_CURRENT); 327 exit(1); 328 } 329 330 /* 331 * Loop through remaining arguments. Note that from here on there 332 * are no exit conditions so that we can process a list of files, 333 * any error condition is retained for a final exit status. 334 */ 335 nfile = argc - optind; 336 for (; optind < argc; optind++) { 337 char *fname = argv[optind]; 338 339 /* 340 * Open file (do this before checking access so that we can 341 * provide the user with better diagnostics). 342 */ 343 if ((var = open(fname, O_RDONLY)) == -1) { 344 int err = errno; 345 (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), cname, 346 fname, strerror(err)); 347 error = 1; 348 continue; 349 } 350 351 /* 352 * Get the files elf descriptor and process it as an elf or 353 * a.out (4.x) file. 354 */ 355 elf = elf_begin(var, ELF_C_READ, (Elf *)0); 356 switch (elf_kind(elf)) { 357 case ELF_K_AR : 358 (void) fprintf(stderr, MSG_INTL(MSG_USP_NODYNORSO), 359 cname, fname); 360 error = 1; 361 break; 362 case ELF_K_COFF: 363 (void) fprintf(stderr, MSG_INTL(MSG_USP_UNKNOWN), 364 cname, fname); 365 error = 1; 366 break; 367 case ELF_K_ELF: 368 if (elf_check(nfile, fname, cname, elf, fflag) != NULL) 369 error = 1; 370 break; 371 default: 372 /* 373 * This is either an unknown file or an aout format 374 */ 375 if (aout_check(nfile, fname, cname, var, fflag) != NULL) 376 error = 1; 377 break; 378 } 379 (void) elf_end(elf); 380 (void) close(var); 381 } 382 return (error); 383 } 384 385 386 387 static int 388 is_runnable(GElf_Ehdr *ehdr) 389 { 390 if ((ehdr->e_ident[EI_CLASS] == M_CLASS) && 391 (ehdr->e_ident[EI_DATA] == M_DATA)) 392 return (ELFCLASS32); 393 394 #if defined(__sparc) 395 if ((ehdr->e_machine == EM_SPARCV9) && 396 (ehdr->e_ident[EI_DATA] == M_DATA) && 397 (conv_sys_eclass() == ELFCLASS64)) 398 return (ELFCLASS64); 399 #elif defined(__x86) 400 if ((ehdr->e_machine == EM_AMD64) && 401 (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) && 402 (conv_sys_eclass() == ELFCLASS64)) 403 return (ELFCLASS64); 404 #endif 405 406 return (ELFCLASSNONE); 407 } 408 409 410 static int 411 elf_check(int nfile, char *fname, char *cname, Elf *elf, int fflag) 412 { 413 GElf_Ehdr ehdr; 414 GElf_Phdr phdr; 415 int dynamic = 0, interp = 0, cnt, class; 416 417 /* 418 * verify information in file header 419 */ 420 if (gelf_getehdr(elf, &ehdr) == NULL) { 421 (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETEHDR), 422 cname, fname, elf_errmsg(-1)); 423 return (1); 424 } 425 426 /* 427 * check class and encoding 428 */ 429 if ((class = is_runnable(&ehdr)) == ELFCLASSNONE) { 430 (void) fprintf(stderr, MSG_INTL(MSG_ELF_CLASSDATA), 431 cname, fname); 432 return (1); 433 } 434 435 /* 436 * check type 437 */ 438 if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN) && 439 (ehdr.e_type != ET_REL)) { 440 (void) fprintf(stderr, MSG_INTL(MSG_ELF_BADMAGIC), 441 cname, fname); 442 return (1); 443 } 444 if ((class == ELFCLASS32) && (ehdr.e_machine != M_MACH)) { 445 if (ehdr.e_machine != M_MACHPLUS) { 446 (void) fprintf(stderr, MSG_INTL(MSG_ELF_MACHTYPE), 447 cname, fname); 448 return (1); 449 } 450 if ((ehdr.e_flags & M_FLAGSPLUS) == 0) { 451 (void) fprintf(stderr, MSG_INTL(MSG_ELF_MACHFLAGS), 452 cname, fname); 453 return (1); 454 } 455 } 456 457 /* 458 * Check that the file is executable. Dynamic executables must be 459 * executable to be exec'ed. Shared objects need not be executable to 460 * be mapped with a dynamic executable, however, by convention they're 461 * supposed to be executable. 462 */ 463 if (access(fname, X_OK) != 0) { 464 if (ehdr.e_type == ET_EXEC) { 465 (void) fprintf(stderr, MSG_INTL(MSG_USP_NOTEXEC_1), 466 cname, fname); 467 return (1); 468 } 469 (void) fprintf(stderr, MSG_INTL(MSG_USP_NOTEXEC_2), cname, 470 fname); 471 } 472 473 /* 474 * Determine whether we have a dynamic section or interpretor. 475 */ 476 for (cnt = 0; cnt < (int)ehdr.e_phnum; cnt++) { 477 if (dynamic && interp) 478 break; 479 480 if (gelf_getphdr(elf, cnt, &phdr) == NULL) { 481 (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETPHDR), 482 cname, fname, elf_errmsg(-1)); 483 return (1); 484 } 485 486 if (phdr.p_type == PT_DYNAMIC) { 487 dynamic = 1; 488 continue; 489 } 490 491 if (phdr.p_type != PT_INTERP) 492 continue; 493 494 interp = 1; 495 496 /* 497 * If fflag is not set, and euid == root, and the interpreter 498 * does not live under /lib, /usr/lib or /etc/lib then don't 499 * allow ldd to execute the image. This prevents someone 500 * creating a `trojan horse' by substituting their own 501 * interpreter that could preform privileged operations 502 * when ldd is against it. 503 */ 504 if ((fflag == 0) && (geteuid() == 0) && 505 (strcmp(fname, conv_lddstub(class)) != 0)) { 506 char *interpreter; 507 508 /* 509 * Does the interpreter live under a trusted directory. 510 */ 511 interpreter = elf_getident(elf, 0) + phdr.p_offset; 512 513 if ((strncmp(interpreter, MSG_ORIG(MSG_PTH_USRLIB), 514 MSG_PTH_USRLIB_SIZE) != 0) && 515 (strncmp(interpreter, MSG_ORIG(MSG_PTH_LIB), 516 MSG_PTH_LIB_SIZE) != 0) && 517 (strncmp(interpreter, MSG_ORIG(MSG_PTH_ETCLIB), 518 MSG_PTH_ETCLIB_SIZE) != 0)) { 519 (void) fprintf(stderr, MSG_INTL(MSG_USP_ELFINS), 520 cname, fname, interpreter); 521 return (1); 522 } 523 } 524 } 525 526 /* 527 * Catch the case of a static executable (ie, an ET_EXEC that has a set 528 * of program headers but no PT_DYNAMIC). 529 */ 530 if (ehdr.e_phnum && !dynamic) { 531 (void) fprintf(stderr, MSG_INTL(MSG_USP_NODYNORSO), cname, 532 fname); 533 return (1); 534 } 535 536 /* 537 * If there is a dynamic section, then check for the DF_1_NOHDR 538 * flag, and bail if it is present. Those objects are created using 539 * the ?N mapfile option: The ELF header and program headers are 540 * not mapped as part of the first segment, and virtual addresses 541 * are computed without them. If ldd tries to interpret such 542 * a file, it will become confused and generate bad output or 543 * crash. Such objects are always special purpose files (like an OS 544 * kernel) --- files for which the ldd operation doesn't make sense. 545 */ 546 if (dynamic && (_gelf_getdyndtflags_1(elf) & DF_1_NOHDR)) { 547 (void) fprintf(stderr, MSG_INTL(MSG_USP_NOHDR), cname, 548 fname); 549 return (1); 550 } 551 552 load = load_elf; 553 554 /* 555 * Run the required program (shared and relocatable objects require the 556 * use of lddstub). 557 */ 558 if ((ehdr.e_type == ET_EXEC) && interp) 559 return (run(nfile, cname, fname, (const char *)fname, class)); 560 else 561 return (run(nfile, cname, fname, conv_lddstub(class), class)); 562 } 563 564 static int 565 aout_check(int nfile, char *fname, char *cname, int fd, int fflag) 566 { 567 struct exec aout; 568 int err; 569 570 if (lseek(fd, 0, SEEK_SET) != 0) { 571 err = errno; 572 (void) fprintf(stderr, MSG_INTL(MSG_SYS_LSEEK), cname, fname, 573 strerror(err)); 574 return (1); 575 } 576 if (read(fd, (char *)&aout, sizeof (struct exec)) != 577 sizeof (struct exec)) { 578 err = errno; 579 (void) fprintf(stderr, MSG_INTL(MSG_SYS_READ), cname, fname, 580 strerror(err)); 581 return (1); 582 } 583 if (aout.a_machtype != M_SPARC) { 584 (void) fprintf(stderr, MSG_INTL(MSG_USP_UNKNOWN), cname, fname); 585 return (1); 586 } 587 if (N_BADMAG(aout) || !aout.a_dynamic) { 588 (void) fprintf(stderr, MSG_INTL(MSG_USP_NODYNORSO), cname, 589 fname); 590 return (1); 591 } 592 if (!fflag && (geteuid() == 0)) { 593 (void) fprintf(stderr, MSG_INTL(MSG_USP_AOUTINS), cname, fname); 594 return (1); 595 } 596 597 /* 598 * Run the required program. 599 */ 600 if ((aout.a_magic == ZMAGIC) && 601 (aout.a_entry <= sizeof (struct exec))) { 602 load = load_elf; 603 return (run(nfile, cname, fname, conv_lddstub(ELFCLASS32), 604 ELFCLASS32)); 605 } else { 606 load = load_aout; 607 return (run(nfile, cname, fname, (const char *)fname, 608 ELFCLASS32)); 609 } 610 } 611 612 613 /* 614 * Run the required program, setting the preload and trace environment 615 * variables accordingly. 616 */ 617 static int 618 run(int nfile, char *cname, char *fname, const char *ename, int class) 619 { 620 const char *preload = 0; 621 int pid, status; 622 623 if ((pid = fork()) == -1) { 624 int err = errno; 625 (void) fprintf(stderr, MSG_INTL(MSG_SYS_FORK), cname, 626 strerror(err)); 627 return (1); 628 } 629 630 if (pid) { /* parent */ 631 while (wait(&status) != pid) 632 ; 633 if (WIFSIGNALED(status) && ((WSIGMASK & status) != SIGPIPE)) { 634 (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXEC), cname, 635 fname); 636 (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXEC_SIG), 637 (WSIGMASK & status), ((status & WCOREFLG) ? 638 MSG_INTL(MSG_SYS_EXEC_CORE) : 639 MSG_ORIG(MSG_STR_EMPTY))); 640 status = 1; 641 } else if (WHIBYTE(status)) { 642 (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXEC), cname, 643 fname); 644 (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXEC_STAT), 645 WHIBYTE(status)); 646 status = 1; 647 } 648 } else { /* child */ 649 Listnode *lnp; 650 char *str; 651 size_t size; 652 653 /* 654 * When using ldd(1) to analyze a shared object we preload the 655 * shared object with lddstub. Any additional preload 656 * requirements are added after the object being analyzed, this 657 * allows us to skip the first object but produce diagnostics 658 * for each other preloaded object. 659 */ 660 if (fname != ename) { 661 char *str; 662 const char *files = prefile; 663 const char *format = MSG_ORIG(MSG_STR_FMT1); 664 665 for (str = fname; *str; str++) 666 if (*str == '/') { 667 format = MSG_ORIG(MSG_STR_FMT2); 668 break; 669 } 670 671 preload = MSG_ORIG(MSG_LD_PRELOAD); 672 673 /* 674 * Determine which preload files and preload environment 675 * variable to use. 676 */ 677 if (class == ELFCLASS64) { 678 if (prefile_64 != MSG_ORIG(MSG_STR_EMPTY)) { 679 files = prefile_64; 680 preload = MSG_ORIG(MSG_LD_PRELOAD_64); 681 } 682 } else { 683 if (prefile_32 != MSG_ORIG(MSG_STR_EMPTY)) { 684 files = prefile_32; 685 preload = MSG_ORIG(MSG_LD_PRELOAD_32); 686 } 687 } 688 689 if ((str = (char *)malloc(strlen(preload) + 690 strlen(fname) + strlen(files) + 5)) == 0) { 691 (void) fprintf(stderr, MSG_INTL(MSG_SYS_MALLOC), 692 cname); 693 exit(1); 694 } 695 696 (void) sprintf(str, format, preload, fname, files); 697 if (putenv(str) != 0) { 698 (void) fprintf(stderr, MSG_INTL(MSG_ENV_FAILED), 699 cname); 700 exit(1); 701 } 702 703 /* 704 * The pointer "load" has be assigned to load_elf[] or 705 * load_aout[]. Use the size of load_elf[] as the size 706 * of load_aout[] is the same. 707 */ 708 load[sizeof (load_elf) - 2] = '2'; 709 } else 710 load[sizeof (load_elf) - 2] = '1'; 711 712 713 /* 714 * Establish new environment variables to affect the child 715 * process. 716 */ 717 if ((putenv(warn) != 0) || (putenv(bind) != 0) || 718 (putenv(path) != 0) || (putenv(verb) != 0) || 719 (putenv(fltr) != 0) || (putenv(conf) != 0) || 720 (putenv(init) != 0) || (putenv(lazy) != 0) || 721 (putenv(uref) != 0) || (putenv(used) != 0) || 722 (putenv(weak) != 0) || (putenv(load) != 0)) { 723 (void) fprintf(stderr, MSG_INTL(MSG_ENV_FAILED), cname); 724 exit(1); 725 } 726 727 /* 728 * Establish explicit environment requires (but don't override 729 * any preload request established to process a shared object). 730 */ 731 size = 0; 732 for (LIST_TRAVERSE(&eopts, lnp, str)) { 733 if (preload) { 734 if (size == 0) 735 size = strlen(preload); 736 if ((strncmp(preload, str, size) == 0) && 737 (str[size] == '=')) { 738 continue; 739 } 740 } 741 if (putenv(str) != 0) { 742 (void) fprintf(stderr, MSG_INTL(MSG_ENV_FAILED), 743 cname); 744 exit(1); 745 } 746 } 747 748 /* 749 * Execute the object and let ld.so.1 do the rest. 750 */ 751 if (nfile > 1) 752 (void) printf(MSG_ORIG(MSG_STR_FMT3), fname); 753 (void) fflush(stdout); 754 if ((execl(ename, ename, (char *)0)) == -1) { 755 (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXEC), cname, 756 fname); 757 perror(ename); 758 _exit(0); 759 /* NOTREACHED */ 760 } 761 } 762 return (status); 763 } 764 765 const char * 766 _ldd_msg(Msg mid) 767 { 768 return (gettext(MSG_ORIG(mid))); 769 } 770