Back to index

glibc  2.9
loadtest.c
Go to the documentation of this file.
00001 #include <assert.h>
00002 #include <dlfcn.h>
00003 #include <errno.h>
00004 #include <error.h>
00005 #include <mcheck.h>
00006 #include <stdio.h>
00007 #include <stdlib.h>
00008 #include <string.h>
00009 
00010 
00011 /* How many load/unload operations do we do.  */
00012 #define TEST_ROUNDS  1000
00013 
00014 
00015 static struct
00016 {
00017   /* Name of the module.  */
00018   const char *name;
00019   /* The handle.  */
00020   void *handle;
00021 } testobjs[] =
00022 {
00023   { "testobj1.so", NULL },
00024   { "testobj2.so", NULL },
00025   { "testobj3.so", NULL },
00026   { "testobj4.so", NULL },
00027   { "testobj5.so", NULL },
00028   { "testobj6.so", NULL },
00029 };
00030 #define NOBJS (sizeof (testobjs) / sizeof (testobjs[0]))
00031 
00032 
00033 static const struct
00034 {
00035   /* Name of a function to call.  */
00036   const char *fname;
00037   /* Index in status and handle array.  */
00038   int index;
00039   /* Options while loading the module.  */
00040   int options;
00041 } tests[] =
00042 {
00043   { "obj1func2", 0, RTLD_LAZY },
00044   { "obj1func1", 0, RTLD_LAZY | RTLD_GLOBAL },
00045   { "obj1func1", 0, RTLD_NOW, },
00046   { "obj1func2", 0, RTLD_NOW | RTLD_GLOBAL },
00047   { "obj2func2", 1, RTLD_LAZY },
00048   { "obj2func1", 1, RTLD_LAZY | RTLD_GLOBAL, },
00049   { "obj2func1", 1, RTLD_NOW, },
00050   { "obj2func2", 1, RTLD_NOW | RTLD_GLOBAL },
00051   { "obj3func2", 2, RTLD_LAZY },
00052   { "obj3func1", 2, RTLD_LAZY | RTLD_GLOBAL },
00053   { "obj3func1", 2, RTLD_NOW },
00054   { "obj3func2", 2, RTLD_NOW | RTLD_GLOBAL },
00055   { "obj4func2", 3, RTLD_LAZY },
00056   { "obj4func1", 3, RTLD_LAZY | RTLD_GLOBAL },
00057   { "obj4func1", 3, RTLD_NOW },
00058   { "obj4func2", 3, RTLD_NOW | RTLD_GLOBAL },
00059   { "obj5func2", 4, RTLD_LAZY },
00060   { "obj5func1", 4, RTLD_LAZY | RTLD_GLOBAL },
00061   { "obj5func1", 4, RTLD_NOW },
00062   { "obj5func2", 4, RTLD_NOW | RTLD_GLOBAL },
00063   { "obj6func2", 5, RTLD_LAZY },
00064   { "obj6func1", 5, RTLD_LAZY | RTLD_GLOBAL },
00065   { "obj6func1", 5, RTLD_NOW },
00066   { "obj6func2", 5, RTLD_NOW | RTLD_GLOBAL },
00067 };
00068 #define NTESTS       (sizeof (tests) / sizeof (tests[0]))
00069 
00070 
00071 #include <include/link.h>
00072 
00073 #define MAPS ((struct link_map *) _r_debug.r_map)
00074 
00075 #define OUT \
00076   for (map = MAPS; map != NULL; map = map->l_next)                   \
00077     if (map->l_type == lt_loaded)                                    \
00078       printf ("name = \"%s\", direct_opencount = %d\n",                     \
00079              map->l_name, (int) map->l_direct_opencount);                   \
00080   fflush (stdout)
00081 
00082 
00083 int
00084 main (int argc, char *argv[])
00085 {
00086   int debug = argc > 1 && argv[1][0] != '\0';
00087   int count = TEST_ROUNDS;
00088   int result = 0;
00089   struct link_map *map;
00090 
00091   mtrace ();
00092 
00093   /* Just a seed.  */
00094   srandom (TEST_ROUNDS);
00095 
00096   if (debug)
00097     {
00098       puts ("in the beginning");
00099       OUT;
00100     }
00101 
00102   while (count--)
00103     {
00104       int nr = random () % NTESTS;
00105       int index = tests[nr].index;
00106 
00107       printf ("%4d: %4d: ", count + 1, nr);
00108       fflush (stdout);
00109 
00110       if (testobjs[index].handle == NULL)
00111        {
00112          int (*fct) (int);
00113 
00114          /* Load the object.  */
00115          testobjs[index].handle = dlopen (testobjs[index].name,
00116                                       tests[nr].options);
00117          if (testobjs[index].handle == NULL)
00118            error (EXIT_FAILURE, 0, "cannot load `%s': %s",
00119                  testobjs[index].name, dlerror ());
00120 
00121          /* Test the function call.  */
00122          fct = dlsym (testobjs[index].handle, tests[nr].fname);
00123          if (fct == NULL)
00124            error (EXIT_FAILURE, 0,
00125                  "cannot get function `%s' from shared object `%s': %s",
00126                  tests[nr].fname, testobjs[index].name, dlerror ());
00127 
00128          fct (10);
00129 
00130          printf ("successfully loaded `%s', handle %p\n",
00131                 testobjs[index].name, testobjs[index].handle);
00132        }
00133       else
00134        {
00135          if (dlclose (testobjs[index].handle) != 0)
00136            {
00137              printf ("failed to close %s\n", testobjs[index].name);
00138              result = 1;
00139            }
00140          else
00141            printf ("successfully unloaded `%s', handle %p\n",
00142                   testobjs[index].name, testobjs[index].handle);
00143 
00144          testobjs[index].handle = NULL;
00145 
00146          if (testobjs[0].handle == NULL
00147              && testobjs[1].handle == NULL
00148              && testobjs[5].handle == NULL)
00149            {
00150              /* In this case none of the objects above should be
00151                present.  */
00152              for (map = MAPS; map != NULL; map = map->l_next)
00153               if (map->l_type == lt_loaded
00154                   && (strstr (map->l_name, testobjs[0].name) != NULL
00155                      || strstr (map->l_name, testobjs[1].name) != NULL
00156                      || strstr (map->l_name, testobjs[5].name) != NULL))
00157                 {
00158                   printf ("`%s' is still loaded\n", map->l_name);
00159                   result = 1;
00160                 }
00161            }
00162        }
00163 
00164       if (debug)
00165        OUT;
00166     }
00167 
00168   /* Unload all loaded modules.  */
00169   for (count = 0; count < (int) NOBJS; ++count)
00170     if (testobjs[count].handle != NULL)
00171       {
00172        printf ("\nclose: %s: l_initfini = %p, l_versions = %p\n",
00173               testobjs[count].name,
00174               ((struct link_map *) testobjs[count].handle)->l_initfini,
00175               ((struct link_map *) testobjs[count].handle)->l_versions);
00176 
00177        if (dlclose (testobjs[count].handle) != 0)
00178          {
00179            printf ("failed to close %s\n", testobjs[count].name);
00180            result = 1;
00181          }
00182       }
00183 
00184   /* Check whether all files are unloaded.  */
00185   for (map = MAPS; map != NULL; map = map->l_next)
00186     if (map->l_type == lt_loaded)
00187       {
00188        printf ("name = \"%s\", direct_opencount = %d\n",
00189               map->l_name, (int) map->l_direct_opencount);
00190        result = 1;
00191       }
00192 
00193   return result;
00194 }
00195 
00196 
00197 extern int foo (int a);
00198 int
00199 foo (int a)
00200 {
00201   return a - 1;
00202 }