13cab2bb3Spatrick //===-- interception_win_test.cpp -----------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
103cab2bb3Spatrick // Tests for interception_win.h.
113cab2bb3Spatrick //
123cab2bb3Spatrick //===----------------------------------------------------------------------===//
133cab2bb3Spatrick #include "interception/interception.h"
143cab2bb3Spatrick
153cab2bb3Spatrick #include "gtest/gtest.h"
163cab2bb3Spatrick
173cab2bb3Spatrick // Too slow for debug build
183cab2bb3Spatrick #if !SANITIZER_DEBUG
193cab2bb3Spatrick #if SANITIZER_WINDOWS
203cab2bb3Spatrick
213cab2bb3Spatrick #define WIN32_LEAN_AND_MEAN
223cab2bb3Spatrick #include <windows.h>
233cab2bb3Spatrick
243cab2bb3Spatrick namespace __interception {
253cab2bb3Spatrick namespace {
263cab2bb3Spatrick
273cab2bb3Spatrick enum FunctionPrefixKind {
283cab2bb3Spatrick FunctionPrefixNone,
293cab2bb3Spatrick FunctionPrefixPadding,
303cab2bb3Spatrick FunctionPrefixHotPatch,
313cab2bb3Spatrick FunctionPrefixDetour,
323cab2bb3Spatrick };
333cab2bb3Spatrick
343cab2bb3Spatrick typedef bool (*TestOverrideFunction)(uptr, uptr, uptr*);
353cab2bb3Spatrick typedef int (*IdentityFunction)(int);
363cab2bb3Spatrick
373cab2bb3Spatrick #if SANITIZER_WINDOWS64
383cab2bb3Spatrick
393cab2bb3Spatrick const u8 kIdentityCodeWithPrologue[] = {
403cab2bb3Spatrick 0x55, // push rbp
413cab2bb3Spatrick 0x48, 0x89, 0xE5, // mov rbp,rsp
423cab2bb3Spatrick 0x8B, 0xC1, // mov eax,ecx
433cab2bb3Spatrick 0x5D, // pop rbp
443cab2bb3Spatrick 0xC3, // ret
453cab2bb3Spatrick };
463cab2bb3Spatrick
473cab2bb3Spatrick const u8 kIdentityCodeWithPushPop[] = {
483cab2bb3Spatrick 0x55, // push rbp
493cab2bb3Spatrick 0x48, 0x89, 0xE5, // mov rbp,rsp
503cab2bb3Spatrick 0x53, // push rbx
513cab2bb3Spatrick 0x50, // push rax
523cab2bb3Spatrick 0x58, // pop rax
533cab2bb3Spatrick 0x8B, 0xC1, // mov rax,rcx
543cab2bb3Spatrick 0x5B, // pop rbx
553cab2bb3Spatrick 0x5D, // pop rbp
563cab2bb3Spatrick 0xC3, // ret
573cab2bb3Spatrick };
583cab2bb3Spatrick
593cab2bb3Spatrick const u8 kIdentityTwiceOffset = 16;
603cab2bb3Spatrick const u8 kIdentityTwice[] = {
613cab2bb3Spatrick 0x55, // push rbp
623cab2bb3Spatrick 0x48, 0x89, 0xE5, // mov rbp,rsp
633cab2bb3Spatrick 0x8B, 0xC1, // mov eax,ecx
643cab2bb3Spatrick 0x5D, // pop rbp
653cab2bb3Spatrick 0xC3, // ret
663cab2bb3Spatrick 0x90, 0x90, 0x90, 0x90,
673cab2bb3Spatrick 0x90, 0x90, 0x90, 0x90,
683cab2bb3Spatrick 0x55, // push rbp
693cab2bb3Spatrick 0x48, 0x89, 0xE5, // mov rbp,rsp
703cab2bb3Spatrick 0x8B, 0xC1, // mov eax,ecx
713cab2bb3Spatrick 0x5D, // pop rbp
723cab2bb3Spatrick 0xC3, // ret
733cab2bb3Spatrick };
743cab2bb3Spatrick
753cab2bb3Spatrick const u8 kIdentityCodeWithMov[] = {
763cab2bb3Spatrick 0x89, 0xC8, // mov eax, ecx
773cab2bb3Spatrick 0xC3, // ret
783cab2bb3Spatrick };
793cab2bb3Spatrick
803cab2bb3Spatrick const u8 kIdentityCodeWithJump[] = {
813cab2bb3Spatrick 0xE9, 0x04, 0x00, 0x00,
823cab2bb3Spatrick 0x00, // jmp + 4
833cab2bb3Spatrick 0xCC, 0xCC, 0xCC, 0xCC,
843cab2bb3Spatrick 0x89, 0xC8, // mov eax, ecx
853cab2bb3Spatrick 0xC3, // ret
863cab2bb3Spatrick };
873cab2bb3Spatrick
88*810390e3Srobert const u8 kIdentityCodeWithJumpBackwards[] = {
89*810390e3Srobert 0x89, 0xC8, // mov eax, ecx
90*810390e3Srobert 0xC3, // ret
91*810390e3Srobert 0xE9, 0xF8, 0xFF, 0xFF,
92*810390e3Srobert 0xFF, // jmp - 8
93*810390e3Srobert 0xCC, 0xCC, 0xCC, 0xCC,
94*810390e3Srobert };
95*810390e3Srobert const u8 kIdentityCodeWithJumpBackwardsOffset = 3;
96*810390e3Srobert
973cab2bb3Spatrick # else
983cab2bb3Spatrick
993cab2bb3Spatrick const u8 kIdentityCodeWithPrologue[] = {
1003cab2bb3Spatrick 0x55, // push ebp
1013cab2bb3Spatrick 0x8B, 0xEC, // mov ebp,esp
1023cab2bb3Spatrick 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8]
1033cab2bb3Spatrick 0x5D, // pop ebp
1043cab2bb3Spatrick 0xC3, // ret
1053cab2bb3Spatrick };
1063cab2bb3Spatrick
1073cab2bb3Spatrick const u8 kIdentityCodeWithPushPop[] = {
1083cab2bb3Spatrick 0x55, // push ebp
1093cab2bb3Spatrick 0x8B, 0xEC, // mov ebp,esp
1103cab2bb3Spatrick 0x53, // push ebx
1113cab2bb3Spatrick 0x50, // push eax
1123cab2bb3Spatrick 0x58, // pop eax
1133cab2bb3Spatrick 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8]
1143cab2bb3Spatrick 0x5B, // pop ebx
1153cab2bb3Spatrick 0x5D, // pop ebp
1163cab2bb3Spatrick 0xC3, // ret
1173cab2bb3Spatrick };
1183cab2bb3Spatrick
1193cab2bb3Spatrick const u8 kIdentityTwiceOffset = 8;
1203cab2bb3Spatrick const u8 kIdentityTwice[] = {
1213cab2bb3Spatrick 0x55, // push ebp
1223cab2bb3Spatrick 0x8B, 0xEC, // mov ebp,esp
1233cab2bb3Spatrick 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8]
1243cab2bb3Spatrick 0x5D, // pop ebp
1253cab2bb3Spatrick 0xC3, // ret
1263cab2bb3Spatrick 0x55, // push ebp
1273cab2bb3Spatrick 0x8B, 0xEC, // mov ebp,esp
1283cab2bb3Spatrick 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8]
1293cab2bb3Spatrick 0x5D, // pop ebp
1303cab2bb3Spatrick 0xC3, // ret
1313cab2bb3Spatrick };
1323cab2bb3Spatrick
1333cab2bb3Spatrick const u8 kIdentityCodeWithMov[] = {
1343cab2bb3Spatrick 0x8B, 0x44, 0x24, 0x04, // mov eax,dword ptr [esp + 4]
1353cab2bb3Spatrick 0xC3, // ret
1363cab2bb3Spatrick };
1373cab2bb3Spatrick
1383cab2bb3Spatrick const u8 kIdentityCodeWithJump[] = {
1393cab2bb3Spatrick 0xE9, 0x04, 0x00, 0x00,
1403cab2bb3Spatrick 0x00, // jmp + 4
1413cab2bb3Spatrick 0xCC, 0xCC, 0xCC, 0xCC,
1423cab2bb3Spatrick 0x8B, 0x44, 0x24, 0x04, // mov eax,dword ptr [esp + 4]
1433cab2bb3Spatrick 0xC3, // ret
1443cab2bb3Spatrick };
1453cab2bb3Spatrick
146*810390e3Srobert const u8 kIdentityCodeWithJumpBackwards[] = {
147*810390e3Srobert 0x8B, 0x44, 0x24, 0x04, // mov eax,dword ptr [esp + 4]
148*810390e3Srobert 0xC3, // ret
149*810390e3Srobert 0xE9, 0xF6, 0xFF, 0xFF,
150*810390e3Srobert 0xFF, // jmp - 10
151*810390e3Srobert 0xCC, 0xCC, 0xCC, 0xCC,
152*810390e3Srobert };
153*810390e3Srobert const u8 kIdentityCodeWithJumpBackwardsOffset = 5;
154*810390e3Srobert
1553cab2bb3Spatrick # endif
1563cab2bb3Spatrick
1573cab2bb3Spatrick const u8 kPatchableCode1[] = {
1583cab2bb3Spatrick 0xB8, 0x4B, 0x00, 0x00, 0x00, // mov eax,4B
1593cab2bb3Spatrick 0x33, 0xC9, // xor ecx,ecx
1603cab2bb3Spatrick 0xC3, // ret
1613cab2bb3Spatrick };
1623cab2bb3Spatrick
1633cab2bb3Spatrick const u8 kPatchableCode2[] = {
1643cab2bb3Spatrick 0x55, // push ebp
1653cab2bb3Spatrick 0x8B, 0xEC, // mov ebp,esp
1663cab2bb3Spatrick 0x33, 0xC0, // xor eax,eax
1673cab2bb3Spatrick 0x5D, // pop ebp
1683cab2bb3Spatrick 0xC3, // ret
1693cab2bb3Spatrick };
1703cab2bb3Spatrick
1713cab2bb3Spatrick const u8 kPatchableCode3[] = {
1723cab2bb3Spatrick 0x55, // push ebp
1733cab2bb3Spatrick 0x8B, 0xEC, // mov ebp,esp
1743cab2bb3Spatrick 0x6A, 0x00, // push 0
1753cab2bb3Spatrick 0xE8, 0x3D, 0xFF, 0xFF, 0xFF, // call <func>
1763cab2bb3Spatrick };
1773cab2bb3Spatrick
1783cab2bb3Spatrick const u8 kPatchableCode4[] = {
1793cab2bb3Spatrick 0xE9, 0xCC, 0xCC, 0xCC, 0xCC, // jmp <label>
1803cab2bb3Spatrick 0x90, 0x90, 0x90, 0x90,
1813cab2bb3Spatrick };
1823cab2bb3Spatrick
1833cab2bb3Spatrick const u8 kPatchableCode5[] = {
1843cab2bb3Spatrick 0x55, // push ebp
1853cab2bb3Spatrick 0x8b, 0xec, // mov ebp,esp
1863cab2bb3Spatrick 0x8d, 0xa4, 0x24, 0x30, 0xfd, 0xff, 0xff, // lea esp,[esp-2D0h]
1873cab2bb3Spatrick 0x54, // push esp
1883cab2bb3Spatrick };
1893cab2bb3Spatrick
1903cab2bb3Spatrick #if SANITIZER_WINDOWS64
1913cab2bb3Spatrick u8 kLoadGlobalCode[] = {
1923cab2bb3Spatrick 0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, // mov eax [rip + global]
1933cab2bb3Spatrick 0xC3, // ret
1943cab2bb3Spatrick };
1953cab2bb3Spatrick #endif
1963cab2bb3Spatrick
1973cab2bb3Spatrick const u8 kUnpatchableCode1[] = {
1983cab2bb3Spatrick 0xC3, // ret
1993cab2bb3Spatrick };
2003cab2bb3Spatrick
2013cab2bb3Spatrick const u8 kUnpatchableCode2[] = {
2023cab2bb3Spatrick 0x33, 0xC9, // xor ecx,ecx
2033cab2bb3Spatrick 0xC3, // ret
2043cab2bb3Spatrick };
2053cab2bb3Spatrick
2063cab2bb3Spatrick const u8 kUnpatchableCode3[] = {
2073cab2bb3Spatrick 0x75, 0xCC, // jne <label>
2083cab2bb3Spatrick 0x33, 0xC9, // xor ecx,ecx
2093cab2bb3Spatrick 0xC3, // ret
2103cab2bb3Spatrick };
2113cab2bb3Spatrick
2123cab2bb3Spatrick const u8 kUnpatchableCode4[] = {
2133cab2bb3Spatrick 0x74, 0xCC, // jne <label>
2143cab2bb3Spatrick 0x33, 0xC9, // xor ecx,ecx
2153cab2bb3Spatrick 0xC3, // ret
2163cab2bb3Spatrick };
2173cab2bb3Spatrick
2183cab2bb3Spatrick const u8 kUnpatchableCode5[] = {
2193cab2bb3Spatrick 0xEB, 0x02, // jmp <label>
2203cab2bb3Spatrick 0x33, 0xC9, // xor ecx,ecx
2213cab2bb3Spatrick 0xC3, // ret
2223cab2bb3Spatrick };
2233cab2bb3Spatrick
2243cab2bb3Spatrick const u8 kUnpatchableCode6[] = {
2253cab2bb3Spatrick 0xE8, 0xCC, 0xCC, 0xCC, 0xCC, // call <func>
2263cab2bb3Spatrick 0x90, 0x90, 0x90, 0x90,
2273cab2bb3Spatrick };
2283cab2bb3Spatrick
229*810390e3Srobert const u8 kUnpatchableCode7[] = {
230*810390e3Srobert 0x33, 0xc0, // xor eax,eax
231*810390e3Srobert 0x48, 0x85, 0xd2, // test rdx,rdx
232*810390e3Srobert 0x74, 0x10, // je +16 (unpatchable)
233*810390e3Srobert };
234*810390e3Srobert
235*810390e3Srobert const u8 kUnpatchableCode8[] = {
236*810390e3Srobert 0x48, 0x8b, 0xc1, // mov rax,rcx
237*810390e3Srobert 0x0f, 0xb7, 0x10, // movzx edx,word ptr [rax]
238*810390e3Srobert 0x48, 0x83, 0xc0, 0x02, // add rax,2
239*810390e3Srobert 0x66, 0x85, 0xd2, // test dx,dx
240*810390e3Srobert 0x75, 0xf4, // jne -12 (unpatchable)
241*810390e3Srobert };
242*810390e3Srobert
243*810390e3Srobert const u8 kUnpatchableCode9[] = {
244*810390e3Srobert 0x4c, 0x8b, 0xc1, // mov r8,rcx
245*810390e3Srobert 0x8a, 0x01, // mov al,byte ptr [rcx]
246*810390e3Srobert 0x48, 0xff, 0xc1, // inc rcx
247*810390e3Srobert 0x84, 0xc0, // test al,al
248*810390e3Srobert 0x75, 0xf7, // jne -9 (unpatchable)
249*810390e3Srobert };
250*810390e3Srobert
2513cab2bb3Spatrick const u8 kPatchableCode6[] = {
2523cab2bb3Spatrick 0x48, 0x89, 0x54, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], rdx
2533cab2bb3Spatrick 0x33, 0xC9, // xor ecx,ecx
2543cab2bb3Spatrick 0xC3, // ret
2553cab2bb3Spatrick };
2563cab2bb3Spatrick
2573cab2bb3Spatrick const u8 kPatchableCode7[] = {
2583cab2bb3Spatrick 0x4c, 0x89, 0x4c, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], r9
2593cab2bb3Spatrick 0x33, 0xC9, // xor ecx,ecx
2603cab2bb3Spatrick 0xC3, // ret
2613cab2bb3Spatrick };
2623cab2bb3Spatrick
2633cab2bb3Spatrick const u8 kPatchableCode8[] = {
2643cab2bb3Spatrick 0x4c, 0x89, 0x44, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], r8
2653cab2bb3Spatrick 0x33, 0xC9, // xor ecx,ecx
2663cab2bb3Spatrick 0xC3, // ret
2673cab2bb3Spatrick };
2683cab2bb3Spatrick
269*810390e3Srobert const u8 kPatchableCode9[] = {
270*810390e3Srobert 0x8a, 0x01, // al,byte ptr [rcx]
271*810390e3Srobert 0x45, 0x33, 0xc0, // xor r8d,r8d
272*810390e3Srobert 0x84, 0xc0, // test al,al
273*810390e3Srobert };
274*810390e3Srobert
275*810390e3Srobert const u8 kPatchableCode10[] = {
276*810390e3Srobert 0x45, 0x33, 0xc0, // xor r8d,r8d
277*810390e3Srobert 0x41, 0x8b, 0xc0, // mov eax,r8d
278*810390e3Srobert 0x48, 0x85, 0xd2, // test rdx,rdx
279*810390e3Srobert };
280*810390e3Srobert
281*810390e3Srobert const u8 kPatchableCode11[] = {
282*810390e3Srobert 0x48, 0x83, 0xec, 0x38, // sub rsp,38h
283*810390e3Srobert 0x83, 0x64, 0x24, 0x28, 0x00, // and dword ptr [rsp+28h],0
284*810390e3Srobert };
285*810390e3Srobert
2863cab2bb3Spatrick // A buffer holding the dynamically generated code under test.
2873cab2bb3Spatrick u8* ActiveCode;
2883cab2bb3Spatrick const size_t ActiveCodeLength = 4096;
2893cab2bb3Spatrick
2903cab2bb3Spatrick int InterceptorFunction(int x);
2913cab2bb3Spatrick
2923cab2bb3Spatrick /// Allocate code memory more than 2GB away from Base.
AllocateCode2GBAway(u8 * Base)2933cab2bb3Spatrick u8 *AllocateCode2GBAway(u8 *Base) {
2943cab2bb3Spatrick // Find a 64K aligned location after Base plus 2GB.
2953cab2bb3Spatrick size_t TwoGB = 0x80000000;
2963cab2bb3Spatrick size_t AllocGranularity = 0x10000;
2973cab2bb3Spatrick Base = (u8 *)((((uptr)Base + TwoGB + AllocGranularity)) & ~(AllocGranularity - 1));
2983cab2bb3Spatrick
2993cab2bb3Spatrick // Check if that location is free, and if not, loop over regions until we find
3003cab2bb3Spatrick // one that is.
3013cab2bb3Spatrick MEMORY_BASIC_INFORMATION mbi = {};
3023cab2bb3Spatrick while (sizeof(mbi) == VirtualQuery(Base, &mbi, sizeof(mbi))) {
3033cab2bb3Spatrick if (mbi.State & MEM_FREE) break;
3043cab2bb3Spatrick Base += mbi.RegionSize;
3053cab2bb3Spatrick }
3063cab2bb3Spatrick
3073cab2bb3Spatrick // Allocate one RWX page at the free location.
3083cab2bb3Spatrick return (u8 *)::VirtualAlloc(Base, ActiveCodeLength, MEM_COMMIT | MEM_RESERVE,
3093cab2bb3Spatrick PAGE_EXECUTE_READWRITE);
3103cab2bb3Spatrick }
3113cab2bb3Spatrick
3123cab2bb3Spatrick template<class T>
LoadActiveCode(const T & code,uptr * entry_point,FunctionPrefixKind prefix_kind=FunctionPrefixNone)3133cab2bb3Spatrick static void LoadActiveCode(
3143cab2bb3Spatrick const T &code,
3153cab2bb3Spatrick uptr *entry_point,
3163cab2bb3Spatrick FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
3173cab2bb3Spatrick if (ActiveCode == nullptr) {
3183cab2bb3Spatrick ActiveCode = AllocateCode2GBAway((u8*)&InterceptorFunction);
3193cab2bb3Spatrick ASSERT_NE(ActiveCode, nullptr) << "failed to allocate RWX memory 2GB away";
3203cab2bb3Spatrick }
3213cab2bb3Spatrick
3223cab2bb3Spatrick size_t position = 0;
3233cab2bb3Spatrick
3243cab2bb3Spatrick // Add padding to avoid memory violation when scanning the prefix.
3253cab2bb3Spatrick for (int i = 0; i < 16; ++i)
3263cab2bb3Spatrick ActiveCode[position++] = 0xC3; // Instruction 'ret'.
3273cab2bb3Spatrick
3283cab2bb3Spatrick // Add function padding.
3293cab2bb3Spatrick size_t padding = 0;
3303cab2bb3Spatrick if (prefix_kind == FunctionPrefixPadding)
3313cab2bb3Spatrick padding = 16;
3323cab2bb3Spatrick else if (prefix_kind == FunctionPrefixDetour ||
3333cab2bb3Spatrick prefix_kind == FunctionPrefixHotPatch)
3343cab2bb3Spatrick padding = FIRST_32_SECOND_64(5, 6);
3353cab2bb3Spatrick // Insert |padding| instructions 'nop'.
3363cab2bb3Spatrick for (size_t i = 0; i < padding; ++i)
3373cab2bb3Spatrick ActiveCode[position++] = 0x90;
3383cab2bb3Spatrick
3393cab2bb3Spatrick // Keep track of the entry point.
3403cab2bb3Spatrick *entry_point = (uptr)&ActiveCode[position];
3413cab2bb3Spatrick
3423cab2bb3Spatrick // Add the detour instruction (i.e. mov edi, edi)
3433cab2bb3Spatrick if (prefix_kind == FunctionPrefixDetour) {
3443cab2bb3Spatrick #if SANITIZER_WINDOWS64
3453cab2bb3Spatrick // Note that "mov edi,edi" is NOP in 32-bit only, in 64-bit it clears
3463cab2bb3Spatrick // higher bits of RDI.
3473cab2bb3Spatrick // Use 66,90H as NOP for Windows64.
3483cab2bb3Spatrick ActiveCode[position++] = 0x66;
3493cab2bb3Spatrick ActiveCode[position++] = 0x90;
3503cab2bb3Spatrick #else
3513cab2bb3Spatrick // mov edi,edi.
3523cab2bb3Spatrick ActiveCode[position++] = 0x8B;
3533cab2bb3Spatrick ActiveCode[position++] = 0xFF;
3543cab2bb3Spatrick #endif
3553cab2bb3Spatrick
3563cab2bb3Spatrick }
3573cab2bb3Spatrick
3583cab2bb3Spatrick // Copy the function body.
3593cab2bb3Spatrick for (size_t i = 0; i < sizeof(T); ++i)
3603cab2bb3Spatrick ActiveCode[position++] = code[i];
3613cab2bb3Spatrick }
3623cab2bb3Spatrick
3633cab2bb3Spatrick int InterceptorFunctionCalled;
3643cab2bb3Spatrick IdentityFunction InterceptedRealFunction;
3653cab2bb3Spatrick
InterceptorFunction(int x)3663cab2bb3Spatrick int InterceptorFunction(int x) {
3673cab2bb3Spatrick ++InterceptorFunctionCalled;
3683cab2bb3Spatrick return InterceptedRealFunction(x);
3693cab2bb3Spatrick }
3703cab2bb3Spatrick
3713cab2bb3Spatrick } // namespace
3723cab2bb3Spatrick
3733cab2bb3Spatrick // Tests for interception_win.h
TEST(Interception,InternalGetProcAddress)3743cab2bb3Spatrick TEST(Interception, InternalGetProcAddress) {
3753cab2bb3Spatrick HMODULE ntdll_handle = ::GetModuleHandle("ntdll");
3763cab2bb3Spatrick ASSERT_NE(nullptr, ntdll_handle);
3773cab2bb3Spatrick uptr DbgPrint_expected = (uptr)::GetProcAddress(ntdll_handle, "DbgPrint");
3783cab2bb3Spatrick uptr isdigit_expected = (uptr)::GetProcAddress(ntdll_handle, "isdigit");
3793cab2bb3Spatrick uptr DbgPrint_adddress = InternalGetProcAddress(ntdll_handle, "DbgPrint");
3803cab2bb3Spatrick uptr isdigit_address = InternalGetProcAddress(ntdll_handle, "isdigit");
3813cab2bb3Spatrick
3823cab2bb3Spatrick EXPECT_EQ(DbgPrint_expected, DbgPrint_adddress);
3833cab2bb3Spatrick EXPECT_EQ(isdigit_expected, isdigit_address);
3843cab2bb3Spatrick EXPECT_NE(DbgPrint_adddress, isdigit_address);
3853cab2bb3Spatrick }
3863cab2bb3Spatrick
3873cab2bb3Spatrick template <class T>
TestIdentityFunctionPatching(const T & code,TestOverrideFunction override,FunctionPrefixKind prefix_kind=FunctionPrefixNone,int function_start_offset=0)3883cab2bb3Spatrick static void TestIdentityFunctionPatching(
389*810390e3Srobert const T &code, TestOverrideFunction override,
390*810390e3Srobert FunctionPrefixKind prefix_kind = FunctionPrefixNone,
391*810390e3Srobert int function_start_offset = 0) {
3923cab2bb3Spatrick uptr identity_address;
3933cab2bb3Spatrick LoadActiveCode(code, &identity_address, prefix_kind);
394*810390e3Srobert identity_address += function_start_offset;
3953cab2bb3Spatrick IdentityFunction identity = (IdentityFunction)identity_address;
3963cab2bb3Spatrick
3973cab2bb3Spatrick // Validate behavior before dynamic patching.
3983cab2bb3Spatrick InterceptorFunctionCalled = 0;
3993cab2bb3Spatrick EXPECT_EQ(0, identity(0));
4003cab2bb3Spatrick EXPECT_EQ(42, identity(42));
4013cab2bb3Spatrick EXPECT_EQ(0, InterceptorFunctionCalled);
4023cab2bb3Spatrick
4033cab2bb3Spatrick // Patch the function.
4043cab2bb3Spatrick uptr real_identity_address = 0;
4053cab2bb3Spatrick bool success = override(identity_address,
4063cab2bb3Spatrick (uptr)&InterceptorFunction,
4073cab2bb3Spatrick &real_identity_address);
4083cab2bb3Spatrick EXPECT_TRUE(success);
4093cab2bb3Spatrick EXPECT_NE(0U, real_identity_address);
4103cab2bb3Spatrick IdentityFunction real_identity = (IdentityFunction)real_identity_address;
4113cab2bb3Spatrick InterceptedRealFunction = real_identity;
4123cab2bb3Spatrick
4133cab2bb3Spatrick // Don't run tests if hooking failed or the real function is not valid.
4143cab2bb3Spatrick if (!success || !real_identity_address)
4153cab2bb3Spatrick return;
4163cab2bb3Spatrick
4173cab2bb3Spatrick // Calling the redirected function.
4183cab2bb3Spatrick InterceptorFunctionCalled = 0;
4193cab2bb3Spatrick EXPECT_EQ(0, identity(0));
4203cab2bb3Spatrick EXPECT_EQ(42, identity(42));
4213cab2bb3Spatrick EXPECT_EQ(2, InterceptorFunctionCalled);
4223cab2bb3Spatrick
4233cab2bb3Spatrick // Calling the real function.
4243cab2bb3Spatrick InterceptorFunctionCalled = 0;
4253cab2bb3Spatrick EXPECT_EQ(0, real_identity(0));
4263cab2bb3Spatrick EXPECT_EQ(42, real_identity(42));
4273cab2bb3Spatrick EXPECT_EQ(0, InterceptorFunctionCalled);
4283cab2bb3Spatrick
4293cab2bb3Spatrick TestOnlyReleaseTrampolineRegions();
4303cab2bb3Spatrick }
4313cab2bb3Spatrick
4323cab2bb3Spatrick # if !SANITIZER_WINDOWS64
TEST(Interception,OverrideFunctionWithDetour)4333cab2bb3Spatrick TEST(Interception, OverrideFunctionWithDetour) {
4343cab2bb3Spatrick TestOverrideFunction override = OverrideFunctionWithDetour;
4353cab2bb3Spatrick FunctionPrefixKind prefix = FunctionPrefixDetour;
4363cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
4373cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
4383cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
4393cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
4403cab2bb3Spatrick }
4413cab2bb3Spatrick #endif // !SANITIZER_WINDOWS64
4423cab2bb3Spatrick
TEST(Interception,OverrideFunctionWithRedirectJump)4433cab2bb3Spatrick TEST(Interception, OverrideFunctionWithRedirectJump) {
4443cab2bb3Spatrick TestOverrideFunction override = OverrideFunctionWithRedirectJump;
4453cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithJump, override);
446*810390e3Srobert TestIdentityFunctionPatching(kIdentityCodeWithJumpBackwards, override,
447*810390e3Srobert FunctionPrefixNone,
448*810390e3Srobert kIdentityCodeWithJumpBackwardsOffset);
4493cab2bb3Spatrick }
4503cab2bb3Spatrick
TEST(Interception,OverrideFunctionWithHotPatch)4513cab2bb3Spatrick TEST(Interception, OverrideFunctionWithHotPatch) {
4523cab2bb3Spatrick TestOverrideFunction override = OverrideFunctionWithHotPatch;
4533cab2bb3Spatrick FunctionPrefixKind prefix = FunctionPrefixHotPatch;
4543cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
4553cab2bb3Spatrick }
4563cab2bb3Spatrick
TEST(Interception,OverrideFunctionWithTrampoline)4573cab2bb3Spatrick TEST(Interception, OverrideFunctionWithTrampoline) {
4583cab2bb3Spatrick TestOverrideFunction override = OverrideFunctionWithTrampoline;
4593cab2bb3Spatrick FunctionPrefixKind prefix = FunctionPrefixNone;
4603cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
4613cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
4623cab2bb3Spatrick
4633cab2bb3Spatrick prefix = FunctionPrefixPadding;
4643cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
4653cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
4663cab2bb3Spatrick }
4673cab2bb3Spatrick
TEST(Interception,OverrideFunction)4683cab2bb3Spatrick TEST(Interception, OverrideFunction) {
4693cab2bb3Spatrick TestOverrideFunction override = OverrideFunction;
4703cab2bb3Spatrick FunctionPrefixKind prefix = FunctionPrefixNone;
4713cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
4723cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
4733cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
4743cab2bb3Spatrick
4753cab2bb3Spatrick prefix = FunctionPrefixPadding;
4763cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
4773cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
4783cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
4793cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
4803cab2bb3Spatrick
4813cab2bb3Spatrick prefix = FunctionPrefixHotPatch;
4823cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
4833cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
4843cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
4853cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
4863cab2bb3Spatrick
4873cab2bb3Spatrick prefix = FunctionPrefixDetour;
4883cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
4893cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
4903cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
4913cab2bb3Spatrick TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
4923cab2bb3Spatrick }
4933cab2bb3Spatrick
4943cab2bb3Spatrick template<class T>
TestIdentityFunctionMultiplePatching(const T & code,TestOverrideFunction override,FunctionPrefixKind prefix_kind=FunctionPrefixNone)4953cab2bb3Spatrick static void TestIdentityFunctionMultiplePatching(
4963cab2bb3Spatrick const T &code,
4973cab2bb3Spatrick TestOverrideFunction override,
4983cab2bb3Spatrick FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
4993cab2bb3Spatrick uptr identity_address;
5003cab2bb3Spatrick LoadActiveCode(code, &identity_address, prefix_kind);
5013cab2bb3Spatrick
5023cab2bb3Spatrick // Patch the function.
5033cab2bb3Spatrick uptr real_identity_address = 0;
5043cab2bb3Spatrick bool success = override(identity_address,
5053cab2bb3Spatrick (uptr)&InterceptorFunction,
5063cab2bb3Spatrick &real_identity_address);
5073cab2bb3Spatrick EXPECT_TRUE(success);
5083cab2bb3Spatrick EXPECT_NE(0U, real_identity_address);
5093cab2bb3Spatrick
5103cab2bb3Spatrick // Re-patching the function should not work.
5113cab2bb3Spatrick success = override(identity_address,
5123cab2bb3Spatrick (uptr)&InterceptorFunction,
5133cab2bb3Spatrick &real_identity_address);
5143cab2bb3Spatrick EXPECT_FALSE(success);
5153cab2bb3Spatrick
5163cab2bb3Spatrick TestOnlyReleaseTrampolineRegions();
5173cab2bb3Spatrick }
5183cab2bb3Spatrick
TEST(Interception,OverrideFunctionMultiplePatchingIsFailing)5193cab2bb3Spatrick TEST(Interception, OverrideFunctionMultiplePatchingIsFailing) {
5203cab2bb3Spatrick #if !SANITIZER_WINDOWS64
5213cab2bb3Spatrick TestIdentityFunctionMultiplePatching(kIdentityCodeWithPrologue,
5223cab2bb3Spatrick OverrideFunctionWithDetour,
5233cab2bb3Spatrick FunctionPrefixDetour);
5243cab2bb3Spatrick #endif
5253cab2bb3Spatrick
5263cab2bb3Spatrick TestIdentityFunctionMultiplePatching(kIdentityCodeWithMov,
5273cab2bb3Spatrick OverrideFunctionWithHotPatch,
5283cab2bb3Spatrick FunctionPrefixHotPatch);
5293cab2bb3Spatrick
5303cab2bb3Spatrick TestIdentityFunctionMultiplePatching(kIdentityCodeWithPushPop,
5313cab2bb3Spatrick OverrideFunctionWithTrampoline,
5323cab2bb3Spatrick FunctionPrefixPadding);
5333cab2bb3Spatrick }
5343cab2bb3Spatrick
TEST(Interception,OverrideFunctionTwice)5353cab2bb3Spatrick TEST(Interception, OverrideFunctionTwice) {
5363cab2bb3Spatrick uptr identity_address1;
5373cab2bb3Spatrick LoadActiveCode(kIdentityTwice, &identity_address1);
5383cab2bb3Spatrick uptr identity_address2 = identity_address1 + kIdentityTwiceOffset;
5393cab2bb3Spatrick IdentityFunction identity1 = (IdentityFunction)identity_address1;
5403cab2bb3Spatrick IdentityFunction identity2 = (IdentityFunction)identity_address2;
5413cab2bb3Spatrick
5423cab2bb3Spatrick // Patch the two functions.
5433cab2bb3Spatrick uptr real_identity_address = 0;
5443cab2bb3Spatrick EXPECT_TRUE(OverrideFunction(identity_address1,
5453cab2bb3Spatrick (uptr)&InterceptorFunction,
5463cab2bb3Spatrick &real_identity_address));
5473cab2bb3Spatrick EXPECT_TRUE(OverrideFunction(identity_address2,
5483cab2bb3Spatrick (uptr)&InterceptorFunction,
5493cab2bb3Spatrick &real_identity_address));
5503cab2bb3Spatrick IdentityFunction real_identity = (IdentityFunction)real_identity_address;
5513cab2bb3Spatrick InterceptedRealFunction = real_identity;
5523cab2bb3Spatrick
5533cab2bb3Spatrick // Calling the redirected function.
5543cab2bb3Spatrick InterceptorFunctionCalled = 0;
5553cab2bb3Spatrick EXPECT_EQ(42, identity1(42));
5563cab2bb3Spatrick EXPECT_EQ(42, identity2(42));
5573cab2bb3Spatrick EXPECT_EQ(2, InterceptorFunctionCalled);
5583cab2bb3Spatrick
5593cab2bb3Spatrick TestOnlyReleaseTrampolineRegions();
5603cab2bb3Spatrick }
5613cab2bb3Spatrick
5623cab2bb3Spatrick template<class T>
TestFunctionPatching(const T & code,TestOverrideFunction override,FunctionPrefixKind prefix_kind=FunctionPrefixNone)5633cab2bb3Spatrick static bool TestFunctionPatching(
5643cab2bb3Spatrick const T &code,
5653cab2bb3Spatrick TestOverrideFunction override,
5663cab2bb3Spatrick FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
5673cab2bb3Spatrick uptr address;
5683cab2bb3Spatrick LoadActiveCode(code, &address, prefix_kind);
5693cab2bb3Spatrick uptr unused_real_address = 0;
5703cab2bb3Spatrick bool result = override(
5713cab2bb3Spatrick address, (uptr)&InterceptorFunction, &unused_real_address);
5723cab2bb3Spatrick
5733cab2bb3Spatrick TestOnlyReleaseTrampolineRegions();
5743cab2bb3Spatrick return result;
5753cab2bb3Spatrick }
5763cab2bb3Spatrick
TEST(Interception,PatchableFunction)5773cab2bb3Spatrick TEST(Interception, PatchableFunction) {
5783cab2bb3Spatrick TestOverrideFunction override = OverrideFunction;
5793cab2bb3Spatrick // Test without function padding.
5803cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override));
5813cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override));
5823cab2bb3Spatrick #if SANITIZER_WINDOWS64
5833cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
5843cab2bb3Spatrick #else
5853cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override));
5863cab2bb3Spatrick #endif
5873cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override));
5883cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode5, override));
5893cab2bb3Spatrick #if SANITIZER_WINDOWS64
5903cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kLoadGlobalCode, override));
5913cab2bb3Spatrick #endif
5923cab2bb3Spatrick
5933cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
5943cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
5953cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
5963cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
5973cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
5983cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
5993cab2bb3Spatrick }
6003cab2bb3Spatrick
6013cab2bb3Spatrick #if !SANITIZER_WINDOWS64
TEST(Interception,PatchableFunctionWithDetour)6023cab2bb3Spatrick TEST(Interception, PatchableFunctionWithDetour) {
6033cab2bb3Spatrick TestOverrideFunction override = OverrideFunctionWithDetour;
6043cab2bb3Spatrick // Without the prefix, no function can be detoured.
6053cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override));
6063cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override));
6073cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
6083cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override));
6093cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
6103cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
6113cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
6123cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
6133cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
6143cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
6153cab2bb3Spatrick
6163cab2bb3Spatrick // With the prefix, all functions can be detoured.
6173cab2bb3Spatrick FunctionPrefixKind prefix = FunctionPrefixDetour;
6183cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
6193cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
6203cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
6213cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix));
6223cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
6233cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
6243cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
6253cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
6263cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
6273cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
6283cab2bb3Spatrick }
6293cab2bb3Spatrick #endif // !SANITIZER_WINDOWS64
6303cab2bb3Spatrick
TEST(Interception,PatchableFunctionWithRedirectJump)6313cab2bb3Spatrick TEST(Interception, PatchableFunctionWithRedirectJump) {
6323cab2bb3Spatrick TestOverrideFunction override = OverrideFunctionWithRedirectJump;
6333cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override));
6343cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override));
6353cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
6363cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override));
6373cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
6383cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
6393cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
6403cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
6413cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
6423cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
6433cab2bb3Spatrick }
6443cab2bb3Spatrick
TEST(Interception,PatchableFunctionWithHotPatch)6453cab2bb3Spatrick TEST(Interception, PatchableFunctionWithHotPatch) {
6463cab2bb3Spatrick TestOverrideFunction override = OverrideFunctionWithHotPatch;
6473cab2bb3Spatrick FunctionPrefixKind prefix = FunctionPrefixHotPatch;
6483cab2bb3Spatrick
6493cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
6503cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override, prefix));
6513cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
6523cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix));
6533cab2bb3Spatrick #if SANITIZER_WINDOWS64
6543cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode6, override, prefix));
6553cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode7, override, prefix));
6563cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode8, override, prefix));
6573cab2bb3Spatrick #endif
6583cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
6593cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
6603cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
6613cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
6623cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
6633cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
6643cab2bb3Spatrick }
6653cab2bb3Spatrick
TEST(Interception,PatchableFunctionWithTrampoline)6663cab2bb3Spatrick TEST(Interception, PatchableFunctionWithTrampoline) {
6673cab2bb3Spatrick TestOverrideFunction override = OverrideFunctionWithTrampoline;
6683cab2bb3Spatrick FunctionPrefixKind prefix = FunctionPrefixPadding;
6693cab2bb3Spatrick
6703cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
6713cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
6723cab2bb3Spatrick #if SANITIZER_WINDOWS64
6733cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
674*810390e3Srobert EXPECT_TRUE(TestFunctionPatching(kPatchableCode9, override, prefix));
675*810390e3Srobert EXPECT_TRUE(TestFunctionPatching(kPatchableCode10, override, prefix));
676*810390e3Srobert EXPECT_TRUE(TestFunctionPatching(kPatchableCode11, override, prefix));
677*810390e3Srobert EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode7, override, prefix));
678*810390e3Srobert EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode8, override, prefix));
679*810390e3Srobert EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode9, override, prefix));
6803cab2bb3Spatrick #else
6813cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
6823cab2bb3Spatrick #endif
6833cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix));
6843cab2bb3Spatrick
6853cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
6863cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
6873cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
6883cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
6893cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
6903cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
6913cab2bb3Spatrick }
6923cab2bb3Spatrick
TEST(Interception,PatchableFunctionPadding)6933cab2bb3Spatrick TEST(Interception, PatchableFunctionPadding) {
6943cab2bb3Spatrick TestOverrideFunction override = OverrideFunction;
6953cab2bb3Spatrick FunctionPrefixKind prefix = FunctionPrefixPadding;
6963cab2bb3Spatrick
6973cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
6983cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
6993cab2bb3Spatrick #if SANITIZER_WINDOWS64
7003cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
7013cab2bb3Spatrick #else
7023cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
7033cab2bb3Spatrick #endif
7043cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix));
7053cab2bb3Spatrick
7063cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
7073cab2bb3Spatrick EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
7083cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
7093cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
7103cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
7113cab2bb3Spatrick EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
7123cab2bb3Spatrick }
7133cab2bb3Spatrick
TEST(Interception,EmptyExportTable)7143cab2bb3Spatrick TEST(Interception, EmptyExportTable) {
7153cab2bb3Spatrick // We try to get a pointer to a function from an executable that doesn't
7163cab2bb3Spatrick // export any symbol (empty export table).
7173cab2bb3Spatrick uptr FunPtr = InternalGetProcAddress((void *)GetModuleHandleA(0), "example");
7183cab2bb3Spatrick EXPECT_EQ(0U, FunPtr);
7193cab2bb3Spatrick }
7203cab2bb3Spatrick
7213cab2bb3Spatrick } // namespace __interception
7223cab2bb3Spatrick
7233cab2bb3Spatrick #endif // SANITIZER_WINDOWS
7243cab2bb3Spatrick #endif // #if !SANITIZER_DEBUG
725