Extract the determination of the kind of (dynamic) executable from

the main-loop into a seperate function.
Instead of using hardcoded environment variables, define them in a
lookup table.
For the rest, no functionality changes.

Approved by:	bde (mentor)
MFC after:	1 week
This commit is contained in:
Edwin Groothuis 2008-07-03 22:30:18 +00:00
parent a0d476a986
commit d3c1e14b41

View File

@ -47,13 +47,28 @@ __FBSDID("$FreeBSD$");
#include "extern.h"
static void
usage(void)
{
static int is_executable(const char *fname, int fd, int *is_shlib,
int *type);
static void usage(void);
fprintf(stderr, "usage: ldd [-a] [-v] [-f format] program ...\n");
exit(1);
}
#define TYPE_UNKNOWN 0
#define TYPE_AOUT 1
#define TYPE_ELF 2 /* Architecture default */
#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",
};
int
main(int argc, char *argv[])
@ -104,95 +119,35 @@ main(int argc, char *argv[])
}
#endif
/* ld.so magic */
setenv("LD_TRACE_LOADED_OBJECTS", "yes", 1);
if (fmt1 != NULL)
setenv("LD_TRACE_LOADED_OBJECTS_FMT1", fmt1, 1);
if (fmt2 != NULL)
setenv("LD_TRACE_LOADED_OBJECTS_FMT2", fmt2, 1);
rval = 0;
for (; argc > 0; argc--, argv++) {
int fd, n, status, file_ok, is_shlib;
union {
struct exec aout;
Elf_Ehdr elf;
} hdr;
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;
continue;
}
if ((n = read(fd, &hdr, sizeof(hdr))) == -1) {
warn("%s: can't read program header", *argv);
close(fd);
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, i;
dynamic = 0;
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;
}
rv = is_executable(*argv, fd, &is_shlib, &type);
close(fd);
if (!file_ok) {
if (rv == 0) {
rval |= 1;
continue;
}
setenv("LD_TRACE_LOADED_OBJECTS_PROGNAME", *argv, 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("LD_TRACE_LOADED_OBJECTS_ALL", "1", 1);
setenv(env[ENV_OBJECTS_ALL], "1", 1);
else if (fmt1 == NULL && fmt2 == NULL)
/* Default formats */
printf("%s:\n", *argv);
@ -230,3 +185,87 @@ main(int argc, char *argv[])
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;
} 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) &&
hdr.elf.e_ident[EI_CLASS] == ELF_TARG_CLASS) {
/* Handle default ELF objects on this architecture */
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);
}