summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2015-04-22 10:59:05 +0000
committerkib <kib@FreeBSD.org>2015-04-22 10:59:05 +0000
commit5ddf292b719ba6df47105bbf4c7a7b6c9dae3574 (patch)
tree0f86cf3a8e7c60ba96faf8a27e12ceb65d0ae0ca /libexec
parent62ec6c0a01ffc399b8cadcc4c1b284631824842c (diff)
downloadFreeBSD-src-5ddf292b719ba6df47105bbf4c7a7b6c9dae3574.zip
FreeBSD-src-5ddf292b719ba6df47105bbf4c7a7b6c9dae3574.tar.gz
MFC r281549:
Implement support for -z global linker option.
Diffstat (limited to 'libexec')
-rw-r--r--libexec/rtld-elf/rtld.c47
-rw-r--r--libexec/rtld-elf/rtld.h1
2 files changed, 31 insertions, 17 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 84d1c80..cef0c42 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -1150,8 +1150,8 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
obj->z_noopen = true;
if ((dynp->d_un.d_val & DF_1_ORIGIN) && trust)
obj->z_origin = true;
- /*if (dynp->d_un.d_val & DF_1_GLOBAL)
- XXX ;*/
+ if (dynp->d_un.d_val & DF_1_GLOBAL)
+ obj->z_global = true;
if (dynp->d_un.d_val & DF_1_BIND_NOW)
obj->bind_now = true;
if (dynp->d_un.d_val & DF_1_NODELETE)
@@ -1775,22 +1775,35 @@ init_dag(Obj_Entry *root)
}
static void
-process_nodelete(Obj_Entry *root)
+process_z(Obj_Entry *root)
{
const Objlist_Entry *elm;
+ Obj_Entry *obj;
/*
- * Walk over object DAG and process every dependent object that
- * is marked as DF_1_NODELETE. They need to grow their own DAG,
- * which then should have its reference upped separately.
+ * Walk over object DAG and process every dependent object
+ * that is marked as DF_1_NODELETE or DF_1_GLOBAL. They need
+ * to grow their own DAG.
+ *
+ * For DF_1_GLOBAL, DAG is required for symbol lookups in
+ * symlook_global() to work.
+ *
+ * For DF_1_NODELETE, the DAG should have its reference upped.
*/
STAILQ_FOREACH(elm, &root->dagmembers, link) {
- if (elm->obj != NULL && elm->obj->z_nodelete &&
- !elm->obj->ref_nodel) {
- dbg("obj %s nodelete", elm->obj->path);
- init_dag(elm->obj);
- ref_dag(elm->obj);
- elm->obj->ref_nodel = true;
+ obj = elm->obj;
+ if (obj == NULL)
+ continue;
+ if (obj->z_nodelete && !obj->ref_nodel) {
+ dbg("obj %s -z nodelete", obj->path);
+ init_dag(obj);
+ ref_dag(obj);
+ obj->ref_nodel = true;
+ }
+ if (obj->z_global && objlist_find(&list_global, obj) == NULL) {
+ dbg("obj %s -z global", obj->path);
+ objlist_push_tail(&list_global, obj);
+ init_dag(obj);
}
}
}
@@ -2961,13 +2974,13 @@ dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags,
initlist_add_objects(obj, &obj->next, &initlist);
}
/*
- * Process all no_delete objects here, given them own
- * DAGs to prevent their dependencies from being unloaded.
- * This has to be done after we have loaded all of the
- * dependencies, so that we do not miss any.
+ * Process all no_delete or global objects here, given
+ * them own DAGs to prevent their dependencies from being
+ * unloaded. This has to be done after we have loaded all
+ * of the dependencies, so that we do not miss any.
*/
if (obj != NULL)
- process_nodelete(obj);
+ process_z(obj);
} else {
/*
* Bump the reference counts for objects on this DAG. If
diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h
index e16e46a..2fef9ef 100644
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -264,6 +264,7 @@ typedef struct Struct_Obj_Entry {
bool z_loadfltr : 1; /* Immediately load filtees */
bool z_interpose : 1; /* Interpose all objects but main */
bool z_nodeflib : 1; /* Don't search default library path */
+ bool z_global : 1; /* Make the object global */
bool ref_nodel : 1; /* Refcount increased to prevent dlclose */
bool init_scanned: 1; /* Object is already on init list. */
bool on_fini_list: 1; /* Object is already on fini list. */
OpenPOWER on IntegriCloud