diff options
| author | Etienne Bergeron <etienneb@google.com> | 2016-07-11 23:02:18 +0000 |
|---|---|---|
| committer | Etienne Bergeron <etienneb@google.com> | 2016-07-11 23:02:18 +0000 |
| commit | f5525670ad6c5cb9f6e33b28c85589d4df97c4da (patch) | |
| tree | 4798d449492dad73f00c05aad23f4dc754ef62af /compiler-rt/lib/interception/tests | |
| parent | de1be7171a7fe2471761487eeac795035f885aea (diff) | |
| download | bcm5719-llvm-f5525670ad6c5cb9f6e33b28c85589d4df97c4da.tar.gz bcm5719-llvm-f5525670ad6c5cb9f6e33b28c85589d4df97c4da.zip | |
[compiler-rt] Refactor the interception code on windows.
Summary:
This is a cleanup and refactoring of the interception code on windows
Enhancement:
* Adding the support for 64-bits code
* Adding several hooking technique:
* Detour
* JumpRedirect
* HotPatch
* Trampoline
* Adding a trampoline memory pool (64-bits) and release the allocated memory in unittests
Cleanup:
* Adding unittests for 64-bits hooking techniques
* Enhancing the RoundUpInstruction by sharing common decoder
Reviewers: rnk
Subscribers: llvm-commits, wang0109, chrisha
Differential Revision: http://reviews.llvm.org/D22111
llvm-svn: 275123
Diffstat (limited to 'compiler-rt/lib/interception/tests')
| -rw-r--r-- | compiler-rt/lib/interception/tests/interception_win_test.cc | 497 |
1 files changed, 428 insertions, 69 deletions
diff --git a/compiler-rt/lib/interception/tests/interception_win_test.cc b/compiler-rt/lib/interception/tests/interception_win_test.cc index 276ad271f54..642afd545f1 100644 --- a/compiler-rt/lib/interception/tests/interception_win_test.cc +++ b/compiler-rt/lib/interception/tests/interception_win_test.cc @@ -22,32 +22,121 @@ #define WIN32_LEAN_AND_MEAN #include <windows.h> +namespace __interception { namespace { +enum FunctionPrefixKind { + FunctionPrefixNone, + FunctionPrefixPadding, + FunctionPrefixHotPatch, + FunctionPrefixDetour, +}; + +typedef bool (*TestOverrideFunction)(uptr, uptr, uptr*); typedef int (*IdentityFunction)(int); -#if !SANITIZER_WINDOWS64 +#if SANITIZER_WINDOWS64 const u8 kIdentityCodeWithPrologue[] = { - 0x55, // push ebp - 0x8B, 0xEC, // mov ebp,esp - 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8] - 0x5D, // pop ebp - 0xC3, // ret + 0x55, // push rbp + 0x48, 0x89, 0xE5, // mov rbp,rsp + 0x8B, 0xC1, // mov eax,ecx + 0x5D, // pop rbp + 0xC3, // ret }; const u8 kIdentityCodeWithPushPop[] = { - 0x55, // push ebp - 0x8B, 0xEC, // mov ebp,esp - 0x53, // push ebx - 0x50, // push eax - 0x58, // pop eax - 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8] - 0x5B, // pop ebx - 0x5D, // pop ebp - 0xC3, // ret + 0x55, // push rbp + 0x48, 0x89, 0xE5, // mov rbp,rsp + 0x53, // push rbx + 0x50, // push rax + 0x58, // pop rax + 0x8B, 0xC1, // mov rax,rcx + 0x5B, // pop rbx + 0x5D, // pop rbp + 0xC3, // ret +}; + +const u8 kIdentityTwiceOffset = 16; +const u8 kIdentityTwice[] = { + 0x55, // push rbp + 0x48, 0x89, 0xE5, // mov rbp,rsp + 0x8B, 0xC1, // mov eax,ecx + 0x5D, // pop rbp + 0xC3, // ret + 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, + 0x55, // push rbp + 0x48, 0x89, 0xE5, // mov rbp,rsp + 0x8B, 0xC1, // mov eax,ecx + 0x5D, // pop rbp + 0xC3, // ret +}; + +const u8 kIdentityCodeWithMov[] = { + 0x89, 0xC8, // mov eax, ecx + 0xC3, // ret +}; + +const u8 kIdentityCodeWithJump[] = { + 0xE9, 0x04, 0x00, 0x00, + 0x00, // jmp + 4 + 0xCC, 0xCC, 0xCC, 0xCC, + 0x89, 0xC8, // mov eax, ecx + 0xC3, // ret +}; + +#else + +const u8 kIdentityCodeWithPrologue[] = { + 0x55, // push ebp + 0x8B, 0xEC, // mov ebp,esp + 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8] + 0x5D, // pop ebp + 0xC3, // ret +}; + +const u8 kIdentityCodeWithPushPop[] = { + 0x55, // push ebp + 0x8B, 0xEC, // mov ebp,esp + 0x53, // push ebx + 0x50, // push eax + 0x58, // pop eax + 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8] + 0x5B, // pop ebx + 0x5D, // pop ebp + 0xC3, // ret +}; + +const u8 kIdentityTwiceOffset = 8; +const u8 kIdentityTwice[] = { + 0x55, // push ebp + 0x8B, 0xEC, // mov ebp,esp + 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8] + 0x5D, // pop ebp + 0xC3, // ret + 0x55, // push ebp + 0x8B, 0xEC, // mov ebp,esp + 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8] + 0x5D, // pop ebp + 0xC3, // ret +}; + +const u8 kIdentityCodeWithMov[] = { + 0x8B, 0x44, 0x24, 0x04, // mov eax,dword ptr [esp + 4] + 0xC3, // ret }; +const u8 kIdentityCodeWithJump[] = { + 0xE9, 0x04, 0x00, 0x00, + 0x00, // jmp + 4 + 0xCC, 0xCC, 0xCC, 0xCC, + 0x8B, 0x44, 0x24, 0x04, // mov eax,dword ptr [esp + 4] + 0xC3, // ret +}; + +#endif + const u8 kPatchableCode1[] = { 0xB8, 0x4B, 0x00, 0x00, 0x00, // mov eax,4B 0x33, 0xC9, // xor ecx,ecx @@ -69,6 +158,11 @@ const u8 kPatchableCode3[] = { 0xE8, 0x3D, 0xFF, 0xFF, 0xFF, // call <func> }; +const u8 kPatchableCode4[] = { + 0xE9, 0xCC, 0xCC, 0xCC, 0xCC, // jmp <label> + 0x90, 0x90, 0x90, 0x90, +}; + const u8 kUnpatchableCode1[] = { 0xC3, // ret }; @@ -97,49 +191,68 @@ const u8 kUnpatchableCode5[] = { }; const u8 kUnpatchableCode6[] = { - 0xE9, 0xCC, 0xCC, 0xCC, 0xCC, // jmp <label> - 0x90, 0x90, 0x90, 0x90, -}; - -const u8 kUnpatchableCode7[] = { 0xE8, 0xCC, 0xCC, 0xCC, 0xCC, // call <func> 0x90, 0x90, 0x90, 0x90, }; -#endif - // A buffer holding the dynamically generated code under test. u8* ActiveCode; size_t ActiveCodeLength = 4096; template<class T> -void LoadActiveCode(const T &Code, uptr *EntryPoint) { +static void LoadActiveCode( + const T &code, + uptr *entry_point, + FunctionPrefixKind prefix_kind = FunctionPrefixNone) { if (ActiveCode == nullptr) { ActiveCode = - (u8*)::VirtualAlloc(nullptr, ActiveCodeLength, MEM_COMMIT | MEM_RESERVE, + (u8*)::VirtualAlloc(nullptr, ActiveCodeLength, + MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); ASSERT_NE(ActiveCode, nullptr); } - size_t Position = 0; - *EntryPoint = (uptr)&ActiveCode[0]; + size_t position = 0; + + // Add padding to avoid memory violation when scanning the prefix. + for (int i = 0; i < 16; ++i) + ActiveCode[position++] = 0xC3; // Instruction 'ret'. + + // Add function padding. + size_t padding = 0; + if (prefix_kind == FunctionPrefixPadding) + padding = 16; + else if (prefix_kind == FunctionPrefixDetour || + prefix_kind == FunctionPrefixHotPatch) + padding = FIRST_32_SECOND_64(5, 6); + // Insert |padding| instructions 'nop'. + for (size_t i = 0; i < padding; ++i) + ActiveCode[position++] = 0x90; + + // Keep track of the entry point. + *entry_point = (uptr)&ActiveCode[position]; + + // Add the detour instruction (i.e. mov edi, edi) + if (prefix_kind == FunctionPrefixDetour) { + ActiveCode[position++] = 0x8B; + ActiveCode[position++] = 0xFF; + } // Copy the function body. for (size_t i = 0; i < sizeof(T); ++i) - ActiveCode[Position++] = Code[i]; + ActiveCode[position++] = code[i]; } int InterceptorFunctionCalled; +IdentityFunction InterceptedRealFunction; -NOINLINE int InterceptorFunction(int x) { +int InterceptorFunction(int x) { ++InterceptorFunctionCalled; - return x; + return InterceptedRealFunction(x); } } // namespace -namespace __interception { - // Tests for interception_win.h TEST(Interception, InternalGetProcAddress) { HMODULE ntdll_handle = ::GetModuleHandle("ntdll"); @@ -155,67 +268,313 @@ TEST(Interception, InternalGetProcAddress) { } template<class T> -bool TestFunctionPatching(const T &Code) { - uptr Address; - int x = sizeof(T); - - LoadActiveCode<T>(Code, &Address); - uptr UnusedRealAddress = 0; - return OverrideFunction(Address, (uptr)&InterceptorFunction, - &UnusedRealAddress); -} - -template<class T> -void TestIdentityFunctionPatching(const T &IdentityCode) { - uptr IdentityAddress; - LoadActiveCode<T>(IdentityCode, &IdentityAddress); - IdentityFunction Identity = (IdentityFunction)IdentityAddress; +static void TestIdentityFunctionPatching( + const T &code, + TestOverrideFunction override, + FunctionPrefixKind prefix_kind = FunctionPrefixNone) { + uptr identity_address; + LoadActiveCode(code, &identity_address, prefix_kind); + IdentityFunction identity = (IdentityFunction)identity_address; // Validate behavior before dynamic patching. InterceptorFunctionCalled = 0; - EXPECT_EQ(0, Identity(0)); - EXPECT_EQ(42, Identity(42)); + EXPECT_EQ(0, identity(0)); + EXPECT_EQ(42, identity(42)); EXPECT_EQ(0, InterceptorFunctionCalled); // Patch the function. - uptr RealIdentityAddress = 0; - EXPECT_TRUE(OverrideFunction(IdentityAddress, (uptr)&InterceptorFunction, - &RealIdentityAddress)); - IdentityFunction RealIdentity = (IdentityFunction)RealIdentityAddress; + uptr real_identity_address = 0; + bool success = override(identity_address, + (uptr)&InterceptorFunction, + &real_identity_address); + EXPECT_TRUE(success); + EXPECT_NE(0U, real_identity_address); + IdentityFunction real_identity = (IdentityFunction)real_identity_address; + InterceptedRealFunction = real_identity; + + // Don't run tests if hooking failed or the real function is not valid. + if (!success || !real_identity_address) + return; // Calling the redirected function. InterceptorFunctionCalled = 0; - EXPECT_EQ(0, Identity(0)); - EXPECT_EQ(42, Identity(42)); + EXPECT_EQ(0, identity(0)); + EXPECT_EQ(42, identity(42)); EXPECT_EQ(2, InterceptorFunctionCalled); // Calling the real function. InterceptorFunctionCalled = 0; - EXPECT_EQ(0, RealIdentity(0)); - EXPECT_EQ(42, RealIdentity(42)); + EXPECT_EQ(0, real_identity(0)); + EXPECT_EQ(42, real_identity(42)); EXPECT_EQ(0, InterceptorFunctionCalled); + + TestOnlyReleaseTrampolineRegions(); } #if !SANITIZER_WINDOWS64 +TEST(Interception, OverrideFunctionWithDetour) { + TestOverrideFunction override = OverrideFunctionWithDetour; + FunctionPrefixKind prefix = FunctionPrefixDetour; + TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); +} +#endif // !SANITIZER_WINDOWS64 + +TEST(Interception, OverrideFunctionWithRedirectJump) { + TestOverrideFunction override = OverrideFunctionWithRedirectJump; + TestIdentityFunctionPatching(kIdentityCodeWithJump, override); +} + +TEST(Interception, OverrideFunctionWithHotPatch) { + TestOverrideFunction override = OverrideFunctionWithHotPatch; + FunctionPrefixKind prefix = FunctionPrefixHotPatch; + TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); +} + +TEST(Interception, OverrideFunctionWithTrampoline) { + TestOverrideFunction override = OverrideFunctionWithTrampoline; + FunctionPrefixKind prefix = FunctionPrefixNone; + TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); + + prefix = FunctionPrefixPadding; + TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); +} + TEST(Interception, OverrideFunction) { - TestIdentityFunctionPatching(kIdentityCodeWithPrologue); - TestIdentityFunctionPatching(kIdentityCodeWithPushPop); + TestOverrideFunction override = OverrideFunction; + FunctionPrefixKind prefix = FunctionPrefixNone; + TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); + + prefix = FunctionPrefixPadding; + TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); + + prefix = FunctionPrefixHotPatch; + TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); + + prefix = FunctionPrefixDetour; + TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); + TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); +} + +template<class T> +static void TestIdentityFunctionMultiplePatching( + const T &code, + TestOverrideFunction override, + FunctionPrefixKind prefix_kind = FunctionPrefixNone) { + uptr identity_address; + LoadActiveCode(code, &identity_address, prefix_kind); + + // Patch the function. + uptr real_identity_address = 0; + bool success = override(identity_address, + (uptr)&InterceptorFunction, + &real_identity_address); + EXPECT_TRUE(success); + EXPECT_NE(0U, real_identity_address); + + // Re-patching the function should not work. + success = override(identity_address, + (uptr)&InterceptorFunction, + &real_identity_address); + EXPECT_FALSE(success); + + TestOnlyReleaseTrampolineRegions(); +} + +TEST(Interception, OverrideFunctionMultiplePatchingIsFailing) { +#if !SANITIZER_WINDOWS64 + TestIdentityFunctionMultiplePatching(kIdentityCodeWithPrologue, + OverrideFunctionWithDetour, + FunctionPrefixDetour); +#endif + + TestIdentityFunctionMultiplePatching(kIdentityCodeWithMov, + OverrideFunctionWithHotPatch, + FunctionPrefixHotPatch); + + TestIdentityFunctionMultiplePatching(kIdentityCodeWithPushPop, + OverrideFunctionWithTrampoline, + FunctionPrefixPadding); +} + +TEST(Interception, OverrideFunctionTwice) { + uptr identity_address1; + LoadActiveCode(kIdentityTwice, &identity_address1); + uptr identity_address2 = identity_address1 + kIdentityTwiceOffset; + IdentityFunction identity1 = (IdentityFunction)identity_address1; + IdentityFunction identity2 = (IdentityFunction)identity_address2; + + // Patch the two functions. + uptr real_identity_address = 0; + EXPECT_TRUE(OverrideFunction(identity_address1, + (uptr)&InterceptorFunction, + &real_identity_address)); + EXPECT_TRUE(OverrideFunction(identity_address2, + (uptr)&InterceptorFunction, + &real_identity_address)); + IdentityFunction real_identity = (IdentityFunction)real_identity_address; + InterceptedRealFunction = real_identity; + + // Calling the redirected function. + InterceptorFunctionCalled = 0; + EXPECT_EQ(42, identity1(42)); + EXPECT_EQ(42, identity2(42)); + EXPECT_EQ(2, InterceptorFunctionCalled); + + TestOnlyReleaseTrampolineRegions(); +} + +template<class T> +static bool TestFunctionPatching( + const T &code, + TestOverrideFunction override, + FunctionPrefixKind prefix_kind = FunctionPrefixNone) { + uptr address; + LoadActiveCode(code, &address, prefix_kind); + uptr unused_real_address = 0; + bool result = override( + address, (uptr)&InterceptorFunction, &unused_real_address); + + TestOnlyReleaseTrampolineRegions(); + return result; } TEST(Interception, PatchableFunction) { - EXPECT_TRUE(TestFunctionPatching(kPatchableCode1)); - EXPECT_TRUE(TestFunctionPatching(kPatchableCode2)); - EXPECT_TRUE(TestFunctionPatching(kPatchableCode3)); - - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode7)); + TestOverrideFunction override = OverrideFunction; + // Test without function padding. + EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override)); + EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override)); +#if SANITIZER_WINDOWS64 + EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override)); +#else + EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override)); +#endif + EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override)); + + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override)); +} + +#if !SANITIZER_WINDOWS64 +TEST(Interception, PatchableFunctionWithDetour) { + TestOverrideFunction override = OverrideFunctionWithDetour; + // Without the prefix, no function can be detoured. + EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override)); + EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override)); + EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override)); + EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override)); + + // With the prefix, all functions can be detoured. + FunctionPrefixKind prefix = FunctionPrefixDetour; + EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode1, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode3, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode4, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode5, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode6, override, prefix)); +} +#endif // !SANITIZER_WINDOWS64 + +TEST(Interception, PatchableFunctionWithRedirectJump) { + TestOverrideFunction override = OverrideFunctionWithRedirectJump; + EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override)); + EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override)); + EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override)); + EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override)); +} + +TEST(Interception, PatchableFunctionWithHotPatch) { + TestOverrideFunction override = OverrideFunctionWithHotPatch; + FunctionPrefixKind prefix = FunctionPrefixHotPatch; + + EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix)); + + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix)); } + +TEST(Interception, PatchableFunctionWithTrampoline) { + TestOverrideFunction override = OverrideFunctionWithTrampoline; + FunctionPrefixKind prefix = FunctionPrefixPadding; + + EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix)); +#if SANITIZER_WINDOWS64 + EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix)); +#else + EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix)); #endif + EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix)); + + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix)); +} + +TEST(Interception, PatchableFunctionPadding) { + TestOverrideFunction override = OverrideFunction; + FunctionPrefixKind prefix = FunctionPrefixPadding; + + EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix)); +#if SANITIZER_WINDOWS64 + EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix)); +#else + EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix)); +#endif + EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix)); + + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix)); + EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix)); +} } // namespace __interception |

