diff options
-rw-r--r-- | src/dlfcn.c | 186 | ||||
-rw-r--r-- | tests/test.c | 8 |
2 files changed, 140 insertions, 54 deletions
diff --git a/src/dlfcn.c b/src/dlfcn.c index abbd58d..86f24df 100644 --- a/src/dlfcn.c +++ b/src/dlfcn.c | |||
@@ -24,9 +24,6 @@ | |||
24 | * THE SOFTWARE. | 24 | * THE SOFTWARE. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #ifndef _WIN32_WINNT | ||
28 | #define _WIN32_WINNT 0x0501 | ||
29 | #endif | ||
30 | #ifdef _DEBUG | 27 | #ifdef _DEBUG |
31 | #define _CRTDBG_MAP_ALLOC | 28 | #define _CRTDBG_MAP_ALLOC |
32 | #include <stdlib.h> | 29 | #include <stdlib.h> |
@@ -36,13 +33,26 @@ | |||
36 | #include <stdio.h> | 33 | #include <stdio.h> |
37 | #include <stdlib.h> | 34 | #include <stdlib.h> |
38 | 35 | ||
36 | /* Older versions do not have this type */ | ||
37 | #if _WIN32_WINNT < 0x0500 | ||
38 | typedef ULONG ULONG_PTR; | ||
39 | #endif | ||
40 | |||
41 | /* Older SDK versions do not have these macros */ | ||
42 | #ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | ||
43 | #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x4 | ||
44 | #endif | ||
45 | #ifndef GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | ||
46 | #define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 0x2 | ||
47 | #endif | ||
48 | |||
39 | #ifdef _MSC_VER | 49 | #ifdef _MSC_VER |
40 | /* https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress */ | 50 | /* https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress */ |
41 | #pragma intrinsic(_ReturnAddress) | 51 | #pragma intrinsic( _ReturnAddress ) |
42 | #else | 52 | #else |
43 | /* https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html */ | 53 | /* https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html */ |
44 | #ifndef _ReturnAddress | 54 | #ifndef _ReturnAddress |
45 | #define _ReturnAddress() (__builtin_extract_return_addr(__builtin_return_address(0))) | 55 | #define _ReturnAddress( ) ( __builtin_extract_return_addr( __builtin_return_address( 0 ) ) ) |
46 | #endif | 56 | #endif |
47 | #endif | 57 | #endif |
48 | 58 | ||
@@ -51,6 +61,16 @@ | |||
51 | #endif | 61 | #endif |
52 | #include "dlfcn.h" | 62 | #include "dlfcn.h" |
53 | 63 | ||
64 | #if defined( _MSC_VER ) && _MSC_VER >= 1300 | ||
65 | /* https://docs.microsoft.com/en-us/cpp/cpp/noinline */ | ||
66 | #define DLFCN_NOINLINE __declspec( noinline ) | ||
67 | #elif defined( __GNUC__ ) && ( ( __GNUC__ > 3 ) || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 1 ) ) | ||
68 | /* https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html */ | ||
69 | #define DLFCN_NOINLINE __attribute__(( noinline )) | ||
70 | #else | ||
71 | #define DLFCN_NOINLINE | ||
72 | #endif | ||
73 | |||
54 | /* Note: | 74 | /* Note: |
55 | * MSDN says these functions are not thread-safe. We make no efforts to have | 75 | * MSDN says these functions are not thread-safe. We make no efforts to have |
56 | * any kind of thread safety. | 76 | * any kind of thread safety. |
@@ -90,18 +110,15 @@ static BOOL local_add( HMODULE hModule ) | |||
90 | pobject = local_search( hModule ); | 110 | pobject = local_search( hModule ); |
91 | 111 | ||
92 | /* Do not add object again if it's already on the list */ | 112 | /* Do not add object again if it's already on the list */ |
93 | if( pobject ) | 113 | if( pobject != NULL ) |
94 | return TRUE; | 114 | return TRUE; |
95 | 115 | ||
96 | for( pobject = &first_object; pobject->next; pobject = pobject->next ); | 116 | for( pobject = &first_object; pobject->next; pobject = pobject->next ); |
97 | 117 | ||
98 | nobject = (local_object*) malloc( sizeof( local_object ) ); | 118 | nobject = (local_object *) malloc( sizeof( local_object ) ); |
99 | 119 | ||
100 | if( !nobject ) | 120 | if( !nobject ) |
101 | { | ||
102 | SetLastError( ERROR_NOT_ENOUGH_MEMORY ); | ||
103 | return FALSE; | 121 | return FALSE; |
104 | } | ||
105 | 122 | ||
106 | pobject->next = nobject; | 123 | pobject->next = nobject; |
107 | nobject->next = NULL; | 124 | nobject->next = NULL; |
@@ -120,7 +137,7 @@ static void local_rem( HMODULE hModule ) | |||
120 | 137 | ||
121 | pobject = local_search( hModule ); | 138 | pobject = local_search( hModule ); |
122 | 139 | ||
123 | if( !pobject ) | 140 | if( pobject == NULL ) |
124 | return; | 141 | return; |
125 | 142 | ||
126 | if( pobject->next ) | 143 | if( pobject->next ) |
@@ -139,17 +156,11 @@ static void local_rem( HMODULE hModule ) | |||
139 | static char error_buffer[65535]; | 156 | static char error_buffer[65535]; |
140 | static BOOL error_occurred; | 157 | static BOOL error_occurred; |
141 | 158 | ||
142 | static void save_err_str( const char *str ) | 159 | static void save_err_str( const char *str, DWORD dwMessageId ) |
143 | { | 160 | { |
144 | DWORD dwMessageId; | ||
145 | DWORD ret; | 161 | DWORD ret; |
146 | size_t pos, len; | 162 | size_t pos, len; |
147 | 163 | ||
148 | dwMessageId = GetLastError( ); | ||
149 | |||
150 | if( dwMessageId == 0 ) | ||
151 | return; | ||
152 | |||
153 | len = strlen( str ); | 164 | len = strlen( str ); |
154 | if( len > sizeof( error_buffer ) - 5 ) | 165 | if( len > sizeof( error_buffer ) - 5 ) |
155 | len = sizeof( error_buffer ) - 5; | 166 | len = sizeof( error_buffer ) - 5; |
@@ -159,7 +170,7 @@ static void save_err_str( const char *str ) | |||
159 | */ | 170 | */ |
160 | pos = 0; | 171 | pos = 0; |
161 | error_buffer[pos++] = '"'; | 172 | error_buffer[pos++] = '"'; |
162 | memcpy( error_buffer+pos, str, len ); | 173 | memcpy( error_buffer + pos, str, len ); |
163 | pos += len; | 174 | pos += len; |
164 | error_buffer[pos++] = '"'; | 175 | error_buffer[pos++] = '"'; |
165 | error_buffer[pos++] = ':'; | 176 | error_buffer[pos++] = ':'; |
@@ -167,7 +178,7 @@ static void save_err_str( const char *str ) | |||
167 | 178 | ||
168 | ret = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwMessageId, | 179 | ret = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwMessageId, |
169 | MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), | 180 | MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), |
170 | error_buffer+pos, (DWORD) (sizeof(error_buffer)-pos), NULL ); | 181 | error_buffer + pos, (DWORD) ( sizeof( error_buffer ) - pos ), NULL ); |
171 | pos += ret; | 182 | pos += ret; |
172 | 183 | ||
173 | /* When FormatMessageA() fails it returns zero and does not touch buffer | 184 | /* When FormatMessageA() fails it returns zero and does not touch buffer |
@@ -185,7 +196,7 @@ static void save_err_str( const char *str ) | |||
185 | error_occurred = TRUE; | 196 | error_occurred = TRUE; |
186 | } | 197 | } |
187 | 198 | ||
188 | static void save_err_ptr_str( const void *ptr ) | 199 | static void save_err_ptr_str( const void *ptr, DWORD dwMessageId ) |
189 | { | 200 | { |
190 | char ptr_buf[2 + 2 * sizeof( ptr ) + 1]; | 201 | char ptr_buf[2 + 2 * sizeof( ptr ) + 1]; |
191 | char num; | 202 | char num; |
@@ -196,28 +207,91 @@ static void save_err_ptr_str( const void *ptr ) | |||
196 | 207 | ||
197 | for( i = 0; i < 2 * sizeof( ptr ); i++ ) | 208 | for( i = 0; i < 2 * sizeof( ptr ); i++ ) |
198 | { | 209 | { |
199 | num = ( ( (ULONG_PTR) ptr ) >> ( 8 * sizeof( ptr ) - 4 * ( i + 1 ) ) ) & 0xF; | 210 | num = (char) ( ( ( (ULONG_PTR) ptr ) >> ( 8 * sizeof( ptr ) - 4 * ( i + 1 ) ) ) & 0xF ); |
200 | ptr_buf[2+i] = num + ( ( num < 0xA ) ? '0' : ( 'A' - 0xA ) ); | 211 | ptr_buf[2 + i] = num + ( ( num < 0xA ) ? '0' : ( 'A' - 0xA ) ); |
201 | } | 212 | } |
202 | 213 | ||
203 | ptr_buf[2 + 2 * sizeof( ptr )] = 0; | 214 | ptr_buf[2 + 2 * sizeof( ptr )] = 0; |
204 | 215 | ||
205 | save_err_str( ptr_buf ); | 216 | save_err_str( ptr_buf, dwMessageId ); |
217 | } | ||
218 | |||
219 | static HMODULE MyGetModuleHandleFromAddress( void *addr ) | ||
220 | { | ||
221 | static BOOL (WINAPI *GetModuleHandleExAPtr)(DWORD, LPCSTR, HMODULE *) = NULL; | ||
222 | static BOOL failed = FALSE; | ||
223 | HMODULE kernel32; | ||
224 | HMODULE hModule; | ||
225 | MEMORY_BASIC_INFORMATION info; | ||
226 | SIZE_T sLen; | ||
227 | |||
228 | if( !failed && GetModuleHandleExAPtr == NULL ) | ||
229 | { | ||
230 | kernel32 = GetModuleHandleA( "Kernel32.dll" ); | ||
231 | if( kernel32 != NULL ) | ||
232 | GetModuleHandleExAPtr = (BOOL (WINAPI *)(DWORD, LPCSTR, HMODULE *)) GetProcAddress( kernel32, "GetModuleHandleExA" ); | ||
233 | if( GetModuleHandleExAPtr == NULL ) | ||
234 | failed = TRUE; | ||
235 | } | ||
236 | |||
237 | if( !failed ) | ||
238 | { | ||
239 | /* If GetModuleHandleExA is available use it with GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS */ | ||
240 | if( !GetModuleHandleExAPtr( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) addr, &hModule ) ) | ||
241 | return NULL; | ||
242 | } | ||
243 | else | ||
244 | { | ||
245 | /* To get HMODULE from address use undocumented hack from https://stackoverflow.com/a/2396380 | ||
246 | * The HMODULE of a DLL is the same value as the module's base address. | ||
247 | */ | ||
248 | sLen = VirtualQuery( addr, &info, sizeof( info ) ); | ||
249 | if( sLen != sizeof( info ) ) | ||
250 | return NULL; | ||
251 | hModule = (HMODULE) info.AllocationBase; | ||
252 | } | ||
253 | |||
254 | return hModule; | ||
206 | } | 255 | } |
207 | 256 | ||
208 | /* Load Psapi.dll at runtime, this avoids linking caveat */ | 257 | /* Load Psapi.dll at runtime, this avoids linking caveat */ |
209 | static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded ) | 258 | static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded ) |
210 | { | 259 | { |
211 | static BOOL (WINAPI *EnumProcessModulesPtr)(HANDLE, HMODULE *, DWORD, LPDWORD); | 260 | static BOOL (WINAPI *EnumProcessModulesPtr)(HANDLE, HMODULE *, DWORD, LPDWORD) = NULL; |
261 | static BOOL failed = FALSE; | ||
262 | UINT uMode; | ||
212 | HMODULE psapi; | 263 | HMODULE psapi; |
213 | 264 | ||
214 | if( !EnumProcessModulesPtr ) | 265 | if( failed ) |
266 | return FALSE; | ||
267 | |||
268 | if( EnumProcessModulesPtr == NULL ) | ||
215 | { | 269 | { |
216 | psapi = LoadLibraryA( "Psapi.dll" ); | 270 | /* Windows 7 and newer versions have K32EnumProcessModules in Kernel32.dll which is always pre-loaded */ |
217 | if( psapi ) | 271 | psapi = GetModuleHandleA( "Kernel32.dll" ); |
218 | EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) GetProcAddress( psapi, "EnumProcessModules" ); | 272 | if( psapi != NULL ) |
219 | if( !EnumProcessModulesPtr ) | 273 | EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) GetProcAddress( psapi, "K32EnumProcessModules" ); |
220 | return 0; | 274 | |
275 | /* Windows Vista and older version have EnumProcessModules in Psapi.dll which needs to be loaded */ | ||
276 | if( EnumProcessModulesPtr == NULL ) | ||
277 | { | ||
278 | /* Do not let Windows display the critical-error-handler message box */ | ||
279 | uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); | ||
280 | psapi = LoadLibraryA( "Psapi.dll" ); | ||
281 | if( psapi != NULL ) | ||
282 | { | ||
283 | EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) GetProcAddress( psapi, "EnumProcessModules" ); | ||
284 | if( EnumProcessModulesPtr == NULL ) | ||
285 | FreeLibrary( psapi ); | ||
286 | } | ||
287 | SetErrorMode( uMode ); | ||
288 | } | ||
289 | |||
290 | if( EnumProcessModulesPtr == NULL ) | ||
291 | { | ||
292 | failed = TRUE; | ||
293 | return FALSE; | ||
294 | } | ||
221 | } | 295 | } |
222 | 296 | ||
223 | return EnumProcessModulesPtr( hProcess, lphModule, cb, lpcbNeeded ); | 297 | return EnumProcessModulesPtr( hProcess, lphModule, cb, lpcbNeeded ); |
@@ -234,9 +308,9 @@ void *dlopen( const char *file, int mode ) | |||
234 | /* Do not let Windows display the critical-error-handler message box */ | 308 | /* Do not let Windows display the critical-error-handler message box */ |
235 | uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); | 309 | uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); |
236 | 310 | ||
237 | if( file == 0 ) | 311 | if( file == NULL ) |
238 | { | 312 | { |
239 | /* POSIX says that if the value of file is 0, a handle on a global | 313 | /* POSIX says that if the value of file is NULL, a handle on a global |
240 | * symbol object must be provided. That object must be able to access | 314 | * symbol object must be provided. That object must be able to access |
241 | * all symbols from the original program file, and any objects loaded | 315 | * all symbols from the original program file, and any objects loaded |
242 | * with the RTLD_GLOBAL flag. | 316 | * with the RTLD_GLOBAL flag. |
@@ -249,7 +323,7 @@ void *dlopen( const char *file, int mode ) | |||
249 | hModule = GetModuleHandle( NULL ); | 323 | hModule = GetModuleHandle( NULL ); |
250 | 324 | ||
251 | if( !hModule ) | 325 | if( !hModule ) |
252 | save_err_str( "(null)" ); | 326 | save_err_str( "(null)", GetLastError( ) ); |
253 | } | 327 | } |
254 | else | 328 | else |
255 | { | 329 | { |
@@ -262,8 +336,7 @@ void *dlopen( const char *file, int mode ) | |||
262 | 336 | ||
263 | if( len >= sizeof( lpFileName ) ) | 337 | if( len >= sizeof( lpFileName ) ) |
264 | { | 338 | { |
265 | SetLastError( ERROR_FILENAME_EXCED_RANGE ); | 339 | save_err_str( file, ERROR_FILENAME_EXCED_RANGE ); |
266 | save_err_str( file ); | ||
267 | hModule = NULL; | 340 | hModule = NULL; |
268 | } | 341 | } |
269 | else | 342 | else |
@@ -292,7 +365,7 @@ void *dlopen( const char *file, int mode ) | |||
292 | 365 | ||
293 | if( !hModule ) | 366 | if( !hModule ) |
294 | { | 367 | { |
295 | save_err_str( lpFileName ); | 368 | save_err_str( lpFileName, GetLastError( ) ); |
296 | } | 369 | } |
297 | else | 370 | else |
298 | { | 371 | { |
@@ -312,7 +385,7 @@ void *dlopen( const char *file, int mode ) | |||
312 | { | 385 | { |
313 | if( !local_add( hModule ) ) | 386 | if( !local_add( hModule ) ) |
314 | { | 387 | { |
315 | save_err_str( lpFileName ); | 388 | save_err_str( lpFileName, ERROR_NOT_ENOUGH_MEMORY ); |
316 | FreeLibrary( hModule ); | 389 | FreeLibrary( hModule ); |
317 | hModule = NULL; | 390 | hModule = NULL; |
318 | } | 391 | } |
@@ -347,7 +420,7 @@ int dlclose( void *handle ) | |||
347 | if( ret ) | 420 | if( ret ) |
348 | local_rem( hModule ); | 421 | local_rem( hModule ); |
349 | else | 422 | else |
350 | save_err_ptr_str( handle ); | 423 | save_err_ptr_str( handle, GetLastError( ) ); |
351 | 424 | ||
352 | /* dlclose's return value in inverted in relation to FreeLibrary's. */ | 425 | /* dlclose's return value in inverted in relation to FreeLibrary's. */ |
353 | ret = !ret; | 426 | ret = !ret; |
@@ -355,21 +428,21 @@ int dlclose( void *handle ) | |||
355 | return (int) ret; | 428 | return (int) ret; |
356 | } | 429 | } |
357 | 430 | ||
358 | __declspec(noinline) /* Needed for _ReturnAddress() */ | 431 | DLFCN_NOINLINE /* Needed for _ReturnAddress() */ |
359 | DLFCN_EXPORT | 432 | DLFCN_EXPORT |
360 | void *dlsym( void *handle, const char *name ) | 433 | void *dlsym( void *handle, const char *name ) |
361 | { | 434 | { |
362 | FARPROC symbol; | 435 | FARPROC symbol; |
363 | HMODULE hCaller; | 436 | HMODULE hCaller; |
364 | HMODULE hModule; | 437 | HMODULE hModule; |
365 | HANDLE hCurrentProc; | 438 | DWORD dwMessageId; |
366 | 439 | ||
367 | error_occurred = FALSE; | 440 | error_occurred = FALSE; |
368 | 441 | ||
369 | symbol = NULL; | 442 | symbol = NULL; |
370 | hCaller = NULL; | 443 | hCaller = NULL; |
371 | hModule = GetModuleHandle( NULL ); | 444 | hModule = GetModuleHandle( NULL ); |
372 | hCurrentProc = GetCurrentProcess( ); | 445 | dwMessageId = 0; |
373 | 446 | ||
374 | if( handle == RTLD_DEFAULT ) | 447 | if( handle == RTLD_DEFAULT ) |
375 | { | 448 | { |
@@ -387,10 +460,16 @@ void *dlsym( void *handle, const char *name ) | |||
387 | * The next object is the one found upon the application of a load | 460 | * The next object is the one found upon the application of a load |
388 | * order symbol resolution algorithm. To get caller function of dlsym() | 461 | * order symbol resolution algorithm. To get caller function of dlsym() |
389 | * use _ReturnAddress() intrinsic. To get HMODULE of caller function | 462 | * use _ReturnAddress() intrinsic. To get HMODULE of caller function |
390 | * use standard GetModuleHandleExA() function. | 463 | * use MyGetModuleHandleFromAddress() which calls either standard |
464 | * GetModuleHandleExA() function or hack via VirtualQuery(). | ||
391 | */ | 465 | */ |
392 | if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) _ReturnAddress( ), &hCaller ) ) | 466 | hCaller = MyGetModuleHandleFromAddress( _ReturnAddress( ) ); |
467 | |||
468 | if( hCaller == NULL ) | ||
469 | { | ||
470 | dwMessageId = ERROR_INVALID_PARAMETER; | ||
393 | goto end; | 471 | goto end; |
472 | } | ||
394 | } | 473 | } |
395 | 474 | ||
396 | if( handle != RTLD_NEXT ) | 475 | if( handle != RTLD_NEXT ) |
@@ -407,11 +486,14 @@ void *dlsym( void *handle, const char *name ) | |||
407 | 486 | ||
408 | if( hModule == handle || handle == RTLD_NEXT ) | 487 | if( hModule == handle || handle == RTLD_NEXT ) |
409 | { | 488 | { |
489 | HANDLE hCurrentProc; | ||
410 | HMODULE *modules; | 490 | HMODULE *modules; |
411 | DWORD cbNeeded; | 491 | DWORD cbNeeded; |
412 | DWORD dwSize; | 492 | DWORD dwSize; |
413 | size_t i; | 493 | size_t i; |
414 | 494 | ||
495 | hCurrentProc = GetCurrentProcess( ); | ||
496 | |||
415 | /* GetModuleHandle( NULL ) only returns the current program file. So | 497 | /* GetModuleHandle( NULL ) only returns the current program file. So |
416 | * if we want to get ALL loaded module including those in linked DLLs, | 498 | * if we want to get ALL loaded module including those in linked DLLs, |
417 | * we have to use EnumProcessModules( ). | 499 | * we have to use EnumProcessModules( ). |
@@ -447,7 +529,7 @@ void *dlsym( void *handle, const char *name ) | |||
447 | } | 529 | } |
448 | else | 530 | else |
449 | { | 531 | { |
450 | SetLastError( ERROR_NOT_ENOUGH_MEMORY ); | 532 | dwMessageId = ERROR_NOT_ENOUGH_MEMORY; |
451 | goto end; | 533 | goto end; |
452 | } | 534 | } |
453 | } | 535 | } |
@@ -456,9 +538,9 @@ void *dlsym( void *handle, const char *name ) | |||
456 | end: | 538 | end: |
457 | if( symbol == NULL ) | 539 | if( symbol == NULL ) |
458 | { | 540 | { |
459 | if( GetLastError() == 0 ) | 541 | if( !dwMessageId ) |
460 | SetLastError( ERROR_PROC_NOT_FOUND ); | 542 | dwMessageId = ERROR_PROC_NOT_FOUND; |
461 | save_err_str( name ); | 543 | save_err_str( name, dwMessageId ); |
462 | } | 544 | } |
463 | 545 | ||
464 | return *(void **) (&symbol); | 546 | return *(void **) (&symbol); |
@@ -617,7 +699,9 @@ static BOOL fill_info( void *addr, Dl_info *info ) | |||
617 | void *funcAddress = NULL; | 699 | void *funcAddress = NULL; |
618 | 700 | ||
619 | /* Get module of the specified address */ | 701 | /* Get module of the specified address */ |
620 | if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, addr, &hModule ) || hModule == NULL ) | 702 | hModule = MyGetModuleHandleFromAddress( addr ); |
703 | |||
704 | if( hModule == NULL ) | ||
621 | return FALSE; | 705 | return FALSE; |
622 | 706 | ||
623 | dwSize = GetModuleFileNameA( hModule, module_filename, sizeof( module_filename ) ); | 707 | dwSize = GetModuleFileNameA( hModule, module_filename, sizeof( module_filename ) ); |
@@ -655,7 +739,9 @@ int dladdr( void *addr, Dl_info *info ) | |||
655 | HMODULE hModule; | 739 | HMODULE hModule; |
656 | 740 | ||
657 | /* Get module of the import thunk address */ | 741 | /* Get module of the import thunk address */ |
658 | if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, addr, &hModule ) || hModule == NULL ) | 742 | hModule = MyGetModuleHandleFromAddress( addr ); |
743 | |||
744 | if( hModule == NULL ) | ||
659 | return 0; | 745 | return 0; |
660 | 746 | ||
661 | if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) ) | 747 | if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) ) |
diff --git a/tests/test.c b/tests/test.c index 132ede6..1d0d437 100644 --- a/tests/test.c +++ b/tests/test.c | |||
@@ -342,7 +342,7 @@ int main() | |||
342 | *(void **) (&fwrite_local) = dlsym( global, "fwrite" ); | 342 | *(void **) (&fwrite_local) = dlsym( global, "fwrite" ); |
343 | if (!fwrite_local) | 343 | if (!fwrite_local) |
344 | { | 344 | { |
345 | error = dlerror(); | 345 | error = dlerror( ); |
346 | printf("ERROR\tCould not get symbol from global handle: %s\n", | 346 | printf("ERROR\tCould not get symbol from global handle: %s\n", |
347 | error ? error : ""); | 347 | error ? error : ""); |
348 | CLOSE_LIB; | 348 | CLOSE_LIB; |
@@ -360,7 +360,7 @@ int main() | |||
360 | *(void **) (&fputs_default) = dlsym( RTLD_DEFAULT, "fputs" ); | 360 | *(void **) (&fputs_default) = dlsym( RTLD_DEFAULT, "fputs" ); |
361 | if (!fputs_default) | 361 | if (!fputs_default) |
362 | { | 362 | { |
363 | error = dlerror(); | 363 | error = dlerror( ); |
364 | printf("ERROR\tCould not get symbol from default handle: %s\n", | 364 | printf("ERROR\tCould not get symbol from default handle: %s\n", |
365 | error ? error : ""); | 365 | error ? error : ""); |
366 | CLOSE_LIB; | 366 | CLOSE_LIB; |
@@ -623,7 +623,7 @@ int main() | |||
623 | *(void **) (&function) = dlsym( global, "fwrite" ); | 623 | *(void **) (&function) = dlsym( global, "fwrite" ); |
624 | if (!function) | 624 | if (!function) |
625 | { | 625 | { |
626 | error = dlerror(); | 626 | error = dlerror( ); |
627 | printf("ERROR\tCould not get symbol from global handle: %s\n", | 627 | printf("ERROR\tCould not get symbol from global handle: %s\n", |
628 | error ? error : ""); | 628 | error ? error : ""); |
629 | CLOSE_LIB; | 629 | CLOSE_LIB; |
@@ -659,7 +659,7 @@ int main() | |||
659 | *(void **) (&function) = dlsym( global, "function3" ); | 659 | *(void **) (&function) = dlsym( global, "function3" ); |
660 | if (!function) | 660 | if (!function) |
661 | { | 661 | { |
662 | error = dlerror(); | 662 | error = dlerror( ); |
663 | printf("ERROR\tCould not get symbol from global handle: %s\n", | 663 | printf("ERROR\tCould not get symbol from global handle: %s\n", |
664 | error ? error : ""); | 664 | error ? error : ""); |
665 | CLOSE_LIB; | 665 | CLOSE_LIB; |