diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2011-11-28 20:59:04 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2011-11-28 20:59:04 +0000 |
commit | 12153d2c7b20ffb704a75582c22d13633e38b361 (patch) | |
tree | 482aeaf3ab1dbf80bcd453d6cc53ec2471ac7f27 /libexec/ld.so | |
parent | 782ca313c57ce6984dfddd8a2dacb70b1ba66f40 (diff) |
Add support for getting some flags from DT_FLAGS_1: new flags
DF_1_NODELETE and DF_1_INITFIRST, as well as DF_1_NOW and DF_1_GLOBAL.
Committing for kurt@ who worked out the final version; ok guenther@ drahn@
Diffstat (limited to 'libexec/ld.so')
-rw-r--r-- | libexec/ld.so/dlfcn.c | 17 | ||||
-rw-r--r-- | libexec/ld.so/ldconfig/prebind.c | 6 | ||||
-rw-r--r-- | libexec/ld.so/library.c | 4 | ||||
-rw-r--r-- | libexec/ld.so/library_mquery.c | 4 | ||||
-rw-r--r-- | libexec/ld.so/library_subr.c | 4 | ||||
-rw-r--r-- | libexec/ld.so/loader.c | 52 | ||||
-rw-r--r-- | libexec/ld.so/resolve.c | 16 | ||||
-rw-r--r-- | libexec/ld.so/resolve.h | 7 |
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)) |