aboutsummaryrefslogtreecommitdiff
path: root/test.c
diff options
context:
space:
mode:
authorPali Rohár <pali.rohar@gmail.com>2019-01-29 22:38:42 +0100
committerPali Rohár <pali.rohar@gmail.com>2019-02-14 09:25:21 +0100
commit29c46a54ffa31513be1a2cdcd9e8a55938d6e549 (patch)
tree1aca7d982c3ddd9262e7bad702099a25c3ac2f84 /test.c
parent1530bed62922128ed0c2cdc436a55649ff9423fe (diff)
downloaddlfcn-win32-29c46a54ffa31513be1a2cdcd9e8a55938d6e549.tar.gz
dlfcn-win32-29c46a54ffa31513be1a2cdcd9e8a55938d6e549.tar.bz2
dlfcn-win32-29c46a54ffa31513be1a2cdcd9e8a55938d6e549.zip
Fix resolving global symbols when LoadLibrary() is called after dlopen()
Usage of first_automatic_object cache is wrong. This cache is filled by all loaded DLL files (either implicitly or explicitly with LoadLibrary() call) by EnumProcessModules() call at first usage of dlopen(). So dlsym() can resolve global symbols only if they were loaded prior to dlopen() call. Any future usage of LoadLibrary() does not include newly loaded DLLs into first_automatic_object cache. To fix this problem, first_automatic_object cache is fully removed and EnumProcessModules() call is issued directly in dlsym() call. As EnumProcessModules() returns all DLLs, included those which were loaded by dlopen() with RTLD_LOCAL, it may break RTLD_LOCAL support. To address this problem switch linked-list of all loaded DLLs with RTLD_GLOBAL to linked-list of all loaded DLLs with RTLD_LOCAL flag. And then skip modules from EnumProcessModules() which are in linked-list. Also in WinAPI all DLLs loaded by LoadLibrary() behaves like RTLD_GLOBAL. So above change is compatible with this behavior. There may be another problem. Before retrieving HMODULE for DLL filename (which is done by LoadLibrary()), it is not possible to detect if DLL was already loaded by RTLD_LOCAL or not. And after calling LoadLibrary() it is not possible to know if DLL was loaded either by dlsym() with RTLD_LOCAL or by LoadLibrary() (which is equivalent to RTLD_GLOBAL). To address this problem, compare number of loaded modules (counted by EnumProcessModules()) before and after LoadLibrary() called from dlsym(). If number does not change it means that DLL was already loaded. So based on this result either add or remove HMODULE from linked-list of RTLD_LOCAL modules. Added test demonstrate usage of: global = dlopen(NULL, RTLD_GLOBAL); /* global handle */ LoadLibrary("library.dll"); /* this provides function */ function = dlsym(global, "function"); /* resolve function from library.dll */
Diffstat (limited to 'test.c')
-rw-r--r--test.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/test.c b/test.c
index ba440da..10c655e 100644
--- a/test.c
+++ b/test.c
@@ -2,6 +2,7 @@
2 * dlfcn-win32 2 * dlfcn-win32
3 * Copyright (c) 2007-2009 Ramiro Polla 3 * Copyright (c) 2007-2009 Ramiro Polla
4 * Copyright (c) 2014 Tiancheng "Timothy" Gu 4 * Copyright (c) 2014 Tiancheng "Timothy" Gu
5 * Copyright (c) 2019 Pali Rohár <pali.rohar@gmail.com>
5 * 6 *
6 * dlfcn-win32 is free software; you can redistribute it and/or 7 * dlfcn-win32 is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public 8 * modify it under the terms of the GNU Lesser General Public
@@ -25,6 +26,7 @@
25#endif 26#endif
26#include <stdio.h> 27#include <stdio.h>
27#include <string.h> 28#include <string.h>
29#include <windows.h>
28#include "dlfcn.h" 30#include "dlfcn.h"
29 31
30/* If these dlclose's fails, we don't care as the handles are going to be 32/* If these dlclose's fails, we don't care as the handles are going to be
@@ -77,6 +79,7 @@ int main()
77 size_t (*fwrite_local) ( const void *, size_t, size_t, FILE * ); 79 size_t (*fwrite_local) ( const void *, size_t, size_t, FILE * );
78 int (*nonexistentfunction)( void ); 80 int (*nonexistentfunction)( void );
79 int ret; 81 int ret;
82 HMODULE library3;
80 83
81#ifdef _DEBUG 84#ifdef _DEBUG
82 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); 85 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
@@ -335,6 +338,15 @@ int main()
335 printf("SUCCESS\tGot symbol from global handle: %p\n", function); 338 printf("SUCCESS\tGot symbol from global handle: %p\n", function);
336 339
337 340
341 library3 = LoadLibraryA("testdll3.dll");
342 if (!library3)
343 {
344 printf( "ERROR\tCould not open library3 via WINAPI\n" );
345 RETURN_ERROR;
346 }
347 else
348 printf( "SUCCESS\tOpened library3 via WINAPI: %p\n", library3 );
349
338 ret = dlclose( library ); 350 ret = dlclose( library );
339 if( ret ) 351 if( ret )
340 { 352 {
@@ -346,6 +358,21 @@ int main()
346 else 358 else
347 printf( "SUCCESS\tClosed library.\n" ); 359 printf( "SUCCESS\tClosed library.\n" );
348 360
361 function = dlsym(global, "function3");
362 if (!function)
363 {
364 error = dlerror();
365 printf("ERROR\tCould not get symbol from global handle: %s\n",
366 error ? error : "");
367 CLOSE_LIB;
368 CLOSE_GLOBAL;
369 RETURN_ERROR;
370 }
371 else
372 printf("SUCCESS\tGot symbol from global handle: %p\n", function);
373
374 RUNFUNC;
375
349 ret = dlclose( global ); 376 ret = dlclose( global );
350 if( ret ) 377 if( ret )
351 { 378 {