xref: /freebsd/usr.bin/ldd/ldd.c (revision d138df6140a3452c0625ce238565e1dae56f8bfd)
1b9ae52e3SPaul Richards /*
2b9ae52e3SPaul Richards  * Copyright (c) 1993 Paul Kranenburg
3b9ae52e3SPaul Richards  * All rights reserved.
4b9ae52e3SPaul Richards  *
5b9ae52e3SPaul Richards  * Redistribution and use in source and binary forms, with or without
6b9ae52e3SPaul Richards  * modification, are permitted provided that the following conditions
7b9ae52e3SPaul Richards  * are met:
8b9ae52e3SPaul Richards  * 1. Redistributions of source code must retain the above copyright
9b9ae52e3SPaul Richards  *    notice, this list of conditions and the following disclaimer.
10b9ae52e3SPaul Richards  * 2. Redistributions in binary form must reproduce the above copyright
11b9ae52e3SPaul Richards  *    notice, this list of conditions and the following disclaimer in the
12b9ae52e3SPaul Richards  *    documentation and/or other materials provided with the distribution.
13b9ae52e3SPaul Richards  * 3. All advertising materials mentioning features or use of this software
14b9ae52e3SPaul Richards  *    must display the following acknowledgement:
15b9ae52e3SPaul Richards  *      This product includes software developed by Paul Kranenburg.
16b9ae52e3SPaul Richards  * 4. The name of the author may not be used to endorse or promote products
1709e3d49dSJordan K. Hubbard  *    derived from this software without specific prior written permission
18b9ae52e3SPaul Richards  *
19b9ae52e3SPaul Richards  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20b9ae52e3SPaul Richards  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21b9ae52e3SPaul Richards  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22b9ae52e3SPaul Richards  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23b9ae52e3SPaul Richards  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24b9ae52e3SPaul Richards  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25b9ae52e3SPaul Richards  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26b9ae52e3SPaul Richards  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27b9ae52e3SPaul Richards  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28b9ae52e3SPaul Richards  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29b9ae52e3SPaul Richards  *
30d138df61SPeter Wemm  *	$Id: ldd.c,v 1.5 1994/12/23 22:31:31 nate Exp $
31b9ae52e3SPaul Richards  */
32b9ae52e3SPaul Richards 
33b9ae52e3SPaul Richards #include <sys/types.h>
34b9ae52e3SPaul Richards #include <sys/stat.h>
35b9ae52e3SPaul Richards #include <sys/file.h>
36b9ae52e3SPaul Richards #include <sys/time.h>
37b9ae52e3SPaul Richards #include <sys/resource.h>
38b9ae52e3SPaul Richards #include <sys/wait.h>
39b9ae52e3SPaul Richards #include <a.out.h>
40699e1b82SRich Murphey #include <err.h>
41699e1b82SRich Murphey #include <fcntl.h>
42699e1b82SRich Murphey #include <stdio.h>
43699e1b82SRich Murphey #include <stdlib.h>
44699e1b82SRich Murphey #include <string.h>
45699e1b82SRich Murphey #include <unistd.h>
46b9ae52e3SPaul Richards 
47b9ae52e3SPaul Richards void
48b9ae52e3SPaul Richards usage()
49b9ae52e3SPaul Richards {
50699e1b82SRich Murphey 	extern char *__progname;
51699e1b82SRich Murphey 
52699e1b82SRich Murphey 	fprintf(stderr, "Usage: %s <filename> ...\n", __progname);
53699e1b82SRich Murphey 	exit(1);
54b9ae52e3SPaul Richards }
55b9ae52e3SPaul Richards 
56b9ae52e3SPaul Richards int
57b9ae52e3SPaul Richards main(argc, argv)
58b9ae52e3SPaul Richards int	argc;
59b9ae52e3SPaul Richards char	*argv[];
60b9ae52e3SPaul Richards {
61d138df61SPeter Wemm 	char		*fmt1 = NULL, *fmt2 = NULL;
62699e1b82SRich Murphey 	int		rval;
63b9ae52e3SPaul Richards 	int		c;
64b9ae52e3SPaul Richards 
65d138df61SPeter Wemm 	while ((c = getopt(argc, argv, "f:")) != EOF) {
66b9ae52e3SPaul Richards 		switch (c) {
67d138df61SPeter Wemm 		case 'f':
68d138df61SPeter Wemm 			if (fmt1) {
69d138df61SPeter Wemm 				if (fmt2)
70d138df61SPeter Wemm 					errx(1, "Too many formats");
71d138df61SPeter Wemm 				fmt2 = optarg;
72d138df61SPeter Wemm 			} else
73d138df61SPeter Wemm 				fmt1 = optarg;
74d138df61SPeter Wemm 			break;
75b9ae52e3SPaul Richards 		default:
76b9ae52e3SPaul Richards 			usage();
77699e1b82SRich Murphey 			/*NOTREACHED*/
78b9ae52e3SPaul Richards 		}
79b9ae52e3SPaul Richards 	}
80b9ae52e3SPaul Richards 	argc -= optind;
81b9ae52e3SPaul Richards 	argv += optind;
82b9ae52e3SPaul Richards 
83b9ae52e3SPaul Richards 	if (argc <= 0) {
84b9ae52e3SPaul Richards 		usage();
85699e1b82SRich Murphey 		/*NOTREACHED*/
86b9ae52e3SPaul Richards 	}
87b9ae52e3SPaul Richards 
88b9ae52e3SPaul Richards 	/* ld.so magic */
89b9ae52e3SPaul Richards 	setenv("LD_TRACE_LOADED_OBJECTS", "", 1);
90d138df61SPeter Wemm 	if (fmt1)
91d138df61SPeter Wemm 		setenv("LD_TRACE_LOADED_OBJECTS_FMT1", fmt1, 1);
92d138df61SPeter Wemm 	if (fmt2)
93d138df61SPeter Wemm 		setenv("LD_TRACE_LOADED_OBJECTS_FMT2", fmt2, 1);
94b9ae52e3SPaul Richards 
95699e1b82SRich Murphey 	rval = 0;
96b9ae52e3SPaul Richards 	while (argc--) {
97b9ae52e3SPaul Richards 		int	fd;
98b9ae52e3SPaul Richards 		struct exec hdr;
99b9ae52e3SPaul Richards 		int	status;
100b9ae52e3SPaul Richards 
101b9ae52e3SPaul Richards 		if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
102699e1b82SRich Murphey 			warn("%s", *argv);
103b9ae52e3SPaul Richards 			rval |= 1;
104b9ae52e3SPaul Richards 			argv++;
105b9ae52e3SPaul Richards 			continue;
106b9ae52e3SPaul Richards 		}
10761f9ce8dSNate Williams 		if (read(fd, &hdr, sizeof hdr) != sizeof hdr
10861f9ce8dSNate Williams 		    || (N_GETFLAG(hdr) & EX_DPMASK) != EX_DYNAMIC
10961f9ce8dSNate Williams #if 1 /* Compatibility */
11061f9ce8dSNate Williams 		    || hdr.a_entry < __LDPGSZ
11161f9ce8dSNate Williams #endif
11261f9ce8dSNate Williams 		    ) {
113699e1b82SRich Murphey 
114699e1b82SRich Murphey 			warnx("%s: not a dynamic executable", *argv);
115b9ae52e3SPaul Richards 			(void)close(fd);
116b9ae52e3SPaul Richards 			rval |= 1;
117b9ae52e3SPaul Richards 			argv++;
118b9ae52e3SPaul Richards 			continue;
119b9ae52e3SPaul Richards 		}
120b9ae52e3SPaul Richards 		(void)close(fd);
121b9ae52e3SPaul Richards 
122d138df61SPeter Wemm 		setenv("LD_TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1);
123d138df61SPeter Wemm 		if (fmt1 == NULL && fmt2 == NULL)
124d138df61SPeter Wemm 			/* Default formats */
125b9ae52e3SPaul Richards 			printf("%s:\n", *argv);
126d138df61SPeter Wemm 
12709e3d49dSJordan K. Hubbard 		fflush(stdout);
128b9ae52e3SPaul Richards 
129b9ae52e3SPaul Richards 		switch (fork()) {
130b9ae52e3SPaul Richards 		case -1:
131699e1b82SRich Murphey 			err(1, "fork");
132b9ae52e3SPaul Richards 			break;
133b9ae52e3SPaul Richards 		default:
134699e1b82SRich Murphey 			if (wait(&status) <= 0) {
135699e1b82SRich Murphey 				warn("wait");
136699e1b82SRich Murphey 				rval |= 1;
137699e1b82SRich Murphey 			} else if (WIFSIGNALED(status)) {
138b9ae52e3SPaul Richards 				fprintf(stderr, "%s: signal %d\n",
139b9ae52e3SPaul Richards 						*argv, WTERMSIG(status));
140b9ae52e3SPaul Richards 				rval |= 1;
141b9ae52e3SPaul Richards 			} else if (WIFEXITED(status) && WEXITSTATUS(status)) {
142b9ae52e3SPaul Richards 				fprintf(stderr, "%s: exit status %d\n",
143b9ae52e3SPaul Richards 						*argv, WEXITSTATUS(status));
144b9ae52e3SPaul Richards 				rval |= 1;
145b9ae52e3SPaul Richards 			}
146b9ae52e3SPaul Richards 			break;
147b9ae52e3SPaul Richards 		case 0:
148699e1b82SRich Murphey 			rval |= execl(*argv, *argv, NULL) != 0;
149b9ae52e3SPaul Richards 			perror(*argv);
150b9ae52e3SPaul Richards 			_exit(1);
151b9ae52e3SPaul Richards 		}
152b9ae52e3SPaul Richards 		argv++;
153b9ae52e3SPaul Richards 	}
154b9ae52e3SPaul Richards 
155b9ae52e3SPaul Richards 	return rval;
156b9ae52e3SPaul Richards }
157