summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2010-07-01 19:25:45 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2010-07-01 19:25:45 +0000
commit5c18e9dfe10ac1d1ea0983ddea83330dd0d14041 (patch)
treeca2491ef38df06955329c0a88c1c1621792f4e1a
parent49984b2fd4aaec1b1f239db0b01cbc3fd1a66109 (diff)
When generating grpsym lists, avoid duplicates without searching the
already generated list. Speeds up startup on deeply nested dlopen binaries. ok guenther@, tested by ckuethe@ and ajacoutot@
-rw-r--r--libexec/ld.so/dlfcn.c4
-rw-r--r--libexec/ld.so/library_subr.c23
-rw-r--r--libexec/ld.so/loader.c8
-rw-r--r--libexec/ld.so/resolve.c27
-rw-r--r--libexec/ld.so/resolve.h13
5 files changed, 61 insertions, 14 deletions
diff --git a/libexec/ld.so/dlfcn.c b/libexec/ld.so/dlfcn.c
index f09b8b5603e..f975f61603e 100644
--- a/libexec/ld.so/dlfcn.c
+++ b/libexec/ld.so/dlfcn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dlfcn.c,v 1.81 2010/05/02 04:57:01 guenther Exp $ */
+/* $OpenBSD: dlfcn.c,v 1.82 2010/07/01 19:25:44 drahn Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -85,7 +85,7 @@ dlopen(const char *libname, int flags)
/* if opened but grpsym_list has not been created */
if (OBJECT_DLREF_CNT(object) == 1) {
/* add first object manually */
- _dl_link_grpsym(object);
+ _dl_link_grpsym(object, 1);
_dl_cache_grpsym_list(object);
}
goto loaded;
diff --git a/libexec/ld.so/library_subr.c b/libexec/ld.so/library_subr.c
index a1eb5fae752..852e5c12233 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.30 2010/05/09 09:53:28 matthieu Exp $ */
+/* $OpenBSD: library_subr.c,v 1.31 2010/07/01 19:25:44 drahn Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -448,13 +448,20 @@ _dl_link_child(elf_object_t *dep, elf_object_t *p)
}
void
-_dl_link_grpsym(elf_object_t *object)
+_dl_link_grpsym(elf_object_t *object, int checklist)
{
struct dep_node *n;
- TAILQ_FOREACH(n, &_dl_loading_object->grpsym_list, next_sib)
- if (n->data == object)
+ if (checklist) {
+ TAILQ_FOREACH(n, &_dl_loading_object->grpsym_list, next_sib)
+ if (n->data == object)
+ return; /* found, dont bother adding */
+ } else {
+ if (object->lastlookup == _dl_searchnum) {
return; /* found, dont bother adding */
+ }
+ }
+ object->lastlookup = _dl_searchnum;
n = _dl_malloc(sizeof *n);
if (n == NULL)
@@ -464,6 +471,12 @@ _dl_link_grpsym(elf_object_t *object)
}
void
+_dl_cache_grpsym_list_setup(elf_object_t *object)
+{
+ _dl_newsymsearch();
+ _dl_cache_grpsym_list(object);
+}
+void
_dl_cache_grpsym_list(elf_object_t *object)
{
struct dep_node *n;
@@ -475,7 +488,7 @@ _dl_cache_grpsym_list(elf_object_t *object)
*/
TAILQ_FOREACH(n, &object->child_list, next_sib)
- _dl_link_grpsym(n->data);
+ _dl_link_grpsym(n->data, 0);
TAILQ_FOREACH(n, &object->child_list, next_sib)
_dl_cache_grpsym_list(n->data);
diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c
index 1b577effa47..2fa77a8804a 100644
--- a/libexec/ld.so/loader.c
+++ b/libexec/ld.so/loader.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: loader.c,v 1.118 2010/01/02 12:16:35 kettenis Exp $ */
+/* $OpenBSD: loader.c,v 1.119 2010/07/01 19:25:44 drahn Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -337,8 +337,8 @@ _dl_load_dep_libs(elf_object_t *object, int flags, int booting)
}
/* add first object manually */
- _dl_link_grpsym(object);
- _dl_cache_grpsym_list(object);
+ _dl_link_grpsym(object, 1);
+ _dl_cache_grpsym_list_setup(object);
return(0);
}
@@ -498,7 +498,7 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
_dl_add_object(dyn_obj);
dyn_obj->refcount++;
- _dl_link_grpsym(dyn_obj);
+ _dl_link_grpsym(dyn_obj, 1);
dyn_obj->status |= STAT_RELOC_DONE;
diff --git a/libexec/ld.so/resolve.c b/libexec/ld.so/resolve.c
index 765a5b66c1c..ff516f6a3be 100644
--- a/libexec/ld.so/resolve.c
+++ b/libexec/ld.so/resolve.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.c,v 1.49 2008/05/05 02:29:02 kurt Exp $ */
+/* $OpenBSD: resolve.c,v 1.50 2010/07/01 19:25:44 drahn Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -159,6 +159,7 @@ _dl_finalize_object(const char *objname, Elf_Dyn *dynp, Elf_Phdr *phdrp,
/* default dev, inode for dlopen-able objects. */
object->dev = 0;
object->inode = 0;
+ object->lastlookup = 0;
TAILQ_INIT(&object->grpsym_list);
TAILQ_INIT(&object->grpref_list);
@@ -302,6 +303,26 @@ _dl_find_symbol_bysym(elf_object_t *req_obj, unsigned int symidx,
return ret;
}
+uint32_t _dl_searchnum = 0;
+void
+_dl_newsymsearch(void)
+{
+ _dl_searchnum += 1;
+
+ if (_dl_searchnum < 0) {
+ /* if the signed number roll over, reset
+ * all counters so we dont get accidental collision
+ */
+ elf_object_t *walkobj;
+ for (walkobj = _dl_objects;
+ walkobj != NULL;
+ walkobj = walkobj->next) {
+ walkobj->lastlookup = 0;
+ }
+ _dl_searchnum = 1;
+ }
+}
+
Elf_Addr
_dl_find_symbol(const char *name, const Elf_Sym **this,
int flags, const Elf_Sym *ref_sym, elf_object_t *req_obj,
@@ -368,6 +389,8 @@ _dl_find_symbol(const char *name, const Elf_Sym **this,
if ((flags & SYM_SEARCH_SELF) || (flags & SYM_SEARCH_NEXT))
skip = 1;
+ _dl_newsymsearch();
+
/*
* search dlopened objects: global or req_obj == dlopened_obj
* and and it's children
@@ -377,6 +400,7 @@ _dl_find_symbol(const char *name, const Elf_Sym **this,
(n->data != req_obj->load_object))
continue;
+ n->data->lastlookup_head = _dl_searchnum;
TAILQ_FOREACH(m, &n->data->grpsym_list, next_sib) {
if (skip == 1) {
if (m->data == req_obj) {
@@ -389,6 +413,7 @@ _dl_find_symbol(const char *name, const Elf_Sym **this,
if ((flags & SYM_SEARCH_OTHER) &&
(m->data == req_obj))
continue;
+ m->data->lastlookup = _dl_searchnum;
if (_dl_find_symbol_obj(m->data, name, h, flags,
this, &weak_sym, &weak_object)) {
object = m->data;
diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h
index feb11d5a584..b259941c722 100644
--- a/libexec/ld.so/resolve.h
+++ b/libexec/ld.so/resolve.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.h,v 1.59 2010/05/02 04:57:01 guenther Exp $ */
+/* $OpenBSD: resolve.h,v 1.60 2010/07/01 19:25:44 drahn Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -142,6 +142,10 @@ struct elf_object {
/* for object confirmation */
dev_t dev;
ino_t inode;
+
+ /* last symbol lookup on this object, to avoid mutiple searches */
+ int lastlookup_head;
+ int lastlookup;
};
struct dep_node {
@@ -201,8 +205,9 @@ int _dl_load_dep_libs(elf_object_t *object, int flags, int booting);
int _dl_rtld(elf_object_t *object);
void _dl_call_init(elf_object_t *object);
void _dl_link_child(elf_object_t *dep, elf_object_t *p);
-void _dl_link_grpsym(elf_object_t *object);
+void _dl_link_grpsym(elf_object_t *object, int checklist);
void _dl_cache_grpsym_list(elf_object_t *object);
+void _dl_cache_grpsym_list_setup(elf_object_t *object);
void _dl_link_grpref(elf_object_t *load_group, elf_object_t *load_object);
void _dl_link_dlopen(elf_object_t *dep);
void _dl_unlink_dlopen(elf_object_t *dep);
@@ -274,5 +279,9 @@ extern int _dl_symcachestat_lookups;
TAILQ_HEAD(dlochld, dep_node);
extern struct dlochld _dlopened_child_list;
+/* variables used to avoid duplicate node checking */
+uint32_t _dl_searchnum;
+uint32_t _dl_skipnum;
+void _dl_newsymsearch(void);
#endif /* _RESOLVE_H_ */