Allow ldd(1) be used on shared libraries in addition to executables.

This commit is contained in:
Maxim Sobolev 2002-02-04 10:33:48 +00:00
parent fc41545e4e
commit c6de4ce791
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=90172
5 changed files with 57 additions and 12 deletions

View File

@ -45,6 +45,7 @@
#define RTLD_MODEMASK 0x3 #define RTLD_MODEMASK 0x3
#define RTLD_GLOBAL 0x100 /* Make symbols globally available */ #define RTLD_GLOBAL 0x100 /* Make symbols globally available */
#define RTLD_LOCAL 0 /* Opposite of RTLD_GLOBAL, and the default */ #define RTLD_LOCAL 0 /* Opposite of RTLD_GLOBAL, and the default */
#define RTLD_TRACE 0x200 /* Trace loaded objects and exit */
/* /*
* Special handle arguments for dlsym(). * Special handle arguments for dlsym().

View File

@ -123,6 +123,13 @@ Symbols in this shared object and its DAG of needed objects will be
available for resolving undefined references only from other objects available for resolving undefined references only from other objects
in the same DAG. This is the default, but it may be specified in the same DAG. This is the default, but it may be specified
explicitly with this flag. explicitly with this flag.
.It Dv RTLD_TRACE
When set, causes dynamic linker to exit after loading all objects
needed by this shared object and printing a summary which includes
the absolute pathnames of all objects, to standard output.
With this flag
.Fn dlopen
will return to the caller only in the case of error.
.El .El
.Pp .Pp
If If

View File

@ -107,6 +107,7 @@ static void objlist_remove_unref(Objlist *);
static int relocate_objects(Obj_Entry *, bool); static int relocate_objects(Obj_Entry *, bool);
static void rtld_exit(void); static void rtld_exit(void);
static char *search_library_path(const char *, const char *); static char *search_library_path(const char *, const char *);
static const void **get_program_var_addr(const char *name);
static void set_program_var(const char *, const void *); static void set_program_var(const char *, const void *);
static const Elf_Sym *symlook_default(const char *, unsigned long hash, static const Elf_Sym *symlook_default(const char *, unsigned long hash,
const Obj_Entry *refobj, const Obj_Entry **defobj_out, bool in_plt); const Obj_Entry *refobj, const Obj_Entry **defobj_out, bool in_plt);
@ -1556,6 +1557,11 @@ dlopen(const char *name, int mode)
Obj_Entry **old_obj_tail; Obj_Entry **old_obj_tail;
Obj_Entry *obj; Obj_Entry *obj;
Objlist initlist; Objlist initlist;
int result;
ld_tracing = (mode & RTLD_TRACE) == 0 ? NULL : "1";
if (ld_tracing != NULL)
environ = (char **)*get_program_var_addr("environ");
objlist_init(&initlist); objlist_init(&initlist);
@ -1581,7 +1587,14 @@ dlopen(const char *name, int mode)
if (*old_obj_tail != NULL) { /* We loaded something new. */ if (*old_obj_tail != NULL) { /* We loaded something new. */
assert(*old_obj_tail == obj); assert(*old_obj_tail == obj);
if (load_needed_objects(obj) == -1 || result = load_needed_objects(obj);
if (result != -1 && ld_tracing) {
trace_loaded_objects(obj);
wlock_release();
exit(0);
}
if (result == -1 ||
(init_dag(obj), relocate_objects(obj, mode == RTLD_NOW)) == -1) { (init_dag(obj), relocate_objects(obj, mode == RTLD_NOW)) == -1) {
obj->dl_refcount--; obj->dl_refcount--;
unref_dag(obj); unref_dag(obj);
@ -1812,12 +1825,10 @@ r_debug_state(struct r_debug* rd, struct link_map *m)
} }
/* /*
* Set a pointer variable in the main program to the given value. This * Get address of the pointer variable in the main program.
* is used to set key variables such as "environ" before any of the
* init functions are called.
*/ */
static void static const void **
set_program_var(const char *name, const void *value) get_program_var_addr(const char *name)
{ {
const Obj_Entry *obj; const Obj_Entry *obj;
unsigned long hash; unsigned long hash;
@ -1830,11 +1841,26 @@ set_program_var(const char *name, const void *value)
const void **addr; const void **addr;
addr = (const void **)(obj->relocbase + def->st_value); addr = (const void **)(obj->relocbase + def->st_value);
dbg("\"%s\": *%p <-- %p", name, addr, value); return addr;
*addr = value;
break;
} }
} }
return NULL;
}
/*
* Set a pointer variable in the main program to the given value. This
* is used to set key variables such as "environ" before any of the
* init functions are called.
*/
static void
set_program_var(const char *name, const void *value)
{
const void **addr;
if ((addr = get_program_var_addr(name)) != NULL) {
dbg("\"%s\": *%p <-- %p", name, addr, value);
*addr = value;
}
} }
/* /*

View File

@ -13,7 +13,8 @@
.Ar program ... .Ar program ...
.Sh DESCRIPTION .Sh DESCRIPTION
.Nm .Nm
displays all shared objects that are needed to run the given program. displays all shared objects that are needed to run the given program or
to load the given shared object.
Contrary to Contrary to
.Xr nm 1 , .Xr nm 1 ,
the list includes the list includes

View File

@ -36,6 +36,7 @@ static const char rcsid[] =
#include <sys/wait.h> #include <sys/wait.h>
#include <machine/elf.h> #include <machine/elf.h>
#include <a.out.h> #include <a.out.h>
#include <dlfcn.h>
#include <err.h> #include <err.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
@ -116,6 +117,7 @@ char *argv[];
int n; int n;
int status; int status;
int file_ok; int file_ok;
int is_shlib;
if ((fd = open(*argv, O_RDONLY, 0)) < 0) { if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
warn("%s", *argv); warn("%s", *argv);
@ -130,6 +132,7 @@ char *argv[];
} }
file_ok = 1; file_ok = 1;
is_shlib = 0;
if (n >= sizeof hdr.aout && !N_BADMAG(hdr.aout)) { if (n >= sizeof hdr.aout && !N_BADMAG(hdr.aout)) {
/* a.out file */ /* a.out file */
if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC
@ -167,6 +170,8 @@ char *argv[];
if (!dynamic) { if (!dynamic) {
warnx("%s: not a dynamic executable", *argv); warnx("%s: not a dynamic executable", *argv);
file_ok = 0; file_ok = 0;
} else if (hdr.elf.e_type == ET_DYN) {
is_shlib = 1;
} }
} else { } else {
warnx("%s: not a dynamic executable", *argv); warnx("%s: not a dynamic executable", *argv);
@ -204,8 +209,13 @@ char *argv[];
} }
break; break;
case 0: case 0:
execl(*argv, *argv, (char *)NULL); if (is_shlib == 0) {
warn("%s", *argv); execl(*argv, *argv, (char *)NULL);
warn("%s", *argv);
} else {
dlopen(*argv, RTLD_TRACE);
warnx("%s: %s", *argv, dlerror());
}
_exit(1); _exit(1);
} }
} }