From 0a02858f5e8d5f91851081ebf7ec5d9b2e48bfcc Mon Sep 17 00:00:00 2001 From: Mike Gelfand Date: Sun, 21 Jun 2020 01:46:05 +0300 Subject: [PATCH] Implement `Replace::Replace` properly for aarch64 Add a separate implementation for aarch64 which boils down to ldr x17, =0x1122334455667788 br x17 The `x17` register is used as it's allowed to be modified during function call and doesn't require saving. Old approach under `SOME_ARM` ifdef that doesn't require changing any registers isn't possible since the `pc` register is no longer directly accessible. Tested with qemu-aarch64 user mode emulation. --- HippoMocks/hippomocks.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/HippoMocks/hippomocks.h b/HippoMocks/hippomocks.h index 386aa0c..b3870ca 100644 --- a/HippoMocks/hippomocks.h +++ b/HippoMocks/hippomocks.h @@ -93,7 +93,7 @@ extern "C" __declspec(dllimport) void WINCALL DebugBreak(); #define SOME_ARM #endif -#if defined(__x86_64__) || defined(_M_X64) +#if defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) #define CMOCK_FUNC_PLATFORMIS64BIT #endif @@ -307,6 +307,12 @@ class Replace Unprotect _allow_write(origFunc, sizeof(backupData)); memcpy(backupData, origFunc, sizeof(backupData)); +#ifdef CMOCK_FUNC_PLATFORMIS64BIT + unsigned int *rawptr = (unsigned int *)origFunc; + rawptr[0] = 0x58000051; + rawptr[1] = 0xD61F0220; + *(long long*)(horrible_cast(origFunc) + 8) = (long long)(horrible_cast(replacement)); +#else unsigned int *rawptr = (unsigned int *)((intptr_t)(origFunc) & (~3)); if ((intptr_t)origFunc & 1) { rawptr[0] = 0x6800A001; @@ -317,6 +323,8 @@ class Replace rawptr[1] = (intptr_t)replacement; rawptr[2] = (intptr_t)replacement; } +#endif + __clear_cache((char *)rawptr, (char *)rawptr+16); #endif }