]> git.proxmox.com Git - rustc.git/blame - src/libcompiler_builtins/compiler-rt/lib/interception/tests/interception_win_test.cc
New upstream version 1.25.0+dfsg1
[rustc.git] / src / libcompiler_builtins / compiler-rt / lib / interception / tests / interception_win_test.cc
CommitLineData
5bcae85e
SL
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
25namespace __interception {
26namespace {
27
28enum FunctionPrefixKind {
29 FunctionPrefixNone,
30 FunctionPrefixPadding,
31 FunctionPrefixHotPatch,
32 FunctionPrefixDetour,
33};
34
35typedef bool (*TestOverrideFunction)(uptr, uptr, uptr*);
36typedef int (*IdentityFunction)(int);
37
38#if SANITIZER_WINDOWS64
39
40const 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
48const 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
60const u8 kIdentityTwiceOffset = 16;
61const 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
76const u8 kIdentityCodeWithMov[] = {
77 0x89, 0xC8, // mov eax, ecx
78 0xC3, // ret
79};
80
81const 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
91const 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
99const 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
111const u8 kIdentityTwiceOffset = 8;
112const 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
125const u8 kIdentityCodeWithMov[] = {
126 0x8B, 0x44, 0x24, 0x04, // mov eax,dword ptr [esp + 4]
127 0xC3, // ret
128};
129
130const 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
140const u8 kPatchableCode1[] = {
141 0xB8, 0x4B, 0x00, 0x00, 0x00, // mov eax,4B
142 0x33, 0xC9, // xor ecx,ecx
143 0xC3, // ret
144};
145
146const 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
154const 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
161const u8 kPatchableCode4[] = {
162 0xE9, 0xCC, 0xCC, 0xCC, 0xCC, // jmp <label>
163 0x90, 0x90, 0x90, 0x90,
164};
165
7cac9316
XL
166const 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
2c00a5a8
XL
173#if SANITIZER_WINDOWS64
174u8 kLoadGlobalCode[] = {
175 0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, // mov eax [rip + global]
176 0xC3, // ret
177};
178#endif
179
5bcae85e
SL
180const u8 kUnpatchableCode1[] = {
181 0xC3, // ret
182};
183
184const u8 kUnpatchableCode2[] = {
185 0x33, 0xC9, // xor ecx,ecx
186 0xC3, // ret
187};
188
189const u8 kUnpatchableCode3[] = {
190 0x75, 0xCC, // jne <label>
191 0x33, 0xC9, // xor ecx,ecx
192 0xC3, // ret
193};
194
195const u8 kUnpatchableCode4[] = {
196 0x74, 0xCC, // jne <label>
197 0x33, 0xC9, // xor ecx,ecx
198 0xC3, // ret
199};
200
201const u8 kUnpatchableCode5[] = {
202 0xEB, 0x02, // jmp <label>
203 0x33, 0xC9, // xor ecx,ecx
204 0xC3, // ret
205};
206
207const 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.
213u8* ActiveCode;
7cac9316
XL
214const size_t ActiveCodeLength = 4096;
215
216int InterceptorFunction(int x);
217
218/// Allocate code memory more than 2GB away from Base.
219u8 *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}
5bcae85e
SL
237
238template<class T>
239static void LoadActiveCode(
240 const T &code,
241 uptr *entry_point,
242 FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
243 if (ActiveCode == nullptr) {
7cac9316
XL
244 ActiveCode = AllocateCode2GBAway((u8*)&InterceptorFunction);
245 ASSERT_NE(ActiveCode, nullptr) << "failed to allocate RWX memory 2GB away";
5bcae85e
SL
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
289int InterceptorFunctionCalled;
290IdentityFunction InterceptedRealFunction;
291
292int InterceptorFunction(int x) {
293 ++InterceptorFunctionCalled;
294 return InterceptedRealFunction(x);
295}
296
297} // namespace
298
299// Tests for interception_win.h
300TEST(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
313template<class T>
314static 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
358TEST(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
368TEST(Interception, OverrideFunctionWithRedirectJump) {
369 TestOverrideFunction override = OverrideFunctionWithRedirectJump;
370 TestIdentityFunctionPatching(kIdentityCodeWithJump, override);
371}
372
373TEST(Interception, OverrideFunctionWithHotPatch) {
374 TestOverrideFunction override = OverrideFunctionWithHotPatch;
375 FunctionPrefixKind prefix = FunctionPrefixHotPatch;
376 TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
377}
378
379TEST(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
390TEST(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
416template<class T>
417static 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
441TEST(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
457TEST(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
484template<class T>
485static 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
499TEST(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));
7cac9316 510 EXPECT_TRUE(TestFunctionPatching(kPatchableCode5, override));
5bcae85e 511
2c00a5a8
XL
512#if SANITIZER_WINDOWS64
513 EXPECT_TRUE(TestFunctionPatching(kLoadGlobalCode, override));
514#endif
515
5bcae85e
SL
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
525TEST(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
554TEST(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
568TEST(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
585TEST(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
606TEST(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
2c00a5a8
XL
627TEST(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
5bcae85e
SL
634} // namespace __interception
635
636#endif // SANITIZER_WINDOWS
637#endif // #if !SANITIZER_DEBUG