ldd.c revision 21576
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 * 3021576Sjdp * $Id: ldd.c,v 1.10 1996/11/30 16:12:46 bde 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> 401741Srich#include <err.h> 411741Srich#include <fcntl.h> 421741Srich#include <stdio.h> 431741Srich#include <stdlib.h> 441741Srich#include <string.h> 451741Srich#include <unistd.h> 46696Spaul 4718600Speterextern void dump_filename __P((const char *)); 4818600Speterextern int error_count; 4918600Speter 50696Spaulvoid 51696Spaulusage() 52696Spaul{ 5320050Sbde fprintf(stderr, "usage: ldd [-v] [-f format] program ...\n"); 541741Srich exit(1); 55696Spaul} 56696Spaul 57696Spaulint 58696Spaulmain(argc, argv) 59696Spaulint argc; 60696Spaulchar *argv[]; 61696Spaul{ 6218598Speter char *fmt1 = NULL, *fmt2 = NULL; 631741Srich int rval; 64696Spaul int c; 6519253Speter int vflag = 0; 66696Spaul 6718600Speter while ((c = getopt(argc, argv, "vf:")) != EOF) { 68696Spaul switch (c) { 6918600Speter case 'v': 7018600Speter vflag++; 7118600Speter break; 7218598Speter case 'f': 7318598Speter if (fmt1) { 7418598Speter if (fmt2) 7518598Speter errx(1, "Too many formats"); 7618598Speter fmt2 = optarg; 7718598Speter } else 7818598Speter fmt1 = optarg; 7918598Speter break; 80696Spaul default: 81696Spaul usage(); 821741Srich /*NOTREACHED*/ 83696Spaul } 84696Spaul } 85696Spaul argc -= optind; 86696Spaul argv += optind; 87696Spaul 8818600Speter if (vflag && fmt1) 8918600Speter errx(1, "-v may not be used with -f"); 9018600Speter 91696Spaul if (argc <= 0) { 92696Spaul usage(); 931741Srich /*NOTREACHED*/ 94696Spaul } 95696Spaul 9618600Speter if (vflag) { 9718600Speter for (c = 0; c < argc; c++) 9818600Speter dump_file(argv[c]); 9918600Speter exit(error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 10018600Speter } 10118600Speter 102696Spaul /* ld.so magic */ 10321576Sjdp setenv("LD_TRACE_LOADED_OBJECTS", "1", 1); 10418598Speter if (fmt1) 10518598Speter setenv("LD_TRACE_LOADED_OBJECTS_FMT1", fmt1, 1); 10618598Speter if (fmt2) 10718598Speter setenv("LD_TRACE_LOADED_OBJECTS_FMT2", fmt2, 1); 108696Spaul 1091741Srich rval = 0; 110696Spaul while (argc--) { 111696Spaul int fd; 112696Spaul struct exec hdr; 113696Spaul int status; 114696Spaul 115696Spaul if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 1161741Srich warn("%s", *argv); 117696Spaul rval |= 1; 118696Spaul argv++; 119696Spaul continue; 120696Spaul } 1215205Snate if (read(fd, &hdr, sizeof hdr) != sizeof hdr 1225205Snate || (N_GETFLAG(hdr) & EX_DPMASK) != EX_DYNAMIC 1235205Snate#if 1 /* Compatibility */ 1245205Snate || hdr.a_entry < __LDPGSZ 1255205Snate#endif 1265205Snate ) { 1271741Srich 1281741Srich warnx("%s: not a dynamic executable", *argv); 129696Spaul (void)close(fd); 130696Spaul rval |= 1; 131696Spaul argv++; 132696Spaul continue; 133696Spaul } 134696Spaul (void)close(fd); 135696Spaul 13618598Speter setenv("LD_TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1); 13718598Speter if (fmt1 == NULL && fmt2 == NULL) 13818598Speter /* Default formats */ 13918598Speter printf("%s:\n", *argv); 14018598Speter 1411153Sjkh fflush(stdout); 142696Spaul 143696Spaul switch (fork()) { 144696Spaul case -1: 1451741Srich err(1, "fork"); 146696Spaul break; 147696Spaul default: 1481741Srich if (wait(&status) <= 0) { 1491741Srich warn("wait"); 1501741Srich rval |= 1; 1511741Srich } else if (WIFSIGNALED(status)) { 152696Spaul fprintf(stderr, "%s: signal %d\n", 153696Spaul *argv, WTERMSIG(status)); 154696Spaul rval |= 1; 155696Spaul } else if (WIFEXITED(status) && WEXITSTATUS(status)) { 156696Spaul fprintf(stderr, "%s: exit status %d\n", 157696Spaul *argv, WEXITSTATUS(status)); 158696Spaul rval |= 1; 159696Spaul } 160696Spaul break; 161696Spaul case 0: 1621741Srich rval |= execl(*argv, *argv, NULL) != 0; 163696Spaul perror(*argv); 164696Spaul _exit(1); 165696Spaul } 166696Spaul argv++; 167696Spaul } 168696Spaul 169696Spaul return rval; 170696Spaul} 171