11de7b4b8SPedro F. Giffuni /*- 21de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-4-Clause 31de7b4b8SPedro F. Giffuni * 4b9ae52e3SPaul Richards * Copyright (c) 1993 Paul Kranenburg 5b9ae52e3SPaul Richards * All rights reserved. 6b9ae52e3SPaul Richards * 7b9ae52e3SPaul Richards * Redistribution and use in source and binary forms, with or without 8b9ae52e3SPaul Richards * modification, are permitted provided that the following conditions 9b9ae52e3SPaul Richards * are met: 10b9ae52e3SPaul Richards * 1. Redistributions of source code must retain the above copyright 11b9ae52e3SPaul Richards * notice, this list of conditions and the following disclaimer. 12b9ae52e3SPaul Richards * 2. Redistributions in binary form must reproduce the above copyright 13b9ae52e3SPaul Richards * notice, this list of conditions and the following disclaimer in the 14b9ae52e3SPaul Richards * documentation and/or other materials provided with the distribution. 15b9ae52e3SPaul Richards * 3. All advertising materials mentioning features or use of this software 16b9ae52e3SPaul Richards * must display the following acknowledgement: 17b9ae52e3SPaul Richards * This product includes software developed by Paul Kranenburg. 18b9ae52e3SPaul Richards * 4. The name of the author may not be used to endorse or promote products 1909e3d49dSJordan K. Hubbard * derived from this software without specific prior written permission 20b9ae52e3SPaul Richards * 21b9ae52e3SPaul Richards * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22b9ae52e3SPaul Richards * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23b9ae52e3SPaul Richards * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24b9ae52e3SPaul Richards * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25b9ae52e3SPaul Richards * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26b9ae52e3SPaul Richards * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27b9ae52e3SPaul Richards * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28b9ae52e3SPaul Richards * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29b9ae52e3SPaul Richards * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30b9ae52e3SPaul Richards * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31b9ae52e3SPaul Richards */ 32b9ae52e3SPaul Richards 33a53809fdSMark Murray #include <sys/cdefs.h> 34a53809fdSMark Murray __FBSDID("$FreeBSD$"); 353e762626SPhilippe Charnier 36b9ae52e3SPaul Richards #include <sys/wait.h> 37a53809fdSMark Murray 385e6220d9SDavid E. O'Brien #include <machine/elf.h> 39a53809fdSMark Murray 40a2cfdda8SMike Barcroft #include <arpa/inet.h> 41a53809fdSMark Murray 42c6de4ce7SMaxim Sobolev #include <dlfcn.h> 43699e1b82SRich Murphey #include <err.h> 44fffd993dSEdwin Groothuis #include <errno.h> 45699e1b82SRich Murphey #include <fcntl.h> 46699e1b82SRich Murphey #include <stdio.h> 47699e1b82SRich Murphey #include <stdlib.h> 48e68ed793SJohn Baldwin #include <string.h> 49699e1b82SRich Murphey #include <unistd.h> 50b9ae52e3SPaul Richards 518bd833ffSEdwin Groothuis /* 52bff71350SEdwin Groothuis * 32-bit ELF data structures can only be used if the system header[s] declare 53bff71350SEdwin Groothuis * them. There is no official macro for determining whether they are declared, 54bff71350SEdwin Groothuis * so check for the existence of one of the 32-macros defined in elf(5). 558bd833ffSEdwin Groothuis */ 56bff71350SEdwin Groothuis #ifdef ELF32_R_TYPE 578bd833ffSEdwin Groothuis #define ELF32_SUPPORTED 588bd833ffSEdwin Groothuis #endif 598bd833ffSEdwin Groothuis 60a94a4b74SMark Johnston #define LDD_SETENV(name, value, overwrite) do { \ 61a94a4b74SMark Johnston setenv("LD_" name, value, overwrite); \ 62a94a4b74SMark Johnston setenv("LD_32_" name, value, overwrite); \ 63a94a4b74SMark Johnston } while (0) 64a94a4b74SMark Johnston 65a94a4b74SMark Johnston #define LDD_UNSETENV(name) do { \ 66a94a4b74SMark Johnston unsetenv("LD_" name); \ 67a94a4b74SMark Johnston unsetenv("LD_32_" name); \ 68a94a4b74SMark Johnston } while (0) 69a94a4b74SMark Johnston 70d3c1e14bSEdwin Groothuis static int is_executable(const char *fname, int fd, int *is_shlib, 71d3c1e14bSEdwin Groothuis int *type); 72d3c1e14bSEdwin Groothuis static void usage(void); 73a0d476a9SEdwin Groothuis 74d3c1e14bSEdwin Groothuis #define TYPE_UNKNOWN 0 75*c8eee7c0SEd Maste #define TYPE_ELF 1 /* Architecture default */ 768bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED) 77*c8eee7c0SEd Maste #define TYPE_ELF32 2 /* Explicit 32 bits on architectures >32 bits */ 78d3c1e14bSEdwin Groothuis 79e68ed793SJohn Baldwin #define _PATH_LDD32 "/usr/bin/ldd32" 80d3c1e14bSEdwin Groothuis 81e68ed793SJohn Baldwin static int 82e68ed793SJohn Baldwin execldd32(char *file, char *fmt1, char *fmt2, int aflag, int vflag) 83e68ed793SJohn Baldwin { 844b426307SDon Lewis char *argv[9]; 85e68ed793SJohn Baldwin int i, rval, status; 86e68ed793SJohn Baldwin 87a94a4b74SMark Johnston LDD_UNSETENV("TRACE_LOADED_OBJECTS"); 88e68ed793SJohn Baldwin rval = 0; 89e68ed793SJohn Baldwin i = 0; 90e68ed793SJohn Baldwin argv[i++] = strdup(_PATH_LDD32); 91e68ed793SJohn Baldwin if (aflag) 92e68ed793SJohn Baldwin argv[i++] = strdup("-a"); 93e68ed793SJohn Baldwin if (vflag) 94e68ed793SJohn Baldwin argv[i++] = strdup("-v"); 9552122f31SJohn Baldwin if (fmt1 != NULL) { 96e68ed793SJohn Baldwin argv[i++] = strdup("-f"); 97e68ed793SJohn Baldwin argv[i++] = strdup(fmt1); 98e68ed793SJohn Baldwin } 9952122f31SJohn Baldwin if (fmt2 != NULL) { 100e68ed793SJohn Baldwin argv[i++] = strdup("-f"); 101e68ed793SJohn Baldwin argv[i++] = strdup(fmt2); 102e68ed793SJohn Baldwin } 103e68ed793SJohn Baldwin argv[i++] = strdup(file); 104e68ed793SJohn Baldwin argv[i++] = NULL; 105e68ed793SJohn Baldwin 106e68ed793SJohn Baldwin switch (fork()) { 107e68ed793SJohn Baldwin case -1: 108e68ed793SJohn Baldwin err(1, "fork"); 109e68ed793SJohn Baldwin break; 110e68ed793SJohn Baldwin case 0: 111e68ed793SJohn Baldwin execv(_PATH_LDD32, argv); 112e68ed793SJohn Baldwin warn("%s", _PATH_LDD32); 11352122f31SJohn Baldwin _exit(127); 114e68ed793SJohn Baldwin break; 115e68ed793SJohn Baldwin default: 11652122f31SJohn Baldwin if (wait(&status) < 0) 117e68ed793SJohn Baldwin rval = 1; 11852122f31SJohn Baldwin else if (WIFSIGNALED(status)) 119e68ed793SJohn Baldwin rval = 1; 12052122f31SJohn Baldwin else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) 121e68ed793SJohn Baldwin rval = 1; 122e68ed793SJohn Baldwin break; 123e68ed793SJohn Baldwin } 124e68ed793SJohn Baldwin while (i--) 125e68ed793SJohn Baldwin free(argv[i]); 126a94a4b74SMark Johnston LDD_SETENV("TRACE_LOADED_OBJECTS", "yes", 1); 127e68ed793SJohn Baldwin return (rval); 128e68ed793SJohn Baldwin } 129fffd993dSEdwin Groothuis #endif 130b9ae52e3SPaul Richards 131b9ae52e3SPaul Richards int 132a53809fdSMark Murray main(int argc, char *argv[]) 133b9ae52e3SPaul Richards { 134a0d476a9SEdwin Groothuis char *fmt1, *fmt2; 135a0d476a9SEdwin Groothuis int rval, c, aflag, vflag; 136b9ae52e3SPaul Richards 13720249943SDavid E. O'Brien aflag = vflag = 0; 138a0d476a9SEdwin Groothuis fmt1 = fmt2 = NULL; 13920249943SDavid E. O'Brien 140a0d476a9SEdwin Groothuis while ((c = getopt(argc, argv, "af:v")) != -1) { 141b9ae52e3SPaul Richards switch (c) { 14220249943SDavid E. O'Brien case 'a': 14320249943SDavid E. O'Brien aflag++; 14420249943SDavid E. O'Brien break; 145d138df61SPeter Wemm case 'f': 146a0d476a9SEdwin Groothuis if (fmt1 != NULL) { 147a0d476a9SEdwin Groothuis if (fmt2 != NULL) 1483e762626SPhilippe Charnier errx(1, "too many formats"); 149d138df61SPeter Wemm fmt2 = optarg; 150d138df61SPeter Wemm } else 151d138df61SPeter Wemm fmt1 = optarg; 152d138df61SPeter Wemm break; 153a0d476a9SEdwin Groothuis case 'v': 154a0d476a9SEdwin Groothuis vflag++; 155a0d476a9SEdwin Groothuis break; 156b9ae52e3SPaul Richards default: 157b9ae52e3SPaul Richards usage(); 158699e1b82SRich Murphey /* NOTREACHED */ 159b9ae52e3SPaul Richards } 160b9ae52e3SPaul Richards } 161b9ae52e3SPaul Richards argc -= optind; 162b9ae52e3SPaul Richards argv += optind; 163b9ae52e3SPaul Richards 164a0d476a9SEdwin Groothuis if (vflag && fmt1 != NULL) 1659731d137SPeter Wemm errx(1, "-v may not be used with -f"); 1669731d137SPeter Wemm 167b9ae52e3SPaul Richards if (argc <= 0) { 168b9ae52e3SPaul Richards usage(); 169699e1b82SRich Murphey /* NOTREACHED */ 170b9ae52e3SPaul Richards } 171b9ae52e3SPaul Richards 172699e1b82SRich Murphey rval = 0; 173e2daa140SJohn Polstra for (; argc > 0; argc--, argv++) { 174d3c1e14bSEdwin Groothuis int fd, status, is_shlib, rv, type; 175d3c1e14bSEdwin Groothuis 176b9ae52e3SPaul Richards if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 177699e1b82SRich Murphey warn("%s", *argv); 178b9ae52e3SPaul Richards rval |= 1; 179b9ae52e3SPaul Richards continue; 180b9ae52e3SPaul Richards } 181d3c1e14bSEdwin Groothuis rv = is_executable(*argv, fd, &is_shlib, &type); 182a0d476a9SEdwin Groothuis close(fd); 183d3c1e14bSEdwin Groothuis if (rv == 0) { 184c474c6d3SDoug Rabson rval |= 1; 185c474c6d3SDoug Rabson continue; 186c474c6d3SDoug Rabson } 187c474c6d3SDoug Rabson 188fffd993dSEdwin Groothuis switch (type) { 189fffd993dSEdwin Groothuis case TYPE_ELF: 190fffd993dSEdwin Groothuis break; 1918bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED) 192fffd993dSEdwin Groothuis case TYPE_ELF32: 193e68ed793SJohn Baldwin rval |= execldd32(*argv, fmt1, fmt2, aflag, vflag); 194e68ed793SJohn Baldwin continue; 195fffd993dSEdwin Groothuis #endif 196fffd993dSEdwin Groothuis case TYPE_UNKNOWN: 197fffd993dSEdwin Groothuis default: 198fffd993dSEdwin Groothuis /* 199fffd993dSEdwin Groothuis * This shouldn't happen unless is_executable() 200fffd993dSEdwin Groothuis * is broken. 201fffd993dSEdwin Groothuis */ 202fffd993dSEdwin Groothuis errx(EDOOFUS, "unknown executable type"); 203fffd993dSEdwin Groothuis } 204fffd993dSEdwin Groothuis 205d3c1e14bSEdwin Groothuis /* ld.so magic */ 206a94a4b74SMark Johnston LDD_SETENV("TRACE_LOADED_OBJECTS", "yes", 1); 207d3c1e14bSEdwin Groothuis if (fmt1 != NULL) 208a94a4b74SMark Johnston LDD_SETENV("TRACE_LOADED_OBJECTS_FMT1", fmt1, 1); 209d3c1e14bSEdwin Groothuis if (fmt2 != NULL) 210a94a4b74SMark Johnston LDD_SETENV("TRACE_LOADED_OBJECTS_FMT2", fmt2, 1); 211a0d476a9SEdwin Groothuis 212a94a4b74SMark Johnston LDD_SETENV("TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1); 213a0d476a9SEdwin Groothuis if (aflag) 214a94a4b74SMark Johnston LDD_SETENV("TRACE_LOADED_OBJECTS_ALL", "1", 1); 21520249943SDavid E. O'Brien else if (fmt1 == NULL && fmt2 == NULL) 216d138df61SPeter Wemm /* Default formats */ 217b9ae52e3SPaul Richards printf("%s:\n", *argv); 21809e3d49dSJordan K. Hubbard fflush(stdout); 219b9ae52e3SPaul Richards 220b9ae52e3SPaul Richards switch (fork()) { 221b9ae52e3SPaul Richards case -1: 222699e1b82SRich Murphey err(1, "fork"); 223b9ae52e3SPaul Richards break; 224b9ae52e3SPaul Richards default: 22552122f31SJohn Baldwin if (wait(&status) < 0) { 226699e1b82SRich Murphey warn("wait"); 227699e1b82SRich Murphey rval |= 1; 228699e1b82SRich Murphey } else if (WIFSIGNALED(status)) { 229a0d476a9SEdwin Groothuis fprintf(stderr, "%s: signal %d\n", *argv, 230a0d476a9SEdwin Groothuis WTERMSIG(status)); 231b9ae52e3SPaul Richards rval |= 1; 23252122f31SJohn Baldwin } else if (WIFEXITED(status) && 23352122f31SJohn Baldwin WEXITSTATUS(status) != 0) { 234a0d476a9SEdwin Groothuis fprintf(stderr, "%s: exit status %d\n", *argv, 235a0d476a9SEdwin Groothuis WEXITSTATUS(status)); 236b9ae52e3SPaul Richards rval |= 1; 237b9ae52e3SPaul Richards } 238b9ae52e3SPaul Richards break; 239b9ae52e3SPaul Richards case 0: 240d1cf9ea2SMaxim Sobolev if (is_shlib == 0) { 241fc41545eSMaxim Sobolev execl(*argv, *argv, (char *)NULL); 2423e762626SPhilippe Charnier warn("%s", *argv); 243d1cf9ea2SMaxim Sobolev } else { 244d1cf9ea2SMaxim Sobolev dlopen(*argv, RTLD_TRACE); 245d1cf9ea2SMaxim Sobolev warnx("%s: %s", *argv, dlerror()); 246c6de4ce7SMaxim Sobolev } 247b9ae52e3SPaul Richards _exit(1); 248b9ae52e3SPaul Richards } 249b9ae52e3SPaul Richards } 250b9ae52e3SPaul Richards 251b9ae52e3SPaul Richards return rval; 252b9ae52e3SPaul Richards } 253d3c1e14bSEdwin Groothuis 254d3c1e14bSEdwin Groothuis static void 255d3c1e14bSEdwin Groothuis usage(void) 256d3c1e14bSEdwin Groothuis { 257d3c1e14bSEdwin Groothuis 258d3c1e14bSEdwin Groothuis fprintf(stderr, "usage: ldd [-a] [-v] [-f format] program ...\n"); 259d3c1e14bSEdwin Groothuis exit(1); 260d3c1e14bSEdwin Groothuis } 261d3c1e14bSEdwin Groothuis 262d3c1e14bSEdwin Groothuis static int 263d3c1e14bSEdwin Groothuis is_executable(const char *fname, int fd, int *is_shlib, int *type) 264d3c1e14bSEdwin Groothuis { 265d3c1e14bSEdwin Groothuis union { 2668bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED) 267fffd993dSEdwin Groothuis Elf32_Ehdr elf32; 2688bd833ffSEdwin Groothuis #endif 269d3c1e14bSEdwin Groothuis Elf_Ehdr elf; 270d3c1e14bSEdwin Groothuis } hdr; 2712b5d88fdSKonstantin Belousov Elf_Phdr phdr, dynphdr; 2722b5d88fdSKonstantin Belousov Elf_Dyn *dynp; 2732b5d88fdSKonstantin Belousov void *dyndata; 2742b5d88fdSKonstantin Belousov #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED) 2752b5d88fdSKonstantin Belousov Elf32_Phdr phdr32, dynphdr32; 2762b5d88fdSKonstantin Belousov Elf32_Dyn *dynp32; 2772b5d88fdSKonstantin Belousov #endif 2782b5d88fdSKonstantin Belousov int df1pie, dynamic, i, n; 279d3c1e14bSEdwin Groothuis 280d3c1e14bSEdwin Groothuis *is_shlib = 0; 281d3c1e14bSEdwin Groothuis *type = TYPE_UNKNOWN; 2822b5d88fdSKonstantin Belousov df1pie = 0; 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 2898bd833ffSEdwin Groothuis #if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED) 290fffd993dSEdwin Groothuis if ((size_t)n >= sizeof(hdr.elf32) && IS_ELF(hdr.elf32) && 291fffd993dSEdwin Groothuis hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) { 292fffd993dSEdwin Groothuis /* Handle 32 bit ELF objects */ 293fffd993dSEdwin Groothuis 294fffd993dSEdwin Groothuis dynamic = 0; 295fffd993dSEdwin Groothuis *type = TYPE_ELF32; 296fffd993dSEdwin Groothuis 297fffd993dSEdwin Groothuis if (lseek(fd, hdr.elf32.e_phoff, SEEK_SET) == -1) { 298fffd993dSEdwin Groothuis warnx("%s: header too short", fname); 299fffd993dSEdwin Groothuis return (0); 300fffd993dSEdwin Groothuis } 301fffd993dSEdwin Groothuis for (i = 0; i < hdr.elf32.e_phnum; i++) { 3022b5d88fdSKonstantin Belousov if (read(fd, &phdr32, hdr.elf32.e_phentsize) != 3032b5d88fdSKonstantin Belousov sizeof(phdr32)) { 304fffd993dSEdwin Groothuis warnx("%s: can't read program header", fname); 305fffd993dSEdwin Groothuis return (0); 306fffd993dSEdwin Groothuis } 3072b5d88fdSKonstantin Belousov if (phdr32.p_type == PT_DYNAMIC) { 308fffd993dSEdwin Groothuis dynamic = 1; 3092b5d88fdSKonstantin Belousov dynphdr32 = phdr32; 310fffd993dSEdwin Groothuis break; 311fffd993dSEdwin Groothuis } 312fffd993dSEdwin Groothuis } 313fffd993dSEdwin Groothuis 314fffd993dSEdwin Groothuis if (!dynamic) { 315fffd993dSEdwin Groothuis warnx("%s: not a dynamic ELF executable", fname); 316fffd993dSEdwin Groothuis return (0); 317fffd993dSEdwin Groothuis } 3182b5d88fdSKonstantin Belousov 319fffd993dSEdwin Groothuis if (hdr.elf32.e_type == ET_DYN) { 3202b5d88fdSKonstantin Belousov if (lseek(fd, dynphdr32.p_offset, SEEK_SET) == -1) { 3212b5d88fdSKonstantin Belousov warnx("%s: dynamic segment out of range", 3222b5d88fdSKonstantin Belousov fname); 3232b5d88fdSKonstantin Belousov return (0); 3242b5d88fdSKonstantin Belousov } 3252b5d88fdSKonstantin Belousov dyndata = malloc(dynphdr32.p_filesz); 3262b5d88fdSKonstantin Belousov if (dyndata == NULL) { 3272b5d88fdSKonstantin Belousov warn("malloc"); 3282b5d88fdSKonstantin Belousov return (0); 3292b5d88fdSKonstantin Belousov } 3302b5d88fdSKonstantin Belousov if (read(fd, dyndata, dynphdr32.p_filesz) != 3312b5d88fdSKonstantin Belousov (ssize_t)dynphdr32.p_filesz) { 3322b5d88fdSKonstantin Belousov free(dyndata); 3332b5d88fdSKonstantin Belousov warnx("%s: can't read dynamic segment", fname); 3342b5d88fdSKonstantin Belousov return (0); 3352b5d88fdSKonstantin Belousov } 3362b5d88fdSKonstantin Belousov for (dynp32 = dyndata; dynp32->d_tag != DT_NULL; 3372b5d88fdSKonstantin Belousov dynp32++) { 3382b5d88fdSKonstantin Belousov if (dynp32->d_tag != DT_FLAGS_1) 3392b5d88fdSKonstantin Belousov continue; 3402b5d88fdSKonstantin Belousov df1pie = (dynp32->d_un.d_val & DF_1_PIE) != 0; 3412b5d88fdSKonstantin Belousov break; 3422b5d88fdSKonstantin Belousov } 3432b5d88fdSKonstantin Belousov free(dyndata); 3442b5d88fdSKonstantin Belousov 34570557f4fSRebecca Cran if (hdr.elf32.e_ident[EI_OSABI] == ELFOSABI_FREEBSD) { 3462b5d88fdSKonstantin Belousov if (!df1pie) 347fffd993dSEdwin Groothuis *is_shlib = 1; 348fffd993dSEdwin Groothuis return (1); 349fffd993dSEdwin Groothuis } 350fffd993dSEdwin Groothuis warnx("%s: not a FreeBSD ELF shared object", fname); 351fffd993dSEdwin Groothuis return (0); 352fffd993dSEdwin Groothuis } 353fffd993dSEdwin Groothuis 354fffd993dSEdwin Groothuis return (1); 355fffd993dSEdwin Groothuis } 356fffd993dSEdwin Groothuis #endif 357fffd993dSEdwin Groothuis 358d3c1e14bSEdwin Groothuis if ((size_t)n >= sizeof(hdr.elf) && IS_ELF(hdr.elf) && 359d3c1e14bSEdwin Groothuis hdr.elf.e_ident[EI_CLASS] == ELF_TARG_CLASS) { 360d3c1e14bSEdwin Groothuis /* Handle default ELF objects on this architecture */ 361d3c1e14bSEdwin Groothuis 362d3c1e14bSEdwin Groothuis dynamic = 0; 363d3c1e14bSEdwin Groothuis *type = TYPE_ELF; 364d3c1e14bSEdwin Groothuis 365d3c1e14bSEdwin Groothuis if (lseek(fd, hdr.elf.e_phoff, SEEK_SET) == -1) { 366d3c1e14bSEdwin Groothuis warnx("%s: header too short", fname); 367d3c1e14bSEdwin Groothuis return (0); 368d3c1e14bSEdwin Groothuis } 369d3c1e14bSEdwin Groothuis for (i = 0; i < hdr.elf.e_phnum; i++) { 370d3c1e14bSEdwin Groothuis if (read(fd, &phdr, hdr.elf.e_phentsize) 371d3c1e14bSEdwin Groothuis != sizeof(phdr)) { 372d3c1e14bSEdwin Groothuis warnx("%s: can't read program header", fname); 373d3c1e14bSEdwin Groothuis return (0); 374d3c1e14bSEdwin Groothuis } 375d3c1e14bSEdwin Groothuis if (phdr.p_type == PT_DYNAMIC) { 376d3c1e14bSEdwin Groothuis dynamic = 1; 3772b5d88fdSKonstantin Belousov dynphdr = phdr; 378d3c1e14bSEdwin Groothuis break; 379d3c1e14bSEdwin Groothuis } 380d3c1e14bSEdwin Groothuis } 381d3c1e14bSEdwin Groothuis 382d3c1e14bSEdwin Groothuis if (!dynamic) { 383d3c1e14bSEdwin Groothuis warnx("%s: not a dynamic ELF executable", fname); 384d3c1e14bSEdwin Groothuis return (0); 385d3c1e14bSEdwin Groothuis } 3862b5d88fdSKonstantin Belousov 387d3c1e14bSEdwin Groothuis if (hdr.elf.e_type == ET_DYN) { 3882b5d88fdSKonstantin Belousov if (lseek(fd, dynphdr.p_offset, SEEK_SET) == -1) { 3892b5d88fdSKonstantin Belousov warnx("%s: dynamic segment out of range", 3902b5d88fdSKonstantin Belousov fname); 3912b5d88fdSKonstantin Belousov return (0); 3922b5d88fdSKonstantin Belousov } 3932b5d88fdSKonstantin Belousov dyndata = malloc(dynphdr.p_filesz); 3942b5d88fdSKonstantin Belousov if (dyndata == NULL) { 3952b5d88fdSKonstantin Belousov warn("malloc"); 3962b5d88fdSKonstantin Belousov return (0); 3972b5d88fdSKonstantin Belousov } 3982b5d88fdSKonstantin Belousov if (read(fd, dyndata, dynphdr.p_filesz) != 3992b5d88fdSKonstantin Belousov (ssize_t)dynphdr.p_filesz) { 4002b5d88fdSKonstantin Belousov free(dyndata); 4012b5d88fdSKonstantin Belousov warnx("%s: can't read dynamic segment", fname); 4022b5d88fdSKonstantin Belousov return (0); 4032b5d88fdSKonstantin Belousov } 4042b5d88fdSKonstantin Belousov for (dynp = dyndata; dynp->d_tag != DT_NULL; dynp++) { 4052b5d88fdSKonstantin Belousov if (dynp->d_tag != DT_FLAGS_1) 4062b5d88fdSKonstantin Belousov continue; 4072b5d88fdSKonstantin Belousov df1pie = (dynp->d_un.d_val & DF_1_PIE) != 0; 4082b5d88fdSKonstantin Belousov break; 4092b5d88fdSKonstantin Belousov } 4102b5d88fdSKonstantin Belousov free(dyndata); 4112b5d88fdSKonstantin Belousov 412a41dab8fSJung-uk Kim switch (hdr.elf.e_ident[EI_OSABI]) { 413a41dab8fSJung-uk Kim case ELFOSABI_FREEBSD: 4142b5d88fdSKonstantin Belousov if (!df1pie) 415d3c1e14bSEdwin Groothuis *is_shlib = 1; 416d3c1e14bSEdwin Groothuis return (1); 417a41dab8fSJung-uk Kim #ifdef __ARM_EABI__ 418a41dab8fSJung-uk Kim case ELFOSABI_NONE: 419a41dab8fSJung-uk Kim if (hdr.elf.e_machine != EM_ARM) 420a41dab8fSJung-uk Kim break; 421a41dab8fSJung-uk Kim if (EF_ARM_EABI_VERSION(hdr.elf.e_flags) < 422a41dab8fSJung-uk Kim EF_ARM_EABI_FREEBSD_MIN) 423a41dab8fSJung-uk Kim break; 424a41dab8fSJung-uk Kim *is_shlib = 1; 425a41dab8fSJung-uk Kim return (1); 426a41dab8fSJung-uk Kim #endif 427d3c1e14bSEdwin Groothuis } 428d3c1e14bSEdwin Groothuis warnx("%s: not a FreeBSD ELF shared object", fname); 429d3c1e14bSEdwin Groothuis return (0); 430d3c1e14bSEdwin Groothuis } 431d3c1e14bSEdwin Groothuis 432d3c1e14bSEdwin Groothuis return (1); 433d3c1e14bSEdwin Groothuis } 434d3c1e14bSEdwin Groothuis 435d3c1e14bSEdwin Groothuis warnx("%s: not a dynamic executable", fname); 436d3c1e14bSEdwin Groothuis return (0); 437d3c1e14bSEdwin Groothuis } 438