| lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 1 | #include <dlfcn.h> | 
|  | 2 | #include <libintl.h> | 
|  | 3 | #include <link.h> | 
|  | 4 | #include <stdio.h> | 
|  | 5 | #include <stdlib.h> | 
|  | 6 | #include <string.h> | 
|  | 7 |  | 
|  | 8 | #define MAPS ((struct link_map *) _r_debug.r_map) | 
|  | 9 |  | 
|  | 10 | static int | 
|  | 11 | check_loaded_objects (const char **loaded) | 
|  | 12 | { | 
|  | 13 | struct link_map *lm; | 
|  | 14 | int n; | 
|  | 15 | int *found = NULL; | 
|  | 16 | int errors = 0; | 
|  | 17 |  | 
|  | 18 | for (n = 0; loaded[n]; n++) | 
|  | 19 | /* NOTHING */; | 
|  | 20 |  | 
|  | 21 | if (n) | 
|  | 22 | { | 
|  | 23 | found = (int *) alloca (sizeof (int) * n); | 
|  | 24 | memset (found, 0, sizeof (int) * n); | 
|  | 25 | } | 
|  | 26 |  | 
|  | 27 | printf("   Name\n"); | 
|  | 28 | printf(" --------------------------------------------------------\n"); | 
|  | 29 | for (lm = MAPS; lm; lm = lm->l_next) | 
|  | 30 | { | 
|  | 31 | if (lm->l_name && lm->l_name[0]) | 
|  | 32 | printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount); | 
|  | 33 | if (lm->l_type == lt_loaded && lm->l_name) | 
|  | 34 | { | 
|  | 35 | int match = 0; | 
|  | 36 | for (n = 0; loaded[n] != NULL; n++) | 
|  | 37 | { | 
|  | 38 | if (strcmp (basename (loaded[n]), basename (lm->l_name)) == 0) | 
|  | 39 | { | 
|  | 40 | found[n] = 1; | 
|  | 41 | match = 1; | 
|  | 42 | break; | 
|  | 43 | } | 
|  | 44 | } | 
|  | 45 |  | 
|  | 46 | if (match == 0) | 
|  | 47 | { | 
|  | 48 | ++errors; | 
|  | 49 | printf ("ERRORS: %s is not unloaded\n", lm->l_name); | 
|  | 50 | } | 
|  | 51 | } | 
|  | 52 | } | 
|  | 53 |  | 
|  | 54 | for (n = 0; loaded[n] != NULL; n++) | 
|  | 55 | { | 
|  | 56 | if (found[n] == 0) | 
|  | 57 | { | 
|  | 58 | ++errors; | 
|  | 59 | printf ("ERRORS: %s is not loaded\n", loaded[n]); | 
|  | 60 | } | 
|  | 61 | } | 
|  | 62 |  | 
|  | 63 | return errors; | 
|  | 64 | } | 
|  | 65 |  | 
|  | 66 | static int | 
|  | 67 | load_dso (const char **loading, int undef, int flag) | 
|  | 68 | { | 
|  | 69 | void *obj; | 
|  | 70 | const char *loaded[] = { NULL, NULL, NULL, NULL }; | 
|  | 71 | int errors = 0; | 
|  | 72 | const char *errstring; | 
|  | 73 |  | 
|  | 74 | printf ("\nThis is what is in memory now:\n"); | 
|  | 75 | errors += check_loaded_objects (loaded); | 
|  | 76 |  | 
|  | 77 | printf ("Loading shared object %s: %s\n", loading[0], | 
|  | 78 | flag == RTLD_LAZY ? "RTLD_LAZY" : "RTLD_NOW"); | 
|  | 79 | obj = dlopen (loading[0], flag); | 
|  | 80 | if (obj == NULL) | 
|  | 81 | { | 
|  | 82 | if (flag == RTLD_LAZY) | 
|  | 83 | { | 
|  | 84 | ++errors; | 
|  | 85 | printf ("ERRORS: dlopen shouldn't fail for RTLD_LAZY\n"); | 
|  | 86 | } | 
|  | 87 |  | 
|  | 88 | errstring = dlerror (); | 
|  | 89 | if (strstr (errstring, "undefined symbol") == 0 | 
|  | 90 | || strstr (errstring, "circlemod2_undefined") == 0) | 
|  | 91 | { | 
|  | 92 | ++errors; | 
|  | 93 | printf ("ERRORS: dlopen: `%s': Invalid error string\n", | 
|  | 94 | errstring); | 
|  | 95 | } | 
|  | 96 | else | 
|  | 97 | printf ("dlopen: %s\n", errstring); | 
|  | 98 | } | 
|  | 99 | else | 
|  | 100 | { | 
|  | 101 | if (undef && flag == RTLD_NOW) | 
|  | 102 | { | 
|  | 103 | ++errors; | 
|  | 104 | printf ("ERRORS: dlopen shouldn't work for RTLD_NOW\n"); | 
|  | 105 | } | 
|  | 106 |  | 
|  | 107 | if (!undef) | 
|  | 108 | { | 
|  | 109 | int (*func) (void); | 
|  | 110 |  | 
|  | 111 | func = dlsym (obj, "circlemod1"); | 
|  | 112 | if (func == NULL) | 
|  | 113 | { | 
|  | 114 | ++errors; | 
|  | 115 | printf ("ERRORS: cannot get address of \"circlemod1\": %s\n", | 
|  | 116 | dlerror ()); | 
|  | 117 | } | 
|  | 118 | else if (func () != 3) | 
|  | 119 | { | 
|  | 120 | ++errors; | 
|  | 121 | printf ("ERRORS: function \"circlemod1\" returned wrong result\n"); | 
|  | 122 | } | 
|  | 123 | } | 
|  | 124 |  | 
|  | 125 | loaded[0] = loading[0]; | 
|  | 126 | loaded[1] = loading[1]; | 
|  | 127 | loaded[2] = loading[2]; | 
|  | 128 | } | 
|  | 129 | errors += check_loaded_objects (loaded); | 
|  | 130 |  | 
|  | 131 | if (obj) | 
|  | 132 | { | 
|  | 133 | printf ("UnLoading shared object %s\n", loading[0]); | 
|  | 134 | dlclose (obj); | 
|  | 135 | loaded[0] = NULL; | 
|  | 136 | loaded[1] = NULL; | 
|  | 137 | loaded[2] = NULL; | 
|  | 138 | errors += check_loaded_objects (loaded); | 
|  | 139 | } | 
|  | 140 |  | 
|  | 141 | return errors; | 
|  | 142 | } | 
|  | 143 |  | 
|  | 144 | int | 
|  | 145 | main (void) | 
|  | 146 | { | 
|  | 147 | int errors = 0; | 
|  | 148 | const char *loading[3]; | 
|  | 149 |  | 
|  | 150 | loading[0] = "circlemod1a.so"; | 
|  | 151 | loading[1] = "circlemod2a.so"; | 
|  | 152 | loading[2] = "circlemod3a.so"; | 
|  | 153 | errors += load_dso (loading, 0, RTLD_LAZY); | 
|  | 154 | errors += load_dso (loading, 0, RTLD_NOW); | 
|  | 155 |  | 
|  | 156 | loading[0] = "circlemod1.so"; | 
|  | 157 | loading[1] = "circlemod2.so"; | 
|  | 158 | loading[2] = "circlemod3.so"; | 
|  | 159 | errors += load_dso (loading, 1, RTLD_LAZY); | 
|  | 160 | errors += load_dso (loading, 1, RTLD_NOW); | 
|  | 161 |  | 
|  | 162 | if (errors != 0) | 
|  | 163 | printf ("%d errors found\n", errors); | 
|  | 164 |  | 
|  | 165 | return errors; | 
|  | 166 | } |