rtld.c (214777) | rtld.c (216489) |
---|---|
1/*- 2 * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. 3 * Copyright 2003 Alexander Kabaev <kan@FreeBSD.ORG>. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 9 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * | 1/*- 2 * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. 3 * Copyright 2003 Alexander Kabaev <kan@FreeBSD.ORG>. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 9 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/libexec/rtld-elf/rtld.c 214777 2010-11-04 09:29:00Z kib $ | 26 * $FreeBSD: head/libexec/rtld-elf/rtld.c 216489 2010-12-16 16:56:44Z jh $ |
27 */ 28 29/* 30 * Dynamic linker for ELF. 31 * 32 * John Polstra <jdp@polstra.com>. 33 */ 34 --- 70 unchanged lines hidden (view full) --- 105static void initlist_add_neededs(Needed_Entry *, Objlist *); 106static void initlist_add_objects(Obj_Entry *, Obj_Entry **, Objlist *); 107static void linkmap_add(Obj_Entry *); 108static void linkmap_delete(Obj_Entry *); 109static int load_needed_objects(Obj_Entry *, int); 110static int load_preload_objects(void); 111static Obj_Entry *load_object(const char *, const Obj_Entry *, int); 112static Obj_Entry *obj_from_addr(const void *); | 27 */ 28 29/* 30 * Dynamic linker for ELF. 31 * 32 * John Polstra <jdp@polstra.com>. 33 */ 34 --- 70 unchanged lines hidden (view full) --- 105static void initlist_add_neededs(Needed_Entry *, Objlist *); 106static void initlist_add_objects(Obj_Entry *, Obj_Entry **, Objlist *); 107static void linkmap_add(Obj_Entry *); 108static void linkmap_delete(Obj_Entry *); 109static int load_needed_objects(Obj_Entry *, int); 110static int load_preload_objects(void); 111static Obj_Entry *load_object(const char *, const Obj_Entry *, int); 112static Obj_Entry *obj_from_addr(const void *); |
113static void objlist_call_fini(Objlist *, bool, int *); | 113static void objlist_call_fini(Objlist *, Obj_Entry *, int *); |
114static void objlist_call_init(Objlist *, int *); 115static void objlist_clear(Objlist *); 116static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *); 117static void objlist_init(Objlist *); 118static void objlist_push_head(Objlist *, Obj_Entry *); 119static void objlist_push_tail(Objlist *, Obj_Entry *); 120static void objlist_remove(Objlist *, Obj_Entry *); 121static void *path_enumerate(const char *, path_enum_proc, void *); --- 1482 unchanged lines hidden (view full) --- 1604 if (addr < (void *) (obj->mapbase + obj->mapsize)) 1605 return obj; 1606 } 1607 return NULL; 1608} 1609 1610/* 1611 * Call the finalization functions for each of the objects in "list" | 114static void objlist_call_init(Objlist *, int *); 115static void objlist_clear(Objlist *); 116static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *); 117static void objlist_init(Objlist *); 118static void objlist_push_head(Objlist *, Obj_Entry *); 119static void objlist_push_tail(Objlist *, Obj_Entry *); 120static void objlist_remove(Objlist *, Obj_Entry *); 121static void *path_enumerate(const char *, path_enum_proc, void *); --- 1482 unchanged lines hidden (view full) --- 1604 if (addr < (void *) (obj->mapbase + obj->mapsize)) 1605 return obj; 1606 } 1607 return NULL; 1608} 1609 1610/* 1611 * Call the finalization functions for each of the objects in "list" |
1612 * which are unreferenced. All of the objects are expected to have 1613 * non-NULL fini functions. | 1612 * belonging to the DAG of "root" and referenced once. If NULL "root" 1613 * is specified, every finalization function will be called regardless 1614 * of the reference count and the list elements won't be freed. All of 1615 * the objects are expected to have non-NULL fini functions. |
1614 */ 1615static void | 1616 */ 1617static void |
1616objlist_call_fini(Objlist *list, bool force, int *lockstate) | 1618objlist_call_fini(Objlist *list, Obj_Entry *root, int *lockstate) |
1617{ | 1619{ |
1618 Objlist_Entry *elm, *elm_tmp; | 1620 Objlist_Entry *elm; |
1619 char *saved_msg; 1620 | 1621 char *saved_msg; 1622 |
1623 assert(root == NULL || root->refcount == 1); 1624 |
|
1621 /* 1622 * Preserve the current error message since a fini function might 1623 * call into the dynamic linker and overwrite it. 1624 */ 1625 saved_msg = errmsg_save(); | 1625 /* 1626 * Preserve the current error message since a fini function might 1627 * call into the dynamic linker and overwrite it. 1628 */ 1629 saved_msg = errmsg_save(); |
1626 STAILQ_FOREACH_SAFE(elm, list, link, elm_tmp) { 1627 if (elm->obj->refcount == 0 || force) { | 1630 do { 1631 STAILQ_FOREACH(elm, list, link) { 1632 if (root != NULL && (elm->obj->refcount != 1 || 1633 objlist_find(&root->dagmembers, elm->obj) == NULL)) 1634 continue; |
1628 dbg("calling fini function for %s at %p", elm->obj->path, 1629 (void *)elm->obj->fini); 1630 LD_UTRACE(UTRACE_FINI_CALL, elm->obj, (void *)elm->obj->fini, 0, 0, 1631 elm->obj->path); 1632 /* Remove object from fini list to prevent recursive invocation. */ 1633 STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link); | 1635 dbg("calling fini function for %s at %p", elm->obj->path, 1636 (void *)elm->obj->fini); 1637 LD_UTRACE(UTRACE_FINI_CALL, elm->obj, (void *)elm->obj->fini, 0, 0, 1638 elm->obj->path); 1639 /* Remove object from fini list to prevent recursive invocation. */ 1640 STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link); |
1641 /* 1642 * XXX: If a dlopen() call references an object while the 1643 * fini function is in progress, we might end up trying to 1644 * unload the referenced object in dlclose() or the object 1645 * won't be unloaded although its fini function has been 1646 * called. 1647 */ |
|
1634 wlock_release(rtld_bind_lock, *lockstate); 1635 call_initfini_pointer(elm->obj, elm->obj->fini); 1636 *lockstate = wlock_acquire(rtld_bind_lock); 1637 /* No need to free anything if process is going down. */ | 1648 wlock_release(rtld_bind_lock, *lockstate); 1649 call_initfini_pointer(elm->obj, elm->obj->fini); 1650 *lockstate = wlock_acquire(rtld_bind_lock); 1651 /* No need to free anything if process is going down. */ |
1638 if (!force) | 1652 if (root != NULL) |
1639 free(elm); | 1653 free(elm); |
1654 /* 1655 * We must restart the list traversal after every fini call 1656 * because a dlclose() call from the fini function or from 1657 * another thread might have modified the reference counts. 1658 */ 1659 break; |
|
1640 } | 1660 } |
1641 } | 1661 } while (elm != NULL); |
1642 errmsg_restore(saved_msg); 1643} 1644 1645/* 1646 * Call the initialization functions for each of the objects in 1647 * "list". All of the objects are expected to have non-NULL init 1648 * functions. 1649 */ --- 171 unchanged lines hidden (view full) --- 1821 */ 1822static void 1823rtld_exit(void) 1824{ 1825 int lockstate; 1826 1827 lockstate = wlock_acquire(rtld_bind_lock); 1828 dbg("rtld_exit()"); | 1662 errmsg_restore(saved_msg); 1663} 1664 1665/* 1666 * Call the initialization functions for each of the objects in 1667 * "list". All of the objects are expected to have non-NULL init 1668 * functions. 1669 */ --- 171 unchanged lines hidden (view full) --- 1841 */ 1842static void 1843rtld_exit(void) 1844{ 1845 int lockstate; 1846 1847 lockstate = wlock_acquire(rtld_bind_lock); 1848 dbg("rtld_exit()"); |
1829 objlist_call_fini(&list_fini, true, &lockstate); | 1849 objlist_call_fini(&list_fini, NULL, &lockstate); |
1830 /* No need to remove the items from the list, since we are exiting. */ 1831 if (!libmap_disable) 1832 lm_fini(); 1833 wlock_release(rtld_bind_lock, lockstate); 1834} 1835 1836static void * 1837path_enumerate(const char *path, path_enum_proc callback, void *arg) --- 96 unchanged lines hidden (view full) --- 1934 return -1; 1935 } 1936 LD_UTRACE(UTRACE_DLCLOSE_START, handle, NULL, 0, root->dl_refcount, 1937 root->path); 1938 1939 /* Unreference the object and its dependencies. */ 1940 root->dl_refcount--; 1941 | 1850 /* No need to remove the items from the list, since we are exiting. */ 1851 if (!libmap_disable) 1852 lm_fini(); 1853 wlock_release(rtld_bind_lock, lockstate); 1854} 1855 1856static void * 1857path_enumerate(const char *path, path_enum_proc callback, void *arg) --- 96 unchanged lines hidden (view full) --- 1954 return -1; 1955 } 1956 LD_UTRACE(UTRACE_DLCLOSE_START, handle, NULL, 0, root->dl_refcount, 1957 root->path); 1958 1959 /* Unreference the object and its dependencies. */ 1960 root->dl_refcount--; 1961 |
1942 unref_dag(root); 1943 1944 if (root->refcount == 0) { | 1962 if (root->refcount == 1) { |
1945 /* | 1963 /* |
1946 * The object is no longer referenced, so we must unload it. | 1964 * The object will be no longer referenced, so we must unload it. |
1947 * First, call the fini functions. 1948 */ | 1965 * First, call the fini functions. 1966 */ |
1949 objlist_call_fini(&list_fini, false, &lockstate); | 1967 objlist_call_fini(&list_fini, root, &lockstate); |
1950 | 1968 |
1969 unref_dag(root); 1970 |
|
1951 /* Finish cleaning up the newly-unreferenced objects. */ 1952 GDB_STATE(RT_DELETE,&root->linkmap); 1953 unload_object(root); 1954 GDB_STATE(RT_CONSISTENT,NULL); | 1971 /* Finish cleaning up the newly-unreferenced objects. */ 1972 GDB_STATE(RT_DELETE,&root->linkmap); 1973 unload_object(root); 1974 GDB_STATE(RT_CONSISTENT,NULL); |
1955 } | 1975 } else 1976 unref_dag(root); 1977 |
1956 LD_UTRACE(UTRACE_DLCLOSE_STOP, handle, NULL, 0, 0, NULL); 1957 wlock_release(rtld_bind_lock, lockstate); 1958 return 0; 1959} 1960 1961char * 1962dlerror(void) 1963{ --- 1727 unchanged lines hidden --- | 1978 LD_UTRACE(UTRACE_DLCLOSE_STOP, handle, NULL, 0, 0, NULL); 1979 wlock_release(rtld_bind_lock, lockstate); 1980 return 0; 1981} 1982 1983char * 1984dlerror(void) 1985{ --- 1727 unchanged lines hidden --- |