Deleted Added
full compact
ldd.c (181136) ldd.c (181161)
1/*
2 * Copyright (c) 1993 Paul Kranenburg
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Paul Kranenburg.
16 * 4. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
1/*
2 * Copyright (c) 1993 Paul Kranenburg
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Paul Kranenburg.
16 * 4. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/usr.bin/ldd/ldd.c 181136 2008-08-01 21:52:41Z jhb $");
32__FBSDID("$FreeBSD: head/usr.bin/ldd/ldd.c 181161 2008-08-02 12:04:59Z jhb $");
33
34#include <sys/wait.h>
35
36#include <machine/elf.h>
37
38#include <arpa/inet.h>
39
40#include <a.out.h>
41#include <dlfcn.h>
42#include <err.h>
43#include <errno.h>
44#include <fcntl.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <unistd.h>
49
50#include "extern.h"
51
52#ifdef COMPAT_32BIT
53#define LD_ "LD_32_"
54#else
55#define LD_ "LD_"
56#endif
57
58/*
59 * 32-bit ELF data structures can only be used if the system header[s] declare
60 * them. There is no official macro for determining whether they are declared,
61 * so check for the existence of one of the 32-macros defined in elf(5).
62 */
63#ifdef ELF32_R_TYPE
64#define ELF32_SUPPORTED
65#endif
66
67static int is_executable(const char *fname, int fd, int *is_shlib,
68 int *type);
69static void usage(void);
70
71#define TYPE_UNKNOWN 0
72#define TYPE_AOUT 1
73#define TYPE_ELF 2 /* Architecture default */
74#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
75#define TYPE_ELF32 3 /* Explicit 32 bits on architectures >32 bits */
76
77#define _PATH_LDD32 "/usr/bin/ldd32"
78
79static int
80execldd32(char *file, char *fmt1, char *fmt2, int aflag, int vflag)
81{
82 char *argv[8];
83 int i, rval, status;
84
85 unsetenv(LD_ "TRACE_LOADED_OBJECTS");
33
34#include <sys/wait.h>
35
36#include <machine/elf.h>
37
38#include <arpa/inet.h>
39
40#include <a.out.h>
41#include <dlfcn.h>
42#include <err.h>
43#include <errno.h>
44#include <fcntl.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <unistd.h>
49
50#include "extern.h"
51
52#ifdef COMPAT_32BIT
53#define LD_ "LD_32_"
54#else
55#define LD_ "LD_"
56#endif
57
58/*
59 * 32-bit ELF data structures can only be used if the system header[s] declare
60 * them. There is no official macro for determining whether they are declared,
61 * so check for the existence of one of the 32-macros defined in elf(5).
62 */
63#ifdef ELF32_R_TYPE
64#define ELF32_SUPPORTED
65#endif
66
67static int is_executable(const char *fname, int fd, int *is_shlib,
68 int *type);
69static void usage(void);
70
71#define TYPE_UNKNOWN 0
72#define TYPE_AOUT 1
73#define TYPE_ELF 2 /* Architecture default */
74#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
75#define TYPE_ELF32 3 /* Explicit 32 bits on architectures >32 bits */
76
77#define _PATH_LDD32 "/usr/bin/ldd32"
78
79static int
80execldd32(char *file, char *fmt1, char *fmt2, int aflag, int vflag)
81{
82 char *argv[8];
83 int i, rval, status;
84
85 unsetenv(LD_ "TRACE_LOADED_OBJECTS");
86
87 rval = 0;
88 i = 0;
89 argv[i++] = strdup(_PATH_LDD32);
90 if (aflag)
91 argv[i++] = strdup("-a");
92 if (vflag)
93 argv[i++] = strdup("-v");
86 rval = 0;
87 i = 0;
88 argv[i++] = strdup(_PATH_LDD32);
89 if (aflag)
90 argv[i++] = strdup("-a");
91 if (vflag)
92 argv[i++] = strdup("-v");
94 if (fmt1) {
93 if (fmt1 != NULL) {
95 argv[i++] = strdup("-f");
96 argv[i++] = strdup(fmt1);
97 }
94 argv[i++] = strdup("-f");
95 argv[i++] = strdup(fmt1);
96 }
98 if (fmt2) {
97 if (fmt2 != NULL) {
99 argv[i++] = strdup("-f");
100 argv[i++] = strdup(fmt2);
101 }
98 argv[i++] = strdup("-f");
99 argv[i++] = strdup(fmt2);
100 }
102
103 argv[i++] = strdup(file);
104 argv[i++] = NULL;
105
106 switch (fork()) {
107 case -1:
108 err(1, "fork");
109 break;
110 case 0:
111 execv(_PATH_LDD32, argv);
112 warn("%s", _PATH_LDD32);
101 argv[i++] = strdup(file);
102 argv[i++] = NULL;
103
104 switch (fork()) {
105 case -1:
106 err(1, "fork");
107 break;
108 case 0:
109 execv(_PATH_LDD32, argv);
110 warn("%s", _PATH_LDD32);
113 _exit(1);
111 _exit(127);
114 break;
115 default:
112 break;
113 default:
116 if (wait(&status) <= 0) {
114 if (wait(&status) < 0)
117 rval = 1;
115 rval = 1;
118 } else if (WIFSIGNALED(status)) {
116 else if (WIFSIGNALED(status))
119 rval = 1;
117 rval = 1;
120 } else if (WIFEXITED(status) && WEXITSTATUS(status)) {
118 else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
121 rval = 1;
119 rval = 1;
122 }
123 break;
124 }
125 while (i--)
126 free(argv[i]);
127 setenv(LD_ "TRACE_LOADED_OBJECTS", "yes", 1);
128 return (rval);
129}
130#endif
131
132int
133main(int argc, char *argv[])
134{
135 char *fmt1, *fmt2;
136 int rval, c, aflag, vflag;
137
138 aflag = vflag = 0;
139 fmt1 = fmt2 = NULL;
140
141 while ((c = getopt(argc, argv, "af:v")) != -1) {
142 switch (c) {
143 case 'a':
144 aflag++;
145 break;
146 case 'f':
147 if (fmt1 != NULL) {
148 if (fmt2 != NULL)
149 errx(1, "too many formats");
150 fmt2 = optarg;
151 } else
152 fmt1 = optarg;
153 break;
154 case 'v':
155 vflag++;
156 break;
157 default:
158 usage();
159 /* NOTREACHED */
160 }
161 }
162 argc -= optind;
163 argv += optind;
164
165 if (vflag && fmt1 != NULL)
166 errx(1, "-v may not be used with -f");
167
168 if (argc <= 0) {
169 usage();
170 /* NOTREACHED */
171 }
172
173#ifdef __i386__
174 if (vflag) {
175 for (c = 0; c < argc; c++)
176 dump_file(argv[c]);
177 exit(error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
178 }
179#endif
180
181 rval = 0;
182 for (; argc > 0; argc--, argv++) {
183 int fd, status, is_shlib, rv, type;
184
185 if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
186 warn("%s", *argv);
187 rval |= 1;
188 continue;
189 }
190 rv = is_executable(*argv, fd, &is_shlib, &type);
191 close(fd);
192 if (rv == 0) {
193 rval |= 1;
194 continue;
195 }
196
197 switch (type) {
198 case TYPE_ELF:
199 case TYPE_AOUT:
200 break;
201#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
202 case TYPE_ELF32:
203 rval |= execldd32(*argv, fmt1, fmt2, aflag, vflag);
204 continue;
205#endif
206 case TYPE_UNKNOWN:
207 default:
208 /*
209 * This shouldn't happen unless is_executable()
210 * is broken.
211 */
212 errx(EDOOFUS, "unknown executable type");
213 }
214
215 /* ld.so magic */
216 setenv(LD_ "TRACE_LOADED_OBJECTS", "yes", 1);
217 if (fmt1 != NULL)
218 setenv(LD_ "TRACE_LOADED_OBJECTS_FMT1", fmt1, 1);
219 if (fmt2 != NULL)
220 setenv(LD_ "TRACE_LOADED_OBJECTS_FMT2", fmt2, 1);
221
222 setenv(LD_ "TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1);
223 if (aflag)
224 setenv(LD_ "TRACE_LOADED_OBJECTS_ALL", "1", 1);
225 else if (fmt1 == NULL && fmt2 == NULL)
226 /* Default formats */
227 printf("%s:\n", *argv);
228 fflush(stdout);
229
230 switch (fork()) {
231 case -1:
232 err(1, "fork");
233 break;
234 default:
120 break;
121 }
122 while (i--)
123 free(argv[i]);
124 setenv(LD_ "TRACE_LOADED_OBJECTS", "yes", 1);
125 return (rval);
126}
127#endif
128
129int
130main(int argc, char *argv[])
131{
132 char *fmt1, *fmt2;
133 int rval, c, aflag, vflag;
134
135 aflag = vflag = 0;
136 fmt1 = fmt2 = NULL;
137
138 while ((c = getopt(argc, argv, "af:v")) != -1) {
139 switch (c) {
140 case 'a':
141 aflag++;
142 break;
143 case 'f':
144 if (fmt1 != NULL) {
145 if (fmt2 != NULL)
146 errx(1, "too many formats");
147 fmt2 = optarg;
148 } else
149 fmt1 = optarg;
150 break;
151 case 'v':
152 vflag++;
153 break;
154 default:
155 usage();
156 /* NOTREACHED */
157 }
158 }
159 argc -= optind;
160 argv += optind;
161
162 if (vflag && fmt1 != NULL)
163 errx(1, "-v may not be used with -f");
164
165 if (argc <= 0) {
166 usage();
167 /* NOTREACHED */
168 }
169
170#ifdef __i386__
171 if (vflag) {
172 for (c = 0; c < argc; c++)
173 dump_file(argv[c]);
174 exit(error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
175 }
176#endif
177
178 rval = 0;
179 for (; argc > 0; argc--, argv++) {
180 int fd, status, is_shlib, rv, type;
181
182 if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
183 warn("%s", *argv);
184 rval |= 1;
185 continue;
186 }
187 rv = is_executable(*argv, fd, &is_shlib, &type);
188 close(fd);
189 if (rv == 0) {
190 rval |= 1;
191 continue;
192 }
193
194 switch (type) {
195 case TYPE_ELF:
196 case TYPE_AOUT:
197 break;
198#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
199 case TYPE_ELF32:
200 rval |= execldd32(*argv, fmt1, fmt2, aflag, vflag);
201 continue;
202#endif
203 case TYPE_UNKNOWN:
204 default:
205 /*
206 * This shouldn't happen unless is_executable()
207 * is broken.
208 */
209 errx(EDOOFUS, "unknown executable type");
210 }
211
212 /* ld.so magic */
213 setenv(LD_ "TRACE_LOADED_OBJECTS", "yes", 1);
214 if (fmt1 != NULL)
215 setenv(LD_ "TRACE_LOADED_OBJECTS_FMT1", fmt1, 1);
216 if (fmt2 != NULL)
217 setenv(LD_ "TRACE_LOADED_OBJECTS_FMT2", fmt2, 1);
218
219 setenv(LD_ "TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1);
220 if (aflag)
221 setenv(LD_ "TRACE_LOADED_OBJECTS_ALL", "1", 1);
222 else if (fmt1 == NULL && fmt2 == NULL)
223 /* Default formats */
224 printf("%s:\n", *argv);
225 fflush(stdout);
226
227 switch (fork()) {
228 case -1:
229 err(1, "fork");
230 break;
231 default:
235 if (wait(&status) <= 0) {
232 if (wait(&status) < 0) {
236 warn("wait");
237 rval |= 1;
238 } else if (WIFSIGNALED(status)) {
239 fprintf(stderr, "%s: signal %d\n", *argv,
240 WTERMSIG(status));
241 rval |= 1;
233 warn("wait");
234 rval |= 1;
235 } else if (WIFSIGNALED(status)) {
236 fprintf(stderr, "%s: signal %d\n", *argv,
237 WTERMSIG(status));
238 rval |= 1;
242 } else if (WIFEXITED(status) && WEXITSTATUS(status)) {
239 } else if (WIFEXITED(status) &&
240 WEXITSTATUS(status) != 0) {
243 fprintf(stderr, "%s: exit status %d\n", *argv,
244 WEXITSTATUS(status));
245 rval |= 1;
246 }
247 break;
248 case 0:
249 if (is_shlib == 0) {
250 execl(*argv, *argv, (char *)NULL);
251 warn("%s", *argv);
252 } else {
253 dlopen(*argv, RTLD_TRACE);
254 warnx("%s: %s", *argv, dlerror());
255 }
256 _exit(1);
257 }
258 }
259
260 return rval;
261}
262
263static void
264usage(void)
265{
266
267 fprintf(stderr, "usage: ldd [-a] [-v] [-f format] program ...\n");
268 exit(1);
269}
270
271static int
272is_executable(const char *fname, int fd, int *is_shlib, int *type)
273{
274 union {
275 struct exec aout;
276#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
277 Elf32_Ehdr elf32;
278#endif
279 Elf_Ehdr elf;
280 } hdr;
281 int n;
282
283 *is_shlib = 0;
284 *type = TYPE_UNKNOWN;
285
286 if ((n = read(fd, &hdr, sizeof(hdr))) == -1) {
287 warn("%s: can't read program header", fname);
288 return (0);
289 }
290
291 if ((size_t)n >= sizeof(hdr.aout) && !N_BADMAG(hdr.aout)) {
292 /* a.out file */
293 if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC
294#if 1 /* Compatibility */
295 || hdr.aout.a_entry < __LDPGSZ
296#endif
297 ) {
298 warnx("%s: not a dynamic executable", fname);
299 return (0);
300 }
301 *type = TYPE_AOUT;
302 return (1);
303 }
304
305#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
306 if ((size_t)n >= sizeof(hdr.elf32) && IS_ELF(hdr.elf32) &&
307 hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
308 /* Handle 32 bit ELF objects */
309 Elf32_Phdr phdr;
310 int dynamic, i;
311
312 dynamic = 0;
313 *type = TYPE_ELF32;
314
315 if (lseek(fd, hdr.elf32.e_phoff, SEEK_SET) == -1) {
316 warnx("%s: header too short", fname);
317 return (0);
318 }
319 for (i = 0; i < hdr.elf32.e_phnum; i++) {
320 if (read(fd, &phdr, hdr.elf32.e_phentsize) !=
321 sizeof(phdr)) {
322 warnx("%s: can't read program header", fname);
323 return (0);
324 }
325 if (phdr.p_type == PT_DYNAMIC) {
326 dynamic = 1;
327 break;
328 }
329 }
330
331 if (!dynamic) {
332 warnx("%s: not a dynamic ELF executable", fname);
333 return (0);
334 }
335 if (hdr.elf32.e_type == ET_DYN) {
336 if (hdr.elf32.e_ident[EI_OSABI] & ELFOSABI_FREEBSD) {
337 *is_shlib = 1;
338 return (1);
339 }
340 warnx("%s: not a FreeBSD ELF shared object", fname);
341 return (0);
342 }
343
344 return (1);
345 }
346#endif
347
348 if ((size_t)n >= sizeof(hdr.elf) && IS_ELF(hdr.elf) &&
349 hdr.elf.e_ident[EI_CLASS] == ELF_TARG_CLASS) {
350 /* Handle default ELF objects on this architecture */
351 Elf_Phdr phdr;
352 int dynamic, i;
353
354 dynamic = 0;
355 *type = TYPE_ELF;
356
357 if (lseek(fd, hdr.elf.e_phoff, SEEK_SET) == -1) {
358 warnx("%s: header too short", fname);
359 return (0);
360 }
361 for (i = 0; i < hdr.elf.e_phnum; i++) {
362 if (read(fd, &phdr, hdr.elf.e_phentsize)
363 != sizeof(phdr)) {
364 warnx("%s: can't read program header", fname);
365 return (0);
366 }
367 if (phdr.p_type == PT_DYNAMIC) {
368 dynamic = 1;
369 break;
370 }
371 }
372
373 if (!dynamic) {
374 warnx("%s: not a dynamic ELF executable", fname);
375 return (0);
376 }
377 if (hdr.elf.e_type == ET_DYN) {
378 if (hdr.elf.e_ident[EI_OSABI] & ELFOSABI_FREEBSD) {
379 *is_shlib = 1;
380 return (1);
381 }
382 warnx("%s: not a FreeBSD ELF shared object", fname);
383 return (0);
384 }
385
386 return (1);
387 }
388
389 warnx("%s: not a dynamic executable", fname);
390 return (0);
391}
241 fprintf(stderr, "%s: exit status %d\n", *argv,
242 WEXITSTATUS(status));
243 rval |= 1;
244 }
245 break;
246 case 0:
247 if (is_shlib == 0) {
248 execl(*argv, *argv, (char *)NULL);
249 warn("%s", *argv);
250 } else {
251 dlopen(*argv, RTLD_TRACE);
252 warnx("%s: %s", *argv, dlerror());
253 }
254 _exit(1);
255 }
256 }
257
258 return rval;
259}
260
261static void
262usage(void)
263{
264
265 fprintf(stderr, "usage: ldd [-a] [-v] [-f format] program ...\n");
266 exit(1);
267}
268
269static int
270is_executable(const char *fname, int fd, int *is_shlib, int *type)
271{
272 union {
273 struct exec aout;
274#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
275 Elf32_Ehdr elf32;
276#endif
277 Elf_Ehdr elf;
278 } hdr;
279 int n;
280
281 *is_shlib = 0;
282 *type = TYPE_UNKNOWN;
283
284 if ((n = read(fd, &hdr, sizeof(hdr))) == -1) {
285 warn("%s: can't read program header", fname);
286 return (0);
287 }
288
289 if ((size_t)n >= sizeof(hdr.aout) && !N_BADMAG(hdr.aout)) {
290 /* a.out file */
291 if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC
292#if 1 /* Compatibility */
293 || hdr.aout.a_entry < __LDPGSZ
294#endif
295 ) {
296 warnx("%s: not a dynamic executable", fname);
297 return (0);
298 }
299 *type = TYPE_AOUT;
300 return (1);
301 }
302
303#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
304 if ((size_t)n >= sizeof(hdr.elf32) && IS_ELF(hdr.elf32) &&
305 hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
306 /* Handle 32 bit ELF objects */
307 Elf32_Phdr phdr;
308 int dynamic, i;
309
310 dynamic = 0;
311 *type = TYPE_ELF32;
312
313 if (lseek(fd, hdr.elf32.e_phoff, SEEK_SET) == -1) {
314 warnx("%s: header too short", fname);
315 return (0);
316 }
317 for (i = 0; i < hdr.elf32.e_phnum; i++) {
318 if (read(fd, &phdr, hdr.elf32.e_phentsize) !=
319 sizeof(phdr)) {
320 warnx("%s: can't read program header", fname);
321 return (0);
322 }
323 if (phdr.p_type == PT_DYNAMIC) {
324 dynamic = 1;
325 break;
326 }
327 }
328
329 if (!dynamic) {
330 warnx("%s: not a dynamic ELF executable", fname);
331 return (0);
332 }
333 if (hdr.elf32.e_type == ET_DYN) {
334 if (hdr.elf32.e_ident[EI_OSABI] & ELFOSABI_FREEBSD) {
335 *is_shlib = 1;
336 return (1);
337 }
338 warnx("%s: not a FreeBSD ELF shared object", fname);
339 return (0);
340 }
341
342 return (1);
343 }
344#endif
345
346 if ((size_t)n >= sizeof(hdr.elf) && IS_ELF(hdr.elf) &&
347 hdr.elf.e_ident[EI_CLASS] == ELF_TARG_CLASS) {
348 /* Handle default ELF objects on this architecture */
349 Elf_Phdr phdr;
350 int dynamic, i;
351
352 dynamic = 0;
353 *type = TYPE_ELF;
354
355 if (lseek(fd, hdr.elf.e_phoff, SEEK_SET) == -1) {
356 warnx("%s: header too short", fname);
357 return (0);
358 }
359 for (i = 0; i < hdr.elf.e_phnum; i++) {
360 if (read(fd, &phdr, hdr.elf.e_phentsize)
361 != sizeof(phdr)) {
362 warnx("%s: can't read program header", fname);
363 return (0);
364 }
365 if (phdr.p_type == PT_DYNAMIC) {
366 dynamic = 1;
367 break;
368 }
369 }
370
371 if (!dynamic) {
372 warnx("%s: not a dynamic ELF executable", fname);
373 return (0);
374 }
375 if (hdr.elf.e_type == ET_DYN) {
376 if (hdr.elf.e_ident[EI_OSABI] & ELFOSABI_FREEBSD) {
377 *is_shlib = 1;
378 return (1);
379 }
380 warnx("%s: not a FreeBSD ELF shared object", fname);
381 return (0);
382 }
383
384 return (1);
385 }
386
387 warnx("%s: not a dynamic executable", fname);
388 return (0);
389}