xref: /freebsd/usr.bin/ldd/ldd.c (revision 4b426307e533ccbb8fe5fc08e752767b28893990)
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 
40c6de4ce7SMaxim Sobolev #include <dlfcn.h>
41699e1b82SRich Murphey #include <err.h>
42fffd993dSEdwin Groothuis #include <errno.h>
43699e1b82SRich Murphey #include <fcntl.h>
44699e1b82SRich Murphey #include <stdio.h>
45699e1b82SRich Murphey #include <stdlib.h>
46e68ed793SJohn Baldwin #include <string.h>
47699e1b82SRich Murphey #include <unistd.h>
48b9ae52e3SPaul Richards 
49a53809fdSMark Murray #include "extern.h"
509731d137SPeter Wemm 
515a0bf0f5SRuslan Bukin /* We don't support a.out executables on arm64 and riscv */
525a0bf0f5SRuslan Bukin #if !defined(__aarch64__) && !defined(__riscv__)
53e1f65999SAndrew Turner #include <a.out.h>
54e1f65999SAndrew Turner #define	AOUT_SUPPORTED
55e1f65999SAndrew Turner #endif
56e1f65999SAndrew Turner 
578bd833ffSEdwin Groothuis /*
58bff71350SEdwin Groothuis  * 32-bit ELF data structures can only be used if the system header[s] declare
59bff71350SEdwin Groothuis  * them.  There is no official macro for determining whether they are declared,
60bff71350SEdwin Groothuis  * so check for the existence of one of the 32-macros defined in elf(5).
618bd833ffSEdwin Groothuis  */
62bff71350SEdwin Groothuis #ifdef ELF32_R_TYPE
638bd833ffSEdwin Groothuis #define	ELF32_SUPPORTED
648bd833ffSEdwin Groothuis #endif
658bd833ffSEdwin Groothuis 
66a94a4b74SMark Johnston #define	LDD_SETENV(name, value, overwrite) do {		\
67a94a4b74SMark Johnston 	setenv("LD_" name, value, overwrite);		\
68a94a4b74SMark Johnston 	setenv("LD_32_" name, value, overwrite);	\
69a94a4b74SMark Johnston } while (0)
70a94a4b74SMark Johnston 
71a94a4b74SMark Johnston #define	LDD_UNSETENV(name) do {		\
72a94a4b74SMark Johnston 	unsetenv("LD_" name);		\
73a94a4b74SMark Johnston 	unsetenv("LD_32_" name);	\
74a94a4b74SMark Johnston } while (0)
75a94a4b74SMark Johnston 
76d3c1e14bSEdwin Groothuis static int	is_executable(const char *fname, int fd, int *is_shlib,
77d3c1e14bSEdwin Groothuis 		    int *type);
78d3c1e14bSEdwin Groothuis static void	usage(void);
79a0d476a9SEdwin Groothuis 
80d3c1e14bSEdwin Groothuis #define	TYPE_UNKNOWN	0
81d3c1e14bSEdwin Groothuis #define	TYPE_AOUT	1
82d3c1e14bSEdwin Groothuis #define	TYPE_ELF	2	/* Architecture default */
838bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
84fffd993dSEdwin Groothuis #define	TYPE_ELF32	3	/* Explicit 32 bits on architectures >32 bits */
85d3c1e14bSEdwin Groothuis 
86e68ed793SJohn Baldwin #define	_PATH_LDD32	"/usr/bin/ldd32"
87d3c1e14bSEdwin Groothuis 
88e68ed793SJohn Baldwin static int
89e68ed793SJohn Baldwin execldd32(char *file, char *fmt1, char *fmt2, int aflag, int vflag)
90e68ed793SJohn Baldwin {
91*4b426307SDon Lewis 	char *argv[9];
92e68ed793SJohn Baldwin 	int i, rval, status;
93e68ed793SJohn Baldwin 
94a94a4b74SMark Johnston 	LDD_UNSETENV("TRACE_LOADED_OBJECTS");
95e68ed793SJohn Baldwin 	rval = 0;
96e68ed793SJohn Baldwin 	i = 0;
97e68ed793SJohn Baldwin 	argv[i++] = strdup(_PATH_LDD32);
98e68ed793SJohn Baldwin 	if (aflag)
99e68ed793SJohn Baldwin 		argv[i++] = strdup("-a");
100e68ed793SJohn Baldwin 	if (vflag)
101e68ed793SJohn Baldwin 		argv[i++] = strdup("-v");
10252122f31SJohn Baldwin 	if (fmt1 != NULL) {
103e68ed793SJohn Baldwin 		argv[i++] = strdup("-f");
104e68ed793SJohn Baldwin 		argv[i++] = strdup(fmt1);
105e68ed793SJohn Baldwin 	}
10652122f31SJohn Baldwin 	if (fmt2 != NULL) {
107e68ed793SJohn Baldwin 		argv[i++] = strdup("-f");
108e68ed793SJohn Baldwin 		argv[i++] = strdup(fmt2);
109e68ed793SJohn Baldwin 	}
110e68ed793SJohn Baldwin 	argv[i++] = strdup(file);
111e68ed793SJohn Baldwin 	argv[i++] = NULL;
112e68ed793SJohn Baldwin 
113e68ed793SJohn Baldwin 	switch (fork()) {
114e68ed793SJohn Baldwin 	case -1:
115e68ed793SJohn Baldwin 		err(1, "fork");
116e68ed793SJohn Baldwin 		break;
117e68ed793SJohn Baldwin 	case 0:
118e68ed793SJohn Baldwin 		execv(_PATH_LDD32, argv);
119e68ed793SJohn Baldwin 		warn("%s", _PATH_LDD32);
12052122f31SJohn Baldwin 		_exit(127);
121e68ed793SJohn Baldwin 		break;
122e68ed793SJohn Baldwin 	default:
12352122f31SJohn Baldwin 		if (wait(&status) < 0)
124e68ed793SJohn Baldwin 			rval = 1;
12552122f31SJohn Baldwin 		else if (WIFSIGNALED(status))
126e68ed793SJohn Baldwin 			rval = 1;
12752122f31SJohn Baldwin 		else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
128e68ed793SJohn Baldwin 			rval = 1;
129e68ed793SJohn Baldwin 		break;
130e68ed793SJohn Baldwin 	}
131e68ed793SJohn Baldwin 	while (i--)
132e68ed793SJohn Baldwin 		free(argv[i]);
133a94a4b74SMark Johnston 	LDD_SETENV("TRACE_LOADED_OBJECTS", "yes", 1);
134e68ed793SJohn Baldwin 	return (rval);
135e68ed793SJohn Baldwin }
136fffd993dSEdwin Groothuis #endif
137b9ae52e3SPaul Richards 
138b9ae52e3SPaul Richards int
139a53809fdSMark Murray main(int argc, char *argv[])
140b9ae52e3SPaul Richards {
141a0d476a9SEdwin Groothuis 	char *fmt1, *fmt2;
142a0d476a9SEdwin Groothuis 	int rval, c, aflag, vflag;
143b9ae52e3SPaul Richards 
14420249943SDavid E. O'Brien 	aflag = vflag = 0;
145a0d476a9SEdwin Groothuis 	fmt1 = fmt2 = NULL;
14620249943SDavid E. O'Brien 
147a0d476a9SEdwin Groothuis 	while ((c = getopt(argc, argv, "af:v")) != -1) {
148b9ae52e3SPaul Richards 		switch (c) {
14920249943SDavid E. O'Brien 		case 'a':
15020249943SDavid E. O'Brien 			aflag++;
15120249943SDavid E. O'Brien 			break;
152d138df61SPeter Wemm 		case 'f':
153a0d476a9SEdwin Groothuis 			if (fmt1 != NULL) {
154a0d476a9SEdwin Groothuis 				if (fmt2 != NULL)
1553e762626SPhilippe Charnier 					errx(1, "too many formats");
156d138df61SPeter Wemm 				fmt2 = optarg;
157d138df61SPeter Wemm 			} else
158d138df61SPeter Wemm 				fmt1 = optarg;
159d138df61SPeter Wemm 			break;
160a0d476a9SEdwin Groothuis 		case 'v':
161a0d476a9SEdwin Groothuis 			vflag++;
162a0d476a9SEdwin Groothuis 			break;
163b9ae52e3SPaul Richards 		default:
164b9ae52e3SPaul Richards 			usage();
165699e1b82SRich Murphey 			/* NOTREACHED */
166b9ae52e3SPaul Richards 		}
167b9ae52e3SPaul Richards 	}
168b9ae52e3SPaul Richards 	argc -= optind;
169b9ae52e3SPaul Richards 	argv += optind;
170b9ae52e3SPaul Richards 
171a0d476a9SEdwin Groothuis 	if (vflag && fmt1 != NULL)
1729731d137SPeter Wemm 		errx(1, "-v may not be used with -f");
1739731d137SPeter Wemm 
174b9ae52e3SPaul Richards 	if (argc <= 0) {
175b9ae52e3SPaul Richards 		usage();
176699e1b82SRich Murphey 		/* NOTREACHED */
177b9ae52e3SPaul Richards 	}
178b9ae52e3SPaul Richards 
17997db68b6SDoug Rabson #ifdef __i386__
1809731d137SPeter Wemm 	if (vflag) {
1819731d137SPeter Wemm 		for (c = 0; c < argc; c++)
1829731d137SPeter Wemm 			dump_file(argv[c]);
1839731d137SPeter Wemm 		exit(error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
1849731d137SPeter Wemm 	}
18597db68b6SDoug Rabson #endif
1869731d137SPeter Wemm 
187699e1b82SRich Murphey 	rval = 0;
188e2daa140SJohn Polstra 	for (; argc > 0; argc--, argv++) {
189d3c1e14bSEdwin Groothuis 		int fd, status, is_shlib, rv, type;
190d3c1e14bSEdwin Groothuis 
191b9ae52e3SPaul Richards 		if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
192699e1b82SRich Murphey 			warn("%s", *argv);
193b9ae52e3SPaul Richards 			rval |= 1;
194b9ae52e3SPaul Richards 			continue;
195b9ae52e3SPaul Richards 		}
196d3c1e14bSEdwin Groothuis 		rv = is_executable(*argv, fd, &is_shlib, &type);
197a0d476a9SEdwin Groothuis 		close(fd);
198d3c1e14bSEdwin Groothuis 		if (rv == 0) {
199c474c6d3SDoug Rabson 			rval |= 1;
200c474c6d3SDoug Rabson 			continue;
201c474c6d3SDoug Rabson 		}
202c474c6d3SDoug Rabson 
203fffd993dSEdwin Groothuis 		switch (type) {
204fffd993dSEdwin Groothuis 		case TYPE_ELF:
205fffd993dSEdwin Groothuis 		case TYPE_AOUT:
206fffd993dSEdwin Groothuis 			break;
2078bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
208fffd993dSEdwin Groothuis 		case TYPE_ELF32:
209e68ed793SJohn Baldwin 			rval |= execldd32(*argv, fmt1, fmt2, aflag, vflag);
210e68ed793SJohn Baldwin 			continue;
211fffd993dSEdwin Groothuis #endif
212fffd993dSEdwin Groothuis 		case TYPE_UNKNOWN:
213fffd993dSEdwin Groothuis 		default:
214fffd993dSEdwin Groothuis 			/*
215fffd993dSEdwin Groothuis 			 * This shouldn't happen unless is_executable()
216fffd993dSEdwin Groothuis 			 * is broken.
217fffd993dSEdwin Groothuis 			 */
218fffd993dSEdwin Groothuis 			errx(EDOOFUS, "unknown executable type");
219fffd993dSEdwin Groothuis 		}
220fffd993dSEdwin Groothuis 
221d3c1e14bSEdwin Groothuis 		/* ld.so magic */
222a94a4b74SMark Johnston 		LDD_SETENV("TRACE_LOADED_OBJECTS", "yes", 1);
223d3c1e14bSEdwin Groothuis 		if (fmt1 != NULL)
224a94a4b74SMark Johnston 			LDD_SETENV("TRACE_LOADED_OBJECTS_FMT1", fmt1, 1);
225d3c1e14bSEdwin Groothuis 		if (fmt2 != NULL)
226a94a4b74SMark Johnston 			LDD_SETENV("TRACE_LOADED_OBJECTS_FMT2", fmt2, 1);
227a0d476a9SEdwin Groothuis 
228a94a4b74SMark Johnston 		LDD_SETENV("TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1);
229a0d476a9SEdwin Groothuis 		if (aflag)
230a94a4b74SMark Johnston 			LDD_SETENV("TRACE_LOADED_OBJECTS_ALL", "1", 1);
23120249943SDavid E. O'Brien 		else if (fmt1 == NULL && fmt2 == NULL)
232d138df61SPeter Wemm 			/* Default formats */
233b9ae52e3SPaul Richards 			printf("%s:\n", *argv);
23409e3d49dSJordan K. Hubbard 		fflush(stdout);
235b9ae52e3SPaul Richards 
236b9ae52e3SPaul Richards 		switch (fork()) {
237b9ae52e3SPaul Richards 		case -1:
238699e1b82SRich Murphey 			err(1, "fork");
239b9ae52e3SPaul Richards 			break;
240b9ae52e3SPaul Richards 		default:
24152122f31SJohn Baldwin 			if (wait(&status) < 0) {
242699e1b82SRich Murphey 				warn("wait");
243699e1b82SRich Murphey 				rval |= 1;
244699e1b82SRich Murphey 			} else if (WIFSIGNALED(status)) {
245a0d476a9SEdwin Groothuis 				fprintf(stderr, "%s: signal %d\n", *argv,
246a0d476a9SEdwin Groothuis 				    WTERMSIG(status));
247b9ae52e3SPaul Richards 				rval |= 1;
24852122f31SJohn Baldwin 			} else if (WIFEXITED(status) &&
24952122f31SJohn Baldwin 			    WEXITSTATUS(status) != 0) {
250a0d476a9SEdwin Groothuis 				fprintf(stderr, "%s: exit status %d\n", *argv,
251a0d476a9SEdwin Groothuis 				    WEXITSTATUS(status));
252b9ae52e3SPaul Richards 				rval |= 1;
253b9ae52e3SPaul Richards 			}
254b9ae52e3SPaul Richards 			break;
255b9ae52e3SPaul Richards 		case 0:
256d1cf9ea2SMaxim Sobolev 			if (is_shlib == 0) {
257fc41545eSMaxim Sobolev 				execl(*argv, *argv, (char *)NULL);
2583e762626SPhilippe Charnier 				warn("%s", *argv);
259d1cf9ea2SMaxim Sobolev 			} else {
260d1cf9ea2SMaxim Sobolev 				dlopen(*argv, RTLD_TRACE);
261d1cf9ea2SMaxim Sobolev 				warnx("%s: %s", *argv, dlerror());
262c6de4ce7SMaxim Sobolev 			}
263b9ae52e3SPaul Richards 			_exit(1);
264b9ae52e3SPaul Richards 		}
265b9ae52e3SPaul Richards 	}
266b9ae52e3SPaul Richards 
267b9ae52e3SPaul Richards 	return rval;
268b9ae52e3SPaul Richards }
269d3c1e14bSEdwin Groothuis 
270d3c1e14bSEdwin Groothuis static void
271d3c1e14bSEdwin Groothuis usage(void)
272d3c1e14bSEdwin Groothuis {
273d3c1e14bSEdwin Groothuis 
274d3c1e14bSEdwin Groothuis 	fprintf(stderr, "usage: ldd [-a] [-v] [-f format] program ...\n");
275d3c1e14bSEdwin Groothuis 	exit(1);
276d3c1e14bSEdwin Groothuis }
277d3c1e14bSEdwin Groothuis 
278d3c1e14bSEdwin Groothuis static int
279d3c1e14bSEdwin Groothuis is_executable(const char *fname, int fd, int *is_shlib, int *type)
280d3c1e14bSEdwin Groothuis {
281d3c1e14bSEdwin Groothuis 	union {
282e1f65999SAndrew Turner #ifdef AOUT_SUPPORTED
283d3c1e14bSEdwin Groothuis 		struct exec aout;
284e1f65999SAndrew Turner #endif
2858bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
286fffd993dSEdwin Groothuis 		Elf32_Ehdr elf32;
2878bd833ffSEdwin Groothuis #endif
288d3c1e14bSEdwin Groothuis 		Elf_Ehdr elf;
289d3c1e14bSEdwin Groothuis 	} hdr;
290d3c1e14bSEdwin Groothuis 	int n;
291d3c1e14bSEdwin Groothuis 
292d3c1e14bSEdwin Groothuis 	*is_shlib = 0;
293d3c1e14bSEdwin Groothuis 	*type = TYPE_UNKNOWN;
294d3c1e14bSEdwin Groothuis 
295d3c1e14bSEdwin Groothuis 	if ((n = read(fd, &hdr, sizeof(hdr))) == -1) {
296d3c1e14bSEdwin Groothuis 		warn("%s: can't read program header", fname);
297d3c1e14bSEdwin Groothuis 		return (0);
298d3c1e14bSEdwin Groothuis 	}
299d3c1e14bSEdwin Groothuis 
300e1f65999SAndrew Turner #ifdef AOUT_SUPPORTED
301d3c1e14bSEdwin Groothuis 	if ((size_t)n >= sizeof(hdr.aout) && !N_BADMAG(hdr.aout)) {
302d3c1e14bSEdwin Groothuis 		/* a.out file */
303d3c1e14bSEdwin Groothuis 		if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC
304d3c1e14bSEdwin Groothuis #if 1 /* Compatibility */
305d3c1e14bSEdwin Groothuis 		    || hdr.aout.a_entry < __LDPGSZ
306d3c1e14bSEdwin Groothuis #endif
307d3c1e14bSEdwin Groothuis 			) {
308d3c1e14bSEdwin Groothuis 			warnx("%s: not a dynamic executable", fname);
309d3c1e14bSEdwin Groothuis 			return (0);
310d3c1e14bSEdwin Groothuis 		}
311d3c1e14bSEdwin Groothuis 		*type = TYPE_AOUT;
312d3c1e14bSEdwin Groothuis 		return (1);
313d3c1e14bSEdwin Groothuis 	}
314e1f65999SAndrew Turner #endif
315d3c1e14bSEdwin Groothuis 
3168bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
317fffd993dSEdwin Groothuis 	if ((size_t)n >= sizeof(hdr.elf32) && IS_ELF(hdr.elf32) &&
318fffd993dSEdwin Groothuis 	    hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
319fffd993dSEdwin Groothuis 		/* Handle 32 bit ELF objects */
320fffd993dSEdwin Groothuis 		Elf32_Phdr phdr;
321fffd993dSEdwin Groothuis 		int dynamic, i;
322fffd993dSEdwin Groothuis 
323fffd993dSEdwin Groothuis 		dynamic = 0;
324fffd993dSEdwin Groothuis 		*type = TYPE_ELF32;
325fffd993dSEdwin Groothuis 
326fffd993dSEdwin Groothuis 		if (lseek(fd, hdr.elf32.e_phoff, SEEK_SET) == -1) {
327fffd993dSEdwin Groothuis 			warnx("%s: header too short", fname);
328fffd993dSEdwin Groothuis 			return (0);
329fffd993dSEdwin Groothuis 		}
330fffd993dSEdwin Groothuis 		for (i = 0; i < hdr.elf32.e_phnum; i++) {
331fffd993dSEdwin Groothuis 			if (read(fd, &phdr, hdr.elf32.e_phentsize) !=
332fffd993dSEdwin Groothuis 			    sizeof(phdr)) {
333fffd993dSEdwin Groothuis 				warnx("%s: can't read program header", fname);
334fffd993dSEdwin Groothuis 				return (0);
335fffd993dSEdwin Groothuis 			}
336fffd993dSEdwin Groothuis 			if (phdr.p_type == PT_DYNAMIC) {
337fffd993dSEdwin Groothuis 				dynamic = 1;
338fffd993dSEdwin Groothuis 				break;
339fffd993dSEdwin Groothuis 			}
340fffd993dSEdwin Groothuis 		}
341fffd993dSEdwin Groothuis 
342fffd993dSEdwin Groothuis 		if (!dynamic) {
343fffd993dSEdwin Groothuis 			warnx("%s: not a dynamic ELF executable", fname);
344fffd993dSEdwin Groothuis 			return (0);
345fffd993dSEdwin Groothuis 		}
346fffd993dSEdwin Groothuis 		if (hdr.elf32.e_type == ET_DYN) {
34770557f4fSRebecca Cran 			if (hdr.elf32.e_ident[EI_OSABI] == ELFOSABI_FREEBSD) {
348fffd993dSEdwin Groothuis 				*is_shlib = 1;
349fffd993dSEdwin Groothuis 				return (1);
350fffd993dSEdwin Groothuis 			}
351fffd993dSEdwin Groothuis 			warnx("%s: not a FreeBSD ELF shared object", fname);
352fffd993dSEdwin Groothuis 			return (0);
353fffd993dSEdwin Groothuis 		}
354fffd993dSEdwin Groothuis 
355fffd993dSEdwin Groothuis 		return (1);
356fffd993dSEdwin Groothuis 	}
357fffd993dSEdwin Groothuis #endif
358fffd993dSEdwin Groothuis 
359d3c1e14bSEdwin Groothuis 	if ((size_t)n >= sizeof(hdr.elf) && IS_ELF(hdr.elf) &&
360d3c1e14bSEdwin Groothuis 	    hdr.elf.e_ident[EI_CLASS] == ELF_TARG_CLASS) {
361d3c1e14bSEdwin Groothuis 		/* Handle default ELF objects on this architecture */
362d3c1e14bSEdwin Groothuis 		Elf_Phdr phdr;
363d3c1e14bSEdwin Groothuis 		int dynamic, i;
364d3c1e14bSEdwin Groothuis 
365d3c1e14bSEdwin Groothuis 		dynamic = 0;
366d3c1e14bSEdwin Groothuis 		*type = TYPE_ELF;
367d3c1e14bSEdwin Groothuis 
368d3c1e14bSEdwin Groothuis 		if (lseek(fd, hdr.elf.e_phoff, SEEK_SET) == -1) {
369d3c1e14bSEdwin Groothuis 			warnx("%s: header too short", fname);
370d3c1e14bSEdwin Groothuis 			return (0);
371d3c1e14bSEdwin Groothuis 		}
372d3c1e14bSEdwin Groothuis 		for (i = 0; i < hdr.elf.e_phnum; i++) {
373d3c1e14bSEdwin Groothuis 			if (read(fd, &phdr, hdr.elf.e_phentsize)
374d3c1e14bSEdwin Groothuis 			   != sizeof(phdr)) {
375d3c1e14bSEdwin Groothuis 				warnx("%s: can't read program header", fname);
376d3c1e14bSEdwin Groothuis 				return (0);
377d3c1e14bSEdwin Groothuis 			}
378d3c1e14bSEdwin Groothuis 			if (phdr.p_type == PT_DYNAMIC) {
379d3c1e14bSEdwin Groothuis 				dynamic = 1;
380d3c1e14bSEdwin Groothuis 				break;
381d3c1e14bSEdwin Groothuis 			}
382d3c1e14bSEdwin Groothuis 		}
383d3c1e14bSEdwin Groothuis 
384d3c1e14bSEdwin Groothuis 		if (!dynamic) {
385d3c1e14bSEdwin Groothuis 			warnx("%s: not a dynamic ELF executable", fname);
386d3c1e14bSEdwin Groothuis 			return (0);
387d3c1e14bSEdwin Groothuis 		}
388d3c1e14bSEdwin Groothuis 		if (hdr.elf.e_type == ET_DYN) {
389a41dab8fSJung-uk Kim 			switch (hdr.elf.e_ident[EI_OSABI]) {
390a41dab8fSJung-uk Kim 			case ELFOSABI_FREEBSD:
391d3c1e14bSEdwin Groothuis 				*is_shlib = 1;
392d3c1e14bSEdwin Groothuis 				return (1);
393a41dab8fSJung-uk Kim #ifdef __ARM_EABI__
394a41dab8fSJung-uk Kim 			case ELFOSABI_NONE:
395a41dab8fSJung-uk Kim 				if (hdr.elf.e_machine != EM_ARM)
396a41dab8fSJung-uk Kim 					break;
397a41dab8fSJung-uk Kim 				if (EF_ARM_EABI_VERSION(hdr.elf.e_flags) <
398a41dab8fSJung-uk Kim 				    EF_ARM_EABI_FREEBSD_MIN)
399a41dab8fSJung-uk Kim 					break;
400a41dab8fSJung-uk Kim 				*is_shlib = 1;
401a41dab8fSJung-uk Kim 				return (1);
402a41dab8fSJung-uk Kim #endif
403d3c1e14bSEdwin Groothuis 			}
404d3c1e14bSEdwin Groothuis 			warnx("%s: not a FreeBSD ELF shared object", fname);
405d3c1e14bSEdwin Groothuis 			return (0);
406d3c1e14bSEdwin Groothuis 		}
407d3c1e14bSEdwin Groothuis 
408d3c1e14bSEdwin Groothuis 		return (1);
409d3c1e14bSEdwin Groothuis 	}
410d3c1e14bSEdwin Groothuis 
411d3c1e14bSEdwin Groothuis 	warnx("%s: not a dynamic executable", fname);
412d3c1e14bSEdwin Groothuis 	return (0);
413d3c1e14bSEdwin Groothuis }
414