xref: /openbsd-src/gnu/llvm/compiler-rt/lib/interception/tests/interception_win_test.cpp (revision 810390e339a5425391477d5d41c78d7cab2424ac)
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