From edwin@mavetju.org  Mon Jun 23 14:26:46 2008
Return-Path: <edwin@mavetju.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 746F01065685
	for <FreeBSD-gnats-submit@freebsd.org>; 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 <FreeBSD-gnats-submit@freebsd.org>; 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 <FreeBSD-gnats-submit@freebsd.org>; 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 <FreeBSD-gnats-submit@freebsd.org>; 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 <edwin@mavetju.org>
Reply-To: Edwin Groothuis <edwin@mavetju.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [patch] teach /usr/bin/ldd about 32 bit objects on a 64 bit architecture
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         124906
>Category:       bin
>Synopsis:       [patch] teach ldd(1) about 32 bit objects on a 64 bit architecture
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    edwin
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jun 23 14:30:01 UTC 2008
>Closed-Date:    Thu Jul 10 01:34:26 UTC 2008
>Last-Modified:  Wed Jul 30 18:30:02 UTC 2008
>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 dynamic 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, "avf:")) != -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,151 @@
 
 	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;
+
+			*type = TYPE_ELF32;
+
+			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;
+			}
+
+			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;
+
+			*type = TYPE_ELF64;
+
+			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;
+			}
+
+			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:
Responsible-Changed-From-To: freebsd-bugs->edwin 
Responsible-Changed-By: edwin 
Responsible-Changed-When: Mon Jun 23 14:46:01 UTC 2008 
Responsible-Changed-Why:  
Handle it with mentor 

http://www.freebsd.org/cgi/query-pr.cgi?pr=124906 

From: John Baldwin <jhb@freebsd.org>
To: bug-followup@freebsd.org, edwin@mavetju.org
Cc:  
Subject: Re: bin/124906: [patch] teach ldd(1) about 32 bit objects on a 64 bit architecture
Date: Tue, 24 Jun 2008 09:02:21 -0400

 At work what we have done is to build a 32-bit 'ldd32' binary during the amd64 
 buildworld (it can handle 32-bit shared libraries) and then teach 'ldd' to 
 exec ldd32 when given a 32-bit argument.
 
 -- 
 John Baldwin

From: Edwin Groothuis <edwin@mavetju.org>
To: FreeBSD Gnats Submit <freebsd-gnats-submit@freebsd.org>
Cc:  
Subject: Re: bin/124906: [patch] teach /usr/bin/ldd about 32 bit objects on a 64 bit architecture
Date: Tue, 1 Jul 2008 00:00:26 +1000

 --VbJkn9YxBvnuCH5J
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 Be ready for further enhancements on ELF without having to change
 the program. (As requested by bde@)
 
 -- 
 Edwin Groothuis      |            Personal website: http://www.mavetju.org
 edwin@mavetju.org    |              Weblog: http://www.mavetju.org/weblog/
 
 --VbJkn9YxBvnuCH5J
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename=a
 
 Index: ldd.c
 ===================================================================
 --- ldd.c	(revision 180119)
 +++ ldd.c	(working copy)
 @@ -32,6 +32,8 @@
  __FBSDID("$FreeBSD$");
  
  #include <sys/wait.h>
 +#include <sys/elf32.h>
 +#include <sys/elf64.h>
  
  #include <machine/elf.h>
  
 @@ -47,24 +49,55 @@
  
  #include "extern.h"
  
 -static void
 -usage(void)
 -{
 -	fprintf(stderr, "usage: ldd [-a] [-v] [-f format] program ...\n");
 -	exit(1);
 -}
 +static void	usage(void);
 +static int	is_executable(const char *fname, int fd, int *is_shlib,
 +		    int *type);
  
 +#define	TYPE_UNKNOWN	0
 +#define	TYPE_AOUT	1
 +#define	TYPE_ELF	2
 +#define	TYPE_ELF32	3
 +#define	TYPE_ELF64	4
 +
 +#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
 +
 +const char	*envdef[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",
 +};
 +const char	*env64[ENV_LAST] = {
 +	"LD_64_TRACE_LOADED_OBJECTS",
 +	"LD_64_TRACE_LOADED_OBJECTS_FMT1",
 +	"LD_64_TRACE_LOADED_OBJECTS_FMT2",
 +	"LD_64_TRACE_LOADED_OBJECTS_PROGNAME",
 +	"LD_64_TRACE_LOADED_OBJECTS_ALL",
 +};
 +
  int
  main(int argc, char *argv[])
  {
 -	char		*fmt1 = NULL, *fmt2 = NULL;
 -	int		rval;
 -	int		c;
 -	int		aflag, vflag;
 +	char *fmt1, *fmt2;
 +	int rval, c, aflag, vflag;
  
  	aflag = vflag = 0;
 +	fmt1 = fmt2 = NULL;
  
 -	while ((c = getopt(argc, argv, "avf:")) != -1) {
 +	while ((c = getopt(argc, argv, "af:v")) != -1) {
  		switch (c) {
  		case 'a':
  			aflag++;
 @@ -73,8 +106,8 @@
  			vflag++;
  			break;
  		case 'f':
 -			if (fmt1) {
 -				if (fmt2)
 +			if (fmt1 != NULL) {
 +				if (fmt2 != NULL)
  					errx(1, "too many formats");
  				fmt2 = optarg;
  			} else
 @@ -82,18 +115,18 @@
  			break;
  		default:
  			usage();
 -			/*NOTREACHED*/
 +			/* NOTREACHED */
  		}
  	}
  	argc -= optind;
  	argv += optind;
  
 -	if (vflag && fmt1)
 +	if (vflag && fmt1 != NULL)
  		errx(1, "-v may not be used with -f");
  
  	if (argc <= 0) {
  		usage();
 -		/*NOTREACHED*/
 +		/* NOTREACHED */
  	}
  
  #ifdef __i386__
 @@ -104,97 +137,54 @@
  	}
  #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;
 +	for (; argc > 0; argc--, argv++) {
 +		int fd, status, is_shlib, rv, type;
 +		const char **env;
  
  		if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
  			warn("%s", *argv);
  			rval |= 1;
  			continue;
  		}
 -		if ((n = read(fd, &hdr, sizeof hdr)) == -1) {
 -			warn("%s: can't read program header", *argv);
 -			(void)close(fd);
 +		rv = is_executable(*argv, fd, &is_shlib, &type);
 +		close(fd);
 +		if (rv == 0) {
  			rval |= 1;
  			continue;
  		}
  
 -		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;
 -
 -			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;
 +		env = NULL;
 +		switch (type) {
 +		case TYPE_ELF:
 +		case TYPE_AOUT:
 +			env = envdef;
 +			break;
 +		case TYPE_ELF32:
 +			env = env32;
 +			break;
 +		case TYPE_ELF64:
 +			env = env64;
 +			break;
 +		case TYPE_UNKNOWN:
 +		default:
 +			break;
  		}
 -		(void)close(fd);
 -		if (!file_ok) {
 +		if (env == NULL) {
 +			warn("%s: Unknown executable type", *argv);
  			rval |= 1;
  			continue;
  		}
  
 -		setenv("LD_TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1);
 -		if (aflag) setenv("LD_TRACE_LOADED_OBJECTS_ALL", "1", 1);
 +		/* ld.so magic */
 +		setenv(env[ENV_OBJECTS], "yes", 1);
 +		if (fmt1 != NULL)
 +			setenv(env[ENV_OBJECTS_FMT1], fmt1, 1);
 +		if (fmt2 != NULL)
 +			setenv(env[ENV_OBJECTS_FMT2], fmt2, 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);
 @@ -210,12 +200,12 @@
  				warn("wait");
  				rval |= 1;
  			} else if (WIFSIGNALED(status)) {
 -				fprintf(stderr, "%s: signal %d\n",
 -						*argv, WTERMSIG(status));
 +				fprintf(stderr, "%s: signal %d\n", *argv,
 +				    WTERMSIG(status));
  				rval |= 1;
  			} else if (WIFEXITED(status) && WEXITSTATUS(status)) {
 -				fprintf(stderr, "%s: exit status %d\n",
 -						*argv, WEXITSTATUS(status));
 +				fprintf(stderr, "%s: exit status %d\n", *argv,
 +				    WEXITSTATUS(status));
  				rval |= 1;
  			}
  			break;
 @@ -233,3 +223,188 @@
  
  	return rval;
  }
 +
 +static void
 +usage(void)
 +{
 +
 +	fprintf(stderr, "usage: ldd [-a] [-v] [-f format] program ...\n");
 +	exit(1);
 +}
 +
 +static int
 +is_executable(const char *fname, int fd, int *is_shlib, int *type)
 +{
 +	union {
 +		struct exec aout;
 +		Elf_Ehdr elf;
 +		Elf32_Ehdr elf32;
 +		Elf64_Ehdr elf64;
 +	} hdr;
 +	int n;
 +
 +	*is_shlib = 0;
 +	*type = TYPE_UNKNOWN;
 +
 +	if ((n = read(fd, &hdr, sizeof(hdr))) == -1) {
 +		warn("%s: can't read program header", fname);
 +		return (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", fname);
 +			return (0);
 +		}
 +		*type = TYPE_AOUT;
 +		return (1);
 +	}
 +
 +	if ((size_t)n >= sizeof(hdr.elf) && IS_ELF(hdr.elf)) {
 +		/* Handle ELF objects */
 +
 +		if (hdr.elf.e_ident[EI_CLASS] == ELFCLASS32) {
 +			/* Handle 32 bit ELF objects */
 +			Elf32_Phdr phdr;
 +			int dynamic, i;
 +
 +			dynamic = 0;
 +			*type = __ELF_WORD_SIZE == 32 ? TYPE_ELF : TYPE_ELF32;
 +
 +			if (lseek(fd, hdr.elf32.e_phoff, SEEK_SET) == -1) {
 +				warnx("%s: header too short", fname);
 +				return (0);
 +			}
 +			for (i = 0; i < hdr.elf32.e_phnum; i++) {
 +				if (read(fd, &phdr, hdr.elf32.e_phentsize)
 +				   != sizeof(phdr)) {
 +					warnx("%s: can't read program header",
 +					    fname);
 +					return (0);
 +				}
 +				if (phdr.p_type == PT_DYNAMIC) {
 +					dynamic = 1;
 +					break;
 +				}
 +			}
 +
 +			if (!dynamic) {
 +				warnx("%s: not a dynamic ELF executable",
 +				    fname);
 +				return (0);
 +			}
 +			if (hdr.elf.e_type == ET_DYN) {
 +				if (hdr.elf.e_ident[EI_OSABI] &
 +				    ELFOSABI_FREEBSD) {
 +					*is_shlib = 1;
 +					return (1);
 +				}
 +				warnx("%s: not a FreeBSD ELF shared object",
 +				    fname);
 +				return (0);
 +			}
 +
 +			return (1);
 +		}
 +
 +		if (hdr.elf.e_ident[EI_CLASS] == ELFCLASS64) {
 +			/* Handle 64 bit ELF objects */
 +			Elf64_Phdr phdr;
 +			int dynamic, i;
 +
 +			dynamic = 0;
 +			*type = __ELF_WORD_SIZE == 64 ? TYPE_ELF : TYPE_ELF64;
 +
 +			if (lseek(fd, hdr.elf64.e_phoff, SEEK_SET) == -1) {
 +				warnx("%s: header too short", fname);
 +				return (0);
 +			}
 +			for (i = 0; i < hdr.elf64.e_phnum; i++) {
 +				if (read(fd, &phdr, hdr.elf64.e_phentsize)
 +				   != sizeof(phdr)) {
 +					warnx("%s: can't read program header",
 +					    fname);
 +					return (0);
 +				}
 +				if (phdr.p_type == PT_DYNAMIC) {
 +					dynamic = 1;
 +					break;
 +				}
 +			}
 +
 +			if (!dynamic) {
 +				warnx("%s: not a dynamic ELF executable",
 +				    fname);
 +				return (0);
 +			}
 +			if (hdr.elf.e_type == ET_DYN) {
 +				if (hdr.elf.e_ident[EI_OSABI] &
 +				    ELFOSABI_FREEBSD) {
 +					*is_shlib = 1;
 +					return (1);
 +				}
 +				warnx("%s: not a FreeBSD ELF shared object",
 +				    fname);
 +				return (0);
 +			}
 +
 +			return (1);
 +		}
 +
 +		{
 +			/*
 +			 * Handle any other kinds of ELF objects -
 +			 * Should we throw a warning?
 +			 */
 +			Elf_Phdr phdr;
 +			int dynamic, i;
 +
 +			dynamic = 0;
 +			*type = TYPE_ELF;
 +
 +			if (lseek(fd, hdr.elf.e_phoff, SEEK_SET) == -1) {
 +				warnx("%s: header too short", fname);
 +				return (0);
 +			}
 +			for (i = 0; i < hdr.elf.e_phnum; i++) {
 +				if (read(fd, &phdr, hdr.elf.e_phentsize)
 +				   != sizeof(phdr)) {
 +					warnx("%s: can't read program header",
 +					    fname);
 +					return (0);
 +				}
 +				if (phdr.p_type == PT_DYNAMIC) {
 +					dynamic = 1;
 +					break;
 +				}
 +			}
 +
 +			if (!dynamic) {
 +				warnx("%s: not a dynamic ELF executable",
 +				    fname);
 +				return (0);
 +			}
 +			if (hdr.elf.e_type == ET_DYN) {
 +				if (hdr.elf.e_ident[EI_OSABI] &
 +				    ELFOSABI_FREEBSD) {
 +					*is_shlib = 1;
 +					return (1);
 +				}
 +				warnx("%s: not a FreeBSD ELF shared object",
 +				    fname);
 +				return (0);
 +			}
 +
 +			return (1);
 +		}
 +
 +	}
 +
 +	warnx("%s: not a dynamic executable", fname);
 +	return (0);
 +}
 
 --VbJkn9YxBvnuCH5J--
State-Changed-From-To: open->patched 
State-Changed-By: edwin 
State-Changed-When: Thu Jul 3 22:39:57 UTC 2008 
State-Changed-Why:  
Patched in HEAD. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=124906 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/124906: commit references a PR
Date: Thu,  3 Jul 2008 22:38:14 +0000 (UTC)

 edwin       2008-07-03 22:37:51 UTC
 
   FreeBSD src repository
 
   Modified files:
     usr.bin/ldd          ldd.1 ldd.c 
   Log:
   SVN rev 180236 on 2008-07-03 22:37:51Z by edwin
   
   On 64 bit architectures, you can run 32 bit executables and the rtld can trace them, but ldd(1) doesn't know yet how to detect them:
   
       [/] 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)
   
   Added support in ldd(1) for the LD_32_xxx environment variables if
   the architecture of the machine is >32 bits. If we ever go to 128
   bit architectures this excercise will have to be repeated but thanks
   to earlier commits today it will be relative simple.
   
   PR:             bin/124906
   Submitted by:   edwin
   Approved by:    bde (mentor)
   MFC after:      1 week
   
   Revision  Changes    Path
   1.27      +6 -0      src/usr.bin/ldd/ldd.1
   1.36      +76 -2     src/usr.bin/ldd/ldd.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: edwin 
State-Changed-When: Thu Jul 10 01:34:08 UTC 2008 
State-Changed-Why:  
MFC done. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=124906 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/124906: commit references a PR
Date: Thu, 10 Jul 2008 01:32:38 +0000 (UTC)

 edwin       2008-07-10 01:32:08 UTC
 
   FreeBSD src repository
 
   Modified files:        (Branch: RELENG_7)
     usr.bin/ldd          ldd.1 ldd.c 
   Log:
   SVN rev 180404 on 2008-07-10 01:32:08Z by edwin
   
   MFC of changes 180234-180236:
   
   On 64 bit architectures, you can run 32 bit executables and the rtld can trace them, but ldd(1) doesn't know yet how to detect them:
   
       [/] 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)
   
       Added support in ldd(1) for the LD_32_xxx environment variables if
       the architecture of the machine is >32 bits. If we ever go to 128
       bit architectures this excercise will have to be repeated but thanks
       to earlier commits today it will be relative simple.
   
   PR:             bin/124906
   Submitted by:   edwin
   Approved by:    bde (mentor)
   
   Revision   Changes    Path
   1.24.2.1   +6 -0      src/usr.bin/ldd/ldd.1
   1.33.24.1  +211 -101  src/usr.bin/ldd/ldd.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/124906: commit references a PR
Date: Thu, 10 Jul 2008 01:34:10 +0000 (UTC)

 edwin       2008-07-10 01:33:48 UTC
 
   FreeBSD src repository
 
   Modified files:        (Branch: RELENG_6)
     usr.bin/ldd          ldd.1 ldd.c 
   Log:
   SVN rev 180405 on 2008-07-10 01:33:48Z by edwin
   
   MFC of changes 180234-180236:
   
   On 64 bit architectures, you can run 32 bit executables and the rtld can trace them, but ldd(1) doesn't know yet how to detect them:
   
       [/] 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)
   
       Added support in ldd(1) for the LD_32_xxx environment variables if
       the architecture of the machine is >32 bits. If we ever go to 128
       bit architectures this excercise will have to be repeated but thanks
       to earlier commits today it will be relative simple.
   
   PR:             bin/124906
   Submitted by:   edwin
   Approved by:    bde (mentor)
   
   Revision   Changes    Path
   1.23.12.2  +6 -0      src/usr.bin/ldd/ldd.1
   1.33.14.1  +211 -101  src/usr.bin/ldd/ldd.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/124906: commit references a PR
Date: Mon, 21 Jul 2008 02:13:38 +0000 (UTC)

 edwin       2008-07-21 02:13:14 UTC
 
   FreeBSD src repository
 
   Modified files:
     usr.bin/ldd          ldd.c 
   Log:
   SVN rev 180646 on 2008-07-21 02:13:14Z by edwin
   
   After the commit of SVN rev 180236, wilko@ noticed that the approach
   doesn't work on the Alpha platform: machine/elf.h doesn't include
   sys/elf32.h there.
   
   PR:             related to bin/124906
   Approved by:    bde@
   MFC after:      1 week
   
   Revision  Changes    Path
   1.37      +18 -4     src/usr.bin/ldd/ldd.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/124906: commit references a PR
Date: Wed, 30 Jul 2008 18:19:45 +0000 (UTC)

 edwin       2008-07-30 03:32:32 UTC
 
   FreeBSD src repository
 
   Modified files:        (Branch: RELENG_6)
     usr.bin/ldd          ldd.c 
   Log:
   SVN rev 180984 on 2008-07-30 03:32:32Z by edwin
   
   MFC of 180646, 180877:
   
   After the commit of SVN rev 180236, wilko@ noticed that the approach
   doesn't work on the Alpha platform: machine/elf.h doesn't include
   sys/elf32.h there.
   
   PR:             related to bin/124906
   Approved by:    bde@
   
   Revision   Changes    Path
   1.33.14.2  +15 -4     src/usr.bin/ldd/ldd.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/124906: commit references a PR
Date: Wed, 30 Jul 2008 18:20:05 +0000 (UTC)

 edwin       2008-07-30 03:33:49 UTC
 
   FreeBSD src repository
 
   Modified files:        (Branch: RELENG_7)
     usr.bin/ldd          ldd.c 
   Log:
   SVN rev 180985 on 2008-07-30 03:33:49Z by edwin
   
   MFC of 180646, 180877:
   
   After the commit of SVN rev 180236, wilko@ noticed that the approach
   doesn't work on the Alpha platform: machine/elf.h doesn't include
   sys/elf32.h there.
   
   PR:             related to bin/124906
   Approved by:    bde@
   
   Revision   Changes    Path
   1.33.24.2  +15 -4     src/usr.bin/ldd/ldd.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
>Unformatted:
