Tweak the support for using ldd on 32-bit objects a bit further.
Specifically, build a 32-bit /usr/bin/ldd32 on amd64 which handles 32-bit objects. Since it is a 32-bit binary, it can fork a child process which can dlopen() a 32-bit shared library. The current 32-bit support in ldd can't do this because it does the dlopen() from a 64-bit process. In order to preserve an intuitive interface for users, the ldd binary automatically execs /usr/bin/ldd32 for 32-bit objects. The end result is that ldd on amd64 now transparently handles 32-bit shared libraries in addition to 32-bit binaries. Submitted by: ps (indirectly)
This commit is contained in:
parent
a05cf8c6db
commit
e68ed79390
@ -482,6 +482,8 @@ build32:
|
||||
.for _t in obj depend all
|
||||
cd ${.CURDIR}/libexec/rtld-elf; \
|
||||
PROG=ld-elf32.so.1 ${LIB32WMAKE} ${_t}
|
||||
cd ${.CURDIR}/usr.bin/ldd; \
|
||||
PROG=ldd32 ${LIB32WMAKE} ${_t}
|
||||
.endfor
|
||||
|
||||
distribute32 install32:
|
||||
@ -501,6 +503,7 @@ distribute32 install32:
|
||||
cd ${.CURDIR}/secure/lib; ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
.endif
|
||||
cd ${.CURDIR}/libexec/rtld-elf; PROG=ld-elf32.so.1 ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIB32IMAKE} ${.TARGET:S/32$//}
|
||||
.endif
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= ldd
|
||||
PROG?= ldd
|
||||
SRCS= ldd.c
|
||||
.if ${MACHINE_ARCH} == "i386"
|
||||
SRCS+= sods.c
|
||||
|
@ -64,12 +64,6 @@ 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 ,
|
||||
|
@ -44,10 +44,17 @@ __FBSDID("$FreeBSD$");
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
#ifdef COMPAT_32BIT
|
||||
#define LD_ "LD_32_"
|
||||
#else
|
||||
#define LD_ "LD_"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 32-bit ELF data structures can only be used if the system header[s] declare
|
||||
* them. There is no official macro for determining whether they are declared,
|
||||
@ -66,30 +73,60 @@ static void usage(void);
|
||||
#define TYPE_ELF 2 /* Architecture default */
|
||||
#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
|
||||
#define TYPE_ELF32 3 /* Explicit 32 bits on architectures >32 bits */
|
||||
#endif
|
||||
|
||||
#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
|
||||
#define _PATH_LDD32 "/usr/bin/ldd32"
|
||||
|
||||
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",
|
||||
};
|
||||
#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
|
||||
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",
|
||||
};
|
||||
static int
|
||||
execldd32(char *file, char *fmt1, char *fmt2, int aflag, int vflag)
|
||||
{
|
||||
char *argv[8];
|
||||
int i, rval, status;
|
||||
|
||||
unsetenv(LD_ "TRACE_LOADED_OBJECTS");
|
||||
|
||||
rval = 0;
|
||||
i = 0;
|
||||
argv[i++] = strdup(_PATH_LDD32);
|
||||
if (aflag)
|
||||
argv[i++] = strdup("-a");
|
||||
if (vflag)
|
||||
argv[i++] = strdup("-v");
|
||||
if (fmt1) {
|
||||
argv[i++] = strdup("-f");
|
||||
argv[i++] = strdup(fmt1);
|
||||
}
|
||||
if (fmt2) {
|
||||
argv[i++] = strdup("-f");
|
||||
argv[i++] = strdup(fmt2);
|
||||
}
|
||||
|
||||
argv[i++] = strdup(file);
|
||||
argv[i++] = NULL;
|
||||
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
err(1, "fork");
|
||||
break;
|
||||
case 0:
|
||||
execv(_PATH_LDD32, argv);
|
||||
warn("%s", _PATH_LDD32);
|
||||
_exit(1);
|
||||
break;
|
||||
default:
|
||||
if (wait(&status) <= 0) {
|
||||
rval = 1;
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
rval = 1;
|
||||
} else if (WIFEXITED(status) && WEXITSTATUS(status)) {
|
||||
rval = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
while (i--)
|
||||
free(argv[i]);
|
||||
setenv(LD_ "TRACE_LOADED_OBJECTS", "yes", 1);
|
||||
return (rval);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
@ -144,7 +181,6 @@ main(int argc, char *argv[])
|
||||
rval = 0;
|
||||
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);
|
||||
@ -161,12 +197,11 @@ main(int argc, char *argv[])
|
||||
switch (type) {
|
||||
case TYPE_ELF:
|
||||
case TYPE_AOUT:
|
||||
env = envdef;
|
||||
break;
|
||||
#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
|
||||
case TYPE_ELF32:
|
||||
env = env32;
|
||||
break;
|
||||
rval |= execldd32(*argv, fmt1, fmt2, aflag, vflag);
|
||||
continue;
|
||||
#endif
|
||||
case TYPE_UNKNOWN:
|
||||
default:
|
||||
@ -178,15 +213,15 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* ld.so magic */
|
||||
setenv(env[ENV_OBJECTS], "yes", 1);
|
||||
setenv(LD_ "TRACE_LOADED_OBJECTS", "yes", 1);
|
||||
if (fmt1 != NULL)
|
||||
setenv(env[ENV_OBJECTS_FMT1], fmt1, 1);
|
||||
setenv(LD_ "TRACE_LOADED_OBJECTS_FMT1", fmt1, 1);
|
||||
if (fmt2 != NULL)
|
||||
setenv(env[ENV_OBJECTS_FMT2], fmt2, 1);
|
||||
setenv(LD_ "TRACE_LOADED_OBJECTS_FMT2", fmt2, 1);
|
||||
|
||||
setenv(env[ENV_OBJECTS_PROGNAME], *argv, 1);
|
||||
setenv(LD_ "TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1);
|
||||
if (aflag)
|
||||
setenv(env[ENV_OBJECTS_ALL], "1", 1);
|
||||
setenv(LD_ "TRACE_LOADED_OBJECTS_ALL", "1", 1);
|
||||
else if (fmt1 == NULL && fmt2 == NULL)
|
||||
/* Default formats */
|
||||
printf("%s:\n", *argv);
|
||||
|
Loading…
Reference in New Issue
Block a user