diff options
| author | John Polstra <jdp@FreeBSD.org> | 1999-07-09 16:22:55 +0000 |
|---|---|---|
| committer | John Polstra <jdp@FreeBSD.org> | 1999-07-09 16:22:55 +0000 |
| commit | 8d05e8c4535a87a623927c2d9496608ae60c78f2 (patch) | |
| tree | 6e8133f8fa4b56a08424f8f31f5462297cbbff20 /libexec/rtld-elf | |
| parent | 68d0ed40e48d2e4a05dbed39b67f6680de4b934f (diff) | |
Notes
Diffstat (limited to 'libexec/rtld-elf')
| -rw-r--r-- | libexec/rtld-elf/rtld.c | 82 |
1 files changed, 44 insertions, 38 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 1ff518e0ab02..8a69de136bb0 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -22,7 +22,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: rtld.c,v 1.25 1999/06/25 04:50:06 jdp Exp $ + * $Id: rtld.c,v 1.26 1999/07/03 23:54:02 jdp Exp $ */ /* @@ -89,8 +89,9 @@ static int relocate_objects(Obj_Entry *, bool); static void rtld_exit(void); static char *search_library_path(const char *, const char *); static void set_program_var(const char *, const void *); -static void unref_object_dag(Obj_Entry *); static void trace_loaded_objects(Obj_Entry *obj); +static void unload_object(Obj_Entry *, bool do_fini_funcs); +static void unref_object_dag(Obj_Entry *); void r_debug_state(void); void xprintf(const char *, ...); @@ -942,6 +943,7 @@ load_object(char *path) _rtld_error("Cannot open \"%s\"", path); return NULL; } + dbg("loading \"%s\"", path); obj = map_object(fd); close(fd); if (obj == NULL) { @@ -1106,38 +1108,8 @@ dlclose(void *handle) return -1; GDB_STATE(RT_DELETE); - + unload_object(root, true); root->dl_refcount--; - unref_object_dag(root); - if (root->refcount == 0) { /* We are finished with some objects. */ - Obj_Entry *obj; - Obj_Entry **linkp; - - /* Finalize objects that are about to be unmapped. */ - for (obj = obj_list->next; obj != NULL; obj = obj->next) - if (obj->refcount == 0 && obj->fini != NULL) - (*obj->fini)(); - - /* Unmap all objects that are no longer referenced. */ - linkp = &obj_list->next; - while ((obj = *linkp) != NULL) { - if (obj->refcount == 0) { - munmap(obj->mapbase, obj->mapsize); - free(obj->path); - while (obj->needed != NULL) { - Needed_Entry *needed = obj->needed; - obj->needed = needed->next; - free(needed); - } - linkmap_delete(obj); - *linkp = obj->next; - free(obj); - } else - linkp = &obj->next; - } - obj_tail = linkp; - } - GDB_STATE(RT_CONSISTENT); return 0; @@ -1173,11 +1145,9 @@ dlopen(const char *name, int mode) if (*old_obj_tail != NULL) { /* We loaded something new. */ assert(*old_obj_tail == obj); - /* XXX - Clean up properly after an error. */ - if (load_needed_objects(obj) == -1) { - obj->dl_refcount--; - obj = NULL; - } else if (relocate_objects(obj, mode == RTLD_NOW) == -1) { + if (load_needed_objects(obj) == -1 || + relocate_objects(obj, mode == RTLD_NOW) == -1) { + unload_object(obj, false); obj->dl_refcount--; obj = NULL; } else @@ -1503,6 +1473,42 @@ trace_loaded_objects(Obj_Entry *obj) } static void +unload_object(Obj_Entry *root, bool do_fini_funcs) +{ + unref_object_dag(root); + if (root->refcount == 0) { /* We are finished with some objects. */ + Obj_Entry *obj; + Obj_Entry **linkp; + + /* Finalize objects that are about to be unmapped. */ + if (do_fini_funcs) + for (obj = obj_list->next; obj != NULL; obj = obj->next) + if (obj->refcount == 0 && obj->fini != NULL) + (*obj->fini)(); + + /* Unmap all objects that are no longer referenced. */ + linkp = &obj_list->next; + while ((obj = *linkp) != NULL) { + if (obj->refcount == 0) { + dbg("unloading \"%s\"", obj->path); + munmap(obj->mapbase, obj->mapsize); + free(obj->path); + while (obj->needed != NULL) { + Needed_Entry *needed = obj->needed; + obj->needed = needed->next; + free(needed); + } + linkmap_delete(obj); + *linkp = obj->next; + free(obj); + } else + linkp = &obj->next; + } + obj_tail = linkp; + } +} + +static void unref_object_dag(Obj_Entry *root) { assert(root->refcount != 0); |
