From owner-freebsd-bugs@FreeBSD.ORG Mon Jun 23 14:30:08 2008 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1233F1065671 for ; Mon, 23 Jun 2008 14:30:08 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 862488FC2B for ; Mon, 23 Jun 2008 14:30:02 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id m5NEU22Y001974 for ; Mon, 23 Jun 2008 14:30:02 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id m5NEU2Fc001971; Mon, 23 Jun 2008 14:30:02 GMT (envelope-from gnats) Resent-Date: Mon, 23 Jun 2008 14:30:02 GMT Resent-Message-Id: <200806231430.m5NEU2Fc001971@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Edwin Groothuis Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 746F01065685 for ; Mon, 23 Jun 2008 14:26:46 +0000 (UTC) (envelope-from edwin@mavetju.org) Received: from mail5out.barnet.com.au (mail5.barnet.com.au [202.83.178.78]) by mx1.freebsd.org (Postfix) with ESMTP id EAB598FC19 for ; Mon, 23 Jun 2008 14:26:45 +0000 (UTC) (envelope-from edwin@mavetju.org) Received: by mail5out.barnet.com.au (Postfix, from userid 1001) id 6CCC22218958; Tue, 24 Jun 2008 00:26:44 +1000 (EST) Received: from mail5auth.barnet.com.au (mail5.barnet.com.au [202.83.178.78]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "mail5auth.barnet.com.au", Issuer "*.barnet.com.au" (verified OK)) by mail5.barnet.com.au (Postfix) with ESMTP id 2EF3C21B3CE7 for ; Tue, 24 Jun 2008 00:26:44 +1000 (EST) Received: from k7.mavetju (unknown [10.10.26.14]) by mail5auth.barnet.com.au (Postfix) with ESMTP id 56969221894F for ; Tue, 24 Jun 2008 00:26:43 +1000 (EST) Received: by k7.mavetju (Postfix, from userid 1001) id 6C68D972; Tue, 24 Jun 2008 00:26:25 +1000 (EST) Message-Id: <20080623142625.6C68D972@k7.mavetju> Date: Tue, 24 Jun 2008 00:26:25 +1000 (EST) From: Edwin Groothuis To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Cc: Subject: bin/124906: [patch] teach /usr/bin/ldd about 32 bit objects on a 64 bit architecture X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Edwin Groothuis List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 23 Jun 2008 14:30:08 -0000 >Number: 124906 >Category: bin >Synopsis: [patch] teach /usr/bin/ldd about 32 bit objects on a 64 bit architecture >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Mon Jun 23 14:30:01 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Edwin Groothuis >Release: FreeBSD 7.0-RELEASE-p1 i386 >Organization: >Environment: System: FreeBSD k7.mavetju 7.0-RELEASE-p1 FreeBSD 7.0-RELEASE-p1 #2: Wed May 28 08:12:56 EST 2008 edwin@k7.mavetju:/usr/src/sys/i386/compile/k7 i386 >Description: The ldd utility of a 64 bit architecture doesn't work with 32 bit objects. [/] root@ed-exigent>uname -a FreeBSD ed-exigent.barnet.com.au 6.3-RELEASE-p1 FreeBSD 6.3-RELEASE-p1 #0: Wed Feb 13 00:11:33 UTC 2008 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/SMP amd64 [/] root@ed-exigent>ldd `which httpd` ldd: /usr/local/sbin/httpd: can't read program header ldd: /usr/local/sbin/httpd: not a dynamic executable But... [/] root@ed-exigent>LD_32_TRACE_LOADED_OBJECTS==1 `which httpd` libm.so.4 => /lib32//libm.so.4 (0x280c8000) libaprutil-1.so.2 => /usr/local/lib/libaprutil-1.so.2 (0x280de000) libexpat.so.6 => /usr/local/lib/libexpat.so.6 (0x280f2000) libiconv.so.3 => /usr/local/lib/libiconv.so.3 (0x28110000) libapr-1.so.2 => /usr/local/lib/libapr-1.so.2 (0x281fd000) libcrypt.so.3 => /lib32//libcrypt.so.3 (0x2821d000) libpthread.so.2 => not found (0x0) libc.so.6 => /lib32//libc.so.6 (0x28235000) libpthread.so.2 => /usr/lib32/libpthread.so.2 (0x2830d000) So it is possible, it just doesn't have the right options. >How-To-Repeat: >Fix: The following patch will teach ldd(1) to handle them properly: [/] root@ed-exigent>/tmp/ldd /usr/local/lib/libexpat.so /usr/lib/libssh.so /bin/sh /usr/local/bin/bash /usr/local/lib/libexpat.so: ldd: /usr/local/lib/libexpat.so: /usr/local/lib/libexpat.so: unsupported file layout /usr/local/lib/libexpat.so: exit status 1 /usr/lib/libssh.so: libz.so.3 => /lib/libz.so.3 (0x800963000) libgssapi.so.8 => /usr/lib/libgssapi.so.8 (0x800a76000) libkrb5.so.8 => /usr/lib/libkrb5.so.8 (0x800b85000) libasn1.so.8 => /usr/lib/libasn1.so.8 (0x800cc9000) libcom_err.so.3 => /usr/lib/libcom_err.so.3 (0x800df2000) libmd.so.3 => /lib/libmd.so.3 (0x800ef4000) libroken.so.8 => /usr/lib/libroken.so.8 (0x801000000) libcrypto.so.4 => /lib/libcrypto.so.4 (0x80110e000) libcrypt.so.3 => /lib/libcrypt.so.3 (0x801354000) /bin/sh: libedit.so.5 => /lib/libedit.so.5 (0x800646000) libncurses.so.6 => /lib/libncurses.so.6 (0x800760000) libc.so.6 => /lib/libc.so.6 (0x8008b9000) /usr/local/bin/bash: libncurses.so.6 => /lib32//libncurses.so.6 (0x28106000) libintl.so.6 => /usr/local/lib/libintl.so.6 (0x28145000) libiconv.so.3 => /usr/local/lib/libiconv.so.3 (0x2814e000) libc.so.6 => /lib32//libc.so.6 (0x2823b000) It can't do 32 bit libraries because dlopen() can't do it. Index: ldd.1 =================================================================== --- ldd.1 (revision 179947) +++ ldd.1 (working copy) @@ -64,6 +64,11 @@ It will print a report of all ELF binaries in the current directory, which link against libc.so.6: .Dl "find . -type f | xargs -n1 file -F " " | grep ELF | cut -f1 -d' ' | xargs ldd -f '%A %o\en' | grep libc.so.6" +.Sh BUGS +On 64 bit architectures, dlopen() can't open 32 bit dynamica libraries +and +.Nm +will show the error "unsupported file layout". .Sh SEE ALSO .Xr ld 1 , .Xr nm 1 , Index: ldd.c =================================================================== --- ldd.c (revision 179947) +++ ldd.c (working copy) @@ -47,6 +47,45 @@ #include "extern.h" +int is_executable(char *file, int *is_shlib, int *type); + +#define TYPE_AOUT 1 +#define TYPE_ELF32 2 +#define TYPE_ELF64 3 + +#define ENV_OBJECTS 0 +#define ENV_OBJECTS_FMT1 1 +#define ENV_OBJECTS_FMT2 2 +#define ENV_OBJECTS_PROGNAME 3 +#define ENV_OBJECTS_ALL 4 +#define ENV_LAST 5 + +#ifdef __i386__ +const char *env32[ENV_LAST] = { + "LD_TRACE_LOADED_OBJECTS", + "LD_TRACE_LOADED_OBJECTS_FMT1", + "LD_TRACE_LOADED_OBJECTS_FMT2", + "LD_TRACE_LOADED_OBJECTS_PROGNAME", + "LD_TRACE_LOADED_OBJECTS_ALL", +}; +const char *env64[ENV_LAST] = {}; +#else +const char *env64[ENV_LAST] = { + "LD_TRACE_LOADED_OBJECTS", + "LD_TRACE_LOADED_OBJECTS_FMT1", + "LD_TRACE_LOADED_OBJECTS_FMT2", + "LD_TRACE_LOADED_OBJECTS_PROGNAME", + "LD_TRACE_LOADED_OBJECTS_ALL", +}; +const char *env32[ENV_LAST] = { + "LD_32_TRACE_LOADED_OBJECTS", + "LD_32_TRACE_LOADED_OBJECTS_FMT1", + "LD_32_TRACE_LOADED_OBJECTS_FMT2", + "LD_32_TRACE_LOADED_OBJECTS_PROGNAME", + "LD_32_TRACE_LOADED_OBJECTS_ALL", +}; +#endif + static void usage(void) { @@ -61,10 +100,11 @@ int rval; int c; int aflag, vflag; + const char **env; aflag = vflag = 0; - while ((c = getopt(argc, argv, "avf:")) != -1) { + while ((c = getopt(argc, argv, "23avf:")) != -1) { switch (c) { case 'a': aflag++; @@ -104,97 +144,38 @@ } #endif - /* ld.so magic */ - setenv("LD_TRACE_LOADED_OBJECTS", "yes", 1); - if (fmt1) - setenv("LD_TRACE_LOADED_OBJECTS_FMT1", fmt1, 1); - if (fmt2) - setenv("LD_TRACE_LOADED_OBJECTS_FMT2", fmt2, 1); - rval = 0; for ( ; argc > 0; argc--, argv++) { - int fd; - union { - struct exec aout; - Elf_Ehdr elf; - } hdr; - int n; int status; - int file_ok; int is_shlib; + int type; - if ((fd = open(*argv, O_RDONLY, 0)) < 0) { - warn("%s", *argv); + if (is_executable(*argv, &is_shlib, &type) == 0) { rval |= 1; continue; } - if ((n = read(fd, &hdr, sizeof hdr)) == -1) { - warn("%s: can't read program header", *argv); - (void)close(fd); - rval |= 1; - continue; + + switch (type) { + default: + case TYPE_AOUT: /* XXX */ + case TYPE_ELF32: + env = env32; + break; + case TYPE_ELF64: + env = env64; + break; } - file_ok = 1; - is_shlib = 0; - if ((size_t)n >= sizeof hdr.aout && !N_BADMAG(hdr.aout)) { - /* a.out file */ - if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC -#if 1 /* Compatibility */ - || hdr.aout.a_entry < __LDPGSZ -#endif - ) { - warnx("%s: not a dynamic executable", *argv); - file_ok = 0; - } - } else if ((size_t)n >= sizeof hdr.elf && IS_ELF(hdr.elf)) { - Elf_Ehdr ehdr; - Elf_Phdr phdr; - int dynamic = 0, i; + /* ld.so magic */ + setenv(env[ENV_OBJECTS], "yes", 1); + if (fmt1) + setenv(env[ENV_OBJECTS_FMT1], fmt1, 1); + if (fmt2) + setenv(env[ENV_OBJECTS_FMT2], fmt2, 1); - if (lseek(fd, 0, SEEK_SET) == -1 || - read(fd, &ehdr, sizeof ehdr) != sizeof ehdr || - lseek(fd, ehdr.e_phoff, SEEK_SET) == -1 - ) { - warnx("%s: can't read program header", *argv); - file_ok = 0; - } else { - for (i = 0; i < ehdr.e_phnum; i++) { - if (read(fd, &phdr, ehdr.e_phentsize) - != sizeof phdr) { - warnx("%s: can't read program header", - *argv); - file_ok = 0; - break; - } - if (phdr.p_type == PT_DYNAMIC) - dynamic = 1; - } - } - if (!dynamic) { - warnx("%s: not a dynamic executable", *argv); - file_ok = 0; - } else if (hdr.elf.e_type == ET_DYN) { - if (hdr.elf.e_ident[EI_OSABI] & ELFOSABI_FREEBSD) { - is_shlib = 1; - } else { - warnx("%s: not a FreeBSD ELF shared " - "object", *argv); - file_ok = 0; - } - } - } else { - warnx("%s: not a dynamic executable", *argv); - file_ok = 0; - } - (void)close(fd); - if (!file_ok) { - rval |= 1; - continue; - } - - setenv("LD_TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1); - if (aflag) setenv("LD_TRACE_LOADED_OBJECTS_ALL", "1", 1); + setenv(env[ENV_OBJECTS_PROGNAME], *argv, 1); + if (aflag) + setenv(env[ENV_OBJECTS_ALL], "1", 1); else if (fmt1 == NULL && fmt2 == NULL) /* Default formats */ printf("%s:\n", *argv); @@ -233,3 +214,149 @@ return rval; } + +int +is_executable(char *file, int *is_shlib, int *type) +{ + int fd; + union { + struct exec aout; + Elf_Ehdr elf; + } hdr; + int n; + int file_ok = 0; + + if ((fd = open(file, O_RDONLY, 0)) < 0) { + warn("%s", file); + return (0); + } + if ((n = read(fd, &hdr, sizeof hdr)) == -1) { + warn("%s: can't read program header", file); + goto bye; + } + + *is_shlib = 0; + if ((size_t)n >= sizeof hdr.aout && !N_BADMAG(hdr.aout)) { + /* a.out file */ + if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC +#if 1 /* Compatibility */ + || hdr.aout.a_entry < __LDPGSZ +#endif + ) { + warnx("%s: not a dynamic a.out executable", + file); + goto bye; + } + file_ok = 1; + *type = TYPE_AOUT; + goto bye; + } + + if ((size_t)n >= sizeof hdr.elf && IS_ELF(hdr.elf)) { + + /* 32 bit object */ + if (hdr.elf.e_ident[EI_CLASS] == 1) { + Elf32_Ehdr ehdr; + Elf32_Phdr phdr; + int dynamic = 0, i; + + if (lseek(fd, 0, SEEK_SET) == -1 || + read(fd, &ehdr, sizeof ehdr) != sizeof ehdr || + lseek(fd, ehdr.e_phoff, SEEK_SET) == -1 + ) { + warnx("%s: can't read program header", file); + goto bye; + } + + for (i = 0; i < ehdr.e_phnum; i++) { + if (read(fd, &phdr, ehdr.e_phentsize) + != sizeof phdr) { + warnx("%s: can't read program header", + file); + goto bye; + } + if (phdr.p_type == PT_DYNAMIC) + dynamic = 1; + } + + if (!dynamic) { + warnx("%s: not a dynamic ELF executable", + file); + goto bye; + } + + if (ehdr.e_type == ET_DYN) { + if (ehdr.e_ident[EI_OSABI] & + ELFOSABI_FREEBSD) { + *is_shlib = 1; + file_ok = 1; + goto bye; + } + warnx("%s: not a FreeBSD ELF shared object", + file); + goto bye; + } + + *type = TYPE_ELF32; + file_ok = 1; + goto bye; + } + +#ifndef __i386__ + /* 64 bit object */ + if (hdr.elf.e_ident[EI_CLASS] == 2) { + Elf64_Ehdr ehdr; + Elf64_Phdr phdr; + int dynamic = 0, i; + + if (lseek(fd, 0, SEEK_SET) == -1 || + read(fd, &ehdr, sizeof ehdr) != sizeof ehdr || + lseek(fd, ehdr.e_phoff, SEEK_SET) == -1 + ) { + warnx("%s: can't read program header", file); + goto bye; + } + + for (i = 0; i < ehdr.e_phnum; i++) { + if (read(fd, &phdr, ehdr.e_phentsize) + != sizeof phdr) { + warnx("%s: can't read program header", + file); + goto bye; + } + if (phdr.p_type == PT_DYNAMIC) + dynamic = 1; + } + + if (!dynamic) { + warnx("%s: not a dynamic ELF executable", + file); + goto bye; + } + + if (ehdr.e_type == ET_DYN) { + if (ehdr.e_ident[EI_OSABI] & + ELFOSABI_FREEBSD) { + *is_shlib = 1; + file_ok = 1; + goto bye; + } + warnx("%s: not a FreeBSD ELF shared object", + file); + goto bye; + } + + *type = TYPE_ELF64; + file_ok = 1; + goto bye; + } +#endif + } + + warnx("%s: not a known dynamic executable", file); + goto bye; + +bye: + (void)close(fd); + return (file_ok); +} >Release-Note: >Audit-Trail: >Unformatted: