Use double linked list instead of static array of 255 global objects.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
diff --git a/dlfcn.c b/dlfcn.c
index 4c82304..f0efc22 100644
--- a/dlfcn.c
+++ b/dlfcn.c
@@ -27,43 +27,76 @@
* any kind of thread safety.
*/
-/* I have no special reason to have set MAX_GLOBAL_OBJECTS to this value. Any
- * comments are welcome.
- */
-#define MAX_OBJECTS 255
+typedef struct global_object {
+ HMODULE hModule;
+ struct global_object *previous;
+ struct global_object *next;
+} global_object;
-static HMODULE global_objects[MAX_OBJECTS];
+static global_object first_object;
-/* This function adds an object to the list of global objects.
- * The implementation is very simple and slow.
- * TODO: should failing this function be enough to fail the call to dlopen( )?
- */
-static void global_object_add( HMODULE hModule )
+/* These functions implement a double linked list for the global objects. */
+static global_object *global_search( HMODULE hModule )
{
- int i;
+ global_object *pobject;
- for( i = 0 ; i < MAX_OBJECTS ; i++ )
- {
- if( !global_objects[i] )
- {
- global_objects[i] = hModule;
- break;
- }
- }
+ if( hModule == NULL )
+ return NULL;
+
+ for( pobject = &first_object; pobject ; pobject = pobject->next )
+ if( pobject->hModule == hModule )
+ return pobject;
+
+ return NULL;
}
-static void global_object_rem( HMODULE hModule )
+static void global_add( HMODULE hModule )
{
- int i;
+ global_object *pobject;
+ global_object *nobject;
- for( i = 0 ; i < MAX_OBJECTS ; i++ )
- {
- if( global_objects[i] == hModule )
- {
- global_objects[i] = 0;
- break;
- }
- }
+ if( hModule == NULL )
+ return;
+
+ pobject = global_search( hModule );
+
+ /* Do not add object again if it's already on the list */
+ if( pobject )
+ return;
+
+ for( pobject = &first_object; pobject->next ; pobject = pobject->next );
+
+ nobject = malloc( sizeof(global_object) );
+
+ /* Should this be enough to fail global_add, and therefore also fail
+ * dlopen?
+ */
+ if( !nobject )
+ return;
+
+ pobject->next = nobject;
+ nobject->previous = pobject;
+ nobject->hModule = hModule;
+}
+
+static void global_rem( HMODULE hModule )
+{
+ global_object *pobject;
+
+ if( hModule == NULL )
+ return;
+
+ pobject = global_search( hModule );
+
+ if( !pobject )
+ return;
+
+ if( pobject->next )
+ pobject->next->previous = pobject->previous;
+ if( pobject->previous )
+ pobject->previous->next = pobject->next;
+
+ free( pobject );
}
/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one
@@ -191,7 +224,7 @@ void *dlopen( const char *file, int mode )
if( !hModule )
save_err_str( lpFileName );
else if( (mode & RTLD_GLOBAL) )
- global_object_add( hModule );
+ global_add( hModule );
}
/* Return to previous state of the error-mode bit flags. */
@@ -213,7 +246,7 @@ int dlclose( void *handle )
* objects.
*/
if( ret )
- global_object_rem( hModule );
+ global_rem( hModule );
else
save_err_ptr( handle );
@@ -243,13 +276,13 @@ void *dlsym( void *handle, const char *name )
if( hModule == handle )
{
- int i;
+ global_object *pobject;
- for( i = 0 ; i < MAX_OBJECTS ; i++ )
+ for( pobject = &first_object; pobject ; pobject = pobject->next )
{
- if( global_objects[i] != 0 )
+ if( pobject->hModule )
{
- symbol = GetProcAddress( global_objects[i], name );
+ symbol = GetProcAddress( pobject->hModule, name );
if( symbol != NULL )
break;
}