diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2010-07-01 19:25:45 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2010-07-01 19:25:45 +0000 |
commit | 5c18e9dfe10ac1d1ea0983ddea83330dd0d14041 (patch) | |
tree | ca2491ef38df06955329c0a88c1c1621792f4e1a | |
parent | 49984b2fd4aaec1b1f239db0b01cbc3fd1a66109 (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.c | 4 | ||||
-rw-r--r-- | libexec/ld.so/library_subr.c | 23 | ||||
-rw-r--r-- | libexec/ld.so/loader.c | 8 | ||||
-rw-r--r-- | libexec/ld.so/resolve.c | 27 | ||||
-rw-r--r-- | libexec/ld.so/resolve.h | 13 |
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_ */ |