Module Name: src
Committed By: skrll
Date: Fri Dec 24 12:41:44 UTC 2010
Modified Files:
src/distrib/sets/lists/tests: mi
src/include: dlfcn.h
src/lib/libpthread: Makefile
src/libexec/ld.elf_so: headers.c load.c reloc.c rtld.c rtld.h search.c
src/share/man/man3: dlfcn.3
src/sys/sys: exec_elf.h
src/tests/libexec/ld.elf_so: Makefile
Added Files:
src/tests/libexec/ld.elf_so: h_df_1_noopen.c t_df_1_noopen.sh
Log Message:
Add support for DF_1_BIND_NOW, DF_1_NODELETE and DF_1_NOOPEN marked
objects, and the RTLD_NODELETE and RTLD_NOLOAD flags to dlopen(3).
Mark libpthread as DF_1_NOOPEN and use it to test the functionality.
Somewhat taken from FreeBSD.
Fixes PR 42029.
OK from christos and joerg.
To generate a diff of this commit:
cvs rdiff -u -r1.187 -r1.188 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.21 -r1.22 src/include/dlfcn.h
cvs rdiff -u -r1.70 -r1.71 src/lib/libpthread/Makefile
cvs rdiff -u -r1.37 -r1.38 src/libexec/ld.elf_so/headers.c
cvs rdiff -u -r1.41 -r1.42 src/libexec/ld.elf_so/load.c
cvs rdiff -u -r1.102 -r1.103 src/libexec/ld.elf_so/reloc.c
cvs rdiff -u -r1.136 -r1.137 src/libexec/ld.elf_so/rtld.c
cvs rdiff -u -r1.96 -r1.97 src/libexec/ld.elf_so/rtld.h
cvs rdiff -u -r1.22 -r1.23 src/libexec/ld.elf_so/search.c
cvs rdiff -u -r1.27 -r1.28 src/share/man/man3/dlfcn.3
cvs rdiff -u -r1.107 -r1.108 src/sys/sys/exec_elf.h
cvs rdiff -u -r1.2 -r1.3 src/tests/libexec/ld.elf_so/Makefile
cvs rdiff -u -r0 -r1.1 src/tests/libexec/ld.elf_so/h_df_1_noopen.c \
src/tests/libexec/ld.elf_so/t_df_1_noopen.sh
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.187 src/distrib/sets/lists/tests/mi:1.188
--- src/distrib/sets/lists/tests/mi:1.187 Thu Dec 23 15:27:44 2010
+++ src/distrib/sets/lists/tests/mi Fri Dec 24 12:41:42 2010
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.187 2010/12/23 15:27:44 pgoyette Exp $
+# $NetBSD: mi,v 1.188 2010/12/24 12:41:42 skrll Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@@ -387,6 +387,8 @@
./usr/libdata/debug/usr/tests/lib/libutil/t_sockaddr_snprintf.debug tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/libexec tests-lib-debug
./usr/libdata/debug/usr/tests/libexec/ld.elf_so tests-libexec-debug
+./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_df_1_noopen1.debug tests-libexec-debug debug,atf
+./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_df_1_noopen2.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-cleared.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-false.debug tests-libexec-debug debug,atf
./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlinfo.debug tests-libexec-debug debug,atf
@@ -1632,6 +1634,9 @@
./usr/tests/libexec/Atffile tests-lib-tests atf
./usr/tests/libexec/ld.elf_so tests-libexec-tests
./usr/tests/libexec/ld.elf_so/Atffile tests-libexec-tests atf
+./usr/tests/libexec/ld.elf_so/h_df_1_noopen1 tests-libexec-tests atf
+./usr/tests/libexec/ld.elf_so/h_df_1_noopen2 tests-libexec-tests atf
+./usr/tests/libexec/ld.elf_so/t_df_1_noopen tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/t_dlerror-cleared tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/t_dlerror-false tests-libexec-tests atf
./usr/tests/libexec/ld.elf_so/t_dlinfo tests-libexec-tests atf
Index: src/include/dlfcn.h
diff -u src/include/dlfcn.h:1.21 src/include/dlfcn.h:1.22
--- src/include/dlfcn.h:1.21 Thu Jan 7 07:35:35 2010
+++ src/include/dlfcn.h Fri Dec 24 12:41:42 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: dlfcn.h,v 1.21 2010/01/07 07:35:35 skrll Exp $ */
+/* $NetBSD: dlfcn.h,v 1.22 2010/12/24 12:41:42 skrll Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -64,6 +64,8 @@
#define RTLD_NOW 2
#define RTLD_GLOBAL 0x100 /* Allow global searches in object */
#define RTLD_LOCAL 0x200
+#define RTLD_NODELETE 0x01000 /* Do not remove members. */
+#define RTLD_NOLOAD 0x02000 /* Do not load if not already loaded. */
#if defined(_NETBSD_SOURCE)
#define DL_LAZY RTLD_LAZY /* Compat */
#endif
Index: src/lib/libpthread/Makefile
diff -u src/lib/libpthread/Makefile:1.70 src/lib/libpthread/Makefile:1.71
--- src/lib/libpthread/Makefile:1.70 Fri Aug 6 05:35:42 2010
+++ src/lib/libpthread/Makefile Fri Dec 24 12:41:42 2010
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.70 2010/08/06 05:35:42 christos Exp $
+# $NetBSD: Makefile,v 1.71 2010/12/24 12:41:42 skrll Exp $
#
WARNS= 4
@@ -33,6 +33,8 @@
LIB= pthread
+LDFLAGS+= -Wl,-znodlopen
+
#
# NOTE: When you create a new file for libpthread, make sure that pthread.c
# gets a reference to a symbol in that file. Otherwise, Unix's stupid static
Index: src/libexec/ld.elf_so/headers.c
diff -u src/libexec/ld.elf_so/headers.c:1.37 src/libexec/ld.elf_so/headers.c:1.38
--- src/libexec/ld.elf_so/headers.c:1.37 Sat Oct 16 17:48:12 2010
+++ src/libexec/ld.elf_so/headers.c Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: headers.c,v 1.37 2010/10/16 17:48:12 skrll Exp $ */
+/* $NetBSD: headers.c,v 1.38 2010/12/24 12:41:43 skrll Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: headers.c,v 1.37 2010/10/16 17:48:12 skrll Exp $");
+__RCSID("$NetBSD: headers.c,v 1.38 2010/12/24 12:41:43 skrll Exp $");
#endif /* not lint */
#include <err.h>
@@ -242,8 +242,14 @@
break;
#endif
case DT_FLAGS_1:
- obj->initfirst =
+ obj->z_now =
+ ((dynp->d_un.d_val & DF_1_BIND_NOW) != 0);
+ obj->z_nodelete =
+ ((dynp->d_un.d_val & DF_1_NODELETE) != 0);
+ obj->z_initfirst =
((dynp->d_un.d_val & DF_1_INITFIRST) != 0);
+ obj->z_noopen =
+ ((dynp->d_un.d_val & DF_1_NOOPEN) != 0);
break;
}
}
Index: src/libexec/ld.elf_so/load.c
diff -u src/libexec/ld.elf_so/load.c:1.41 src/libexec/ld.elf_so/load.c:1.42
--- src/libexec/ld.elf_so/load.c:1.41 Sun Dec 19 17:26:51 2010
+++ src/libexec/ld.elf_so/load.c Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: load.c,v 1.41 2010/12/19 17:26:51 skrll Exp $ */
+/* $NetBSD: load.c,v 1.42 2010/12/24 12:41:43 skrll Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: load.c,v 1.41 2010/12/19 17:26:51 skrll Exp $");
+__RCSID("$NetBSD: load.c,v 1.42 2010/12/24 12:41:43 skrll Exp $");
#endif /* not lint */
#include <err.h>
@@ -109,7 +109,7 @@
* on failure.
*/
Obj_Entry *
-_rtld_load_object(const char *filepath, int mode)
+_rtld_load_object(const char *filepath, int flags)
{
Obj_Entry *obj;
int fd = -1;
@@ -153,6 +153,18 @@
return NULL;
_rtld_digest_dynamic(filepath, obj);
+ if (flags & _RTLD_DLOPEN) {
+ if (obj->z_noopen || (flags & _RTLD_NOLOAD)) {
+ dbg(("refusing to load non-loadable \"%s\"",
+ obj->path));
+ _rtld_error("Cannot dlopen non-loadable %s",
+ obj->path);
+ munmap(obj->mapbase, obj->mapsize);
+ _rtld_obj_free(obj);
+ return OBJ_ERR;
+ }
+ }
+
*_rtld_objtail = obj;
_rtld_objtail = &obj->next;
_rtld_objcount++;
@@ -168,12 +180,12 @@
++obj->refcount;
#ifdef RTLD_LOADER
- if (mode & RTLD_MAIN && !obj->mainref) {
+ if (flags & _RTLD_MAIN && !obj->mainref) {
obj->mainref = 1;
dbg(("adding %p (%s) to _rtld_list_main", obj, obj->path));
_rtld_objlist_push_tail(&_rtld_list_main, obj);
}
- if (mode & RTLD_GLOBAL && !obj->globalref) {
+ if (flags & _RTLD_GLOBAL && !obj->globalref) {
obj->globalref = 1;
dbg(("adding %p (%s) to _rtld_list_global", obj, obj->path));
_rtld_objlist_push_tail(&_rtld_list_global, obj);
@@ -183,7 +195,8 @@
}
static bool
-_rtld_load_by_name(const char *name, Obj_Entry *obj, Needed_Entry **needed, int mode)
+_rtld_load_by_name(const char *name, Obj_Entry *obj, Needed_Entry **needed,
+ int flags)
{
Library_Xform *x = _rtld_xforms;
Obj_Entry *o = NULL;
@@ -240,7 +253,7 @@
for (j = 0; j < RTLD_MAX_LIBRARY &&
x->entry[i].library[j] != NULL; j++) {
o = _rtld_load_library(x->entry[i].library[j], obj,
- mode);
+ flags);
if (o == NULL) {
xwarnx("could not load %s for %s",
x->entry[i].library[j], name);
@@ -266,7 +279,7 @@
if (got)
return true;
- return ((*needed)->obj = _rtld_load_library(name, obj, mode)) != NULL;
+ return ((*needed)->obj = _rtld_load_library(name, obj, flags)) != NULL;
}
@@ -276,7 +289,7 @@
* returns -1 on failure.
*/
int
-_rtld_load_needed_objects(Obj_Entry *first, int mode)
+_rtld_load_needed_objects(Obj_Entry *first, int flags)
{
Obj_Entry *obj;
int status = 0;
@@ -287,11 +300,25 @@
for (needed = obj->needed; needed != NULL;
needed = needed->next) {
const char *name = obj->strtab + needed->name;
- if (!_rtld_load_by_name(name, obj, &needed, mode))
+#ifdef RTLD_LOADER
+ Obj_Entry *nobj;
+#endif
+ if (!_rtld_load_by_name(name, obj, &needed,
+ flags & ~_RTLD_NOLOAD))
status = -1; /* FIXME - cleanup */
#ifdef RTLD_LOADER
if (status == -1)
return status;
+
+ if (flags & _RTLD_MAIN)
+ continue;
+
+ nobj = needed->obj;
+ if (nobj->z_nodelete && !obj->ref_nodel) {
+ dbg(("obj %s nodelete", nobj->path));
+ _rtld_ref_dag(nobj);
+ nobj->ref_nodel = true;
+ }
#endif
}
}
@@ -310,7 +337,7 @@
if (preload_path != NULL && *preload_path != '\0') {
cp = buf = xstrdup(preload_path);
while ((path = strsep(&cp, " :")) != NULL && status == 0) {
- if (!_rtld_load_object(path, RTLD_MAIN))
+ if (!_rtld_load_object(path, _RTLD_MAIN))
status = -1;
else
dbg((" preloaded \"%s\"", path));
Index: src/libexec/ld.elf_so/reloc.c
diff -u src/libexec/ld.elf_so/reloc.c:1.102 src/libexec/ld.elf_so/reloc.c:1.103
--- src/libexec/ld.elf_so/reloc.c:1.102 Mon Apr 5 14:01:26 2010
+++ src/libexec/ld.elf_so/reloc.c Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: reloc.c,v 1.102 2010/04/05 14:01:26 joerg Exp $ */
+/* $NetBSD: reloc.c,v 1.103 2010/12/24 12:41:43 skrll Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -39,7 +39,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: reloc.c,v 1.102 2010/04/05 14:01:26 joerg Exp $");
+__RCSID("$NetBSD: reloc.c,v 1.103 2010/12/24 12:41:43 skrll Exp $");
#endif /* not lint */
#include <err.h>
@@ -195,7 +195,7 @@
#if defined(__hppa__)
bind_now = 1;
#endif
- if (bind_now) {
+ if (obj->z_now || bind_now) {
dbg(("doing immediate PLT binding"));
if (_rtld_relocate_plt_objects(obj) < 0)
ok = 0;
Index: src/libexec/ld.elf_so/rtld.c
diff -u src/libexec/ld.elf_so/rtld.c:1.136 src/libexec/ld.elf_so/rtld.c:1.137
--- src/libexec/ld.elf_so/rtld.c:1.136 Sun Dec 19 17:26:51 2010
+++ src/libexec/ld.elf_so/rtld.c Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.c,v 1.136 2010/12/19 17:26:51 skrll Exp $ */
+/* $NetBSD: rtld.c,v 1.137 2010/12/24 12:41:43 skrll Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: rtld.c,v 1.136 2010/12/19 17:26:51 skrll Exp $");
+__RCSID("$NetBSD: rtld.c,v 1.137 2010/12/24 12:41:43 skrll Exp $");
#endif /* not lint */
#include <err.h>
@@ -147,7 +147,7 @@
if (obj->refcount > 0 && !force) {
continue;
}
- if (obj->fini == NULL || obj->fini_called || obj->initfirst) {
+ if (obj->fini == NULL || obj->fini_called || obj->z_initfirst) {
continue;
}
dbg (("calling fini function %s at %p", obj->path,
@@ -188,7 +188,7 @@
/* First pass: objects marked with DF_1_INITFIRST. */
SIMPLEQ_FOREACH(elm, &initlist, link) {
obj = elm->obj;
- if (obj->init == NULL || obj->init_called || !obj->initfirst) {
+ if (obj->init == NULL || obj->init_called || !obj->z_initfirst) {
continue;
}
dbg (("calling init function %s at %p (DF_1_INITFIRST)",
@@ -568,7 +568,7 @@
}
dbg(("loading needed objects"));
- if (_rtld_load_needed_objects(_rtld_objmain, RTLD_MAIN) == -1)
+ if (_rtld_load_needed_objects(_rtld_objmain, _RTLD_MAIN) == -1)
_rtld_die();
dbg(("relocating objects"));
@@ -760,13 +760,35 @@
}
}
+void
+_rtld_ref_dag(Obj_Entry *root)
+{
+ const Needed_Entry *needed;
+
+ assert(root);
+
+ ++root->refcount;
+
+ dbg(("incremented reference on \"%s\" (%d)", root->path,
+ root->refcount));
+ for (needed = root->needed; needed != NULL;
+ needed = needed->next) {
+ if (needed->obj != NULL)
+ _rtld_ref_dag(needed->obj);
+ }
+}
+
static void
_rtld_unref_dag(Obj_Entry *root)
{
assert(root);
assert(root->refcount != 0);
+
--root->refcount;
+ dbg(("decremented reference on \"%s\" (%d)", root->path,
+ root->refcount));
+
if (root->refcount == 0) {
const Needed_Entry *needed;
@@ -815,6 +837,15 @@
{
Obj_Entry **old_obj_tail = _rtld_objtail;
Obj_Entry *obj = NULL;
+ int flags = _RTLD_DLOPEN;
+ bool nodelete;
+ bool now;
+
+ flags |= (mode & RTLD_GLOBAL) ? _RTLD_GLOBAL : 0;
+ flags |= (mode & RTLD_NOLOAD) ? _RTLD_NOLOAD : 0;
+
+ nodelete = (mode & RTLD_NODELETE) ? true : false;
+ now = ((mode & RTLD_MODEMASK) == RTLD_NOW) ? true : false;
_rtld_debug.r_state = RT_ADD;
_rtld_debug_state();
@@ -823,17 +854,18 @@
obj = _rtld_objmain;
obj->refcount++;
} else
- obj = _rtld_load_library(name, _rtld_objmain, mode);
+ obj = _rtld_load_library(name, _rtld_objmain, flags);
+
if (obj != NULL) {
++obj->dl_refcount;
if (*old_obj_tail != NULL) { /* We loaded something new. */
assert(*old_obj_tail == obj);
- if (_rtld_load_needed_objects(obj, mode) == -1 ||
+ if (_rtld_load_needed_objects(obj, flags) == -1 ||
(_rtld_init_dag(obj),
_rtld_relocate_objects(obj,
- ((mode & 3) == RTLD_NOW))) == -1) {
+ (now || obj->z_now))) == -1) {
_rtld_unload_object(obj, false);
obj->dl_refcount--;
obj = NULL;
@@ -841,6 +873,13 @@
_rtld_call_init_functions();
}
}
+ if (obj != NULL) {
+ if ((nodelete || obj->z_nodelete) && !obj->ref_nodel) {
+ dbg(("dlopen obj %s nodelete", obj->path));
+ _rtld_ref_dag(obj);
+ obj->z_nodelete = obj->ref_nodel = true;
+ }
+ }
}
_rtld_debug.r_state = RT_CONSISTENT;
_rtld_debug_state();
Index: src/libexec/ld.elf_so/rtld.h
diff -u src/libexec/ld.elf_so/rtld.h:1.96 src/libexec/ld.elf_so/rtld.h:1.97
--- src/libexec/ld.elf_so/rtld.h:1.96 Sun Dec 5 00:56:06 2010
+++ src/libexec/ld.elf_so/rtld.h Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.h,v 1.96 2010/12/05 00:56:06 joerg Exp $ */
+/* $NetBSD: rtld.h,v 1.97 2010/12/24 12:41:43 skrll Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -128,7 +128,6 @@
#define RTLD_MAGIC 0xd550b87a
#define RTLD_VERSION 1
-#define RTLD_MAIN 0x800
typedef struct Struct_Obj_Entry {
Elf32_Word magic; /* Magic number (sanity check) */
@@ -202,10 +201,17 @@
* called */
fini_called:1, /* True if .fini function has been
* called */
- initfirst:1, /* True if object's .init/.fini take
+ z_now:1, /* True if object's symbols should be
+ bound immediately */
+ z_nodelete:1, /* True if object should never be
+ unloaded */
+ z_initfirst:1, /* True if object's .init/.fini take
* priority over others */
- phdr_loaded:1; /* Phdr is loaded and doesn't need to
+ z_noopen:1, /* True if object should never be
+ dlopen'ed */
+ phdr_loaded:1, /* Phdr is loaded and doesn't need to
* be freed. */
+ ref_nodel:1; /* Refcount increased to prevent dlclose */
struct link_map linkmap; /* for GDB */
@@ -251,6 +257,14 @@
extern Objlist _rtld_list_main;
extern Elf_Sym _rtld_sym_zero;
+#define RTLD_MODEMASK 0x3
+
+/* Flags for _rtld_load_object() and friends. */
+#define _RTLD_GLOBAL 0x01 /* Add object to global DAG. */
+#define _RTLD_MAIN 0x02
+#define _RTLD_NOLOAD 0x04 /* dlopen() specified RTLD_NOLOAD. */
+#define _RTLD_DLOPEN 0x08 /* Load_object() called from dlopen(). */
+
/* rtld.c */
/* We export these symbols using _rtld_symbol_lookup and is_exported. */
@@ -274,6 +288,7 @@
void _rtld_objlist_push_head(Objlist *, Obj_Entry *);
void _rtld_objlist_push_tail(Objlist *, Obj_Entry *);
Objlist_Entry *_rtld_objlist_find(Objlist *, const Obj_Entry *);
+void _rtld_ref_dag(Obj_Entry *);
/* expand.c */
size_t _rtld_expand_path(char *, size_t, const char *, const char *,\
@@ -288,6 +303,7 @@
int _rtld_load_needed_objects(Obj_Entry *, int);
int _rtld_preload(const char *);
+#define OBJ_ERR (Obj_Entry *)(-1)
/* path.c */
void _rtld_add_paths(const char *, Search_Path **, const char *);
void _rtld_process_hints(const char *, Search_Path **, Library_Xform **,
Index: src/libexec/ld.elf_so/search.c
diff -u src/libexec/ld.elf_so/search.c:1.22 src/libexec/ld.elf_so/search.c:1.23
--- src/libexec/ld.elf_so/search.c:1.22 Sat Aug 7 19:47:34 2010
+++ src/libexec/ld.elf_so/search.c Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: search.c,v 1.22 2010/08/07 19:47:34 joerg Exp $ */
+/* $NetBSD: search.c,v 1.23 2010/12/24 12:41:43 skrll Exp $ */
/*
* Copyright 1996 Matt Thomas <[email protected]>
@@ -38,7 +38,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: search.c,v 1.22 2010/08/07 19:47:34 joerg Exp $");
+__RCSID("$NetBSD: search.c,v 1.23 2010/12/24 12:41:43 skrll Exp $");
#endif /* not lint */
#include <err.h>
@@ -67,7 +67,7 @@
static Obj_Entry *
_rtld_search_library_path(const char *name, size_t namelen,
- const char *dir, size_t dirlen, int mode)
+ const char *dir, size_t dirlen, int flags)
{
char pathname[MAXPATHLEN];
size_t pathnamelen;
@@ -93,7 +93,7 @@
pathname[pathnamelen] = '\0';
dbg((" Trying \"%s\"", pathname));
- obj = _rtld_load_object(pathname, mode);
+ obj = _rtld_load_object(pathname, flags);
if (obj == NULL) {
Search_Path *path;
@@ -115,7 +115,7 @@
* loaded shared object, whose library search path will be searched.
*/
Obj_Entry *
-_rtld_load_library(const char *name, const Obj_Entry *refobj, int mode)
+_rtld_load_library(const char *name, const Obj_Entry *refobj, int flags)
{
char tmperror[512], *tmperrorp;
Search_Path *sp;
@@ -145,18 +145,18 @@
for (sp = _rtld_paths; sp != NULL; sp = sp->sp_next)
if ((obj = _rtld_search_library_path(name, namelen,
- sp->sp_path, sp->sp_pathlen, mode)) != NULL)
+ sp->sp_path, sp->sp_pathlen, flags)) != NULL)
goto pathfound;
if (refobj != NULL)
for (sp = refobj->rpaths; sp != NULL; sp = sp->sp_next)
if ((obj = _rtld_search_library_path(name,
- namelen, sp->sp_path, sp->sp_pathlen, mode)) != NULL)
+ namelen, sp->sp_path, sp->sp_pathlen, flags)) != NULL)
goto pathfound;
for (sp = _rtld_default_paths; sp != NULL; sp = sp->sp_next)
if ((obj = _rtld_search_library_path(name, namelen,
- sp->sp_path, sp->sp_pathlen, mode)) != NULL)
+ sp->sp_path, sp->sp_pathlen, flags)) != NULL)
goto pathfound;
_rtld_error("Shared object \"%s\" not found", name);
@@ -164,6 +164,12 @@
pathfound:
/*
+ * The library has been found, but it couldn't be loaded for some
+ * reason.
+ */
+ if (obj == OBJ_ERR)
+ return NULL;
+ /*
* Successfully found a library; restore the dlerror state as it was
* before _rtld_load_library() was called (any failed call to
* _rtld_search_library_path() will set the dlerror state, but if the
@@ -177,5 +183,10 @@
return obj;
found:
- return _rtld_load_object(pathname, mode);
+ obj = _rtld_load_object(pathname, flags);
+ if (obj == OBJ_ERR)
+ return NULL;
+
+ return obj;
}
+
Index: src/share/man/man3/dlfcn.3
diff -u src/share/man/man3/dlfcn.3:1.27 src/share/man/man3/dlfcn.3:1.28
--- src/share/man/man3/dlfcn.3:1.27 Sun Jan 24 22:54:14 2010
+++ src/share/man/man3/dlfcn.3 Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-.\" $NetBSD: dlfcn.3,v 1.27 2010/01/24 22:54:14 wiz Exp $
+.\" $NetBSD: dlfcn.3,v 1.28 2010/12/24 12:41:43 skrll Exp $
.\"
.\" Copyright (c) 1998 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -65,24 +65,29 @@
The
.Fn dlopen
function takes the name of a shared object as the first argument.
-The shared object is mapped into the address space, relocated, and
-its external references are resolved in the same way as is done
-with the implicitly loaded shared libraries at program startup.
-.Pp
The
.Fa path
argument can be specified as either an absolute pathname to a shared object
or just the name of the shared object itself.
When an absolute pathname is specified,
only the path provided will be searched.
-When just a shared object name is specified, the same search rules apply that are
-used for
+When just a shared object name is specified, the same search rules apply that
+are used for
.Dq intrinsic
shared object searches.
+.Po
+see
+.Xr ld.elf_so 5
+.Pc
.Pp
Shared libraries take the following form:
.Do lib Ns Ao name Ac Ns .so Ns Oo .xx Ns Oo .yy Oc Oc Dc .
.Pp
+The shared object is mapped into the address space, relocated, and
+its external references are resolved in the same way as is done
+with the implicitly loaded shared libraries at program startup.
+.Pp
+The
If the first argument is
.Dv NULL ,
.Fn dlopen
@@ -97,7 +102,7 @@
.Fa mode
parameter specifies symbol resolution time and symbol visibility.
One of the following values may be used to specify symbol resolution time:
-.Bl -tag -width "RTLD_LAZYXX" -offset indent
+.Bl -tag -width "RTLD_GLOBALXX" -offset indent
.It Dv RTLD_NOW
Symbols are resolved immediately.
.It Dv RTLD_LAZY
@@ -107,7 +112,7 @@
.Pp
One of the following values may be used to specify symbol visibility:
.Pp
-.Bl -tag -width "RTLD_GLOBAL" -compact -offset indent
+.Bl -tag -width "RTLD_GLOBALXX" -offset indent
.It Dv RTLD_GLOBAL
The object's symbols and the symbols of its dependencies will be visible to
other objects.
@@ -126,6 +131,23 @@
then it is promoted to
.Dv RTLD_GLOBAL .
.Pp
+Additionally, one of the following flags may be ORed into the
+.Fa mode
+argument:
+.Bl -tag -width "RTLD_NODELETEXX" -offset indent
+.It Dv RTLD_NODELETE
+Prevents unload of the loaded object on
+.Fn dlclose .
+The same behaviour may be requested by
+.Fl "z nodelete"
+option of the static linker
+.Xr ld 1 .
+.It Dv RTLD_NOLOAD
+Only return valid handle for the object if it is already loaded in
+the process address space, otherwise do not load the object and return
+.Dv NULL .
+.El
+.Pp
.Fn dlopen
returns a
.Fa handle
@@ -192,13 +214,13 @@
dependencies without calling
.Fn dlopen .
.It Dv RTLD_DEFAULT
-All the visible shared objects and the executable will be searched in the order they
-were loaded.
+All the visible shared objects and the executable will be searched in the order
+they were loaded.
.It Dv RTLD_NEXT
The search for
.Fa symbol
-is limited to the visible shared objects which were loaded after the one issuing the
-call to
+is limited to the visible shared objects which were loaded after the one
+issuing the call to
.Fn dlsym .
Thus, if
.Fn dlsym
Index: src/sys/sys/exec_elf.h
diff -u src/sys/sys/exec_elf.h:1.107 src/sys/sys/exec_elf.h:1.108
--- src/sys/sys/exec_elf.h:1.107 Mon Dec 13 19:37:32 2010
+++ src/sys/sys/exec_elf.h Fri Dec 24 12:41:43 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: exec_elf.h,v 1.107 2010/12/13 19:37:32 joerg Exp $ */
+/* $NetBSD: exec_elf.h,v 1.108 2010/12/24 12:41:43 skrll Exp $ */
/*-
* Copyright (c) 1994 The NetBSD Foundation, Inc.
@@ -668,7 +668,10 @@
#define DT_HIPROC 0x7fffffff
/* Flag values for DT_FLAGS_1 (incomplete) */
+#define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */
+#define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */
#define DF_1_INITFIRST 0x00000020 /* Object's init/fini take priority */
+#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */
/*
* Auxiliary Vectors
Index: src/tests/libexec/ld.elf_so/Makefile
diff -u src/tests/libexec/ld.elf_so/Makefile:1.2 src/tests/libexec/ld.elf_so/Makefile:1.3
--- src/tests/libexec/ld.elf_so/Makefile:1.2 Tue Dec 14 05:57:32 2010
+++ src/tests/libexec/ld.elf_so/Makefile Fri Dec 24 12:41:43 2010
@@ -1,6 +1,8 @@
# $NetBSD
#
+NOMAN= # defined
+
.include <bsd.own.mk>
TESTSDIR= ${TESTSBASE}/libexec/ld.elf_so
@@ -9,4 +11,14 @@
LDADD.t_dlerror-false= -Wl,-rpath,/var/nonexistent/lib
+TESTS_SH+= t_df_1_noopen
+
+BINDIR= ${TESTSDIR}
+PROGS+= h_df_1_noopen1
+SRCS.h_df_1_noopen1= h_df_1_noopen.c
+
+PROGS+= h_df_1_noopen2
+SRCS.h_df_1_noopen2= h_df_1_noopen.c
+LDADD.h_df_1_noopen2= -lpthread
+
.include <bsd.test.mk>
Added files:
Index: src/tests/libexec/ld.elf_so/h_df_1_noopen.c
diff -u /dev/null src/tests/libexec/ld.elf_so/h_df_1_noopen.c:1.1
--- /dev/null Fri Dec 24 12:41:44 2010
+++ src/tests/libexec/ld.elf_so/h_df_1_noopen.c Fri Dec 24 12:41:43 2010
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <dlfcn.h>
+#include <err.h>
+#include <unistd.h>
+
+int
+main(void)
+{
+ void *handle;
+
+ handle = dlopen("libpthread.so", RTLD_NOLOAD);
+ if (handle == NULL)
+ errx(1, dlerror());
+
+ printf("libpthread loaded successfully\n");
+ return 0;
+}
Index: src/tests/libexec/ld.elf_so/t_df_1_noopen.sh
diff -u /dev/null src/tests/libexec/ld.elf_so/t_df_1_noopen.sh:1.1
--- /dev/null Fri Dec 24 12:41:44 2010
+++ src/tests/libexec/ld.elf_so/t_df_1_noopen.sh Fri Dec 24 12:41:43 2010
@@ -0,0 +1,64 @@
+# $NetBSD: t_df_1_noopen.sh,v 1.1 2010/12/24 12:41:43 skrll Exp $
+#
+# Copyright (c) 2010 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# This code is derived from software contributed to The NetBSD Foundation
+# by
+#
+# 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.
+#
+
+atf_test_case df_1_noopen1
+df_1_noopen1_head()
+{
+ atf_set "descr" "Checks DF_1_NOOPEN prevents dlopening of library"
+}
+df_1_noopen1_body()
+{
+ cat >expout <<EOF
+h_df_1_noopen1: Cannot dlopen non-loadable /usr/lib/libpthread.so
+EOF
+
+ atf_check -o file:expout "$(atf_get_srcdir)/h_df_1_noopen1"
+ atf_expect_exit 1 "libpthread is marked DF_1_NOOPEN"
+}
+
+atf_test_case df_1_noopen2
+df_1_noopen2_head()
+{
+ atf_set "descr" "Checks DF_1_NOOPEN is allowed on already loaded library"
+}
+df_1_noopen2_body()
+{
+ cat >expout <<EOF
+libpthread loaded successfully
+EOF
+
+ atf_check -o file:expout "$(atf_get_srcdir)/h_df_1_noopen2"
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case df_1_noopen1
+ atf_add_test_case df_1_noopen2
+}