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 313e762626SPhilippe Charnier #ifndef lint 323e762626SPhilippe Charnier static const char rcsid[] = 333e762626SPhilippe Charnier "$FreeBSD$"; 343e762626SPhilippe Charnier #endif /* not lint */ 353e762626SPhilippe Charnier 36b9ae52e3SPaul Richards #include <sys/wait.h> 375e6220d9SDavid E. O'Brien #include <machine/elf.h> 38b9ae52e3SPaul Richards #include <a.out.h> 39699e1b82SRich Murphey #include <err.h> 40699e1b82SRich Murphey #include <fcntl.h> 41699e1b82SRich Murphey #include <stdio.h> 42699e1b82SRich Murphey #include <stdlib.h> 43699e1b82SRich Murphey #include <unistd.h> 44b9ae52e3SPaul Richards 45170fa4e8SJohn Polstra extern void dump_file __P((const char *)); 469731d137SPeter Wemm extern int error_count; 479731d137SPeter Wemm 48b9ae52e3SPaul Richards void 49b9ae52e3SPaul Richards usage() 50b9ae52e3SPaul Richards { 5145f4c7f9SBruce Evans fprintf(stderr, "usage: ldd [-v] [-f format] program ...\n"); 52699e1b82SRich Murphey exit(1); 53b9ae52e3SPaul Richards } 54b9ae52e3SPaul Richards 55b9ae52e3SPaul Richards int 56b9ae52e3SPaul Richards main(argc, argv) 57b9ae52e3SPaul Richards int argc; 58b9ae52e3SPaul Richards char *argv[]; 59b9ae52e3SPaul Richards { 60d138df61SPeter Wemm char *fmt1 = NULL, *fmt2 = NULL; 61699e1b82SRich Murphey int rval; 62b9ae52e3SPaul Richards int c; 63fecaa127SPeter Wemm int vflag = 0; 64b9ae52e3SPaul Richards 6562f882d6SWarner Losh while ((c = getopt(argc, argv, "vf:")) != -1) { 66b9ae52e3SPaul Richards switch (c) { 679731d137SPeter Wemm case 'v': 689731d137SPeter Wemm vflag++; 699731d137SPeter Wemm break; 70d138df61SPeter Wemm case 'f': 71d138df61SPeter Wemm if (fmt1) { 72d138df61SPeter Wemm if (fmt2) 733e762626SPhilippe Charnier errx(1, "too many formats"); 74d138df61SPeter Wemm fmt2 = optarg; 75d138df61SPeter Wemm } else 76d138df61SPeter Wemm fmt1 = optarg; 77d138df61SPeter Wemm break; 78b9ae52e3SPaul Richards default: 79b9ae52e3SPaul Richards usage(); 80699e1b82SRich Murphey /*NOTREACHED*/ 81b9ae52e3SPaul Richards } 82b9ae52e3SPaul Richards } 83b9ae52e3SPaul Richards argc -= optind; 84b9ae52e3SPaul Richards argv += optind; 85b9ae52e3SPaul Richards 869731d137SPeter Wemm if (vflag && fmt1) 879731d137SPeter Wemm errx(1, "-v may not be used with -f"); 889731d137SPeter Wemm 89b9ae52e3SPaul Richards if (argc <= 0) { 90b9ae52e3SPaul Richards usage(); 91699e1b82SRich Murphey /*NOTREACHED*/ 92b9ae52e3SPaul Richards } 93b9ae52e3SPaul Richards 9497db68b6SDoug Rabson #ifdef __i386__ 959731d137SPeter Wemm if (vflag) { 969731d137SPeter Wemm for (c = 0; c < argc; c++) 979731d137SPeter Wemm dump_file(argv[c]); 989731d137SPeter Wemm exit(error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 999731d137SPeter Wemm } 10097db68b6SDoug Rabson #endif 1019731d137SPeter Wemm 102b9ae52e3SPaul Richards /* ld.so magic */ 10318c0f29eSJohn Polstra setenv("LD_TRACE_LOADED_OBJECTS", "1", 1); 104d138df61SPeter Wemm if (fmt1) 105d138df61SPeter Wemm setenv("LD_TRACE_LOADED_OBJECTS_FMT1", fmt1, 1); 106d138df61SPeter Wemm if (fmt2) 107d138df61SPeter Wemm setenv("LD_TRACE_LOADED_OBJECTS_FMT2", fmt2, 1); 108b9ae52e3SPaul Richards 109699e1b82SRich Murphey rval = 0; 110e2daa140SJohn Polstra for ( ; argc > 0; argc--, argv++) { 111b9ae52e3SPaul Richards int fd; 112e2daa140SJohn Polstra union { 113e2daa140SJohn Polstra struct exec aout; 11497db68b6SDoug Rabson Elf_Ehdr elf; 115e2daa140SJohn Polstra } hdr; 116e2daa140SJohn Polstra int n; 117b9ae52e3SPaul Richards int status; 118e2daa140SJohn Polstra int file_ok; 119b9ae52e3SPaul Richards 120b9ae52e3SPaul Richards if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 121699e1b82SRich Murphey warn("%s", *argv); 122b9ae52e3SPaul Richards rval |= 1; 123b9ae52e3SPaul Richards continue; 124b9ae52e3SPaul Richards } 125e2daa140SJohn Polstra if ((n = read(fd, &hdr, sizeof hdr)) == -1) { 126e2daa140SJohn Polstra warn("%s: can't read program header", *argv); 127c474c6d3SDoug Rabson (void)close(fd); 128c474c6d3SDoug Rabson rval |= 1; 129c474c6d3SDoug Rabson continue; 130c474c6d3SDoug Rabson } 131c474c6d3SDoug Rabson 132e2daa140SJohn Polstra file_ok = 1; 133e2daa140SJohn Polstra if (n >= sizeof hdr.aout && !N_BADMAG(hdr.aout)) { 134c474c6d3SDoug Rabson /* a.out file */ 135e2daa140SJohn Polstra if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC 13661f9ce8dSNate Williams #if 1 /* Compatibility */ 137e2daa140SJohn Polstra || hdr.aout.a_entry < __LDPGSZ 13861f9ce8dSNate Williams #endif 13961f9ce8dSNate Williams ) { 140699e1b82SRich Murphey warnx("%s: not a dynamic executable", *argv); 141e2daa140SJohn Polstra file_ok = 0; 142b9ae52e3SPaul Richards } 143e2daa140SJohn Polstra } else if (n >= sizeof hdr.elf && IS_ELF(hdr.elf)) { 14497db68b6SDoug Rabson Elf_Ehdr ehdr; 14597db68b6SDoug Rabson Elf_Phdr phdr; 146c474c6d3SDoug Rabson int dynamic = 0, i; 147c474c6d3SDoug Rabson 148e6f0df2bSAndrey A. Chernov if (lseek(fd, 0, SEEK_SET) == -1 || 149e6f0df2bSAndrey A. Chernov read(fd, &ehdr, sizeof ehdr) != sizeof ehdr || 150e6f0df2bSAndrey A. Chernov lseek(fd, ehdr.e_phoff, SEEK_SET) == -1 151e6f0df2bSAndrey A. Chernov ) { 152c474c6d3SDoug Rabson warnx("%s: can't read program header", *argv); 153e2daa140SJohn Polstra file_ok = 0; 154e6f0df2bSAndrey A. Chernov } else { 155c474c6d3SDoug Rabson for (i = 0; i < ehdr.e_phnum; i++) { 156c474c6d3SDoug Rabson if (read(fd, &phdr, ehdr.e_phentsize) 157c474c6d3SDoug Rabson != sizeof phdr) { 158e2daa140SJohn Polstra warnx("%s: can't read program header", 159e2daa140SJohn Polstra *argv); 160e2daa140SJohn Polstra file_ok = 0; 161e6f0df2bSAndrey A. Chernov break; 162c474c6d3SDoug Rabson } 163c474c6d3SDoug Rabson if (phdr.p_type == PT_DYNAMIC) 164c474c6d3SDoug Rabson dynamic = 1; 165c474c6d3SDoug Rabson } 166e6f0df2bSAndrey A. Chernov } 167c474c6d3SDoug Rabson if (!dynamic) { 168c474c6d3SDoug Rabson warnx("%s: not a dynamic executable", *argv); 169e2daa140SJohn Polstra file_ok = 0; 170e2daa140SJohn Polstra } 171e2daa140SJohn Polstra } else { 172e2daa140SJohn Polstra warnx("%s: not a dynamic executable", *argv); 173e2daa140SJohn Polstra file_ok = 0; 174e2daa140SJohn Polstra } 175c474c6d3SDoug Rabson (void)close(fd); 176e2daa140SJohn Polstra if (!file_ok) { 177c474c6d3SDoug Rabson rval |= 1; 178c474c6d3SDoug Rabson continue; 179c474c6d3SDoug Rabson } 180b9ae52e3SPaul Richards 181d138df61SPeter Wemm setenv("LD_TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1); 182d138df61SPeter Wemm if (fmt1 == NULL && fmt2 == NULL) 183d138df61SPeter Wemm /* Default formats */ 184b9ae52e3SPaul Richards printf("%s:\n", *argv); 185d138df61SPeter Wemm 18609e3d49dSJordan K. Hubbard fflush(stdout); 187b9ae52e3SPaul Richards 188b9ae52e3SPaul Richards switch (fork()) { 189b9ae52e3SPaul Richards case -1: 190699e1b82SRich Murphey err(1, "fork"); 191b9ae52e3SPaul Richards break; 192b9ae52e3SPaul Richards default: 193699e1b82SRich Murphey if (wait(&status) <= 0) { 194699e1b82SRich Murphey warn("wait"); 195699e1b82SRich Murphey rval |= 1; 196699e1b82SRich Murphey } else if (WIFSIGNALED(status)) { 197b9ae52e3SPaul Richards fprintf(stderr, "%s: signal %d\n", 198b9ae52e3SPaul Richards *argv, WTERMSIG(status)); 199b9ae52e3SPaul Richards rval |= 1; 200b9ae52e3SPaul Richards } else if (WIFEXITED(status) && WEXITSTATUS(status)) { 201b9ae52e3SPaul Richards fprintf(stderr, "%s: exit status %d\n", 202b9ae52e3SPaul Richards *argv, WEXITSTATUS(status)); 203b9ae52e3SPaul Richards rval |= 1; 204b9ae52e3SPaul Richards } 205b9ae52e3SPaul Richards break; 206b9ae52e3SPaul Richards case 0: 207699e1b82SRich Murphey rval |= execl(*argv, *argv, NULL) != 0; 2083e762626SPhilippe Charnier warn("%s", *argv); 209b9ae52e3SPaul Richards _exit(1); 210b9ae52e3SPaul Richards } 211b9ae52e3SPaul Richards } 212b9ae52e3SPaul Richards 213b9ae52e3SPaul Richards return rval; 214b9ae52e3SPaul Richards } 215