Skip to content

Commit

Permalink
Allow ldd(1) be used on shared libraries in addition to executables.
Browse files Browse the repository at this point in the history
  • Loading branch information
sobomax authored and sobomax committed Feb 4, 2002
1 parent c61b721 commit 0a68f50
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 12 deletions.
1 change: 1 addition & 0 deletions include/dlfcn.h
Original file line number Diff line number Diff line change
Expand Up @@ -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().
Expand Down
7 changes: 7 additions & 0 deletions lib/libc/gen/dlopen.3
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
44 changes: 35 additions & 9 deletions libexec/rtld-elf/rtld.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
}

/*
Expand Down
3 changes: 2 additions & 1 deletion usr.bin/ldd/ldd.1
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 12 additions & 2 deletions usr.bin/ldd/ldd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}
Expand Down

0 comments on commit 0a68f50

Please sign in to comment.