--- libexec/rtld-elf/Symbol.map (revision 298672) +++ 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; }; --- libexec/rtld-elf/rtld.c (revision 298672) +++ libexec/rtld-elf/rtld.c (working copy) @@ -96,8 +96,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); @@ -533,8 +535,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. */ TAILQ_INSERT_HEAD(&obj_list, obj_main, next); @@ -2282,7 +2284,7 @@ TAILQ_INSERT_TAIL(&obj_list, 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, @@ -3622,19 +3624,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; @@ -3658,10 +3667,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; @@ -4300,7 +4313,7 @@ dbg("unloading \"%s\"", obj->path); unload_filtees(root); munmap(obj->mapbase, obj->mapsize); - linkmap_delete(obj); + linkmap_delete_obj(obj); TAILQ_REMOVE(&obj_list, obj, next); obj_count--; obj_free(obj); @@ -5039,6 +5052,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