summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/interception/tests
diff options
context:
space:
mode:
authorEtienne Bergeron <etienneb@google.com>2016-07-11 23:02:18 +0000
committerEtienne Bergeron <etienneb@google.com>2016-07-11 23:02:18 +0000
commitf5525670ad6c5cb9f6e33b28c85589d4df97c4da (patch)
tree4798d449492dad73f00c05aad23f4dc754ef62af /compiler-rt/lib/interception/tests
parentde1be7171a7fe2471761487eeac795035f885aea (diff)
downloadbcm5719-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.cc497
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
OpenPOWER on IntegriCloud