Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Apr 2015 10:59:06 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r281849 - stable/10/libexec/rtld-elf
Message-ID:  <201504221059.t3MAx6f0061792@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Apr 22 10:59:05 2015
New Revision: 281849
URL: https://svnweb.freebsd.org/changeset/base/281849

Log:
  MFC r281549:
  Implement support for -z global linker option.

Modified:
  stable/10/libexec/rtld-elf/rtld.c
  stable/10/libexec/rtld-elf/rtld.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/libexec/rtld-elf/rtld.c
==============================================================================
--- stable/10/libexec/rtld-elf/rtld.c	Wed Apr 22 10:57:00 2015	(r281848)
+++ stable/10/libexec/rtld-elf/rtld.c	Wed Apr 22 10:59:05 2015	(r281849)
@@ -1150,8 +1150,8 @@ digest_dynamic1(Obj_Entry *obj, int earl
 		    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, 
 		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

Modified: stable/10/libexec/rtld-elf/rtld.h
==============================================================================
--- stable/10/libexec/rtld-elf/rtld.h	Wed Apr 22 10:57:00 2015	(r281848)
+++ stable/10/libexec/rtld-elf/rtld.h	Wed Apr 22 10:59:05 2015	(r281849)
@@ -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. */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201504221059.t3MAx6f0061792>