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