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
This commit is contained in:
Edwin Groothuis 2008-07-03 22:37:51 +00:00
parent d3c1e14b41
commit fffd993df2
2 changed files with 82 additions and 2 deletions

View File

@ -64,6 +64,12 @@ option.
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() cannot open 32 bit dynamic libraries,
so
.Nm
will show the error
.Qq "unsupported file layout" .
.Sh SEE ALSO
.Xr ld 1 ,
.Xr nm 1 ,

View File

@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <a.out.h>
#include <dlfcn.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
@ -54,6 +55,9 @@ static void usage(void);
#define TYPE_UNKNOWN 0
#define TYPE_AOUT 1
#define TYPE_ELF 2 /* Architecture default */
#if __ELF_WORD_SIZE > 32
#define TYPE_ELF32 3 /* Explicit 32 bits on architectures >32 bits */
#endif
#define ENV_OBJECTS 0
#define ENV_OBJECTS_FMT1 1
@ -69,6 +73,15 @@ const char *envdef[ENV_LAST] = {
"LD_TRACE_LOADED_OBJECTS_PROGNAME",
"LD_TRACE_LOADED_OBJECTS_ALL",
};
#if __ELF_WORD_SIZE > 32
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
int
main(int argc, char *argv[])
@ -124,8 +137,6 @@ main(int argc, char *argv[])
int fd, status, is_shlib, rv, type;
const char **env;
env = envdef; /* Temporary placeholder */
if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
warn("%s", *argv);
rval |= 1;
@ -138,6 +149,25 @@ main(int argc, char *argv[])
continue;
}
switch (type) {
case TYPE_ELF:
case TYPE_AOUT:
env = envdef;
break;
#if __ELF_WORD_SIZE > 32
case TYPE_ELF32:
env = env32;
break;
#endif
case TYPE_UNKNOWN:
default:
/*
* This shouldn't happen unless is_executable()
* is broken.
*/
errx(EDOOFUS, "unknown executable type");
}
/* ld.so magic */
setenv(env[ENV_OBJECTS], "yes", 1);
if (fmt1 != NULL)
@ -199,6 +229,7 @@ is_executable(const char *fname, int fd, int *is_shlib, int *type)
{
union {
struct exec aout;
Elf32_Ehdr elf32;
Elf_Ehdr elf;
} hdr;
int n;
@ -225,6 +256,49 @@ is_executable(const char *fname, int fd, int *is_shlib, int *type)
return (1);
}
#if __ELF_WORD_SIZE > 32
if ((size_t)n >= sizeof(hdr.elf32) && IS_ELF(hdr.elf32) &&
hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
/* Handle 32 bit ELF objects */
Elf32_Phdr phdr;
int dynamic, i;
dynamic = 0;
*type = 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.elf32.e_type == ET_DYN) {
if (hdr.elf32.e_ident[EI_OSABI] & ELFOSABI_FREEBSD) {
*is_shlib = 1;
return (1);
}
warnx("%s: not a FreeBSD ELF shared object", fname);
return (0);
}
return (1);
}
#endif
if ((size_t)n >= sizeof(hdr.elf) && IS_ELF(hdr.elf) &&
hdr.elf.e_ident[EI_CLASS] == ELF_TARG_CLASS) {
/* Handle default ELF objects on this architecture */