xref: /freebsd/usr.bin/ldd/ldd.c (revision a94a4b74bdd9f9fa2cd9ec7f782fd6ed394e76ab)
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  */
30b9ae52e3SPaul Richards 
31a53809fdSMark Murray #include <sys/cdefs.h>
32a53809fdSMark Murray __FBSDID("$FreeBSD$");
333e762626SPhilippe Charnier 
34b9ae52e3SPaul Richards #include <sys/wait.h>
35a53809fdSMark Murray 
365e6220d9SDavid E. O'Brien #include <machine/elf.h>
37a53809fdSMark Murray 
38a2cfdda8SMike Barcroft #include <arpa/inet.h>
39a53809fdSMark Murray 
40b9ae52e3SPaul Richards #include <a.out.h>
41c6de4ce7SMaxim Sobolev #include <dlfcn.h>
42699e1b82SRich Murphey #include <err.h>
43fffd993dSEdwin Groothuis #include <errno.h>
44699e1b82SRich Murphey #include <fcntl.h>
45699e1b82SRich Murphey #include <stdio.h>
46699e1b82SRich Murphey #include <stdlib.h>
47e68ed793SJohn Baldwin #include <string.h>
48699e1b82SRich Murphey #include <unistd.h>
49b9ae52e3SPaul Richards 
50a53809fdSMark Murray #include "extern.h"
519731d137SPeter Wemm 
528bd833ffSEdwin Groothuis /*
53bff71350SEdwin Groothuis  * 32-bit ELF data structures can only be used if the system header[s] declare
54bff71350SEdwin Groothuis  * them.  There is no official macro for determining whether they are declared,
55bff71350SEdwin Groothuis  * so check for the existence of one of the 32-macros defined in elf(5).
568bd833ffSEdwin Groothuis  */
57bff71350SEdwin Groothuis #ifdef ELF32_R_TYPE
588bd833ffSEdwin Groothuis #define	ELF32_SUPPORTED
598bd833ffSEdwin Groothuis #endif
608bd833ffSEdwin Groothuis 
61*a94a4b74SMark Johnston #define	LDD_SETENV(name, value, overwrite) do {		\
62*a94a4b74SMark Johnston 	setenv("LD_" name, value, overwrite);		\
63*a94a4b74SMark Johnston 	setenv("LD_32_" name, value, overwrite);	\
64*a94a4b74SMark Johnston } while (0)
65*a94a4b74SMark Johnston 
66*a94a4b74SMark Johnston #define	LDD_UNSETENV(name) do {		\
67*a94a4b74SMark Johnston 	unsetenv("LD_" name);		\
68*a94a4b74SMark Johnston 	unsetenv("LD_32_" name);	\
69*a94a4b74SMark Johnston } while (0)
70*a94a4b74SMark Johnston 
71d3c1e14bSEdwin Groothuis static int	is_executable(const char *fname, int fd, int *is_shlib,
72d3c1e14bSEdwin Groothuis 		    int *type);
73d3c1e14bSEdwin Groothuis static void	usage(void);
74a0d476a9SEdwin Groothuis 
75d3c1e14bSEdwin Groothuis #define	TYPE_UNKNOWN	0
76d3c1e14bSEdwin Groothuis #define	TYPE_AOUT	1
77d3c1e14bSEdwin Groothuis #define	TYPE_ELF	2	/* Architecture default */
788bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
79fffd993dSEdwin Groothuis #define	TYPE_ELF32	3	/* Explicit 32 bits on architectures >32 bits */
80d3c1e14bSEdwin Groothuis 
81e68ed793SJohn Baldwin #define	_PATH_LDD32	"/usr/bin/ldd32"
82d3c1e14bSEdwin Groothuis 
83e68ed793SJohn Baldwin static int
84e68ed793SJohn Baldwin execldd32(char *file, char *fmt1, char *fmt2, int aflag, int vflag)
85e68ed793SJohn Baldwin {
86e68ed793SJohn Baldwin 	char *argv[8];
87e68ed793SJohn Baldwin 	int i, rval, status;
88e68ed793SJohn Baldwin 
89*a94a4b74SMark Johnston 	LDD_UNSETENV("TRACE_LOADED_OBJECTS");
90e68ed793SJohn Baldwin 	rval = 0;
91e68ed793SJohn Baldwin 	i = 0;
92e68ed793SJohn Baldwin 	argv[i++] = strdup(_PATH_LDD32);
93e68ed793SJohn Baldwin 	if (aflag)
94e68ed793SJohn Baldwin 		argv[i++] = strdup("-a");
95e68ed793SJohn Baldwin 	if (vflag)
96e68ed793SJohn Baldwin 		argv[i++] = strdup("-v");
9752122f31SJohn Baldwin 	if (fmt1 != NULL) {
98e68ed793SJohn Baldwin 		argv[i++] = strdup("-f");
99e68ed793SJohn Baldwin 		argv[i++] = strdup(fmt1);
100e68ed793SJohn Baldwin 	}
10152122f31SJohn Baldwin 	if (fmt2 != NULL) {
102e68ed793SJohn Baldwin 		argv[i++] = strdup("-f");
103e68ed793SJohn Baldwin 		argv[i++] = strdup(fmt2);
104e68ed793SJohn Baldwin 	}
105e68ed793SJohn Baldwin 	argv[i++] = strdup(file);
106e68ed793SJohn Baldwin 	argv[i++] = NULL;
107e68ed793SJohn Baldwin 
108e68ed793SJohn Baldwin 	switch (fork()) {
109e68ed793SJohn Baldwin 	case -1:
110e68ed793SJohn Baldwin 		err(1, "fork");
111e68ed793SJohn Baldwin 		break;
112e68ed793SJohn Baldwin 	case 0:
113e68ed793SJohn Baldwin 		execv(_PATH_LDD32, argv);
114e68ed793SJohn Baldwin 		warn("%s", _PATH_LDD32);
11552122f31SJohn Baldwin 		_exit(127);
116e68ed793SJohn Baldwin 		break;
117e68ed793SJohn Baldwin 	default:
11852122f31SJohn Baldwin 		if (wait(&status) < 0)
119e68ed793SJohn Baldwin 			rval = 1;
12052122f31SJohn Baldwin 		else if (WIFSIGNALED(status))
121e68ed793SJohn Baldwin 			rval = 1;
12252122f31SJohn Baldwin 		else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
123e68ed793SJohn Baldwin 			rval = 1;
124e68ed793SJohn Baldwin 		break;
125e68ed793SJohn Baldwin 	}
126e68ed793SJohn Baldwin 	while (i--)
127e68ed793SJohn Baldwin 		free(argv[i]);
128*a94a4b74SMark Johnston 	LDD_SETENV("TRACE_LOADED_OBJECTS", "yes", 1);
129e68ed793SJohn Baldwin 	return (rval);
130e68ed793SJohn Baldwin }
131fffd993dSEdwin Groothuis #endif
132b9ae52e3SPaul Richards 
133b9ae52e3SPaul Richards int
134a53809fdSMark Murray main(int argc, char *argv[])
135b9ae52e3SPaul Richards {
136a0d476a9SEdwin Groothuis 	char *fmt1, *fmt2;
137a0d476a9SEdwin Groothuis 	int rval, c, aflag, vflag;
138b9ae52e3SPaul Richards 
13920249943SDavid E. O'Brien 	aflag = vflag = 0;
140a0d476a9SEdwin Groothuis 	fmt1 = fmt2 = NULL;
14120249943SDavid E. O'Brien 
142a0d476a9SEdwin Groothuis 	while ((c = getopt(argc, argv, "af:v")) != -1) {
143b9ae52e3SPaul Richards 		switch (c) {
14420249943SDavid E. O'Brien 		case 'a':
14520249943SDavid E. O'Brien 			aflag++;
14620249943SDavid E. O'Brien 			break;
147d138df61SPeter Wemm 		case 'f':
148a0d476a9SEdwin Groothuis 			if (fmt1 != NULL) {
149a0d476a9SEdwin Groothuis 				if (fmt2 != NULL)
1503e762626SPhilippe Charnier 					errx(1, "too many formats");
151d138df61SPeter Wemm 				fmt2 = optarg;
152d138df61SPeter Wemm 			} else
153d138df61SPeter Wemm 				fmt1 = optarg;
154d138df61SPeter Wemm 			break;
155a0d476a9SEdwin Groothuis 		case 'v':
156a0d476a9SEdwin Groothuis 			vflag++;
157a0d476a9SEdwin Groothuis 			break;
158b9ae52e3SPaul Richards 		default:
159b9ae52e3SPaul Richards 			usage();
160699e1b82SRich Murphey 			/* NOTREACHED */
161b9ae52e3SPaul Richards 		}
162b9ae52e3SPaul Richards 	}
163b9ae52e3SPaul Richards 	argc -= optind;
164b9ae52e3SPaul Richards 	argv += optind;
165b9ae52e3SPaul Richards 
166a0d476a9SEdwin Groothuis 	if (vflag && fmt1 != NULL)
1679731d137SPeter Wemm 		errx(1, "-v may not be used with -f");
1689731d137SPeter Wemm 
169b9ae52e3SPaul Richards 	if (argc <= 0) {
170b9ae52e3SPaul Richards 		usage();
171699e1b82SRich Murphey 		/* NOTREACHED */
172b9ae52e3SPaul Richards 	}
173b9ae52e3SPaul Richards 
17497db68b6SDoug Rabson #ifdef __i386__
1759731d137SPeter Wemm 	if (vflag) {
1769731d137SPeter Wemm 		for (c = 0; c < argc; c++)
1779731d137SPeter Wemm 			dump_file(argv[c]);
1789731d137SPeter Wemm 		exit(error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
1799731d137SPeter Wemm 	}
18097db68b6SDoug Rabson #endif
1819731d137SPeter Wemm 
182699e1b82SRich Murphey 	rval = 0;
183e2daa140SJohn Polstra 	for (; argc > 0; argc--, argv++) {
184d3c1e14bSEdwin Groothuis 		int fd, status, is_shlib, rv, type;
185d3c1e14bSEdwin Groothuis 
186b9ae52e3SPaul Richards 		if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
187699e1b82SRich Murphey 			warn("%s", *argv);
188b9ae52e3SPaul Richards 			rval |= 1;
189b9ae52e3SPaul Richards 			continue;
190b9ae52e3SPaul Richards 		}
191d3c1e14bSEdwin Groothuis 		rv = is_executable(*argv, fd, &is_shlib, &type);
192a0d476a9SEdwin Groothuis 		close(fd);
193d3c1e14bSEdwin Groothuis 		if (rv == 0) {
194c474c6d3SDoug Rabson 			rval |= 1;
195c474c6d3SDoug Rabson 			continue;
196c474c6d3SDoug Rabson 		}
197c474c6d3SDoug Rabson 
198fffd993dSEdwin Groothuis 		switch (type) {
199fffd993dSEdwin Groothuis 		case TYPE_ELF:
200fffd993dSEdwin Groothuis 		case TYPE_AOUT:
201fffd993dSEdwin Groothuis 			break;
2028bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
203fffd993dSEdwin Groothuis 		case TYPE_ELF32:
204e68ed793SJohn Baldwin 			rval |= execldd32(*argv, fmt1, fmt2, aflag, vflag);
205e68ed793SJohn Baldwin 			continue;
206fffd993dSEdwin Groothuis #endif
207fffd993dSEdwin Groothuis 		case TYPE_UNKNOWN:
208fffd993dSEdwin Groothuis 		default:
209fffd993dSEdwin Groothuis 			/*
210fffd993dSEdwin Groothuis 			 * This shouldn't happen unless is_executable()
211fffd993dSEdwin Groothuis 			 * is broken.
212fffd993dSEdwin Groothuis 			 */
213fffd993dSEdwin Groothuis 			errx(EDOOFUS, "unknown executable type");
214fffd993dSEdwin Groothuis 		}
215fffd993dSEdwin Groothuis 
216d3c1e14bSEdwin Groothuis 		/* ld.so magic */
217*a94a4b74SMark Johnston 		LDD_SETENV("TRACE_LOADED_OBJECTS", "yes", 1);
218d3c1e14bSEdwin Groothuis 		if (fmt1 != NULL)
219*a94a4b74SMark Johnston 			LDD_SETENV("TRACE_LOADED_OBJECTS_FMT1", fmt1, 1);
220d3c1e14bSEdwin Groothuis 		if (fmt2 != NULL)
221*a94a4b74SMark Johnston 			LDD_SETENV("TRACE_LOADED_OBJECTS_FMT2", fmt2, 1);
222a0d476a9SEdwin Groothuis 
223*a94a4b74SMark Johnston 		LDD_SETENV("TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1);
224a0d476a9SEdwin Groothuis 		if (aflag)
225*a94a4b74SMark Johnston 			LDD_SETENV("TRACE_LOADED_OBJECTS_ALL", "1", 1);
22620249943SDavid E. O'Brien 		else if (fmt1 == NULL && fmt2 == NULL)
227d138df61SPeter Wemm 			/* Default formats */
228b9ae52e3SPaul Richards 			printf("%s:\n", *argv);
22909e3d49dSJordan K. Hubbard 		fflush(stdout);
230b9ae52e3SPaul Richards 
231b9ae52e3SPaul Richards 		switch (fork()) {
232b9ae52e3SPaul Richards 		case -1:
233699e1b82SRich Murphey 			err(1, "fork");
234b9ae52e3SPaul Richards 			break;
235b9ae52e3SPaul Richards 		default:
23652122f31SJohn Baldwin 			if (wait(&status) < 0) {
237699e1b82SRich Murphey 				warn("wait");
238699e1b82SRich Murphey 				rval |= 1;
239699e1b82SRich Murphey 			} else if (WIFSIGNALED(status)) {
240a0d476a9SEdwin Groothuis 				fprintf(stderr, "%s: signal %d\n", *argv,
241a0d476a9SEdwin Groothuis 				    WTERMSIG(status));
242b9ae52e3SPaul Richards 				rval |= 1;
24352122f31SJohn Baldwin 			} else if (WIFEXITED(status) &&
24452122f31SJohn Baldwin 			    WEXITSTATUS(status) != 0) {
245a0d476a9SEdwin Groothuis 				fprintf(stderr, "%s: exit status %d\n", *argv,
246a0d476a9SEdwin Groothuis 				    WEXITSTATUS(status));
247b9ae52e3SPaul Richards 				rval |= 1;
248b9ae52e3SPaul Richards 			}
249b9ae52e3SPaul Richards 			break;
250b9ae52e3SPaul Richards 		case 0:
251d1cf9ea2SMaxim Sobolev 			if (is_shlib == 0) {
252fc41545eSMaxim Sobolev 				execl(*argv, *argv, (char *)NULL);
2533e762626SPhilippe Charnier 				warn("%s", *argv);
254d1cf9ea2SMaxim Sobolev 			} else {
255d1cf9ea2SMaxim Sobolev 				dlopen(*argv, RTLD_TRACE);
256d1cf9ea2SMaxim Sobolev 				warnx("%s: %s", *argv, dlerror());
257c6de4ce7SMaxim Sobolev 			}
258b9ae52e3SPaul Richards 			_exit(1);
259b9ae52e3SPaul Richards 		}
260b9ae52e3SPaul Richards 	}
261b9ae52e3SPaul Richards 
262b9ae52e3SPaul Richards 	return rval;
263b9ae52e3SPaul Richards }
264d3c1e14bSEdwin Groothuis 
265d3c1e14bSEdwin Groothuis static void
266d3c1e14bSEdwin Groothuis usage(void)
267d3c1e14bSEdwin Groothuis {
268d3c1e14bSEdwin Groothuis 
269d3c1e14bSEdwin Groothuis 	fprintf(stderr, "usage: ldd [-a] [-v] [-f format] program ...\n");
270d3c1e14bSEdwin Groothuis 	exit(1);
271d3c1e14bSEdwin Groothuis }
272d3c1e14bSEdwin Groothuis 
273d3c1e14bSEdwin Groothuis static int
274d3c1e14bSEdwin Groothuis is_executable(const char *fname, int fd, int *is_shlib, int *type)
275d3c1e14bSEdwin Groothuis {
276d3c1e14bSEdwin Groothuis 	union {
277d3c1e14bSEdwin Groothuis 		struct exec aout;
2788bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
279fffd993dSEdwin Groothuis 		Elf32_Ehdr elf32;
2808bd833ffSEdwin Groothuis #endif
281d3c1e14bSEdwin Groothuis 		Elf_Ehdr elf;
282d3c1e14bSEdwin Groothuis 	} hdr;
283d3c1e14bSEdwin Groothuis 	int n;
284d3c1e14bSEdwin Groothuis 
285d3c1e14bSEdwin Groothuis 	*is_shlib = 0;
286d3c1e14bSEdwin Groothuis 	*type = TYPE_UNKNOWN;
287d3c1e14bSEdwin Groothuis 
288d3c1e14bSEdwin Groothuis 	if ((n = read(fd, &hdr, sizeof(hdr))) == -1) {
289d3c1e14bSEdwin Groothuis 		warn("%s: can't read program header", fname);
290d3c1e14bSEdwin Groothuis 		return (0);
291d3c1e14bSEdwin Groothuis 	}
292d3c1e14bSEdwin Groothuis 
293d3c1e14bSEdwin Groothuis 	if ((size_t)n >= sizeof(hdr.aout) && !N_BADMAG(hdr.aout)) {
294d3c1e14bSEdwin Groothuis 		/* a.out file */
295d3c1e14bSEdwin Groothuis 		if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC
296d3c1e14bSEdwin Groothuis #if 1 /* Compatibility */
297d3c1e14bSEdwin Groothuis 		    || hdr.aout.a_entry < __LDPGSZ
298d3c1e14bSEdwin Groothuis #endif
299d3c1e14bSEdwin Groothuis 			) {
300d3c1e14bSEdwin Groothuis 			warnx("%s: not a dynamic executable", fname);
301d3c1e14bSEdwin Groothuis 			return (0);
302d3c1e14bSEdwin Groothuis 		}
303d3c1e14bSEdwin Groothuis 		*type = TYPE_AOUT;
304d3c1e14bSEdwin Groothuis 		return (1);
305d3c1e14bSEdwin Groothuis 	}
306d3c1e14bSEdwin Groothuis 
3078bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
308fffd993dSEdwin Groothuis 	if ((size_t)n >= sizeof(hdr.elf32) && IS_ELF(hdr.elf32) &&
309fffd993dSEdwin Groothuis 	    hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
310fffd993dSEdwin Groothuis 		/* Handle 32 bit ELF objects */
311fffd993dSEdwin Groothuis 		Elf32_Phdr phdr;
312fffd993dSEdwin Groothuis 		int dynamic, i;
313fffd993dSEdwin Groothuis 
314fffd993dSEdwin Groothuis 		dynamic = 0;
315fffd993dSEdwin Groothuis 		*type = TYPE_ELF32;
316fffd993dSEdwin Groothuis 
317fffd993dSEdwin Groothuis 		if (lseek(fd, hdr.elf32.e_phoff, SEEK_SET) == -1) {
318fffd993dSEdwin Groothuis 			warnx("%s: header too short", fname);
319fffd993dSEdwin Groothuis 			return (0);
320fffd993dSEdwin Groothuis 		}
321fffd993dSEdwin Groothuis 		for (i = 0; i < hdr.elf32.e_phnum; i++) {
322fffd993dSEdwin Groothuis 			if (read(fd, &phdr, hdr.elf32.e_phentsize) !=
323fffd993dSEdwin Groothuis 			    sizeof(phdr)) {
324fffd993dSEdwin Groothuis 				warnx("%s: can't read program header", fname);
325fffd993dSEdwin Groothuis 				return (0);
326fffd993dSEdwin Groothuis 			}
327fffd993dSEdwin Groothuis 			if (phdr.p_type == PT_DYNAMIC) {
328fffd993dSEdwin Groothuis 				dynamic = 1;
329fffd993dSEdwin Groothuis 				break;
330fffd993dSEdwin Groothuis 			}
331fffd993dSEdwin Groothuis 		}
332fffd993dSEdwin Groothuis 
333fffd993dSEdwin Groothuis 		if (!dynamic) {
334fffd993dSEdwin Groothuis 			warnx("%s: not a dynamic ELF executable", fname);
335fffd993dSEdwin Groothuis 			return (0);
336fffd993dSEdwin Groothuis 		}
337fffd993dSEdwin Groothuis 		if (hdr.elf32.e_type == ET_DYN) {
33870557f4fSRebecca Cran 			if (hdr.elf32.e_ident[EI_OSABI] == ELFOSABI_FREEBSD) {
339fffd993dSEdwin Groothuis 				*is_shlib = 1;
340fffd993dSEdwin Groothuis 				return (1);
341fffd993dSEdwin Groothuis 			}
342fffd993dSEdwin Groothuis 			warnx("%s: not a FreeBSD ELF shared object", fname);
343fffd993dSEdwin Groothuis 			return (0);
344fffd993dSEdwin Groothuis 		}
345fffd993dSEdwin Groothuis 
346fffd993dSEdwin Groothuis 		return (1);
347fffd993dSEdwin Groothuis 	}
348fffd993dSEdwin Groothuis #endif
349fffd993dSEdwin Groothuis 
350d3c1e14bSEdwin Groothuis 	if ((size_t)n >= sizeof(hdr.elf) && IS_ELF(hdr.elf) &&
351d3c1e14bSEdwin Groothuis 	    hdr.elf.e_ident[EI_CLASS] == ELF_TARG_CLASS) {
352d3c1e14bSEdwin Groothuis 		/* Handle default ELF objects on this architecture */
353d3c1e14bSEdwin Groothuis 		Elf_Phdr phdr;
354d3c1e14bSEdwin Groothuis 		int dynamic, i;
355d3c1e14bSEdwin Groothuis 
356d3c1e14bSEdwin Groothuis 		dynamic = 0;
357d3c1e14bSEdwin Groothuis 		*type = TYPE_ELF;
358d3c1e14bSEdwin Groothuis 
359d3c1e14bSEdwin Groothuis 		if (lseek(fd, hdr.elf.e_phoff, SEEK_SET) == -1) {
360d3c1e14bSEdwin Groothuis 			warnx("%s: header too short", fname);
361d3c1e14bSEdwin Groothuis 			return (0);
362d3c1e14bSEdwin Groothuis 		}
363d3c1e14bSEdwin Groothuis 		for (i = 0; i < hdr.elf.e_phnum; i++) {
364d3c1e14bSEdwin Groothuis 			if (read(fd, &phdr, hdr.elf.e_phentsize)
365d3c1e14bSEdwin Groothuis 			   != sizeof(phdr)) {
366d3c1e14bSEdwin Groothuis 				warnx("%s: can't read program header", fname);
367d3c1e14bSEdwin Groothuis 				return (0);
368d3c1e14bSEdwin Groothuis 			}
369d3c1e14bSEdwin Groothuis 			if (phdr.p_type == PT_DYNAMIC) {
370d3c1e14bSEdwin Groothuis 				dynamic = 1;
371d3c1e14bSEdwin Groothuis 				break;
372d3c1e14bSEdwin Groothuis 			}
373d3c1e14bSEdwin Groothuis 		}
374d3c1e14bSEdwin Groothuis 
375d3c1e14bSEdwin Groothuis 		if (!dynamic) {
376d3c1e14bSEdwin Groothuis 			warnx("%s: not a dynamic ELF executable", fname);
377d3c1e14bSEdwin Groothuis 			return (0);
378d3c1e14bSEdwin Groothuis 		}
379d3c1e14bSEdwin Groothuis 		if (hdr.elf.e_type == ET_DYN) {
38070557f4fSRebecca Cran 			if (hdr.elf.e_ident[EI_OSABI] == ELFOSABI_FREEBSD) {
381d3c1e14bSEdwin Groothuis 				*is_shlib = 1;
382d3c1e14bSEdwin Groothuis 				return (1);
383d3c1e14bSEdwin Groothuis 			}
384d3c1e14bSEdwin Groothuis 			warnx("%s: not a FreeBSD ELF shared object", fname);
385d3c1e14bSEdwin Groothuis 			return (0);
386d3c1e14bSEdwin Groothuis 		}
387d3c1e14bSEdwin Groothuis 
388d3c1e14bSEdwin Groothuis 		return (1);
389d3c1e14bSEdwin Groothuis 	}
390d3c1e14bSEdwin Groothuis 
391d3c1e14bSEdwin Groothuis 	warnx("%s: not a dynamic executable", fname);
392d3c1e14bSEdwin Groothuis 	return (0);
393d3c1e14bSEdwin Groothuis }
394