diff options
author | Silvio Traversaro <silvio@traversaro.it> | 2025-05-03 12:27:40 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-03 12:27:40 +0200 |
commit | 8bfddb5aa345ce10ba98e925acbc7bfb53639679 (patch) | |
tree | 43c768ea57ebe87edb35aeb7f71e7a90efc7bc92 /src | |
parent | 3b52e651f385df00045dd8966407fd9de57fc94b (diff) | |
parent | 7989e4dc4fa1dc31b4c353c72b092209a773c78f (diff) | |
download | dlfcn-win32-master.tar.gz dlfcn-win32-master.tar.bz2 dlfcn-win32-master.zip |
Remove use of CRT, fix gcc compilation in C++ mode, fix missing includes and fix warnings
Diffstat (limited to 'src')
-rw-r--r-- | src/dlfcn.c | 132 |
1 files changed, 83 insertions, 49 deletions
diff --git a/src/dlfcn.c b/src/dlfcn.c index cb9f9bb..1830b20 100644 --- a/src/dlfcn.c +++ b/src/dlfcn.c | |||
@@ -26,12 +26,10 @@ | |||
26 | 26 | ||
27 | #ifdef _DEBUG | 27 | #ifdef _DEBUG |
28 | #define _CRTDBG_MAP_ALLOC | 28 | #define _CRTDBG_MAP_ALLOC |
29 | #include <stdlib.h> | 29 | #include <stdlib.h> /* malloc() and free() */ |
30 | #include <crtdbg.h> | 30 | #include <crtdbg.h> |
31 | #endif | 31 | #endif |
32 | #include <windows.h> | 32 | #include <windows.h> |
33 | #include <stdio.h> | ||
34 | #include <stdlib.h> | ||
35 | 33 | ||
36 | /* Older versions do not have this type */ | 34 | /* Older versions do not have this type */ |
37 | #if _WIN32_WINNT < 0x0500 | 35 | #if _WIN32_WINNT < 0x0500 |
@@ -61,7 +59,12 @@ typedef ULONG ULONG_PTR; | |||
61 | 59 | ||
62 | #ifdef _MSC_VER | 60 | #ifdef _MSC_VER |
63 | #if _MSC_VER >= 1000 | 61 | #if _MSC_VER >= 1000 |
64 | /* https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress */ | 62 | /* https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress |
63 | * When compiling in C++ mode, it is required to have C declaration for _ReturnAddress. | ||
64 | */ | ||
65 | #ifdef __cplusplus | ||
66 | extern "C" void *_ReturnAddress(void); | ||
67 | #endif | ||
65 | #pragma intrinsic( _ReturnAddress ) | 68 | #pragma intrinsic( _ReturnAddress ) |
66 | #else | 69 | #else |
67 | /* On older version read return address from the value on stack pointer + 4 of | 70 | /* On older version read return address from the value on stack pointer + 4 of |
@@ -70,7 +73,11 @@ typedef ULONG ULONG_PTR; | |||
70 | * EBP register optimization. Read value of EBP + 4 via inline assembly. And | 73 | * EBP register optimization. Read value of EBP + 4 via inline assembly. And |
71 | * because inline assembly does not have a return value, put it into naked | 74 | * because inline assembly does not have a return value, put it into naked |
72 | * function which does not have prologue and epilogue and preserve registers. | 75 | * function which does not have prologue and epilogue and preserve registers. |
76 | * When compiling in C++ mode, it is required to have C declaration for _alloca. | ||
73 | */ | 77 | */ |
78 | #ifdef __cplusplus | ||
79 | extern "C" void *__cdecl _alloca(size_t); | ||
80 | #endif | ||
74 | __declspec( naked ) static void *_ReturnAddress( void ) { __asm mov eax, [ebp+4] __asm ret } | 81 | __declspec( naked ) static void *_ReturnAddress( void ) { __asm mov eax, [ebp+4] __asm ret } |
75 | #define _ReturnAddress( ) ( _alloca(1), _ReturnAddress( ) ) | 82 | #define _ReturnAddress( ) ( _alloca(1), _ReturnAddress( ) ) |
76 | #endif | 83 | #endif |
@@ -96,6 +103,24 @@ __declspec( naked ) static void *_ReturnAddress( void ) { __asm mov eax, [ebp+4] | |||
96 | #define DLFCN_NOINLINE | 103 | #define DLFCN_NOINLINE |
97 | #endif | 104 | #endif |
98 | 105 | ||
106 | static void *MyAlloc( size_t size ) | ||
107 | { | ||
108 | #ifdef _DEBUG | ||
109 | return malloc( size ); | ||
110 | #else | ||
111 | return LocalAlloc( LPTR, size ); | ||
112 | #endif | ||
113 | } | ||
114 | |||
115 | static void MyFree( void *ptr ) | ||
116 | { | ||
117 | #ifdef _DEBUG | ||
118 | free( ptr ); | ||
119 | #else | ||
120 | LocalFree( ptr ); | ||
121 | #endif | ||
122 | } | ||
123 | |||
99 | /* Note: | 124 | /* Note: |
100 | * MSDN says these functions are not thread-safe. We make no efforts to have | 125 | * MSDN says these functions are not thread-safe. We make no efforts to have |
101 | * any kind of thread safety. | 126 | * any kind of thread safety. |
@@ -140,7 +165,7 @@ static BOOL local_add( HMODULE hModule ) | |||
140 | 165 | ||
141 | for( pobject = &first_object; pobject->next; pobject = pobject->next ); | 166 | for( pobject = &first_object; pobject->next; pobject = pobject->next ); |
142 | 167 | ||
143 | nobject = (local_object *) malloc( sizeof( local_object ) ); | 168 | nobject = (local_object *) MyAlloc( sizeof( local_object ) ); |
144 | 169 | ||
145 | if( !nobject ) | 170 | if( !nobject ) |
146 | return FALSE; | 171 | return FALSE; |
@@ -170,7 +195,7 @@ static void local_rem( HMODULE hModule ) | |||
170 | if( pobject->previous ) | 195 | if( pobject->previous ) |
171 | pobject->previous->next = pobject->next; | 196 | pobject->previous->next = pobject->next; |
172 | 197 | ||
173 | free( pobject ); | 198 | MyFree( pobject ); |
174 | } | 199 | } |
175 | 200 | ||
176 | /* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one | 201 | /* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one |
@@ -184,19 +209,15 @@ static BOOL error_occurred; | |||
184 | static void save_err_str( const char *str, DWORD dwMessageId ) | 209 | static void save_err_str( const char *str, DWORD dwMessageId ) |
185 | { | 210 | { |
186 | DWORD ret; | 211 | DWORD ret; |
187 | size_t pos, len; | 212 | size_t pos, i; |
188 | |||
189 | len = strlen( str ); | ||
190 | if( len > sizeof( error_buffer ) - 5 ) | ||
191 | len = sizeof( error_buffer ) - 5; | ||
192 | 213 | ||
193 | /* Format error message to: | 214 | /* Format error message to: |
194 | * "<argument to function that failed>": <Windows localized error message> | 215 | * "<argument to function that failed>": <Windows localized error message> |
195 | */ | 216 | */ |
196 | pos = 0; | 217 | pos = 0; |
197 | error_buffer[pos++] = '"'; | 218 | error_buffer[pos++] = '"'; |
198 | memcpy( error_buffer + pos, str, len ); | 219 | for( i = 0; i < sizeof( error_buffer ) - 5 && str[i] != '\0'; i++ ) |
199 | pos += len; | 220 | error_buffer[pos++] = str[i]; |
200 | error_buffer[pos++] = '"'; | 221 | error_buffer[pos++] = '"'; |
201 | error_buffer[pos++] = ':'; | 222 | error_buffer[pos++] = ':'; |
202 | error_buffer[pos++] = ' '; | 223 | error_buffer[pos++] = ' '; |
@@ -233,7 +254,7 @@ static void save_err_ptr_str( const void *ptr, DWORD dwMessageId ) | |||
233 | for( i = 0; i < 2 * sizeof( ptr ); i++ ) | 254 | for( i = 0; i < 2 * sizeof( ptr ); i++ ) |
234 | { | 255 | { |
235 | num = (char) ( ( ( (ULONG_PTR) ptr ) >> ( 8 * sizeof( ptr ) - 4 * ( i + 1 ) ) ) & 0xF ); | 256 | num = (char) ( ( ( (ULONG_PTR) ptr ) >> ( 8 * sizeof( ptr ) - 4 * ( i + 1 ) ) ) & 0xF ); |
236 | ptr_buf[2 + i] = num + ( ( num < 0xA ) ? '0' : ( 'A' - 0xA ) ); | 257 | ptr_buf[2 + i] = (char) ( num + ( ( num < 0xA ) ? '0' : ( 'A' - 0xA ) ) ); |
237 | } | 258 | } |
238 | 259 | ||
239 | ptr_buf[2 + 2 * sizeof( ptr )] = 0; | 260 | ptr_buf[2 + 2 * sizeof( ptr )] = 0; |
@@ -252,7 +273,7 @@ static UINT MySetErrorMode( UINT uMode ) | |||
252 | { | 273 | { |
253 | kernel32 = GetModuleHandleA( "Kernel32.dll" ); | 274 | kernel32 = GetModuleHandleA( "Kernel32.dll" ); |
254 | if( kernel32 != NULL ) | 275 | if( kernel32 != NULL ) |
255 | SetThreadErrorModePtr = (BOOL (WINAPI *)(DWORD, DWORD *)) (LPVOID) GetProcAddress( kernel32, "SetThreadErrorMode" ); | 276 | SetThreadErrorModePtr = (BOOL (WINAPI *)(DWORD, DWORD *)) (void(*)(void)) GetProcAddress( kernel32, "SetThreadErrorMode" ); |
256 | if( SetThreadErrorModePtr == NULL ) | 277 | if( SetThreadErrorModePtr == NULL ) |
257 | failed = TRUE; | 278 | failed = TRUE; |
258 | } | 279 | } |
@@ -283,7 +304,7 @@ static HMODULE MyGetModuleHandleFromAddress( const void *addr ) | |||
283 | { | 304 | { |
284 | kernel32 = GetModuleHandleA( "Kernel32.dll" ); | 305 | kernel32 = GetModuleHandleA( "Kernel32.dll" ); |
285 | if( kernel32 != NULL ) | 306 | if( kernel32 != NULL ) |
286 | GetModuleHandleExAPtr = (BOOL (WINAPI *)(DWORD, LPCSTR, HMODULE *)) (LPVOID) GetProcAddress( kernel32, "GetModuleHandleExA" ); | 307 | GetModuleHandleExAPtr = (BOOL (WINAPI *)(DWORD, LPCSTR, HMODULE *)) (void(*)(void)) GetProcAddress( kernel32, "GetModuleHandleExA" ); |
287 | if( GetModuleHandleExAPtr == NULL ) | 308 | if( GetModuleHandleExAPtr == NULL ) |
288 | failed = TRUE; | 309 | failed = TRUE; |
289 | } | 310 | } |
@@ -291,7 +312,7 @@ static HMODULE MyGetModuleHandleFromAddress( const void *addr ) | |||
291 | if( !failed ) | 312 | if( !failed ) |
292 | { | 313 | { |
293 | /* If GetModuleHandleExA is available use it with GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS */ | 314 | /* If GetModuleHandleExA is available use it with GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS */ |
294 | if( !GetModuleHandleExAPtr( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, addr, &hModule ) ) | 315 | if( !GetModuleHandleExAPtr( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) addr, &hModule ) ) |
295 | return NULL; | 316 | return NULL; |
296 | } | 317 | } |
297 | else | 318 | else |
@@ -314,6 +335,7 @@ static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, | |||
314 | static BOOL (WINAPI *EnumProcessModulesPtr)(HANDLE, HMODULE *, DWORD, LPDWORD) = NULL; | 335 | static BOOL (WINAPI *EnumProcessModulesPtr)(HANDLE, HMODULE *, DWORD, LPDWORD) = NULL; |
315 | static BOOL failed = FALSE; | 336 | static BOOL failed = FALSE; |
316 | UINT uMode; | 337 | UINT uMode; |
338 | HMODULE kernel32; | ||
317 | HMODULE psapi; | 339 | HMODULE psapi; |
318 | 340 | ||
319 | if( failed ) | 341 | if( failed ) |
@@ -322,9 +344,9 @@ static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, | |||
322 | if( EnumProcessModulesPtr == NULL ) | 344 | if( EnumProcessModulesPtr == NULL ) |
323 | { | 345 | { |
324 | /* Windows 7 and newer versions have K32EnumProcessModules in Kernel32.dll which is always pre-loaded */ | 346 | /* Windows 7 and newer versions have K32EnumProcessModules in Kernel32.dll which is always pre-loaded */ |
325 | psapi = GetModuleHandleA( "Kernel32.dll" ); | 347 | kernel32 = GetModuleHandleA( "Kernel32.dll" ); |
326 | if( psapi != NULL ) | 348 | if( kernel32 != NULL ) |
327 | EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) (LPVOID) GetProcAddress( psapi, "K32EnumProcessModules" ); | 349 | EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) (void(*)(void)) GetProcAddress( kernel32, "K32EnumProcessModules" ); |
328 | 350 | ||
329 | /* Windows Vista and older version have EnumProcessModules in Psapi.dll which needs to be loaded */ | 351 | /* Windows Vista and older version have EnumProcessModules in Psapi.dll which needs to be loaded */ |
330 | if( EnumProcessModulesPtr == NULL ) | 352 | if( EnumProcessModulesPtr == NULL ) |
@@ -332,13 +354,13 @@ static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, | |||
332 | /* Do not let Windows display the critical-error-handler message box */ | 354 | /* Do not let Windows display the critical-error-handler message box */ |
333 | uMode = MySetErrorMode( SEM_FAILCRITICALERRORS ); | 355 | uMode = MySetErrorMode( SEM_FAILCRITICALERRORS ); |
334 | psapi = LoadLibraryA( "Psapi.dll" ); | 356 | psapi = LoadLibraryA( "Psapi.dll" ); |
357 | MySetErrorMode( uMode ); | ||
335 | if( psapi != NULL ) | 358 | if( psapi != NULL ) |
336 | { | 359 | { |
337 | EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) (LPVOID) GetProcAddress( psapi, "EnumProcessModules" ); | 360 | EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) (void(*)(void)) GetProcAddress( psapi, "EnumProcessModules" ); |
338 | if( EnumProcessModulesPtr == NULL ) | 361 | if( EnumProcessModulesPtr == NULL ) |
339 | FreeLibrary( psapi ); | 362 | FreeLibrary( psapi ); |
340 | } | 363 | } |
341 | MySetErrorMode( uMode ); | ||
342 | } | 364 | } |
343 | 365 | ||
344 | if( EnumProcessModulesPtr == NULL ) | 366 | if( EnumProcessModulesPtr == NULL ) |
@@ -368,13 +390,13 @@ void *dlopen( const char *file, int mode ) | |||
368 | * symbol object must be provided. That object must be able to access | 390 | * symbol object must be provided. That object must be able to access |
369 | * all symbols from the original program file, and any objects loaded | 391 | * all symbols from the original program file, and any objects loaded |
370 | * with the RTLD_GLOBAL flag. | 392 | * with the RTLD_GLOBAL flag. |
371 | * The return value from GetModuleHandle( ) allows us to retrieve | 393 | * The return value from GetModuleHandleA( ) allows us to retrieve |
372 | * symbols only from the original program file. EnumProcessModules() is | 394 | * symbols only from the original program file. EnumProcessModules() is |
373 | * used to access symbols from other libraries. For objects loaded | 395 | * used to access symbols from other libraries. For objects loaded |
374 | * with the RTLD_LOCAL flag, we create our own list later on. They are | 396 | * with the RTLD_LOCAL flag, we create our own list later on. They are |
375 | * excluded from EnumProcessModules() iteration. | 397 | * excluded from EnumProcessModules() iteration. |
376 | */ | 398 | */ |
377 | hModule = GetModuleHandle( NULL ); | 399 | hModule = GetModuleHandleA( NULL ); |
378 | 400 | ||
379 | if( !hModule ) | 401 | if( !hModule ) |
380 | save_err_str( "(null)", GetLastError( ) ); | 402 | save_err_str( "(null)", GetLastError( ) ); |
@@ -386,7 +408,11 @@ void *dlopen( const char *file, int mode ) | |||
386 | char lpFileName[MAX_PATH]; | 408 | char lpFileName[MAX_PATH]; |
387 | size_t i, len; | 409 | size_t i, len; |
388 | 410 | ||
389 | len = strlen( file ); | 411 | for( len = 0; ; len++ ) |
412 | { | ||
413 | if( file[len] == '\0' ) | ||
414 | break; | ||
415 | } | ||
390 | 416 | ||
391 | if( len >= sizeof( lpFileName ) ) | 417 | if( len >= sizeof( lpFileName ) ) |
392 | { | 418 | { |
@@ -466,6 +492,10 @@ int dlclose( void *handle ) | |||
466 | 492 | ||
467 | error_occurred = FALSE; | 493 | error_occurred = FALSE; |
468 | 494 | ||
495 | /* dlopen(NULL, ...) does not call LoadLibrary(), so do not call FreeLibrary(). */ | ||
496 | if( hModule == GetModuleHandleA( NULL ) ) | ||
497 | return 0; | ||
498 | |||
469 | ret = FreeLibrary( hModule ); | 499 | ret = FreeLibrary( hModule ); |
470 | 500 | ||
471 | /* If the object was loaded with RTLD_LOCAL, remove it from list of local | 501 | /* If the object was loaded with RTLD_LOCAL, remove it from list of local |
@@ -495,7 +525,7 @@ void *dlsym( void *handle, const char *name ) | |||
495 | 525 | ||
496 | symbol = NULL; | 526 | symbol = NULL; |
497 | hCaller = NULL; | 527 | hCaller = NULL; |
498 | hModule = GetModuleHandle( NULL ); | 528 | hModule = GetModuleHandleA( NULL ); |
499 | dwMessageId = 0; | 529 | dwMessageId = 0; |
500 | 530 | ||
501 | if( handle == RTLD_DEFAULT ) | 531 | if( handle == RTLD_DEFAULT ) |
@@ -548,13 +578,13 @@ void *dlsym( void *handle, const char *name ) | |||
548 | 578 | ||
549 | hCurrentProc = GetCurrentProcess( ); | 579 | hCurrentProc = GetCurrentProcess( ); |
550 | 580 | ||
551 | /* GetModuleHandle( NULL ) only returns the current program file. So | 581 | /* GetModuleHandleA( NULL ) only returns the current program file. So |
552 | * if we want to get ALL loaded module including those in linked DLLs, | 582 | * if we want to get ALL loaded module including those in linked DLLs, |
553 | * we have to use EnumProcessModules( ). | 583 | * we have to use EnumProcessModules( ). |
554 | */ | 584 | */ |
555 | if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwSize ) != 0 ) | 585 | if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwSize ) != 0 ) |
556 | { | 586 | { |
557 | modules = malloc( dwSize ); | 587 | modules = (HMODULE *) MyAlloc( dwSize ); |
558 | if( modules ) | 588 | if( modules ) |
559 | { | 589 | { |
560 | if( MyEnumProcessModules( hCurrentProc, modules, dwSize, &cbNeeded ) != 0 && dwSize == cbNeeded ) | 590 | if( MyEnumProcessModules( hCurrentProc, modules, dwSize, &cbNeeded ) != 0 && dwSize == cbNeeded ) |
@@ -573,13 +603,13 @@ void *dlsym( void *handle, const char *name ) | |||
573 | symbol = GetProcAddress( modules[i], name ); | 603 | symbol = GetProcAddress( modules[i], name ); |
574 | if( symbol != NULL ) | 604 | if( symbol != NULL ) |
575 | { | 605 | { |
576 | free( modules ); | 606 | MyFree( modules ); |
577 | goto end; | 607 | goto end; |
578 | } | 608 | } |
579 | } | 609 | } |
580 | 610 | ||
581 | } | 611 | } |
582 | free( modules ); | 612 | MyFree( modules ); |
583 | } | 613 | } |
584 | else | 614 | else |
585 | { | 615 | { |
@@ -640,7 +670,7 @@ static BOOL get_image_section( HMODULE module, int index, void **ptr, DWORD *siz | |||
640 | if( optionalHeader->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC ) | 670 | if( optionalHeader->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC ) |
641 | return FALSE; | 671 | return FALSE; |
642 | 672 | ||
643 | if( index < 0 || index >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES || index >= optionalHeader->NumberOfRvaAndSizes ) | 673 | if( index < 0 || index >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES || (DWORD)index >= optionalHeader->NumberOfRvaAndSizes ) |
644 | return FALSE; | 674 | return FALSE; |
645 | 675 | ||
646 | if( optionalHeader->DataDirectory[index].Size == 0 || optionalHeader->DataDirectory[index].VirtualAddress == 0 ) | 676 | if( optionalHeader->DataDirectory[index].Size == 0 || optionalHeader->DataDirectory[index].VirtualAddress == 0 ) |
@@ -699,18 +729,18 @@ static BOOL is_valid_address( const void *addr ) | |||
699 | /* check valid pointer */ | 729 | /* check valid pointer */ |
700 | result = VirtualQuery( addr, &info, sizeof( info ) ); | 730 | result = VirtualQuery( addr, &info, sizeof( info ) ); |
701 | 731 | ||
702 | if( result == 0 || info.AllocationBase == NULL || info.AllocationProtect == 0 || info.AllocationProtect == PAGE_NOACCESS ) | 732 | if( result != sizeof( info ) || info.AllocationBase == NULL || info.State == MEM_FREE || info.State == MEM_RESERVE || info.Protect == 0 || info.Protect == PAGE_NOACCESS ) |
703 | return FALSE; | 733 | return FALSE; |
704 | 734 | ||
705 | return TRUE; | 735 | return TRUE; |
706 | } | 736 | } |
707 | 737 | ||
708 | #if defined(_M_ARM64) || defined(__aarch64__) | 738 | #if defined(_M_ARM64) || defined(__aarch64__) |
709 | static INT64 sign_extend(UINT64 value, UINT bits) | 739 | static INT64 sign_extend( UINT64 value, UINT bits ) |
710 | { | 740 | { |
711 | const UINT left = 64 - bits; | 741 | const UINT left = 64 - bits; |
712 | const INT64 m1 = -1; | 742 | const INT64 m1 = -1; |
713 | const INT64 wide = (INT64) (value << left); | 743 | const INT64 wide = (INT64) ( value << left ); |
714 | const INT64 sign = ( wide < 0 ) ? ( m1 << left ) : 0; | 744 | const INT64 sign = ( wide < 0 ) ? ( m1 << left ) : 0; |
715 | 745 | ||
716 | return value | sign; | 746 | return value | sign; |
@@ -742,16 +772,18 @@ static INT64 sign_extend(UINT64 value, UINT bits) | |||
742 | static BOOL is_import_thunk( const void *addr ) | 772 | static BOOL is_import_thunk( const void *addr ) |
743 | { | 773 | { |
744 | #if defined(_M_ARM64) || defined(__aarch64__) | 774 | #if defined(_M_ARM64) || defined(__aarch64__) |
745 | ULONG opCode1 = * (ULONG *) ( (BYTE *) addr ); | 775 | ULONG opCode1 = *(ULONG *) ( (BYTE *) addr ); |
746 | ULONG opCode2 = * (ULONG *) ( (BYTE *) addr + 4 ); | 776 | ULONG opCode2 = *(ULONG *) ( (BYTE *) addr + 4 ); |
747 | ULONG opCode3 = * (ULONG *) ( (BYTE *) addr + 8 ); | 777 | ULONG opCode3 = *(ULONG *) ( (BYTE *) addr + 8 ); |
748 | 778 | ||
749 | return (opCode1 & 0x9f00001f) == 0x90000010 /* adrp x16, [page_offset] */ | 779 | return ( opCode1 & 0x9f00001f ) == 0x90000010 /* adrp x16, [page_offset] */ |
750 | && (opCode2 & 0xffe003ff) == 0xf9400210 /* ldr x16, [x16, offset] */ | 780 | && ( opCode2 & 0xffe003ff ) == 0xf9400210 /* ldr x16, [x16, offset] */ |
751 | && opCode3 == 0xd61f0200 /* br x16 */ | 781 | && opCode3 == 0xd61f0200 /* br x16 */ |
752 | ? TRUE : FALSE; | 782 | ? TRUE : FALSE; |
783 | #elif defined(_M_AMD64) || defined(_M_IX86) || defined(__x86_64__) || defined(__i386__) | ||
784 | return *(USHORT *) addr == 0x25ff ? TRUE : FALSE; | ||
753 | #else | 785 | #else |
754 | return *(short *) addr == 0x25ff ? TRUE : FALSE; | 786 | return FALSE; |
755 | #endif | 787 | #endif |
756 | } | 788 | } |
757 | 789 | ||
@@ -768,24 +800,24 @@ static void *get_address_from_import_address_table( void *iat, DWORD iat_size, c | |||
768 | * 0x7ff772ae78c4 <+25764>: ldr x16, [x16, #0xdc0] | 800 | * 0x7ff772ae78c4 <+25764>: ldr x16, [x16, #0xdc0] |
769 | * 0x7ff772ae78c8 <+25768>: br x16 | 801 | * 0x7ff772ae78c8 <+25768>: br x16 |
770 | */ | 802 | */ |
771 | ULONG opCode1 = * (ULONG *) ( (BYTE *) addr ); | 803 | ULONG opCode1 = *(ULONG *) ( (BYTE *) addr ); |
772 | ULONG opCode2 = * (ULONG *) ( (BYTE *) addr + 4 ); | 804 | ULONG opCode2 = *(ULONG *) ( (BYTE *) addr + 4 ); |
773 | 805 | ||
774 | /* Extract the offset from adrp instruction */ | 806 | /* Extract the offset from adrp instruction */ |
775 | UINT64 pageLow2 = (opCode1 >> 29) & 3; | 807 | UINT64 pageLow2 = ( opCode1 >> 29 ) & 3; |
776 | UINT64 pageHigh19 = (opCode1 >> 5) & ~(~0ull << 19); | 808 | UINT64 pageHigh19 = ( opCode1 >> 5 ) & ~( ~0ull << 19 ); |
777 | INT64 page = sign_extend((pageHigh19 << 2) | pageLow2, 21) << 12; | 809 | INT64 page = sign_extend( ( pageHigh19 << 2 ) | pageLow2, 21 ) << 12; |
778 | 810 | ||
779 | /* Extract the offset from ldr instruction */ | 811 | /* Extract the offset from ldr instruction */ |
780 | UINT64 offset = ((opCode2 >> 10) & ~(~0ull << 12)) << 3; | 812 | UINT64 offset = ( ( opCode2 >> 10 ) & ~( ~0ull << 12 ) ) << 3; |
781 | 813 | ||
782 | /* Calculate the final address */ | 814 | /* Calculate the final address */ |
783 | BYTE *ptr = (BYTE *) ( (ULONG64) thkp & ~0xfffull ) + page + offset; | 815 | BYTE *ptr = (BYTE *) ( (ULONG64) thkp & ~0xfffull ) + page + offset; |
784 | #else | 816 | #elif defined(_M_AMD64) || defined(_M_IX86) || defined(__x86_64__) || defined(__i386__) |
785 | /* Get offset from thunk table (after instruction 0xff 0x25) | 817 | /* Get offset from thunk table (after instruction 0xff 0x25) |
786 | * 4018c8 <_VirtualQuery>: ff 25 4a 8a 00 00 | 818 | * 4018c8 <_VirtualQuery>: ff 25 4a 8a 00 00 |
787 | */ | 819 | */ |
788 | ULONG offset = *(ULONG *)( thkp + 2 ); | 820 | ULONG offset = *(ULONG *) ( thkp + 2 ); |
789 | #if defined(_M_AMD64) || defined(__x86_64__) | 821 | #if defined(_M_AMD64) || defined(__x86_64__) |
790 | /* On 64 bit the offset is relative | 822 | /* On 64 bit the offset is relative |
791 | * 4018c8: ff 25 4a 8a 00 00 jmpq *0x8a4a(%rip) # 40a318 <__imp_VirtualQuery> | 823 | * 4018c8: ff 25 4a 8a 00 00 jmpq *0x8a4a(%rip) # 40a318 <__imp_VirtualQuery> |
@@ -793,13 +825,15 @@ static void *get_address_from_import_address_table( void *iat, DWORD iat_size, c | |||
793 | * 100002f20: ff 25 3a e1 ff ff jmpq *-0x1ec6(%rip) # 0x100001060 | 825 | * 100002f20: ff 25 3a e1 ff ff jmpq *-0x1ec6(%rip) # 0x100001060 |
794 | * So cast to signed LONG type | 826 | * So cast to signed LONG type |
795 | */ | 827 | */ |
796 | BYTE *ptr = (BYTE *)( thkp + 6 + (LONG) offset ); | 828 | BYTE *ptr = (BYTE *) ( thkp + 6 + (LONG) offset ); |
797 | #else | 829 | #else |
798 | /* On 32 bit the offset is absolute | 830 | /* On 32 bit the offset is absolute |
799 | * 4019b4: ff 25 90 71 40 00 jmp *0x40719 | 831 | * 4019b4: ff 25 90 71 40 00 jmp *0x40719 |
800 | */ | 832 | */ |
801 | BYTE *ptr = (BYTE *) offset; | 833 | BYTE *ptr = (BYTE *) offset; |
802 | #endif | 834 | #endif |
835 | #else | ||
836 | return NULL; | ||
803 | #endif | 837 | #endif |
804 | 838 | ||
805 | if( !is_valid_address( ptr ) || ptr < (BYTE *) iat || ptr > (BYTE *) iat + iat_size ) | 839 | if( !is_valid_address( ptr ) || ptr < (BYTE *) iat || ptr > (BYTE *) iat + iat_size ) |