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