misc/186435: [patch] Allow for an alternative run-time loader
Yuri
yuri at rawbw.com
Sun Feb 23 09:10:01 UTC 2014
The following reply was made to PR misc/186435; it has been noted by GNATS.
From: Yuri <yuri at rawbw.com>
To: bug-followup at FreeBSD.org
Cc: Alexander Kabaev <kabaev at gmail.com>
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--
More information about the freebsd-bugs
mailing list