diff options
Diffstat (limited to 'usr.bin/ldd')
-rw-r--r-- | usr.bin/ldd/Makefile.common | 16 | ||||
-rw-r--r-- | usr.bin/ldd/Makefile.elf | 10 | ||||
-rw-r--r-- | usr.bin/ldd/build/Makefile | 42 | ||||
-rw-r--r-- | usr.bin/ldd/dummy.c | 3 | ||||
-rw-r--r-- | usr.bin/ldd/elf32/Makefile | 33 | ||||
-rw-r--r-- | usr.bin/ldd/elf32_compat/Makefile | 26 | ||||
-rw-r--r-- | usr.bin/ldd/elf64/Makefile | 51 | ||||
-rw-r--r-- | usr.bin/ldd/ldd.1 | 126 | ||||
-rw-r--r-- | usr.bin/ldd/ldd.c | 237 | ||||
-rw-r--r-- | usr.bin/ldd/ldd.h | 47 | ||||
-rw-r--r-- | usr.bin/ldd/ldd_elfxx.c | 269 |
11 files changed, 860 insertions, 0 deletions
diff --git a/usr.bin/ldd/Makefile.common b/usr.bin/ldd/Makefile.common new file mode 100644 index 0000000..6193b71 --- /dev/null +++ b/usr.bin/ldd/Makefile.common @@ -0,0 +1,16 @@ +# $NetBSD: Makefile.common,v 1.3 2013/04/25 07:12:46 matt Exp $ + +LDELFSO=${NETBSDSRCDIR}/libexec/ld.elf_so +CPPFLAGS+= -I${LDELFSO} -DLIBDIR=\"${LIBDIR}\" +CPPFLAGS+= -D_RTLD_SOURCE +.if !empty(MACHINE_ARCH:Mearm*) +CPPFLAGS+= -I${NETBSDSRCDIR}/lib/libexecinfo +.endif +#CPPFLAGS+= -DDEBUG +.PATH: ${LDELFSO} + +.if (${MACHINE_ARCH} == "sparc") || (${MACHINE_ARCH} == "sparc64") || \ + (${MACHINE_ARCH} == "arm") || (${MACHINE_ARCH} == "m68k") || \ + (${MACHINE_ARCH} == "powerpc") || (${MACHINE_ARCH:Mmips*} != "") +CPPFLAGS+= -DVARPSZ +.endif diff --git a/usr.bin/ldd/Makefile.elf b/usr.bin/ldd/Makefile.elf new file mode 100644 index 0000000..3acc9a9 --- /dev/null +++ b/usr.bin/ldd/Makefile.elf @@ -0,0 +1,10 @@ +# $NetBSD: Makefile.elf,v 1.5 2013/05/07 13:00:35 christos Exp $ + +# Makefile fragment to build a (32 or 64 bit) libldd_elfxx.a. +# Expects CPPFLAGS to have ELFSIZE set, and LIB to be set. + +SRCS= ldd_elfxx.c +SRCS+= xmalloc.c debug.c expand.c map_object.c load.c search.c \ + headers.c paths.c tls.c symver.c + +.include "Makefile.common" diff --git a/usr.bin/ldd/build/Makefile b/usr.bin/ldd/build/Makefile new file mode 100644 index 0000000..312eb00 --- /dev/null +++ b/usr.bin/ldd/build/Makefile @@ -0,0 +1,42 @@ +# $NetBSD: Makefile,v 1.5 2019/01/27 05:17:48 kre Exp $ + +NOSANITIZER= # defined + +.include <bsd.own.mk> # for MKDYNAMICROOT definition + +PROG= ldd +SRCS= ldd.c +MAN= ldd.1 + +.PATH: ${.CURDIR}/.. + +.if ${OBJECT_FMTS:Melf32} != "" +LIB_ELF32DIR!= cd ${.CURDIR}/../elf32 && ${PRINTOBJDIR} +EXTRA_LIBS+= ${LIB_ELF32DIR}/libldd_elf32.a +.else +CPPFLAGS.ldd.c+= -DELF64_ONLY +.endif + +.if (${MACHINE_ARCH} == "mips64el") || (${MACHINE_ARCH} == "mips64eb") +LIB_ELF32COMPATDIR!= cd ${.CURDIR}/../elf32_compat && ${PRINTOBJDIR} +EXTRA_LIBS+= ${LIB_ELF32COMPATDIR}/libldd_elf32_compat.a +.endif + +.if ${OBJECT_FMTS:Melf64} != "" +LIB_ELF64DIR!= cd ${.CURDIR}/../elf64 && ${PRINTOBJDIR} +EXTRA_LIBS+= ${LIB_ELF64DIR}/libldd_elf64.a +CPPFLAGS.ldd.c+= -DELFSIZE=64 +.else +CPPFLAGS.ldd.c+= -DELFSIZE=32 +.endif + +LDADD+= ${EXTRA_LIBS} +DPADD+= ${EXTRA_LIBS} + +.include "Makefile.common" + +.if (${MKDYNAMICROOT} == "no") +LDSTATIC?= -static +.endif + +.include <bsd.prog.mk> diff --git a/usr.bin/ldd/dummy.c b/usr.bin/ldd/dummy.c new file mode 100644 index 0000000..51f4a6e --- /dev/null +++ b/usr.bin/ldd/dummy.c @@ -0,0 +1,3 @@ +/* $NetBSD: dummy.c,v 1.1 2009/01/07 00:39:24 mrg Exp $ */ + +/* This file left intentially blank. */ diff --git a/usr.bin/ldd/elf32/Makefile b/usr.bin/ldd/elf32/Makefile new file mode 100644 index 0000000..71e00b2 --- /dev/null +++ b/usr.bin/ldd/elf32/Makefile @@ -0,0 +1,33 @@ +# $NetBSD: Makefile,v 1.12 2019/01/27 05:16:55 kre Exp $ + +NOSANITIZER= # defined + +.include <bsd.own.mk> +.include <bsd.init.mk> + +RTLD_FUNCS = \ + _rtld_tls_allocate \ + _rtld_tls_free \ + +.for _d in ${RTLD_FUNCS} +CPPFLAGS+= -D${_d}=_elf32_${_d} +.endfor + +CPPFLAGS+= -DELFSIZE=32 +LIB= ldd_elf32 + +# XXX Force one member +SRCS= dummy.c + +LIBISPRIVATE= yes +.PATH: ${.CURDIR}/.. + +.ifdef MLIBDIR +CPPFLAGS+= -DRTLD_ARCH_SUBDIR=\"${MLIBDIR}\" +.endif + +.if ${OBJECT_FMTS:Melf32} != "" +.include "../Makefile.elf" +.endif + +.include <bsd.lib.mk> diff --git a/usr.bin/ldd/elf32_compat/Makefile b/usr.bin/ldd/elf32_compat/Makefile new file mode 100644 index 0000000..e604c20 --- /dev/null +++ b/usr.bin/ldd/elf32_compat/Makefile @@ -0,0 +1,26 @@ +# $NetBSD: Makefile,v 1.4 2019/01/27 05:15:42 kre Exp $ + +NOSANITIZER= # defined + +.include <bsd.own.mk> +.include <bsd.init.mk> + +CPPFLAGS+= -DELFSIZE=32 -DELF32_COMPAT +LIB= ldd_elf32_compat + +# XXX Force one member +SRCS= dummy.c + +LIBISPRIVATE= yes +.PATH: ${.CURDIR}/.. + +.ifdef COMPAT_MLIBDIR +MLIBDIR= ${COMPAT_MLIBDIR} +CPPFLAGS+= -DRTLD_ARCH_SUBDIR=\"${MLIBDIR}\" +.endif + +.ifdef MLIBDIR +.include "../Makefile.elf" +.endif + +.include <bsd.lib.mk> diff --git a/usr.bin/ldd/elf64/Makefile b/usr.bin/ldd/elf64/Makefile new file mode 100644 index 0000000..f5cb2ab --- /dev/null +++ b/usr.bin/ldd/elf64/Makefile @@ -0,0 +1,51 @@ +# $NetBSD: Makefile,v 1.11 2019/01/27 05:14:45 kre Exp $ + +NOSANITIZER= # defined + +.include <bsd.own.mk> + +CPPFLAGS+= -DELFSIZE=64 +LIB= ldd_elf64 + +# XXX Force one member +SRCS= dummy.c + +LIBISPRIVATE= yes +.PATH: ${.CURDIR}/.. + +.if ${OBJECT_FMTS:Melf64} != "" + +# XXX we need to make sure that we don't accidentally get the elf32 +# XXX versions of these. + +RTLD_FUNCS = \ + _rtld_expand_path \ + _rtld_digest_dynamic \ + _rtld_digest_phdr \ + _rtld_load_needed_objects \ + _rtld_load_object \ + _rtld_map_object \ + _rtld_obj_free \ + _rtld_obj_new \ + _rtld_object_add_name \ + _rtld_object_match_name \ + _rtld_add_paths \ + _rtld_process_hints \ + _rtld_sysctl \ + _rtld_tls_allocate \ + _rtld_tls_free \ + _rtld_load_library + +.for _d in ${RTLD_FUNCS} +CPPFLAGS+= -D${_d}=_elf64_${_d} +.endfor + +.if (${MACHINE_ARCH} == "mips64el") || (${MACHINE_ARCH} == "mips64eb") +CPPFLAGS+= -DRTLD_ARCH_SUBDIR=\"${MLIBDIR}\" +.endif + +.include "../Makefile.elf" + +.endif + +.include <bsd.lib.mk> diff --git a/usr.bin/ldd/ldd.1 b/usr.bin/ldd/ldd.1 new file mode 100644 index 0000000..6e49e9c --- /dev/null +++ b/usr.bin/ldd/ldd.1 @@ -0,0 +1,126 @@ +.\" $NetBSD: ldd.1,v 1.20 2017/12/25 05:08:49 maya Exp $ +.\" +.\" Copyright (c) 1998 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Paul Kranenburg. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd December 25, 2017 +.Dt LDD 1 +.Os +.Sh NAME +.Nm ldd +.Nd list dynamic object dependencies +.Sh SYNOPSIS +.Nm +.Op Fl o +.Op Fl f Ar format +.Ar program ... +.Sh DESCRIPTION +.Nm +displays all shared objects that are needed to run the given program. +Contrary to +.Xr nm 1 , +the list includes +.Dq indirect +dependencies that are the result of needed shared objects which themselves +depend on yet other shared objects. +Zero, one or two +.Fl f +options may be given. +The argument is a format string passed to +.Xr rtld 1 +and allows customization of +.Nm ldd Ns 's +output. +The first format argument is used for library objects and defaults to +.Qq "\et-l%o.%m => %p\en" . +The second format argument is used for non-library objects and defaults to +.Qq "\et%o => %p\en" . +.Pp +These arguments are interpreted as format strings a la +.Xr printf 3 +to customize the trace output and allow +.Nm +to be operated as a filter more conveniently. +The following conversions can be used: +.Bl -tag -width xxxx +.It \&%a +The main program's name +.Po also known as +.Dq __progname +.Pc . +.It \&%A +The value of the environment variable +.Ev LD_TRACE_LOADED_OBJECTS_PROGNAME +in a.out and the program name from the argument vector from elf. +.It \&%o +The library name. +.It \&%m +The library's major version number. +.It \&%n +The library's minor version number (a.out only, ignored in elf). +.It \&%p +The full pathname as determined by +.Nm rtld Ns 's +library search rules. +.It \&%x +The library's load address +.El +.Pp +Additionally, +.Sy \en +and +.Sy \et +are recognized and have their usual meaning. +.Pp +The +.Fl o +option is an alias for +.Fl f +.Ar \&%a:-l\&%o.\&%m => \&%p\en , +which makes +.Nm +behave analogously to +.Ic nm Fl o . +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr ld 1 , +.Xr ld.elf_so 1 , +.Xr nm 1 , +.Xr rtld 1 +.Sh HISTORY +A +.Nm +utility first appeared in SunOS 4.0, it appeared in its current form +in +.Nx 0.9a . +.Sh BUGS +The +a.out +.Nm +actually runs the program it has been requested to analyze which in specially +constructed environments can have security implications. diff --git a/usr.bin/ldd/ldd.c b/usr.bin/ldd/ldd.c new file mode 100644 index 0000000..a2794f8 --- /dev/null +++ b/usr.bin/ldd/ldd.c @@ -0,0 +1,237 @@ +/* $NetBSD: ldd.c,v 1.23 2017/12/25 05:08:49 maya Exp $ */ + +/*- + * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright 1996 John D. Polstra. + * Copyright 1996 Matt Thomas <matt@3am-software.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Polstra. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: ldd.c,v 1.23 2017/12/25 05:08:49 maya Exp $"); +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/wait.h> + +#include <dirent.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> + +#include "debug.h" +#include "rtld.h" +#include "ldd.h" + +/* + * Data declarations. + */ +static char *error_message; /* Message for dlopen(), or NULL */ +bool _rtld_trust; /* False for setuid and setgid programs */ +/* + * This may be ELF64 or ELF32 but since they are used opaquely it doesn't + * really matter. + */ +Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */ +Obj_Entry **_rtld_objtail = &_rtld_objlist; + /* Link field of last object in list */ +u_int _rtld_objcount; /* Number of shared objects */ +u_int _rtld_objloads; /* Number of objects loaded */ + +Obj_Entry *_rtld_objmain; /* The main program shared object */ +size_t _rtld_pagesz; + +Search_Path *_rtld_default_paths; +Search_Path *_rtld_paths; +Library_Xform *_rtld_xforms; + +static void usage(void) __dead; +char *main_local; +char *main_progname; + +static void +usage(void) +{ + fprintf(stderr, "Usage: %s [-f <format 1>] [-f <format 2>] <filename>" + " ...\n", getprogname()); + exit(1); +} + +int +main(int argc, char **argv) +{ + const char *fmt1 = NULL, *fmt2 = NULL; + int c, exit_status = EXIT_SUCCESS; + +#ifdef DEBUG + debug = 1; +#endif + while ((c = getopt(argc, argv, "f:o")) != -1) { + switch (c) { + case 'f': + if (fmt1) { + if (fmt2) + errx(1, "Too many formats"); + fmt2 = optarg; + } else + fmt1 = optarg; + break; + case 'o': + if (fmt1 || fmt2) + errx(1, "Cannot use -o and -f together"); + fmt1 = "%a:-l%o.%m => %p\n"; + break; + default: + usage(); + /*NOTREACHED*/ + } + } + argc -= optind; + argv += optind; + + if (argc <= 0) { + usage(); + /*NOTREACHED*/ + } + + for (; argc != 0; argc--, argv++) { + int fd; + + fd = open(*argv, O_RDONLY); + if (fd == -1) { + exit_status = EXIT_FAILURE; + warn("%s", *argv); + continue; + } + if (elf_ldd(fd, *argv, fmt1, fmt2) == -1 + /* Alpha never had 32 bit support. */ +#if (defined(_LP64) && !defined(ELF64_ONLY)) || defined(MIPS_N32) + && elf32_ldd(fd, *argv, fmt1, fmt2) == -1 +#if defined(__mips__) && 0 /* XXX this is still hosed for some reason */ + && elf32_ldd_compat(fd, *argv, fmt1, fmt2) == -1 +#endif +#endif + ) { + exit_status = EXIT_FAILURE; + warnx("%s", error_message); + } + close(fd); + } + + return exit_status; +} + +/* + * Error reporting function. Use it like printf. If formats the message + * into a buffer, and sets things up so that the next call to dlerror() + * will return the message. + */ +void +_rtld_error(const char *fmt, ...) +{ + static char buf[512]; + va_list ap; + va_start(ap, fmt); + xvsnprintf(buf, sizeof buf, fmt, ap); + error_message = buf; + va_end(ap); +} + +char * +dlerror() +{ + char *msg = error_message; + error_message = NULL; + return msg; +} + +void +_rtld_die(void) +{ + const char *msg = dlerror(); + + if (msg == NULL) + msg = "Fatal error"; + xerrx(1, "%s", msg); +} + +void +_rtld_shared_enter(void) +{ +} + +void +_rtld_shared_exit(void) +{ +} + +void +_rtld_exclusive_enter(sigset_t *mask) +{ +} + +void +_rtld_exclusive_exit(sigset_t *mask) +{ +} diff --git a/usr.bin/ldd/ldd.h b/usr.bin/ldd/ldd.h new file mode 100644 index 0000000..a3b4520 --- /dev/null +++ b/usr.bin/ldd/ldd.h @@ -0,0 +1,47 @@ +/* $NetBSD: ldd.h,v 1.7 2012/07/08 00:53:44 matt Exp $ */ + +/* + * Copyright (c) 2008 Matthew R. Green + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +int elf32_ldd(int, char *, const char *, const char *); + +#ifdef _LP64 +#define LDD_ELF64 +#endif + +#ifdef LDD_ELF64 +int elf64_ldd(int, char *, const char *, const char *); +#define elf_ldd elf64_ldd +#elif defined(ELF32_COMPAT) +#define elf_ldd elf32_compat_ldd +#else +#define elf_ldd elf32_ldd +#endif + +extern char *main_local; +extern char *main_progname; diff --git a/usr.bin/ldd/ldd_elfxx.c b/usr.bin/ldd/ldd_elfxx.c new file mode 100644 index 0000000..d5def64 --- /dev/null +++ b/usr.bin/ldd/ldd_elfxx.c @@ -0,0 +1,269 @@ +/* $NetBSD: ldd_elfxx.c,v 1.7 2017/01/10 21:11:25 christos Exp $ */ + +/*- + * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright 1996 John D. Polstra. + * Copyright 1996 Matt Thomas <matt@3am-software.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Polstra. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: ldd_elfxx.c,v 1.7 2017/01/10 21:11:25 christos Exp $"); +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/wait.h> +#include <sys/stat.h> + +#include <dirent.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> + +#include "debug.h" +#include "rtld.h" +#include "ldd.h" + +static void print_needed(Obj_Entry *, const char *, const char *); +static void fmtprint(const char *, Obj_Entry *, const char *, const char *); + +/* + * elfxx_ldd() - bit-size independent ELF ldd implementation. + * returns 0 on success and -1 on failure. + */ +int +ELFNAME(ldd)(int fd, char *path, const char *fmt1, const char *fmt2) +{ + struct stat st; + + if (lseek(fd, 0, SEEK_SET) < 0 || + fstat(fd, &st) < 0) { + _rtld_error("%s: %s", path, strerror(errno)); + return -1; + } + + _rtld_pagesz = sysconf(_SC_PAGESIZE); + +#ifdef RTLD_ARCH_SUBDIR + _rtld_add_paths(path, &_rtld_default_paths, + RTLD_DEFAULT_LIBRARY_PATH "/" RTLD_ARCH_SUBDIR); +#endif + _rtld_add_paths(path, &_rtld_default_paths, RTLD_DEFAULT_LIBRARY_PATH); + + _rtld_paths = NULL; + _rtld_trust = (st.st_mode & (S_ISUID | S_ISGID)) == 0; + if (_rtld_trust) + _rtld_add_paths(path, &_rtld_paths, getenv("LD_LIBRARY_PATH")); + + _rtld_process_hints(path, &_rtld_paths, &_rtld_xforms, _PATH_LD_HINTS); + _rtld_objmain = _rtld_map_object(xstrdup(path), fd, &st); + if (_rtld_objmain == NULL) + return -1; + + _rtld_objmain->path = xstrdup(path); + _rtld_digest_dynamic(path, _rtld_objmain); + + /* Link the main program into the list of objects. */ + *_rtld_objtail = _rtld_objmain; + _rtld_objtail = &_rtld_objmain->next; + ++_rtld_objmain->refcount; + + (void) _rtld_load_needed_objects(_rtld_objmain, 0); + + if (fmt1 == NULL) + printf("%s:\n", _rtld_objmain->path); + main_local = path; + main_progname = _rtld_objmain->path; + print_needed(_rtld_objmain, fmt1, fmt2); + + while (_rtld_objlist != NULL) { + Obj_Entry *obj = _rtld_objlist; + _rtld_objlist = obj->next; + while (obj->rpaths != NULL) { + const Search_Path *rpath = obj->rpaths; + obj->rpaths = rpath->sp_next; + xfree(__UNCONST(rpath->sp_path)); + xfree(__UNCONST(rpath)); + } + while (obj->needed != NULL) { + const Needed_Entry *needed = obj->needed; + obj->needed = needed->next; + xfree(__UNCONST(needed)); + } + (void) munmap(obj->mapbase, obj->mapsize); + xfree(obj->path); + xfree(obj); + } + + _rtld_objmain = NULL; + _rtld_objtail = &_rtld_objlist; + /* Need to free _rtld_paths? */ + + return 0; +} + +void +fmtprint(const char *libname, Obj_Entry *obj, const char *fmt1, + const char *fmt2) +{ + const char *libpath = obj ? obj->path : "not found"; + char libnamebuf[200]; + char *libmajor = NULL; + const char *fmt; + char *cp; + int c; + + if (strncmp(libname, "lib", 3) == 0 && + (cp = strstr(libname, ".so")) != NULL) { + size_t i = cp - (libname + 3); + + if (i >= sizeof(libnamebuf)) + i = sizeof(libnamebuf) - 1; + (void)memcpy(libnamebuf, libname + 3, i); + libnamebuf[i] = '\0'; + if (cp[3] && isdigit((unsigned char)cp[4])) + libmajor = &cp[4]; + libname = libnamebuf; + } + + if (fmt1 == NULL) + fmt1 = libmajor != NULL ? + "\t-l%o.%m => %p\n" : + "\t-l%o => %p\n"; + if (fmt2 == NULL) + fmt2 = "\t%o => %p\n"; + + fmt = libname == libnamebuf ? fmt1 : fmt2; + while ((c = *fmt++) != '\0') { + switch (c) { + default: + putchar(c); + continue; + case '\\': + switch (c = *fmt) { + case '\0': + continue; + case 'n': + putchar('\n'); + break; + case 't': + putchar('\t'); + break; + } + break; + case '%': + switch (c = *fmt) { + case '\0': + continue; + case '%': + default: + putchar(c); + break; + case 'A': + printf("%s", main_local); + break; + case 'a': + printf("%s", main_progname); + break; + case 'o': + printf("%s", libname); + break; + case 'm': + printf("%s", libmajor); + break; + case 'n': + /* XXX: not supported for elf */ + break; + case 'p': + printf("%s", libpath); + break; + case 'x': + printf("%p", obj ? obj->mapbase : 0); + break; + } + break; + } + ++fmt; + } +} + +void +print_needed(Obj_Entry *obj, const char *fmt1, const char *fmt2) +{ + const Needed_Entry *needed; + + for (needed = obj->needed; needed != NULL; needed = needed->next) { + const char *libname = obj->strtab + needed->name; + + if (needed->obj != NULL) { + if (!needed->obj->printed) { + fmtprint(libname, needed->obj, fmt1, fmt2); + needed->obj->printed = 1; + print_needed(needed->obj, fmt1, fmt2); + } + } else { + fmtprint(libname, needed->obj, fmt1, fmt2); + } + } +} |