1 //===-- interception_win_test.cpp -----------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
10 // Tests for interception_win.h.
12 //===----------------------------------------------------------------------===//
13 #include "interception/interception.h"
15 #include "gtest/gtest.h"
17 // Too slow for debug build
18 // Disabling for ARM64 since testcases are x86/x64 assembly.
21 # if !SANITIZER_WINDOWS_ARM64
25 # define WIN32_LEAN_AND_MEAN
28 namespace __interception
{
31 enum FunctionPrefixKind
{
33 FunctionPrefixPadding
,
34 FunctionPrefixHotPatch
,
38 typedef bool (*TestOverrideFunction
)(uptr
, uptr
, uptr
*);
39 typedef int (*IdentityFunction
)(int);
41 #if SANITIZER_WINDOWS64
43 const u8 kIdentityCodeWithPrologue
[] = {
45 0x48, 0x89, 0xE5, // mov rbp,rsp
46 0x8B, 0xC1, // mov eax,ecx
51 const u8 kIdentityCodeWithPushPop
[] = {
53 0x48, 0x89, 0xE5, // mov rbp,rsp
57 0x8B, 0xC1, // mov rax,rcx
63 const u8 kIdentityTwiceOffset
= 16;
64 const u8 kIdentityTwice
[] = {
66 0x48, 0x89, 0xE5, // mov rbp,rsp
67 0x8B, 0xC1, // mov eax,ecx
70 0x90, 0x90, 0x90, 0x90,
71 0x90, 0x90, 0x90, 0x90,
73 0x48, 0x89, 0xE5, // mov rbp,rsp
74 0x8B, 0xC1, // mov eax,ecx
79 const u8 kIdentityCodeWithMov
[] = {
80 0x89, 0xC8, // mov eax, ecx
84 const u8 kIdentityCodeWithJump
[] = {
85 0xE9, 0x04, 0x00, 0x00,
87 0xCC, 0xCC, 0xCC, 0xCC,
88 0x89, 0xC8, // mov eax, ecx
92 const u8 kIdentityCodeWithJumpBackwards
[] = {
93 0x89, 0xC8, // mov eax, ecx
95 0xE9, 0xF8, 0xFF, 0xFF,
97 0xCC, 0xCC, 0xCC, 0xCC,
99 const u8 kIdentityCodeWithJumpBackwardsOffset
= 3;
103 const u8 kIdentityCodeWithPrologue
[] = {
105 0x8B, 0xEC, // mov ebp,esp
106 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8]
111 const u8 kIdentityCodeWithPushPop
[] = {
113 0x8B, 0xEC, // mov ebp,esp
117 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8]
123 const u8 kIdentityTwiceOffset
= 8;
124 const u8 kIdentityTwice
[] = {
126 0x8B, 0xEC, // mov ebp,esp
127 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8]
131 0x8B, 0xEC, // mov ebp,esp
132 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8]
137 const u8 kIdentityCodeWithMov
[] = {
138 0x8B, 0x44, 0x24, 0x04, // mov eax,dword ptr [esp + 4]
142 const u8 kIdentityCodeWithJump
[] = {
143 0xE9, 0x04, 0x00, 0x00,
145 0xCC, 0xCC, 0xCC, 0xCC,
146 0x8B, 0x44, 0x24, 0x04, // mov eax,dword ptr [esp + 4]
150 const u8 kIdentityCodeWithJumpBackwards
[] = {
151 0x8B, 0x44, 0x24, 0x04, // mov eax,dword ptr [esp + 4]
153 0xE9, 0xF6, 0xFF, 0xFF,
155 0xCC, 0xCC, 0xCC, 0xCC,
157 const u8 kIdentityCodeWithJumpBackwardsOffset
= 5;
161 const u8 kPatchableCode1
[] = {
162 0xB8, 0x4B, 0x00, 0x00, 0x00, // mov eax,4B
163 0x33, 0xC9, // xor ecx,ecx
167 const u8 kPatchableCode2
[] = {
169 0x8B, 0xEC, // mov ebp,esp
170 0x33, 0xC0, // xor eax,eax
175 const u8 kPatchableCode3
[] = {
177 0x8B, 0xEC, // mov ebp,esp
178 0x6A, 0x00, // push 0
179 0xE8, 0x3D, 0xFF, 0xFF, 0xFF, // call <func>
182 const u8 kPatchableCode4
[] = {
183 0xE9, 0xCC, 0xCC, 0xCC, 0xCC, // jmp <label>
184 0x90, 0x90, 0x90, 0x90,
187 const u8 kPatchableCode5
[] = {
189 0x8b, 0xec, // mov ebp,esp
190 0x8d, 0xa4, 0x24, 0x30, 0xfd, 0xff, 0xff, // lea esp,[esp-2D0h]
194 #if SANITIZER_WINDOWS64
195 u8 kLoadGlobalCode
[] = {
196 0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, // mov eax [rip + global]
201 const u8 kUnpatchableCode1
[] = {
205 const u8 kUnpatchableCode2
[] = {
206 0x33, 0xC9, // xor ecx,ecx
210 const u8 kUnpatchableCode3
[] = {
211 0x75, 0xCC, // jne <label>
212 0x33, 0xC9, // xor ecx,ecx
216 const u8 kUnpatchableCode4
[] = {
217 0x74, 0xCC, // jne <label>
218 0x33, 0xC9, // xor ecx,ecx
222 const u8 kUnpatchableCode5
[] = {
223 0xEB, 0x02, // jmp <label>
224 0x33, 0xC9, // xor ecx,ecx
228 const u8 kUnpatchableCode6
[] = {
229 0xE8, 0xCC, 0xCC, 0xCC, 0xCC, // call <func>
230 0x90, 0x90, 0x90, 0x90,
233 const u8 kUnpatchableCode7
[] = {
234 0x33, 0xc0, // xor eax,eax
235 0x48, 0x85, 0xd2, // test rdx,rdx
236 0x74, 0x10, // je +16 (unpatchable)
239 const u8 kUnpatchableCode8
[] = {
240 0x48, 0x8b, 0xc1, // mov rax,rcx
241 0x0f, 0xb7, 0x10, // movzx edx,word ptr [rax]
242 0x48, 0x83, 0xc0, 0x02, // add rax,2
243 0x66, 0x85, 0xd2, // test dx,dx
244 0x75, 0xf4, // jne -12 (unpatchable)
247 const u8 kUnpatchableCode9
[] = {
248 0x4c, 0x8b, 0xc1, // mov r8,rcx
249 0x8a, 0x01, // mov al,byte ptr [rcx]
250 0x48, 0xff, 0xc1, // inc rcx
251 0x84, 0xc0, // test al,al
252 0x75, 0xf7, // jne -9 (unpatchable)
255 const u8 kPatchableCode6
[] = {
256 0x48, 0x89, 0x54, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], rdx
257 0x33, 0xC9, // xor ecx,ecx
261 const u8 kPatchableCode7
[] = {
262 0x4c, 0x89, 0x4c, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], r9
263 0x33, 0xC9, // xor ecx,ecx
267 const u8 kPatchableCode8
[] = {
268 0x4c, 0x89, 0x44, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], r8
269 0x33, 0xC9, // xor ecx,ecx
273 const u8 kPatchableCode9
[] = {
274 0x8a, 0x01, // al,byte ptr [rcx]
275 0x45, 0x33, 0xc0, // xor r8d,r8d
276 0x84, 0xc0, // test al,al
279 const u8 kPatchableCode10
[] = {
280 0x45, 0x33, 0xc0, // xor r8d,r8d
281 0x41, 0x8b, 0xc0, // mov eax,r8d
282 0x48, 0x85, 0xd2, // test rdx,rdx
285 const u8 kPatchableCode11
[] = {
286 0x48, 0x83, 0xec, 0x38, // sub rsp,38h
287 0x83, 0x64, 0x24, 0x28, 0x00, // and dword ptr [rsp+28h],0
290 const u8 kPatchableCode12
[] = {
295 0x8b, 0x6c, 0x24, 0x18, // mov ebp,dword ptr[esp+18h]
298 const u8 kPatchableCode13
[] = {
303 0x8b, 0x5c, 0x24, 0x14, // mov ebx,dword ptr[esp+14h]
306 const u8 kPatchableCode14
[] = {
308 0x89, 0xe5, // mov ebp,esp
314 const u8 kUnsupportedCode1
[] = {
321 // A buffer holding the dynamically generated code under test.
323 const size_t ActiveCodeLength
= 4096;
325 int InterceptorFunction(int x
);
327 /// Allocate code memory more than 2GB away from Base.
328 u8
*AllocateCode2GBAway(u8
*Base
) {
329 // Find a 64K aligned location after Base plus 2GB.
330 size_t TwoGB
= 0x80000000;
331 size_t AllocGranularity
= 0x10000;
332 Base
= (u8
*)((((uptr
)Base
+ TwoGB
+ AllocGranularity
)) & ~(AllocGranularity
- 1));
334 // Check if that location is free, and if not, loop over regions until we find
336 MEMORY_BASIC_INFORMATION mbi
= {};
337 while (sizeof(mbi
) == VirtualQuery(Base
, &mbi
, sizeof(mbi
))) {
338 if (mbi
.State
& MEM_FREE
) break;
339 Base
+= mbi
.RegionSize
;
342 // Allocate one RWX page at the free location.
343 return (u8
*)::VirtualAlloc(Base
, ActiveCodeLength
, MEM_COMMIT
| MEM_RESERVE
,
344 PAGE_EXECUTE_READWRITE
);
348 static void LoadActiveCode(
351 FunctionPrefixKind prefix_kind
= FunctionPrefixNone
) {
352 if (ActiveCode
== nullptr) {
353 ActiveCode
= AllocateCode2GBAway((u8
*)&InterceptorFunction
);
354 ASSERT_NE(ActiveCode
, nullptr) << "failed to allocate RWX memory 2GB away";
359 // Add padding to avoid memory violation when scanning the prefix.
360 for (int i
= 0; i
< 16; ++i
)
361 ActiveCode
[position
++] = 0xC3; // Instruction 'ret'.
363 // Add function padding.
365 if (prefix_kind
== FunctionPrefixPadding
)
367 else if (prefix_kind
== FunctionPrefixDetour
||
368 prefix_kind
== FunctionPrefixHotPatch
)
369 padding
= FIRST_32_SECOND_64(5, 6);
370 // Insert |padding| instructions 'nop'.
371 for (size_t i
= 0; i
< padding
; ++i
)
372 ActiveCode
[position
++] = 0x90;
374 // Keep track of the entry point.
375 *entry_point
= (uptr
)&ActiveCode
[position
];
377 // Add the detour instruction (i.e. mov edi, edi)
378 if (prefix_kind
== FunctionPrefixDetour
) {
379 #if SANITIZER_WINDOWS64
380 // Note that "mov edi,edi" is NOP in 32-bit only, in 64-bit it clears
381 // higher bits of RDI.
382 // Use 66,90H as NOP for Windows64.
383 ActiveCode
[position
++] = 0x66;
384 ActiveCode
[position
++] = 0x90;
387 ActiveCode
[position
++] = 0x8B;
388 ActiveCode
[position
++] = 0xFF;
393 // Copy the function body.
394 for (size_t i
= 0; i
< sizeof(T
); ++i
)
395 ActiveCode
[position
++] = code
[i
];
398 int InterceptorFunctionCalled
;
399 IdentityFunction InterceptedRealFunction
;
401 int InterceptorFunction(int x
) {
402 ++InterceptorFunctionCalled
;
403 return InterceptedRealFunction(x
);
408 // Tests for interception_win.h
409 TEST(Interception
, InternalGetProcAddress
) {
410 HMODULE ntdll_handle
= ::GetModuleHandle("ntdll");
411 ASSERT_NE(nullptr, ntdll_handle
);
412 uptr DbgPrint_expected
= (uptr
)::GetProcAddress(ntdll_handle
, "DbgPrint");
413 uptr isdigit_expected
= (uptr
)::GetProcAddress(ntdll_handle
, "isdigit");
414 uptr DbgPrint_adddress
= InternalGetProcAddress(ntdll_handle
, "DbgPrint");
415 uptr isdigit_address
= InternalGetProcAddress(ntdll_handle
, "isdigit");
417 EXPECT_EQ(DbgPrint_expected
, DbgPrint_adddress
);
418 EXPECT_EQ(isdigit_expected
, isdigit_address
);
419 EXPECT_NE(DbgPrint_adddress
, isdigit_address
);
423 static void TestIdentityFunctionPatching(
424 const T
&code
, TestOverrideFunction override
,
425 FunctionPrefixKind prefix_kind
= FunctionPrefixNone
,
426 int function_start_offset
= 0) {
427 uptr identity_address
;
428 LoadActiveCode(code
, &identity_address
, prefix_kind
);
429 identity_address
+= function_start_offset
;
430 IdentityFunction identity
= (IdentityFunction
)identity_address
;
432 // Validate behavior before dynamic patching.
433 InterceptorFunctionCalled
= 0;
434 EXPECT_EQ(0, identity(0));
435 EXPECT_EQ(42, identity(42));
436 EXPECT_EQ(0, InterceptorFunctionCalled
);
438 // Patch the function.
439 uptr real_identity_address
= 0;
440 bool success
= override(identity_address
,
441 (uptr
)&InterceptorFunction
,
442 &real_identity_address
);
443 EXPECT_TRUE(success
);
444 EXPECT_NE(0U, real_identity_address
);
445 IdentityFunction real_identity
= (IdentityFunction
)real_identity_address
;
446 InterceptedRealFunction
= real_identity
;
448 // Don't run tests if hooking failed or the real function is not valid.
449 if (!success
|| !real_identity_address
)
452 // Calling the redirected function.
453 InterceptorFunctionCalled
= 0;
454 EXPECT_EQ(0, identity(0));
455 EXPECT_EQ(42, identity(42));
456 EXPECT_EQ(2, InterceptorFunctionCalled
);
458 // Calling the real function.
459 InterceptorFunctionCalled
= 0;
460 EXPECT_EQ(0, real_identity(0));
461 EXPECT_EQ(42, real_identity(42));
462 EXPECT_EQ(0, InterceptorFunctionCalled
);
464 TestOnlyReleaseTrampolineRegions();
467 # if !SANITIZER_WINDOWS64
468 TEST(Interception
, OverrideFunctionWithDetour
) {
469 TestOverrideFunction override
= OverrideFunctionWithDetour
;
470 FunctionPrefixKind prefix
= FunctionPrefixDetour
;
471 TestIdentityFunctionPatching(kIdentityCodeWithPrologue
, override
, prefix
);
472 TestIdentityFunctionPatching(kIdentityCodeWithPushPop
, override
, prefix
);
473 TestIdentityFunctionPatching(kIdentityCodeWithMov
, override
, prefix
);
474 TestIdentityFunctionPatching(kIdentityCodeWithJump
, override
, prefix
);
476 #endif // !SANITIZER_WINDOWS64
478 TEST(Interception
, OverrideFunctionWithRedirectJump
) {
479 TestOverrideFunction override
= OverrideFunctionWithRedirectJump
;
480 TestIdentityFunctionPatching(kIdentityCodeWithJump
, override
);
481 TestIdentityFunctionPatching(kIdentityCodeWithJumpBackwards
, override
,
483 kIdentityCodeWithJumpBackwardsOffset
);
486 TEST(Interception
, OverrideFunctionWithHotPatch
) {
487 TestOverrideFunction override
= OverrideFunctionWithHotPatch
;
488 FunctionPrefixKind prefix
= FunctionPrefixHotPatch
;
489 TestIdentityFunctionPatching(kIdentityCodeWithMov
, override
, prefix
);
492 TEST(Interception
, OverrideFunctionWithTrampoline
) {
493 TestOverrideFunction override
= OverrideFunctionWithTrampoline
;
494 FunctionPrefixKind prefix
= FunctionPrefixNone
;
495 TestIdentityFunctionPatching(kIdentityCodeWithPrologue
, override
, prefix
);
496 TestIdentityFunctionPatching(kIdentityCodeWithPushPop
, override
, prefix
);
498 prefix
= FunctionPrefixPadding
;
499 TestIdentityFunctionPatching(kIdentityCodeWithPrologue
, override
, prefix
);
500 TestIdentityFunctionPatching(kIdentityCodeWithPushPop
, override
, prefix
);
503 TEST(Interception
, OverrideFunction
) {
504 TestOverrideFunction override
= OverrideFunction
;
505 FunctionPrefixKind prefix
= FunctionPrefixNone
;
506 TestIdentityFunctionPatching(kIdentityCodeWithPrologue
, override
, prefix
);
507 TestIdentityFunctionPatching(kIdentityCodeWithPushPop
, override
, prefix
);
508 TestIdentityFunctionPatching(kIdentityCodeWithJump
, override
, prefix
);
510 prefix
= FunctionPrefixPadding
;
511 TestIdentityFunctionPatching(kIdentityCodeWithPrologue
, override
, prefix
);
512 TestIdentityFunctionPatching(kIdentityCodeWithPushPop
, override
, prefix
);
513 TestIdentityFunctionPatching(kIdentityCodeWithMov
, override
, prefix
);
514 TestIdentityFunctionPatching(kIdentityCodeWithJump
, override
, prefix
);
516 prefix
= FunctionPrefixHotPatch
;
517 TestIdentityFunctionPatching(kIdentityCodeWithPrologue
, override
, prefix
);
518 TestIdentityFunctionPatching(kIdentityCodeWithPushPop
, override
, prefix
);
519 TestIdentityFunctionPatching(kIdentityCodeWithMov
, override
, prefix
);
520 TestIdentityFunctionPatching(kIdentityCodeWithJump
, override
, prefix
);
522 prefix
= FunctionPrefixDetour
;
523 TestIdentityFunctionPatching(kIdentityCodeWithPrologue
, override
, prefix
);
524 TestIdentityFunctionPatching(kIdentityCodeWithPushPop
, override
, prefix
);
525 TestIdentityFunctionPatching(kIdentityCodeWithMov
, override
, prefix
);
526 TestIdentityFunctionPatching(kIdentityCodeWithJump
, override
, prefix
);
530 static void TestIdentityFunctionMultiplePatching(
532 TestOverrideFunction override
,
533 FunctionPrefixKind prefix_kind
= FunctionPrefixNone
) {
534 uptr identity_address
;
535 LoadActiveCode(code
, &identity_address
, prefix_kind
);
537 // Patch the function.
538 uptr real_identity_address
= 0;
539 bool success
= override(identity_address
,
540 (uptr
)&InterceptorFunction
,
541 &real_identity_address
);
542 EXPECT_TRUE(success
);
543 EXPECT_NE(0U, real_identity_address
);
545 // Re-patching the function should not work.
546 success
= override(identity_address
,
547 (uptr
)&InterceptorFunction
,
548 &real_identity_address
);
549 EXPECT_FALSE(success
);
551 TestOnlyReleaseTrampolineRegions();
554 TEST(Interception
, OverrideFunctionMultiplePatchingIsFailing
) {
555 #if !SANITIZER_WINDOWS64
556 TestIdentityFunctionMultiplePatching(kIdentityCodeWithPrologue
,
557 OverrideFunctionWithDetour
,
558 FunctionPrefixDetour
);
561 TestIdentityFunctionMultiplePatching(kIdentityCodeWithMov
,
562 OverrideFunctionWithHotPatch
,
563 FunctionPrefixHotPatch
);
565 TestIdentityFunctionMultiplePatching(kIdentityCodeWithPushPop
,
566 OverrideFunctionWithTrampoline
,
567 FunctionPrefixPadding
);
570 TEST(Interception
, OverrideFunctionTwice
) {
571 uptr identity_address1
;
572 LoadActiveCode(kIdentityTwice
, &identity_address1
);
573 uptr identity_address2
= identity_address1
+ kIdentityTwiceOffset
;
574 IdentityFunction identity1
= (IdentityFunction
)identity_address1
;
575 IdentityFunction identity2
= (IdentityFunction
)identity_address2
;
577 // Patch the two functions.
578 uptr real_identity_address
= 0;
579 EXPECT_TRUE(OverrideFunction(identity_address1
,
580 (uptr
)&InterceptorFunction
,
581 &real_identity_address
));
582 EXPECT_TRUE(OverrideFunction(identity_address2
,
583 (uptr
)&InterceptorFunction
,
584 &real_identity_address
));
585 IdentityFunction real_identity
= (IdentityFunction
)real_identity_address
;
586 InterceptedRealFunction
= real_identity
;
588 // Calling the redirected function.
589 InterceptorFunctionCalled
= 0;
590 EXPECT_EQ(42, identity1(42));
591 EXPECT_EQ(42, identity2(42));
592 EXPECT_EQ(2, InterceptorFunctionCalled
);
594 TestOnlyReleaseTrampolineRegions();
598 static bool TestFunctionPatching(
600 TestOverrideFunction override
,
601 FunctionPrefixKind prefix_kind
= FunctionPrefixNone
) {
603 LoadActiveCode(code
, &address
, prefix_kind
);
604 uptr unused_real_address
= 0;
605 bool result
= override(
606 address
, (uptr
)&InterceptorFunction
, &unused_real_address
);
608 TestOnlyReleaseTrampolineRegions();
612 TEST(Interception
, PatchableFunction
) {
613 TestOverrideFunction override
= OverrideFunction
;
614 // Test without function padding.
615 EXPECT_TRUE(TestFunctionPatching(kPatchableCode1
, override
));
616 EXPECT_TRUE(TestFunctionPatching(kPatchableCode2
, override
));
617 #if SANITIZER_WINDOWS64
618 EXPECT_FALSE(TestFunctionPatching(kPatchableCode3
, override
));
620 EXPECT_TRUE(TestFunctionPatching(kPatchableCode3
, override
));
622 EXPECT_TRUE(TestFunctionPatching(kPatchableCode4
, override
));
623 EXPECT_TRUE(TestFunctionPatching(kPatchableCode5
, override
));
624 #if SANITIZER_WINDOWS64
625 EXPECT_TRUE(TestFunctionPatching(kLoadGlobalCode
, override
));
628 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1
, override
));
629 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2
, override
));
630 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3
, override
));
631 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4
, override
));
632 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5
, override
));
633 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6
, override
));
636 #if !SANITIZER_WINDOWS64
637 TEST(Interception
, PatchableFunctionWithDetour
) {
638 TestOverrideFunction override
= OverrideFunctionWithDetour
;
639 // Without the prefix, no function can be detoured.
640 EXPECT_FALSE(TestFunctionPatching(kPatchableCode1
, override
));
641 EXPECT_FALSE(TestFunctionPatching(kPatchableCode2
, override
));
642 EXPECT_FALSE(TestFunctionPatching(kPatchableCode3
, override
));
643 EXPECT_FALSE(TestFunctionPatching(kPatchableCode4
, override
));
644 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1
, override
));
645 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2
, override
));
646 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3
, override
));
647 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4
, override
));
648 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5
, override
));
649 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6
, override
));
651 // With the prefix, all functions can be detoured.
652 FunctionPrefixKind prefix
= FunctionPrefixDetour
;
653 EXPECT_TRUE(TestFunctionPatching(kPatchableCode1
, override
, prefix
));
654 EXPECT_TRUE(TestFunctionPatching(kPatchableCode2
, override
, prefix
));
655 EXPECT_TRUE(TestFunctionPatching(kPatchableCode3
, override
, prefix
));
656 EXPECT_TRUE(TestFunctionPatching(kPatchableCode4
, override
, prefix
));
657 EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode1
, override
, prefix
));
658 EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2
, override
, prefix
));
659 EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode3
, override
, prefix
));
660 EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode4
, override
, prefix
));
661 EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode5
, override
, prefix
));
662 EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode6
, override
, prefix
));
664 #endif // !SANITIZER_WINDOWS64
666 TEST(Interception
, PatchableFunctionWithRedirectJump
) {
667 TestOverrideFunction override
= OverrideFunctionWithRedirectJump
;
668 EXPECT_FALSE(TestFunctionPatching(kPatchableCode1
, override
));
669 EXPECT_FALSE(TestFunctionPatching(kPatchableCode2
, override
));
670 EXPECT_FALSE(TestFunctionPatching(kPatchableCode3
, override
));
671 EXPECT_TRUE(TestFunctionPatching(kPatchableCode4
, override
));
672 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1
, override
));
673 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2
, override
));
674 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3
, override
));
675 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4
, override
));
676 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5
, override
));
677 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6
, override
));
680 TEST(Interception
, PatchableFunctionWithHotPatch
) {
681 TestOverrideFunction override
= OverrideFunctionWithHotPatch
;
682 FunctionPrefixKind prefix
= FunctionPrefixHotPatch
;
684 EXPECT_TRUE(TestFunctionPatching(kPatchableCode1
, override
, prefix
));
685 EXPECT_FALSE(TestFunctionPatching(kPatchableCode2
, override
, prefix
));
686 EXPECT_FALSE(TestFunctionPatching(kPatchableCode3
, override
, prefix
));
687 EXPECT_FALSE(TestFunctionPatching(kPatchableCode4
, override
, prefix
));
688 #if SANITIZER_WINDOWS64
689 EXPECT_TRUE(TestFunctionPatching(kPatchableCode6
, override
, prefix
));
690 EXPECT_TRUE(TestFunctionPatching(kPatchableCode7
, override
, prefix
));
691 EXPECT_TRUE(TestFunctionPatching(kPatchableCode8
, override
, prefix
));
693 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1
, override
, prefix
));
694 EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2
, override
, prefix
));
695 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3
, override
, prefix
));
696 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4
, override
, prefix
));
697 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5
, override
, prefix
));
698 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6
, override
, prefix
));
701 TEST(Interception
, PatchableFunctionWithTrampoline
) {
702 TestOverrideFunction override
= OverrideFunctionWithTrampoline
;
703 FunctionPrefixKind prefix
= FunctionPrefixPadding
;
705 EXPECT_TRUE(TestFunctionPatching(kPatchableCode1
, override
, prefix
));
706 EXPECT_TRUE(TestFunctionPatching(kPatchableCode2
, override
, prefix
));
707 #if SANITIZER_WINDOWS64
708 EXPECT_FALSE(TestFunctionPatching(kPatchableCode3
, override
, prefix
));
709 EXPECT_TRUE(TestFunctionPatching(kPatchableCode9
, override
, prefix
));
710 EXPECT_TRUE(TestFunctionPatching(kPatchableCode10
, override
, prefix
));
711 EXPECT_TRUE(TestFunctionPatching(kPatchableCode11
, override
, prefix
));
712 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode7
, override
, prefix
));
713 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode8
, override
, prefix
));
714 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode9
, override
, prefix
));
716 EXPECT_TRUE(TestFunctionPatching(kPatchableCode3
, override
, prefix
));
717 EXPECT_TRUE(TestFunctionPatching(kPatchableCode12
, override
, prefix
));
718 EXPECT_TRUE(TestFunctionPatching(kPatchableCode13
, override
, prefix
));
720 EXPECT_FALSE(TestFunctionPatching(kPatchableCode4
, override
, prefix
));
721 EXPECT_TRUE(TestFunctionPatching(kPatchableCode14
, override
, prefix
));
723 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1
, override
, prefix
));
724 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2
, override
, prefix
));
725 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3
, override
, prefix
));
726 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4
, override
, prefix
));
727 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5
, override
, prefix
));
728 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6
, override
, prefix
));
731 TEST(Interception
, UnsupportedInstructionWithTrampoline
) {
732 TestOverrideFunction override
= OverrideFunctionWithTrampoline
;
733 FunctionPrefixKind prefix
= FunctionPrefixPadding
;
735 static bool reportCalled
;
736 reportCalled
= false;
739 static void Report(const char *format
, ...) {
741 FAIL() << "Report called more times than expected";
744 "interception_win: unhandled instruction at %p: %02x %02x %02x %02x "
745 "%02x %02x %02x %02x\n",
748 va_start(args
, format
);
749 u8
*ptr
= va_arg(args
, u8
*);
750 for (int i
= 0; i
< 8; i
++) EXPECT_EQ(kUnsupportedCode1
[i
], ptr
[i
]);
752 for (int i
= 0; i
< 8; i
++) {
753 bytes
[i
] = va_arg(args
, int);
754 EXPECT_EQ(kUnsupportedCode1
[i
], bytes
[i
]);
760 SetErrorReportCallback(Local::Report
);
761 EXPECT_FALSE(TestFunctionPatching(kUnsupportedCode1
, override
, prefix
));
762 SetErrorReportCallback(nullptr);
765 ADD_FAILURE() << "Report not called";
768 TEST(Interception
, PatchableFunctionPadding
) {
769 TestOverrideFunction override
= OverrideFunction
;
770 FunctionPrefixKind prefix
= FunctionPrefixPadding
;
772 EXPECT_TRUE(TestFunctionPatching(kPatchableCode1
, override
, prefix
));
773 EXPECT_TRUE(TestFunctionPatching(kPatchableCode2
, override
, prefix
));
774 #if SANITIZER_WINDOWS64
775 EXPECT_FALSE(TestFunctionPatching(kPatchableCode3
, override
, prefix
));
777 EXPECT_TRUE(TestFunctionPatching(kPatchableCode3
, override
, prefix
));
779 EXPECT_TRUE(TestFunctionPatching(kPatchableCode4
, override
, prefix
));
781 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1
, override
, prefix
));
782 EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2
, override
, prefix
));
783 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3
, override
, prefix
));
784 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4
, override
, prefix
));
785 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5
, override
, prefix
));
786 EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6
, override
, prefix
));
789 TEST(Interception
, EmptyExportTable
) {
790 // We try to get a pointer to a function from an executable that doesn't
791 // export any symbol (empty export table).
792 uptr FunPtr
= InternalGetProcAddress((void *)GetModuleHandleA(0), "example");
793 EXPECT_EQ(0U, FunPtr
);
796 } // namespace __interception
798 # endif // !SANITIZER_WINDOWS_ARM64
799 #endif // SANITIZER_WINDOWS
800 #endif // #if !SANITIZER_DEBUG