--- 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; }; --- 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 --- 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