10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51698Sab196087 * Common Development and Distribution License (the "License").
61698Sab196087 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
206150Srie *
210Sstevel@tonic-gate * Copyright (c) 1988 AT&T
220Sstevel@tonic-gate * All Rights Reserved
230Sstevel@tonic-gate *
240Sstevel@tonic-gate *
2512382SAli.Bahrami@Oracle.COM * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
260Sstevel@tonic-gate */
270Sstevel@tonic-gate
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate * Print the list of shared objects required by a dynamic executable or shared
300Sstevel@tonic-gate * object.
310Sstevel@tonic-gate *
32*12498SRod.Evans@Sun.COM * usage is: ldd [-d | -r] [-c] [-D] [-e envar] [-i] [-f] [-L] [-l] [-p] [-s]
334947Srie * [-U | -u] [-v] [-w] file(s)
340Sstevel@tonic-gate *
350Sstevel@tonic-gate * ldd opens the file and verifies the information in the elf header.
360Sstevel@tonic-gate * If the file is a dynamic executable, we set up some environment variables
370Sstevel@tonic-gate * and exec(2) the file. If the file is a shared object, we preload the
380Sstevel@tonic-gate * file with a dynamic executable stub. The runtime linker (ld.so.1) actually
390Sstevel@tonic-gate * provides the diagnostic output, according to the environment variables set.
400Sstevel@tonic-gate *
410Sstevel@tonic-gate * If neither -d nor -r is specified, we set only LD_TRACE_LOADED_OBJECTS_[AE].
420Sstevel@tonic-gate * The runtime linker will print the pathnames of all dynamic objects it
430Sstevel@tonic-gate * loads, and then exit. Note that we distiguish between ELF and AOUT objects
440Sstevel@tonic-gate * when setting this environment variable - AOUT executables cause the mapping
450Sstevel@tonic-gate * of sbcp, the dependencies of which the user isn't interested in.
460Sstevel@tonic-gate *
470Sstevel@tonic-gate * If -d or -r is specified, we also set LD_WARN=1; the runtime linker will
480Sstevel@tonic-gate * perform its normal relocations and issue warning messages for unresolved
490Sstevel@tonic-gate * references. It will then exit.
500Sstevel@tonic-gate * If -r is specified, we set LD_BIND_NOW=1, so that the runtime linker
510Sstevel@tonic-gate * will perform all relocations, otherwise (under -d) the runtime linker
520Sstevel@tonic-gate * will not perform PLT (function) type relocations.
530Sstevel@tonic-gate *
540Sstevel@tonic-gate * If -c is specified we also set LD_NOCONFIG=1, thus disabling any
550Sstevel@tonic-gate * configuration file use.
560Sstevel@tonic-gate *
5712449SRod.Evans@Sun.COM * If -D is specified we skip deferred dependency processing. By default,
5812449SRod.Evans@Sun.COM * ldd loads all deferred dependencies. However, during normal process
5912449SRod.Evans@Sun.COM * execution, deferred dependencies are only loaded when an explicit binding
6012449SRod.Evans@Sun.COM * to an individual deferred reference is made. As no user code is executed
6112449SRod.Evans@Sun.COM * under ldd, explicit references to deferred symbols can't be triggered.
6212449SRod.Evans@Sun.COM *
630Sstevel@tonic-gate * If -e is specified the associated environment variable is set for the
640Sstevel@tonic-gate * child process that will produce ldd's diagnostics.
650Sstevel@tonic-gate *
660Sstevel@tonic-gate * If -i is specified, we set LD_INIT=1. The order of inititialization
670Sstevel@tonic-gate * sections to be executed is printed. We also set LD_WARN=1.
680Sstevel@tonic-gate *
690Sstevel@tonic-gate * If -f is specified, we will run ldd as root on executables that have
700Sstevel@tonic-gate * an unsercure runtime linker that does not live under the "/usr/lib"
710Sstevel@tonic-gate * directory. By default we will not let this happen.
720Sstevel@tonic-gate *
730Sstevel@tonic-gate * If -l is specified it generates a warning for any auxiliary filter not found.
740Sstevel@tonic-gate * Prior to 2.8 this forced any filters to load (all) their filtees. This is
750Sstevel@tonic-gate * now the default, however missing auxiliary filters don't generate any error
760Sstevel@tonic-gate * diagniostic. See also -L.
770Sstevel@tonic-gate *
780Sstevel@tonic-gate * If -L is specified we revert to lazy loading, thus any filtee or lazy
790Sstevel@tonic-gate * dependency loading is deferred until relocations cause loading. Without
800Sstevel@tonic-gate * this option we set LD_LOADFLTR=1, thus forcing any filters to load (all)
810Sstevel@tonic-gate * their filtees, and LD_NOLAZYLOAD=1 thus forcing immediate processing of
820Sstevel@tonic-gate * any lazy loaded dependencies.
830Sstevel@tonic-gate *
840Sstevel@tonic-gate * If -s is specified we also set LD_TRACE_SEARCH_PATH=1, thus enabling
850Sstevel@tonic-gate * the runtime linker to indicate the search algorithm used.
860Sstevel@tonic-gate *
870Sstevel@tonic-gate * If -v is specified we also set LD_VERBOSE=1, thus enabling the runtime
880Sstevel@tonic-gate * linker to indicate all object dependencies (not just the first object
8912449SRod.Evans@Sun.COM * loaded) together with any versioning requirements.
900Sstevel@tonic-gate *
910Sstevel@tonic-gate * If -U or -u is specified unused dependencies are detected. -u causes
920Sstevel@tonic-gate * LD_UNUSED=1 to be set, which causes dependencies that are unused within the
930Sstevel@tonic-gate * process to be detected. -U causes LD_UNREF=1 to be set, which causes
940Sstevel@tonic-gate * unreferenced objects, and unreferenced cyclic dependencies to be detected.
950Sstevel@tonic-gate * These options assert that at least -d is set as relocation references are
960Sstevel@tonic-gate * what determine an objects use.
974947Srie *
984947Srie * If -w is specified, no unresolved weak references are allowed. -w causes
994947Srie * LD_NOUNRESWEAK=1 to be set. By default, an unresolved weak reference is
1004947Srie * allowed, and a "0" is written to the relocation offset. The -w option
1014947Srie * disables this default. Any weak references that can not be resolved result
1026150Srie * in relocation error messages. This option has no use without -r or -d.
1036150Srie *
1046150Srie * If the -p option is specified, no unresolved PARENT or EXTERN references are
1056150Srie * allowed. -p causes LD_NOPAREXT=1 to be set. By default, PARENT and EXTERN
1066150Srie * references, which have been explicitly assigned via a mapfile when a shared
1076150Srie * object was built, imply that a caller will provide the symbols, and hence
1086150Srie * these are not reported as relocation errors. Note, the -p option is asserted
1096150Srie * by default when either the -r or -d options are used to inspect a dynamic
1106150Srie * executable. This option has no use with a shared object without -r or -d.
1110Sstevel@tonic-gate */
1120Sstevel@tonic-gate #include <fcntl.h>
1130Sstevel@tonic-gate #include <stdio.h>
1140Sstevel@tonic-gate #include <string.h>
1151698Sab196087 #include <_libelf.h>
1160Sstevel@tonic-gate #include <stdlib.h>
1170Sstevel@tonic-gate #include <unistd.h>
1180Sstevel@tonic-gate #include <wait.h>
1190Sstevel@tonic-gate #include <locale.h>
1200Sstevel@tonic-gate #include <errno.h>
1210Sstevel@tonic-gate #include <signal.h>
1220Sstevel@tonic-gate #include "machdep.h"
1230Sstevel@tonic-gate #include "sgs.h"
1240Sstevel@tonic-gate #include "conv.h"
1250Sstevel@tonic-gate #include "a.out.h"
1260Sstevel@tonic-gate #include "msg.h"
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate static int elf_check(int, char *, char *, Elf *, int);
1290Sstevel@tonic-gate static int aout_check(int, char *, char *, int, int);
1300Sstevel@tonic-gate static int run(int, char *, char *, const char *, int);
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate /*
1344947Srie * Define all environment variable strings. The character following the "="
1354947Srie * will be written to, to disable or enable the associated feature.
1360Sstevel@tonic-gate */
1370Sstevel@tonic-gate static char bind[] = "LD_BIND_NOW= ",
1380Sstevel@tonic-gate load_elf[] = "LD_TRACE_LOADED_OBJECTS_E= ",
1390Sstevel@tonic-gate load_aout[] = "LD_TRACE_LOADED_OBJECTS_A= ",
1400Sstevel@tonic-gate path[] = "LD_TRACE_SEARCH_PATHS= ",
1410Sstevel@tonic-gate verb[] = "LD_VERBOSE= ",
1420Sstevel@tonic-gate warn[] = "LD_WARN= ",
1430Sstevel@tonic-gate conf[] = "LD_NOCONFIG= ",
1440Sstevel@tonic-gate fltr[] = "LD_LOADFLTR= ",
1450Sstevel@tonic-gate lazy[] = "LD_NOLAZYLOAD=1",
1460Sstevel@tonic-gate init[] = "LD_INIT= ",
1470Sstevel@tonic-gate uref[] = "LD_UNREF= ",
1484947Srie used[] = "LD_UNUSED= ",
1496150Srie weak[] = "LD_NOUNRESWEAK= ",
15012449SRod.Evans@Sun.COM nope[] = "LD_NOPAREXT= ",
15112449SRod.Evans@Sun.COM defr[] = "LD_DEFERRED= ";
1520Sstevel@tonic-gate static char *load;
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate static const char *prefile_32, *prefile_64, *prefile;
1559131SRod.Evans@Sun.COM static APlist *eopts = NULL;
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate int
main(int argc,char ** argv,char ** envp)1586223Sab196087 main(int argc, char **argv, char **envp)
1590Sstevel@tonic-gate {
1600Sstevel@tonic-gate char *str, *cname = argv[0];
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate Elf *elf;
1630Sstevel@tonic-gate int cflag = 0, dflag = 0, fflag = 0, iflag = 0, Lflag = 0;
1640Sstevel@tonic-gate int lflag = 0, rflag = 0, sflag = 0, Uflag = 0, uflag = 0;
16512449SRod.Evans@Sun.COM int Dflag = 0, pflag = 0, vflag = 0, wflag = 0;
16612449SRod.Evans@Sun.COM int nfile, var, error = 0;
1679131SRod.Evans@Sun.COM Aliste idx;
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate /*
1706223Sab196087 * If we're on a 64-bit kernel, try to exec a full 64-bit version of
1716223Sab196087 * the binary. If successful, conv_check_native() won't return.
1726223Sab196087 *
1736223Sab196087 * This is done to ensure that ldd can handle objects >2GB.
1746223Sab196087 * ldd uses libelf, which is not large file capable. The
1756223Sab196087 * 64-bit ldd can handle any sized object.
1766223Sab196087 */
1776223Sab196087 (void) conv_check_native(argv, envp);
1786223Sab196087
1796223Sab196087 /*
1800Sstevel@tonic-gate * Establish locale.
1810Sstevel@tonic-gate */
1820Sstevel@tonic-gate (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY));
1830Sstevel@tonic-gate (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS));
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate /*
1860Sstevel@tonic-gate * verify command line syntax and process arguments
1870Sstevel@tonic-gate */
1880Sstevel@tonic-gate opterr = 0; /* disable getopt error mesg */
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_GETOPT))) != EOF) {
1910Sstevel@tonic-gate switch (var) {
1920Sstevel@tonic-gate case 'c' : /* enable config search */
1930Sstevel@tonic-gate cflag = 1;
1940Sstevel@tonic-gate break;
19512449SRod.Evans@Sun.COM case 'D' : /* skip deferred dependencies */
19612449SRod.Evans@Sun.COM Dflag = 1;
19712449SRod.Evans@Sun.COM break;
1980Sstevel@tonic-gate case 'd' : /* perform data relocations */
1990Sstevel@tonic-gate dflag = 1;
2000Sstevel@tonic-gate if (rflag)
2010Sstevel@tonic-gate error++;
2020Sstevel@tonic-gate break;
2030Sstevel@tonic-gate case 'e' :
2049131SRod.Evans@Sun.COM if (aplist_append(&eopts, optarg, 10) == NULL) {
2050Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_MALLOC),
2060Sstevel@tonic-gate cname);
2070Sstevel@tonic-gate exit(1);
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate break;
2100Sstevel@tonic-gate case 'f' :
2110Sstevel@tonic-gate fflag = 1;
2120Sstevel@tonic-gate break;
2130Sstevel@tonic-gate case 'L' :
2140Sstevel@tonic-gate Lflag = 1;
2150Sstevel@tonic-gate break;
2160Sstevel@tonic-gate case 'l' :
2170Sstevel@tonic-gate lflag = 1;
2180Sstevel@tonic-gate break;
2190Sstevel@tonic-gate case 'i' : /* print the order of .init */
2200Sstevel@tonic-gate iflag = 1;
2210Sstevel@tonic-gate break;
2226150Srie case 'p' :
2236150Srie pflag = 1; /* expose unreferenced */
2246150Srie break; /* parent or externals */
2250Sstevel@tonic-gate case 'r' : /* perform all relocations */
2260Sstevel@tonic-gate rflag = 1;
2270Sstevel@tonic-gate if (dflag)
2280Sstevel@tonic-gate error++;
2290Sstevel@tonic-gate break;
2300Sstevel@tonic-gate case 's' : /* enable search path output */
2310Sstevel@tonic-gate sflag = 1;
2320Sstevel@tonic-gate break;
2330Sstevel@tonic-gate case 'U' : /* list unreferenced */
2340Sstevel@tonic-gate Uflag = 1; /* dependencies */
2350Sstevel@tonic-gate if (uflag)
2360Sstevel@tonic-gate error++;
2370Sstevel@tonic-gate break;
2380Sstevel@tonic-gate case 'u' : /* list unused dependencies */
2390Sstevel@tonic-gate uflag = 1;
2400Sstevel@tonic-gate if (Uflag)
2410Sstevel@tonic-gate error++;
2420Sstevel@tonic-gate break;
2430Sstevel@tonic-gate case 'v' : /* enable verbose output */
2440Sstevel@tonic-gate vflag = 1;
2450Sstevel@tonic-gate break;
2466150Srie case 'w' : /* expose unresolved weak */
2474947Srie wflag = 1; /* references */
2484947Srie break;
2490Sstevel@tonic-gate default :
2500Sstevel@tonic-gate error++;
2510Sstevel@tonic-gate break;
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate if (error)
2540Sstevel@tonic-gate break;
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate if (error) {
2570Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_USAGE), cname);
2580Sstevel@tonic-gate exit(1);
2590Sstevel@tonic-gate }
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate /*
2620Sstevel@tonic-gate * Determine if any of the LD_PRELOAD family is already set in the
2630Sstevel@tonic-gate * environment, if so we'll continue to analyze each object with the
2640Sstevel@tonic-gate * appropriate setting.
2650Sstevel@tonic-gate */
2660Sstevel@tonic-gate if (((prefile_32 = getenv(MSG_ORIG(MSG_LD_PRELOAD_32))) == NULL) ||
2670Sstevel@tonic-gate (*prefile_32 == '\0')) {
2680Sstevel@tonic-gate prefile_32 = MSG_ORIG(MSG_STR_EMPTY);
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate if (((prefile_64 = getenv(MSG_ORIG(MSG_LD_PRELOAD_64))) == NULL) ||
2710Sstevel@tonic-gate (*prefile_64 == '\0')) {
2720Sstevel@tonic-gate prefile_64 = MSG_ORIG(MSG_STR_EMPTY);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate if (((prefile = getenv(MSG_ORIG(MSG_LD_PRELOAD))) == NULL) ||
2750Sstevel@tonic-gate (*prefile == '\0')) {
2760Sstevel@tonic-gate prefile = MSG_ORIG(MSG_STR_EMPTY);
2770Sstevel@tonic-gate }
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate /*
2800Sstevel@tonic-gate * Determine if any environment requests are for the LD_PRELOAD family,
2810Sstevel@tonic-gate * and if so override any environment settings we've established above.
2820Sstevel@tonic-gate */
2839131SRod.Evans@Sun.COM for (APLIST_TRAVERSE(eopts, idx, str)) {
2840Sstevel@tonic-gate if ((strncmp(str, MSG_ORIG(MSG_LD_PRELOAD_32),
2850Sstevel@tonic-gate MSG_LD_PRELOAD_32_SIZE)) == 0) {
2860Sstevel@tonic-gate str += MSG_LD_PRELOAD_32_SIZE;
2870Sstevel@tonic-gate if ((*str++ == '=') && (*str != '\0'))
2880Sstevel@tonic-gate prefile_32 = str;
2890Sstevel@tonic-gate continue;
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate if ((strncmp(str, MSG_ORIG(MSG_LD_PRELOAD_64),
2920Sstevel@tonic-gate MSG_LD_PRELOAD_64_SIZE)) == 0) {
2930Sstevel@tonic-gate str += MSG_LD_PRELOAD_64_SIZE;
2940Sstevel@tonic-gate if ((*str++ == '=') && (*str != '\0'))
2950Sstevel@tonic-gate prefile_64 = str;
2960Sstevel@tonic-gate continue;
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate if ((strncmp(str, MSG_ORIG(MSG_LD_PRELOAD),
2990Sstevel@tonic-gate MSG_LD_PRELOAD_SIZE)) == 0) {
3000Sstevel@tonic-gate str += MSG_LD_PRELOAD_SIZE;
3010Sstevel@tonic-gate if ((*str++ == '=') && (*str != '\0'))
3020Sstevel@tonic-gate prefile = str;
3030Sstevel@tonic-gate continue;
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate /*
3080Sstevel@tonic-gate * Set the appropriate relocation environment variables (Note unsetting
3090Sstevel@tonic-gate * the environment variables is done just in case the user already
3100Sstevel@tonic-gate * has these in their environment ... sort of thing the test folks
3110Sstevel@tonic-gate * would do :-)
3120Sstevel@tonic-gate */
3134947Srie warn[sizeof (warn) - 2] = (dflag || rflag || Uflag || uflag) ? '1' :
3140Sstevel@tonic-gate '\0';
3154947Srie bind[sizeof (bind) - 2] = (rflag) ? '1' : '\0';
3164947Srie path[sizeof (path) - 2] = (sflag) ? '1' : '\0';
3174947Srie verb[sizeof (verb) - 2] = (vflag) ? '1' : '\0';
3184947Srie fltr[sizeof (fltr) - 2] = (Lflag) ? '\0' : (lflag) ? '2' : '1';
3194947Srie init[sizeof (init) - 2] = (iflag) ? '1' : '\0';
3204947Srie conf[sizeof (conf) - 2] = (cflag) ? '1' : '\0';
3214947Srie lazy[sizeof (lazy) - 2] = (Lflag) ? '\0' : '1';
3224947Srie uref[sizeof (uref) - 2] = (Uflag) ? '1' : '\0';
3234947Srie used[sizeof (used) - 2] = (uflag) ? '1' : '\0';
3244947Srie weak[sizeof (weak) - 2] = (wflag) ? '1' : '\0';
3256150Srie nope[sizeof (nope) - 2] = (pflag) ? '1' : '\0';
32612449SRod.Evans@Sun.COM defr[sizeof (defr) - 2] = (Dflag) ? '\0' : '1';
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate /*
3290Sstevel@tonic-gate * coordinate libelf's version information
3300Sstevel@tonic-gate */
3310Sstevel@tonic-gate if (elf_version(EV_CURRENT) == EV_NONE) {
3320Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_LIBELF), cname,
3330Sstevel@tonic-gate EV_CURRENT);
3340Sstevel@tonic-gate exit(1);
3350Sstevel@tonic-gate }
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate /*
3380Sstevel@tonic-gate * Loop through remaining arguments. Note that from here on there
3390Sstevel@tonic-gate * are no exit conditions so that we can process a list of files,
3400Sstevel@tonic-gate * any error condition is retained for a final exit status.
3410Sstevel@tonic-gate */
3420Sstevel@tonic-gate nfile = argc - optind;
3430Sstevel@tonic-gate for (; optind < argc; optind++) {
3440Sstevel@tonic-gate char *fname = argv[optind];
3450Sstevel@tonic-gate
3460Sstevel@tonic-gate /*
3470Sstevel@tonic-gate * Open file (do this before checking access so that we can
3480Sstevel@tonic-gate * provide the user with better diagnostics).
3490Sstevel@tonic-gate */
3500Sstevel@tonic-gate if ((var = open(fname, O_RDONLY)) == -1) {
3510Sstevel@tonic-gate int err = errno;
3520Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), cname,
3530Sstevel@tonic-gate fname, strerror(err));
3540Sstevel@tonic-gate error = 1;
3550Sstevel@tonic-gate continue;
3560Sstevel@tonic-gate }
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate /*
3590Sstevel@tonic-gate * Get the files elf descriptor and process it as an elf or
3600Sstevel@tonic-gate * a.out (4.x) file.
3610Sstevel@tonic-gate */
3620Sstevel@tonic-gate elf = elf_begin(var, ELF_C_READ, (Elf *)0);
3630Sstevel@tonic-gate switch (elf_kind(elf)) {
3640Sstevel@tonic-gate case ELF_K_AR :
3650Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USP_NODYNORSO),
3660Sstevel@tonic-gate cname, fname);
3670Sstevel@tonic-gate error = 1;
3680Sstevel@tonic-gate break;
3690Sstevel@tonic-gate case ELF_K_COFF:
3700Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USP_UNKNOWN),
3710Sstevel@tonic-gate cname, fname);
3720Sstevel@tonic-gate error = 1;
3730Sstevel@tonic-gate break;
3740Sstevel@tonic-gate case ELF_K_ELF:
3750Sstevel@tonic-gate if (elf_check(nfile, fname, cname, elf, fflag) != NULL)
3760Sstevel@tonic-gate error = 1;
3770Sstevel@tonic-gate break;
3780Sstevel@tonic-gate default:
3790Sstevel@tonic-gate /*
3800Sstevel@tonic-gate * This is either an unknown file or an aout format
3810Sstevel@tonic-gate */
3820Sstevel@tonic-gate if (aout_check(nfile, fname, cname, var, fflag) != NULL)
3830Sstevel@tonic-gate error = 1;
3840Sstevel@tonic-gate break;
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate (void) elf_end(elf);
3870Sstevel@tonic-gate (void) close(var);
3880Sstevel@tonic-gate }
3890Sstevel@tonic-gate return (error);
3900Sstevel@tonic-gate }
3910Sstevel@tonic-gate
3920Sstevel@tonic-gate
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate static int
elf_check(int nfile,char * fname,char * cname,Elf * elf,int fflag)3950Sstevel@tonic-gate elf_check(int nfile, char *fname, char *cname, Elf *elf, int fflag)
3960Sstevel@tonic-gate {
39712382SAli.Bahrami@Oracle.COM Conv_inv_buf_t inv_buf;
3980Sstevel@tonic-gate GElf_Ehdr ehdr;
3990Sstevel@tonic-gate GElf_Phdr phdr;
4000Sstevel@tonic-gate int dynamic = 0, interp = 0, cnt, class;
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate /*
4030Sstevel@tonic-gate * verify information in file header
4040Sstevel@tonic-gate */
4050Sstevel@tonic-gate if (gelf_getehdr(elf, &ehdr) == NULL) {
4060Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETEHDR),
4074947Srie cname, fname, elf_errmsg(-1));
4080Sstevel@tonic-gate return (1);
4090Sstevel@tonic-gate }
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate /*
41212382SAli.Bahrami@Oracle.COM * Compatible machine
4130Sstevel@tonic-gate */
41412382SAli.Bahrami@Oracle.COM if ((ehdr.e_machine != M_MACH_32) && (ehdr.e_machine != M_MACH_64) &&
41512382SAli.Bahrami@Oracle.COM (ehdr.e_machine != M_MACHPLUS)) {
41612382SAli.Bahrami@Oracle.COM (void) fprintf(stderr, MSG_INTL(MSG_ELF_MACHTYPE), cname, fname,
41712382SAli.Bahrami@Oracle.COM conv_ehdr_mach(ehdr.e_machine, 0, &inv_buf));
41812382SAli.Bahrami@Oracle.COM return (1);
41912382SAli.Bahrami@Oracle.COM }
42012382SAli.Bahrami@Oracle.COM
42112382SAli.Bahrami@Oracle.COM /*
42212382SAli.Bahrami@Oracle.COM * Compatible encoding (byte order)
42312382SAli.Bahrami@Oracle.COM */
42412382SAli.Bahrami@Oracle.COM if (ehdr.e_ident[EI_DATA] != M_DATA) {
42512382SAli.Bahrami@Oracle.COM (void) fprintf(stderr, MSG_INTL(MSG_ELF_DATA), cname, fname,
42612382SAli.Bahrami@Oracle.COM conv_ehdr_data(ehdr.e_ident[EI_DATA], 0, &inv_buf));
4270Sstevel@tonic-gate return (1);
4280Sstevel@tonic-gate }
4290Sstevel@tonic-gate
4300Sstevel@tonic-gate /*
43112382SAli.Bahrami@Oracle.COM * Compatible class
43212382SAli.Bahrami@Oracle.COM */
43312382SAli.Bahrami@Oracle.COM switch (class = ehdr.e_ident[EI_CLASS]) {
43412382SAli.Bahrami@Oracle.COM case ELFCLASS32:
43512382SAli.Bahrami@Oracle.COM /*
43612382SAli.Bahrami@Oracle.COM * If M_MACH is not the same thing as M_MACHPLUS and this
43712382SAli.Bahrami@Oracle.COM * is an M_MACHPLUS object, then the corresponding header
43812382SAli.Bahrami@Oracle.COM * flag must be set.
43912382SAli.Bahrami@Oracle.COM */
44012382SAli.Bahrami@Oracle.COM if ((ehdr.e_machine != M_MACH) &&
44112382SAli.Bahrami@Oracle.COM ((ehdr.e_flags & M_FLAGSPLUS) == 0)) {
44212382SAli.Bahrami@Oracle.COM (void) fprintf(stderr, MSG_INTL(MSG_ELF_MACHFLAGS),
44312382SAli.Bahrami@Oracle.COM cname, fname);
44412382SAli.Bahrami@Oracle.COM return (1);
44512382SAli.Bahrami@Oracle.COM }
44612382SAli.Bahrami@Oracle.COM break;
44712382SAli.Bahrami@Oracle.COM case ELFCLASS64:
44812382SAli.Bahrami@Oracle.COM /* Requires 64-bit kernel */
44912382SAli.Bahrami@Oracle.COM if (conv_sys_eclass() == ELFCLASS32) {
45012382SAli.Bahrami@Oracle.COM (void) fprintf(stderr, MSG_INTL(MSG_ELF_KCLASS32),
45112382SAli.Bahrami@Oracle.COM cname, fname, conv_ehdr_class(class, 0, &inv_buf));
45212382SAli.Bahrami@Oracle.COM return (1);
45312382SAli.Bahrami@Oracle.COM }
45412382SAli.Bahrami@Oracle.COM break;
45512382SAli.Bahrami@Oracle.COM default:
45612382SAli.Bahrami@Oracle.COM (void) fprintf(stderr, MSG_INTL(MSG_ELF_CLASS), cname, fname,
45712382SAli.Bahrami@Oracle.COM conv_ehdr_class(class, 0, &inv_buf));
45812382SAli.Bahrami@Oracle.COM return (1);
45912382SAli.Bahrami@Oracle.COM }
46012382SAli.Bahrami@Oracle.COM
46112382SAli.Bahrami@Oracle.COM /*
46212382SAli.Bahrami@Oracle.COM * Object type
4630Sstevel@tonic-gate */
4640Sstevel@tonic-gate if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN) &&
4650Sstevel@tonic-gate (ehdr.e_type != ET_REL)) {
4660Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_BADMAGIC),
4674947Srie cname, fname);
4680Sstevel@tonic-gate return (1);
4690Sstevel@tonic-gate }
4700Sstevel@tonic-gate
4710Sstevel@tonic-gate /*
4720Sstevel@tonic-gate * Check that the file is executable. Dynamic executables must be
4730Sstevel@tonic-gate * executable to be exec'ed. Shared objects need not be executable to
4740Sstevel@tonic-gate * be mapped with a dynamic executable, however, by convention they're
4750Sstevel@tonic-gate * supposed to be executable.
4760Sstevel@tonic-gate */
4770Sstevel@tonic-gate if (access(fname, X_OK) != 0) {
4780Sstevel@tonic-gate if (ehdr.e_type == ET_EXEC) {
4790Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USP_NOTEXEC_1),
4804947Srie cname, fname);
4810Sstevel@tonic-gate return (1);
4820Sstevel@tonic-gate }
4830Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USP_NOTEXEC_2), cname,
4840Sstevel@tonic-gate fname);
4850Sstevel@tonic-gate }
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate /*
4880Sstevel@tonic-gate * Determine whether we have a dynamic section or interpretor.
4890Sstevel@tonic-gate */
4900Sstevel@tonic-gate for (cnt = 0; cnt < (int)ehdr.e_phnum; cnt++) {
4910Sstevel@tonic-gate if (dynamic && interp)
4920Sstevel@tonic-gate break;
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate if (gelf_getphdr(elf, cnt, &phdr) == NULL) {
4950Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETPHDR),
4964947Srie cname, fname, elf_errmsg(-1));
4970Sstevel@tonic-gate return (1);
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate
5000Sstevel@tonic-gate if (phdr.p_type == PT_DYNAMIC) {
5010Sstevel@tonic-gate dynamic = 1;
5020Sstevel@tonic-gate continue;
5030Sstevel@tonic-gate }
5040Sstevel@tonic-gate
5050Sstevel@tonic-gate if (phdr.p_type != PT_INTERP)
5060Sstevel@tonic-gate continue;
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate interp = 1;
5090Sstevel@tonic-gate
5100Sstevel@tonic-gate /*
5110Sstevel@tonic-gate * If fflag is not set, and euid == root, and the interpreter
5120Sstevel@tonic-gate * does not live under /lib, /usr/lib or /etc/lib then don't
5130Sstevel@tonic-gate * allow ldd to execute the image. This prevents someone
5140Sstevel@tonic-gate * creating a `trojan horse' by substituting their own
5150Sstevel@tonic-gate * interpreter that could preform privileged operations
5160Sstevel@tonic-gate * when ldd is against it.
5170Sstevel@tonic-gate */
5180Sstevel@tonic-gate if ((fflag == 0) && (geteuid() == 0) &&
5190Sstevel@tonic-gate (strcmp(fname, conv_lddstub(class)) != 0)) {
5200Sstevel@tonic-gate char *interpreter;
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate /*
5230Sstevel@tonic-gate * Does the interpreter live under a trusted directory.
5240Sstevel@tonic-gate */
5250Sstevel@tonic-gate interpreter = elf_getident(elf, 0) + phdr.p_offset;
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate if ((strncmp(interpreter, MSG_ORIG(MSG_PTH_USRLIB),
5280Sstevel@tonic-gate MSG_PTH_USRLIB_SIZE) != 0) &&
5290Sstevel@tonic-gate (strncmp(interpreter, MSG_ORIG(MSG_PTH_LIB),
5300Sstevel@tonic-gate MSG_PTH_LIB_SIZE) != 0) &&
5310Sstevel@tonic-gate (strncmp(interpreter, MSG_ORIG(MSG_PTH_ETCLIB),
5320Sstevel@tonic-gate MSG_PTH_ETCLIB_SIZE) != 0)) {
5330Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USP_ELFINS),
5344947Srie cname, fname, interpreter);
5350Sstevel@tonic-gate return (1);
5360Sstevel@tonic-gate }
5370Sstevel@tonic-gate }
5380Sstevel@tonic-gate }
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate /*
5410Sstevel@tonic-gate * Catch the case of a static executable (ie, an ET_EXEC that has a set
5420Sstevel@tonic-gate * of program headers but no PT_DYNAMIC).
5430Sstevel@tonic-gate */
5440Sstevel@tonic-gate if (ehdr.e_phnum && !dynamic) {
5450Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USP_NODYNORSO), cname,
5460Sstevel@tonic-gate fname);
5470Sstevel@tonic-gate return (1);
5480Sstevel@tonic-gate }
5490Sstevel@tonic-gate
5501698Sab196087 /*
5511698Sab196087 * If there is a dynamic section, then check for the DF_1_NOHDR
55211734SAli.Bahrami@Sun.COM * flag, and bail if it is present. Such objects are created using
55311734SAli.Bahrami@Sun.COM * a mapfile option (?N in the version 1 syntax, or HDR_NOALLOC
55411734SAli.Bahrami@Sun.COM * otherwise). The ELF header and program headers are
5551698Sab196087 * not mapped as part of the first segment, and virtual addresses
5561698Sab196087 * are computed without them. If ldd tries to interpret such
5571698Sab196087 * a file, it will become confused and generate bad output or
5581698Sab196087 * crash. Such objects are always special purpose files (like an OS
5591698Sab196087 * kernel) --- files for which the ldd operation doesn't make sense.
5601698Sab196087 */
5611698Sab196087 if (dynamic && (_gelf_getdyndtflags_1(elf) & DF_1_NOHDR)) {
5621698Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USP_NOHDR), cname,
5631698Sab196087 fname);
5641698Sab196087 return (1);
5651698Sab196087 }
5661698Sab196087
5670Sstevel@tonic-gate load = load_elf;
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate /*
5700Sstevel@tonic-gate * Run the required program (shared and relocatable objects require the
5710Sstevel@tonic-gate * use of lddstub).
5720Sstevel@tonic-gate */
5730Sstevel@tonic-gate if ((ehdr.e_type == ET_EXEC) && interp)
5740Sstevel@tonic-gate return (run(nfile, cname, fname, (const char *)fname, class));
5750Sstevel@tonic-gate else
5760Sstevel@tonic-gate return (run(nfile, cname, fname, conv_lddstub(class), class));
5770Sstevel@tonic-gate }
5780Sstevel@tonic-gate
5790Sstevel@tonic-gate static int
aout_check(int nfile,char * fname,char * cname,int fd,int fflag)5800Sstevel@tonic-gate aout_check(int nfile, char *fname, char *cname, int fd, int fflag)
5810Sstevel@tonic-gate {
5826223Sab196087 struct exec32 aout;
5830Sstevel@tonic-gate int err;
5840Sstevel@tonic-gate
5850Sstevel@tonic-gate if (lseek(fd, 0, SEEK_SET) != 0) {
5860Sstevel@tonic-gate err = errno;
5870Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_LSEEK), cname, fname,
5880Sstevel@tonic-gate strerror(err));
5890Sstevel@tonic-gate return (1);
5900Sstevel@tonic-gate }
5916223Sab196087 if (read(fd, (char *)&aout, sizeof (aout)) != sizeof (aout)) {
5920Sstevel@tonic-gate err = errno;
5930Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_READ), cname, fname,
5940Sstevel@tonic-gate strerror(err));
5950Sstevel@tonic-gate return (1);
5960Sstevel@tonic-gate }
5970Sstevel@tonic-gate if (aout.a_machtype != M_SPARC) {
5980Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USP_UNKNOWN), cname, fname);
5990Sstevel@tonic-gate return (1);
6000Sstevel@tonic-gate }
6010Sstevel@tonic-gate if (N_BADMAG(aout) || !aout.a_dynamic) {
6020Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USP_NODYNORSO), cname,
6030Sstevel@tonic-gate fname);
6040Sstevel@tonic-gate return (1);
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate if (!fflag && (geteuid() == 0)) {
6070Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_USP_AOUTINS), cname, fname);
6080Sstevel@tonic-gate return (1);
6090Sstevel@tonic-gate }
6100Sstevel@tonic-gate
6110Sstevel@tonic-gate /*
6120Sstevel@tonic-gate * Run the required program.
6130Sstevel@tonic-gate */
6146223Sab196087 if ((aout.a_magic == ZMAGIC) && (aout.a_entry <= sizeof (aout))) {
6150Sstevel@tonic-gate load = load_elf;
6160Sstevel@tonic-gate return (run(nfile, cname, fname, conv_lddstub(ELFCLASS32),
6170Sstevel@tonic-gate ELFCLASS32));
6180Sstevel@tonic-gate } else {
6190Sstevel@tonic-gate load = load_aout;
6200Sstevel@tonic-gate return (run(nfile, cname, fname, (const char *)fname,
6210Sstevel@tonic-gate ELFCLASS32));
6220Sstevel@tonic-gate }
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate /*
6270Sstevel@tonic-gate * Run the required program, setting the preload and trace environment
6280Sstevel@tonic-gate * variables accordingly.
6290Sstevel@tonic-gate */
6300Sstevel@tonic-gate static int
run(int nfile,char * cname,char * fname,const char * ename,int class)6310Sstevel@tonic-gate run(int nfile, char *cname, char *fname, const char *ename, int class)
6320Sstevel@tonic-gate {
6330Sstevel@tonic-gate const char *preload = 0;
6340Sstevel@tonic-gate int pid, status;
6350Sstevel@tonic-gate
6360Sstevel@tonic-gate if ((pid = fork()) == -1) {
6370Sstevel@tonic-gate int err = errno;
6380Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_FORK), cname,
6390Sstevel@tonic-gate strerror(err));
6400Sstevel@tonic-gate return (1);
6410Sstevel@tonic-gate }
6420Sstevel@tonic-gate
6430Sstevel@tonic-gate if (pid) { /* parent */
6440Sstevel@tonic-gate while (wait(&status) != pid)
6450Sstevel@tonic-gate ;
6460Sstevel@tonic-gate if (WIFSIGNALED(status) && ((WSIGMASK & status) != SIGPIPE)) {
6470Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXEC), cname,
6480Sstevel@tonic-gate fname);
6490Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXEC_SIG),
6500Sstevel@tonic-gate (WSIGMASK & status), ((status & WCOREFLG) ?
6510Sstevel@tonic-gate MSG_INTL(MSG_SYS_EXEC_CORE) :
6520Sstevel@tonic-gate MSG_ORIG(MSG_STR_EMPTY)));
6530Sstevel@tonic-gate status = 1;
6540Sstevel@tonic-gate } else if (WHIBYTE(status)) {
6550Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXEC), cname,
6560Sstevel@tonic-gate fname);
6570Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXEC_STAT),
6580Sstevel@tonic-gate WHIBYTE(status));
6590Sstevel@tonic-gate status = 1;
6600Sstevel@tonic-gate }
6610Sstevel@tonic-gate } else { /* child */
6629131SRod.Evans@Sun.COM Aliste idx;
6639131SRod.Evans@Sun.COM char *str;
6649131SRod.Evans@Sun.COM size_t size;
6650Sstevel@tonic-gate
6660Sstevel@tonic-gate /*
6670Sstevel@tonic-gate * When using ldd(1) to analyze a shared object we preload the
6680Sstevel@tonic-gate * shared object with lddstub. Any additional preload
6690Sstevel@tonic-gate * requirements are added after the object being analyzed, this
6700Sstevel@tonic-gate * allows us to skip the first object but produce diagnostics
6710Sstevel@tonic-gate * for each other preloaded object.
6720Sstevel@tonic-gate */
6730Sstevel@tonic-gate if (fname != ename) {
6740Sstevel@tonic-gate char *str;
6750Sstevel@tonic-gate const char *files = prefile;
6760Sstevel@tonic-gate const char *format = MSG_ORIG(MSG_STR_FMT1);
6770Sstevel@tonic-gate
6780Sstevel@tonic-gate for (str = fname; *str; str++)
6790Sstevel@tonic-gate if (*str == '/') {
6800Sstevel@tonic-gate format = MSG_ORIG(MSG_STR_FMT2);
6810Sstevel@tonic-gate break;
6820Sstevel@tonic-gate }
6830Sstevel@tonic-gate
6840Sstevel@tonic-gate preload = MSG_ORIG(MSG_LD_PRELOAD);
6850Sstevel@tonic-gate
6860Sstevel@tonic-gate /*
6870Sstevel@tonic-gate * Determine which preload files and preload environment
6880Sstevel@tonic-gate * variable to use.
6890Sstevel@tonic-gate */
6900Sstevel@tonic-gate if (class == ELFCLASS64) {
6910Sstevel@tonic-gate if (prefile_64 != MSG_ORIG(MSG_STR_EMPTY)) {
6920Sstevel@tonic-gate files = prefile_64;
6930Sstevel@tonic-gate preload = MSG_ORIG(MSG_LD_PRELOAD_64);
6940Sstevel@tonic-gate }
6950Sstevel@tonic-gate } else {
6960Sstevel@tonic-gate if (prefile_32 != MSG_ORIG(MSG_STR_EMPTY)) {
6970Sstevel@tonic-gate files = prefile_32;
6980Sstevel@tonic-gate preload = MSG_ORIG(MSG_LD_PRELOAD_32);
6990Sstevel@tonic-gate }
7000Sstevel@tonic-gate }
7010Sstevel@tonic-gate
7020Sstevel@tonic-gate if ((str = (char *)malloc(strlen(preload) +
7030Sstevel@tonic-gate strlen(fname) + strlen(files) + 5)) == 0) {
7040Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_MALLOC),
7050Sstevel@tonic-gate cname);
7060Sstevel@tonic-gate exit(1);
7070Sstevel@tonic-gate }
7080Sstevel@tonic-gate
7090Sstevel@tonic-gate (void) sprintf(str, format, preload, fname, files);
7100Sstevel@tonic-gate if (putenv(str) != 0) {
7110Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ENV_FAILED),
7120Sstevel@tonic-gate cname);
7130Sstevel@tonic-gate exit(1);
7140Sstevel@tonic-gate }
7154947Srie
7164947Srie /*
7174947Srie * The pointer "load" has be assigned to load_elf[] or
7184947Srie * load_aout[]. Use the size of load_elf[] as the size
7194947Srie * of load_aout[] is the same.
7204947Srie */
7214947Srie load[sizeof (load_elf) - 2] = '2';
7220Sstevel@tonic-gate } else
7234947Srie load[sizeof (load_elf) - 2] = '1';
7240Sstevel@tonic-gate
7250Sstevel@tonic-gate
7260Sstevel@tonic-gate /*
7270Sstevel@tonic-gate * Establish new environment variables to affect the child
7280Sstevel@tonic-gate * process.
7290Sstevel@tonic-gate */
7300Sstevel@tonic-gate if ((putenv(warn) != 0) || (putenv(bind) != 0) ||
7310Sstevel@tonic-gate (putenv(path) != 0) || (putenv(verb) != 0) ||
7320Sstevel@tonic-gate (putenv(fltr) != 0) || (putenv(conf) != 0) ||
7330Sstevel@tonic-gate (putenv(init) != 0) || (putenv(lazy) != 0) ||
7340Sstevel@tonic-gate (putenv(uref) != 0) || (putenv(used) != 0) ||
7356150Srie (putenv(weak) != 0) || (putenv(load) != 0) ||
73612449SRod.Evans@Sun.COM (putenv(nope) != 0) || (putenv(defr) != 0)) {
7370Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ENV_FAILED), cname);
7380Sstevel@tonic-gate exit(1);
7390Sstevel@tonic-gate }
7400Sstevel@tonic-gate
7410Sstevel@tonic-gate /*
7420Sstevel@tonic-gate * Establish explicit environment requires (but don't override
7430Sstevel@tonic-gate * any preload request established to process a shared object).
7440Sstevel@tonic-gate */
7450Sstevel@tonic-gate size = 0;
7469131SRod.Evans@Sun.COM for (APLIST_TRAVERSE(eopts, idx, str)) {
7470Sstevel@tonic-gate if (preload) {
7480Sstevel@tonic-gate if (size == 0)
7490Sstevel@tonic-gate size = strlen(preload);
7500Sstevel@tonic-gate if ((strncmp(preload, str, size) == 0) &&
7510Sstevel@tonic-gate (str[size] == '=')) {
7520Sstevel@tonic-gate continue;
7530Sstevel@tonic-gate }
7540Sstevel@tonic-gate }
7550Sstevel@tonic-gate if (putenv(str) != 0) {
7560Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ENV_FAILED),
7570Sstevel@tonic-gate cname);
7580Sstevel@tonic-gate exit(1);
7590Sstevel@tonic-gate }
7600Sstevel@tonic-gate }
7610Sstevel@tonic-gate
7620Sstevel@tonic-gate /*
7630Sstevel@tonic-gate * Execute the object and let ld.so.1 do the rest.
7640Sstevel@tonic-gate */
7650Sstevel@tonic-gate if (nfile > 1)
7660Sstevel@tonic-gate (void) printf(MSG_ORIG(MSG_STR_FMT3), fname);
7670Sstevel@tonic-gate (void) fflush(stdout);
7680Sstevel@tonic-gate if ((execl(ename, ename, (char *)0)) == -1) {
7690Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXEC), cname,
7700Sstevel@tonic-gate fname);
7710Sstevel@tonic-gate perror(ename);
7720Sstevel@tonic-gate _exit(0);
7730Sstevel@tonic-gate /* NOTREACHED */
7740Sstevel@tonic-gate }
7750Sstevel@tonic-gate }
7760Sstevel@tonic-gate return (status);
7770Sstevel@tonic-gate }
7780Sstevel@tonic-gate
7790Sstevel@tonic-gate const char *
_ldd_msg(Msg mid)7800Sstevel@tonic-gate _ldd_msg(Msg mid)
7810Sstevel@tonic-gate {
7820Sstevel@tonic-gate return (gettext(MSG_ORIG(mid)));
7830Sstevel@tonic-gate }
784