// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Lysann Tranvouez. All rights reserved. #pragma once #ifndef MACH_DETOURS_ARM64_H #define MACH_DETOURS_ARM64_H #include typedef struct detour_align { uint8_t obTarget; uint8_t obTrampoline; } detour_align; typedef struct detour_trampoline { // An ARM64 instruction is 4 bytes long. // // The overwrite is always composed of 3 instructions (12 bytes) which perform an indirect jump // using _DETOUR_TRAMPOLINE::pbDetour as the address holding the target location. // // Copied instructions can expand. // // The scheme using MovImmediate can cause an instruction // to grow as much as 6 times. // That would be Bcc or Tbz with a large address space: // 4 instructions to form immediate // inverted tbz/bcc // br // // An expansion of 4 is not uncommon -- bl/blr and small address space: // 3 instructions to form immediate // br or brl // // A theoretical maximum for rbCode is thefore 4*4*6 + 16 = 112 (another 16 for jmp to pbRemain). // // With literals, the maximum expansion is 5, including the literals: 4*4*5 + 16 = 96. // // The number is rounded up to 128. m_rbScratchDst should match this. // uint8_t code[128]; // target code + jmp to pbRemain uint8_t code_size; // size of moved target code. uint8_t code_padding[3]; // padding to make debugging easier. uint8_t restore_code[24]; // original target code. uint8_t restore_code_size; // size of original target code. uint8_t restore_code_padding[3]; // padding to make debugging easier. detour_align align[8]; // instruction alignment array. uint8_t* ptr_remain; // first instruction after moved code. [free list] uint8_t* ptr_detour; // first instruction of detour function. } detour_trampoline; static_assert(sizeof(detour_trampoline) == 192); #endif //MACH_DETOURS_ARM64_H