rtld.c (232777) | rtld.c (232831) |
---|---|
1/*- 2 * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. 3 * Copyright 2003 Alexander Kabaev <kan@FreeBSD.ORG>. 4 * Copyright 2009, 2010, 2011 Konstantin Belousov <kib@FreeBSD.ORG>. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 10 unchanged lines hidden (view full) --- 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * | 1/*- 2 * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. 3 * Copyright 2003 Alexander Kabaev <kan@FreeBSD.ORG>. 4 * Copyright 2009, 2010, 2011 Konstantin Belousov <kib@FreeBSD.ORG>. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 10 unchanged lines hidden (view full) --- 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * |
27 * $FreeBSD: head/libexec/rtld-elf/rtld.c 232777 2012-03-10 08:49:44Z kib $ | 27 * $FreeBSD: head/libexec/rtld-elf/rtld.c 232831 2012-03-11 20:03:09Z kib $ |
28 */ 29 30/* 31 * Dynamic linker for ELF. 32 * 33 * John Polstra <jdp@polstra.com>. 34 */ 35 --- 20 unchanged lines hidden (view full) --- 56#include <string.h> 57#include <unistd.h> 58 59#include "debug.h" 60#include "rtld.h" 61#include "libmap.h" 62#include "rtld_tls.h" 63#include "rtld_printf.h" | 28 */ 29 30/* 31 * Dynamic linker for ELF. 32 * 33 * John Polstra <jdp@polstra.com>. 34 */ 35 --- 20 unchanged lines hidden (view full) --- 56#include <string.h> 57#include <unistd.h> 58 59#include "debug.h" 60#include "rtld.h" 61#include "libmap.h" 62#include "rtld_tls.h" 63#include "rtld_printf.h" |
64#include "notes.h" |
|
64 65#ifndef COMPAT_32BIT 66#define PATH_RTLD "/libexec/ld-elf.so.1" 67#else 68#define PATH_RTLD "/libexec/ld-elf32.so.1" 69#endif 70 71/* Types. */ --- 62 unchanged lines hidden (view full) --- 134static void trace_loaded_objects(Obj_Entry *); 135static void unlink_object(Obj_Entry *); 136static void unload_object(Obj_Entry *); 137static void unref_dag(Obj_Entry *); 138static void ref_dag(Obj_Entry *); 139static int origin_subst_one(char **, const char *, const char *, 140 const char *, char *); 141static char *origin_subst(const char *, const char *); | 65 66#ifndef COMPAT_32BIT 67#define PATH_RTLD "/libexec/ld-elf.so.1" 68#else 69#define PATH_RTLD "/libexec/ld-elf32.so.1" 70#endif 71 72/* Types. */ --- 62 unchanged lines hidden (view full) --- 135static void trace_loaded_objects(Obj_Entry *); 136static void unlink_object(Obj_Entry *); 137static void unload_object(Obj_Entry *); 138static void unref_dag(Obj_Entry *); 139static void ref_dag(Obj_Entry *); 140static int origin_subst_one(char **, const char *, const char *, 141 const char *, char *); 142static char *origin_subst(const char *, const char *); |
143static void preinit_main(void); |
|
142static int rtld_verify_versions(const Objlist *); 143static int rtld_verify_object_versions(Obj_Entry *); 144static void object_add_name(Obj_Entry *, const char *); 145static int object_match_name(const Obj_Entry *, const char *); 146static void ld_utrace_log(int, void *, void *, size_t, int, const char *); 147static void rtld_fill_dl_phdr_info(const Obj_Entry *obj, 148 struct dl_phdr_info *phdr_info); 149 --- 50 unchanged lines hidden (view full) --- 200/* 201 * Global declarations normally provided by crt1. The dynamic linker is 202 * not built with crt1, so we have to provide them ourselves. 203 */ 204char *__progname; 205char **environ; 206 207/* | 144static int rtld_verify_versions(const Objlist *); 145static int rtld_verify_object_versions(Obj_Entry *); 146static void object_add_name(Obj_Entry *, const char *); 147static int object_match_name(const Obj_Entry *, const char *); 148static void ld_utrace_log(int, void *, void *, size_t, int, const char *); 149static void rtld_fill_dl_phdr_info(const Obj_Entry *obj, 150 struct dl_phdr_info *phdr_info); 151 --- 50 unchanged lines hidden (view full) --- 202/* 203 * Global declarations normally provided by crt1. The dynamic linker is 204 * not built with crt1, so we have to provide them ourselves. 205 */ 206char *__progname; 207char **environ; 208 209/* |
210 * Used to pass argc, argv to init functions. 211 */ 212int main_argc; 213char **main_argv; 214 215/* |
|
208 * Globals to control TLS allocation. 209 */ 210size_t tls_last_offset; /* Static TLS offset of last module */ 211size_t tls_last_size; /* Static TLS size of last module */ 212size_t tls_static_space; /* Static TLS space allocated */ 213int tls_dtv_generation = 1; /* Used to detect when dtv size changes */ 214int tls_max_index = 1; /* Largest module index allocated */ 215 --- 114 unchanged lines hidden (view full) --- 330 331 /* Initialize and relocate ourselves. */ 332 assert(aux_info[AT_BASE] != NULL); 333 init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr, aux_info); 334 335 __progname = obj_rtld.path; 336 argv0 = argv[0] != NULL ? argv[0] : "(null)"; 337 environ = env; | 216 * Globals to control TLS allocation. 217 */ 218size_t tls_last_offset; /* Static TLS offset of last module */ 219size_t tls_last_size; /* Static TLS size of last module */ 220size_t tls_static_space; /* Static TLS space allocated */ 221int tls_dtv_generation = 1; /* Used to detect when dtv size changes */ 222int tls_max_index = 1; /* Largest module index allocated */ 223 --- 114 unchanged lines hidden (view full) --- 338 339 /* Initialize and relocate ourselves. */ 340 assert(aux_info[AT_BASE] != NULL); 341 init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr, aux_info); 342 343 __progname = obj_rtld.path; 344 argv0 = argv[0] != NULL ? argv[0] : "(null)"; 345 environ = env; |
346 main_argc = argc; 347 main_argv = argv; |
|
338 339 trust = !issetugid(); 340 341 ld_bind_now = getenv(LD_ "BIND_NOW"); 342 /* 343 * If the process is tainted, then we un-set the dangerous environment 344 * variables. The process will be marked as tainted until setuid(2) 345 * is called. If any child process calls setuid(2) we do not want any --- 107 unchanged lines hidden (view full) --- 453 linkmap_add(obj_main); 454 linkmap_add(&obj_rtld); 455 456 /* Link the main program into the list of objects. */ 457 *obj_tail = obj_main; 458 obj_tail = &obj_main->next; 459 obj_count++; 460 obj_loads++; | 348 349 trust = !issetugid(); 350 351 ld_bind_now = getenv(LD_ "BIND_NOW"); 352 /* 353 * If the process is tainted, then we un-set the dangerous environment 354 * variables. The process will be marked as tainted until setuid(2) 355 * is called. If any child process calls setuid(2) we do not want any --- 107 unchanged lines hidden (view full) --- 463 linkmap_add(obj_main); 464 linkmap_add(&obj_rtld); 465 466 /* Link the main program into the list of objects. */ 467 *obj_tail = obj_main; 468 obj_tail = &obj_main->next; 469 obj_count++; 470 obj_loads++; |
461 /* Make sure we don't call the main program's init and fini functions. */ 462 obj_main->init = obj_main->fini = (Elf_Addr)NULL; | |
463 464 /* Initialize a fake symbol for resolving undefined weak references. */ 465 sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); 466 sym_zero.st_shndx = SHN_UNDEF; 467 sym_zero.st_value = -(uintptr_t)obj_main->relocbase; 468 469 if (!libmap_disable) 470 libmap_disable = (bool)lm_init(libmap_override); --- 75 unchanged lines hidden (view full) --- 546 547 map_stacks_exec(NULL); 548 549 dbg("resolving ifuncs"); 550 if (resolve_objects_ifunc(obj_main, 551 ld_bind_now != NULL && *ld_bind_now != '\0', NULL) == -1) 552 die(); 553 | 471 472 /* Initialize a fake symbol for resolving undefined weak references. */ 473 sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); 474 sym_zero.st_shndx = SHN_UNDEF; 475 sym_zero.st_value = -(uintptr_t)obj_main->relocbase; 476 477 if (!libmap_disable) 478 libmap_disable = (bool)lm_init(libmap_override); --- 75 unchanged lines hidden (view full) --- 554 555 map_stacks_exec(NULL); 556 557 dbg("resolving ifuncs"); 558 if (resolve_objects_ifunc(obj_main, 559 ld_bind_now != NULL && *ld_bind_now != '\0', NULL) == -1) 560 die(); 561 |
562 if (!obj_main->crt_no_init) { 563 /* 564 * Make sure we don't call the main program's init and fini 565 * functions for binaries linked with old crt1 which calls 566 * _init itself. 567 */ 568 obj_main->init = obj_main->fini = (Elf_Addr)NULL; 569 obj_main->preinit_array = obj_main->init_array = 570 obj_main->fini_array = (Elf_Addr)NULL; 571 } 572 |
|
554 wlock_acquire(rtld_bind_lock, &lockstate); | 573 wlock_acquire(rtld_bind_lock, &lockstate); |
574 if (obj_main->crt_no_init) 575 preinit_main(); |
|
555 objlist_call_init(&initlist, &lockstate); 556 objlist_clear(&initlist); 557 dbg("loading filtees"); 558 for (obj = obj_list->next; obj != NULL; obj = obj->next) { 559 if (ld_loadfltr || obj->z_loadfltr) 560 load_filtees(obj, 0, &lockstate); 561 } 562 lock_release(rtld_bind_lock, &lockstate); --- 368 unchanged lines hidden (view full) --- 931 case DT_SONAME: 932 *dyn_soname = dynp; 933 break; 934 935 case DT_INIT: 936 obj->init = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); 937 break; 938 | 576 objlist_call_init(&initlist, &lockstate); 577 objlist_clear(&initlist); 578 dbg("loading filtees"); 579 for (obj = obj_list->next; obj != NULL; obj = obj->next) { 580 if (ld_loadfltr || obj->z_loadfltr) 581 load_filtees(obj, 0, &lockstate); 582 } 583 lock_release(rtld_bind_lock, &lockstate); --- 368 unchanged lines hidden (view full) --- 952 case DT_SONAME: 953 *dyn_soname = dynp; 954 break; 955 956 case DT_INIT: 957 obj->init = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); 958 break; 959 |
960 case DT_PREINIT_ARRAY: 961 obj->preinit_array = (Elf_Addr)(obj->relocbase + dynp->d_un.d_ptr); 962 break; 963 964 case DT_PREINIT_ARRAYSZ: 965 obj->preinit_array_num = dynp->d_un.d_val / sizeof(Elf_Addr); 966 break; 967 968 case DT_INIT_ARRAY: 969 obj->init_array = (Elf_Addr)(obj->relocbase + dynp->d_un.d_ptr); 970 break; 971 972 case DT_INIT_ARRAYSZ: 973 obj->init_array_num = dynp->d_un.d_val / sizeof(Elf_Addr); 974 break; 975 |
|
939 case DT_FINI: 940 obj->fini = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); 941 break; 942 | 976 case DT_FINI: 977 obj->fini = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); 978 break; 979 |
980 case DT_FINI_ARRAY: 981 obj->fini_array = (Elf_Addr)(obj->relocbase + dynp->d_un.d_ptr); 982 break; 983 984 case DT_FINI_ARRAYSZ: 985 obj->fini_array_num = dynp->d_un.d_val / sizeof(Elf_Addr); 986 break; 987 |
|
943 /* 944 * Don't process DT_DEBUG on MIPS as the dynamic section 945 * is mapped read-only. DT_MIPS_RLD_MAP is used instead. 946 */ 947 948#ifndef __mips__ 949 case DT_DEBUG: 950 /* XXX - not implemented yet */ --- 109 unchanged lines hidden (view full) --- 1060 * returns an Obj_Entry structure. 1061 */ 1062static Obj_Entry * 1063digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path) 1064{ 1065 Obj_Entry *obj; 1066 const Elf_Phdr *phlimit = phdr + phnum; 1067 const Elf_Phdr *ph; | 988 /* 989 * Don't process DT_DEBUG on MIPS as the dynamic section 990 * is mapped read-only. DT_MIPS_RLD_MAP is used instead. 991 */ 992 993#ifndef __mips__ 994 case DT_DEBUG: 995 /* XXX - not implemented yet */ --- 109 unchanged lines hidden (view full) --- 1105 * returns an Obj_Entry structure. 1106 */ 1107static Obj_Entry * 1108digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path) 1109{ 1110 Obj_Entry *obj; 1111 const Elf_Phdr *phlimit = phdr + phnum; 1112 const Elf_Phdr *ph; |
1113 Elf_Addr note_start, note_end; |
|
1068 int nsegs = 0; 1069 1070 obj = obj_new(); 1071 for (ph = phdr; ph < phlimit; ph++) { 1072 if (ph->p_type != PT_PHDR) 1073 continue; 1074 1075 obj->phdr = phdr; --- 39 unchanged lines hidden (view full) --- 1115 case PT_GNU_STACK: 1116 obj->stack_flags = ph->p_flags; 1117 break; 1118 1119 case PT_GNU_RELRO: 1120 obj->relro_page = obj->relocbase + trunc_page(ph->p_vaddr); 1121 obj->relro_size = round_page(ph->p_memsz); 1122 break; | 1114 int nsegs = 0; 1115 1116 obj = obj_new(); 1117 for (ph = phdr; ph < phlimit; ph++) { 1118 if (ph->p_type != PT_PHDR) 1119 continue; 1120 1121 obj->phdr = phdr; --- 39 unchanged lines hidden (view full) --- 1161 case PT_GNU_STACK: 1162 obj->stack_flags = ph->p_flags; 1163 break; 1164 1165 case PT_GNU_RELRO: 1166 obj->relro_page = obj->relocbase + trunc_page(ph->p_vaddr); 1167 obj->relro_size = round_page(ph->p_memsz); 1168 break; |
1169 1170 case PT_NOTE: 1171 note_start = (Elf_Addr)obj->relocbase + ph->p_vaddr; 1172 note_end = note_start + ph->p_filesz; 1173 digest_notes(obj, note_start, note_end); 1174 break; |
|
1123 } 1124 } 1125 if (nsegs < 1) { 1126 _rtld_error("%s: too few PT_LOAD segments", path); 1127 return NULL; 1128 } 1129 1130 obj->entry = entry; 1131 return obj; 1132} 1133 | 1175 } 1176 } 1177 if (nsegs < 1) { 1178 _rtld_error("%s: too few PT_LOAD segments", path); 1179 return NULL; 1180 } 1181 1182 obj->entry = entry; 1183 return obj; 1184} 1185 |
1186void 1187digest_notes(Obj_Entry *obj, Elf_Addr note_start, Elf_Addr note_end) 1188{ 1189 const Elf_Note *note; 1190 const char *note_name; 1191 uintptr_t p; 1192 1193 for (note = (const Elf_Note *)note_start; (Elf_Addr)note < note_end; 1194 note = (const Elf_Note *)((const char *)(note + 1) + 1195 roundup2(note->n_namesz, sizeof(Elf32_Addr)) + 1196 roundup2(note->n_descsz, sizeof(Elf32_Addr)))) { 1197 if (note->n_namesz != sizeof(NOTE_FREEBSD_VENDOR) || 1198 note->n_descsz != sizeof(int32_t)) 1199 continue; 1200 if (note->n_type != ABI_NOTETYPE && 1201 note->n_type != CRT_NOINIT_NOTETYPE) 1202 continue; 1203 note_name = (const char *)(note + 1); 1204 if (strncmp(NOTE_FREEBSD_VENDOR, note_name, 1205 sizeof(NOTE_FREEBSD_VENDOR)) != 0) 1206 continue; 1207 switch (note->n_type) { 1208 case ABI_NOTETYPE: 1209 /* FreeBSD osrel note */ 1210 p = (uintptr_t)(note + 1); 1211 p += roundup2(note->n_namesz, sizeof(Elf32_Addr)); 1212 obj->osrel = *(const int32_t *)(p); 1213 dbg("note osrel %d", obj->osrel); 1214 break; 1215 case CRT_NOINIT_NOTETYPE: 1216 /* FreeBSD 'crt does not call init' note */ 1217 obj->crt_no_init = true; 1218 dbg("note crt_no_init"); 1219 break; 1220 } 1221 } 1222} 1223 |
|
1134static Obj_Entry * 1135dlcheck(void *handle) 1136{ 1137 Obj_Entry *obj; 1138 1139 for (obj = obj_list; obj != NULL; obj = obj->next) 1140 if (obj == (Obj_Entry *) handle) 1141 break; --- 357 unchanged lines hidden (view full) --- 1499 if (&obj->next != tail) 1500 initlist_add_objects(obj->next, tail, list); 1501 1502 /* Recursively process the needed objects. */ 1503 if (obj->needed != NULL) 1504 initlist_add_neededs(obj->needed, list); 1505 1506 /* Add the object to the init list. */ | 1224static Obj_Entry * 1225dlcheck(void *handle) 1226{ 1227 Obj_Entry *obj; 1228 1229 for (obj = obj_list; obj != NULL; obj = obj->next) 1230 if (obj == (Obj_Entry *) handle) 1231 break; --- 357 unchanged lines hidden (view full) --- 1589 if (&obj->next != tail) 1590 initlist_add_objects(obj->next, tail, list); 1591 1592 /* Recursively process the needed objects. */ 1593 if (obj->needed != NULL) 1594 initlist_add_neededs(obj->needed, list); 1595 1596 /* Add the object to the init list. */ |
1507 if (obj->init != (Elf_Addr)NULL) | 1597 if (obj->preinit_array != (Elf_Addr)NULL || obj->init != (Elf_Addr)NULL || 1598 obj->init_array != (Elf_Addr)NULL) |
1508 objlist_push_tail(list, obj); 1509 1510 /* Add the object to the global fini list in the reverse order. */ | 1599 objlist_push_tail(list, obj); 1600 1601 /* Add the object to the global fini list in the reverse order. */ |
1511 if (obj->fini != (Elf_Addr)NULL && !obj->on_fini_list) { | 1602 if ((obj->fini != (Elf_Addr)NULL || obj->fini_array != (Elf_Addr)NULL) 1603 && !obj->on_fini_list) { |
1512 objlist_push_head(&list_fini, obj); 1513 obj->on_fini_list = true; 1514 } 1515} 1516 1517#ifndef FPTR_TARGET 1518#define FPTR_TARGET(f) ((Elf_Addr) (f)) 1519#endif --- 271 unchanged lines hidden (view full) --- 1791 if (addr < (void *) obj->mapbase) 1792 continue; 1793 if (addr < (void *) (obj->mapbase + obj->mapsize)) 1794 return obj; 1795 } 1796 return NULL; 1797} 1798 | 1604 objlist_push_head(&list_fini, obj); 1605 obj->on_fini_list = true; 1606 } 1607} 1608 1609#ifndef FPTR_TARGET 1610#define FPTR_TARGET(f) ((Elf_Addr) (f)) 1611#endif --- 271 unchanged lines hidden (view full) --- 1883 if (addr < (void *) obj->mapbase) 1884 continue; 1885 if (addr < (void *) (obj->mapbase + obj->mapsize)) 1886 return obj; 1887 } 1888 return NULL; 1889} 1890 |
1891static void 1892preinit_main(void) 1893{ 1894 Elf_Addr *preinit_addr; 1895 int index; 1896 1897 preinit_addr = (Elf_Addr *)obj_main->preinit_array; 1898 if (preinit_addr == (Elf_Addr)NULL) 1899 return; 1900 1901 for (index = 0; index < obj_main->preinit_array_num; index++) { 1902 if (preinit_addr[index] != 0 && preinit_addr[index] != 1) { 1903 dbg("calling preinit function for %s at %p", obj_main->path, 1904 (void *)preinit_addr[index]); 1905 LD_UTRACE(UTRACE_INIT_CALL, obj_main, (void *)preinit_addr[index], 1906 0, 0, obj_main->path); 1907 call_init_pointer(obj_main, preinit_addr[index]); 1908 } 1909 } 1910} 1911 |
|
1799/* 1800 * Call the finalization functions for each of the objects in "list" 1801 * belonging to the DAG of "root" and referenced once. If NULL "root" 1802 * is specified, every finalization function will be called regardless 1803 * of the reference count and the list elements won't be freed. All of 1804 * the objects are expected to have non-NULL fini functions. 1805 */ 1806static void 1807objlist_call_fini(Objlist *list, Obj_Entry *root, RtldLockState *lockstate) 1808{ 1809 Objlist_Entry *elm; 1810 char *saved_msg; | 1912/* 1913 * Call the finalization functions for each of the objects in "list" 1914 * belonging to the DAG of "root" and referenced once. If NULL "root" 1915 * is specified, every finalization function will be called regardless 1916 * of the reference count and the list elements won't be freed. All of 1917 * the objects are expected to have non-NULL fini functions. 1918 */ 1919static void 1920objlist_call_fini(Objlist *list, Obj_Entry *root, RtldLockState *lockstate) 1921{ 1922 Objlist_Entry *elm; 1923 char *saved_msg; |
1924 Elf_Addr *fini_addr; 1925 int index; |
|
1811 1812 assert(root == NULL || root->refcount == 1); 1813 1814 /* 1815 * Preserve the current error message since a fini function might 1816 * call into the dynamic linker and overwrite it. 1817 */ 1818 saved_msg = errmsg_save(); 1819 do { 1820 STAILQ_FOREACH(elm, list, link) { 1821 if (root != NULL && (elm->obj->refcount != 1 || 1822 objlist_find(&root->dagmembers, elm->obj) == NULL)) 1823 continue; | 1926 1927 assert(root == NULL || root->refcount == 1); 1928 1929 /* 1930 * Preserve the current error message since a fini function might 1931 * call into the dynamic linker and overwrite it. 1932 */ 1933 saved_msg = errmsg_save(); 1934 do { 1935 STAILQ_FOREACH(elm, list, link) { 1936 if (root != NULL && (elm->obj->refcount != 1 || 1937 objlist_find(&root->dagmembers, elm->obj) == NULL)) 1938 continue; |
1824 dbg("calling fini function for %s at %p", elm->obj->path, 1825 (void *)elm->obj->fini); 1826 LD_UTRACE(UTRACE_FINI_CALL, elm->obj, (void *)elm->obj->fini, 0, 0, 1827 elm->obj->path); | |
1828 /* Remove object from fini list to prevent recursive invocation. */ 1829 STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link); 1830 /* 1831 * XXX: If a dlopen() call references an object while the 1832 * fini function is in progress, we might end up trying to 1833 * unload the referenced object in dlclose() or the object 1834 * won't be unloaded although its fini function has been 1835 * called. 1836 */ 1837 lock_release(rtld_bind_lock, lockstate); | 1939 /* Remove object from fini list to prevent recursive invocation. */ 1940 STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link); 1941 /* 1942 * XXX: If a dlopen() call references an object while the 1943 * fini function is in progress, we might end up trying to 1944 * unload the referenced object in dlclose() or the object 1945 * won't be unloaded although its fini function has been 1946 * called. 1947 */ 1948 lock_release(rtld_bind_lock, lockstate); |
1838 call_initfini_pointer(elm->obj, elm->obj->fini); | 1949 1950 /* 1951 * It is legal to have both DT_FINI and DT_FINI_ARRAY defined. 1952 * When this happens, DT_FINI_ARRAY is processed first. 1953 */ 1954 fini_addr = (Elf_Addr *)elm->obj->fini_array; 1955 if (fini_addr != NULL && elm->obj->fini_array_num > 0) { 1956 for (index = elm->obj->fini_array_num - 1; index >= 0; 1957 index--) { 1958 if (fini_addr[index] != 0 && fini_addr[index] != 1) { 1959 dbg("calling fini function for %s at %p", 1960 elm->obj->path, (void *)fini_addr[index]); 1961 LD_UTRACE(UTRACE_FINI_CALL, elm->obj, 1962 (void *)fini_addr[index], 0, 0, elm->obj->path); 1963 call_initfini_pointer(elm->obj, fini_addr[index]); 1964 } 1965 } 1966 } 1967 if (elm->obj->fini != (Elf_Addr)NULL) { 1968 dbg("calling fini function for %s at %p", elm->obj->path, 1969 (void *)elm->obj->fini); 1970 LD_UTRACE(UTRACE_FINI_CALL, elm->obj, (void *)elm->obj->fini, 1971 0, 0, elm->obj->path); 1972 call_initfini_pointer(elm->obj, elm->obj->fini); 1973 } |
1839 wlock_acquire(rtld_bind_lock, lockstate); 1840 /* No need to free anything if process is going down. */ 1841 if (root != NULL) 1842 free(elm); 1843 /* 1844 * We must restart the list traversal after every fini call 1845 * because a dlclose() call from the fini function or from 1846 * another thread might have modified the reference counts. --- 10 unchanged lines hidden (view full) --- 1857 * functions. 1858 */ 1859static void 1860objlist_call_init(Objlist *list, RtldLockState *lockstate) 1861{ 1862 Objlist_Entry *elm; 1863 Obj_Entry *obj; 1864 char *saved_msg; | 1974 wlock_acquire(rtld_bind_lock, lockstate); 1975 /* No need to free anything if process is going down. */ 1976 if (root != NULL) 1977 free(elm); 1978 /* 1979 * We must restart the list traversal after every fini call 1980 * because a dlclose() call from the fini function or from 1981 * another thread might have modified the reference counts. --- 10 unchanged lines hidden (view full) --- 1992 * functions. 1993 */ 1994static void 1995objlist_call_init(Objlist *list, RtldLockState *lockstate) 1996{ 1997 Objlist_Entry *elm; 1998 Obj_Entry *obj; 1999 char *saved_msg; |
2000 Elf_Addr *init_addr; 2001 int index; |
|
1865 1866 /* 1867 * Clean init_scanned flag so that objects can be rechecked and 1868 * possibly initialized earlier if any of vectors called below 1869 * cause the change by using dlopen. 1870 */ 1871 for (obj = obj_list; obj != NULL; obj = obj->next) 1872 obj->init_scanned = false; 1873 1874 /* 1875 * Preserve the current error message since an init function might 1876 * call into the dynamic linker and overwrite it. 1877 */ 1878 saved_msg = errmsg_save(); 1879 STAILQ_FOREACH(elm, list, link) { 1880 if (elm->obj->init_done) /* Initialized early. */ 1881 continue; | 2002 2003 /* 2004 * Clean init_scanned flag so that objects can be rechecked and 2005 * possibly initialized earlier if any of vectors called below 2006 * cause the change by using dlopen. 2007 */ 2008 for (obj = obj_list; obj != NULL; obj = obj->next) 2009 obj->init_scanned = false; 2010 2011 /* 2012 * Preserve the current error message since an init function might 2013 * call into the dynamic linker and overwrite it. 2014 */ 2015 saved_msg = errmsg_save(); 2016 STAILQ_FOREACH(elm, list, link) { 2017 if (elm->obj->init_done) /* Initialized early. */ 2018 continue; |
1882 dbg("calling init function for %s at %p", elm->obj->path, 1883 (void *)elm->obj->init); 1884 LD_UTRACE(UTRACE_INIT_CALL, elm->obj, (void *)elm->obj->init, 0, 0, 1885 elm->obj->path); | |
1886 /* 1887 * Race: other thread might try to use this object before current 1888 * one completes the initilization. Not much can be done here 1889 * without better locking. 1890 */ 1891 elm->obj->init_done = true; 1892 lock_release(rtld_bind_lock, lockstate); | 2019 /* 2020 * Race: other thread might try to use this object before current 2021 * one completes the initilization. Not much can be done here 2022 * without better locking. 2023 */ 2024 elm->obj->init_done = true; 2025 lock_release(rtld_bind_lock, lockstate); |
1893 call_initfini_pointer(elm->obj, elm->obj->init); | 2026 2027 /* 2028 * It is legal to have both DT_INIT and DT_INIT_ARRAY defined. 2029 * When this happens, DT_INIT is processed first. 2030 */ 2031 if (elm->obj->init != (Elf_Addr)NULL) { 2032 dbg("calling init function for %s at %p", elm->obj->path, 2033 (void *)elm->obj->init); 2034 LD_UTRACE(UTRACE_INIT_CALL, elm->obj, (void *)elm->obj->init, 2035 0, 0, elm->obj->path); 2036 call_initfini_pointer(elm->obj, elm->obj->init); 2037 } 2038 init_addr = (Elf_Addr *)elm->obj->init_array; 2039 if (init_addr != (Elf_Addr)NULL) { 2040 for (index = 0; index < elm->obj->init_array_num; index++) { 2041 if (init_addr[index] != 0 && init_addr[index] != 1) { 2042 dbg("calling init function for %s at %p", elm->obj->path, 2043 (void *)init_addr[index]); 2044 LD_UTRACE(UTRACE_INIT_CALL, elm->obj, 2045 (void *)init_addr[index], 0, 0, elm->obj->path); 2046 call_init_pointer(elm->obj, init_addr[index]); 2047 } 2048 } 2049 } |
1894 wlock_acquire(rtld_bind_lock, lockstate); 1895 } 1896 errmsg_restore(saved_msg); 1897} 1898 1899static void 1900objlist_clear(Objlist *list) 1901{ --- 2258 unchanged lines hidden --- | 2050 wlock_acquire(rtld_bind_lock, lockstate); 2051 } 2052 errmsg_restore(saved_msg); 2053} 2054 2055static void 2056objlist_clear(Objlist *list) 2057{ --- 2258 unchanged lines hidden --- |