19642e337SNico Weber //===-- interception_win_test.cpp -----------------------------------------===// 29642e337SNico Weber // 39642e337SNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 49642e337SNico Weber // See https://llvm.org/LICENSE.txt for license information. 59642e337SNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 69642e337SNico Weber // 79642e337SNico Weber //===----------------------------------------------------------------------===// 89642e337SNico Weber // 99642e337SNico Weber // This file is a part of ThreadSanitizer/AddressSanitizer runtime. 109642e337SNico Weber // Tests for interception_win.h. 119642e337SNico Weber // 129642e337SNico Weber //===----------------------------------------------------------------------===// 139642e337SNico Weber #include "interception/interception.h" 149642e337SNico Weber 159642e337SNico Weber #include "gtest/gtest.h" 169642e337SNico Weber 179642e337SNico Weber // Too slow for debug build 18d79aee9fSFarzon Lotfi // Disabling for ARM64 since testcases are x86/x64 assembly. 199642e337SNico Weber #if !SANITIZER_DEBUG 209642e337SNico Weber #if SANITIZER_WINDOWS 21d79aee9fSFarzon Lotfi # if !SANITIZER_WINDOWS_ARM64 229642e337SNico Weber 230716888dSAlvin Wong # include <stdarg.h> 240716888dSAlvin Wong 259642e337SNico Weber # define WIN32_LEAN_AND_MEAN 269642e337SNico Weber # include <windows.h> 279642e337SNico Weber 289642e337SNico Weber namespace __interception { 299642e337SNico Weber namespace { 309642e337SNico Weber 319642e337SNico Weber enum FunctionPrefixKind { 329642e337SNico Weber FunctionPrefixNone, 339642e337SNico Weber FunctionPrefixPadding, 349642e337SNico Weber FunctionPrefixHotPatch, 359642e337SNico Weber FunctionPrefixDetour, 369642e337SNico Weber }; 379642e337SNico Weber 389642e337SNico Weber typedef bool (*TestOverrideFunction)(uptr, uptr, uptr*); 399642e337SNico Weber typedef int (*IdentityFunction)(int); 409642e337SNico Weber 419642e337SNico Weber #if SANITIZER_WINDOWS64 429642e337SNico Weber 439642e337SNico Weber const u8 kIdentityCodeWithPrologue[] = { 449642e337SNico Weber 0x55, // push rbp 459642e337SNico Weber 0x48, 0x89, 0xE5, // mov rbp,rsp 469642e337SNico Weber 0x8B, 0xC1, // mov eax,ecx 479642e337SNico Weber 0x5D, // pop rbp 489642e337SNico Weber 0xC3, // ret 499642e337SNico Weber }; 509642e337SNico Weber 519642e337SNico Weber const u8 kIdentityCodeWithPushPop[] = { 529642e337SNico Weber 0x55, // push rbp 539642e337SNico Weber 0x48, 0x89, 0xE5, // mov rbp,rsp 549642e337SNico Weber 0x53, // push rbx 559642e337SNico Weber 0x50, // push rax 569642e337SNico Weber 0x58, // pop rax 579642e337SNico Weber 0x8B, 0xC1, // mov rax,rcx 589642e337SNico Weber 0x5B, // pop rbx 599642e337SNico Weber 0x5D, // pop rbp 609642e337SNico Weber 0xC3, // ret 619642e337SNico Weber }; 629642e337SNico Weber 639642e337SNico Weber const u8 kIdentityTwiceOffset = 16; 649642e337SNico Weber const u8 kIdentityTwice[] = { 659642e337SNico Weber 0x55, // push rbp 669642e337SNico Weber 0x48, 0x89, 0xE5, // mov rbp,rsp 679642e337SNico Weber 0x8B, 0xC1, // mov eax,ecx 689642e337SNico Weber 0x5D, // pop rbp 699642e337SNico Weber 0xC3, // ret 709642e337SNico Weber 0x90, 0x90, 0x90, 0x90, 719642e337SNico Weber 0x90, 0x90, 0x90, 0x90, 729642e337SNico Weber 0x55, // push rbp 739642e337SNico Weber 0x48, 0x89, 0xE5, // mov rbp,rsp 749642e337SNico Weber 0x8B, 0xC1, // mov eax,ecx 759642e337SNico Weber 0x5D, // pop rbp 769642e337SNico Weber 0xC3, // ret 779642e337SNico Weber }; 789642e337SNico Weber 799642e337SNico Weber const u8 kIdentityCodeWithMov[] = { 809642e337SNico Weber 0x89, 0xC8, // mov eax, ecx 819642e337SNico Weber 0xC3, // ret 829642e337SNico Weber }; 839642e337SNico Weber 849642e337SNico Weber const u8 kIdentityCodeWithJump[] = { 859642e337SNico Weber 0xE9, 0x04, 0x00, 0x00, 869642e337SNico Weber 0x00, // jmp + 4 879642e337SNico Weber 0xCC, 0xCC, 0xCC, 0xCC, 889642e337SNico Weber 0x89, 0xC8, // mov eax, ecx 899642e337SNico Weber 0xC3, // ret 909642e337SNico Weber }; 919642e337SNico Weber 9278c033b5SMarkus Böck const u8 kIdentityCodeWithJumpBackwards[] = { 9378c033b5SMarkus Böck 0x89, 0xC8, // mov eax, ecx 9478c033b5SMarkus Böck 0xC3, // ret 9578c033b5SMarkus Böck 0xE9, 0xF8, 0xFF, 0xFF, 9678c033b5SMarkus Böck 0xFF, // jmp - 8 9778c033b5SMarkus Böck 0xCC, 0xCC, 0xCC, 0xCC, 9878c033b5SMarkus Böck }; 9978c033b5SMarkus Böck const u8 kIdentityCodeWithJumpBackwardsOffset = 3; 10078c033b5SMarkus Böck 1019642e337SNico Weber # else 1029642e337SNico Weber 1039642e337SNico Weber const u8 kIdentityCodeWithPrologue[] = { 1049642e337SNico Weber 0x55, // push ebp 1059642e337SNico Weber 0x8B, 0xEC, // mov ebp,esp 1069642e337SNico Weber 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8] 1079642e337SNico Weber 0x5D, // pop ebp 1089642e337SNico Weber 0xC3, // ret 1099642e337SNico Weber }; 1109642e337SNico Weber 1119642e337SNico Weber const u8 kIdentityCodeWithPushPop[] = { 1129642e337SNico Weber 0x55, // push ebp 1139642e337SNico Weber 0x8B, 0xEC, // mov ebp,esp 1149642e337SNico Weber 0x53, // push ebx 1159642e337SNico Weber 0x50, // push eax 1169642e337SNico Weber 0x58, // pop eax 1179642e337SNico Weber 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8] 1189642e337SNico Weber 0x5B, // pop ebx 1199642e337SNico Weber 0x5D, // pop ebp 1209642e337SNico Weber 0xC3, // ret 1219642e337SNico Weber }; 1229642e337SNico Weber 1239642e337SNico Weber const u8 kIdentityTwiceOffset = 8; 1249642e337SNico Weber const u8 kIdentityTwice[] = { 1259642e337SNico Weber 0x55, // push ebp 1269642e337SNico Weber 0x8B, 0xEC, // mov ebp,esp 1279642e337SNico Weber 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8] 1289642e337SNico Weber 0x5D, // pop ebp 1299642e337SNico Weber 0xC3, // ret 1309642e337SNico Weber 0x55, // push ebp 1319642e337SNico Weber 0x8B, 0xEC, // mov ebp,esp 1329642e337SNico Weber 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8] 1339642e337SNico Weber 0x5D, // pop ebp 1349642e337SNico Weber 0xC3, // ret 1359642e337SNico Weber }; 1369642e337SNico Weber 1379642e337SNico Weber const u8 kIdentityCodeWithMov[] = { 1389642e337SNico Weber 0x8B, 0x44, 0x24, 0x04, // mov eax,dword ptr [esp + 4] 1399642e337SNico Weber 0xC3, // ret 1409642e337SNico Weber }; 1419642e337SNico Weber 1429642e337SNico Weber const u8 kIdentityCodeWithJump[] = { 1439642e337SNico Weber 0xE9, 0x04, 0x00, 0x00, 1449642e337SNico Weber 0x00, // jmp + 4 1459642e337SNico Weber 0xCC, 0xCC, 0xCC, 0xCC, 1469642e337SNico Weber 0x8B, 0x44, 0x24, 0x04, // mov eax,dword ptr [esp + 4] 1479642e337SNico Weber 0xC3, // ret 1489642e337SNico Weber }; 1499642e337SNico Weber 15078c033b5SMarkus Böck const u8 kIdentityCodeWithJumpBackwards[] = { 15178c033b5SMarkus Böck 0x8B, 0x44, 0x24, 0x04, // mov eax,dword ptr [esp + 4] 15278c033b5SMarkus Böck 0xC3, // ret 15378c033b5SMarkus Böck 0xE9, 0xF6, 0xFF, 0xFF, 15478c033b5SMarkus Böck 0xFF, // jmp - 10 15578c033b5SMarkus Böck 0xCC, 0xCC, 0xCC, 0xCC, 15678c033b5SMarkus Böck }; 15778c033b5SMarkus Böck const u8 kIdentityCodeWithJumpBackwardsOffset = 5; 15878c033b5SMarkus Böck 1599642e337SNico Weber # endif 1609642e337SNico Weber 1619642e337SNico Weber const u8 kPatchableCode1[] = { 1629642e337SNico Weber 0xB8, 0x4B, 0x00, 0x00, 0x00, // mov eax,4B 1639642e337SNico Weber 0x33, 0xC9, // xor ecx,ecx 1649642e337SNico Weber 0xC3, // ret 1659642e337SNico Weber }; 1669642e337SNico Weber 1679642e337SNico Weber const u8 kPatchableCode2[] = { 1689642e337SNico Weber 0x55, // push ebp 1699642e337SNico Weber 0x8B, 0xEC, // mov ebp,esp 1709642e337SNico Weber 0x33, 0xC0, // xor eax,eax 1719642e337SNico Weber 0x5D, // pop ebp 1729642e337SNico Weber 0xC3, // ret 1739642e337SNico Weber }; 1749642e337SNico Weber 1759642e337SNico Weber const u8 kPatchableCode3[] = { 1769642e337SNico Weber 0x55, // push ebp 1779642e337SNico Weber 0x8B, 0xEC, // mov ebp,esp 1789642e337SNico Weber 0x6A, 0x00, // push 0 1799642e337SNico Weber 0xE8, 0x3D, 0xFF, 0xFF, 0xFF, // call <func> 1809642e337SNico Weber }; 1819642e337SNico Weber 1829642e337SNico Weber const u8 kPatchableCode4[] = { 1839642e337SNico Weber 0xE9, 0xCC, 0xCC, 0xCC, 0xCC, // jmp <label> 1849642e337SNico Weber 0x90, 0x90, 0x90, 0x90, 1859642e337SNico Weber }; 1869642e337SNico Weber 1879642e337SNico Weber const u8 kPatchableCode5[] = { 1889642e337SNico Weber 0x55, // push ebp 1899642e337SNico Weber 0x8b, 0xec, // mov ebp,esp 1909642e337SNico Weber 0x8d, 0xa4, 0x24, 0x30, 0xfd, 0xff, 0xff, // lea esp,[esp-2D0h] 1919642e337SNico Weber 0x54, // push esp 1929642e337SNico Weber }; 1939642e337SNico Weber 1949642e337SNico Weber #if SANITIZER_WINDOWS64 1959642e337SNico Weber u8 kLoadGlobalCode[] = { 1969642e337SNico Weber 0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, // mov eax [rip + global] 1979642e337SNico Weber 0xC3, // ret 1989642e337SNico Weber }; 1999642e337SNico Weber #endif 2009642e337SNico Weber 2019642e337SNico Weber const u8 kUnpatchableCode1[] = { 2029642e337SNico Weber 0xC3, // ret 2039642e337SNico Weber }; 2049642e337SNico Weber 2059642e337SNico Weber const u8 kUnpatchableCode2[] = { 2069642e337SNico Weber 0x33, 0xC9, // xor ecx,ecx 2079642e337SNico Weber 0xC3, // ret 2089642e337SNico Weber }; 2099642e337SNico Weber 2109642e337SNico Weber const u8 kUnpatchableCode3[] = { 2119642e337SNico Weber 0x75, 0xCC, // jne <label> 2129642e337SNico Weber 0x33, 0xC9, // xor ecx,ecx 2139642e337SNico Weber 0xC3, // ret 2149642e337SNico Weber }; 2159642e337SNico Weber 2169642e337SNico Weber const u8 kUnpatchableCode4[] = { 2179642e337SNico Weber 0x74, 0xCC, // jne <label> 2189642e337SNico Weber 0x33, 0xC9, // xor ecx,ecx 2199642e337SNico Weber 0xC3, // ret 2209642e337SNico Weber }; 2219642e337SNico Weber 2229642e337SNico Weber const u8 kUnpatchableCode5[] = { 2239642e337SNico Weber 0xEB, 0x02, // jmp <label> 2249642e337SNico Weber 0x33, 0xC9, // xor ecx,ecx 2259642e337SNico Weber 0xC3, // ret 2269642e337SNico Weber }; 2279642e337SNico Weber 2289642e337SNico Weber const u8 kUnpatchableCode6[] = { 2299642e337SNico Weber 0xE8, 0xCC, 0xCC, 0xCC, 0xCC, // call <func> 2309642e337SNico Weber 0x90, 0x90, 0x90, 0x90, 2319642e337SNico Weber }; 2329642e337SNico Weber 233b89e7746Sbernhardu # if SANITIZER_WINDOWS64 23422ea0ceaSToshihito Kikuchi const u8 kUnpatchableCode7[] = { 23522ea0ceaSToshihito Kikuchi 0x33, 0xc0, // xor eax,eax 23622ea0ceaSToshihito Kikuchi 0x48, 0x85, 0xd2, // test rdx,rdx 23722ea0ceaSToshihito Kikuchi 0x74, 0x10, // je +16 (unpatchable) 23822ea0ceaSToshihito Kikuchi }; 23922ea0ceaSToshihito Kikuchi 24022ea0ceaSToshihito Kikuchi const u8 kUnpatchableCode8[] = { 24122ea0ceaSToshihito Kikuchi 0x48, 0x8b, 0xc1, // mov rax,rcx 24222ea0ceaSToshihito Kikuchi 0x0f, 0xb7, 0x10, // movzx edx,word ptr [rax] 24322ea0ceaSToshihito Kikuchi 0x48, 0x83, 0xc0, 0x02, // add rax,2 24422ea0ceaSToshihito Kikuchi 0x66, 0x85, 0xd2, // test dx,dx 24522ea0ceaSToshihito Kikuchi 0x75, 0xf4, // jne -12 (unpatchable) 24622ea0ceaSToshihito Kikuchi }; 24722ea0ceaSToshihito Kikuchi 24822ea0ceaSToshihito Kikuchi const u8 kUnpatchableCode9[] = { 24922ea0ceaSToshihito Kikuchi 0x4c, 0x8b, 0xc1, // mov r8,rcx 25022ea0ceaSToshihito Kikuchi 0x8a, 0x01, // mov al,byte ptr [rcx] 25122ea0ceaSToshihito Kikuchi 0x48, 0xff, 0xc1, // inc rcx 25222ea0ceaSToshihito Kikuchi 0x84, 0xc0, // test al,al 25322ea0ceaSToshihito Kikuchi 0x75, 0xf7, // jne -9 (unpatchable) 25422ea0ceaSToshihito Kikuchi }; 25522ea0ceaSToshihito Kikuchi 2569642e337SNico Weber const u8 kPatchableCode6[] = { 2579642e337SNico Weber 0x48, 0x89, 0x54, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], rdx 2589642e337SNico Weber 0x33, 0xC9, // xor ecx,ecx 2599642e337SNico Weber 0xC3, // ret 2609642e337SNico Weber }; 2619642e337SNico Weber 2629642e337SNico Weber const u8 kPatchableCode7[] = { 2639642e337SNico Weber 0x4c, 0x89, 0x4c, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], r9 2649642e337SNico Weber 0x33, 0xC9, // xor ecx,ecx 2659642e337SNico Weber 0xC3, // ret 2669642e337SNico Weber }; 2679642e337SNico Weber 2689642e337SNico Weber const u8 kPatchableCode8[] = { 2699642e337SNico Weber 0x4c, 0x89, 0x44, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], r8 2709642e337SNico Weber 0x33, 0xC9, // xor ecx,ecx 2719642e337SNico Weber 0xC3, // ret 2729642e337SNico Weber }; 2739642e337SNico Weber 27422ea0ceaSToshihito Kikuchi const u8 kPatchableCode9[] = { 27522ea0ceaSToshihito Kikuchi 0x8a, 0x01, // al,byte ptr [rcx] 27622ea0ceaSToshihito Kikuchi 0x45, 0x33, 0xc0, // xor r8d,r8d 27722ea0ceaSToshihito Kikuchi 0x84, 0xc0, // test al,al 27822ea0ceaSToshihito Kikuchi }; 27922ea0ceaSToshihito Kikuchi 28022ea0ceaSToshihito Kikuchi const u8 kPatchableCode10[] = { 28122ea0ceaSToshihito Kikuchi 0x45, 0x33, 0xc0, // xor r8d,r8d 28222ea0ceaSToshihito Kikuchi 0x41, 0x8b, 0xc0, // mov eax,r8d 28322ea0ceaSToshihito Kikuchi 0x48, 0x85, 0xd2, // test rdx,rdx 28422ea0ceaSToshihito Kikuchi }; 28522ea0ceaSToshihito Kikuchi 28622ea0ceaSToshihito Kikuchi const u8 kPatchableCode11[] = { 28722ea0ceaSToshihito Kikuchi 0x48, 0x83, 0xec, 0x38, // sub rsp,38h 28822ea0ceaSToshihito Kikuchi 0x83, 0x64, 0x24, 0x28, 0x00, // and dword ptr [rsp+28h],0 28922ea0ceaSToshihito Kikuchi }; 290b89e7746Sbernhardu # endif 29122ea0ceaSToshihito Kikuchi 292b89e7746Sbernhardu # if !SANITIZER_WINDOWS64 293ca40985eSAlvin Wong const u8 kPatchableCode12[] = { 294ca40985eSAlvin Wong 0x55, // push ebp 295ca40985eSAlvin Wong 0x53, // push ebx 296ca40985eSAlvin Wong 0x57, // push edi 297ca40985eSAlvin Wong 0x56, // push esi 298ca40985eSAlvin Wong 0x8b, 0x6c, 0x24, 0x18, // mov ebp,dword ptr[esp+18h] 299ca40985eSAlvin Wong }; 300ca40985eSAlvin Wong 301ca40985eSAlvin Wong const u8 kPatchableCode13[] = { 302ca40985eSAlvin Wong 0x55, // push ebp 303ca40985eSAlvin Wong 0x53, // push ebx 304ca40985eSAlvin Wong 0x57, // push edi 305ca40985eSAlvin Wong 0x56, // push esi 306ca40985eSAlvin Wong 0x8b, 0x5c, 0x24, 0x14, // mov ebx,dword ptr[esp+14h] 307ca40985eSAlvin Wong }; 308b89e7746Sbernhardu # endif 309ca40985eSAlvin Wong 310ca40985eSAlvin Wong const u8 kPatchableCode14[] = { 311ca40985eSAlvin Wong 0x55, // push ebp 312ca40985eSAlvin Wong 0x89, 0xe5, // mov ebp,esp 313ca40985eSAlvin Wong 0x53, // push ebx 314ca40985eSAlvin Wong 0x57, // push edi 315ca40985eSAlvin Wong 0x56, // push esi 316ca40985eSAlvin Wong }; 317ca40985eSAlvin Wong 3187b5571f3SAlvin Wong const u8 kUnsupportedCode1[] = { 3197b5571f3SAlvin Wong 0x0f, 0x0b, // ud2 3207b5571f3SAlvin Wong 0x0f, 0x0b, // ud2 3217b5571f3SAlvin Wong 0x0f, 0x0b, // ud2 3227b5571f3SAlvin Wong 0x0f, 0x0b, // ud2 3237b5571f3SAlvin Wong }; 3247b5571f3SAlvin Wong 3259642e337SNico Weber // A buffer holding the dynamically generated code under test. 3269642e337SNico Weber u8* ActiveCode; 3279642e337SNico Weber const size_t ActiveCodeLength = 4096; 3289642e337SNico Weber 3299642e337SNico Weber int InterceptorFunction(int x); 3309642e337SNico Weber 3319642e337SNico Weber /// Allocate code memory more than 2GB away from Base. 3329642e337SNico Weber u8 *AllocateCode2GBAway(u8 *Base) { 3339642e337SNico Weber // Find a 64K aligned location after Base plus 2GB. 3349642e337SNico Weber size_t TwoGB = 0x80000000; 3359642e337SNico Weber size_t AllocGranularity = 0x10000; 3369642e337SNico Weber Base = (u8 *)((((uptr)Base + TwoGB + AllocGranularity)) & ~(AllocGranularity - 1)); 3379642e337SNico Weber 3389642e337SNico Weber // Check if that location is free, and if not, loop over regions until we find 3399642e337SNico Weber // one that is. 3409642e337SNico Weber MEMORY_BASIC_INFORMATION mbi = {}; 3419642e337SNico Weber while (sizeof(mbi) == VirtualQuery(Base, &mbi, sizeof(mbi))) { 3429642e337SNico Weber if (mbi.State & MEM_FREE) break; 3439642e337SNico Weber Base += mbi.RegionSize; 3449642e337SNico Weber } 3459642e337SNico Weber 3469642e337SNico Weber // Allocate one RWX page at the free location. 3479642e337SNico Weber return (u8 *)::VirtualAlloc(Base, ActiveCodeLength, MEM_COMMIT | MEM_RESERVE, 3489642e337SNico Weber PAGE_EXECUTE_READWRITE); 3499642e337SNico Weber } 3509642e337SNico Weber 3519642e337SNico Weber template<class T> 3529642e337SNico Weber static void LoadActiveCode( 3539642e337SNico Weber const T &code, 3549642e337SNico Weber uptr *entry_point, 3559642e337SNico Weber FunctionPrefixKind prefix_kind = FunctionPrefixNone) { 3569642e337SNico Weber if (ActiveCode == nullptr) { 3579642e337SNico Weber ActiveCode = AllocateCode2GBAway((u8*)&InterceptorFunction); 3589642e337SNico Weber ASSERT_NE(ActiveCode, nullptr) << "failed to allocate RWX memory 2GB away"; 3599642e337SNico Weber } 3609642e337SNico Weber 3619642e337SNico Weber size_t position = 0; 3629642e337SNico Weber 3639642e337SNico Weber // Add padding to avoid memory violation when scanning the prefix. 3649642e337SNico Weber for (int i = 0; i < 16; ++i) 3659642e337SNico Weber ActiveCode[position++] = 0xC3; // Instruction 'ret'. 3669642e337SNico Weber 3679642e337SNico Weber // Add function padding. 3689642e337SNico Weber size_t padding = 0; 3699642e337SNico Weber if (prefix_kind == FunctionPrefixPadding) 3709642e337SNico Weber padding = 16; 3719642e337SNico Weber else if (prefix_kind == FunctionPrefixDetour || 3729642e337SNico Weber prefix_kind == FunctionPrefixHotPatch) 3739642e337SNico Weber padding = FIRST_32_SECOND_64(5, 6); 3749642e337SNico Weber // Insert |padding| instructions 'nop'. 3759642e337SNico Weber for (size_t i = 0; i < padding; ++i) 3769642e337SNico Weber ActiveCode[position++] = 0x90; 3779642e337SNico Weber 3789642e337SNico Weber // Keep track of the entry point. 3799642e337SNico Weber *entry_point = (uptr)&ActiveCode[position]; 3809642e337SNico Weber 3819642e337SNico Weber // Add the detour instruction (i.e. mov edi, edi) 3829642e337SNico Weber if (prefix_kind == FunctionPrefixDetour) { 3839642e337SNico Weber #if SANITIZER_WINDOWS64 3849642e337SNico Weber // Note that "mov edi,edi" is NOP in 32-bit only, in 64-bit it clears 3859642e337SNico Weber // higher bits of RDI. 3869642e337SNico Weber // Use 66,90H as NOP for Windows64. 3879642e337SNico Weber ActiveCode[position++] = 0x66; 3889642e337SNico Weber ActiveCode[position++] = 0x90; 3899642e337SNico Weber #else 3909642e337SNico Weber // mov edi,edi. 3919642e337SNico Weber ActiveCode[position++] = 0x8B; 3929642e337SNico Weber ActiveCode[position++] = 0xFF; 3939642e337SNico Weber #endif 3949642e337SNico Weber 3959642e337SNico Weber } 3969642e337SNico Weber 3979642e337SNico Weber // Copy the function body. 3989642e337SNico Weber for (size_t i = 0; i < sizeof(T); ++i) 3999642e337SNico Weber ActiveCode[position++] = code[i]; 4009642e337SNico Weber } 4019642e337SNico Weber 4029642e337SNico Weber int InterceptorFunctionCalled; 4039642e337SNico Weber IdentityFunction InterceptedRealFunction; 4049642e337SNico Weber 4059642e337SNico Weber int InterceptorFunction(int x) { 4069642e337SNico Weber ++InterceptorFunctionCalled; 4079642e337SNico Weber return InterceptedRealFunction(x); 4089642e337SNico Weber } 4099642e337SNico Weber 4109642e337SNico Weber } // namespace 4119642e337SNico Weber 4129642e337SNico Weber // Tests for interception_win.h 4139642e337SNico Weber TEST(Interception, InternalGetProcAddress) { 4149642e337SNico Weber HMODULE ntdll_handle = ::GetModuleHandle("ntdll"); 4159642e337SNico Weber ASSERT_NE(nullptr, ntdll_handle); 4169642e337SNico Weber uptr DbgPrint_expected = (uptr)::GetProcAddress(ntdll_handle, "DbgPrint"); 4179642e337SNico Weber uptr isdigit_expected = (uptr)::GetProcAddress(ntdll_handle, "isdigit"); 4189642e337SNico Weber uptr DbgPrint_adddress = InternalGetProcAddress(ntdll_handle, "DbgPrint"); 4199642e337SNico Weber uptr isdigit_address = InternalGetProcAddress(ntdll_handle, "isdigit"); 4209642e337SNico Weber 4219642e337SNico Weber EXPECT_EQ(DbgPrint_expected, DbgPrint_adddress); 4229642e337SNico Weber EXPECT_EQ(isdigit_expected, isdigit_address); 4239642e337SNico Weber EXPECT_NE(DbgPrint_adddress, isdigit_address); 4249642e337SNico Weber } 4259642e337SNico Weber 4269642e337SNico Weber template <class T> 4279642e337SNico Weber static void TestIdentityFunctionPatching( 42878c033b5SMarkus Böck const T &code, TestOverrideFunction override, 42978c033b5SMarkus Böck FunctionPrefixKind prefix_kind = FunctionPrefixNone, 43078c033b5SMarkus Böck int function_start_offset = 0) { 4319642e337SNico Weber uptr identity_address; 4329642e337SNico Weber LoadActiveCode(code, &identity_address, prefix_kind); 43378c033b5SMarkus Böck identity_address += function_start_offset; 4349642e337SNico Weber IdentityFunction identity = (IdentityFunction)identity_address; 4359642e337SNico Weber 4369642e337SNico Weber // Validate behavior before dynamic patching. 4379642e337SNico Weber InterceptorFunctionCalled = 0; 4389642e337SNico Weber EXPECT_EQ(0, identity(0)); 4399642e337SNico Weber EXPECT_EQ(42, identity(42)); 4409642e337SNico Weber EXPECT_EQ(0, InterceptorFunctionCalled); 4419642e337SNico Weber 4429642e337SNico Weber // Patch the function. 4439642e337SNico Weber uptr real_identity_address = 0; 4449642e337SNico Weber bool success = override(identity_address, 4459642e337SNico Weber (uptr)&InterceptorFunction, 4469642e337SNico Weber &real_identity_address); 4479642e337SNico Weber EXPECT_TRUE(success); 4489642e337SNico Weber EXPECT_NE(0U, real_identity_address); 4499642e337SNico Weber IdentityFunction real_identity = (IdentityFunction)real_identity_address; 4509642e337SNico Weber InterceptedRealFunction = real_identity; 4519642e337SNico Weber 4529642e337SNico Weber // Don't run tests if hooking failed or the real function is not valid. 4539642e337SNico Weber if (!success || !real_identity_address) 4549642e337SNico Weber return; 4559642e337SNico Weber 4569642e337SNico Weber // Calling the redirected function. 4579642e337SNico Weber InterceptorFunctionCalled = 0; 4589642e337SNico Weber EXPECT_EQ(0, identity(0)); 4599642e337SNico Weber EXPECT_EQ(42, identity(42)); 4609642e337SNico Weber EXPECT_EQ(2, InterceptorFunctionCalled); 4619642e337SNico Weber 4629642e337SNico Weber // Calling the real function. 4639642e337SNico Weber InterceptorFunctionCalled = 0; 4649642e337SNico Weber EXPECT_EQ(0, real_identity(0)); 4659642e337SNico Weber EXPECT_EQ(42, real_identity(42)); 4669642e337SNico Weber EXPECT_EQ(0, InterceptorFunctionCalled); 4679642e337SNico Weber 4689642e337SNico Weber TestOnlyReleaseTrampolineRegions(); 4699642e337SNico Weber } 4709642e337SNico Weber 4719642e337SNico Weber # if !SANITIZER_WINDOWS64 4729642e337SNico Weber TEST(Interception, OverrideFunctionWithDetour) { 4739642e337SNico Weber TestOverrideFunction override = OverrideFunctionWithDetour; 4749642e337SNico Weber FunctionPrefixKind prefix = FunctionPrefixDetour; 4759642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); 4769642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); 4779642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); 4789642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); 4799642e337SNico Weber } 4809642e337SNico Weber #endif // !SANITIZER_WINDOWS64 4819642e337SNico Weber 4829642e337SNico Weber TEST(Interception, OverrideFunctionWithRedirectJump) { 4839642e337SNico Weber TestOverrideFunction override = OverrideFunctionWithRedirectJump; 4849642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithJump, override); 48578c033b5SMarkus Böck TestIdentityFunctionPatching(kIdentityCodeWithJumpBackwards, override, 48678c033b5SMarkus Böck FunctionPrefixNone, 48778c033b5SMarkus Böck kIdentityCodeWithJumpBackwardsOffset); 4889642e337SNico Weber } 4899642e337SNico Weber 4909642e337SNico Weber TEST(Interception, OverrideFunctionWithHotPatch) { 4919642e337SNico Weber TestOverrideFunction override = OverrideFunctionWithHotPatch; 4929642e337SNico Weber FunctionPrefixKind prefix = FunctionPrefixHotPatch; 4939642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); 4949642e337SNico Weber } 4959642e337SNico Weber 4969642e337SNico Weber TEST(Interception, OverrideFunctionWithTrampoline) { 4979642e337SNico Weber TestOverrideFunction override = OverrideFunctionWithTrampoline; 4989642e337SNico Weber FunctionPrefixKind prefix = FunctionPrefixNone; 4999642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); 5009642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); 5019642e337SNico Weber 5029642e337SNico Weber prefix = FunctionPrefixPadding; 5039642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); 5049642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); 5059642e337SNico Weber } 5069642e337SNico Weber 5079642e337SNico Weber TEST(Interception, OverrideFunction) { 5089642e337SNico Weber TestOverrideFunction override = OverrideFunction; 5099642e337SNico Weber FunctionPrefixKind prefix = FunctionPrefixNone; 5109642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); 5119642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); 5129642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); 5139642e337SNico Weber 5149642e337SNico Weber prefix = FunctionPrefixPadding; 5159642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); 5169642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); 5179642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); 5189642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); 5199642e337SNico Weber 5209642e337SNico Weber prefix = FunctionPrefixHotPatch; 5219642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); 5229642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); 5239642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); 5249642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); 5259642e337SNico Weber 5269642e337SNico Weber prefix = FunctionPrefixDetour; 5279642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); 5289642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); 5299642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); 5309642e337SNico Weber TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); 5319642e337SNico Weber } 5329642e337SNico Weber 5339642e337SNico Weber template<class T> 5349642e337SNico Weber static void TestIdentityFunctionMultiplePatching( 5359642e337SNico Weber const T &code, 5369642e337SNico Weber TestOverrideFunction override, 5379642e337SNico Weber FunctionPrefixKind prefix_kind = FunctionPrefixNone) { 5389642e337SNico Weber uptr identity_address; 5399642e337SNico Weber LoadActiveCode(code, &identity_address, prefix_kind); 5409642e337SNico Weber 5419642e337SNico Weber // Patch the function. 5429642e337SNico Weber uptr real_identity_address = 0; 5439642e337SNico Weber bool success = override(identity_address, 5449642e337SNico Weber (uptr)&InterceptorFunction, 5459642e337SNico Weber &real_identity_address); 5469642e337SNico Weber EXPECT_TRUE(success); 5479642e337SNico Weber EXPECT_NE(0U, real_identity_address); 5489642e337SNico Weber 5499642e337SNico Weber // Re-patching the function should not work. 5509642e337SNico Weber success = override(identity_address, 5519642e337SNico Weber (uptr)&InterceptorFunction, 5529642e337SNico Weber &real_identity_address); 5539642e337SNico Weber EXPECT_FALSE(success); 5549642e337SNico Weber 5559642e337SNico Weber TestOnlyReleaseTrampolineRegions(); 5569642e337SNico Weber } 5579642e337SNico Weber 5589642e337SNico Weber TEST(Interception, OverrideFunctionMultiplePatchingIsFailing) { 5599642e337SNico Weber #if !SANITIZER_WINDOWS64 5609642e337SNico Weber TestIdentityFunctionMultiplePatching(kIdentityCodeWithPrologue, 5619642e337SNico Weber OverrideFunctionWithDetour, 5629642e337SNico Weber FunctionPrefixDetour); 5639642e337SNico Weber #endif 5649642e337SNico Weber 5659642e337SNico Weber TestIdentityFunctionMultiplePatching(kIdentityCodeWithMov, 5669642e337SNico Weber OverrideFunctionWithHotPatch, 5679642e337SNico Weber FunctionPrefixHotPatch); 5689642e337SNico Weber 5699642e337SNico Weber TestIdentityFunctionMultiplePatching(kIdentityCodeWithPushPop, 5709642e337SNico Weber OverrideFunctionWithTrampoline, 5719642e337SNico Weber FunctionPrefixPadding); 5729642e337SNico Weber } 5739642e337SNico Weber 5749642e337SNico Weber TEST(Interception, OverrideFunctionTwice) { 5759642e337SNico Weber uptr identity_address1; 5769642e337SNico Weber LoadActiveCode(kIdentityTwice, &identity_address1); 5779642e337SNico Weber uptr identity_address2 = identity_address1 + kIdentityTwiceOffset; 5789642e337SNico Weber IdentityFunction identity1 = (IdentityFunction)identity_address1; 5799642e337SNico Weber IdentityFunction identity2 = (IdentityFunction)identity_address2; 5809642e337SNico Weber 5819642e337SNico Weber // Patch the two functions. 5829642e337SNico Weber uptr real_identity_address = 0; 5839642e337SNico Weber EXPECT_TRUE(OverrideFunction(identity_address1, 5849642e337SNico Weber (uptr)&InterceptorFunction, 5859642e337SNico Weber &real_identity_address)); 5869642e337SNico Weber EXPECT_TRUE(OverrideFunction(identity_address2, 5879642e337SNico Weber (uptr)&InterceptorFunction, 5889642e337SNico Weber &real_identity_address)); 5899642e337SNico Weber IdentityFunction real_identity = (IdentityFunction)real_identity_address; 5909642e337SNico Weber InterceptedRealFunction = real_identity; 5919642e337SNico Weber 5929642e337SNico Weber // Calling the redirected function. 5939642e337SNico Weber InterceptorFunctionCalled = 0; 5949642e337SNico Weber EXPECT_EQ(42, identity1(42)); 5959642e337SNico Weber EXPECT_EQ(42, identity2(42)); 5969642e337SNico Weber EXPECT_EQ(2, InterceptorFunctionCalled); 5979642e337SNico Weber 5989642e337SNico Weber TestOnlyReleaseTrampolineRegions(); 5999642e337SNico Weber } 6009642e337SNico Weber 6019642e337SNico Weber template<class T> 6029642e337SNico Weber static bool TestFunctionPatching( 6039642e337SNico Weber const T &code, 6049642e337SNico Weber TestOverrideFunction override, 6059642e337SNico Weber FunctionPrefixKind prefix_kind = FunctionPrefixNone) { 6069642e337SNico Weber uptr address; 6079642e337SNico Weber LoadActiveCode(code, &address, prefix_kind); 6089642e337SNico Weber uptr unused_real_address = 0; 6099642e337SNico Weber bool result = override( 6109642e337SNico Weber address, (uptr)&InterceptorFunction, &unused_real_address); 6119642e337SNico Weber 6129642e337SNico Weber TestOnlyReleaseTrampolineRegions(); 6139642e337SNico Weber return result; 6149642e337SNico Weber } 6159642e337SNico Weber 6169642e337SNico Weber TEST(Interception, PatchableFunction) { 6179642e337SNico Weber TestOverrideFunction override = OverrideFunction; 6189642e337SNico Weber // Test without function padding. 6199642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override)); 6209642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override)); 6219642e337SNico Weber #if SANITIZER_WINDOWS64 6229642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override)); 6239642e337SNico Weber #else 6249642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override)); 6259642e337SNico Weber #endif 6269642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override)); 6279642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode5, override)); 6289642e337SNico Weber #if SANITIZER_WINDOWS64 6299642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kLoadGlobalCode, override)); 6309642e337SNico Weber #endif 6319642e337SNico Weber 6329642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override)); 6339642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override)); 6349642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override)); 6359642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override)); 6369642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override)); 6379642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override)); 6389642e337SNico Weber } 6399642e337SNico Weber 6409642e337SNico Weber #if !SANITIZER_WINDOWS64 6419642e337SNico Weber TEST(Interception, PatchableFunctionWithDetour) { 6429642e337SNico Weber TestOverrideFunction override = OverrideFunctionWithDetour; 6439642e337SNico Weber // Without the prefix, no function can be detoured. 6449642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override)); 6459642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override)); 6469642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override)); 6479642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override)); 6489642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override)); 6499642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override)); 6509642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override)); 6519642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override)); 6529642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override)); 6539642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override)); 6549642e337SNico Weber 6559642e337SNico Weber // With the prefix, all functions can be detoured. 6569642e337SNico Weber FunctionPrefixKind prefix = FunctionPrefixDetour; 6579642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix)); 6589642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix)); 6599642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix)); 6609642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix)); 6619642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode1, override, prefix)); 6629642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix)); 6639642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode3, override, prefix)); 6649642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode4, override, prefix)); 6659642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode5, override, prefix)); 6669642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode6, override, prefix)); 6679642e337SNico Weber } 6689642e337SNico Weber #endif // !SANITIZER_WINDOWS64 6699642e337SNico Weber 6709642e337SNico Weber TEST(Interception, PatchableFunctionWithRedirectJump) { 6719642e337SNico Weber TestOverrideFunction override = OverrideFunctionWithRedirectJump; 6729642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override)); 6739642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override)); 6749642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override)); 6759642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override)); 6769642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override)); 6779642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override)); 6789642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override)); 6799642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override)); 6809642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override)); 6819642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override)); 6829642e337SNico Weber } 6839642e337SNico Weber 6849642e337SNico Weber TEST(Interception, PatchableFunctionWithHotPatch) { 6859642e337SNico Weber TestOverrideFunction override = OverrideFunctionWithHotPatch; 6869642e337SNico Weber FunctionPrefixKind prefix = FunctionPrefixHotPatch; 6879642e337SNico Weber 6889642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix)); 6899642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override, prefix)); 6909642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix)); 6919642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix)); 6929642e337SNico Weber #if SANITIZER_WINDOWS64 6939642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode6, override, prefix)); 6949642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode7, override, prefix)); 6959642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode8, override, prefix)); 6969642e337SNico Weber #endif 6979642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix)); 6989642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix)); 6999642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix)); 7009642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix)); 7019642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix)); 7029642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix)); 7039642e337SNico Weber } 7049642e337SNico Weber 7059642e337SNico Weber TEST(Interception, PatchableFunctionWithTrampoline) { 7069642e337SNico Weber TestOverrideFunction override = OverrideFunctionWithTrampoline; 7079642e337SNico Weber FunctionPrefixKind prefix = FunctionPrefixPadding; 7089642e337SNico Weber 7099642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix)); 7109642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix)); 7119642e337SNico Weber #if SANITIZER_WINDOWS64 7129642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix)); 71322ea0ceaSToshihito Kikuchi EXPECT_TRUE(TestFunctionPatching(kPatchableCode9, override, prefix)); 71422ea0ceaSToshihito Kikuchi EXPECT_TRUE(TestFunctionPatching(kPatchableCode10, override, prefix)); 71522ea0ceaSToshihito Kikuchi EXPECT_TRUE(TestFunctionPatching(kPatchableCode11, override, prefix)); 71622ea0ceaSToshihito Kikuchi EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode7, override, prefix)); 71722ea0ceaSToshihito Kikuchi EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode8, override, prefix)); 71822ea0ceaSToshihito Kikuchi EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode9, override, prefix)); 7199642e337SNico Weber #else 7209642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix)); 721ca40985eSAlvin Wong EXPECT_TRUE(TestFunctionPatching(kPatchableCode12, override, prefix)); 722ca40985eSAlvin Wong EXPECT_TRUE(TestFunctionPatching(kPatchableCode13, override, prefix)); 7239642e337SNico Weber #endif 7249642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix)); 725ca40985eSAlvin Wong EXPECT_TRUE(TestFunctionPatching(kPatchableCode14, override, prefix)); 7269642e337SNico Weber 7279642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix)); 7289642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override, prefix)); 7299642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix)); 7309642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix)); 7319642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix)); 7329642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix)); 7339642e337SNico Weber } 7349642e337SNico Weber 7357b5571f3SAlvin Wong TEST(Interception, UnsupportedInstructionWithTrampoline) { 7367b5571f3SAlvin Wong TestOverrideFunction override = OverrideFunctionWithTrampoline; 7377b5571f3SAlvin Wong FunctionPrefixKind prefix = FunctionPrefixPadding; 7387b5571f3SAlvin Wong 7390716888dSAlvin Wong static bool reportCalled; 7400716888dSAlvin Wong reportCalled = false; 7410716888dSAlvin Wong 7420716888dSAlvin Wong struct Local { 7430716888dSAlvin Wong static void Report(const char *format, ...) { 7440716888dSAlvin Wong if (reportCalled) 7450716888dSAlvin Wong FAIL() << "Report called more times than expected"; 7460716888dSAlvin Wong reportCalled = true; 7470716888dSAlvin Wong ASSERT_STREQ( 7480716888dSAlvin Wong "interception_win: unhandled instruction at %p: %02x %02x %02x %02x " 7490716888dSAlvin Wong "%02x %02x %02x %02x\n", 7500716888dSAlvin Wong format); 7510716888dSAlvin Wong va_list args; 7520716888dSAlvin Wong va_start(args, format); 7530716888dSAlvin Wong u8 *ptr = va_arg(args, u8 *); 7540716888dSAlvin Wong for (int i = 0; i < 8; i++) EXPECT_EQ(kUnsupportedCode1[i], ptr[i]); 7550716888dSAlvin Wong int bytes[8]; 7560716888dSAlvin Wong for (int i = 0; i < 8; i++) { 7570716888dSAlvin Wong bytes[i] = va_arg(args, int); 7580716888dSAlvin Wong EXPECT_EQ(kUnsupportedCode1[i], bytes[i]); 7590716888dSAlvin Wong } 7600716888dSAlvin Wong va_end(args); 7610716888dSAlvin Wong } 7620716888dSAlvin Wong }; 7630716888dSAlvin Wong 7640716888dSAlvin Wong SetErrorReportCallback(Local::Report); 7657b5571f3SAlvin Wong EXPECT_FALSE(TestFunctionPatching(kUnsupportedCode1, override, prefix)); 7660716888dSAlvin Wong SetErrorReportCallback(nullptr); 7670716888dSAlvin Wong 7680716888dSAlvin Wong if (!reportCalled) 7690716888dSAlvin Wong ADD_FAILURE() << "Report not called"; 7707b5571f3SAlvin Wong } 7717b5571f3SAlvin Wong 7729642e337SNico Weber TEST(Interception, PatchableFunctionPadding) { 7739642e337SNico Weber TestOverrideFunction override = OverrideFunction; 7749642e337SNico Weber FunctionPrefixKind prefix = FunctionPrefixPadding; 7759642e337SNico Weber 7769642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix)); 7779642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix)); 7789642e337SNico Weber #if SANITIZER_WINDOWS64 7799642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix)); 7809642e337SNico Weber #else 7819642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix)); 7829642e337SNico Weber #endif 7839642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix)); 7849642e337SNico Weber 7859642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix)); 7869642e337SNico Weber EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix)); 7879642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix)); 7889642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix)); 7899642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix)); 7909642e337SNico Weber EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix)); 7919642e337SNico Weber } 7929642e337SNico Weber 7939642e337SNico Weber TEST(Interception, EmptyExportTable) { 7949642e337SNico Weber // We try to get a pointer to a function from an executable that doesn't 7959642e337SNico Weber // export any symbol (empty export table). 7969642e337SNico Weber uptr FunPtr = InternalGetProcAddress((void *)GetModuleHandleA(0), "example"); 7979642e337SNico Weber EXPECT_EQ(0U, FunPtr); 7989642e337SNico Weber } 7999642e337SNico Weber 80036b1811dSbernhardu const struct InstructionSizeData { 80136b1811dSbernhardu size_t size; // hold instruction size or 0 for failure, 80236b1811dSbernhardu // e.g. on control instructions 80336b1811dSbernhardu u8 instr[16]; 8049a9e41caSbernhardu size_t rel_offset; // adjustment for RIP-relative addresses when copying 8059a9e41caSbernhardu // instructions during hooking via hotpatch or trampoline. 80636b1811dSbernhardu const char *comment; 80736b1811dSbernhardu } data[] = { 808b8d857efSbernhardu // clang-format off 809b8d857efSbernhardu // sorted list 810b8d857efSbernhardu { 0, {0x70, 0x71}, 0, "70 XX : jo XX (short conditional jump)"}, 811b8d857efSbernhardu { 0, {0x71, 0x71}, 0, "71 XX : jno XX (short conditional jump)"}, 812b8d857efSbernhardu { 0, {0x72, 0x71}, 0, "72 XX : jb XX (short conditional jump)"}, 813b8d857efSbernhardu { 0, {0x73, 0x71}, 0, "73 XX : jae XX (short conditional jump)"}, 814b8d857efSbernhardu { 0, {0x74, 0x71}, 0, "74 XX : je XX (short conditional jump)"}, 815b8d857efSbernhardu { 0, {0x75, 0x71}, 0, "75 XX : jne XX (short conditional jump)"}, 816b8d857efSbernhardu { 0, {0x76, 0x71}, 0, "76 XX : jbe XX (short conditional jump)"}, 817b8d857efSbernhardu { 0, {0x77, 0x71}, 0, "77 XX : ja XX (short conditional jump)"}, 818b8d857efSbernhardu { 0, {0x78, 0x71}, 0, "78 XX : js XX (short conditional jump)"}, 819b8d857efSbernhardu { 0, {0x79, 0x71}, 0, "79 XX : jns XX (short conditional jump)"}, 820b8d857efSbernhardu { 0, {0x7A, 0x71}, 0, "7A XX : jp XX (short conditional jump)"}, 821b8d857efSbernhardu { 0, {0x7B, 0x71}, 0, "7B XX : jnp XX (short conditional jump)"}, 822b8d857efSbernhardu { 0, {0x7C, 0x71}, 0, "7C XX : jl XX (short conditional jump)"}, 823b8d857efSbernhardu { 0, {0x7D, 0x71}, 0, "7D XX : jge XX (short conditional jump)"}, 824b8d857efSbernhardu { 0, {0x7E, 0x71}, 0, "7E XX : jle XX (short conditional jump)"}, 825b8d857efSbernhardu { 0, {0x7F, 0x71}, 0, "7F XX : jg XX (short conditional jump)"}, 826b8d857efSbernhardu { 0, {0xE8, 0x71, 0x72, 0x73, 0x74}, 0, "E8 XX XX XX XX : call <func>"}, 827b8d857efSbernhardu { 0, {0xE9, 0x71, 0x72, 0x73, 0x74}, 0, "E9 XX XX XX XX : jmp <label>"}, 828b8d857efSbernhardu { 0, {0xEB, 0x71}, 0, "EB XX : jmp XX (short jump)"}, 829b8d857efSbernhardu { 0, {0xFF, 0x25, 0x72, 0x73, 0x74, 0x75}, 0, "FF 25 XX YY ZZ WW : jmp dword ptr ds:[WWZZYYXX]"}, 83036b1811dSbernhardu { 1, {0x50}, 0, "50 : push eax / rax"}, 831b8d857efSbernhardu { 1, {0x51}, 0, "51 : push ecx / rcx"}, 832b8d857efSbernhardu { 1, {0x52}, 0, "52 : push edx / rdx"}, 833b8d857efSbernhardu { 1, {0x53}, 0, "53 : push ebx / rbx"}, 834b8d857efSbernhardu { 1, {0x54}, 0, "54 : push esp / rsp"}, 835b8d857efSbernhardu { 1, {0x55}, 0, "55 : push ebp / rbp"}, 836b8d857efSbernhardu { 1, {0x56}, 0, "56 : push esi / rsi"}, 837b8d857efSbernhardu { 1, {0x57}, 0, "57 : push edi / rdi"}, 838b8d857efSbernhardu { 1, {0x5D}, 0, "5D : pop ebp / rbp"}, 839b8d857efSbernhardu { 1, {0x90}, 0, "90 : nop"}, 840b8d857efSbernhardu { 1, {0xC3}, 0, "C3 : ret (for small/empty function interception"}, 841b8d857efSbernhardu { 1, {0xCC}, 0, "CC : int 3 i.e. registering weak functions)"}, 84299612a3aSbernhardu { 2, {0x31, 0xC0}, 0, "31 C0 : xor eax, eax"}, 84399612a3aSbernhardu { 2, {0x31, 0xC9}, 0, "31 C9 : xor ecx, ecx"}, 84499612a3aSbernhardu { 2, {0x31, 0xD2}, 0, "31 D2 : xor edx, edx"}, 845b8d857efSbernhardu { 2, {0x33, 0xC0}, 0, "33 C0 : xor eax, eax"}, 846b8d857efSbernhardu { 2, {0x33, 0xC9}, 0, "33 C9 : xor ecx, ecx"}, 847b8d857efSbernhardu { 2, {0x33, 0xD2}, 0, "33 D2 : xor edx, edx"}, 848b8d857efSbernhardu { 2, {0x6A, 0x71}, 0, "6A XX : push XX"}, 84999612a3aSbernhardu { 2, {0x84, 0xC0}, 0, "84 C0 : test al,al"}, 850b8d857efSbernhardu { 2, {0x84, 0xC9}, 0, "84 C9 : test cl,cl"}, 851b8d857efSbernhardu { 2, {0x84, 0xD2}, 0, "84 D2 : test dl,dl"}, 852b8d857efSbernhardu { 2, {0x84, 0xDB}, 0, "84 DB : test bl,bl"}, 853b8d857efSbernhardu { 2, {0x89, 0xc8}, 0, "89 C8 : mov eax, ecx"}, 85499612a3aSbernhardu { 2, {0x89, 0xD1}, 0, "89 D1 : mov ecx, edx"}, 855b8d857efSbernhardu { 2, {0x89, 0xE5}, 0, "89 E5 : mov ebp, esp"}, 856b8d857efSbernhardu { 2, {0x8A, 0x01}, 0, "8A 01 : mov al, byte ptr [ecx]"}, 857b8d857efSbernhardu { 2, {0x8B, 0xC1}, 0, "8B C1 : mov eax, ecx"}, 858b8d857efSbernhardu { 2, {0x8B, 0xEC}, 0, "8B EC : mov ebp, esp"}, 859b8d857efSbernhardu { 2, {0x8B, 0xFF}, 0, "8B FF : mov edi, edi"}, 86057466db7Sbernhardu { 3, {0x80, 0x39, 0x72}, 0, "80 39 XX : cmp BYTE PTR [rcx], XX"}, 861f85579fbSbernhardu { 3, {0x83, 0xE4, 0x72}, 0, "83 E4 XX : and esp, XX"}, 862854ea0cfSbernhardu { 3, {0x83, 0xEC, 0x72}, 0, "83 EC XX : sub esp, XX"}, 86357466db7Sbernhardu { 3, {0x8B, 0x4D, 0x72}, 0, "8B 4D XX : mov XX(%ebp), ecx"}, 86457466db7Sbernhardu { 3, {0x8B, 0x55, 0x72}, 0, "8B 55 XX : mov XX(%ebp), edx"}, 86557466db7Sbernhardu { 3, {0x8B, 0x75, 0x72}, 0, "8B 75 XX : mov XX(%ebp), esp"}, 866b8d857efSbernhardu { 3, {0xc2, 0x71, 0x72}, 0, "C2 XX XX : ret XX (needed for registering weak functions)"}, 86756592a81Sbernhardu { 4, {0x8D, 0x4C, 0x24, 0x73}, 0, "8D 4C 24 XX : lea ecx, [esp + XX]"}, 86856592a81Sbernhardu { 4, {0xFF, 0x74, 0x24, 0x73}, 0, "FF 74 24 XX : push qword ptr [rsp + XX]"}, 869b8d857efSbernhardu { 5, {0x68, 0x71, 0x72, 0x73, 0x74}, 0, "68 XX XX XX XX : push imm32"}, 870b8d857efSbernhardu { 5, {0xb8, 0x71, 0x72, 0x73, 0x74}, 0, "b8 XX XX XX XX : mov eax, XX XX XX XX"}, 871b8d857efSbernhardu { 5, {0xB9, 0x71, 0x72, 0x73, 0x74}, 0, "b9 XX XX XX XX : mov ecx, XX XX XX XX"}, 8725f405707Sbernhardu { 5, {0xBA, 0x71, 0x72, 0x73, 0x74}, 0, "ba XX XX XX XX : mov edx, XX XX XX XX"}, 873351ee305Sbernhardu { 6, {0x81, 0xEC, 0x72, 0x73, 0x74, 0x75}, 0, "81 EC XX XX XX XX : sub esp, XX XX XX XX"}, 874351ee305Sbernhardu { 6, {0xFF, 0x89, 0x72, 0x73, 0x74, 0x75}, 0, "FF 89 XX XX XX XX : dec dword ptr [ecx + XX XX XX XX]"}, 8759a9e41caSbernhardu { 7, {0x8D, 0xA4, 0x24, 0x73, 0x74, 0x75, 0x76}, 0, "8D A4 24 XX XX XX XX : lea esp, [esp + XX XX XX XX]"}, 876b8d857efSbernhardu #if SANITIZER_WINDOWS_x64 877b8d857efSbernhardu // sorted list 878b8d857efSbernhardu { 2, {0x40, 0x50}, 0, "40 50 : push rax"}, 879b8d857efSbernhardu { 2, {0x40, 0x51}, 0, "40 51 : push rcx"}, 880b8d857efSbernhardu { 2, {0x40, 0x52}, 0, "40 52 : push rdx"}, 881b8d857efSbernhardu { 2, {0x40, 0x53}, 0, "40 53 : push rbx"}, 882b8d857efSbernhardu { 2, {0x40, 0x54}, 0, "40 54 : push rsp"}, 883b8d857efSbernhardu { 2, {0x40, 0x55}, 0, "40 55 : push rbp"}, 884b8d857efSbernhardu { 2, {0x40, 0x56}, 0, "40 56 : push rsi"}, 885b8d857efSbernhardu { 2, {0x40, 0x57}, 0, "40 57 : push rdi"}, 886b8d857efSbernhardu { 2, {0x41, 0x54}, 0, "41 54 : push r12"}, 887b8d857efSbernhardu { 2, {0x41, 0x55}, 0, "41 55 : push r13"}, 888b8d857efSbernhardu { 2, {0x41, 0x56}, 0, "41 56 : push r14"}, 889b8d857efSbernhardu { 2, {0x41, 0x57}, 0, "41 57 : push r15"}, 890b8d857efSbernhardu { 2, {0x66, 0x90}, 0, "66 90 : Two-byte NOP"}, 891b8d857efSbernhardu { 2, {0x84, 0xc0}, 0, "84 c0 : test al, al"}, 892b8d857efSbernhardu { 2, {0x8a, 0x01}, 0, "8a 01 : mov al, byte ptr [rcx]"}, 89357466db7Sbernhardu { 3, {0x0f, 0xb6, 0x01}, 0, "0f b6 01 : movzx eax, BYTE PTR [rcx]"}, 89457466db7Sbernhardu { 3, {0x0f, 0xb6, 0x09}, 0, "0f b6 09 : movzx ecx, BYTE PTR [rcx]"}, 89557466db7Sbernhardu { 3, {0x0f, 0xb6, 0x11}, 0, "0f b6 11 : movzx edx, BYTE PTR [rcx]"}, 896b8d857efSbernhardu { 3, {0x0f, 0xb6, 0xc2}, 0, "0f b6 c2 : movzx eax, dl"}, 897b8d857efSbernhardu { 3, {0x0f, 0xb6, 0xd2}, 0, "0f b6 d2 : movzx edx, dl"}, 898b8d857efSbernhardu { 3, {0x0f, 0xb7, 0x10}, 0, "0f b7 10 : movzx edx, WORD PTR [rax]"}, 89957466db7Sbernhardu { 3, {0x0f, 0xbe, 0xd2}, 0, "0f be d2 : movsx edx, dl"}, 900b8d857efSbernhardu { 3, {0x41, 0x8b, 0xc0}, 0, "41 8b c0 : mov eax, r8d"}, 901b8d857efSbernhardu { 3, {0x41, 0x8b, 0xc1}, 0, "41 8b c1 : mov eax, r9d"}, 902b8d857efSbernhardu { 3, {0x41, 0x8b, 0xc2}, 0, "41 8b c2 : mov eax, r10d"}, 903b8d857efSbernhardu { 3, {0x41, 0x8b, 0xc3}, 0, "41 8b c3 : mov eax, r11d"}, 904b8d857efSbernhardu { 3, {0x41, 0x8b, 0xc4}, 0, "41 8b c4 : mov eax, r12d"}, 90557466db7Sbernhardu { 3, {0x45, 0x31, 0xc0}, 0, "45 31 c0 : xor r8d,r8d"}, 90657466db7Sbernhardu { 3, {0x45, 0x31, 0xc9}, 0, "45 31 c9 : xor r9d,r9d"}, 907b8d857efSbernhardu { 3, {0x45, 0x33, 0xc0}, 0, "45 33 c0 : xor r8d, r8d"}, 908b8d857efSbernhardu { 3, {0x45, 0x33, 0xc9}, 0, "45 33 c9 : xor r9d, r9d"}, 909b8d857efSbernhardu { 3, {0x45, 0x33, 0xdb}, 0, "45 33 db : xor r11d, r11d"}, 91057466db7Sbernhardu { 3, {0x45, 0x84, 0xc0}, 0, "45 84 c0 : test r8b,r8b"}, 91157466db7Sbernhardu { 3, {0x45, 0x84, 0xd2}, 0, "45 84 d2 : test r10b,r10b"}, 91257466db7Sbernhardu { 3, {0x48, 0x29, 0xd1}, 0, "48 29 d1 : sub rcx, rdx"}, 913b8d857efSbernhardu { 3, {0x48, 0x2b, 0xca}, 0, "48 2b ca : sub rcx, rdx"}, 914b8d857efSbernhardu { 3, {0x48, 0x2b, 0xd1}, 0, "48 2b d1 : sub rdx, rcx"}, 915b8d857efSbernhardu { 3, {0x48, 0x3b, 0xca}, 0, "48 3b ca : cmp rcx, rdx"}, 916b8d857efSbernhardu { 3, {0x48, 0x85, 0xc0}, 0, "48 85 c0 : test rax, rax"}, 917b8d857efSbernhardu { 3, {0x48, 0x85, 0xc9}, 0, "48 85 c9 : test rcx, rcx"}, 918b8d857efSbernhardu { 3, {0x48, 0x85, 0xd2}, 0, "48 85 d2 : test rdx, rdx"}, 919b8d857efSbernhardu { 3, {0x48, 0x85, 0xdb}, 0, "48 85 db : test rbx, rbx"}, 920b8d857efSbernhardu { 3, {0x48, 0x85, 0xe4}, 0, "48 85 e4 : test rsp, rsp"}, 921b8d857efSbernhardu { 3, {0x48, 0x85, 0xed}, 0, "48 85 ed : test rbp, rbp"}, 92257466db7Sbernhardu { 3, {0x48, 0x89, 0xc8}, 0, "48 89 c8 : mov rax,rcx"}, 92357466db7Sbernhardu { 3, {0x48, 0x89, 0xcb}, 0, "48 89 cb : mov rbx,rcx"}, 92457466db7Sbernhardu { 3, {0x48, 0x89, 0xd0}, 0, "48 89 d0 : mov rax,rdx"}, 92557466db7Sbernhardu { 3, {0x48, 0x89, 0xd1}, 0, "48 89 d1 : mov rcx,rdx"}, 92657466db7Sbernhardu { 3, {0x48, 0x89, 0xd3}, 0, "48 89 d3 : mov rbx,rdx"}, 927b8d857efSbernhardu { 3, {0x48, 0x89, 0xe5}, 0, "48 89 e5 : mov rbp, rsp"}, 928b8d857efSbernhardu { 3, {0x48, 0x8b, 0xc1}, 0, "48 8b c1 : mov rax, rcx"}, 929b8d857efSbernhardu { 3, {0x48, 0x8b, 0xc4}, 0, "48 8b c4 : mov rax, rsp"}, 930b8d857efSbernhardu { 3, {0x48, 0x8b, 0xd1}, 0, "48 8b d1 : mov rdx, rcx"}, 931b8d857efSbernhardu { 3, {0x48, 0xf7, 0xd9}, 0, "48 f7 d9 : neg rcx"}, 932b8d857efSbernhardu { 3, {0x48, 0xff, 0xc0}, 0, "48 ff c0 : inc rax"}, 933b8d857efSbernhardu { 3, {0x48, 0xff, 0xc1}, 0, "48 ff c1 : inc rcx"}, 934b8d857efSbernhardu { 3, {0x48, 0xff, 0xc2}, 0, "48 ff c2 : inc rdx"}, 935b8d857efSbernhardu { 3, {0x48, 0xff, 0xc3}, 0, "48 ff c3 : inc rbx"}, 936b8d857efSbernhardu { 3, {0x48, 0xff, 0xc6}, 0, "48 ff c6 : inc rsi"}, 937b8d857efSbernhardu { 3, {0x48, 0xff, 0xc7}, 0, "48 ff c7 : inc rdi"}, 93857466db7Sbernhardu { 3, {0x49, 0x89, 0xc8}, 0, "49 89 c8 : mov r8, rcx"}, 93957466db7Sbernhardu { 3, {0x49, 0x89, 0xc9}, 0, "49 89 c9 : mov r9, rcx"}, 94057466db7Sbernhardu { 3, {0x49, 0x89, 0xca}, 0, "49 89 ca : mov r10,rcx"}, 94157466db7Sbernhardu { 3, {0x49, 0x89, 0xd0}, 0, "49 89 d0 : mov r8, rdx"}, 94257466db7Sbernhardu { 3, {0x49, 0x89, 0xd1}, 0, "49 89 d1 : mov r9, rdx"}, 94357466db7Sbernhardu { 3, {0x49, 0x89, 0xd2}, 0, "49 89 d2 : mov r10, rdx"}, 94457466db7Sbernhardu { 3, {0x49, 0x89, 0xd3}, 0, "49 89 d3 : mov r11, rdx"}, 945b8d857efSbernhardu { 3, {0x49, 0xff, 0xc0}, 0, "49 ff c0 : inc r8"}, 946b8d857efSbernhardu { 3, {0x49, 0xff, 0xc1}, 0, "49 ff c1 : inc r9"}, 947b8d857efSbernhardu { 3, {0x49, 0xff, 0xc2}, 0, "49 ff c2 : inc r10"}, 948b8d857efSbernhardu { 3, {0x49, 0xff, 0xc3}, 0, "49 ff c3 : inc r11"}, 949b8d857efSbernhardu { 3, {0x49, 0xff, 0xc4}, 0, "49 ff c4 : inc r12"}, 950b8d857efSbernhardu { 3, {0x49, 0xff, 0xc5}, 0, "49 ff c5 : inc r13"}, 951b8d857efSbernhardu { 3, {0x49, 0xff, 0xc6}, 0, "49 ff c6 : inc r14"}, 952b8d857efSbernhardu { 3, {0x49, 0xff, 0xc7}, 0, "49 ff c7 : inc r15"}, 953b8d857efSbernhardu { 3, {0x4c, 0x8b, 0xc1}, 0, "4c 8b c1 : mov r8, rcx"}, 954b8d857efSbernhardu { 3, {0x4c, 0x8b, 0xc9}, 0, "4c 8b c9 : mov r9, rcx"}, 955b8d857efSbernhardu { 3, {0x4c, 0x8b, 0xd1}, 0, "4c 8b d1 : mov r10, rcx"}, 956b8d857efSbernhardu { 3, {0x4c, 0x8b, 0xd2}, 0, "4c 8b d2 : mov r10, rdx"}, 957b8d857efSbernhardu { 3, {0x4c, 0x8b, 0xd9}, 0, "4c 8b d9 : mov r11, rcx"}, 958b8d857efSbernhardu { 3, {0x4c, 0x8b, 0xdc}, 0, "4c 8b dc : mov r11, rsp"}, 959b8d857efSbernhardu { 3, {0x4d, 0x0b, 0xc0}, 0, "4d 0b c0 : or r8, r8"}, 960b8d857efSbernhardu { 3, {0x4d, 0x85, 0xc0}, 0, "4d 85 c0 : test r8, r8"}, 961b8d857efSbernhardu { 3, {0x4d, 0x85, 0xc9}, 0, "4d 85 c9 : test r9, r9"}, 962b8d857efSbernhardu { 3, {0x4d, 0x85, 0xd2}, 0, "4d 85 d2 : test r10, r10"}, 963b8d857efSbernhardu { 3, {0x4d, 0x85, 0xdb}, 0, "4d 85 db : test r11, r11"}, 964b8d857efSbernhardu { 3, {0x4d, 0x85, 0xe4}, 0, "4d 85 e4 : test r12, r12"}, 965b8d857efSbernhardu { 3, {0x4d, 0x85, 0xed}, 0, "4d 85 ed : test r13, r13"}, 966b8d857efSbernhardu { 3, {0x4d, 0x85, 0xf6}, 0, "4d 85 f6 : test r14, r14"}, 967b8d857efSbernhardu { 3, {0x4d, 0x85, 0xff}, 0, "4d 85 ff : test r15, r15"}, 968bf6f1ca2Sbernhardu { 3, {0xf6, 0xc1, 0x72}, 0, "f6 c1 XX : test cl, XX"}, 96956592a81Sbernhardu { 4, {0x44, 0x0f, 0xb6, 0x01}, 0, "44 0f b6 01 : movzx r8d, BYTE PTR [rcx]"}, 97056592a81Sbernhardu { 4, {0x44, 0x0f, 0xb6, 0x09}, 0, "44 0f b6 09 : movzx r9d, BYTE PTR [rcx]"}, 97156592a81Sbernhardu { 4, {0x44, 0x0f, 0xb6, 0x0a}, 0, "44 0f b6 0a : movzx r8d, BYTE PTR [rdx]"}, 97256592a81Sbernhardu { 4, {0x44, 0x0f, 0xb6, 0x11}, 0, "44 0f b6 11 : movzx r10d, BYTE PTR [rcx]"}, 973b8d857efSbernhardu { 4, {0x44, 0x0f, 0xb6, 0x1a}, 0, "44 0f b6 1a : movzx r11d, BYTE PTR [rdx]"}, 974b8d857efSbernhardu { 4, {0x44, 0x8d, 0x42, 0x73}, 0, "44 8d 42 XX : lea r8d , [rdx + XX]"}, 975b8d857efSbernhardu { 4, {0x48, 0x83, 0xec, 0x73}, 0, "48 83 ec XX : sub rsp, XX"}, 976b8d857efSbernhardu { 4, {0x48, 0x89, 0x58, 0x73}, 0, "48 89 58 XX : mov QWORD PTR[rax + XX], rbx"}, 977b8d857efSbernhardu { 4, {0x49, 0x83, 0xf8, 0x73}, 0, "49 83 f8 XX : cmp r8, XX"}, 97856592a81Sbernhardu { 4, {0x49, 0x8d, 0x48, 0x73}, 0, "49 8d 48 XX : lea rcx, [...]"}, 97956592a81Sbernhardu { 4, {0x4c, 0x8d, 0x04, 0x73}, 0, "4c 8d 04 XX : lea r8, [...]"}, 98056592a81Sbernhardu { 4, {0x4e, 0x8d, 0x14, 0x73}, 0, "4e 8d 14 XX : lea r10, [...]"}, 98156592a81Sbernhardu { 4, {0x66, 0x83, 0x39, 0x73}, 0, "66 83 39 XX : cmp WORD PTR [rcx], XX"}, 982b8d857efSbernhardu { 4, {0x80, 0x78, 0x72, 0x73}, 0, "80 78 YY XX : cmp BYTE PTR [rax+YY], XX"}, 983b8d857efSbernhardu { 4, {0x80, 0x79, 0x72, 0x73}, 0, "80 79 YY XX : cmp BYTE ptr [rcx+YY], XX"}, 984b8d857efSbernhardu { 4, {0x80, 0x7A, 0x72, 0x73}, 0, "80 7A YY XX : cmp BYTE PTR [rdx+YY], XX"}, 985b8d857efSbernhardu { 4, {0x80, 0x7B, 0x72, 0x73}, 0, "80 7B YY XX : cmp BYTE PTR [rbx+YY], XX"}, 986b8d857efSbernhardu { 4, {0x80, 0x7D, 0x72, 0x73}, 0, "80 7D YY XX : cmp BYTE PTR [rbp+YY], XX"}, 987b8d857efSbernhardu { 4, {0x80, 0x7E, 0x72, 0x73}, 0, "80 7E YY XX : cmp BYTE PTR [rsi+YY], XX"}, 988b8d857efSbernhardu { 4, {0x89, 0x54, 0x24, 0x73}, 0, "89 54 24 XX : mov DWORD PTR[rsp + XX], edx"}, 9895f405707Sbernhardu { 5, {0x0F, 0x1F, 0x44, 0x73, 0x74}, 0, "0F 1F 44 XX XX : nop DWORD PTR [...]"}, 990b8d857efSbernhardu { 5, {0x44, 0x89, 0x44, 0x24, 0x74}, 0, "44 89 44 24 XX : mov DWORD PTR [rsp + XX], r8d"}, 991b8d857efSbernhardu { 5, {0x44, 0x89, 0x4c, 0x24, 0x74}, 0, "44 89 4c 24 XX : mov DWORD PTR [rsp + XX], r9d"}, 992b8d857efSbernhardu { 5, {0x48, 0x89, 0x4C, 0x24, 0x74}, 0, "48 89 4C 24 XX : mov QWORD PTR [rsp + XX], rcx"}, 993b8d857efSbernhardu { 5, {0x48, 0x89, 0x54, 0x24, 0x74}, 0, "48 89 54 24 XX : mov QWORD PTR [rsp + XX], rdx"}, 994b8d857efSbernhardu { 5, {0x48, 0x89, 0x5c, 0x24, 0x74}, 0, "48 89 5c 24 XX : mov QWORD PTR [rsp + XX], rbx"}, 995b8d857efSbernhardu { 5, {0x48, 0x89, 0x6c, 0x24, 0x74}, 0, "48 89 6C 24 XX : mov QWORD ptr [rsp + XX], rbp"}, 996b8d857efSbernhardu { 5, {0x48, 0x89, 0x74, 0x24, 0x74}, 0, "48 89 74 24 XX : mov QWORD PTR [rsp + XX], rsi"}, 997b8d857efSbernhardu { 5, {0x48, 0x89, 0x7c, 0x24, 0x74}, 0, "48 89 7c 24 XX : mov QWORD PTR [rsp + XX], rdi"}, 998b8d857efSbernhardu { 5, {0x48, 0x8b, 0x44, 0x24, 0x74}, 0, "48 8b 44 24 XX : mov rax, QWORD ptr [rsp + XX]"}, 999b8d857efSbernhardu { 5, {0x48, 0x8d, 0x6c, 0x24, 0x74}, 0, "48 8d 6c 24 XX : lea rbp, [rsp + XX]"}, 1000b8d857efSbernhardu { 5, {0x4c, 0x89, 0x44, 0x24, 0x74}, 0, "4c 89 44 24 XX : mov QWORD PTR [rsp + XX], r8"}, 1001b8d857efSbernhardu { 5, {0x4c, 0x89, 0x4c, 0x24, 0x74}, 0, "4c 89 4c 24 XX : mov QWORD PTR [rsp + XX], r9"}, 10025f405707Sbernhardu { 5, {0x66, 0x48, 0x0F, 0x7E, 0xC0}, 0, "66 48 0F 7E C0 : movq rax, xmm0"}, 1003b8d857efSbernhardu { 5, {0x83, 0x44, 0x72, 0x73, 0x74}, 0, "83 44 72 XX YY : add DWORD PTR [rdx+rsi*2+XX],YY"}, 1004b8d857efSbernhardu { 5, {0x83, 0x64, 0x24, 0x73, 0x74}, 0, "83 64 24 XX YY : and DWORD PTR [rsp+XX], YY"}, 1005351ee305Sbernhardu { 6, {0x41, 0xB8, 0x72, 0x73, 0x74, 0x75}, 0, "41 B8 XX XX XX XX : mov r8d, XX XX XX XX"}, 1006b8d857efSbernhardu { 6, {0x48, 0x83, 0x64, 0x24, 0x74, 0x75}, 0, "48 83 64 24 XX YY : and QWORD PTR [rsp + XX], YY"}, 1007b8d857efSbernhardu { 6, {0x66, 0x81, 0x78, 0x73, 0x74, 0x75}, 0, "66 81 78 XX YY YY : cmp WORD PTR [rax+XX], YY YY"}, 1008b8d857efSbernhardu { 6, {0x66, 0x81, 0x79, 0x73, 0x74, 0x75}, 0, "66 81 79 XX YY YY : cmp WORD PTR [rcx+XX], YY YY"}, 1009b8d857efSbernhardu { 6, {0x66, 0x81, 0x7a, 0x73, 0x74, 0x75}, 0, "66 81 7a XX YY YY : cmp WORD PTR [rdx+XX], YY YY"}, 1010b8d857efSbernhardu { 6, {0x66, 0x81, 0x7b, 0x73, 0x74, 0x75}, 0, "66 81 7b XX YY YY : cmp WORD PTR [rbx+XX], YY YY"}, 1011b8d857efSbernhardu { 6, {0x66, 0x81, 0x7e, 0x73, 0x74, 0x75}, 0, "66 81 7e XX YY YY : cmp WORD PTR [rsi+XX], YY YY"}, 1012b8d857efSbernhardu { 6, {0x66, 0x81, 0x7f, 0x73, 0x74, 0x75}, 0, "66 81 7f XX YY YY : cmp WORD PTR [rdi+XX], YY YY"}, 1013b8d857efSbernhardu { 6, {0x8A, 0x05, 0x72, 0x73, 0x74, 0x75}, 2, "8A 05 XX XX XX XX : mov al, byte ptr [XX XX XX XX]"}, 1014b8d857efSbernhardu { 6, {0x8B, 0x05, 0x72, 0x73, 0x74, 0x75}, 2, "8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX]"}, 1015b8d857efSbernhardu { 6, {0xF2, 0x0f, 0x11, 0x44, 0x24, 0x75}, 0, "f2 0f 11 44 24 XX : movsd QWORD PTR [rsp + XX], xmm0"}, 1016b8d857efSbernhardu { 6, {0xF2, 0x0f, 0x11, 0x4c, 0x24, 0x75}, 0, "f2 0f 11 4c 24 XX : movsd QWORD PTR [rsp + XX], xmm1"}, 1017b8d857efSbernhardu { 6, {0xF2, 0x0f, 0x11, 0x54, 0x24, 0x75}, 0, "f2 0f 11 54 24 XX : movsd QWORD PTR [rsp + XX], xmm2"}, 1018b8d857efSbernhardu { 6, {0xF2, 0x0f, 0x11, 0x5c, 0x24, 0x75}, 0, "f2 0f 11 5c 24 XX : movsd QWORD PTR [rsp + XX], xmm3"}, 1019b8d857efSbernhardu { 6, {0xF2, 0x0f, 0x11, 0x64, 0x24, 0x75}, 0, "f2 0f 11 64 24 XX : movsd QWORD PTR [rsp + XX], xmm4"}, 1020b8d857efSbernhardu { 7, {0x48, 0x81, 0xec, 0x73, 0x74, 0x75, 0x76}, 0, "48 81 EC XX XX XX XX : sub rsp, XXXXXXXX"}, 1021b8d857efSbernhardu { 7, {0x48, 0x89, 0x0d, 0x73, 0x74, 0x75, 0x76}, 3, "48 89 0d XX XX XX XX : mov QWORD PTR [rip + XXXXXXXX], rcx"}, 1022b8d857efSbernhardu { 7, {0x48, 0x89, 0x15, 0x73, 0x74, 0x75, 0x76}, 3, "48 89 15 XX XX XX XX : mov QWORD PTR [rip + XXXXXXXX], rdx"}, 1023b8d857efSbernhardu { 7, {0x48, 0x8b, 0x05, 0x73, 0x74, 0x75, 0x76}, 3, "48 8b 05 XX XX XX XX : mov rax, QWORD PTR [rip + XXXXXXXX]"}, 1024b8d857efSbernhardu { 7, {0x48, 0x8d, 0x05, 0x73, 0x74, 0x75, 0x76}, 3, "48 8d 05 XX XX XX XX : lea rax, QWORD PTR [rip + XXXXXXXX]"}, 1025*bbf37706Sbernhardu { 7, {0x48, 0xc7, 0xc0, 0x73, 0x74, 0x75, 0x76}, 0, "48 C7 C0 XX XX XX XX : mov rax, XX XX XX XX"}, 1026b8d857efSbernhardu { 7, {0x48, 0xff, 0x25, 0x73, 0x74, 0x75, 0x76}, 3, "48 ff 25 XX XX XX XX : rex.W jmp QWORD PTR [rip + XXXXXXXX]"}, 1027b8d857efSbernhardu { 7, {0x4C, 0x8D, 0x15, 0x73, 0x74, 0x75, 0x76}, 3, "4c 8d 15 XX XX XX XX : lea r10, [rip + XX]"}, 1028b8d857efSbernhardu { 7, {0x81, 0x78, 0x72, 0x73, 0x74, 0x75, 0x76}, 0, "81 78 YY XX XX XX XX : cmp DWORD PTR [rax+YY], XX XX XX XX"}, 1029b8d857efSbernhardu { 7, {0x81, 0x79, 0x72, 0x73, 0x74, 0x75, 0x76}, 0, "81 79 YY XX XX XX XX : cmp dword ptr [rcx+YY], XX XX XX XX"}, 1030b8d857efSbernhardu { 7, {0x81, 0x7A, 0x72, 0x73, 0x74, 0x75, 0x76}, 0, "81 7A YY XX XX XX XX : cmp DWORD PTR [rdx+YY], XX XX XX XX"}, 1031b8d857efSbernhardu { 7, {0x81, 0x7B, 0x72, 0x73, 0x74, 0x75, 0x76}, 0, "81 7B YY XX XX XX XX : cmp DWORD PTR [rbx+YY], XX XX XX XX"}, 1032b8d857efSbernhardu { 7, {0x81, 0x7D, 0x72, 0x73, 0x74, 0x75, 0x76}, 0, "81 7D YY XX XX XX XX : cmp DWORD PTR [rbp+YY], XX XX XX XX"}, 1033b8d857efSbernhardu { 7, {0x81, 0x7E, 0x72, 0x73, 0x74, 0x75, 0x76}, 0, "81 7E YY XX XX XX XX : cmp DWORD PTR [rsi+YY], XX XX XX XX"}, 1034b8d857efSbernhardu { 8, {0x41, 0x81, 0x78, 0x73, 0x74, 0x75, 0x76, 0x77}, 0, "41 81 78 XX YY YY YY YY : cmp DWORD PTR [r8+YY], XX XX XX XX"}, 1035b8d857efSbernhardu { 8, {0x41, 0x81, 0x79, 0x73, 0x74, 0x75, 0x76, 0x77}, 0, "41 81 79 XX YY YY YY YY : cmp DWORD PTR [r9+YY], XX XX XX XX"}, 1036b8d857efSbernhardu { 8, {0x41, 0x81, 0x7a, 0x73, 0x74, 0x75, 0x76, 0x77}, 0, "41 81 7a XX YY YY YY YY : cmp DWORD PTR [r10+YY], XX XX XX XX"}, 1037b8d857efSbernhardu { 8, {0x41, 0x81, 0x7b, 0x73, 0x74, 0x75, 0x76, 0x77}, 0, "41 81 7b XX YY YY YY YY : cmp DWORD PTR [r11+YY], XX XX XX XX"}, 1038b8d857efSbernhardu { 8, {0x41, 0x81, 0x7d, 0x73, 0x74, 0x75, 0x76, 0x77}, 0, "41 81 7d XX YY YY YY YY : cmp DWORD PTR [r13+YY], XX XX XX XX"}, 1039b8d857efSbernhardu { 8, {0x41, 0x81, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77}, 0, "41 81 7e XX YY YY YY YY : cmp DWORD PTR [r14+YY], XX XX XX XX"}, 1040b8d857efSbernhardu { 8, {0x41, 0x81, 0x7f, 0x73, 0x74, 0x75, 0x76, 0x77}, 0, "41 81 7f YY XX XX XX XX : cmp DWORD PTR [r15+YY], XX XX XX XX"}, 1041*bbf37706Sbernhardu { 8, {0x48, 0x8D, 0xA4, 0x24, 0x74, 0x75, 0x76, 0x77}, 0, "48 8D A4 24 XX XX XX XX : lea rsp, [rsp + XX XX XX XX]"}, 1042b8d857efSbernhardu { 8, {0x81, 0x7c, 0x24, 0x73, 0x74, 0x75, 0x76, 0x77}, 0, "81 7c 24 YY XX XX XX XX : cmp DWORD PTR [rsp+YY], XX XX XX XX"}, 1043b8d857efSbernhardu { 8, {0xc7, 0x44, 0x24, 0x73, 0x74, 0x75, 0x76, 0x77}, 0, "C7 44 24 XX YY YY YY YY : mov dword ptr [rsp + XX], YYYYYYYY"}, 1044213c90d3Sbernhardu { 9, {0x41, 0x81, 0x7c, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78}, 0, "41 81 7c ZZ YY XX XX XX XX : cmp DWORD PTR [reg+reg*n+YY], XX XX XX XX"}, 1045b8d857efSbernhardu { 9, {0xA1, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78}, 0, "A1 XX XX XX XX XX XX XX XX : movabs eax, dword ptr ds:[XXXXXXXX]"}, 1046b8d857efSbernhardu #else 1047b8d857efSbernhardu // sorted list 1048b8d857efSbernhardu { 3, {0x8B, 0x45, 0x72}, 0, "8B 45 XX : mov eax, dword ptr [ebp + XX]"}, 1049b8d857efSbernhardu { 3, {0x8B, 0x5D, 0x72}, 0, "8B 5D XX : mov ebx, dword ptr [ebp + XX]"}, 1050b8d857efSbernhardu { 3, {0x8B, 0x75, 0x72}, 0, "8B 75 XX : mov esi, dword ptr [ebp + XX]"}, 1051b8d857efSbernhardu { 3, {0x8B, 0x7D, 0x72}, 0, "8B 7D XX : mov edi, dword ptr [ebp + XX]"}, 1052b8d857efSbernhardu { 3, {0xFF, 0x75, 0x72}, 0, "FF 75 XX : push dword ptr [ebp + XX]"}, 1053b8d857efSbernhardu { 4, {0x83, 0x7D, 0x72, 0x73}, 0, "83 7D XX YY : cmp dword ptr [ebp + XX], YY"}, 1054b8d857efSbernhardu { 4, {0x8A, 0x44, 0x24, 0x73}, 0, "8A 44 24 XX : mov eal, dword ptr [esp + XX]"}, 1055b8d857efSbernhardu { 4, {0x8B, 0x44, 0x24, 0x73}, 0, "8B 44 24 XX : mov eax, dword ptr [esp + XX]"}, 1056b8d857efSbernhardu { 4, {0x8B, 0x4C, 0x24, 0x73}, 0, "8B 4C 24 XX : mov ecx, dword ptr [esp + XX]"}, 1057b8d857efSbernhardu { 4, {0x8B, 0x54, 0x24, 0x73}, 0, "8B 54 24 XX : mov edx, dword ptr [esp + XX]"}, 1058b8d857efSbernhardu { 4, {0x8B, 0x5C, 0x24, 0x73}, 0, "8B 5C 24 XX : mov ebx, dword ptr [esp + XX]"}, 1059b8d857efSbernhardu { 4, {0x8B, 0x6C, 0x24, 0x73}, 0, "8B 6C 24 XX : mov ebp, dword ptr [esp + XX]"}, 1060b8d857efSbernhardu { 4, {0x8B, 0x74, 0x24, 0x73}, 0, "8B 74 24 XX : mov esi, dword ptr [esp + XX]"}, 1061b8d857efSbernhardu { 4, {0x8B, 0x7C, 0x24, 0x73}, 0, "8B 7C 24 XX : mov edi, dword ptr [esp + XX]"}, 1062b8d857efSbernhardu { 5, {0x0F, 0xB6, 0x44, 0x24, 0x74}, 0, "0F B6 44 24 XX : movzx eax, byte ptr [esp + XX]"}, 1063b8d857efSbernhardu { 5, {0xA1, 0x71, 0x72, 0x73, 0x74}, 0, "A1 XX XX XX XX : mov eax, dword ptr ds:[XXXXXXXX]"}, 1064b8d857efSbernhardu { 6, {0xF7, 0xC1, 0x72, 0x73, 0x74, 0x75}, 0, "F7 C1 XX YY ZZ WW : test ecx, WWZZYYXX"}, 1065b8d857efSbernhardu { 7, {0x83, 0x3D, 0x72, 0x73, 0x74, 0x75, 0x76}, 0, "83 3D XX YY ZZ WW TT : cmp TT, WWZZYYXX"}, 1066b8d857efSbernhardu #endif 1067b8d857efSbernhardu // clang-format on 106836b1811dSbernhardu }; 106936b1811dSbernhardu 107036b1811dSbernhardu std::string dumpInstruction(unsigned arrayIndex, 107136b1811dSbernhardu const InstructionSizeData &data) { 107236b1811dSbernhardu std::stringstream ret; 107336b1811dSbernhardu ret << " with arrayIndex=" << arrayIndex << " {"; 107436b1811dSbernhardu for (size_t i = 0; i < data.size; i++) { 107536b1811dSbernhardu if (i > 0) 107636b1811dSbernhardu ret << ", "; 107736b1811dSbernhardu ret << "0x" << std::setfill('0') << std::setw(2) << std::right << std::hex 107836b1811dSbernhardu << (int)data.instr[i]; 107936b1811dSbernhardu } 108036b1811dSbernhardu ret << "} " << data.comment; 108136b1811dSbernhardu return ret.str(); 108236b1811dSbernhardu } 108336b1811dSbernhardu 108436b1811dSbernhardu TEST(Interception, GetInstructionSize) { 108536b1811dSbernhardu for (unsigned i = 0; i < sizeof(data) / sizeof(*data); i++) { 108636b1811dSbernhardu size_t rel_offset = ~0L; 108736b1811dSbernhardu size_t size = __interception::TestOnlyGetInstructionSize( 108836b1811dSbernhardu (uptr)data[i].instr, &rel_offset); 108936b1811dSbernhardu EXPECT_EQ(data[i].size, size) << dumpInstruction(i, data[i]); 109036b1811dSbernhardu EXPECT_EQ(data[i].rel_offset, rel_offset) << dumpInstruction(i, data[i]); 109136b1811dSbernhardu } 109236b1811dSbernhardu } 109336b1811dSbernhardu 10949642e337SNico Weber } // namespace __interception 10959642e337SNico Weber 1096d79aee9fSFarzon Lotfi # endif // !SANITIZER_WINDOWS_ARM64 10979642e337SNico Weber #endif // SANITIZER_WINDOWS 10989642e337SNico Weber #endif // #if !SANITIZER_DEBUG 1099