Allow ldd(1) be used on shared libraries in addition to executables.
This commit is contained in:
parent
fc41545e4e
commit
c6de4ce791
@ -45,6 +45,7 @@
|
||||
#define RTLD_MODEMASK 0x3
|
||||
#define RTLD_GLOBAL 0x100 /* Make symbols globally available */
|
||||
#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().
|
||||
|
@ -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
|
||||
in the same DAG. This is the default, but it may be specified
|
||||
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
|
||||
.Pp
|
||||
If
|
||||
|
@ -107,6 +107,7 @@ static void objlist_remove_unref(Objlist *);
|
||||
static int relocate_objects(Obj_Entry *, bool);
|
||||
static void rtld_exit(void);
|
||||
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 const Elf_Sym *symlook_default(const char *, unsigned long hash,
|
||||
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 *obj;
|
||||
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);
|
||||
|
||||
@ -1581,7 +1587,14 @@ dlopen(const char *name, int mode)
|
||||
if (*old_obj_tail != NULL) { /* We loaded something new. */
|
||||
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) {
|
||||
obj->dl_refcount--;
|
||||
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
|
||||
* is used to set key variables such as "environ" before any of the
|
||||
* init functions are called.
|
||||
* Get address of the pointer variable in the main program.
|
||||
*/
|
||||
static void
|
||||
set_program_var(const char *name, const void *value)
|
||||
static const void **
|
||||
get_program_var_addr(const char *name)
|
||||
{
|
||||
const Obj_Entry *obj;
|
||||
unsigned long hash;
|
||||
@ -1830,11 +1841,26 @@ set_program_var(const char *name, const void *value)
|
||||
const void **addr;
|
||||
|
||||
addr = (const void **)(obj->relocbase + def->st_value);
|
||||
dbg("\"%s\": *%p <-- %p", name, addr, value);
|
||||
*addr = value;
|
||||
break;
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -13,7 +13,8 @@
|
||||
.Ar program ...
|
||||
.Sh DESCRIPTION
|
||||
.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
|
||||
.Xr nm 1 ,
|
||||
the list includes
|
||||
|
@ -36,6 +36,7 @@ static const char rcsid[] =
|
||||
#include <sys/wait.h>
|
||||
#include <machine/elf.h>
|
||||
#include <a.out.h>
|
||||
#include <dlfcn.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
@ -116,6 +117,7 @@ char *argv[];
|
||||
int n;
|
||||
int status;
|
||||
int file_ok;
|
||||
int is_shlib;
|
||||
|
||||
if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
|
||||
warn("%s", *argv);
|
||||
@ -130,6 +132,7 @@ char *argv[];
|
||||
}
|
||||
|
||||
file_ok = 1;
|
||||
is_shlib = 0;
|
||||
if (n >= sizeof hdr.aout && !N_BADMAG(hdr.aout)) {
|
||||
/* a.out file */
|
||||
if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC
|
||||
@ -167,6 +170,8 @@ char *argv[];
|
||||
if (!dynamic) {
|
||||
warnx("%s: not a dynamic executable", *argv);
|
||||
file_ok = 0;
|
||||
} else if (hdr.elf.e_type == ET_DYN) {
|
||||
is_shlib = 1;
|
||||
}
|
||||
} else {
|
||||
warnx("%s: not a dynamic executable", *argv);
|
||||
@ -204,8 +209,13 @@ char *argv[];
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
execl(*argv, *argv, (char *)NULL);
|
||||
warn("%s", *argv);
|
||||
if (is_shlib == 0) {
|
||||
execl(*argv, *argv, (char *)NULL);
|
||||
warn("%s", *argv);
|
||||
} else {
|
||||
dlopen(*argv, RTLD_TRACE);
|
||||
warnx("%s: %s", *argv, dlerror());
|
||||
}
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user