aboutsummaryrefslogtreecommitdiff
path: root/libsanitizer/interception
diff options
context:
space:
mode:
authorKito Cheng <kito.cheng@sifive.com>2024-11-01 15:33:03 +0800
committerKito Cheng <kito.cheng@sifive.com>2024-11-12 21:56:06 +0800
commitfa321004f3f6288d3ee2eefa6b02177131882dca (patch)
tree6e111379127d142eb20c7630a44254124adef5bb /libsanitizer/interception
parentb8ecd96aea9a97a60b143fc70efa6d03d0f188a2 (diff)
downloadgcc-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.h35
-rw-r--r--libsanitizer/interception/interception_linux.h16
-rw-r--r--libsanitizer/interception/interception_type_test.cpp31
-rw-r--r--libsanitizer/interception/interception_win.cpp237
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