ldd.c revision 35575
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 * 3035575Sdfr * $Id: ldd.c,v 1.14 1997/09/02 21:54:39 jdp 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; 111696Spaul while (argc--) { 112696Spaul int fd; 113696Spaul struct exec hdr; 114696Spaul int status; 115696Spaul 116696Spaul if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 1171741Srich warn("%s", *argv); 118696Spaul rval |= 1; 119696Spaul argv++; 120696Spaul continue; 121696Spaul } 12235575Sdfr if (read(fd, &hdr, sizeof hdr) != sizeof hdr) { 12335575Sdfr warnx("%s: can't read program header", *argv); 124696Spaul (void)close(fd); 125696Spaul rval |= 1; 126696Spaul argv++; 127696Spaul continue; 128696Spaul } 12935575Sdfr 13035575Sdfr if (!N_BADMAG(hdr)) { 13135575Sdfr /* a.out file */ 13235575Sdfr if ((N_GETFLAG(hdr) & EX_DPMASK) != EX_DYNAMIC 13335575Sdfr#if 1 /* Compatibility */ 13435575Sdfr || hdr.a_entry < __LDPGSZ 13535575Sdfr#endif 13635575Sdfr ) { 13735575Sdfr warnx("%s: not a dynamic executable", *argv); 13835575Sdfr (void)close(fd); 13935575Sdfr rval |= 1; 14035575Sdfr argv++; 14135575Sdfr continue; 14235575Sdfr } 14335575Sdfr } else if (IS_ELF(*(Elf32_Ehdr*)&hdr)) { 14435575Sdfr Elf32_Ehdr ehdr; 14535575Sdfr Elf32_Phdr phdr; 14635575Sdfr int dynamic = 0, i; 14735575Sdfr 14835575Sdfr lseek(fd, 0, SEEK_SET); 14935575Sdfr if (read(fd, &ehdr, sizeof ehdr) != sizeof ehdr) { 15035575Sdfr warnx("%s: can't read program header", *argv); 15135575Sdfr (void)close(fd); 15235575Sdfr rval |= 1; 15335575Sdfr argv++; 15435575Sdfr continue; 15535575Sdfr } 15635575Sdfr lseek(fd, 0, ehdr.e_phoff); 15735575Sdfr for (i = 0; i < ehdr.e_phnum; i++) { 15835575Sdfr if (read(fd, &phdr, ehdr.e_phentsize) 15935575Sdfr != sizeof phdr) { 16035575Sdfr warnx("%s: can't read program header", *argv); 16135575Sdfr (void)close(fd); 16235575Sdfr rval |= 1; 16335575Sdfr argv++; 16435575Sdfr continue; 16535575Sdfr } 16635575Sdfr if (phdr.p_type == PT_DYNAMIC) 16735575Sdfr dynamic = 1; 16835575Sdfr } 16935575Sdfr if (!dynamic) { 17035575Sdfr warnx("%s: not a dynamic executable", *argv); 17135575Sdfr (void)close(fd); 17235575Sdfr rval |= 1; 17335575Sdfr argv++; 17435575Sdfr continue; 17535575Sdfr } 17635575Sdfr } 177696Spaul (void)close(fd); 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 argv++; 210696Spaul } 211696Spaul 212696Spaul return rval; 213696Spaul} 214