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