Home | History | Annotate | Line # | Download | only in tests
      1 //===-- interception_win_test.cc ------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
     11 // Tests for interception_win.h.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 #include "interception/interception.h"
     15 
     16 #include "gtest/gtest.h"
     17 
     18 // Too slow for debug build
     19 #if !SANITIZER_DEBUG
     20 #if SANITIZER_WINDOWS
     21 
     22 #define WIN32_LEAN_AND_MEAN
     23 #include <windows.h>
     24 
     25 namespace __interception {
     26 namespace {
     27 
     28 enum FunctionPrefixKind {
     29   FunctionPrefixNone,
     30   FunctionPrefixPadding,
     31   FunctionPrefixHotPatch,
     32   FunctionPrefixDetour,
     33 };
     34 
     35 typedef bool (*TestOverrideFunction)(uptr, uptr, uptr*);
     36 typedef int (*IdentityFunction)(int);
     37 
     38 #if SANITIZER_WINDOWS64
     39 
     40 const u8 kIdentityCodeWithPrologue[] = {
     41     0x55,                   // push        rbp
     42     0x48, 0x89, 0xE5,       // mov         rbp,rsp
     43     0x8B, 0xC1,             // mov         eax,ecx
     44     0x5D,                   // pop         rbp
     45     0xC3,                   // ret
     46 };
     47 
     48 const u8 kIdentityCodeWithPushPop[] = {
     49     0x55,                   // push        rbp
     50     0x48, 0x89, 0xE5,       // mov         rbp,rsp
     51     0x53,                   // push        rbx
     52     0x50,                   // push        rax
     53     0x58,                   // pop         rax
     54     0x8B, 0xC1,             // mov         rax,rcx
     55     0x5B,                   // pop         rbx
     56     0x5D,                   // pop         rbp
     57     0xC3,                   // ret
     58 };
     59 
     60 const u8 kIdentityTwiceOffset = 16;
     61 const u8 kIdentityTwice[] = {
     62     0x55,                   // push        rbp
     63     0x48, 0x89, 0xE5,       // mov         rbp,rsp
     64     0x8B, 0xC1,             // mov         eax,ecx
     65     0x5D,                   // pop         rbp
     66     0xC3,                   // ret
     67     0x90, 0x90, 0x90, 0x90,
     68     0x90, 0x90, 0x90, 0x90,
     69     0x55,                   // push        rbp
     70     0x48, 0x89, 0xE5,       // mov         rbp,rsp
     71     0x8B, 0xC1,             // mov         eax,ecx
     72     0x5D,                   // pop         rbp
     73     0xC3,                   // ret
     74 };
     75 
     76 const u8 kIdentityCodeWithMov[] = {
     77     0x89, 0xC8,             // mov         eax, ecx
     78     0xC3,                   // ret
     79 };
     80 
     81 const u8 kIdentityCodeWithJump[] = {
     82     0xE9, 0x04, 0x00, 0x00,
     83     0x00,                   // jmp + 4
     84     0xCC, 0xCC, 0xCC, 0xCC,
     85     0x89, 0xC8,             // mov         eax, ecx
     86     0xC3,                   // ret
     87 };
     88 
     89 #else
     90 
     91 const u8 kIdentityCodeWithPrologue[] = {
     92     0x55,                   // push        ebp
     93     0x8B, 0xEC,             // mov         ebp,esp
     94     0x8B, 0x45, 0x08,       // mov         eax,dword ptr [ebp + 8]
     95     0x5D,                   // pop         ebp
     96     0xC3,                   // ret
     97 };
     98 
     99 const u8 kIdentityCodeWithPushPop[] = {
    100     0x55,                   // push        ebp
    101     0x8B, 0xEC,             // mov         ebp,esp
    102     0x53,                   // push        ebx
    103     0x50,                   // push        eax
    104     0x58,                   // pop         eax
    105     0x8B, 0x45, 0x08,       // mov         eax,dword ptr [ebp + 8]
    106     0x5B,                   // pop         ebx
    107     0x5D,                   // pop         ebp
    108     0xC3,                   // ret
    109 };
    110 
    111 const u8 kIdentityTwiceOffset = 8;
    112 const u8 kIdentityTwice[] = {
    113     0x55,                   // push        ebp
    114     0x8B, 0xEC,             // mov         ebp,esp
    115     0x8B, 0x45, 0x08,       // mov         eax,dword ptr [ebp + 8]
    116     0x5D,                   // pop         ebp
    117     0xC3,                   // ret
    118     0x55,                   // push        ebp
    119     0x8B, 0xEC,             // mov         ebp,esp
    120     0x8B, 0x45, 0x08,       // mov         eax,dword ptr [ebp + 8]
    121     0x5D,                   // pop         ebp
    122     0xC3,                   // ret
    123 };
    124 
    125 const u8 kIdentityCodeWithMov[] = {
    126     0x8B, 0x44, 0x24, 0x04, // mov         eax,dword ptr [esp + 4]
    127     0xC3,                   // ret
    128 };
    129 
    130 const u8 kIdentityCodeWithJump[] = {
    131     0xE9, 0x04, 0x00, 0x00,
    132     0x00,                   // jmp + 4
    133     0xCC, 0xCC, 0xCC, 0xCC,
    134     0x8B, 0x44, 0x24, 0x04, // mov         eax,dword ptr [esp + 4]
    135     0xC3,                   // ret
    136 };
    137 
    138 #endif
    139 
    140 const u8 kPatchableCode1[] = {
    141     0xB8, 0x4B, 0x00, 0x00, 0x00,   // mov eax,4B
    142     0x33, 0xC9,                     // xor ecx,ecx
    143     0xC3,                           // ret
    144 };
    145 
    146 const u8 kPatchableCode2[] = {
    147     0x55,                           // push ebp
    148     0x8B, 0xEC,                     // mov ebp,esp
    149     0x33, 0xC0,                     // xor eax,eax
    150     0x5D,                           // pop ebp
    151     0xC3,                           // ret
    152 };
    153 
    154 const u8 kPatchableCode3[] = {
    155     0x55,                           // push ebp
    156     0x8B, 0xEC,                     // mov ebp,esp
    157     0x6A, 0x00,                     // push 0
    158     0xE8, 0x3D, 0xFF, 0xFF, 0xFF,   // call <func>
    159 };
    160 
    161 const u8 kPatchableCode4[] = {
    162     0xE9, 0xCC, 0xCC, 0xCC, 0xCC,   // jmp <label>
    163     0x90, 0x90, 0x90, 0x90,
    164 };
    165 
    166 const u8 kPatchableCode5[] = {
    167     0x55,                                      // push    ebp
    168     0x8b, 0xec,                                // mov     ebp,esp
    169     0x8d, 0xa4, 0x24, 0x30, 0xfd, 0xff, 0xff,  // lea     esp,[esp-2D0h]
    170     0x54,                                      // push    esp
    171 };
    172 
    173 #if SANITIZER_WINDOWS64
    174 u8 kLoadGlobalCode[] = {
    175   0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, // mov    eax [rip + global]
    176   0xC3,                               // ret
    177 };
    178 #endif
    179 
    180 const u8 kUnpatchableCode1[] = {
    181     0xC3,                           // ret
    182 };
    183 
    184 const u8 kUnpatchableCode2[] = {
    185     0x33, 0xC9,                     // xor ecx,ecx
    186     0xC3,                           // ret
    187 };
    188 
    189 const u8 kUnpatchableCode3[] = {
    190     0x75, 0xCC,                     // jne <label>
    191     0x33, 0xC9,                     // xor ecx,ecx
    192     0xC3,                           // ret
    193 };
    194 
    195 const u8 kUnpatchableCode4[] = {
    196     0x74, 0xCC,                     // jne <label>
    197     0x33, 0xC9,                     // xor ecx,ecx
    198     0xC3,                           // ret
    199 };
    200 
    201 const u8 kUnpatchableCode5[] = {
    202     0xEB, 0x02,                     // jmp <label>
    203     0x33, 0xC9,                     // xor ecx,ecx
    204     0xC3,                           // ret
    205 };
    206 
    207 const u8 kUnpatchableCode6[] = {
    208     0xE8, 0xCC, 0xCC, 0xCC, 0xCC,   // call <func>
    209     0x90, 0x90, 0x90, 0x90,
    210 };
    211 
    212 // A buffer holding the dynamically generated code under test.
    213 u8* ActiveCode;
    214 const size_t ActiveCodeLength = 4096;
    215 
    216 int InterceptorFunction(int x);
    217 
    218 /// Allocate code memory more than 2GB away from Base.
    219 u8 *AllocateCode2GBAway(u8 *Base) {
    220   // Find a 64K aligned location after Base plus 2GB.
    221   size_t TwoGB = 0x80000000;
    222   size_t AllocGranularity = 0x10000;
    223   Base = (u8 *)((((uptr)Base + TwoGB + AllocGranularity)) & ~(AllocGranularity - 1));
    224 
    225   // Check if that location is free, and if not, loop over regions until we find
    226   // one that is.
    227   MEMORY_BASIC_INFORMATION mbi = {};
    228   while (sizeof(mbi) == VirtualQuery(Base, &mbi, sizeof(mbi))) {
    229     if (mbi.State & MEM_FREE) break;
    230     Base += mbi.RegionSize;
    231   }
    232 
    233   // Allocate one RWX page at the free location.
    234   return (u8 *)::VirtualAlloc(Base, ActiveCodeLength, MEM_COMMIT | MEM_RESERVE,
    235                               PAGE_EXECUTE_READWRITE);
    236 }
    237 
    238 template<class T>
    239 static void LoadActiveCode(
    240     const T &code,
    241     uptr *entry_point,
    242     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
    243   if (ActiveCode == nullptr) {
    244     ActiveCode = AllocateCode2GBAway((u8*)&InterceptorFunction);
    245     ASSERT_NE(ActiveCode, nullptr) << "failed to allocate RWX memory 2GB away";
    246   }
    247 
    248   size_t position = 0;
    249 
    250   // Add padding to avoid memory violation when scanning the prefix.
    251   for (int i = 0; i < 16; ++i)
    252     ActiveCode[position++] = 0xC3;  // Instruction 'ret'.
    253 
    254   // Add function padding.
    255   size_t padding = 0;
    256   if (prefix_kind == FunctionPrefixPadding)
    257     padding = 16;
    258   else if (prefix_kind == FunctionPrefixDetour ||
    259            prefix_kind == FunctionPrefixHotPatch)
    260     padding = FIRST_32_SECOND_64(5, 6);
    261   // Insert |padding| instructions 'nop'.
    262   for (size_t i = 0; i < padding; ++i)
    263     ActiveCode[position++] = 0x90;
    264 
    265   // Keep track of the entry point.
    266   *entry_point = (uptr)&ActiveCode[position];
    267 
    268   // Add the detour instruction (i.e. mov edi, edi)
    269   if (prefix_kind == FunctionPrefixDetour) {
    270 #if SANITIZER_WINDOWS64
    271     // Note that "mov edi,edi" is NOP in 32-bit only, in 64-bit it clears
    272     // higher bits of RDI.
    273     // Use 66,90H as NOP for Windows64.
    274     ActiveCode[position++] = 0x66;
    275     ActiveCode[position++] = 0x90;
    276 #else
    277     // mov edi,edi.
    278     ActiveCode[position++] = 0x8B;
    279     ActiveCode[position++] = 0xFF;
    280 #endif
    281 
    282   }
    283 
    284   // Copy the function body.
    285   for (size_t i = 0; i < sizeof(T); ++i)
    286     ActiveCode[position++] = code[i];
    287 }
    288 
    289 int InterceptorFunctionCalled;
    290 IdentityFunction InterceptedRealFunction;
    291 
    292 int InterceptorFunction(int x) {
    293   ++InterceptorFunctionCalled;
    294   return InterceptedRealFunction(x);
    295 }
    296 
    297 }  // namespace
    298 
    299 // Tests for interception_win.h
    300 TEST(Interception, InternalGetProcAddress) {
    301   HMODULE ntdll_handle = ::GetModuleHandle("ntdll");
    302   ASSERT_NE(nullptr, ntdll_handle);
    303   uptr DbgPrint_expected = (uptr)::GetProcAddress(ntdll_handle, "DbgPrint");
    304   uptr isdigit_expected = (uptr)::GetProcAddress(ntdll_handle, "isdigit");
    305   uptr DbgPrint_adddress = InternalGetProcAddress(ntdll_handle, "DbgPrint");
    306   uptr isdigit_address = InternalGetProcAddress(ntdll_handle, "isdigit");
    307 
    308   EXPECT_EQ(DbgPrint_expected, DbgPrint_adddress);
    309   EXPECT_EQ(isdigit_expected, isdigit_address);
    310   EXPECT_NE(DbgPrint_adddress, isdigit_address);
    311 }
    312 
    313 template<class T>
    314 static void TestIdentityFunctionPatching(
    315     const T &code,
    316     TestOverrideFunction override,
    317     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
    318   uptr identity_address;
    319   LoadActiveCode(code, &identity_address, prefix_kind);
    320   IdentityFunction identity = (IdentityFunction)identity_address;
    321 
    322   // Validate behavior before dynamic patching.
    323   InterceptorFunctionCalled = 0;
    324   EXPECT_EQ(0, identity(0));
    325   EXPECT_EQ(42, identity(42));
    326   EXPECT_EQ(0, InterceptorFunctionCalled);
    327 
    328   // Patch the function.
    329   uptr real_identity_address = 0;
    330   bool success = override(identity_address,
    331                          (uptr)&InterceptorFunction,
    332                          &real_identity_address);
    333   EXPECT_TRUE(success);
    334   EXPECT_NE(0U, real_identity_address);
    335   IdentityFunction real_identity = (IdentityFunction)real_identity_address;
    336   InterceptedRealFunction = real_identity;
    337 
    338   // Don't run tests if hooking failed or the real function is not valid.
    339   if (!success || !real_identity_address)
    340     return;
    341 
    342   // Calling the redirected function.
    343   InterceptorFunctionCalled = 0;
    344   EXPECT_EQ(0, identity(0));
    345   EXPECT_EQ(42, identity(42));
    346   EXPECT_EQ(2, InterceptorFunctionCalled);
    347 
    348   // Calling the real function.
    349   InterceptorFunctionCalled = 0;
    350   EXPECT_EQ(0, real_identity(0));
    351   EXPECT_EQ(42, real_identity(42));
    352   EXPECT_EQ(0, InterceptorFunctionCalled);
    353 
    354   TestOnlyReleaseTrampolineRegions();
    355 }
    356 
    357 #if !SANITIZER_WINDOWS64
    358 TEST(Interception, OverrideFunctionWithDetour) {
    359   TestOverrideFunction override = OverrideFunctionWithDetour;
    360   FunctionPrefixKind prefix = FunctionPrefixDetour;
    361   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
    362   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
    363   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
    364   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
    365 }
    366 #endif  // !SANITIZER_WINDOWS64
    367 
    368 TEST(Interception, OverrideFunctionWithRedirectJump) {
    369   TestOverrideFunction override = OverrideFunctionWithRedirectJump;
    370   TestIdentityFunctionPatching(kIdentityCodeWithJump, override);
    371 }
    372 
    373 TEST(Interception, OverrideFunctionWithHotPatch) {
    374   TestOverrideFunction override = OverrideFunctionWithHotPatch;
    375   FunctionPrefixKind prefix = FunctionPrefixHotPatch;
    376   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
    377 }
    378 
    379 TEST(Interception, OverrideFunctionWithTrampoline) {
    380   TestOverrideFunction override = OverrideFunctionWithTrampoline;
    381   FunctionPrefixKind prefix = FunctionPrefixNone;
    382   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
    383   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
    384 
    385   prefix = FunctionPrefixPadding;
    386   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
    387   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
    388 }
    389 
    390 TEST(Interception, OverrideFunction) {
    391   TestOverrideFunction override = OverrideFunction;
    392   FunctionPrefixKind prefix = FunctionPrefixNone;
    393   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
    394   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
    395   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
    396 
    397   prefix = FunctionPrefixPadding;
    398   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
    399   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
    400   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
    401   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
    402 
    403   prefix = FunctionPrefixHotPatch;
    404   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
    405   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
    406   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
    407   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
    408 
    409   prefix = FunctionPrefixDetour;
    410   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
    411   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
    412   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
    413   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
    414 }
    415 
    416 template<class T>
    417 static void TestIdentityFunctionMultiplePatching(
    418     const T &code,
    419     TestOverrideFunction override,
    420     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
    421   uptr identity_address;
    422   LoadActiveCode(code, &identity_address, prefix_kind);
    423 
    424   // Patch the function.
    425   uptr real_identity_address = 0;
    426   bool success = override(identity_address,
    427                           (uptr)&InterceptorFunction,
    428                           &real_identity_address);
    429   EXPECT_TRUE(success);
    430   EXPECT_NE(0U, real_identity_address);
    431 
    432   // Re-patching the function should not work.
    433   success = override(identity_address,
    434                      (uptr)&InterceptorFunction,
    435                      &real_identity_address);
    436   EXPECT_FALSE(success);
    437 
    438   TestOnlyReleaseTrampolineRegions();
    439 }
    440 
    441 TEST(Interception, OverrideFunctionMultiplePatchingIsFailing) {
    442 #if !SANITIZER_WINDOWS64
    443   TestIdentityFunctionMultiplePatching(kIdentityCodeWithPrologue,
    444                                        OverrideFunctionWithDetour,
    445                                        FunctionPrefixDetour);
    446 #endif
    447 
    448   TestIdentityFunctionMultiplePatching(kIdentityCodeWithMov,
    449                                        OverrideFunctionWithHotPatch,
    450                                        FunctionPrefixHotPatch);
    451 
    452   TestIdentityFunctionMultiplePatching(kIdentityCodeWithPushPop,
    453                                        OverrideFunctionWithTrampoline,
    454                                        FunctionPrefixPadding);
    455 }
    456 
    457 TEST(Interception, OverrideFunctionTwice) {
    458   uptr identity_address1;
    459   LoadActiveCode(kIdentityTwice, &identity_address1);
    460   uptr identity_address2 = identity_address1 + kIdentityTwiceOffset;
    461   IdentityFunction identity1 = (IdentityFunction)identity_address1;
    462   IdentityFunction identity2 = (IdentityFunction)identity_address2;
    463 
    464   // Patch the two functions.
    465   uptr real_identity_address = 0;
    466   EXPECT_TRUE(OverrideFunction(identity_address1,
    467                                (uptr)&InterceptorFunction,
    468                                &real_identity_address));
    469   EXPECT_TRUE(OverrideFunction(identity_address2,
    470                                (uptr)&InterceptorFunction,
    471                                &real_identity_address));
    472   IdentityFunction real_identity = (IdentityFunction)real_identity_address;
    473   InterceptedRealFunction = real_identity;
    474 
    475   // Calling the redirected function.
    476   InterceptorFunctionCalled = 0;
    477   EXPECT_EQ(42, identity1(42));
    478   EXPECT_EQ(42, identity2(42));
    479   EXPECT_EQ(2, InterceptorFunctionCalled);
    480 
    481   TestOnlyReleaseTrampolineRegions();
    482 }
    483 
    484 template<class T>
    485 static bool TestFunctionPatching(
    486     const T &code,
    487     TestOverrideFunction override,
    488     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
    489   uptr address;
    490   LoadActiveCode(code, &address, prefix_kind);
    491   uptr unused_real_address = 0;
    492   bool result = override(
    493       address, (uptr)&InterceptorFunction, &unused_real_address);
    494 
    495   TestOnlyReleaseTrampolineRegions();
    496   return result;
    497 }
    498 
    499 TEST(Interception, PatchableFunction) {
    500   TestOverrideFunction override = OverrideFunction;
    501   // Test without function padding.
    502   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override));
    503   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override));
    504 #if SANITIZER_WINDOWS64
    505   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
    506 #else
    507   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override));
    508 #endif
    509   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override));
    510   EXPECT_TRUE(TestFunctionPatching(kPatchableCode5, override));
    511 
    512 #if SANITIZER_WINDOWS64
    513   EXPECT_TRUE(TestFunctionPatching(kLoadGlobalCode, override));
    514 #endif
    515 
    516   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
    517   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
    518   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
    519   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
    520   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
    521   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
    522 }
    523 
    524 #if !SANITIZER_WINDOWS64
    525 TEST(Interception, PatchableFunctionWithDetour) {
    526   TestOverrideFunction override = OverrideFunctionWithDetour;
    527   // Without the prefix, no function can be detoured.
    528   EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override));
    529   EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override));
    530   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
    531   EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override));
    532   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
    533   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
    534   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
    535   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
    536   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
    537   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
    538 
    539   // With the prefix, all functions can be detoured.
    540   FunctionPrefixKind prefix = FunctionPrefixDetour;
    541   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
    542   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
    543   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
    544   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix));
    545   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
    546   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
    547   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
    548   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
    549   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
    550   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
    551 }
    552 #endif  // !SANITIZER_WINDOWS64
    553 
    554 TEST(Interception, PatchableFunctionWithRedirectJump) {
    555   TestOverrideFunction override = OverrideFunctionWithRedirectJump;
    556   EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override));
    557   EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override));
    558   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
    559   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override));
    560   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
    561   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
    562   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
    563   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
    564   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
    565   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
    566 }
    567 
    568 TEST(Interception, PatchableFunctionWithHotPatch) {
    569   TestOverrideFunction override = OverrideFunctionWithHotPatch;
    570   FunctionPrefixKind prefix = FunctionPrefixHotPatch;
    571 
    572   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
    573   EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override, prefix));
    574   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
    575   EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix));
    576 
    577   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
    578   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
    579   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
    580   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
    581   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
    582   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
    583 }
    584 
    585 TEST(Interception, PatchableFunctionWithTrampoline) {
    586   TestOverrideFunction override = OverrideFunctionWithTrampoline;
    587   FunctionPrefixKind prefix = FunctionPrefixPadding;
    588 
    589   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
    590   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
    591 #if SANITIZER_WINDOWS64
    592   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
    593 #else
    594   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
    595 #endif
    596   EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix));
    597 
    598   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
    599   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
    600   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
    601   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
    602   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
    603   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
    604 }
    605 
    606 TEST(Interception, PatchableFunctionPadding) {
    607   TestOverrideFunction override = OverrideFunction;
    608   FunctionPrefixKind prefix = FunctionPrefixPadding;
    609 
    610   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
    611   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
    612 #if SANITIZER_WINDOWS64
    613   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
    614 #else
    615   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
    616 #endif
    617   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix));
    618 
    619   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
    620   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
    621   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
    622   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
    623   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
    624   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
    625 }
    626 
    627 TEST(Interception, EmptyExportTable) {
    628   // We try to get a pointer to a function from an executable that doesn't
    629   // export any symbol (empty export table).
    630   uptr FunPtr = InternalGetProcAddress((void *)GetModuleHandleA(0), "example");
    631   EXPECT_EQ(0U, FunPtr);
    632 }
    633 
    634 }  // namespace __interception
    635 
    636 #endif  // SANITIZER_WINDOWS
    637 #endif  // #if !SANITIZER_DEBUG
    638