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