From owner-freebsd-bugs@FreeBSD.ORG Sun Feb 23 09:10:01 2014 Return-Path: Delivered-To: freebsd-bugs@smarthost.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 8824F12B for ; Sun, 23 Feb 2014 09:10:01 +0000 (UTC) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 732EB186D for ; Sun, 23 Feb 2014 09:10:01 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.7/8.14.7) with ESMTP id s1N9A17h004938 for ; Sun, 23 Feb 2014 09:10:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.8/8.14.8/Submit) id s1N9A16h004937; Sun, 23 Feb 2014 09:10:01 GMT (envelope-from gnats) Date: Sun, 23 Feb 2014 09:10:01 GMT Message-Id: <201402230910.s1N9A16h004937@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: Yuri Subject: Re: misc/186435: [patch] Allow for an alternative run-time loader X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list Reply-To: Yuri List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 23 Feb 2014 09:10:01 -0000 The following reply was made to PR misc/186435; it has been noted by GNATS. From: Yuri To: bug-followup@FreeBSD.org Cc: Alexander Kabaev Subject: Re: misc/186435: [patch] Allow for an alternative run-time loader Date: Sun, 23 Feb 2014 00:50:37 -0800 This is a multi-part message in MIME format. --------------010107090807030709030204 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Yes, I knew that exposing locks is not nice. However, the upside was that the patch was extremely simple. I reworked it into the proper implementation. I added r_debug_add and r_debug_delete, with all locks hidden in them. They by themselves are sufficient for the goal. I also added r_debug_iterate, in order to potentially gain access to the list we are manipulating with. This is just in order to not lose any functionality that was made available with the previous patch. Yuri --------------010107090807030709030204 Content-Type: text/plain; charset=UTF-8; name="patch-rtld-elf-alt-loader.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="patch-rtld-elf-alt-loader.patch" Index: libexec/rtld-elf/Symbol.map =================================================================== --- libexec/rtld-elf/Symbol.map (revision 260894) +++ libexec/rtld-elf/Symbol.map (working copy) @@ -15,6 +15,9 @@ dlinfo; dl_iterate_phdr; r_debug_state; + r_debug_add; + r_debug_delete; + r_debug_iterate; __tls_get_addr; }; Index: libexec/rtld-elf/rtld.c =================================================================== --- libexec/rtld-elf/rtld.c (revision 260894) +++ libexec/rtld-elf/rtld.c (working copy) @@ -100,8 +100,10 @@ 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 linkmap_add(Obj_Entry *); -static void linkmap_delete(Obj_Entry *); +static void linkmap_add_obj(Obj_Entry *); +static void linkmap_add_map(struct link_map *); +static void linkmap_delete_obj(Obj_Entry *); +static void linkmap_delete_map(struct link_map *); static void load_filtees(Obj_Entry *, int flags, RtldLockState *); static void unload_filtees(Obj_Entry *); static int load_needed_objects(Obj_Entry *, int); @@ -513,8 +515,8 @@ obj_main->path, obj_main->valid_hash_sysv, obj_main->valid_hash_gnu, obj_main->dynsymcount); - linkmap_add(obj_main); - linkmap_add(&obj_rtld); + linkmap_add_obj(obj_main); + linkmap_add_obj(&obj_rtld); /* Link the main program into the list of objects. */ *obj_tail = obj_main; @@ -2155,7 +2157,7 @@ obj_tail = &obj->next; obj_count++; obj_loads++; - linkmap_add(obj); /* for GDB & dlinfo() */ + linkmap_add_obj(obj); /* for GDB & dlinfo() */ max_stack_flags |= obj->stack_flags; dbg(" %p .. %p: %s", obj->mapbase, @@ -3428,19 +3430,26 @@ } static void -linkmap_add(Obj_Entry *obj) +linkmap_add_obj(Obj_Entry *obj) { struct link_map *l = &obj->linkmap; - struct link_map *prev; - obj->linkmap.l_name = obj->path; - obj->linkmap.l_addr = obj->mapbase; - obj->linkmap.l_ld = obj->dynamic; + l->l_name = obj->path; + l->l_addr = obj->mapbase; + l->l_ld = obj->dynamic; #ifdef __mips__ /* GDB needs load offset on MIPS to use the symbols */ - obj->linkmap.l_offs = obj->relocbase; + l->l_offs = obj->relocbase; #endif + linkmap_add_map(l); +} + +static void +linkmap_add_map(struct link_map *l) +{ + struct link_map *prev; + if (r_debug.r_map == NULL) { r_debug.r_map = l; return; @@ -3464,10 +3473,14 @@ } static void -linkmap_delete(Obj_Entry *obj) +linkmap_delete_obj(Obj_Entry *obj) { - struct link_map *l = &obj->linkmap; + linkmap_delete_map(&obj->linkmap); +} +static void +linkmap_delete_map(struct link_map *l) +{ if (l->l_prev == NULL) { if ((r_debug.r_map = l->l_next) != NULL) l->l_next->l_prev = NULL; @@ -4092,7 +4105,7 @@ dbg("unloading \"%s\"", obj->path); unload_filtees(root); munmap(obj->mapbase, obj->mapsize); - linkmap_delete(obj); + linkmap_delete_obj(obj); *linkp = obj->next; obj_count--; obj_free(obj); @@ -4809,6 +4822,58 @@ int _thread_autoinit_dummy_decl = 1; /* + * Support for an alternative loader + */ + +void +r_debug_add(struct link_map *m) +{ + RtldLockState lockstate; + wlock_acquire(rtld_bind_lock, &lockstate); + GDB_STATE(RT_ADD,NULL); + linkmap_add_map(m); + GDB_STATE(RT_CONSISTENT, m) + lock_release(rtld_bind_lock, &lockstate); +} + +void +r_debug_delete(struct link_map *m) +{ + RtldLockState lockstate; + wlock_acquire(rtld_bind_lock, &lockstate); + GDB_STATE(RT_DELETE, m); + linkmap_delete_map(m); + GDB_STATE(RT_CONSISTENT, NULL); + lock_release(rtld_bind_lock, &lockstate); +} + +int +r_debug_iterate(int wr, int (*callback)(struct link_map *, void *), void *param) +{ + struct link_map *m; + int error = 0; + RtldLockState lockstate; + + if (wr) { + wlock_acquire(rtld_bind_lock, &lockstate); + } else { + rlock_acquire(rtld_bind_lock, &lockstate); + } + + /* + * Iterate while callback returns zero + */ + for (m = r_debug.r_map; + m != NULL && (error = callback(m, param)) == 0; + m = m->l_next) + ; + + lock_release(rtld_bind_lock, &lockstate); + + return error; +} + +/* * No unresolved symbols for rtld. */ void Index: sys/sys/link_elf.h =================================================================== --- sys/sys/link_elf.h (revision 260894) +++ sys/sys/link_elf.h (working copy) @@ -94,6 +94,9 @@ extern int dl_iterate_phdr(__dl_iterate_hdr_callback, void *); int _rtld_addr_phdr(const void *, struct dl_phdr_info *); int _rtld_get_stack_prot(void); +void r_debug_add(struct link_map *); +void r_debug_delete(struct link_map *); +int r_debug_iterate(int, int (*callback)(struct link_map *, void *), void *); __END_DECLS --------------010107090807030709030204--