diff options
author | Kito Cheng <kito.cheng@sifive.com> | 2024-11-01 15:33:03 +0800 |
---|---|---|
committer | Kito Cheng <kito.cheng@sifive.com> | 2024-11-12 21:56:06 +0800 |
commit | fa321004f3f6288d3ee2eefa6b02177131882dca (patch) | |
tree | 6e111379127d142eb20c7630a44254124adef5bb /libsanitizer/interception | |
parent | b8ecd96aea9a97a60b143fc70efa6d03d0f188a2 (diff) | |
download | gcc-fa321004f3f6288d3ee2eefa6b02177131882dca.zip gcc-fa321004f3f6288d3ee2eefa6b02177131882dca.tar.gz gcc-fa321004f3f6288d3ee2eefa6b02177131882dca.tar.bz2 |
libsanitizer: merge from upstream (61a6439f35b6de28)
Diffstat (limited to 'libsanitizer/interception')
-rw-r--r-- | libsanitizer/interception/interception.h | 35 | ||||
-rw-r--r-- | libsanitizer/interception/interception_linux.h | 16 | ||||
-rw-r--r-- | libsanitizer/interception/interception_type_test.cpp | 31 | ||||
-rw-r--r-- | libsanitizer/interception/interception_win.cpp | 237 |
4 files changed, 244 insertions, 75 deletions
diff --git a/libsanitizer/interception/interception.h b/libsanitizer/interception/interception.h index 73135b3..0580d97 100644 --- a/libsanitizer/interception/interception.h +++ b/libsanitizer/interception/interception.h @@ -25,8 +25,19 @@ // These typedefs should be used only in the interceptor definitions to replace // the standard system types (e.g. SSIZE_T instead of ssize_t) -typedef __sanitizer::uptr SIZE_T; -typedef __sanitizer::sptr SSIZE_T; +// On Windows the system headers (basetsd.h) provide a conflicting definition +// of SIZE_T/SSIZE_T that do not match the real size_t/ssize_t for 32-bit +// systems (using long instead of the expected int). Work around the typedef +// redefinition by #defining SIZE_T instead of using a typedef. +// TODO: We should be using __sanitizer::usize (and a new ssize) instead of +// these new macros as long as we ensure they match the real system definitions. +#if SANITIZER_WINDOWS +// Ensure that (S)SIZE_T were already defined as we are about to override them. +# include <basetsd.h> +#endif + +#define SIZE_T __sanitizer::usize +#define SSIZE_T __sanitizer::sptr typedef __sanitizer::sptr PTRDIFF_T; typedef __sanitizer::s64 INTMAX_T; typedef __sanitizer::u64 UINTMAX_T; @@ -338,16 +349,20 @@ const interpose_substitution substitution_##func_name[] \ #endif // ISO C++ forbids casting between pointer-to-function and pointer-to-object, -// so we use casting via an integral type __interception::uptr, -// assuming that system is POSIX-compliant. Using other hacks seem -// challenging, as we don't even pass function type to -// INTERCEPT_FUNCTION macro, only its name. +// so we use casts via uintptr_t (the local __sanitizer::uptr equivalent). namespace __interception { -#if defined(_WIN64) -typedef unsigned long long uptr; + +#if defined(__ELF__) && !SANITIZER_FUCHSIA +// The use of interceptors makes many sanitizers unusable for static linking. +// Define a function, if called, will cause a linker error (undefined _DYNAMIC). +// However, -static-pie (which is not common) cannot be detected at link time. +extern uptr kDynamic[] asm("_DYNAMIC"); +inline void DoesNotSupportStaticLinking() { + [[maybe_unused]] volatile auto x = &kDynamic; +} #else -typedef unsigned long uptr; -#endif // _WIN64 +inline void DoesNotSupportStaticLinking() {} +#endif } // namespace __interception #define INCLUDED_FROM_INTERCEPTION_LIB diff --git a/libsanitizer/interception/interception_linux.h b/libsanitizer/interception/interception_linux.h index 433a3d9..2e01ff4 100644 --- a/libsanitizer/interception/interception_linux.h +++ b/libsanitizer/interception/interception_linux.h @@ -28,12 +28,14 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real, uptr func, uptr trampoline); } // namespace __interception -#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \ - ::__interception::InterceptFunction( \ - #func, \ - (::__interception::uptr *)&REAL(func), \ - (::__interception::uptr)&(func), \ - (::__interception::uptr)&TRAMPOLINE(func)) +// Cast func to type of REAL(func) before casting to uptr in case it is an +// overloaded function, which is the case for some glibc functions when +// _FORTIFY_SOURCE is used. This disambiguates which overload to use. +#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \ + ::__interception::InterceptFunction( \ + #func, (::__interception::uptr *)&REAL(func), \ + (::__interception::uptr)(decltype(REAL(func)))&(func), \ + (::__interception::uptr) &TRAMPOLINE(func)) // dlvsym is a GNU extension supported by some other platforms. #if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD @@ -41,7 +43,7 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real, ::__interception::InterceptFunction( \ #func, symver, \ (::__interception::uptr *)&REAL(func), \ - (::__interception::uptr)&(func), \ + (::__interception::uptr)(decltype(REAL(func)))&(func), \ (::__interception::uptr)&TRAMPOLINE(func)) #else #define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \ diff --git a/libsanitizer/interception/interception_type_test.cpp b/libsanitizer/interception/interception_type_test.cpp index 7c3de82..41041ce 100644 --- a/libsanitizer/interception/interception_type_test.cpp +++ b/libsanitizer/interception/interception_type_test.cpp @@ -12,28 +12,35 @@ //===----------------------------------------------------------------------===// #include "interception.h" +#include "sanitizer_common/sanitizer_type_traits.h" -#if SANITIZER_LINUX || SANITIZER_APPLE - -#include <sys/types.h> +#if __has_include(<sys/types.h>) +# include <sys/types.h> +#endif #include <stddef.h> #include <stdint.h> -COMPILER_CHECK(sizeof(::SIZE_T) == sizeof(size_t)); -COMPILER_CHECK(sizeof(::SSIZE_T) == sizeof(ssize_t)); -COMPILER_CHECK(sizeof(::PTRDIFF_T) == sizeof(ptrdiff_t)); +COMPILER_CHECK((__sanitizer::is_same<__sanitizer::uptr, ::uintptr_t>::value)); +COMPILER_CHECK((__sanitizer::is_same<__sanitizer::sptr, ::intptr_t>::value)); +COMPILER_CHECK((__sanitizer::is_same<__sanitizer::usize, ::size_t>::value)); +COMPILER_CHECK((__sanitizer::is_same<::PTRDIFF_T, ::ptrdiff_t>::value)); +COMPILER_CHECK((__sanitizer::is_same<::SIZE_T, ::size_t>::value)); +#if !SANITIZER_WINDOWS +// No ssize_t on Windows. +COMPILER_CHECK((__sanitizer::is_same<::SSIZE_T, ::ssize_t>::value)); +#endif +// TODO: These are not actually the same type on Linux (long vs long long) COMPILER_CHECK(sizeof(::INTMAX_T) == sizeof(intmax_t)); +COMPILER_CHECK(sizeof(::UINTMAX_T) == sizeof(uintmax_t)); -# if SANITIZER_GLIBC || SANITIZER_ANDROID +#if SANITIZER_GLIBC || SANITIZER_ANDROID COMPILER_CHECK(sizeof(::OFF64_T) == sizeof(off64_t)); -# endif +#endif // The following are the cases when pread (and friends) is used instead of // pread64. In those cases we need OFF_T to match off_t. We don't care about the // rest (they depend on _FILE_OFFSET_BITS setting when building an application). -# if SANITIZER_ANDROID || !defined _FILE_OFFSET_BITS || \ - _FILE_OFFSET_BITS != 64 +#if !SANITIZER_WINDOWS && (SANITIZER_ANDROID || !defined _FILE_OFFSET_BITS || \ + _FILE_OFFSET_BITS != 64) COMPILER_CHECK(sizeof(::OFF_T) == sizeof(off_t)); -# endif - #endif diff --git a/libsanitizer/interception/interception_win.cpp b/libsanitizer/interception/interception_win.cpp index 1b681ad..077a536 100644 --- a/libsanitizer/interception/interception_win.cpp +++ b/libsanitizer/interception/interception_win.cpp @@ -27,7 +27,7 @@ // // 1) Detour // -// The Detour hooking technique is assuming the presence of an header with +// The Detour hooking technique is assuming the presence of a header with // padding and an overridable 2-bytes nop instruction (mov edi, edi). The // nop instruction can safely be replaced by a 2-bytes jump without any need // to save the instruction. A jump to the target is encoded in the function @@ -47,7 +47,7 @@ // // func: jmp <label> --> func: jmp <hook> // -// On an 64-bit architecture, a trampoline is inserted. +// On a 64-bit architecture, a trampoline is inserted. // // func: jmp <label> --> func: jmp <tramp> // [...] @@ -60,7 +60,7 @@ // // 3) HotPatch // -// The HotPatch hooking is assuming the presence of an header with padding +// The HotPatch hooking is assuming the presence of a header with padding // and a first instruction with at least 2-bytes. // // The reason to enforce the 2-bytes limitation is to provide the minimal @@ -80,7 +80,7 @@ // real: <instr> // jmp <body> // -// On an 64-bit architecture: +// On a 64-bit architecture: // // head: 6 x nop head: jmp QWORD [addr1] // func: <instr> --> func: jmp short <head> @@ -110,7 +110,7 @@ // <instr> // jmp <body> // -// On an 64-bit architecture: +// On a 64-bit architecture: // // func: <instr> --> func: jmp QWORD [addr1] // <instr> @@ -130,6 +130,7 @@ #include "sanitizer_common/sanitizer_platform.h" #define WIN32_LEAN_AND_MEAN #include <windows.h> +#include <psapi.h> namespace __interception { @@ -339,7 +340,7 @@ struct TrampolineMemoryRegion { uptr max_size; }; -UNUSED static const uptr kTrampolineScanLimitRange = 1 << 31; // 2 gig +UNUSED static const uptr kTrampolineScanLimitRange = 1ull << 31; // 2 gig static const int kMaxTrampolineRegion = 1024; static TrampolineMemoryRegion TrampolineRegions[kMaxTrampolineRegion]; @@ -385,7 +386,30 @@ void TestOnlyReleaseTrampolineRegions() { } } -static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) { +static uptr AllocateMemoryForTrampoline(uptr func_address, size_t size) { + uptr image_address = func_address; + +#if SANITIZER_WINDOWS64 + // Allocate memory after the module (DLL or EXE file), but within 2GB + // of the start of the module so that any address within the module can be + // referenced with PC-relative operands. + // This allows us to not just jump to the trampoline with a PC-relative + // offset, but to relocate any instructions that we copy to the trampoline + // which have references to the original module. If we can't find the base + // address of the module (e.g. if func_address is in mmap'ed memory), just + // use func_address as is. + HMODULE module; + if (::GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (LPCWSTR)func_address, &module)) { + MODULEINFO module_info; + if (::GetModuleInformation(::GetCurrentProcess(), module, + &module_info, sizeof(module_info))) { + image_address = (uptr)module_info.lpBaseOfDll; + } + } +#endif + // Find a region within 2G with enough space to allocate |size| bytes. TrampolineMemoryRegion *region = nullptr; for (size_t bucket = 0; bucket < kMaxTrampolineRegion; ++bucket) { @@ -431,7 +455,8 @@ static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) { // The following prologues cannot be patched because of the short jump // jumping to the patching region. -#if SANITIZER_WINDOWS64 +// Short jump patterns below are only for x86_64. +# if SANITIZER_WINDOWS_x64 // ntdll!wcslen in Win11 // 488bc1 mov rax,rcx // 0fb710 movzx edx,word ptr [rax] @@ -462,7 +487,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { return 4; #endif -#if SANITIZER_WINDOWS64 +# if SANITIZER_WINDOWS_x64 if (memcmp((u8*)address, kPrologueWithShortJump1, sizeof(kPrologueWithShortJump1)) == 0 || memcmp((u8*)address, kPrologueWithShortJump2, @@ -478,6 +503,8 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { switch (*(u8*)address) { case 0x90: // 90 : nop + case 0xC3: // C3 : ret (for small/empty function interception + case 0xCC: // CC : int 3 i.e. registering weak functions) return 1; case 0x50: // push eax / rax @@ -494,6 +521,11 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0x6A: // 6A XX = push XX return 2; + // This instruction can be encoded with a 16-bit immediate but that is + // incredibly unlikely. + case 0x68: // 68 XX XX XX XX : push imm32 + return 5; + case 0xb8: // b8 XX XX XX XX : mov eax, XX XX XX XX case 0xB9: // b9 XX XX XX XX : mov ecx, XX XX XX XX return 5; @@ -501,7 +533,6 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { // Cannot overwrite control-instruction. Return 0 to indicate failure. case 0xE9: // E9 XX XX XX XX : jmp <label> case 0xE8: // E8 XX XX XX XX : call <func> - case 0xC3: // C3 : ret case 0xEB: // EB XX : jmp XX (short jump) case 0x70: // 7Y YY : jy XX (short conditional jump) case 0x71: @@ -532,6 +563,9 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0xC033: // 33 C0 : xor eax, eax case 0xC933: // 33 C9 : xor ecx, ecx case 0xD233: // 33 D2 : xor edx, edx + case 0xDB84: // 84 DB : test bl,bl + case 0xC984: // 84 C9 : test cl,cl + case 0xD284: // 84 D2 : test dl,dl return 2; // Cannot overwrite control-instruction. Return 0 to indicate failure. @@ -540,15 +574,38 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { } switch (0x00FFFFFF & *(u32*)address) { + case 0xF8E483: // 83 E4 F8 : and esp, 0xFFFFFFF8 + case 0x64EC83: // 83 EC 64 : sub esp, 64h + return 3; case 0x24A48D: // 8D A4 24 XX XX XX XX : lea esp, [esp + XX XX XX XX] return 7; } -#if SANITIZER_WINDOWS64 + switch (0x000000FF & *(u32 *)address) { + case 0xc2: // C2 XX XX : ret XX (needed for registering weak functions) + return 3; + } + +# if SANITIZER_WINDOWS_x64 switch (*(u8*)address) { case 0xA1: // A1 XX XX XX XX XX XX XX XX : // movabs eax, dword ptr ds:[XXXXXXXX] return 9; + case 0xF2: + switch (*(u32 *)(address + 1)) { + case 0x2444110f: // f2 0f 11 44 24 XX movsd QWORD PTR + // [rsp + XX], xmm0 + case 0x244c110f: // f2 0f 11 4c 24 XX movsd QWORD PTR + // [rsp + XX], xmm1 + case 0x2454110f: // f2 0f 11 54 24 XX movsd QWORD PTR + // [rsp + XX], xmm2 + case 0x245c110f: // f2 0f 11 5c 24 XX movsd QWORD PTR + // [rsp + XX], xmm3 + case 0x2464110f: // f2 0f 11 64 24 XX movsd QWORD PTR + // [rsp + XX], xmm4 + return 6; + } + break; case 0x83: const u8 next_byte = *(u8*)(address + 1); @@ -577,51 +634,126 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0x018a: // mov al, byte ptr [rcx] return 2; + case 0x058A: // 8A 05 XX XX XX XX : mov al, byte ptr [XX XX XX XX] + case 0x7E80: // 80 7E YY XX cmp BYTE PTR [rsi+YY], XX + case 0x7D80: // 80 7D YY XX cmp BYTE PTR [rbp+YY], XX + case 0x7A80: // 80 7A YY XX cmp BYTE PTR [rdx+YY], XX + case 0x7880: // 80 78 YY XX cmp BYTE PTR [rax+YY], XX + case 0x7B80: // 80 7B YY XX cmp BYTE PTR [rbx+YY], XX + case 0x7980: // 80 79 YY XX cmp BYTE ptr [rcx+YY], XX + return 4; + case 0x058B: // 8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX] if (rel_offset) *rel_offset = 2; return 6; + + case 0x7E81: // 81 7E YY XX XX XX XX cmp DWORD PTR [rsi+YY], XX XX XX XX + case 0x7D81: // 81 7D YY XX XX XX XX cmp DWORD PTR [rbp+YY], XX XX XX XX + case 0x7A81: // 81 7A YY XX XX XX XX cmp DWORD PTR [rdx+YY], XX XX XX XX + case 0x7881: // 81 78 YY XX XX XX XX cmp DWORD PTR [rax+YY], XX XX XX XX + case 0x7B81: // 81 7B YY XX XX XX XX cmp DWORD PTR [rbx+YY], XX XX XX XX + case 0x7981: // 81 79 YY XX XX XX XX cmp dword ptr [rcx+YY], XX XX XX XX + return 7; } switch (0x00FFFFFF & *(u32*)address) { - case 0xe58948: // 48 8b c4 : mov rbp, rsp - case 0xc18b48: // 48 8b c1 : mov rax, rcx - case 0xc48b48: // 48 8b c4 : mov rax, rsp - case 0xd9f748: // 48 f7 d9 : neg rcx - case 0xd12b48: // 48 2b d1 : sub rdx, rcx case 0x07c1f6: // f6 c1 07 : test cl, 0x7 - case 0xc98548: // 48 85 C9 : test rcx, rcx - case 0xd28548: // 48 85 d2 : test rdx, rdx + case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax] + case 0xc00b4d: // 4d 0b c0 : or r8, r8 + case 0xc03345: // 45 33 c0 : xor r8d, r8d + case 0xc08548: // 48 85 c0 : test rax, rax case 0xc0854d: // 4d 85 c0 : test r8, r8 + case 0xc08b41: // 41 8b c0 : mov eax, r8d + case 0xc0ff48: // 48 ff c0 : inc rax + case 0xc0ff49: // 49 ff c0 : inc r8 + case 0xc18b41: // 41 8b c1 : mov eax, r9d + case 0xc18b48: // 48 8b c1 : mov rax, rcx + case 0xc18b4c: // 4c 8b c1 : mov r8, rcx + case 0xc1ff48: // 48 ff c1 : inc rcx + case 0xc1ff49: // 49 ff c1 : inc r9 + case 0xc28b41: // 41 8b c2 : mov eax, r10d case 0xc2b60f: // 0f b6 c2 : movzx eax, dl - case 0xc03345: // 45 33 c0 : xor r8d, r8d + case 0xc2ff48: // 48 ff c2 : inc rdx + case 0xc2ff49: // 49 ff c2 : inc r10 + case 0xc38b41: // 41 8b c3 : mov eax, r11d + case 0xc3ff48: // 48 ff c3 : inc rbx + case 0xc3ff49: // 49 ff c3 : inc r11 + case 0xc48b41: // 41 8b c4 : mov eax, r12d + case 0xc48b48: // 48 8b c4 : mov rax, rsp + case 0xc4ff49: // 49 ff c4 : inc r12 + case 0xc5ff49: // 49 ff c5 : inc r13 + case 0xc6ff48: // 48 ff c6 : inc rsi + case 0xc6ff49: // 49 ff c6 : inc r14 + case 0xc7ff48: // 48 ff c7 : inc rdi + case 0xc7ff49: // 49 ff c7 : inc r15 case 0xc93345: // 45 33 c9 : xor r9d, r9d - case 0xdb3345: // 45 33 DB : xor r11d, r11d - case 0xd98b4c: // 4c 8b d9 : mov r11, rcx - case 0xd28b4c: // 4c 8b d2 : mov r10, rdx - case 0xc98b4c: // 4C 8B C9 : mov r9, rcx - case 0xc18b4c: // 4C 8B C1 : mov r8, rcx - case 0xd2b60f: // 0f b6 d2 : movzx edx, dl + case 0xc98548: // 48 85 c9 : test rcx, rcx + case 0xc9854d: // 4d 85 c9 : test r9, r9 + case 0xc98b4c: // 4c 8b c9 : mov r9, rcx case 0xca2b48: // 48 2b ca : sub rcx, rdx - case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax] - case 0xc00b4d: // 3d 0b c0 : or r8, r8 - case 0xc08b41: // 41 8b c0 : mov eax, r8d + case 0xca3b48: // 48 3b ca : cmp rcx, rdx + case 0xd12b48: // 48 2b d1 : sub rdx, rcx case 0xd18b48: // 48 8b d1 : mov rdx, rcx - case 0xdc8b4c: // 4c 8b dc : mov r11, rsp case 0xd18b4c: // 4c 8b d1 : mov r10, rcx - case 0xE0E483: // 83 E4 E0 : and esp, 0xFFFFFFE0 + case 0xd28548: // 48 85 d2 : test rdx, rdx + case 0xd2854d: // 4d 85 d2 : test r10, r10 + case 0xd28b4c: // 4c 8b d2 : mov r10, rdx + case 0xd2b60f: // 0f b6 d2 : movzx edx, dl + case 0xd98b4c: // 4c 8b d9 : mov r11, rcx + case 0xd9f748: // 48 f7 d9 : neg rcx + case 0xdb3345: // 45 33 db : xor r11d, r11d + case 0xdb8548: // 48 85 db : test rbx, rbx + case 0xdb854d: // 4d 85 db : test r11, r11 + case 0xdc8b4c: // 4c 8b dc : mov r11, rsp + case 0xe0e483: // 83 e4 e0 : and esp, 0xFFFFFFE0 + case 0xe48548: // 48 85 e4 : test rsp, rsp + case 0xe4854d: // 4d 85 e4 : test r12, r12 + case 0xe58948: // 48 89 e5 : mov rbp, rsp + case 0xed8548: // 48 85 ed : test rbp, rbp + case 0xed854d: // 4d 85 ed : test r13, r13 + case 0xf6854d: // 4d 85 f6 : test r14, r14 + case 0xff854d: // 4d 85 ff : test r15, r15 return 3; + case 0x245489: // 89 54 24 XX : mov DWORD PTR[rsp + XX], edx + case 0x428d44: // 44 8d 42 XX : lea r8d , [rdx + XX] + case 0x588948: // 48 89 58 XX : mov QWORD PTR[rax + XX], rbx case 0xec8348: // 48 83 ec XX : sub rsp, XX case 0xf88349: // 49 83 f8 XX : cmp r8, XX - case 0x588948: // 48 89 58 XX : mov QWORD PTR[rax + XX], rbx return 4; + case 0x246483: // 83 64 24 XX YY : and DWORD PTR [rsp+XX], YY + return 5; + + case 0x788166: // 66 81 78 XX YY YY cmp WORD PTR [rax+XX], YY YY + case 0x798166: // 66 81 79 XX YY YY cmp WORD PTR [rcx+XX], YY YY + case 0x7a8166: // 66 81 7a XX YY YY cmp WORD PTR [rdx+XX], YY YY + case 0x7b8166: // 66 81 7b XX YY YY cmp WORD PTR [rbx+XX], YY YY + case 0x7e8166: // 66 81 7e XX YY YY cmp WORD PTR [rsi+XX], YY YY + case 0x7f8166: // 66 81 7f XX YY YY cmp WORD PTR [rdi+XX], YY YY + return 6; + case 0xec8148: // 48 81 EC XX XX XX XX : sub rsp, XXXXXXXX return 7; + // clang-format off + case 0x788141: // 41 81 78 XX YY YY YY YY : cmp DWORD PTR [r8+YY], XX XX XX XX + case 0x798141: // 41 81 79 XX YY YY YY YY : cmp DWORD PTR [r9+YY], XX XX XX XX + case 0x7a8141: // 41 81 7a XX YY YY YY YY : cmp DWORD PTR [r10+YY], XX XX XX XX + case 0x7b8141: // 41 81 7b XX YY YY YY YY : cmp DWORD PTR [r11+YY], XX XX XX XX + case 0x7c8141: // 41 81 7c XX YY YY YY YY : cmp DWORD PTR [r12+YY], XX XX XX XX + case 0x7d8141: // 41 81 7d XX YY YY YY YY : cmp DWORD PTR [r13+YY], XX XX XX XX + case 0x7e8141: // 41 81 7e XX YY YY YY YY : cmp DWORD PTR [r14+YY], XX XX XX XX + case 0x7f8141: // 41 81 7f YY XX XX XX XX : cmp DWORD PTR [r15+YY], XX XX XX XX + case 0x247c81: // 81 7c 24 YY XX XX XX XX : cmp DWORD PTR [rsp+YY], XX XX XX XX + return 8; + // clang-format on + case 0x058b48: // 48 8b 05 XX XX XX XX : // mov rax, QWORD PTR [rip + XXXXXXXX] + case 0x058d48: // 48 8d 05 XX XX XX XX : + // lea rax, QWORD PTR [rip + XXXXXXXX] case 0x25ff48: // 48 ff 25 XX XX XX XX : // rex.W jmp QWORD PTR [rip + XXXXXXXX] case 0x158D4C: // 4c 8d 15 XX XX XX XX : lea r10, [rip + XX] @@ -636,6 +768,8 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { } switch (*(u32*)(address)) { + case 0x1ab60f44: // 44 0f b6 1a : movzx r11d, BYTE PTR [rdx] + return 4; case 0x24448b48: // 48 8b 44 24 XX : mov rax, QWORD ptr [rsp + XX] case 0x246c8948: // 48 89 6C 24 XX : mov QWORD ptr [rsp + XX], rbp case 0x245c8948: // 48 89 5c 24 XX : mov QWORD PTR [rsp + XX], rbx @@ -645,8 +779,11 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0x24548948: // 48 89 54 24 XX : mov QWORD PTR [rsp + XX], rdx case 0x244c894c: // 4c 89 4c 24 XX : mov QWORD PTR [rsp + XX], r9 case 0x2444894c: // 4c 89 44 24 XX : mov QWORD PTR [rsp + XX], r8 + case 0x244c8944: // 44 89 4c 24 XX mov DWORD PTR [rsp + XX], r9d + case 0x24448944: // 44 89 44 24 XX mov DWORD PTR [rsp + XX], r8d + case 0x246c8d48: // 48 8d 6c 24 XX : lea rbp, [rsp + XX] return 5; - case 0x24648348: // 48 83 64 24 XX : and QWORD PTR [rsp + XX], YY + case 0x24648348: // 48 83 64 24 XX YY : and QWORD PTR [rsp + XX], YY return 6; } @@ -660,6 +797,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0x458B: // 8B 45 XX : mov eax, dword ptr [ebp + XX] case 0x5D8B: // 8B 5D XX : mov ebx, dword ptr [ebp + XX] case 0x7D8B: // 8B 7D XX : mov edi, dword ptr [ebp + XX] + case 0x758B: // 8B 75 XX : mov esi, dword ptr [ebp + XX] case 0xEC83: // 83 EC XX : sub esp, XX case 0x75FF: // FF 75 XX : push dword ptr [ebp + XX] return 3; @@ -943,19 +1081,26 @@ bool OverrideFunction( static void **InterestingDLLsAvailable() { static const char *InterestingDLLs[] = { - "kernel32.dll", - "msvcr100.dll", // VS2010 - "msvcr110.dll", // VS2012 - "msvcr120.dll", // VS2013 - "vcruntime140.dll", // VS2015 - "ucrtbase.dll", // Universal CRT -#if (defined(__MINGW32__) && defined(__i386__)) - "libc++.dll", // libc++ - "libunwind.dll", // libunwind -#endif - // NTDLL should go last as it exports some functions that we should - // override in the CRT [presumably only used internally]. - "ntdll.dll", NULL}; + "kernel32.dll", + "msvcr100d.dll", // VS2010 + "msvcr110d.dll", // VS2012 + "msvcr120d.dll", // VS2013 + "vcruntime140d.dll", // VS2015 + "ucrtbased.dll", // Universal CRT + "msvcr100.dll", // VS2010 + "msvcr110.dll", // VS2012 + "msvcr120.dll", // VS2013 + "vcruntime140.dll", // VS2015 + "ucrtbase.dll", // Universal CRT +# if (defined(__MINGW32__) && defined(__i386__)) + "libc++.dll", // libc++ + "libunwind.dll", // libunwind +# endif + // NTDLL should go last as it exports some functions that we should + // override in the CRT [presumably only used internally]. + "ntdll.dll", + NULL + }; static void *result[ARRAY_SIZE(InterestingDLLs)] = { 0 }; if (!result[0]) { for (size_t i = 0, j = 0; InterestingDLLs[i]; ++i) { @@ -1126,4 +1271,4 @@ bool OverrideImportedFunction(const char *module_to_patch, } // namespace __interception -#endif // SANITIZER_APPLE +#endif // SANITIZER_WINDOWS |