Implement RTLD_NOLOAD flag for dlopen(3).

Requested and tested by:	jkim
Reviewed by:	kan
Approved by:	re (kensmith)
This commit is contained in:
Konstantin Belousov 2009-07-17 19:45:42 +00:00
parent 874bb76647
commit 49e8c06b45
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=195745
3 changed files with 19 additions and 7 deletions

View File

@ -48,6 +48,7 @@
#define RTLD_LOCAL 0 /* Opposite of RTLD_GLOBAL, and the default. */
#define RTLD_TRACE 0x200 /* Trace loaded objects and exit. */
#define RTLD_NODELETE 0x01000 /* Do not remove members. */
#define RTLD_NOLOAD 0x02000 /* Do not load if not already loaded. */
/*
* Request arguments for dlinfo().

View File

@ -32,7 +32,7 @@
.\" @(#) dlopen.3 1.6 90/01/31 SMI
.\" $FreeBSD$
.\"
.Dd April 1, 2009
.Dd July 7, 2009
.Os
.Dt DLOPEN 3
.Sh NAME
@ -148,6 +148,13 @@ The same behaviour may be requested by
.Fl "z nodelete"
option of the static linker
.Xr ld 1 .
.It Dv RTLD_NOLOAD
Ony return valid handle for the object if it is already loaded in
the process address space, otherwise
.Dv NULL
is returned.
Other mode flags may be specified, which will be applied for promotion
for the found object.
.El
.Pp
If

View File

@ -105,7 +105,7 @@ static void linkmap_add(Obj_Entry *);
static void linkmap_delete(Obj_Entry *);
static int load_needed_objects(Obj_Entry *);
static int load_preload_objects(void);
static Obj_Entry *load_object(const char *, const Obj_Entry *);
static Obj_Entry *load_object(const char *, const Obj_Entry *, int);
static Obj_Entry *obj_from_addr(const void *);
static void objlist_call_fini(Objlist *, bool, int *);
static void objlist_call_init(Objlist *, int *);
@ -1432,7 +1432,8 @@ load_needed_objects(Obj_Entry *first)
Needed_Entry *needed;
for (needed = obj->needed; needed != NULL; needed = needed->next) {
obj1 = needed->obj = load_object(obj->strtab + needed->name, obj);
obj1 = needed->obj = load_object(obj->strtab + needed->name, obj,
false);
if (obj1 == NULL && !ld_tracing)
return -1;
if (obj1 != NULL && obj1->z_nodelete && !obj1->ref_nodel) {
@ -1463,7 +1464,7 @@ load_preload_objects(void)
savech = p[len];
p[len] = '\0';
if (load_object(p, NULL) == NULL)
if (load_object(p, NULL, false) == NULL)
return -1; /* XXX - cleanup */
p[len] = savech;
p += len;
@ -1480,7 +1481,7 @@ load_preload_objects(void)
* on failure.
*/
static Obj_Entry *
load_object(const char *name, const Obj_Entry *refobj)
load_object(const char *name, const Obj_Entry *refobj, int noload)
{
Obj_Entry *obj;
int fd = -1;
@ -1526,6 +1527,8 @@ load_object(const char *name, const Obj_Entry *refobj)
close(fd);
return obj;
}
if (noload)
return (NULL);
/* First use of this object, so we must map it in */
obj = do_load_object(fd, name, path, &sb);
@ -1982,13 +1985,14 @@ dlopen(const char *name, int mode)
Obj_Entry **old_obj_tail;
Obj_Entry *obj;
Objlist initlist;
int result, lockstate, nodelete;
int result, lockstate, nodelete, noload;
LD_UTRACE(UTRACE_DLOPEN_START, NULL, NULL, 0, mode, name);
ld_tracing = (mode & RTLD_TRACE) == 0 ? NULL : "1";
if (ld_tracing != NULL)
environ = (char **)*get_program_var_addr("environ");
nodelete = mode & RTLD_NODELETE;
noload = mode & RTLD_NOLOAD;
objlist_init(&initlist);
@ -2001,7 +2005,7 @@ dlopen(const char *name, int mode)
obj = obj_main;
obj->refcount++;
} else {
obj = load_object(name, obj_main);
obj = load_object(name, obj_main, noload);
}
if (obj) {