int dlclose(void* handle) { ScopedPthreadMutexLocker locker(&g_dl_mutex); int result = do_dlclose(handle); if (result != 0) { __bionic_format_dlerror("dlclose failed", linker_get_error_buffer()); } return result; }
libearly_init(void) { char *s; int k; s = getenv("EARLY"); if (s == NULL) { printf("%s: EARLY = %s\n", __func__, "(not set)"); return; } printf("%s: EARLY = %s\n", __func__, s); for (k = 0; s[k] != 0; k++) { switch (s[k]) { case 'C': case 'c': do_dlclose(); break; case 'E': case 'e': do_exit(); break; case 'F': case 'f': do_fork(); break; case 'O': case 'o': do_dlopen(); break; case 'T': case 't': do_thread(); break; default: printf("%s: unknown char: %c\n", __func__, s[k]); break; } } }
int dlclose(void* handle) { ScopedPthreadMutexLocker locker(&g_dl_mutex); do_dlclose(reinterpret_cast<soinfo*>(handle)); // dlclose has no defined errors. return 0; }
int dlclose(void* handle) { ScopedPthreadMutexLocker locker(&gDlMutex); return do_dlclose(reinterpret_cast<soinfo*>(handle)); }
int _dlclose(void *vhandle) { return do_dlclose(vhandle, 1); }
void *_dlopen(const char *libname, int flag) { struct elf_resolve *tpnt, *tfrom; struct dyn_elf *rpnt = NULL; struct dyn_elf *dyn_chain; struct dyn_elf *dpnt; static int dl_init = 0; char *from; void (*dl_brk) (void); #ifdef __PIC__ int (*dl_elf_init) (void); #endif /* A bit of sanity checking... */ if (!(flag & (RTLD_LAZY|RTLD_NOW))) { _dl_error_number = LD_BAD_HANDLE; return NULL; } from = __builtin_return_address(0); /* Have the dynamic linker use the regular malloc function now */ if (!dl_init) { dl_init++; _dl_malloc_function = malloc; } /* Cover the trivial case first */ if (!libname) return _dl_symbol_tables; #ifdef USE_CACHE _dl_map_cache(); #endif /* * Try and locate the module we were called from - we * need this so that we get the correct RPATH. Note that * this is the current behavior under Solaris, but the * ABI+ specifies that we should only use the RPATH from * the application. Thus this may go away at some time * in the future. */ tfrom = NULL; for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) { tpnt = dpnt->dyn; if (tpnt->loadaddr < from && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) tfrom = tpnt; } if (!(tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname))) { #ifdef USE_CACHE _dl_unmap_cache(); #endif return NULL; } //tpnt->libtype = loaded_file; dyn_chain = rpnt = (struct dyn_elf *) malloc(sizeof(struct dyn_elf)); _dl_memset(rpnt, 0, sizeof(*rpnt)); rpnt->dyn = tpnt; rpnt->flags = flag; if (!tpnt->symbol_scope) tpnt->symbol_scope = dyn_chain; rpnt->next_handle = _dl_handles; _dl_handles = rpnt; /* * OK, we have the requested file in memory. Now check for * any other requested files that may also be required. */ { struct elf_resolve *tcurr; struct elf_resolve * tpnt1; Elf32_Dyn * dpnt; char * lpnt; tcurr = tpnt; do{ for(dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) { if(dpnt->d_tag == DT_NEEDED) { lpnt = tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val; if(!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpnt))) goto oops; rpnt->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf)); _dl_memset (rpnt->next, 0, sizeof (*(rpnt->next))); rpnt = rpnt->next; if (!tpnt1->symbol_scope) tpnt1->symbol_scope = dyn_chain; rpnt->dyn = tpnt1; }; } tcurr = tcurr->next; } while(tcurr); } /* * OK, now attach the entire chain at the end */ rpnt->next = _dl_symbol_tables; /* * MIPS is special *sigh* */ #ifdef __mips__ _dl_perform_mips_global_got_relocations(tpnt); #endif if (do_fixup(tpnt, flag)) { _dl_error_number = LD_NO_SYMBOL; goto oops; } if (_dl_debug_addr) { dl_brk = (void (*)(void)) _dl_debug_addr->r_brk; if (dl_brk != NULL) { _dl_debug_addr->r_state = RT_ADD; (*dl_brk) (); _dl_debug_addr->r_state = RT_CONSISTENT; (*dl_brk) (); } } #ifdef __PIC__ for (rpnt = dyn_chain; rpnt; rpnt = rpnt->next) { tpnt = rpnt->dyn; /* Apparently crt1 for the application is responsible for handling this. * We only need to run the init/fini for shared libraries */ if (tpnt->libtype == program_interpreter) continue; if (tpnt->libtype == elf_executable) continue; if (tpnt->init_flag & INIT_FUNCS_CALLED) continue; tpnt->init_flag |= INIT_FUNCS_CALLED; if (tpnt->dynamic_info[DT_INIT]) { dl_elf_init = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]); (*dl_elf_init) (); } if (tpnt->dynamic_info[DT_FINI]) { atexit((void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI])); } } #endif #ifdef USE_CACHE _dl_unmap_cache(); #endif return (void *) dyn_chain; oops: /* Something went wrong. Clean up and return NULL. */ #ifdef USE_CACHE _dl_unmap_cache(); #endif do_dlclose(dyn_chain, 0); return NULL; }