summaryrefslogtreecommitdiff
path: root/libexec/ld.so
diff options
context:
space:
mode:
Diffstat (limited to 'libexec/ld.so')
-rw-r--r--libexec/ld.so/dlfcn.c17
-rw-r--r--libexec/ld.so/ldconfig/prebind.c6
-rw-r--r--libexec/ld.so/library.c4
-rw-r--r--libexec/ld.so/library_mquery.c4
-rw-r--r--libexec/ld.so/library_subr.c4
-rw-r--r--libexec/ld.so/loader.c52
-rw-r--r--libexec/ld.so/resolve.c16
-rw-r--r--libexec/ld.so/resolve.h7
8 files changed, 82 insertions, 28 deletions
diff --git a/libexec/ld.so/dlfcn.c b/libexec/ld.so/dlfcn.c
index 6e3f1485208..5e8e11acdbf 100644
--- a/libexec/ld.so/dlfcn.c
+++ b/libexec/ld.so/dlfcn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dlfcn.c,v 1.84 2011/06/27 16:47:50 sthen Exp $ */
+/* $OpenBSD: dlfcn.c,v 1.85 2011/11/28 20:59:03 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -52,6 +52,12 @@ dlopen(const char *libname, int flags)
{
elf_object_t *object;
int failed = 0;
+ int obj_flags;
+
+ if (flags & ~(RTLD_TRACE|RTLD_LAZY|RTLD_NOW|RTLD_GLOBAL)) {
+ _dl_errno = DL_INVALID_MODE;
+ return NULL;
+ }
if (libname == NULL)
return RTLD_DEFAULT;
@@ -72,7 +78,9 @@ dlopen(const char *libname, int flags)
_dl_loading_object = NULL;
- object = _dl_load_shlib(libname, _dl_objects, OBJTYPE_DLO, flags);
+ obj_flags = (flags & RTLD_NOW ? DF_1_NOW : 0)
+ | (flags & RTLD_GLOBAL ? DF_1_GLOBAL : 0);
+ object = _dl_load_shlib(libname, _dl_objects, OBJTYPE_DLO, obj_flags);
if (object == 0) {
DL_DEB(("dlopen: failed to open %s\n", libname));
failed = 1;
@@ -96,7 +104,7 @@ dlopen(const char *libname, int flags)
DL_DEB(("head [%s]\n", object->load_name ));
- if ((failed = _dl_load_dep_libs(object, flags, 0)) == 1) {
+ if ((failed = _dl_load_dep_libs(object, obj_flags, 0)) == 1) {
_dl_real_close(object);
object = NULL;
_dl_errno = DL_CANT_LOAD_OBJ;
@@ -348,6 +356,9 @@ dlerror(void)
case DL_CANT_LOAD_OBJ:
errmsg = "Cannot load specified object";
break;
+ case DL_INVALID_MODE:
+ errmsg = "Invalid mode";
+ break;
default:
errmsg = "Unknown error";
}
diff --git a/libexec/ld.so/ldconfig/prebind.c b/libexec/ld.so/ldconfig/prebind.c
index 81a3f87effc..6badf720d5c 100644
--- a/libexec/ld.so/ldconfig/prebind.c
+++ b/libexec/ld.so/ldconfig/prebind.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: prebind.c,v 1.13 2011/04/06 11:36:25 miod Exp $ */
+/* $OpenBSD: prebind.c,v 1.14 2011/11/28 20:59:03 guenther Exp $ */
/*
* Copyright (c) 2006 Dale Rahn <drahn@dalerahn.com>
*
@@ -546,7 +546,9 @@ elf_load_object(void *pexe, const char *name)
if (dynp->d_tag == DT_SYMBOLIC)
object->dyn.symbolic = 1;
if (dynp->d_tag == DT_BIND_NOW)
- object->obj_flags = RTLD_NOW;
+ object->obj_flags |= DF_1_NOW;
+ if (dynp->d_tag == DT_FLAGS_1)
+ object->obj_flags |= dynp->d_un.d_val;
if (dynp->d_tag == DT_NEEDED)
needed_cnt++;
diff --git a/libexec/ld.so/library.c b/libexec/ld.so/library.c
index 9f6f7027240..e932382de6c 100644
--- a/libexec/ld.so/library.c
+++ b/libexec/ld.so/library.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library.c,v 1.62 2011/05/10 04:50:35 otto Exp $ */
+/* $OpenBSD: library.c,v 1.63 2011/11/28 20:59:03 guenther Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -107,7 +107,7 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
for (object = _dl_objects; object != NULL; object = object->next) {
if (object->dev == sb.st_dev &&
object->inode == sb.st_ino) {
- object->obj_flags |= flags & RTLD_GLOBAL;
+ object->obj_flags |= flags & DF_1_GLOBAL;
_dl_close(libfile);
if (_dl_loading_object == NULL)
_dl_loading_object = object;
diff --git a/libexec/ld.so/library_mquery.c b/libexec/ld.so/library_mquery.c
index fb5366b9e4e..6bf0920cf9b 100644
--- a/libexec/ld.so/library_mquery.c
+++ b/libexec/ld.so/library_mquery.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library_mquery.c,v 1.38 2010/11/16 18:59:00 drahn Exp $ */
+/* $OpenBSD: library_mquery.c,v 1.39 2011/11/28 20:59:03 guenther Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -113,7 +113,7 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
for (object = _dl_objects; object != NULL; object = object->next) {
if (object->dev == sb.st_dev &&
object->inode == sb.st_ino) {
- object->obj_flags |= flags & RTLD_GLOBAL;
+ object->obj_flags |= flags & DF_1_GLOBAL;
_dl_close(libfile);
if (_dl_loading_object == NULL)
_dl_loading_object = object;
diff --git a/libexec/ld.so/library_subr.c b/libexec/ld.so/library_subr.c
index 6b0ac4848a0..23243868803 100644
--- a/libexec/ld.so/library_subr.c
+++ b/libexec/ld.so/library_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library_subr.c,v 1.34 2011/07/13 20:49:44 drahn Exp $ */
+/* $OpenBSD: library_subr.c,v 1.35 2011/11/28 20:59:03 guenther Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -301,7 +301,7 @@ _dl_find_loaded_shlib(const char *req_name, struct sod req_sod, int flags)
}
if (object) { /* Already loaded */
- object->obj_flags |= flags & RTLD_GLOBAL;
+ object->obj_flags |= flags & DF_1_GLOBAL;
if (_dl_loading_object == NULL)
_dl_loading_object = object;
if (object->load_object != _dl_objects &&
diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c
index 3b40de37e50..a48dd495543 100644
--- a/libexec/ld.so/loader.c
+++ b/libexec/ld.so/loader.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: loader.c,v 1.125 2011/06/27 16:47:50 sthen Exp $ */
+/* $OpenBSD: loader.c,v 1.126 2011/11/28 20:59:03 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -59,6 +59,7 @@ void _dl_dtors(void);
void _dl_boot_bind(const long, long *, Elf_Dyn *);
void _dl_fixup_user_env(void);
void _dl_set_sod(const char *, struct sod *);
+void _dl_call_init_recurse(elf_object_t *object, int initfirst);
const char *_dl_progname;
int _dl_pagesz;
@@ -94,13 +95,17 @@ _dl_set_sod(const char *path, struct sod *sod)
*/
void
-_dl_run_all_dtors()
+_dl_run_all_dtors(void)
{
elf_object_t *node;
- int fini_complete;
struct dep_node *dnode;
+ int fini_complete;
+ int skip_initfirst;
+ int initfirst_skipped;
fini_complete = 0;
+ skip_initfirst = 1;
+ initfirst_skipped = 0;
while (fini_complete == 0) {
fini_complete = 1;
@@ -111,7 +116,11 @@ _dl_run_all_dtors()
(OBJECT_REF_CNT(node) == 0) &&
(node->status & STAT_INIT_DONE) &&
((node->status & STAT_FINI_DONE) == 0)) {
- node->status |= STAT_FINI_READY;
+ if (skip_initfirst &&
+ (node->obj_flags & DF_1_INITFIRST))
+ initfirst_skipped = 1;
+ else
+ node->status |= STAT_FINI_READY;
}
}
for (node = _dl_objects->next;
@@ -120,7 +129,9 @@ _dl_run_all_dtors()
if ((node->dyn.fini) &&
(OBJECT_REF_CNT(node) == 0) &&
(node->status & STAT_INIT_DONE) &&
- ((node->status & STAT_FINI_DONE) == 0))
+ ((node->status & STAT_FINI_DONE) == 0) &&
+ (!skip_initfirst ||
+ (node->obj_flags & DF_1_INITFIRST) == 0))
TAILQ_FOREACH(dnode, &node->child_list,
next_sib)
dnode->data->status &= ~STAT_FINI_READY;
@@ -141,6 +152,9 @@ _dl_run_all_dtors()
(*node->dyn.fini)();
}
}
+
+ if (fini_complete && initfirst_skipped)
+ fini_complete = initfirst_skipped = skip_initfirst = 0;
}
}
@@ -265,8 +279,8 @@ _dl_load_dep_libs(elf_object_t *object, int flags, int booting)
DL_DEB(("examining: '%s'\n", dynobj->load_name));
libcount = 0;
- /* propagate RTLD_NOW to deplibs (can be set by dynamic tags) */
- depflags = flags | (dynobj->obj_flags & RTLD_NOW);
+ /* propagate DF_1_NOW to deplibs (can be set by dynamic tags) */
+ depflags = flags | (dynobj->obj_flags & DF_1_NOW);
for (dynp = dynobj->load_dyn; dynp->d_tag; dynp++) {
if (dynp->d_tag == DT_NEEDED) {
@@ -476,7 +490,7 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
phdp++;
}
exe_obj->load_list = load_list;
- exe_obj->obj_flags |= RTLD_GLOBAL;
+ exe_obj->obj_flags |= DF_1_GLOBAL;
exe_obj->load_size = maxva - minva;
_dl_set_sod(exe_obj->load_name, &exe_obj->sod);
@@ -840,7 +854,7 @@ _dl_rtld(elf_object_t *object)
fails += _dl_md_reloc(object, DT_RELA, DT_RELASZ);
prebind_symcache(object, SYM_PLT);
fails += _dl_md_reloc_got(object, !(_dl_bindnow ||
- object->obj_flags & RTLD_NOW));
+ object->obj_flags & DF_1_NOW));
if (_dl_symcache != NULL) {
if (sz != 0)
@@ -852,27 +866,41 @@ _dl_rtld(elf_object_t *object)
return (fails);
}
+
void
_dl_call_init(elf_object_t *object)
{
+ _dl_call_init_recurse(object, 1);
+ _dl_call_init_recurse(object, 0);
+}
+
+void
+_dl_call_init_recurse(elf_object_t *object, int initfirst)
+{
struct dep_node *n;
+ object->status |= STAT_VISITED;
+
TAILQ_FOREACH(n, &object->child_list, next_sib) {
- if (n->data->status & STAT_INIT_DONE)
+ if (n->data->status & STAT_VISITED)
continue;
- _dl_call_init(n->data);
+ _dl_call_init_recurse(n->data, initfirst);
}
+ object->status &= ~STAT_VISITED;
+
if (object->status & STAT_INIT_DONE)
return;
+ if (initfirst && (object->obj_flags & DF_1_INITFIRST) == 0)
+ return;
+
if (object->dyn.init) {
DL_DEB(("doing ctors obj %p @%p: [%s]\n",
object, object->dyn.init, object->load_name));
(*object->dyn.init)();
}
- /* What about loops? */
object->status |= STAT_INIT_DONE;
}
diff --git a/libexec/ld.so/resolve.c b/libexec/ld.so/resolve.c
index ec9dd8296ee..58fcdc0bc98 100644
--- a/libexec/ld.so/resolve.c
+++ b/libexec/ld.so/resolve.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.c,v 1.56 2011/06/27 16:47:50 sthen Exp $ */
+/* $OpenBSD: resolve.c,v 1.57 2011/11/28 20:59:03 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -47,6 +47,13 @@ elf_object_t *_dl_loading_object;
void
_dl_add_object(elf_object_t *object)
{
+ /* if a .so is marked nodelete, then add a reference */
+ if (object->obj_flags & DF_1_NODELETE &&
+ (object->status & STAT_NODELETE) == 0) {
+ DL_DEB(("objname %s is nodelete\n", object->load_name));
+ object->refcount++;
+ object->status |= STAT_NODELETE;
+ }
/*
* if this is a new object, prev will be NULL
@@ -94,9 +101,12 @@ _dl_finalize_object(const char *objname, Elf_Dyn *dynp, Elf_Phdr *phdrp,
if (dynp->d_tag == DT_SYMBOLIC)
object->dyn.symbolic = 1;
if (dynp->d_tag == DT_BIND_NOW)
- object->obj_flags = RTLD_NOW;
+ object->obj_flags |= DF_1_NOW;
+ if (dynp->d_tag == DT_FLAGS_1)
+ object->obj_flags |= dynp->d_un.d_val;
dynp++;
}
+ DL_DEB((" flags %s = 0x%x\n", objname, object->obj_flags ));
/*
* Now relocate all pointer to dynamic info, but only
@@ -385,7 +395,7 @@ _dl_find_symbol(const char *name, const Elf_Sym **this,
* and and it's children
*/
TAILQ_FOREACH(n, &_dlopened_child_list, next_sib) {
- if (((n->data->obj_flags & RTLD_GLOBAL) == 0) &&
+ if (((n->data->obj_flags & DF_1_GLOBAL) == 0) &&
(n->data != req_obj->load_object))
continue;
diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h
index 5de93fa8f0e..d0f6bbd5b43 100644
--- a/libexec/ld.so/resolve.h
+++ b/libexec/ld.so/resolve.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.h,v 1.64 2011/06/27 16:47:50 sthen Exp $ */
+/* $OpenBSD: resolve.h,v 1.65 2011/11/28 20:59:03 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -105,6 +105,8 @@ struct elf_object {
#define STAT_FINI_DONE 0x08
#define STAT_FINI_READY 0x10
#define STAT_UNLOADED 0x20
+#define STAT_NODELETE 0x40
+#define STAT_VISITED 0x80
Elf_Phdr *phdrp;
int phdrc;
@@ -114,7 +116,7 @@ struct elf_object {
#define OBJTYPE_EXE 2
#define OBJTYPE_LIB 3
#define OBJTYPE_DLO 4
- int obj_flags;
+ int obj_flags; /* c.f. <sys/exec_elf.h> DF_1_* */
Elf_Word *buckets;
u_int32_t nbuckets;
@@ -262,6 +264,7 @@ extern char *_dl_debug;
#define DL_NO_OBJECT 9
#define DL_CANT_FIND_OBJ 10
#define DL_CANT_LOAD_OBJ 11
+#define DL_INVALID_MODE 12
#define ELF_ROUND(x,malign) (((x) + (malign)-1) & ~((malign)-1))
#define ELF_TRUNC(x,malign) ((x) & ~((malign)-1))