ldd.c revision 294665
190075Sobrien/*
290075Sobrien * Copyright (c) 1993 Paul Kranenburg
3110611Skan * All rights reserved.
490075Sobrien *
590075Sobrien * Redistribution and use in source and binary forms, with or without
690075Sobrien * modification, are permitted provided that the following conditions
790075Sobrien * are met:
890075Sobrien * 1. Redistributions of source code must retain the above copyright
990075Sobrien *    notice, this list of conditions and the following disclaimer.
1090075Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1190075Sobrien *    notice, this list of conditions and the following disclaimer in the
1290075Sobrien *    documentation and/or other materials provided with the distribution.
1390075Sobrien * 3. All advertising materials mentioning features or use of this software
1490075Sobrien *    must display the following acknowledgement:
1590075Sobrien *      This product includes software developed by Paul Kranenburg.
1690075Sobrien * 4. The name of the author may not be used to endorse or promote products
1790075Sobrien *    derived from this software without specific prior written permission
1890075Sobrien *
1990075Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2090075Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2190075Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2290075Sobrien * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2390075Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2490075Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25132718Skan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26132718Skan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2790075Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2890075Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2990075Sobrien */
3096263Sobrien
3196263Sobrien#include <sys/cdefs.h>
3290075Sobrien__FBSDID("$FreeBSD: head/usr.bin/ldd/ldd.c 294665 2016-01-24 15:15:57Z br $");
3396263Sobrien
3490075Sobrien#include <sys/wait.h>
3590075Sobrien
3690075Sobrien#include <machine/elf.h>
3790075Sobrien
3890075Sobrien#include <arpa/inet.h>
3990075Sobrien
4090075Sobrien#include <dlfcn.h>
4190075Sobrien#include <err.h>
4290075Sobrien#include <errno.h>
4390075Sobrien#include <fcntl.h>
4490075Sobrien#include <stdio.h>
4590075Sobrien#include <stdlib.h>
4690075Sobrien#include <string.h>
4790075Sobrien#include <unistd.h>
4890075Sobrien
49132718Skan#include "extern.h"
50132718Skan
51132718Skan/* We don't support a.out executables on arm64 and riscv */
52132718Skan#if !defined(__aarch64__) && !defined(__riscv__)
53132718Skan#include <a.out.h>
54132718Skan#define	AOUT_SUPPORTED
55132718Skan#endif
56132718Skan
5790075Sobrien/*
58107590Sobrien * 32-bit ELF data structures can only be used if the system header[s] declare
59107590Sobrien * them.  There is no official macro for determining whether they are declared,
60107590Sobrien * so check for the existence of one of the 32-macros defined in elf(5).
61107590Sobrien */
62132718Skan#ifdef ELF32_R_TYPE
63107590Sobrien#define	ELF32_SUPPORTED
64107590Sobrien#endif
65107590Sobrien
66107590Sobrien#define	LDD_SETENV(name, value, overwrite) do {		\
67132718Skan	setenv("LD_" name, value, overwrite);		\
68117395Skan	setenv("LD_32_" name, value, overwrite);	\
69107590Sobrien} while (0)
70107590Sobrien
71107590Sobrien#define	LDD_UNSETENV(name) do {		\
72107590Sobrien	unsetenv("LD_" name);		\
73107590Sobrien	unsetenv("LD_32_" name);	\
74107590Sobrien} while (0)
75107590Sobrien
76107590Sobrienstatic int	is_executable(const char *fname, int fd, int *is_shlib,
77107590Sobrien		    int *type);
78107590Sobrienstatic void	usage(void);
79107590Sobrien
8090075Sobrien#define	TYPE_UNKNOWN	0
8190075Sobrien#define	TYPE_AOUT	1
8290075Sobrien#define	TYPE_ELF	2	/* Architecture default */
8390075Sobrien#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
84132718Skan#define	TYPE_ELF32	3	/* Explicit 32 bits on architectures >32 bits */
8590075Sobrien
8690075Sobrien#define	_PATH_LDD32	"/usr/bin/ldd32"
8790075Sobrien
8890075Sobrienstatic int
8990075Sobrienexecldd32(char *file, char *fmt1, char *fmt2, int aflag, int vflag)
9090075Sobrien{
9190075Sobrien	char *argv[8];
92132718Skan	int i, rval, status;
93107590Sobrien
9490075Sobrien	LDD_UNSETENV("TRACE_LOADED_OBJECTS");
9590075Sobrien	rval = 0;
9690075Sobrien	i = 0;
9790075Sobrien	argv[i++] = strdup(_PATH_LDD32);
98107590Sobrien	if (aflag)
9990075Sobrien		argv[i++] = strdup("-a");
10090075Sobrien	if (vflag)
10190075Sobrien		argv[i++] = strdup("-v");
10290075Sobrien	if (fmt1 != NULL) {
10390075Sobrien		argv[i++] = strdup("-f");
104132718Skan		argv[i++] = strdup(fmt1);
10590075Sobrien	}
106132718Skan	if (fmt2 != NULL) {
107132718Skan		argv[i++] = strdup("-f");
10890075Sobrien		argv[i++] = strdup(fmt2);
109117395Skan	}
110117395Skan	argv[i++] = strdup(file);
111117395Skan	argv[i++] = NULL;
112132718Skan
11390075Sobrien	switch (fork()) {
11490075Sobrien	case -1:
11590075Sobrien		err(1, "fork");
11690075Sobrien		break;
11790075Sobrien	case 0:
11890075Sobrien		execv(_PATH_LDD32, argv);
11990075Sobrien		warn("%s", _PATH_LDD32);
120117395Skan		_exit(127);
12190075Sobrien		break;
12290075Sobrien	default:
12390075Sobrien		if (wait(&status) < 0)
12490075Sobrien			rval = 1;
12590075Sobrien		else if (WIFSIGNALED(status))
12690075Sobrien			rval = 1;
12790075Sobrien		else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
12890075Sobrien			rval = 1;
12990075Sobrien		break;
130132718Skan	}
13190075Sobrien	while (i--)
13290075Sobrien		free(argv[i]);
13390075Sobrien	LDD_SETENV("TRACE_LOADED_OBJECTS", "yes", 1);
13490075Sobrien	return (rval);
13590075Sobrien}
13690075Sobrien#endif
13790075Sobrien
13890075Sobrienint
13990075Sobrienmain(int argc, char *argv[])
14090075Sobrien{
14190075Sobrien	char *fmt1, *fmt2;
142132718Skan	int rval, c, aflag, vflag;
143132718Skan
14490075Sobrien	aflag = vflag = 0;
14590075Sobrien	fmt1 = fmt2 = NULL;
146132718Skan
14790075Sobrien	while ((c = getopt(argc, argv, "af:v")) != -1) {
14890075Sobrien		switch (c) {
14990075Sobrien		case 'a':
150117395Skan			aflag++;
15190075Sobrien			break;
15290075Sobrien		case 'f':
15390075Sobrien			if (fmt1 != NULL) {
15490075Sobrien				if (fmt2 != NULL)
15590075Sobrien					errx(1, "too many formats");
15690075Sobrien				fmt2 = optarg;
15790075Sobrien			} else
15890075Sobrien				fmt1 = optarg;
15990075Sobrien			break;
16090075Sobrien		case 'v':
16190075Sobrien			vflag++;
16290075Sobrien			break;
16390075Sobrien		default:
16490075Sobrien			usage();
16590075Sobrien			/* NOTREACHED */
16690075Sobrien		}
16790075Sobrien	}
16890075Sobrien	argc -= optind;
16990075Sobrien	argv += optind;
17090075Sobrien
17190075Sobrien	if (vflag && fmt1 != NULL)
17290075Sobrien		errx(1, "-v may not be used with -f");
17390075Sobrien
17490075Sobrien	if (argc <= 0) {
17590075Sobrien		usage();
17690075Sobrien		/* NOTREACHED */
17790075Sobrien	}
17890075Sobrien
17990075Sobrien#ifdef __i386__
18090075Sobrien	if (vflag) {
18190075Sobrien		for (c = 0; c < argc; c++)
18290075Sobrien			dump_file(argv[c]);
18390075Sobrien		exit(error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
18490075Sobrien	}
18590075Sobrien#endif
18690075Sobrien
18790075Sobrien	rval = 0;
18890075Sobrien	for (; argc > 0; argc--, argv++) {
18990075Sobrien		int fd, status, is_shlib, rv, type;
19090075Sobrien
19190075Sobrien		if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
19290075Sobrien			warn("%s", *argv);
19390075Sobrien			rval |= 1;
19490075Sobrien			continue;
19590075Sobrien		}
19690075Sobrien		rv = is_executable(*argv, fd, &is_shlib, &type);
19790075Sobrien		close(fd);
19890075Sobrien		if (rv == 0) {
19990075Sobrien			rval |= 1;
20090075Sobrien			continue;
20190075Sobrien		}
20290075Sobrien
20390075Sobrien		switch (type) {
20490075Sobrien		case TYPE_ELF:
20590075Sobrien		case TYPE_AOUT:
20690075Sobrien			break;
20790075Sobrien#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
20890075Sobrien		case TYPE_ELF32:
20990075Sobrien			rval |= execldd32(*argv, fmt1, fmt2, aflag, vflag);
21090075Sobrien			continue;
211117395Skan#endif
212117395Skan		case TYPE_UNKNOWN:
213117395Skan		default:
214132718Skan			/*
215117395Skan			 * This shouldn't happen unless is_executable()
216117395Skan			 * is broken.
217117395Skan			 */
218117395Skan			errx(EDOOFUS, "unknown executable type");
219117395Skan		}
220117395Skan
221117395Skan		/* ld.so magic */
222117395Skan		LDD_SETENV("TRACE_LOADED_OBJECTS", "yes", 1);
223117395Skan		if (fmt1 != NULL)
224117395Skan			LDD_SETENV("TRACE_LOADED_OBJECTS_FMT1", fmt1, 1);
225117395Skan		if (fmt2 != NULL)
226117395Skan			LDD_SETENV("TRACE_LOADED_OBJECTS_FMT2", fmt2, 1);
227117395Skan
228117395Skan		LDD_SETENV("TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1);
229117395Skan		if (aflag)
230117395Skan			LDD_SETENV("TRACE_LOADED_OBJECTS_ALL", "1", 1);
231132718Skan		else if (fmt1 == NULL && fmt2 == NULL)
232117395Skan			/* Default formats */
233117395Skan			printf("%s:\n", *argv);
234117395Skan		fflush(stdout);
235132718Skan
236117395Skan		switch (fork()) {
237132718Skan		case -1:
238117395Skan			err(1, "fork");
239132718Skan			break;
240117395Skan		default:
241117395Skan			if (wait(&status) < 0) {
242117395Skan				warn("wait");
243117395Skan				rval |= 1;
244117395Skan			} else if (WIFSIGNALED(status)) {
24590075Sobrien				fprintf(stderr, "%s: signal %d\n", *argv,
24690075Sobrien				    WTERMSIG(status));
24790075Sobrien				rval |= 1;
24890075Sobrien			} else if (WIFEXITED(status) &&
249132718Skan			    WEXITSTATUS(status) != 0) {
25090075Sobrien				fprintf(stderr, "%s: exit status %d\n", *argv,
25190075Sobrien				    WEXITSTATUS(status));
25290075Sobrien				rval |= 1;
25390075Sobrien			}
25490075Sobrien			break;
25590075Sobrien		case 0:
25690075Sobrien			if (is_shlib == 0) {
25790075Sobrien				execl(*argv, *argv, (char *)NULL);
25890075Sobrien				warn("%s", *argv);
25990075Sobrien			} else {
26090075Sobrien				dlopen(*argv, RTLD_TRACE);
26190075Sobrien				warnx("%s: %s", *argv, dlerror());
26290075Sobrien			}
26390075Sobrien			_exit(1);
26490075Sobrien		}
26590075Sobrien	}
26690075Sobrien
26790075Sobrien	return rval;
26890075Sobrien}
26990075Sobrien
27090075Sobrienstatic void
27190075Sobrienusage(void)
27290075Sobrien{
27390075Sobrien
27490075Sobrien	fprintf(stderr, "usage: ldd [-a] [-v] [-f format] program ...\n");
27590075Sobrien	exit(1);
27690075Sobrien}
27790075Sobrien
278132718Skanstatic int
27990075Sobrienis_executable(const char *fname, int fd, int *is_shlib, int *type)
28090075Sobrien{
28190075Sobrien	union {
282117395Skan#ifdef AOUT_SUPPORTED
28390075Sobrien		struct exec aout;
28490075Sobrien#endif
285117395Skan#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
286117395Skan		Elf32_Ehdr elf32;
28790075Sobrien#endif
28890075Sobrien		Elf_Ehdr elf;
289117395Skan	} hdr;
29090075Sobrien	int n;
291117395Skan
29290075Sobrien	*is_shlib = 0;
29390075Sobrien	*type = TYPE_UNKNOWN;
29490075Sobrien
29590075Sobrien	if ((n = read(fd, &hdr, sizeof(hdr))) == -1) {
29690075Sobrien		warn("%s: can't read program header", fname);
29790075Sobrien		return (0);
29890075Sobrien	}
29990075Sobrien
30090075Sobrien#ifdef AOUT_SUPPORTED
30190075Sobrien	if ((size_t)n >= sizeof(hdr.aout) && !N_BADMAG(hdr.aout)) {
30290075Sobrien		/* a.out file */
30390075Sobrien		if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC
30490075Sobrien#if 1 /* Compatibility */
30596263Sobrien		    || hdr.aout.a_entry < __LDPGSZ
30690075Sobrien#endif
307117395Skan			) {
308132718Skan			warnx("%s: not a dynamic executable", fname);
30990075Sobrien			return (0);
31096263Sobrien		}
311132718Skan		*type = TYPE_AOUT;
31296263Sobrien		return (1);
31396263Sobrien	}
31490075Sobrien#endif
31596263Sobrien
31696263Sobrien#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
31796263Sobrien	if ((size_t)n >= sizeof(hdr.elf32) && IS_ELF(hdr.elf32) &&
31896263Sobrien	    hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
31996263Sobrien		/* Handle 32 bit ELF objects */
32096263Sobrien		Elf32_Phdr phdr;
321110611Skan		int dynamic, i;
322110611Skan
323110611Skan		dynamic = 0;
324110611Skan		*type = TYPE_ELF32;
325110611Skan
32696263Sobrien		if (lseek(fd, hdr.elf32.e_phoff, SEEK_SET) == -1) {
32790075Sobrien			warnx("%s: header too short", fname);
32890075Sobrien			return (0);
32990075Sobrien		}
33090075Sobrien		for (i = 0; i < hdr.elf32.e_phnum; i++) {
33190075Sobrien			if (read(fd, &phdr, hdr.elf32.e_phentsize) !=
33290075Sobrien			    sizeof(phdr)) {
333117395Skan				warnx("%s: can't read program header", fname);
33490075Sobrien				return (0);
335117395Skan			}
336132718Skan			if (phdr.p_type == PT_DYNAMIC) {
33790075Sobrien				dynamic = 1;
33890075Sobrien				break;
33990075Sobrien			}
340117395Skan		}
341117395Skan
342117395Skan		if (!dynamic) {
343117395Skan			warnx("%s: not a dynamic ELF executable", fname);
344117395Skan			return (0);
345117395Skan		}
346132718Skan		if (hdr.elf32.e_type == ET_DYN) {
34790075Sobrien			if (hdr.elf32.e_ident[EI_OSABI] == ELFOSABI_FREEBSD) {
34890075Sobrien				*is_shlib = 1;
34990075Sobrien				return (1);
35090075Sobrien			}
35190075Sobrien			warnx("%s: not a FreeBSD ELF shared object", fname);
35296263Sobrien			return (0);
35390075Sobrien		}
354132718Skan
355132718Skan		return (1);
356132718Skan	}
357132718Skan#endif
35896263Sobrien
35996263Sobrien	if ((size_t)n >= sizeof(hdr.elf) && IS_ELF(hdr.elf) &&
360132718Skan	    hdr.elf.e_ident[EI_CLASS] == ELF_TARG_CLASS) {
361132718Skan		/* Handle default ELF objects on this architecture */
36296263Sobrien		Elf_Phdr phdr;
36396263Sobrien		int dynamic, i;
36490075Sobrien
36596263Sobrien		dynamic = 0;
36696263Sobrien		*type = TYPE_ELF;
36796263Sobrien
36896263Sobrien		if (lseek(fd, hdr.elf.e_phoff, SEEK_SET) == -1) {
36996263Sobrien			warnx("%s: header too short", fname);
37090075Sobrien			return (0);
371132718Skan		}
37290075Sobrien		for (i = 0; i < hdr.elf.e_phnum; i++) {
37390075Sobrien			if (read(fd, &phdr, hdr.elf.e_phentsize)
37490075Sobrien			   != sizeof(phdr)) {
37590075Sobrien				warnx("%s: can't read program header", fname);
37690075Sobrien				return (0);
37790075Sobrien			}
37890075Sobrien			if (phdr.p_type == PT_DYNAMIC) {
379132718Skan				dynamic = 1;
380117395Skan				break;
381117395Skan			}
382117395Skan		}
383117395Skan
384117395Skan		if (!dynamic) {
38590075Sobrien			warnx("%s: not a dynamic ELF executable", fname);
38690075Sobrien			return (0);
38790075Sobrien		}
38890075Sobrien		if (hdr.elf.e_type == ET_DYN) {
389132718Skan			switch (hdr.elf.e_ident[EI_OSABI]) {
390132718Skan			case ELFOSABI_FREEBSD:
391132718Skan				*is_shlib = 1;
392132718Skan				return (1);
393132718Skan#ifdef __ARM_EABI__
394132718Skan			case ELFOSABI_NONE:
395132718Skan				if (hdr.elf.e_machine != EM_ARM)
396132718Skan					break;
397132718Skan				if (EF_ARM_EABI_VERSION(hdr.elf.e_flags) <
39890075Sobrien				    EF_ARM_EABI_FREEBSD_MIN)
39990075Sobrien					break;
40090075Sobrien				*is_shlib = 1;
40190075Sobrien				return (1);
40290075Sobrien#endif
40390075Sobrien			}
40490075Sobrien			warnx("%s: not a FreeBSD ELF shared object", fname);
40590075Sobrien			return (0);
40690075Sobrien		}
40790075Sobrien
40890075Sobrien		return (1);
409117395Skan	}
41090075Sobrien
41190075Sobrien	warnx("%s: not a dynamic executable", fname);
41290075Sobrien	return (0);
413132718Skan}
41490075Sobrien