ldd.c revision 38648
1696Spaul/* 2696Spaul * Copyright (c) 1993 Paul Kranenburg 3696Spaul * All rights reserved. 4696Spaul * 5696Spaul * Redistribution and use in source and binary forms, with or without 6696Spaul * modification, are permitted provided that the following conditions 7696Spaul * are met: 8696Spaul * 1. Redistributions of source code must retain the above copyright 9696Spaul * notice, this list of conditions and the following disclaimer. 10696Spaul * 2. Redistributions in binary form must reproduce the above copyright 11696Spaul * notice, this list of conditions and the following disclaimer in the 12696Spaul * documentation and/or other materials provided with the distribution. 13696Spaul * 3. All advertising materials mentioning features or use of this software 14696Spaul * must display the following acknowledgement: 15696Spaul * This product includes software developed by Paul Kranenburg. 16696Spaul * 4. The name of the author may not be used to endorse or promote products 171153Sjkh * derived from this software without specific prior written permission 18696Spaul * 19696Spaul * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20696Spaul * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21696Spaul * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22696Spaul * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23696Spaul * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24696Spaul * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25696Spaul * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26696Spaul * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27696Spaul * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28696Spaul * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29696Spaul * 3038648Sjdp * $Id: ldd.c,v 1.15 1998/05/01 08:40:11 dfr Exp $ 31696Spaul */ 32696Spaul 33696Spaul#include <sys/types.h> 34696Spaul#include <sys/stat.h> 35696Spaul#include <sys/file.h> 36696Spaul#include <sys/time.h> 37696Spaul#include <sys/resource.h> 38696Spaul#include <sys/wait.h> 39696Spaul#include <a.out.h> 4035575Sdfr#include <elf.h> 411741Srich#include <err.h> 421741Srich#include <fcntl.h> 431741Srich#include <stdio.h> 441741Srich#include <stdlib.h> 451741Srich#include <string.h> 461741Srich#include <unistd.h> 47696Spaul 4829042Sjdpextern void dump_file __P((const char *)); 4918600Speterextern int error_count; 5018600Speter 51696Spaulvoid 52696Spaulusage() 53696Spaul{ 5420050Sbde fprintf(stderr, "usage: ldd [-v] [-f format] program ...\n"); 551741Srich exit(1); 56696Spaul} 57696Spaul 58696Spaulint 59696Spaulmain(argc, argv) 60696Spaulint argc; 61696Spaulchar *argv[]; 62696Spaul{ 6318598Speter char *fmt1 = NULL, *fmt2 = NULL; 641741Srich int rval; 65696Spaul int c; 6619253Speter int vflag = 0; 67696Spaul 6818600Speter while ((c = getopt(argc, argv, "vf:")) != EOF) { 69696Spaul switch (c) { 7018600Speter case 'v': 7118600Speter vflag++; 7218600Speter break; 7318598Speter case 'f': 7418598Speter if (fmt1) { 7518598Speter if (fmt2) 7618598Speter errx(1, "Too many formats"); 7718598Speter fmt2 = optarg; 7818598Speter } else 7918598Speter fmt1 = optarg; 8018598Speter break; 81696Spaul default: 82696Spaul usage(); 831741Srich /*NOTREACHED*/ 84696Spaul } 85696Spaul } 86696Spaul argc -= optind; 87696Spaul argv += optind; 88696Spaul 8918600Speter if (vflag && fmt1) 9018600Speter errx(1, "-v may not be used with -f"); 9118600Speter 92696Spaul if (argc <= 0) { 93696Spaul usage(); 941741Srich /*NOTREACHED*/ 95696Spaul } 96696Spaul 9718600Speter if (vflag) { 9818600Speter for (c = 0; c < argc; c++) 9918600Speter dump_file(argv[c]); 10018600Speter exit(error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 10118600Speter } 10218600Speter 103696Spaul /* ld.so magic */ 10421576Sjdp setenv("LD_TRACE_LOADED_OBJECTS", "1", 1); 10518598Speter if (fmt1) 10618598Speter setenv("LD_TRACE_LOADED_OBJECTS_FMT1", fmt1, 1); 10718598Speter if (fmt2) 10818598Speter setenv("LD_TRACE_LOADED_OBJECTS_FMT2", fmt2, 1); 109696Spaul 1101741Srich rval = 0; 11138648Sjdp for ( ; argc > 0; argc--, argv++) { 112696Spaul int fd; 11338648Sjdp union { 11438648Sjdp struct exec aout; 11538648Sjdp Elf32_Ehdr elf; 11638648Sjdp } hdr; 11738648Sjdp int n; 118696Spaul int status; 11938648Sjdp int file_ok; 120696Spaul 121696Spaul if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 1221741Srich warn("%s", *argv); 123696Spaul rval |= 1; 124696Spaul continue; 125696Spaul } 12638648Sjdp if ((n = read(fd, &hdr, sizeof hdr)) == -1) { 12738648Sjdp warn("%s: can't read program header", *argv); 128696Spaul (void)close(fd); 129696Spaul rval |= 1; 130696Spaul continue; 131696Spaul } 13235575Sdfr 13338648Sjdp file_ok = 1; 13438648Sjdp if (n >= sizeof hdr.aout && !N_BADMAG(hdr.aout)) { 13535575Sdfr /* a.out file */ 13638648Sjdp if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC 13735575Sdfr#if 1 /* Compatibility */ 13838648Sjdp || hdr.aout.a_entry < __LDPGSZ 13935575Sdfr#endif 14035575Sdfr ) { 14135575Sdfr warnx("%s: not a dynamic executable", *argv); 14238648Sjdp file_ok = 0; 14335575Sdfr } 14438648Sjdp } else if (n >= sizeof hdr.elf && IS_ELF(hdr.elf)) { 14535575Sdfr Elf32_Ehdr ehdr; 14635575Sdfr Elf32_Phdr phdr; 14735575Sdfr int dynamic = 0, i; 14835575Sdfr 14935575Sdfr lseek(fd, 0, SEEK_SET); 15035575Sdfr if (read(fd, &ehdr, sizeof ehdr) != sizeof ehdr) { 15135575Sdfr warnx("%s: can't read program header", *argv); 15238648Sjdp file_ok = 0; 15335575Sdfr } 15435575Sdfr lseek(fd, 0, ehdr.e_phoff); 15535575Sdfr for (i = 0; i < ehdr.e_phnum; i++) { 15635575Sdfr if (read(fd, &phdr, ehdr.e_phentsize) 15735575Sdfr != sizeof phdr) { 15838648Sjdp warnx("%s: can't read program header", 15938648Sjdp *argv); 16038648Sjdp file_ok = 0; 16135575Sdfr } 16235575Sdfr if (phdr.p_type == PT_DYNAMIC) 16335575Sdfr dynamic = 1; 16435575Sdfr } 16535575Sdfr if (!dynamic) { 16635575Sdfr warnx("%s: not a dynamic executable", *argv); 16738648Sjdp file_ok = 0; 16835575Sdfr } 16938648Sjdp } else { 17038648Sjdp warnx("%s: not a dynamic executable", *argv); 17138648Sjdp file_ok = 0; 17235575Sdfr } 173696Spaul (void)close(fd); 17438648Sjdp if (!file_ok) { 17538648Sjdp rval |= 1; 17638648Sjdp continue; 17738648Sjdp } 178696Spaul 17918598Speter setenv("LD_TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1); 18018598Speter if (fmt1 == NULL && fmt2 == NULL) 18118598Speter /* Default formats */ 18218598Speter printf("%s:\n", *argv); 18318598Speter 1841153Sjkh fflush(stdout); 185696Spaul 186696Spaul switch (fork()) { 187696Spaul case -1: 1881741Srich err(1, "fork"); 189696Spaul break; 190696Spaul default: 1911741Srich if (wait(&status) <= 0) { 1921741Srich warn("wait"); 1931741Srich rval |= 1; 1941741Srich } else if (WIFSIGNALED(status)) { 195696Spaul fprintf(stderr, "%s: signal %d\n", 196696Spaul *argv, WTERMSIG(status)); 197696Spaul rval |= 1; 198696Spaul } else if (WIFEXITED(status) && WEXITSTATUS(status)) { 199696Spaul fprintf(stderr, "%s: exit status %d\n", 200696Spaul *argv, WEXITSTATUS(status)); 201696Spaul rval |= 1; 202696Spaul } 203696Spaul break; 204696Spaul case 0: 2051741Srich rval |= execl(*argv, *argv, NULL) != 0; 206696Spaul perror(*argv); 207696Spaul _exit(1); 208696Spaul } 209696Spaul } 210696Spaul 211696Spaul return rval; 212696Spaul} 213