ldd.c revision 330449
1330449Seadler/*- 2330449Seadler * SPDX-License-Identifier: BSD-4-Clause 3330449Seadler * 4696Spaul * Copyright (c) 1993 Paul Kranenburg 5696Spaul * All rights reserved. 6696Spaul * 7696Spaul * Redistribution and use in source and binary forms, with or without 8696Spaul * modification, are permitted provided that the following conditions 9696Spaul * are met: 10696Spaul * 1. Redistributions of source code must retain the above copyright 11696Spaul * notice, this list of conditions and the following disclaimer. 12696Spaul * 2. Redistributions in binary form must reproduce the above copyright 13696Spaul * notice, this list of conditions and the following disclaimer in the 14696Spaul * documentation and/or other materials provided with the distribution. 15696Spaul * 3. All advertising materials mentioning features or use of this software 16696Spaul * must display the following acknowledgement: 17696Spaul * This product includes software developed by Paul Kranenburg. 18696Spaul * 4. The name of the author may not be used to endorse or promote products 191153Sjkh * derived from this software without specific prior written permission 20696Spaul * 21696Spaul * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22696Spaul * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23696Spaul * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24696Spaul * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25696Spaul * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26696Spaul * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27696Spaul * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28696Spaul * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29696Spaul * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30696Spaul * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31696Spaul */ 32696Spaul 3395648Smarkm#include <sys/cdefs.h> 3495648Smarkm__FBSDID("$FreeBSD: stable/11/usr.bin/ldd/ldd.c 330449 2018-03-05 07:26:05Z eadler $"); 3569827Scharnier 36696Spaul#include <sys/wait.h> 3795648Smarkm 3876224Sobrien#include <machine/elf.h> 3995648Smarkm 4095153Smike#include <arpa/inet.h> 4195648Smarkm 4290172Ssobomax#include <dlfcn.h> 431741Srich#include <err.h> 44180236Sedwin#include <errno.h> 451741Srich#include <fcntl.h> 461741Srich#include <stdio.h> 471741Srich#include <stdlib.h> 48181136Sjhb#include <string.h> 491741Srich#include <unistd.h> 50696Spaul 5195648Smarkm#include "extern.h" 5218600Speter 53294665Sbr/* We don't support a.out executables on arm64 and riscv */ 54294665Sbr#if !defined(__aarch64__) && !defined(__riscv__) 55280220Sandrew#include <a.out.h> 56280220Sandrew#define AOUT_SUPPORTED 57280220Sandrew#endif 58280220Sandrew 59180646Sedwin/* 60180877Sedwin * 32-bit ELF data structures can only be used if the system header[s] declare 61180877Sedwin * them. There is no official macro for determining whether they are declared, 62180877Sedwin * so check for the existence of one of the 32-macros defined in elf(5). 63180646Sedwin */ 64180877Sedwin#ifdef ELF32_R_TYPE 65180877Sedwin#define ELF32_SUPPORTED 66180646Sedwin#endif 67180646Sedwin 68254018Smarkj#define LDD_SETENV(name, value, overwrite) do { \ 69254018Smarkj setenv("LD_" name, value, overwrite); \ 70254018Smarkj setenv("LD_32_" name, value, overwrite); \ 71254018Smarkj} while (0) 72254018Smarkj 73254018Smarkj#define LDD_UNSETENV(name) do { \ 74254018Smarkj unsetenv("LD_" name); \ 75254018Smarkj unsetenv("LD_32_" name); \ 76254018Smarkj} while (0) 77254018Smarkj 78180235Sedwinstatic int is_executable(const char *fname, int fd, int *is_shlib, 79180235Sedwin int *type); 80180235Sedwinstatic void usage(void); 81180234Sedwin 82180235Sedwin#define TYPE_UNKNOWN 0 83180235Sedwin#define TYPE_AOUT 1 84180235Sedwin#define TYPE_ELF 2 /* Architecture default */ 85180646Sedwin#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED) 86180236Sedwin#define TYPE_ELF32 3 /* Explicit 32 bits on architectures >32 bits */ 87696Spaul 88181136Sjhb#define _PATH_LDD32 "/usr/bin/ldd32" 89180235Sedwin 90181136Sjhbstatic int 91181136Sjhbexecldd32(char *file, char *fmt1, char *fmt2, int aflag, int vflag) 92181136Sjhb{ 93299952Struckman char *argv[9]; 94181136Sjhb int i, rval, status; 95181136Sjhb 96254018Smarkj LDD_UNSETENV("TRACE_LOADED_OBJECTS"); 97181136Sjhb rval = 0; 98181136Sjhb i = 0; 99181136Sjhb argv[i++] = strdup(_PATH_LDD32); 100181136Sjhb if (aflag) 101181136Sjhb argv[i++] = strdup("-a"); 102181136Sjhb if (vflag) 103181136Sjhb argv[i++] = strdup("-v"); 104181161Sjhb if (fmt1 != NULL) { 105181136Sjhb argv[i++] = strdup("-f"); 106181136Sjhb argv[i++] = strdup(fmt1); 107181136Sjhb } 108181161Sjhb if (fmt2 != NULL) { 109181136Sjhb argv[i++] = strdup("-f"); 110181136Sjhb argv[i++] = strdup(fmt2); 111181136Sjhb } 112181136Sjhb argv[i++] = strdup(file); 113181136Sjhb argv[i++] = NULL; 114181136Sjhb 115181136Sjhb switch (fork()) { 116181136Sjhb case -1: 117181136Sjhb err(1, "fork"); 118181136Sjhb break; 119181136Sjhb case 0: 120181136Sjhb execv(_PATH_LDD32, argv); 121181136Sjhb warn("%s", _PATH_LDD32); 122181161Sjhb _exit(127); 123181136Sjhb break; 124181136Sjhb default: 125181161Sjhb if (wait(&status) < 0) 126181136Sjhb rval = 1; 127181161Sjhb else if (WIFSIGNALED(status)) 128181136Sjhb rval = 1; 129181161Sjhb else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) 130181136Sjhb rval = 1; 131181136Sjhb break; 132181136Sjhb } 133181136Sjhb while (i--) 134181136Sjhb free(argv[i]); 135254018Smarkj LDD_SETENV("TRACE_LOADED_OBJECTS", "yes", 1); 136181136Sjhb return (rval); 137181136Sjhb} 138180236Sedwin#endif 139180235Sedwin 140696Spaulint 14195648Smarkmmain(int argc, char *argv[]) 142696Spaul{ 143180234Sedwin char *fmt1, *fmt2; 144180234Sedwin int rval, c, aflag, vflag; 145696Spaul 14690755Sobrien aflag = vflag = 0; 147180234Sedwin fmt1 = fmt2 = NULL; 14890755Sobrien 149180234Sedwin while ((c = getopt(argc, argv, "af:v")) != -1) { 150696Spaul switch (c) { 15190755Sobrien case 'a': 15290755Sobrien aflag++; 15390755Sobrien break; 15418598Speter case 'f': 155180234Sedwin if (fmt1 != NULL) { 156180234Sedwin if (fmt2 != NULL) 15769827Scharnier errx(1, "too many formats"); 15818598Speter fmt2 = optarg; 15918598Speter } else 16018598Speter fmt1 = optarg; 16118598Speter break; 162180234Sedwin case 'v': 163180234Sedwin vflag++; 164180234Sedwin break; 165696Spaul default: 166696Spaul usage(); 167180234Sedwin /* NOTREACHED */ 168696Spaul } 169696Spaul } 170696Spaul argc -= optind; 171696Spaul argv += optind; 172696Spaul 173180234Sedwin if (vflag && fmt1 != NULL) 17418600Speter errx(1, "-v may not be used with -f"); 17518600Speter 176696Spaul if (argc <= 0) { 177696Spaul usage(); 178180234Sedwin /* NOTREACHED */ 179696Spaul } 180696Spaul 18139354Sdfr#ifdef __i386__ 18218600Speter if (vflag) { 18318600Speter for (c = 0; c < argc; c++) 18418600Speter dump_file(argv[c]); 18518600Speter exit(error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 18618600Speter } 18739354Sdfr#endif 18818600Speter 1891741Srich rval = 0; 190180234Sedwin for (; argc > 0; argc--, argv++) { 191180235Sedwin int fd, status, is_shlib, rv, type; 192696Spaul 193696Spaul if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 1941741Srich warn("%s", *argv); 195696Spaul rval |= 1; 196696Spaul continue; 197696Spaul } 198180235Sedwin rv = is_executable(*argv, fd, &is_shlib, &type); 199180235Sedwin close(fd); 200180235Sedwin if (rv == 0) { 201696Spaul rval |= 1; 202696Spaul continue; 203696Spaul } 20435575Sdfr 205180236Sedwin switch (type) { 206180236Sedwin case TYPE_ELF: 207180236Sedwin case TYPE_AOUT: 208180236Sedwin break; 209180646Sedwin#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED) 210180236Sedwin case TYPE_ELF32: 211181136Sjhb rval |= execldd32(*argv, fmt1, fmt2, aflag, vflag); 212181136Sjhb continue; 213180236Sedwin#endif 214180236Sedwin case TYPE_UNKNOWN: 215180236Sedwin default: 216180236Sedwin /* 217180236Sedwin * This shouldn't happen unless is_executable() 218180236Sedwin * is broken. 219180236Sedwin */ 220180236Sedwin errx(EDOOFUS, "unknown executable type"); 221180236Sedwin } 222180236Sedwin 223180235Sedwin /* ld.so magic */ 224254018Smarkj LDD_SETENV("TRACE_LOADED_OBJECTS", "yes", 1); 225180235Sedwin if (fmt1 != NULL) 226254018Smarkj LDD_SETENV("TRACE_LOADED_OBJECTS_FMT1", fmt1, 1); 227180235Sedwin if (fmt2 != NULL) 228254018Smarkj LDD_SETENV("TRACE_LOADED_OBJECTS_FMT2", fmt2, 1); 22935575Sdfr 230254018Smarkj LDD_SETENV("TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1); 231180234Sedwin if (aflag) 232254018Smarkj LDD_SETENV("TRACE_LOADED_OBJECTS_ALL", "1", 1); 23390755Sobrien else if (fmt1 == NULL && fmt2 == NULL) 23418598Speter /* Default formats */ 23518598Speter printf("%s:\n", *argv); 2361153Sjkh fflush(stdout); 237696Spaul 238696Spaul switch (fork()) { 239696Spaul case -1: 2401741Srich err(1, "fork"); 241696Spaul break; 242696Spaul default: 243181161Sjhb if (wait(&status) < 0) { 2441741Srich warn("wait"); 2451741Srich rval |= 1; 2461741Srich } else if (WIFSIGNALED(status)) { 247180234Sedwin fprintf(stderr, "%s: signal %d\n", *argv, 248180234Sedwin WTERMSIG(status)); 249696Spaul rval |= 1; 250181161Sjhb } else if (WIFEXITED(status) && 251181161Sjhb WEXITSTATUS(status) != 0) { 252180234Sedwin fprintf(stderr, "%s: exit status %d\n", *argv, 253180234Sedwin WEXITSTATUS(status)); 254696Spaul rval |= 1; 255696Spaul } 256696Spaul break; 257696Spaul case 0: 258105439Ssobomax if (is_shlib == 0) { 25990172Ssobomax execl(*argv, *argv, (char *)NULL); 26090172Ssobomax warn("%s", *argv); 261105439Ssobomax } else { 262105439Ssobomax dlopen(*argv, RTLD_TRACE); 263105439Ssobomax warnx("%s: %s", *argv, dlerror()); 26490172Ssobomax } 265696Spaul _exit(1); 266696Spaul } 267696Spaul } 268696Spaul 269696Spaul return rval; 270696Spaul} 271180235Sedwin 272180235Sedwinstatic void 273180235Sedwinusage(void) 274180235Sedwin{ 275180235Sedwin 276180235Sedwin fprintf(stderr, "usage: ldd [-a] [-v] [-f format] program ...\n"); 277180235Sedwin exit(1); 278180235Sedwin} 279180235Sedwin 280180235Sedwinstatic int 281180235Sedwinis_executable(const char *fname, int fd, int *is_shlib, int *type) 282180235Sedwin{ 283180235Sedwin union { 284280220Sandrew#ifdef AOUT_SUPPORTED 285180235Sedwin struct exec aout; 286280220Sandrew#endif 287180646Sedwin#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED) 288180236Sedwin Elf32_Ehdr elf32; 289180646Sedwin#endif 290180235Sedwin Elf_Ehdr elf; 291180235Sedwin } hdr; 292180235Sedwin int n; 293180235Sedwin 294180235Sedwin *is_shlib = 0; 295180235Sedwin *type = TYPE_UNKNOWN; 296180235Sedwin 297180235Sedwin if ((n = read(fd, &hdr, sizeof(hdr))) == -1) { 298180235Sedwin warn("%s: can't read program header", fname); 299180235Sedwin return (0); 300180235Sedwin } 301180235Sedwin 302280220Sandrew#ifdef AOUT_SUPPORTED 303180235Sedwin if ((size_t)n >= sizeof(hdr.aout) && !N_BADMAG(hdr.aout)) { 304180235Sedwin /* a.out file */ 305180235Sedwin if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC 306180235Sedwin#if 1 /* Compatibility */ 307180235Sedwin || hdr.aout.a_entry < __LDPGSZ 308180235Sedwin#endif 309180235Sedwin ) { 310180235Sedwin warnx("%s: not a dynamic executable", fname); 311180235Sedwin return (0); 312180235Sedwin } 313180235Sedwin *type = TYPE_AOUT; 314180235Sedwin return (1); 315180235Sedwin } 316280220Sandrew#endif 317180235Sedwin 318180646Sedwin#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED) 319180236Sedwin if ((size_t)n >= sizeof(hdr.elf32) && IS_ELF(hdr.elf32) && 320180236Sedwin hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) { 321180236Sedwin /* Handle 32 bit ELF objects */ 322180236Sedwin Elf32_Phdr phdr; 323180236Sedwin int dynamic, i; 324180236Sedwin 325180236Sedwin dynamic = 0; 326180236Sedwin *type = TYPE_ELF32; 327180236Sedwin 328180236Sedwin if (lseek(fd, hdr.elf32.e_phoff, SEEK_SET) == -1) { 329180236Sedwin warnx("%s: header too short", fname); 330180236Sedwin return (0); 331180236Sedwin } 332180236Sedwin for (i = 0; i < hdr.elf32.e_phnum; i++) { 333180236Sedwin if (read(fd, &phdr, hdr.elf32.e_phentsize) != 334180236Sedwin sizeof(phdr)) { 335180236Sedwin warnx("%s: can't read program header", fname); 336180236Sedwin return (0); 337180236Sedwin } 338180236Sedwin if (phdr.p_type == PT_DYNAMIC) { 339180236Sedwin dynamic = 1; 340180236Sedwin break; 341180236Sedwin } 342180236Sedwin } 343180236Sedwin 344180236Sedwin if (!dynamic) { 345180236Sedwin warnx("%s: not a dynamic ELF executable", fname); 346180236Sedwin return (0); 347180236Sedwin } 348180236Sedwin if (hdr.elf32.e_type == ET_DYN) { 349215705Sbrucec if (hdr.elf32.e_ident[EI_OSABI] == ELFOSABI_FREEBSD) { 350180236Sedwin *is_shlib = 1; 351180236Sedwin return (1); 352180236Sedwin } 353180236Sedwin warnx("%s: not a FreeBSD ELF shared object", fname); 354180236Sedwin return (0); 355180236Sedwin } 356180236Sedwin 357180236Sedwin return (1); 358180236Sedwin } 359180236Sedwin#endif 360180236Sedwin 361180235Sedwin if ((size_t)n >= sizeof(hdr.elf) && IS_ELF(hdr.elf) && 362180235Sedwin hdr.elf.e_ident[EI_CLASS] == ELF_TARG_CLASS) { 363180235Sedwin /* Handle default ELF objects on this architecture */ 364180235Sedwin Elf_Phdr phdr; 365180235Sedwin int dynamic, i; 366180235Sedwin 367180235Sedwin dynamic = 0; 368180235Sedwin *type = TYPE_ELF; 369180235Sedwin 370180235Sedwin if (lseek(fd, hdr.elf.e_phoff, SEEK_SET) == -1) { 371180235Sedwin warnx("%s: header too short", fname); 372180235Sedwin return (0); 373180235Sedwin } 374180235Sedwin for (i = 0; i < hdr.elf.e_phnum; i++) { 375180235Sedwin if (read(fd, &phdr, hdr.elf.e_phentsize) 376180235Sedwin != sizeof(phdr)) { 377180235Sedwin warnx("%s: can't read program header", fname); 378180235Sedwin return (0); 379180235Sedwin } 380180235Sedwin if (phdr.p_type == PT_DYNAMIC) { 381180235Sedwin dynamic = 1; 382180235Sedwin break; 383180235Sedwin } 384180235Sedwin } 385180235Sedwin 386180235Sedwin if (!dynamic) { 387180235Sedwin warnx("%s: not a dynamic ELF executable", fname); 388180235Sedwin return (0); 389180235Sedwin } 390180235Sedwin if (hdr.elf.e_type == ET_DYN) { 391289425Sjkim switch (hdr.elf.e_ident[EI_OSABI]) { 392289425Sjkim case ELFOSABI_FREEBSD: 393180235Sedwin *is_shlib = 1; 394180235Sedwin return (1); 395289425Sjkim#ifdef __ARM_EABI__ 396289425Sjkim case ELFOSABI_NONE: 397289425Sjkim if (hdr.elf.e_machine != EM_ARM) 398289425Sjkim break; 399289425Sjkim if (EF_ARM_EABI_VERSION(hdr.elf.e_flags) < 400289425Sjkim EF_ARM_EABI_FREEBSD_MIN) 401289425Sjkim break; 402289425Sjkim *is_shlib = 1; 403289425Sjkim return (1); 404289425Sjkim#endif 405180235Sedwin } 406180235Sedwin warnx("%s: not a FreeBSD ELF shared object", fname); 407180235Sedwin return (0); 408180235Sedwin } 409180235Sedwin 410180235Sedwin return (1); 411180235Sedwin } 412180235Sedwin 413180235Sedwin warnx("%s: not a dynamic executable", fname); 414180235Sedwin return (0); 415180235Sedwin} 416