diff options
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 ) |
