ldd.c revision 39354
1178355Ssam/* 2178355Ssam * Copyright (c) 1993 Paul Kranenburg 3178355Ssam * All rights reserved. 4208060Sdougb * 5178355Ssam * Redistribution and use in source and binary forms, with or without 6178355Ssam * modification, are permitted provided that the following conditions 7178355Ssam * are met: 8178355Ssam * 1. Redistributions of source code must retain the above copyright 9178355Ssam * notice, this list of conditions and the following disclaimer. 10178355Ssam * 2. Redistributions in binary form must reproduce the above copyright 11178355Ssam * notice, this list of conditions and the following disclaimer in the 12178355Ssam * documentation and/or other materials provided with the distribution. 13208060Sdougb * 3. All advertising materials mentioning features or use of this software 14178355Ssam * must display the following acknowledgement: 15178355Ssam * This product includes software developed by Paul Kranenburg. 16178355Ssam * 4. The name of the author may not be used to endorse or promote products 17178355Ssam * derived from this software without specific prior written permission 18178355Ssam * 19178355Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20178355Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21178355Ssam * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22178355Ssam * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23178355Ssam * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24208060Sdougb * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25178355Ssam * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26178355Ssam * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27178355Ssam * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28178355Ssam * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29178355Ssam * 30178355Ssam * $Id: ldd.c,v 1.16 1998/08/30 18:30:59 jdp Exp $ 31178355Ssam */ 32178355Ssam 33178355Ssam#include <sys/types.h> 34178355Ssam#include <sys/stat.h> 35178355Ssam#include <sys/file.h> 36178355Ssam#include <sys/time.h> 37178355Ssam#include <sys/resource.h> 38178355Ssam#include <sys/wait.h> 39178355Ssam#include <a.out.h> 40178355Ssam#include <elf.h> 41178355Ssam#include <err.h> 42186106Ssam#include <fcntl.h> 43178355Ssam#include <stdio.h> 44178355Ssam#include <stdlib.h> 45178355Ssam#include <string.h> 46178355Ssam#include <unistd.h> 47178355Ssam 48178355Ssamextern void dump_file __P((const char *)); 49178355Ssamextern int error_count; 50178355Ssam 51178355Ssamvoid 52178355Ssamusage() 53178355Ssam{ 54178355Ssam fprintf(stderr, "usage: ldd [-v] [-f format] program ...\n"); 55178355Ssam exit(1); 56178355Ssam} 57178355Ssam 58178355Ssamint 59178355Ssammain(argc, argv) 60178355Ssamint argc; 61178355Ssamchar *argv[]; 62178355Ssam{ 63178355Ssam char *fmt1 = NULL, *fmt2 = NULL; 64178355Ssam int rval; 65178355Ssam int c; 66178355Ssam int vflag = 0; 67178355Ssam 68178355Ssam while ((c = getopt(argc, argv, "vf:")) != EOF) { 69178355Ssam switch (c) { 70178355Ssam case 'v': 71178355Ssam vflag++; 72178355Ssam break; 73178355Ssam case 'f': 74178355Ssam if (fmt1) { 75178355Ssam if (fmt2) 76178355Ssam errx(1, "Too many formats"); 77178355Ssam fmt2 = optarg; 78178355Ssam } else 79178355Ssam fmt1 = optarg; 80178355Ssam break; 81178355Ssam default: 82178355Ssam usage(); 83178355Ssam /*NOTREACHED*/ 84178355Ssam } 85178355Ssam } 86223497Sadrian argc -= optind; 87178355Ssam argv += optind; 88178355Ssam 89178355Ssam if (vflag && fmt1) 90178355Ssam errx(1, "-v may not be used with -f"); 91178355Ssam 92178355Ssam if (argc <= 0) { 93178355Ssam usage(); 94178355Ssam /*NOTREACHED*/ 95178355Ssam } 96178355Ssam 97178355Ssam#ifdef __i386__ 98178355Ssam if (vflag) { 99223498Sadrian for (c = 0; c < argc; c++) 100178355Ssam dump_file(argv[c]); 101178355Ssam exit(error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 102178355Ssam } 103178355Ssam#endif 104178355Ssam 105178355Ssam /* ld.so magic */ 106178355Ssam setenv("LD_TRACE_LOADED_OBJECTS", "1", 1); 107178355Ssam if (fmt1) 108178355Ssam setenv("LD_TRACE_LOADED_OBJECTS_FMT1", fmt1, 1); 109223498Sadrian if (fmt2) 110178355Ssam setenv("LD_TRACE_LOADED_OBJECTS_FMT2", fmt2, 1); 111178355Ssam 112178355Ssam rval = 0; 113178355Ssam for ( ; argc > 0; argc--, argv++) { 114178355Ssam int fd; 115178355Ssam union { 116178355Ssam struct exec aout; 117178355Ssam Elf_Ehdr elf; 118178355Ssam } hdr; 119178355Ssam int n; 120178355Ssam int status; 121178355Ssam int file_ok; 122178355Ssam 123178355Ssam if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 124178355Ssam warn("%s", *argv); 125178355Ssam rval |= 1; 126178355Ssam continue; 127178355Ssam } 128178355Ssam if ((n = read(fd, &hdr, sizeof hdr)) == -1) { 129178355Ssam warn("%s: can't read program header", *argv); 130178355Ssam (void)close(fd); 131178355Ssam rval |= 1; 132178355Ssam continue; 133178355Ssam } 134178355Ssam 135178355Ssam file_ok = 1; 136178355Ssam if (n >= sizeof hdr.aout && !N_BADMAG(hdr.aout)) { 137178355Ssam /* a.out file */ 138178355Ssam if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC 139178355Ssam#if 1 /* Compatibility */ 140178355Ssam || hdr.aout.a_entry < __LDPGSZ 141223496Sadrian#endif 142223564Sadrian ) { 143223496Sadrian warnx("%s: not a dynamic executable", *argv); 144223496Sadrian file_ok = 0; 145223496Sadrian } 146223496Sadrian } else if (n >= sizeof hdr.elf && IS_ELF(hdr.elf)) { 147223563Sadrian Elf_Ehdr ehdr; 148223564Sadrian Elf_Phdr phdr; 149223563Sadrian int dynamic = 0, i; 150223563Sadrian 151223563Sadrian lseek(fd, 0, SEEK_SET); 152223563Sadrian if (read(fd, &ehdr, sizeof ehdr) != sizeof ehdr) { 153223563Sadrian warnx("%s: can't read program header", *argv); 154223564Sadrian file_ok = 0; 155223563Sadrian } 156223563Sadrian lseek(fd, 0, ehdr.e_phoff); 157223563Sadrian for (i = 0; i < ehdr.e_phnum; i++) { 158223563Sadrian if (read(fd, &phdr, ehdr.e_phentsize) 159178355Ssam != sizeof phdr) { 160178355Ssam warnx("%s: can't read program header", 161178355Ssam *argv); 162178355Ssam file_ok = 0; 163178355Ssam } 164178355Ssam if (phdr.p_type == PT_DYNAMIC) 165178355Ssam dynamic = 1; 166178355Ssam } 167178355Ssam if (!dynamic) { 168178355Ssam warnx("%s: not a dynamic executable", *argv); 169178355Ssam file_ok = 0; 170178355Ssam } 171178355Ssam } else { 172178355Ssam warnx("%s: not a dynamic executable", *argv); 173178355Ssam file_ok = 0; 174178355Ssam } 175178355Ssam (void)close(fd); 176178355Ssam if (!file_ok) { 177178355Ssam rval |= 1; 178178355Ssam continue; 179178355Ssam } 180178355Ssam 181178355Ssam setenv("LD_TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1); 182178355Ssam if (fmt1 == NULL && fmt2 == NULL) 183178355Ssam /* Default formats */ 184178355Ssam printf("%s:\n", *argv); 185178355Ssam 186178355Ssam fflush(stdout); 187178355Ssam 188178355Ssam switch (fork()) { 189178355Ssam case -1: 190178355Ssam err(1, "fork"); 191178355Ssam break; 192178355Ssam default: 193178355Ssam if (wait(&status) <= 0) { 194178355Ssam warn("wait"); 195178355Ssam rval |= 1; 196178355Ssam } else if (WIFSIGNALED(status)) { 197223496Sadrian fprintf(stderr, "%s: signal %d\n", 198223564Sadrian *argv, WTERMSIG(status)); 199223496Sadrian rval |= 1; 200223496Sadrian } else if (WIFEXITED(status) && WEXITSTATUS(status)) { 201223496Sadrian fprintf(stderr, "%s: exit status %d\n", 202223496Sadrian *argv, WEXITSTATUS(status)); 203223496Sadrian rval |= 1; 204223496Sadrian } 205223564Sadrian break; 206223496Sadrian case 0: 207223496Sadrian rval |= execl(*argv, *argv, NULL) != 0; 208223496Sadrian perror(*argv); 209223496Sadrian _exit(1); 210223496Sadrian } 211223563Sadrian } 212223564Sadrian 213223563Sadrian return rval; 214223563Sadrian} 215223563Sadrian