| /* Test for unloading (really unmapping) of objects.  By Franz Sirl. | 
 |    This test does not have to passed in all dlopen() et.al. implementation | 
 |    since it is not required the unloading actually happens.  But we | 
 |    require it for glibc.  */ | 
 |  | 
 | #include <dlfcn.h> | 
 | #include <link.h> | 
 | #include <mcheck.h> | 
 | #include <stdio.h> | 
 | #include <stdlib.h> | 
 |  | 
 | #define MAPS ((struct link_map *) _r_debug.r_map) | 
 |  | 
 | #define OUT \ | 
 |   for (map = MAPS; map != NULL; map = map->l_next)			      \ | 
 |     if (map->l_type == lt_loaded)					      \ | 
 |       printf ("name = \"%s\", direct_opencount = %d\n",			      \ | 
 | 	      map->l_name, (int) map->l_direct_opencount);		      \ | 
 |   fflush (stdout) | 
 |  | 
 | typedef struct | 
 | { | 
 |   void *next; | 
 | } strct; | 
 |  | 
 | int | 
 | main (void) | 
 | { | 
 |    void *sohandle; | 
 |    strct *testdat; | 
 |    int ret; | 
 |    int result = 0; | 
 |    struct link_map *map; | 
 |  | 
 |    mtrace (); | 
 |  | 
 |    puts ("\nBefore"); | 
 |    OUT; | 
 |  | 
 |    sohandle = dlopen ("unloadmod.so", RTLD_NOW | RTLD_GLOBAL); | 
 |    if (sohandle == NULL) | 
 |      { | 
 |        printf ("*** first dlopen failed: %s\n", dlerror ()); | 
 |        exit (1); | 
 |      } | 
 |  | 
 |    puts ("\nAfter loading unloadmod.so"); | 
 |    OUT; | 
 |  | 
 |    testdat = dlsym (sohandle, "testdat"); | 
 |    testdat->next = (void *) -1; | 
 |  | 
 |    ret = dlclose (sohandle); | 
 |    if (ret != 0) | 
 |      { | 
 |        puts ("*** first dlclose failed"); | 
 |        result = 1; | 
 |      } | 
 |  | 
 |    puts ("\nAfter closing unloadmod.so"); | 
 |    OUT; | 
 |  | 
 |    sohandle = dlopen ("unloadmod.so", RTLD_NOW | RTLD_GLOBAL); | 
 |    if (sohandle == NULL) | 
 |      { | 
 |        printf ("*** second dlopen failed: %s\n", dlerror ()); | 
 |        exit (1); | 
 |      } | 
 |  | 
 |    puts ("\nAfter loading unloadmod.so the second time"); | 
 |    OUT; | 
 |  | 
 |    testdat = dlsym (sohandle, "testdat"); | 
 |    if (testdat->next == (void *) -1) | 
 |      { | 
 |        puts ("*** testdat->next == (void *) -1"); | 
 |        result = 1; | 
 |      } | 
 |  | 
 |    ret = dlclose (sohandle); | 
 |    if (ret != 0) | 
 |      { | 
 |        puts ("*** second dlclose failed"); | 
 |        result = 1; | 
 |      } | 
 |  | 
 |    puts ("\nAfter closing unloadmod.so again"); | 
 |    OUT; | 
 |  | 
 |    return result; | 
 | } |