Skip to content

Commit 8522bd6

Browse files
committed
Add MacOS Arm64.
1 parent c36630c commit 8522bd6

File tree

3 files changed

+95
-7
lines changed

3 files changed

+95
-7
lines changed

.github/workflows/build.yml

+22-3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ jobs:
4141
output: libRemoteInput.dylib
4242
release: libRemoteInput-x86_64.dylib
4343

44+
#MacOS-aarch64
45+
- os: macos-latest
46+
name: MacOS-aarch64
47+
other_linker_flags: '-m64'
48+
arch: aarch64
49+
output: libRemoteInput.dylib
50+
release: libRemoteInput-aarch64.dylib
51+
4452
#Windows-32
4553
- os: windows-latest
4654
name: Windows-32
@@ -136,6 +144,17 @@ jobs:
136144
if: matrix.config.name == 'MacOS-64'
137145
run: |
138146
cmake --build '${{ github.workspace }}/cmake-build-release' --target all -- -j 4
147+
148+
#MacOS-aarch64
149+
- name: CMake Generate Build Files - MacOS-aarch64
150+
if: matrix.config.name == 'MacOS-aarch64'
151+
run: |
152+
cmake -S '${{ github.workspace }}' -B '${{ github.workspace }}/cmake-build-release' -DCMAKE_BUILD_TYPE=Release -DOTHER_LINKER_FLAGS:STRING=${{ matrix.config.other_linker_flags }} -G "CodeBlocks - Unix Makefiles"
153+
154+
- name: Build - MacOS-aarch64
155+
if: matrix.config.name == 'MacOS-aarch64'
156+
run: |
157+
cmake --build '${{ github.workspace }}/cmake-build-release' --target all -- -j 4
139158
140159
#Windows-32
141160
- name: Dependencies - Windows-32
@@ -216,9 +235,9 @@ jobs:
216235
uses: Brandon-T/wait-for-check-action@v1
217236
with:
218237
github_token: ${{ secrets.GITHUB_TOKEN }}
219-
check_names: '["Linux-aarch64", "Linux-64", "MacOS-64", "Windows-32", "Windows-64"]'
220-
statuses: '["completed", "completed", "completed", "completed", "completed"]'
221-
conclusions: '["success", "success", "success", "success", "success"]'
238+
check_names: '["Linux-aarch64", "Linux-64", "MacOS-64", "MacOS-aarch64", "Windows-32", "Windows-64"]'
239+
statuses: '["completed", "completed", "completed", "completed", "completed", "completed"]'
240+
conclusions: '["success", "success", "success", "success", "success", "success"]'
222241
timeout: 600
223242
poll_interval: 10
224243

RemoteInput/Thirdparty/Hook.cxx

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Hook::Hook(void* original, void* detour) : original(original), detour(detour), t
5858
{
5959
std::memset(&data[0], 0, sizeof(data));
6060

61-
#if defined (__x86_64__)
61+
#if defined (__x86_64__) || defined(__arm64__)
6262
mach_vm_size_t size_of_jump = (sizeof(uintptr_t) * 2);
6363
#else
6464
mach_vm_size_t size_of_jump = (sizeof(int) + 1);

RemoteInput/Thirdparty/rd_route/src/rd_route.c

+72-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include <dlfcn.h> // dladdr()
1212

1313
#include "TargetConditionals.h"
14-
#if defined(__i386__) || defined(__x86_64__)
14+
#if defined(__i386__) || defined(__x86_64__) || defined(__arm64__)
1515
#if !(TARGET_IPHONE_SIMULATOR)
1616
#include <mach/mach_vm.h> // mach_vm_*
1717
#else
@@ -38,7 +38,7 @@
3838
#define RDErrorLog(format, ...) fprintf(stderr, "%s:%d:\n\terror: "format"\n", \
3939
__FILE__, __LINE__, ##__VA_ARGS__)
4040

41-
#if defined(__x86_64__)
41+
#if defined(__x86_64__) || defined(__arm64__)
4242
typedef struct mach_header_64 mach_header_t;
4343
typedef struct segment_command_64 segment_command_t;
4444
#define LC_SEGMENT_ARCH_INDEPENDENT LC_SEGMENT_64
@@ -288,7 +288,7 @@ static mach_vm_size_t _image_size(void *image, mach_vm_size_t image_slide, mach_
288288
return (image_end - image_addr);
289289
}
290290

291-
291+
#if defined(__x86_64__) || defined(__i386__)
292292
static kern_return_t _insert_jmp(void* where, void* to)
293293
{
294294
assert(where);
@@ -320,6 +320,75 @@ static kern_return_t _insert_jmp(void* where, void* to)
320320

321321
return (err);
322322
}
323+
#elif defined(__arm64__)
324+
#include <sys/mman.h>
325+
326+
// Function to create an executable trampoline pointing to the target address
327+
static void* create_trampoline(void* to) {
328+
assert(to);
329+
330+
// Allocate an executable memory page
331+
void* trampoline = mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE | MAP_JIT, -1, 0);
332+
if (trampoline == MAP_FAILED) {
333+
perror("mmap");
334+
return NULL;
335+
}
336+
337+
// ARM64 absolute jump sequence:
338+
// - Load 64-bit address into x16
339+
// - Branch to x16
340+
uint32_t trampoline_code[] = {
341+
0x58000050, // LDR x16, #8 (load address of target function into x16)
342+
0xD61F0200, // BR x16 (branch to address in x16)
343+
(uint32_t)((uintptr_t)to), // Address of the target function (low 32 bits)
344+
(uint32_t)((uintptr_t)to >> 32) // Address of the target function (high 32 bits)
345+
};
346+
347+
// Copy the code into the trampoline
348+
memcpy(trampoline, trampoline_code, sizeof(trampoline_code));
349+
350+
// Make the trampoline read-execute only
351+
if (mprotect(trampoline, 4096, PROT_READ | PROT_EXEC) != 0) {
352+
perror("mprotect");
353+
munmap(trampoline, 4096);
354+
return NULL;
355+
}
356+
357+
return trampoline;
358+
}
359+
360+
static kern_return_t _insert_jmp(void* where, void* to)
361+
{
362+
// ARM64 branch (B) instruction format: 4 bytes with a 26-bit signed offset
363+
uint32_t* patch_location = (uint32_t*)where;
364+
int64_t offset = (int64_t)to - (int64_t)where;
365+
366+
// Check if the offset is within ARM64 branch limits (+/-128MB)
367+
/*if (offset < -33554432 || offset > 33554428) {
368+
// Target address is out of range, create a trampoline
369+
void* trampoline = create_trampoline(to);
370+
if (!trampoline) {
371+
fprintf(stderr, "Failed to create trampoline\n");
372+
return KERN_FAILURE;
373+
}
374+
375+
// Update `to` to point to the trampoline
376+
to = trampoline;
377+
offset = (int64_t)to - (int64_t)where;
378+
}*/
379+
380+
// Calculate the signed 26-bit offset (in words) and encode in a branch instruction
381+
uint32_t branch_instruction = 0x14000000 | ((offset >> 2) & 0x03FFFFFF);
382+
383+
kern_return_t err = _patch_memory(patch_location, sizeof(branch_instruction), (uint8_t*)&branch_instruction);
384+
if (err != KERN_SUCCESS) {
385+
fprintf(stderr, "_patch_memory failed with error 0x%x\n", err);
386+
}
387+
return err;
388+
}
389+
#else
390+
#error rd_route doesn't work on iOS
391+
#endif
323392

324393

325394
static kern_return_t _patch_memory(void *address, mach_msg_type_number_t count, uint8_t *new_bytes)

0 commit comments

Comments
 (0)