diff options
author | Pali Rohár <pali.rohar@gmail.com> | 2021-02-03 20:59:58 +0100 |
---|---|---|
committer | Pali Rohár <pali.rohar@gmail.com> | 2021-02-03 20:59:58 +0100 |
commit | 06fea3fe8b3efe8c79f97fa724f703bc0e25aeef (patch) | |
tree | 76242f5a02117496107898597b904f1ea67de297 /src | |
parent | 0e9d85a9d03bcedade35cced63ec6b969ab3451e (diff) | |
download | dlfcn-win32-06fea3fe8b3efe8c79f97fa724f703bc0e25aeef.tar.gz dlfcn-win32-06fea3fe8b3efe8c79f97fa724f703bc0e25aeef.tar.bz2 dlfcn-win32-06fea3fe8b3efe8c79f97fa724f703bc0e25aeef.zip |
Add helper function MyGetModuleHandleFromAddress()
This function implements calling GetModuleHandleExA() with correct flags to
retrieve hModule from passed address.
To allow compilation also with older compilers and environments (like WDK)
with any _WIN32_WINNT value, retrieve pointer to this function via
GetProcAddress(). And as a fallback implementation use old code via
VirtualQuery() which was there prior commit 8ec5ffef2eca.
Diffstat (limited to 'src')
-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 ) ) |