xref: /freebsd/usr.bin/ldd/ldd.c (revision 52122f3139311d4fac507a7a1de5f64ff4844283)
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 
52e68ed793SJohn Baldwin #ifdef COMPAT_32BIT
53e68ed793SJohn Baldwin #define	LD_	"LD_32_"
54e68ed793SJohn Baldwin #else
55e68ed793SJohn Baldwin #define	LD_	"LD_"
56e68ed793SJohn Baldwin #endif
57e68ed793SJohn Baldwin 
588bd833ffSEdwin Groothuis /*
59bff71350SEdwin Groothuis  * 32-bit ELF data structures can only be used if the system header[s] declare
60bff71350SEdwin Groothuis  * them.  There is no official macro for determining whether they are declared,
61bff71350SEdwin Groothuis  * so check for the existence of one of the 32-macros defined in elf(5).
628bd833ffSEdwin Groothuis  */
63bff71350SEdwin Groothuis #ifdef ELF32_R_TYPE
648bd833ffSEdwin Groothuis #define	ELF32_SUPPORTED
658bd833ffSEdwin Groothuis #endif
668bd833ffSEdwin Groothuis 
67d3c1e14bSEdwin Groothuis static int	is_executable(const char *fname, int fd, int *is_shlib,
68d3c1e14bSEdwin Groothuis 		    int *type);
69d3c1e14bSEdwin Groothuis static void	usage(void);
70a0d476a9SEdwin Groothuis 
71d3c1e14bSEdwin Groothuis #define	TYPE_UNKNOWN	0
72d3c1e14bSEdwin Groothuis #define	TYPE_AOUT	1
73d3c1e14bSEdwin Groothuis #define	TYPE_ELF	2	/* Architecture default */
748bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
75fffd993dSEdwin Groothuis #define	TYPE_ELF32	3	/* Explicit 32 bits on architectures >32 bits */
76d3c1e14bSEdwin Groothuis 
77e68ed793SJohn Baldwin #define	_PATH_LDD32	"/usr/bin/ldd32"
78d3c1e14bSEdwin Groothuis 
79e68ed793SJohn Baldwin static int
80e68ed793SJohn Baldwin execldd32(char *file, char *fmt1, char *fmt2, int aflag, int vflag)
81e68ed793SJohn Baldwin {
82e68ed793SJohn Baldwin 	char *argv[8];
83e68ed793SJohn Baldwin 	int i, rval, status;
84e68ed793SJohn Baldwin 
85e68ed793SJohn Baldwin 	unsetenv(LD_ "TRACE_LOADED_OBJECTS");
86e68ed793SJohn Baldwin 	rval = 0;
87e68ed793SJohn Baldwin 	i = 0;
88e68ed793SJohn Baldwin 	argv[i++] = strdup(_PATH_LDD32);
89e68ed793SJohn Baldwin 	if (aflag)
90e68ed793SJohn Baldwin 		argv[i++] = strdup("-a");
91e68ed793SJohn Baldwin 	if (vflag)
92e68ed793SJohn Baldwin 		argv[i++] = strdup("-v");
9352122f31SJohn Baldwin 	if (fmt1 != NULL) {
94e68ed793SJohn Baldwin 		argv[i++] = strdup("-f");
95e68ed793SJohn Baldwin 		argv[i++] = strdup(fmt1);
96e68ed793SJohn Baldwin 	}
9752122f31SJohn Baldwin 	if (fmt2 != NULL) {
98e68ed793SJohn Baldwin 		argv[i++] = strdup("-f");
99e68ed793SJohn Baldwin 		argv[i++] = strdup(fmt2);
100e68ed793SJohn Baldwin 	}
101e68ed793SJohn Baldwin 	argv[i++] = strdup(file);
102e68ed793SJohn Baldwin 	argv[i++] = NULL;
103e68ed793SJohn Baldwin 
104e68ed793SJohn Baldwin 	switch (fork()) {
105e68ed793SJohn Baldwin 	case -1:
106e68ed793SJohn Baldwin 		err(1, "fork");
107e68ed793SJohn Baldwin 		break;
108e68ed793SJohn Baldwin 	case 0:
109e68ed793SJohn Baldwin 		execv(_PATH_LDD32, argv);
110e68ed793SJohn Baldwin 		warn("%s", _PATH_LDD32);
11152122f31SJohn Baldwin 		_exit(127);
112e68ed793SJohn Baldwin 		break;
113e68ed793SJohn Baldwin 	default:
11452122f31SJohn Baldwin 		if (wait(&status) < 0)
115e68ed793SJohn Baldwin 			rval = 1;
11652122f31SJohn Baldwin 		else if (WIFSIGNALED(status))
117e68ed793SJohn Baldwin 			rval = 1;
11852122f31SJohn Baldwin 		else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
119e68ed793SJohn Baldwin 			rval = 1;
120e68ed793SJohn Baldwin 		break;
121e68ed793SJohn Baldwin 	}
122e68ed793SJohn Baldwin 	while (i--)
123e68ed793SJohn Baldwin 		free(argv[i]);
124e68ed793SJohn Baldwin 	setenv(LD_ "TRACE_LOADED_OBJECTS", "yes", 1);
125e68ed793SJohn Baldwin 	return (rval);
126e68ed793SJohn Baldwin }
127fffd993dSEdwin Groothuis #endif
128b9ae52e3SPaul Richards 
129b9ae52e3SPaul Richards int
130a53809fdSMark Murray main(int argc, char *argv[])
131b9ae52e3SPaul Richards {
132a0d476a9SEdwin Groothuis 	char *fmt1, *fmt2;
133a0d476a9SEdwin Groothuis 	int rval, c, aflag, vflag;
134b9ae52e3SPaul Richards 
13520249943SDavid E. O'Brien 	aflag = vflag = 0;
136a0d476a9SEdwin Groothuis 	fmt1 = fmt2 = NULL;
13720249943SDavid E. O'Brien 
138a0d476a9SEdwin Groothuis 	while ((c = getopt(argc, argv, "af:v")) != -1) {
139b9ae52e3SPaul Richards 		switch (c) {
14020249943SDavid E. O'Brien 		case 'a':
14120249943SDavid E. O'Brien 			aflag++;
14220249943SDavid E. O'Brien 			break;
143d138df61SPeter Wemm 		case 'f':
144a0d476a9SEdwin Groothuis 			if (fmt1 != NULL) {
145a0d476a9SEdwin Groothuis 				if (fmt2 != NULL)
1463e762626SPhilippe Charnier 					errx(1, "too many formats");
147d138df61SPeter Wemm 				fmt2 = optarg;
148d138df61SPeter Wemm 			} else
149d138df61SPeter Wemm 				fmt1 = optarg;
150d138df61SPeter Wemm 			break;
151a0d476a9SEdwin Groothuis 		case 'v':
152a0d476a9SEdwin Groothuis 			vflag++;
153a0d476a9SEdwin Groothuis 			break;
154b9ae52e3SPaul Richards 		default:
155b9ae52e3SPaul Richards 			usage();
156699e1b82SRich Murphey 			/* NOTREACHED */
157b9ae52e3SPaul Richards 		}
158b9ae52e3SPaul Richards 	}
159b9ae52e3SPaul Richards 	argc -= optind;
160b9ae52e3SPaul Richards 	argv += optind;
161b9ae52e3SPaul Richards 
162a0d476a9SEdwin Groothuis 	if (vflag && fmt1 != NULL)
1639731d137SPeter Wemm 		errx(1, "-v may not be used with -f");
1649731d137SPeter Wemm 
165b9ae52e3SPaul Richards 	if (argc <= 0) {
166b9ae52e3SPaul Richards 		usage();
167699e1b82SRich Murphey 		/* NOTREACHED */
168b9ae52e3SPaul Richards 	}
169b9ae52e3SPaul Richards 
17097db68b6SDoug Rabson #ifdef __i386__
1719731d137SPeter Wemm 	if (vflag) {
1729731d137SPeter Wemm 		for (c = 0; c < argc; c++)
1739731d137SPeter Wemm 			dump_file(argv[c]);
1749731d137SPeter Wemm 		exit(error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
1759731d137SPeter Wemm 	}
17697db68b6SDoug Rabson #endif
1779731d137SPeter Wemm 
178699e1b82SRich Murphey 	rval = 0;
179e2daa140SJohn Polstra 	for (; argc > 0; argc--, argv++) {
180d3c1e14bSEdwin Groothuis 		int fd, status, is_shlib, rv, type;
181d3c1e14bSEdwin Groothuis 
182b9ae52e3SPaul Richards 		if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
183699e1b82SRich Murphey 			warn("%s", *argv);
184b9ae52e3SPaul Richards 			rval |= 1;
185b9ae52e3SPaul Richards 			continue;
186b9ae52e3SPaul Richards 		}
187d3c1e14bSEdwin Groothuis 		rv = is_executable(*argv, fd, &is_shlib, &type);
188a0d476a9SEdwin Groothuis 		close(fd);
189d3c1e14bSEdwin Groothuis 		if (rv == 0) {
190c474c6d3SDoug Rabson 			rval |= 1;
191c474c6d3SDoug Rabson 			continue;
192c474c6d3SDoug Rabson 		}
193c474c6d3SDoug Rabson 
194fffd993dSEdwin Groothuis 		switch (type) {
195fffd993dSEdwin Groothuis 		case TYPE_ELF:
196fffd993dSEdwin Groothuis 		case TYPE_AOUT:
197fffd993dSEdwin Groothuis 			break;
1988bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
199fffd993dSEdwin Groothuis 		case TYPE_ELF32:
200e68ed793SJohn Baldwin 			rval |= execldd32(*argv, fmt1, fmt2, aflag, vflag);
201e68ed793SJohn Baldwin 			continue;
202fffd993dSEdwin Groothuis #endif
203fffd993dSEdwin Groothuis 		case TYPE_UNKNOWN:
204fffd993dSEdwin Groothuis 		default:
205fffd993dSEdwin Groothuis 			/*
206fffd993dSEdwin Groothuis 			 * This shouldn't happen unless is_executable()
207fffd993dSEdwin Groothuis 			 * is broken.
208fffd993dSEdwin Groothuis 			 */
209fffd993dSEdwin Groothuis 			errx(EDOOFUS, "unknown executable type");
210fffd993dSEdwin Groothuis 		}
211fffd993dSEdwin Groothuis 
212d3c1e14bSEdwin Groothuis 		/* ld.so magic */
213e68ed793SJohn Baldwin 		setenv(LD_ "TRACE_LOADED_OBJECTS", "yes", 1);
214d3c1e14bSEdwin Groothuis 		if (fmt1 != NULL)
215e68ed793SJohn Baldwin 			setenv(LD_ "TRACE_LOADED_OBJECTS_FMT1", fmt1, 1);
216d3c1e14bSEdwin Groothuis 		if (fmt2 != NULL)
217e68ed793SJohn Baldwin 			setenv(LD_ "TRACE_LOADED_OBJECTS_FMT2", fmt2, 1);
218a0d476a9SEdwin Groothuis 
219e68ed793SJohn Baldwin 		setenv(LD_ "TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1);
220a0d476a9SEdwin Groothuis 		if (aflag)
221e68ed793SJohn Baldwin 			setenv(LD_ "TRACE_LOADED_OBJECTS_ALL", "1", 1);
22220249943SDavid E. O'Brien 		else if (fmt1 == NULL && fmt2 == NULL)
223d138df61SPeter Wemm 			/* Default formats */
224b9ae52e3SPaul Richards 			printf("%s:\n", *argv);
22509e3d49dSJordan K. Hubbard 		fflush(stdout);
226b9ae52e3SPaul Richards 
227b9ae52e3SPaul Richards 		switch (fork()) {
228b9ae52e3SPaul Richards 		case -1:
229699e1b82SRich Murphey 			err(1, "fork");
230b9ae52e3SPaul Richards 			break;
231b9ae52e3SPaul Richards 		default:
23252122f31SJohn Baldwin 			if (wait(&status) < 0) {
233699e1b82SRich Murphey 				warn("wait");
234699e1b82SRich Murphey 				rval |= 1;
235699e1b82SRich Murphey 			} else if (WIFSIGNALED(status)) {
236a0d476a9SEdwin Groothuis 				fprintf(stderr, "%s: signal %d\n", *argv,
237a0d476a9SEdwin Groothuis 				    WTERMSIG(status));
238b9ae52e3SPaul Richards 				rval |= 1;
23952122f31SJohn Baldwin 			} else if (WIFEXITED(status) &&
24052122f31SJohn Baldwin 			    WEXITSTATUS(status) != 0) {
241a0d476a9SEdwin Groothuis 				fprintf(stderr, "%s: exit status %d\n", *argv,
242a0d476a9SEdwin Groothuis 				    WEXITSTATUS(status));
243b9ae52e3SPaul Richards 				rval |= 1;
244b9ae52e3SPaul Richards 			}
245b9ae52e3SPaul Richards 			break;
246b9ae52e3SPaul Richards 		case 0:
247d1cf9ea2SMaxim Sobolev 			if (is_shlib == 0) {
248fc41545eSMaxim Sobolev 				execl(*argv, *argv, (char *)NULL);
2493e762626SPhilippe Charnier 				warn("%s", *argv);
250d1cf9ea2SMaxim Sobolev 			} else {
251d1cf9ea2SMaxim Sobolev 				dlopen(*argv, RTLD_TRACE);
252d1cf9ea2SMaxim Sobolev 				warnx("%s: %s", *argv, dlerror());
253c6de4ce7SMaxim Sobolev 			}
254b9ae52e3SPaul Richards 			_exit(1);
255b9ae52e3SPaul Richards 		}
256b9ae52e3SPaul Richards 	}
257b9ae52e3SPaul Richards 
258b9ae52e3SPaul Richards 	return rval;
259b9ae52e3SPaul Richards }
260d3c1e14bSEdwin Groothuis 
261d3c1e14bSEdwin Groothuis static void
262d3c1e14bSEdwin Groothuis usage(void)
263d3c1e14bSEdwin Groothuis {
264d3c1e14bSEdwin Groothuis 
265d3c1e14bSEdwin Groothuis 	fprintf(stderr, "usage: ldd [-a] [-v] [-f format] program ...\n");
266d3c1e14bSEdwin Groothuis 	exit(1);
267d3c1e14bSEdwin Groothuis }
268d3c1e14bSEdwin Groothuis 
269d3c1e14bSEdwin Groothuis static int
270d3c1e14bSEdwin Groothuis is_executable(const char *fname, int fd, int *is_shlib, int *type)
271d3c1e14bSEdwin Groothuis {
272d3c1e14bSEdwin Groothuis 	union {
273d3c1e14bSEdwin Groothuis 		struct exec aout;
2748bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
275fffd993dSEdwin Groothuis 		Elf32_Ehdr elf32;
2768bd833ffSEdwin Groothuis #endif
277d3c1e14bSEdwin Groothuis 		Elf_Ehdr elf;
278d3c1e14bSEdwin Groothuis 	} hdr;
279d3c1e14bSEdwin Groothuis 	int n;
280d3c1e14bSEdwin Groothuis 
281d3c1e14bSEdwin Groothuis 	*is_shlib = 0;
282d3c1e14bSEdwin Groothuis 	*type = TYPE_UNKNOWN;
283d3c1e14bSEdwin Groothuis 
284d3c1e14bSEdwin Groothuis 	if ((n = read(fd, &hdr, sizeof(hdr))) == -1) {
285d3c1e14bSEdwin Groothuis 		warn("%s: can't read program header", fname);
286d3c1e14bSEdwin Groothuis 		return (0);
287d3c1e14bSEdwin Groothuis 	}
288d3c1e14bSEdwin Groothuis 
289d3c1e14bSEdwin Groothuis 	if ((size_t)n >= sizeof(hdr.aout) && !N_BADMAG(hdr.aout)) {
290d3c1e14bSEdwin Groothuis 		/* a.out file */
291d3c1e14bSEdwin Groothuis 		if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC
292d3c1e14bSEdwin Groothuis #if 1 /* Compatibility */
293d3c1e14bSEdwin Groothuis 		    || hdr.aout.a_entry < __LDPGSZ
294d3c1e14bSEdwin Groothuis #endif
295d3c1e14bSEdwin Groothuis 			) {
296d3c1e14bSEdwin Groothuis 			warnx("%s: not a dynamic executable", fname);
297d3c1e14bSEdwin Groothuis 			return (0);
298d3c1e14bSEdwin Groothuis 		}
299d3c1e14bSEdwin Groothuis 		*type = TYPE_AOUT;
300d3c1e14bSEdwin Groothuis 		return (1);
301d3c1e14bSEdwin Groothuis 	}
302d3c1e14bSEdwin Groothuis 
3038bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
304fffd993dSEdwin Groothuis 	if ((size_t)n >= sizeof(hdr.elf32) && IS_ELF(hdr.elf32) &&
305fffd993dSEdwin Groothuis 	    hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
306fffd993dSEdwin Groothuis 		/* Handle 32 bit ELF objects */
307fffd993dSEdwin Groothuis 		Elf32_Phdr phdr;
308fffd993dSEdwin Groothuis 		int dynamic, i;
309fffd993dSEdwin Groothuis 
310fffd993dSEdwin Groothuis 		dynamic = 0;
311fffd993dSEdwin Groothuis 		*type = TYPE_ELF32;
312fffd993dSEdwin Groothuis 
313fffd993dSEdwin Groothuis 		if (lseek(fd, hdr.elf32.e_phoff, SEEK_SET) == -1) {
314fffd993dSEdwin Groothuis 			warnx("%s: header too short", fname);
315fffd993dSEdwin Groothuis 			return (0);
316fffd993dSEdwin Groothuis 		}
317fffd993dSEdwin Groothuis 		for (i = 0; i < hdr.elf32.e_phnum; i++) {
318fffd993dSEdwin Groothuis 			if (read(fd, &phdr, hdr.elf32.e_phentsize) !=
319fffd993dSEdwin Groothuis 			    sizeof(phdr)) {
320fffd993dSEdwin Groothuis 				warnx("%s: can't read program header", fname);
321fffd993dSEdwin Groothuis 				return (0);
322fffd993dSEdwin Groothuis 			}
323fffd993dSEdwin Groothuis 			if (phdr.p_type == PT_DYNAMIC) {
324fffd993dSEdwin Groothuis 				dynamic = 1;
325fffd993dSEdwin Groothuis 				break;
326fffd993dSEdwin Groothuis 			}
327fffd993dSEdwin Groothuis 		}
328fffd993dSEdwin Groothuis 
329fffd993dSEdwin Groothuis 		if (!dynamic) {
330fffd993dSEdwin Groothuis 			warnx("%s: not a dynamic ELF executable", fname);
331fffd993dSEdwin Groothuis 			return (0);
332fffd993dSEdwin Groothuis 		}
333fffd993dSEdwin Groothuis 		if (hdr.elf32.e_type == ET_DYN) {
334fffd993dSEdwin Groothuis 			if (hdr.elf32.e_ident[EI_OSABI] & ELFOSABI_FREEBSD) {
335fffd993dSEdwin Groothuis 				*is_shlib = 1;
336fffd993dSEdwin Groothuis 				return (1);
337fffd993dSEdwin Groothuis 			}
338fffd993dSEdwin Groothuis 			warnx("%s: not a FreeBSD ELF shared object", fname);
339fffd993dSEdwin Groothuis 			return (0);
340fffd993dSEdwin Groothuis 		}
341fffd993dSEdwin Groothuis 
342fffd993dSEdwin Groothuis 		return (1);
343fffd993dSEdwin Groothuis 	}
344fffd993dSEdwin Groothuis #endif
345fffd993dSEdwin Groothuis 
346d3c1e14bSEdwin Groothuis 	if ((size_t)n >= sizeof(hdr.elf) && IS_ELF(hdr.elf) &&
347d3c1e14bSEdwin Groothuis 	    hdr.elf.e_ident[EI_CLASS] == ELF_TARG_CLASS) {
348d3c1e14bSEdwin Groothuis 		/* Handle default ELF objects on this architecture */
349d3c1e14bSEdwin Groothuis 		Elf_Phdr phdr;
350d3c1e14bSEdwin Groothuis 		int dynamic, i;
351d3c1e14bSEdwin Groothuis 
352d3c1e14bSEdwin Groothuis 		dynamic = 0;
353d3c1e14bSEdwin Groothuis 		*type = TYPE_ELF;
354d3c1e14bSEdwin Groothuis 
355d3c1e14bSEdwin Groothuis 		if (lseek(fd, hdr.elf.e_phoff, SEEK_SET) == -1) {
356d3c1e14bSEdwin Groothuis 			warnx("%s: header too short", fname);
357d3c1e14bSEdwin Groothuis 			return (0);
358d3c1e14bSEdwin Groothuis 		}
359d3c1e14bSEdwin Groothuis 		for (i = 0; i < hdr.elf.e_phnum; i++) {
360d3c1e14bSEdwin Groothuis 			if (read(fd, &phdr, hdr.elf.e_phentsize)
361d3c1e14bSEdwin Groothuis 			   != sizeof(phdr)) {
362d3c1e14bSEdwin Groothuis 				warnx("%s: can't read program header", fname);
363d3c1e14bSEdwin Groothuis 				return (0);
364d3c1e14bSEdwin Groothuis 			}
365d3c1e14bSEdwin Groothuis 			if (phdr.p_type == PT_DYNAMIC) {
366d3c1e14bSEdwin Groothuis 				dynamic = 1;
367d3c1e14bSEdwin Groothuis 				break;
368d3c1e14bSEdwin Groothuis 			}
369d3c1e14bSEdwin Groothuis 		}
370d3c1e14bSEdwin Groothuis 
371d3c1e14bSEdwin Groothuis 		if (!dynamic) {
372d3c1e14bSEdwin Groothuis 			warnx("%s: not a dynamic ELF executable", fname);
373d3c1e14bSEdwin Groothuis 			return (0);
374d3c1e14bSEdwin Groothuis 		}
375d3c1e14bSEdwin Groothuis 		if (hdr.elf.e_type == ET_DYN) {
376d3c1e14bSEdwin Groothuis 			if (hdr.elf.e_ident[EI_OSABI] & ELFOSABI_FREEBSD) {
377d3c1e14bSEdwin Groothuis 				*is_shlib = 1;
378d3c1e14bSEdwin Groothuis 				return (1);
379d3c1e14bSEdwin Groothuis 			}
380d3c1e14bSEdwin Groothuis 			warnx("%s: not a FreeBSD ELF shared object", fname);
381d3c1e14bSEdwin Groothuis 			return (0);
382d3c1e14bSEdwin Groothuis 		}
383d3c1e14bSEdwin Groothuis 
384d3c1e14bSEdwin Groothuis 		return (1);
385d3c1e14bSEdwin Groothuis 	}
386d3c1e14bSEdwin Groothuis 
387d3c1e14bSEdwin Groothuis 	warnx("%s: not a dynamic executable", fname);
388d3c1e14bSEdwin Groothuis 	return (0);
389d3c1e14bSEdwin Groothuis }
390