# HG changeset patch # Parent 6f5669356e76cacd52bd8dc593371bdec2b2404c Implement lddsoft, analogous to ldd32 for determining libraries loaded for soft float binaries. lddsoft gets called automatically by ldd based on the signature. diff -r 6f5669356e76 usr.bin/ldd/ldd.c --- a/usr.bin/ldd/ldd.c +++ b/usr.bin/ldd/ldd.c @@ -48,6 +48,10 @@ #include "extern.h" +#ifdef __arm__ +#include +#endif + /* We don't support a.out executables on arm64 */ #ifndef __aarch64__ #include @@ -66,11 +70,13 @@ #define LDD_SETENV(name, value, overwrite) do { \ setenv("LD_" name, value, overwrite); \ setenv("LD_32_" name, value, overwrite); \ + setenv("LD_SOFT_" name, value, overwrite); \ } while (0) #define LDD_UNSETENV(name) do { \ unsetenv("LD_" name); \ unsetenv("LD_32_" name); \ + unsetenv("LD_SOFT_" name); \ } while (0) static int is_executable(const char *fname, int fd, int *is_shlib, @@ -135,6 +141,61 @@ execldd32(char *file, char *fmt1, char * } #endif +#if __ARM_ARCH >= 6 && defined(__VFP_FP__) +#define TYPE_ELFSOFT 4 /* Explicit soft float on a hard float */ + +#define _PATH_LDDSOFT "/usr/bin/lddsoft" + +static int +execlddsoft(char *file, char *fmt1, char *fmt2, int aflag, int vflag) +{ + char *argv[8]; + int i, rval, status; + + LDD_UNSETENV("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 != NULL) { + argv[i++] = strdup("-f"); + argv[i++] = strdup(fmt1); + } + if (fmt2 != NULL) { + 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_LDDSOFT, argv); + warn("%s", _PATH_LDDSOFT); + _exit(127); + break; + default: + if (wait(&status) < 0) + rval = 1; + else if (WIFSIGNALED(status)) + rval = 1; + else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) + rval = 1; + break; + } + while (i--) + free(argv[i]); + LDD_SETENV("TRACE_LOADED_OBJECTS", "yes", 1); + return (rval); +} +#endif + int main(int argc, char *argv[]) { @@ -204,11 +265,16 @@ main(int argc, char *argv[]) case TYPE_ELF: case TYPE_AOUT: break; -#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED) +#if defined(TYPE_ELF32) case TYPE_ELF32: rval |= execldd32(*argv, fmt1, fmt2, aflag, vflag); continue; #endif +#if defined(TYPE_ELFSOFT) + case TYPE_ELFSOFT: + rval |= execlddsoft(*argv, fmt1, fmt2, aflag, vflag); + continue; +#endif case TYPE_UNKNOWN: default: /* @@ -364,6 +430,11 @@ is_executable(const char *fname, int fd, dynamic = 0; *type = TYPE_ELF; +#if __ARM_ARCH >= 6 && defined(__VFP_FP__) + /* Not definitely hard float -> soft float */ + if ((hrd.elf.e_flags & EF_ARM_VFP_FLOAT) == 0) + *type = TYPE_ELFSOFT; +#endif if (lseek(fd, hdr.elf.e_phoff, SEEK_SET) == -1) { warnx("%s: header too short", fname);