diff options
-rw-r--r-- | src/dlfcn.c | 64 |
1 files changed, 57 insertions, 7 deletions
diff --git a/src/dlfcn.c b/src/dlfcn.c index 4e4e10e..80bd119 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,6 +33,14 @@ | |||
36 | #include <stdio.h> | 33 | #include <stdio.h> |
37 | #include <stdlib.h> | 34 | #include <stdlib.h> |
38 | 35 | ||
36 | /* Older SDK versions do not have these macros */ | ||
37 | #ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | ||
38 | #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x4 | ||
39 | #endif | ||
40 | #ifndef GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | ||
41 | #define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 0x2 | ||
42 | #endif | ||
43 | |||
39 | #ifdef _MSC_VER | 44 | #ifdef _MSC_VER |
40 | /* https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress */ | 45 | /* https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress */ |
41 | #pragma intrinsic( _ReturnAddress ) | 46 | #pragma intrinsic( _ReturnAddress ) |
@@ -196,6 +201,44 @@ static void save_err_ptr_str( const void *ptr, DWORD dwMessageId ) | |||
196 | save_err_str( ptr_buf, dwMessageId ); | 201 | save_err_str( ptr_buf, dwMessageId ); |
197 | } | 202 | } |
198 | 203 | ||
204 | static HMODULE MyGetModuleHandleFromAddress( void *addr ) | ||
205 | { | ||
206 | static BOOL (WINAPI *GetModuleHandleExAPtr)(DWORD, LPCSTR, HMODULE *) = NULL; | ||
207 | static BOOL failed = FALSE; | ||
208 | HMODULE kernel32; | ||
209 | HMODULE hModule; | ||
210 | MEMORY_BASIC_INFORMATION info; | ||
211 | SIZE_T sLen; | ||
212 | |||
213 | if( !failed && GetModuleHandleExAPtr == NULL ) | ||
214 | { | ||
215 | kernel32 = GetModuleHandleA( "Kernel32.dll" ); | ||
216 | if( kernel32 != NULL ) | ||
217 | GetModuleHandleExAPtr = (BOOL (WINAPI *)(DWORD, LPCSTR, HMODULE *)) GetProcAddress( kernel32, "GetModuleHandleExA" ); | ||
218 | if( GetModuleHandleExAPtr == NULL ) | ||
219 | failed = TRUE; | ||
220 | } | ||
221 | |||
222 | if( !failed ) | ||
223 | { | ||
224 | /* If GetModuleHandleExA is available use it with GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS */ | ||
225 | if( !GetModuleHandleExAPtr( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) addr, &hModule ) ) | ||
226 | return NULL; | ||
227 | } | ||
228 | else | ||
229 | { | ||
230 | /* To get HMODULE from address use undocumented hack from https://stackoverflow.com/a/2396380 | ||
231 | * The HMODULE of a DLL is the same value as the module's base address. | ||
232 | */ | ||
233 | sLen = VirtualQuery( addr, &info, sizeof( info ) ); | ||
234 | if( sLen != sizeof( info ) ) | ||
235 | return NULL; | ||
236 | hModule = (HMODULE) info.AllocationBase; | ||
237 | } | ||
238 | |||
239 | return hModule; | ||
240 | } | ||
241 | |||
199 | /* Load Psapi.dll at runtime, this avoids linking caveat */ | 242 | /* Load Psapi.dll at runtime, this avoids linking caveat */ |
200 | static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded ) | 243 | static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded ) |
201 | { | 244 | { |
@@ -402,9 +445,12 @@ void *dlsym( void *handle, const char *name ) | |||
402 | * The next object is the one found upon the application of a load | 445 | * The next object is the one found upon the application of a load |
403 | * order symbol resolution algorithm. To get caller function of dlsym() | 446 | * order symbol resolution algorithm. To get caller function of dlsym() |
404 | * use _ReturnAddress() intrinsic. To get HMODULE of caller function | 447 | * use _ReturnAddress() intrinsic. To get HMODULE of caller function |
405 | * use standard GetModuleHandleExA() function. | 448 | * use MyGetModuleHandleFromAddress() which calls either standard |
449 | * GetModuleHandleExA() function or hack via VirtualQuery(). | ||
406 | */ | 450 | */ |
407 | if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) _ReturnAddress( ), &hCaller ) ) | 451 | hCaller = MyGetModuleHandleFromAddress( _ReturnAddress( ) ); |
452 | |||
453 | if( hCaller == NULL ) | ||
408 | { | 454 | { |
409 | dwMessageId = ERROR_INVALID_PARAMETER; | 455 | dwMessageId = ERROR_INVALID_PARAMETER; |
410 | goto end; | 456 | goto end; |
@@ -638,7 +684,9 @@ static BOOL fill_info( void *addr, Dl_info *info ) | |||
638 | void *funcAddress = NULL; | 684 | void *funcAddress = NULL; |
639 | 685 | ||
640 | /* Get module of the specified address */ | 686 | /* Get module of the specified address */ |
641 | if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, addr, &hModule ) || hModule == NULL ) | 687 | hModule = MyGetModuleHandleFromAddress( addr ); |
688 | |||
689 | if( hModule == NULL ) | ||
642 | return FALSE; | 690 | return FALSE; |
643 | 691 | ||
644 | dwSize = GetModuleFileNameA( hModule, module_filename, sizeof( module_filename ) ); | 692 | dwSize = GetModuleFileNameA( hModule, module_filename, sizeof( module_filename ) ); |
@@ -676,7 +724,9 @@ int dladdr( void *addr, Dl_info *info ) | |||
676 | HMODULE hModule; | 724 | HMODULE hModule; |
677 | 725 | ||
678 | /* Get module of the import thunk address */ | 726 | /* Get module of the import thunk address */ |
679 | if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, addr, &hModule ) || hModule == NULL ) | 727 | hModule = MyGetModuleHandleFromAddress( addr ); |
728 | |||
729 | if( hModule == NULL ) | ||
680 | return 0; | 730 | return 0; |
681 | 731 | ||
682 | if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) ) | 732 | if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) ) |