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