Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 10 May 2025 19:33:12 GMT
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: f31acb9d5cb2 - stable/14 - rtld: add support for -z initfirst
Message-ID:  <202505101933.54AJXCmQ055062@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/14 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=f31acb9d5cb25678cb497cb28bc466442b99239f

commit f31acb9d5cb25678cb497cb28bc466442b99239f
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-05-03 08:14:25 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-05-10 18:57:46 +0000

    rtld: add support for -z initfirst
    
    (cherry picked from commit 78aaab9f1cf359f3b7325e4369653f6b50593393)
---
 libexec/rtld-elf/rtld.c | 138 +++++++++++++++++++++++++++++++++++-------------
 libexec/rtld-elf/rtld.h |   1 +
 2 files changed, 103 insertions(+), 36 deletions(-)

diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index ba8e2aea6e7c..8a3129093e8c 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -114,8 +114,11 @@ static void init_dag(Obj_Entry *);
 static void init_marker(Obj_Entry *);
 static void init_pagesizes(Elf_Auxinfo **aux_info);
 static void init_rtld(caddr_t, Elf_Auxinfo **);
-static void initlist_add_neededs(Needed_Entry *, Objlist *);
-static void initlist_add_objects(Obj_Entry *, Obj_Entry *, Objlist *);
+static void initlist_add_neededs(Needed_Entry *, Objlist *, Objlist *);
+static void initlist_add_objects(Obj_Entry *, Obj_Entry *, Objlist *,
+    Objlist *);
+static void initlist_for_loaded_obj(Obj_Entry *obj, Obj_Entry *tail,
+    Objlist *list);
 static int initlist_objects_ifunc(Objlist *, bool, int, RtldLockState *);
 static void linkmap_add(Obj_Entry *);
 static void linkmap_delete(Obj_Entry *);
@@ -932,8 +935,8 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
 
     /* Make a list of init functions to call. */
     objlist_init(&initlist);
-    initlist_add_objects(globallist_curr(TAILQ_FIRST(&obj_list)),
-      preload_tail, &initlist);
+    initlist_for_loaded_obj(globallist_curr(TAILQ_FIRST(&obj_list)),
+	preload_tail, &initlist);
 
     r_debug_state(NULL, &obj_main->linkmap); /* say hello to gdb! */
 
@@ -1510,6 +1513,8 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
 		    obj->bind_now = true;
 		if (dynp->d_un.d_val & DF_STATIC_TLS)
 		    obj->static_tls = true;
+		if (dynp->d_un.d_val & DF_1_INITFIRST)
+		    obj->z_initfirst = true;
 	    break;
 
 #ifdef __powerpc__
@@ -2518,15 +2523,15 @@ psa_filled:
  * when this function is called.
  */
 static void
-initlist_add_neededs(Needed_Entry *needed, Objlist *list)
+initlist_add_neededs(Needed_Entry *needed, Objlist *list, Objlist *iflist)
 {
     /* Recursively process the successor needed objects. */
     if (needed->next != NULL)
-	initlist_add_neededs(needed->next, list);
+	initlist_add_neededs(needed->next, list, iflist);
 
     /* Process the current needed object. */
     if (needed->obj != NULL)
-	initlist_add_objects(needed->obj, needed->obj, list);
+	initlist_add_objects(needed->obj, needed->obj, list, iflist);
 }
 
 /*
@@ -2539,36 +2544,97 @@ initlist_add_neededs(Needed_Entry *needed, Objlist *list)
  * held when this function is called.
  */
 static void
-initlist_add_objects(Obj_Entry *obj, Obj_Entry *tail, Objlist *list)
+initlist_for_loaded_obj(Obj_Entry *obj, Obj_Entry *tail, Objlist *list)
 {
-    Obj_Entry *nobj;
+	Objlist iflist;		/* initfirst objs and their needed */
+	Objlist_Entry *tmp;
 
-    if (obj->init_scanned || obj->init_done)
-	return;
-    obj->init_scanned = true;
-
-    /* Recursively process the successor objects. */
-    nobj = globallist_next(obj);
-    if (nobj != NULL && obj != tail)
-	initlist_add_objects(nobj, tail, list);
-
-    /* Recursively process the needed objects. */
-    if (obj->needed != NULL)
-	initlist_add_neededs(obj->needed, list);
-    if (obj->needed_filtees != NULL)
-	initlist_add_neededs(obj->needed_filtees, list);
-    if (obj->needed_aux_filtees != NULL)
-	initlist_add_neededs(obj->needed_aux_filtees, list);
-
-    /* Add the object to the init list. */
-    objlist_push_tail(list, obj);
-
-    /* Add the object to the global fini list in the reverse order. */
-    if ((obj->fini != (Elf_Addr)NULL || obj->fini_array != (Elf_Addr)NULL)
-      && !obj->on_fini_list) {
-	objlist_push_head(&list_fini, obj);
-	obj->on_fini_list = true;
-    }
+	objlist_init(&iflist);
+	initlist_add_objects(obj, tail, list, &iflist);
+
+	STAILQ_FOREACH(tmp, &iflist, link) {
+		Obj_Entry *tobj = tmp->obj;
+
+		if ((tobj->fini != (Elf_Addr)NULL ||
+		    tobj->fini_array != (Elf_Addr)NULL) &&
+		    !tobj->on_fini_list) {
+			objlist_push_tail(&list_fini, tobj);
+			tobj->on_fini_list = true;
+		}
+	}
+
+	/*
+	 * This might result in the same object appearing more
+	 * than once on the init list.  objlist_call_init()
+	 * uses obj->init_scanned to avoid dup calls.
+	 */
+	STAILQ_REVERSE(&iflist, Struct_Objlist_Entry, link);
+	STAILQ_FOREACH(tmp, &iflist, link)
+		objlist_push_head(list, tmp->obj);
+
+	objlist_clear(&iflist);
+}
+
+static void
+initlist_add_objects(Obj_Entry *obj, Obj_Entry *tail, Objlist *list,
+    Objlist *iflist)
+{
+	Obj_Entry *nobj;
+
+	if (obj->init_done)
+		return;
+
+	if (obj->z_initfirst || list == NULL) {
+		/*
+		 * Ignore obj->init_scanned.  The object might indeed
+		 * already be on the init list, but due to being
+		 * needed by an initfirst object, we must put it at
+		 * the head of the init list.  obj->init_done protects
+		 * against double-initialization.
+		 */
+		if (obj->needed != NULL)
+			initlist_add_neededs(obj->needed, NULL, iflist);
+		if (obj->needed_filtees != NULL)
+			initlist_add_neededs(obj->needed_filtees, NULL,
+			    iflist);
+		if (obj->needed_aux_filtees != NULL)
+			initlist_add_neededs(obj->needed_aux_filtees,
+			    NULL, iflist);
+		objlist_push_tail(iflist, obj);
+	} else {
+		if (obj->init_scanned)
+			return;
+		obj->init_scanned = true;
+
+		/* Recursively process the successor objects. */
+		nobj = globallist_next(obj);
+		if (nobj != NULL && obj != tail)
+			initlist_add_objects(nobj, tail, list, iflist);
+		
+		/* Recursively process the needed objects. */
+		if (obj->needed != NULL)
+			initlist_add_neededs(obj->needed, list, iflist);
+		if (obj->needed_filtees != NULL)
+			initlist_add_neededs(obj->needed_filtees, list,
+			    iflist);
+		if (obj->needed_aux_filtees != NULL)
+			initlist_add_neededs(obj->needed_aux_filtees, list,
+			    iflist);
+		
+		/* Add the object to the init list. */
+		objlist_push_tail(list, obj);
+
+		/*
+		 * Add the object to the global fini list in the
+		 * reverse order.
+		 */
+		if ((obj->fini != (Elf_Addr)NULL ||
+		    obj->fini_array != (Elf_Addr)NULL) &&
+		    !obj->on_fini_list) {
+			objlist_push_head(&list_fini, obj);
+			obj->on_fini_list = true;
+		}
+	}
 }
 
 static void
@@ -3824,7 +3890,7 @@ dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags,
 		 */
 	    } else {
 		/* Make list of init functions to call. */
-		initlist_add_objects(obj, obj, &initlist);
+		initlist_for_loaded_obj(obj, obj, &initlist);
 	    }
 	    /*
 	     * Process all no_delete or global objects here, given
diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h
index 97187b24ce84..8d0b8bfed2ab 100644
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -256,6 +256,7 @@ typedef struct Struct_Obj_Entry {
     bool z_nodeflib : 1;	/* Don't search default library path */
     bool z_global : 1;		/* Make the object global */
     bool z_pie : 1;		/* Object proclaimed itself PIE executable */
+    bool z_initfirst : 1;	/* Proceed initializers before other objects */
     bool static_tls : 1;	/* Needs static TLS allocation */
     bool static_tls_copied : 1;	/* Needs static TLS copying */
     bool ref_nodel : 1;		/* Refcount increased to prevent dlclose */



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