Lines Matching +full:48 +full:- +full:bit
1 //===-- interception_win.cpp ------------------------------------*- C++ -*-===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 // Windows-specific interception methods.
20 // On 64-bit architecture, there is no direct 64-bit jump instruction. To allow
23 // where it is safe to add custom assembly code to build 64-bit jumps.
31 // padding and an overridable 2-bytes nop instruction (mov edi, edi). The
32 // nop instruction can safely be replaced by a 2-bytes jump without any need
37 // func: mov edi, edi --> func: jmp short <head>
40 // This technique is only implemented on 32-bit architecture.
48 // func: jmp <label> --> func: jmp <hook>
50 // On an 64-bit architecture, a trampoline is inserted.
52 // func: jmp <label> --> func: jmp <tramp>
64 // and a first instruction with at least 2-bytes.
66 // The reason to enforce the 2-bytes limitation is to provide the minimal
72 // see: https://msdn.microsoft.com/en-us/library/ms173507.aspx
73 // Default padding length is 5 bytes in 32-bits and 6 bytes in 64-bits.
76 // func: <instr> --> func: jmp short <head>
83 // On an 64-bit architecture:
86 // func: <instr> --> func: jmp short <head>
104 // func: <instr> --> func: jmp <hook>
113 // On an 64-bit architecture:
115 // func: <instr> --> func: jmp QWORD [addr1]
125 //===----------------------------------------------------------------------===//
173 return target - from <= (uptr)0x7FFFFFFFU; in DistanceIsWithin2Gig()
175 return from - target <= (uptr)0x80000000U; in DistanceIsWithin2Gig()
177 // In a 32-bit address space, the address calculation will wrap, so this check in DistanceIsWithin2Gig()
190 return (size + boundary - 1) & ~(boundary - 1); in RoundUpTo()
199 return p - str; in _strlen()
252 u8* function = (u8*)address - sizeof(pattern); in FunctionHasPrefix()
260 if (IsMemoryPadding(address - size, size)) in FunctionHasPadding()
280 ptrdiff_t offset = target - from - kJumpInstructionLength; in WriteJumpInstruction()
286 sptr offset = target - from - kShortJumpInstructionLength; in WriteShortJumpInstruction()
287 if (offset < -128 || offset > 127) in WriteShortJumpInstruction()
299 // 32-bit in x64, so indirect_target must be located within +/- 2GB range. in WriteIndirectJumpInstruction()
300 int offset = indirect_target - from - kIndirectJumpInstructionLength; in WriteIndirectJumpInstruction()
381 if (current->content == 0) in TestOnlyReleaseTrampolineRegions()
383 ::VirtualFree((void*)current->content, 0, MEM_RELEASE); in TestOnlyReleaseTrampolineRegions()
384 current->content = 0; in TestOnlyReleaseTrampolineRegions()
393 if (current->content == 0) { in AllocateMemoryForTrampoline()
400 current->content = (uptr)content; in AllocateMemoryForTrampoline()
401 current->allocated_size = 0; in AllocateMemoryForTrampoline()
402 current->max_size = bucket_size; in AllocateMemoryForTrampoline()
405 } else if (current->max_size - current->allocated_size > size) { in AllocateMemoryForTrampoline()
407 // In 64-bits, the memory space must be allocated within 2G boundary. in AllocateMemoryForTrampoline()
408 uptr next_address = current->content + current->allocated_size; in AllocateMemoryForTrampoline()
410 next_address - image_address >= 0x7FFF0000) in AllocateMemoryForTrampoline()
424 uptr allocated_space = region->content + region->allocated_size; in AllocateMemoryForTrampoline()
425 region->allocated_size += size; in AllocateMemoryForTrampoline()
441 // 75f4 jne -12
450 // 48ffc1 inc rcx
452 // 75f7 jne -9
504 // Cannot overwrite control-instruction. Return 0 to indicate failure. in GetInstructionSize()
539 // Cannot overwrite control-instruction. Return 0 to indicate failure. in GetInstructionSize()
582 case 0x9066: // Two-byte NOP in GetInstructionSize()
595 case 0xe58948: // 48 8b c4 : mov rbp, rsp in GetInstructionSize()
596 case 0xc18b48: // 48 8b c1 : mov rax, rcx in GetInstructionSize()
597 case 0xc48b48: // 48 8b c4 : mov rax, rsp in GetInstructionSize()
598 case 0xd9f748: // 48 f7 d9 : neg rcx in GetInstructionSize()
599 case 0xd12b48: // 48 2b d1 : sub rdx, rcx in GetInstructionSize()
601 case 0xc98548: // 48 85 C9 : test rcx, rcx in GetInstructionSize()
602 case 0xd28548: // 48 85 d2 : test rdx, rdx in GetInstructionSize()
613 case 0xca2b48: // 48 2b ca : sub rcx, rdx in GetInstructionSize()
614 case 0xca3b48: // 48 3b ca : cmp rcx, rdx in GetInstructionSize()
618 case 0xd18b48: // 48 8b d1 : mov rdx, rcx in GetInstructionSize()
624 case 0xec8348: // 48 83 ec XX : sub rsp, XX in GetInstructionSize()
626 case 0x588948: // 48 89 58 XX : mov QWORD PTR[rax + XX], rbx in GetInstructionSize()
629 case 0xec8148: // 48 81 EC XX XX XX XX : sub rsp, XXXXXXXX in GetInstructionSize()
632 case 0x058b48: // 48 8b 05 XX XX XX XX : in GetInstructionSize()
634 case 0x058d48: // 48 8d 05 XX XX XX XX : in GetInstructionSize()
636 case 0x25ff48: // 48 ff 25 XX XX XX XX : in GetInstructionSize()
650 case 0x24448b48: // 48 8b 44 24 XX : mov rax, QWORD ptr [rsp + XX] in GetInstructionSize()
651 case 0x246c8948: // 48 89 6C 24 XX : mov QWORD ptr [rsp + XX], rbp in GetInstructionSize()
652 case 0x245c8948: // 48 89 5c 24 XX : mov QWORD PTR [rsp + XX], rbx in GetInstructionSize()
653 case 0x24748948: // 48 89 74 24 XX : mov QWORD PTR [rsp + XX], rsi in GetInstructionSize()
654 case 0x247c8948: // 48 89 7c 24 XX : mov QWORD PTR [rsp + XX], rdi in GetInstructionSize()
655 case 0x244C8948: // 48 89 4C 24 XX : mov QWORD PTR [rsp + XX], rcx in GetInstructionSize()
656 case 0x24548948: // 48 89 54 24 XX : mov QWORD PTR [rsp + XX], rdx in GetInstructionSize()
660 case 0x24648348: // 48 83 64 24 XX : and QWORD PTR [rsp + XX], YY in GetInstructionSize()
744 // we want to make sure that the new relative offset still fits in 32-bits in CopyInstructions()
745 // this will be untrue if relocated_offset \notin [-2**31, 2**31) in CopyInstructions()
746 s64 delta = to - from; in CopyInstructions()
747 s64 relocated_offset = *(s32 *)(to + cursor + rel_offset) - delta; in CopyInstructions()
748 if (-0x8000'0000ll > relocated_offset || relocated_offset > 0x7FFF'FFFFll) in CopyInstructions()
751 // on 32-bit, the relative offset will always be correct in CopyInstructions()
752 s32 delta = to - from; in CopyInstructions()
753 s32 relocated_offset = *(s32 *)(to + cursor + rel_offset) - delta; in CopyInstructions()
769 uptr header = (uptr)old_func - kDetourHeaderLen; in OverrideFunctionWithDetour()
838 uptr header = (uptr)old_func - kHotPatchHeaderLen; in OverrideFunctionWithHotPatch()
913 if (IsMemoryPadding(old_func - kAddressLength, kAddressLength)) { in OverrideFunctionWithTrampoline()
914 indirect_address = old_func - kAddressLength; in OverrideFunctionWithTrampoline()
924 uptr patch_address = old_func - padding_length; in OverrideFunctionWithTrampoline()
994 T *operator->() { return ptr_; } in operator ->()
1010 RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew); in InternalGetProcAddress()
1011 if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ" in InternalGetProcAddress()
1012 headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0" in InternalGetProcAddress()
1013 headers->FileHeader.SizeOfOptionalHeader < in InternalGetProcAddress()
1019 &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; in InternalGetProcAddress()
1020 if (export_directory->Size == 0) in InternalGetProcAddress()
1023 export_directory->VirtualAddress); in InternalGetProcAddress()
1024 RVAPtr<DWORD> functions(module, exports->AddressOfFunctions); in InternalGetProcAddress()
1025 RVAPtr<DWORD> names(module, exports->AddressOfNames); in InternalGetProcAddress()
1026 RVAPtr<WORD> ordinals(module, exports->AddressOfNameOrdinals); in InternalGetProcAddress()
1028 for (DWORD i = 0; i < exports->NumberOfNames; i++) { in InternalGetProcAddress()
1036 if (offset >= export_directory->VirtualAddress && in InternalGetProcAddress()
1037 offset < export_directory->VirtualAddress + export_directory->Size) { in InternalGetProcAddress()
1043 if (funtion_name_length >= sizeof(function_name) - 1) in InternalGetProcAddress()
1090 RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew); in OverrideImportedFunction()
1091 if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ" in OverrideImportedFunction()
1092 headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0" in OverrideImportedFunction()
1093 headers->FileHeader.SizeOfOptionalHeader < in OverrideImportedFunction()
1099 &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; in OverrideImportedFunction()
1104 import_directory->VirtualAddress); in OverrideImportedFunction()
1105 for (; imports->FirstThunk != 0; ++imports) { in OverrideImportedFunction()
1106 RVAPtr<const char> modname(module, imports->Name); in OverrideImportedFunction()
1110 if (imports->FirstThunk == 0) in OverrideImportedFunction()
1117 RVAPtr<IMAGE_THUNK_DATA> name_table(module, imports->OriginalFirstThunk); in OverrideImportedFunction()
1118 RVAPtr<IMAGE_THUNK_DATA> iat(module, imports->FirstThunk); in OverrideImportedFunction()
1119 for (; name_table->u1.Ordinal != 0; ++name_table, ++iat) { in OverrideImportedFunction()
1120 if (!IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) { in OverrideImportedFunction()
1122 module, name_table->u1.ForwarderString); in OverrideImportedFunction()
1123 const char *funcname = &import_by_name->Name[0]; in OverrideImportedFunction()
1128 if (name_table->u1.Ordinal == 0) in OverrideImportedFunction()
1134 *orig_old_func = iat->u1.AddressOfData; in OverrideImportedFunction()
1136 if (!VirtualProtect(&iat->u1.AddressOfData, 4, PAGE_EXECUTE_READWRITE, in OverrideImportedFunction()
1139 iat->u1.AddressOfData = new_function; in OverrideImportedFunction()
1140 if (!VirtualProtect(&iat->u1.AddressOfData, 4, old_prot, &unused_prot)) in OverrideImportedFunction()