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