/* We run this if we debug the memory allocation. */ static void __libc_freeres_fn_section do_release_all (void *nodep) { struct __gconv_loaded_object *obj = (struct __gconv_loaded_object *) nodep; /* Unload the shared object. */ if (obj->handle != NULL) __libc_dlclose (obj->handle); free (obj); }
void __libc_freeres_fn_section __unwind_freeres (void) { void *handle = libgcc_s_handle; if (handle != NULL) { libgcc_s_handle = NULL; __libc_dlclose (handle); } }
int main(int argc, char **argv) { void *handle; double (*puts)(char *); char *error; handle = __libc_dlopen_mode("libc.so.6", RTLD_LAZY); if (!handle) { exit(1); } puts = __libc_dlsym(handle, "puts"); (*puts)("Hello World"); __libc_dlclose(handle); }
free_mem (void) { name_database *top = service_table; name_database_entry *entry; service_library *library; if (top == NULL) /* Maybe we have not read the nsswitch.conf file. */ return; /* Don't disturb ongoing other threads (if there are any). */ service_table = NULL; entry = top->entry; while (entry != NULL) { name_database_entry *olde = entry; service_user *service = entry->service; while (service != NULL) { service_user *olds = service; if (service->known != NULL) __tdestroy (service->known, free); service = service->next; free (olds); } entry = entry->next; free (olde); } library = top->library; while (library != NULL) { service_library *oldl = library; __libc_dlclose (library->lib_handle); library = library->next; free (oldl); } free (top); }
static void init (void) { libgcc_handle = __libc_dlopen ("libgcc_s.so.2"); if (libgcc_handle == NULL) return; unwind_backtrace = __libc_dlsym (libgcc_handle, "_Unwind_Backtrace"); unwind_getip = __libc_dlsym (libgcc_handle, "_Unwind_GetIP"); unwind_getcfa = __libc_dlsym (libgcc_handle, "_Unwind_GetCFA"); unwind_getgr = __libc_dlsym (libgcc_handle, "_Unwind_GetGR"); if (unwind_getip == NULL || unwind_getgr == NULL || unwind_getcfa == NULL) { unwind_backtrace = NULL; __libc_dlclose (libgcc_handle); libgcc_handle = NULL; } }
static void do_release_shlib (void *nodep, VISIT value, int level) { struct __gconv_loaded_object *obj = *(struct __gconv_loaded_object **) nodep; if (value != preorder && value != leaf) return; if (obj == release_handle) { /* This is the object we want to unload. Now decrement the reference counter. */ assert (obj->counter > 0); --obj->counter; } else if (obj->counter <= 0 && obj->counter >= -TRIES_BEFORE_UNLOAD && --obj->counter < -TRIES_BEFORE_UNLOAD && obj->handle != NULL) { /* Unload the shared object. */ __libc_dlclose (obj->handle); obj->handle = NULL; } }
void * threadfunc (void * arg) { printf ("in threadfunc\n"); void * handle = __libc_dlopen_mode ("./test_unload.so", RTLD_LAZY | 0x80000000); printf ("dlopen ok handle: %p\n", handle); void (*pfn_shared_method)(void) = __libc_dlsym(handle, "shared_method"); printf ("before func\n"); pfn_shared_method (); printf ("after func\n"); printf ("about to dlclose handle: %p\n", handle); __libc_dlclose (handle); printf ("done dlclose\n"); while (!stopping) sleep (1); printf ("leaving threadfunc\n"); stopped = 1; }