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>