diff --git a/libexec/rtld-elf/amd64/reloc.c b/libexec/rtld-elf/amd64/reloc.c index 5f40847..6abc0d3 100644 --- a/libexec/rtld-elf/amd64/reloc.c +++ b/libexec/rtld-elf/amd64/reloc.c @@ -82,6 +82,7 @@ do_copy_relocations(Obj_Entry *dstobj) size = dstsym->st_size; symlook_init(&req, name); req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info)); + req.flags = SYMLOOK_EARLY; for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) { res = symlook_obj(&req, srcobj); diff --git a/libexec/rtld-elf/i386/reloc.c b/libexec/rtld-elf/i386/reloc.c index a2c8c98..ebd56c9 100644 --- a/libexec/rtld-elf/i386/reloc.c +++ b/libexec/rtld-elf/i386/reloc.c @@ -83,6 +83,7 @@ do_copy_relocations(Obj_Entry *dstobj) size = dstsym->st_size; symlook_init(&req, name); req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rel->r_info)); + req.flags = SYMLOOK_EARLY; for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) { res = symlook_obj(&req, srcobj); diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 3432232..c8f3baf 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -1605,6 +1605,7 @@ initlist_add_neededs(Needed_Entry *needed, Objlist *list) static void initlist_add_objects(Obj_Entry *obj, Obj_Entry **tail, Objlist *list) { + if (obj->init_scanned || obj->init_done) return; obj->init_scanned = true; @@ -1616,6 +1617,10 @@ initlist_add_objects(Obj_Entry *obj, Obj_Entry **tail, Objlist *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. */ if (obj->preinit_array != (Elf_Addr)NULL || obj->init != (Elf_Addr)NULL || @@ -2515,7 +2520,8 @@ dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags, objlist_push_tail(&list_global, obj); if (*old_obj_tail != NULL) { /* We loaded something new. */ assert(*old_obj_tail == obj); - result = load_needed_objects(obj, lo_flags & RTLD_LO_DLOPEN); + result = load_needed_objects(obj, + lo_flags & (RTLD_LO_DLOPEN | RTLD_LO_EARLY)); init_dag(obj); ref_dag(obj); if (result != -1) @@ -2526,6 +2532,8 @@ dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags, == RTLD_NOW, &obj_rtld, &lockstate)) == -1) { dlopen_cleanup(obj); obj = NULL; + } else if (lo_flags & RTLD_LO_EARLY) { + /* XXX */ } else { /* Make list of init functions to call. */ initlist_add_objects(obj, &obj->next, &initlist); @@ -2566,8 +2574,10 @@ dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags, return (NULL); } - /* Call the init functions. */ - objlist_call_init(&initlist, &lockstate); + if (!(lo_flags & RTLD_LO_EARLY)) { + /* Call the init functions. */ + objlist_call_init(&initlist, &lockstate); + } objlist_clear(&initlist); lock_release(rtld_bind_lock, &lockstate); return obj; @@ -3354,12 +3364,13 @@ symlook_obj(SymLook *req, const Obj_Entry *obj) { DoneList donelist; SymLook req1; - int res, mres; + int flags, res, mres; mres = symlook_obj1(req, obj); if (mres == 0) { if (obj->needed_filtees != NULL) { - load_filtees(__DECONST(Obj_Entry *, obj), 0, req->lockstate); + flags = (req->flags & SYMLOOK_EARLY) ? RTLD_LO_EARLY : 0; + load_filtees(__DECONST(Obj_Entry *, obj), flags, req->lockstate); donelist_init(&donelist); symlook_init_from_req(&req1, req); res = symlook_needed(&req1, obj->needed_filtees, &donelist); @@ -3370,7 +3381,8 @@ symlook_obj(SymLook *req, const Obj_Entry *obj) return (res); } if (obj->needed_aux_filtees != NULL) { - load_filtees(__DECONST(Obj_Entry *, obj), 0, req->lockstate); + flags = (req->flags & SYMLOOK_EARLY) ? RTLD_LO_EARLY : 0; + load_filtees(__DECONST(Obj_Entry *, obj), flags, req->lockstate); donelist_init(&donelist); symlook_init_from_req(&req1, req); res = symlook_needed(&req1, obj->needed_aux_filtees, &donelist); diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index 9dfa0a2..0ceebab 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -267,6 +267,7 @@ typedef struct Struct_Obj_Entry { #define SYMLOOK_IN_PLT 0x01 /* Lookup for PLT symbol */ #define SYMLOOK_DLSYM 0x02 /* Return newest versioned symbol. Used by dlsym. */ +#define SYMLOOK_EARLY 0x04 /* Symlook is done during initialization. */ /* Flags for load_object(). */ #define RTLD_LO_NOLOAD 0x01 /* dlopen() specified RTLD_NOLOAD. */ @@ -274,6 +275,8 @@ typedef struct Struct_Obj_Entry { #define RTLD_LO_TRACE 0x04 /* Only tracing. */ #define RTLD_LO_NODELETE 0x08 /* Loaded object cannot be closed. */ #define RTLD_LO_FILTEES 0x10 /* Loading filtee. */ +#define RTLD_LO_EARLY 0x20 /* Do not call ctors, postpone it to the + initialization during the image start. */ /* * Symbol cache entry used during relocation to avoid multiple lookups