move platform specific into arm file
This commit is contained in:
parent
ccaa4bfbf0
commit
db603acded
3 changed files with 193 additions and 156 deletions
|
|
@ -305,55 +305,9 @@ static void internal_detour_free_unused_trampoline_regions()
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Trampoline Helpers
|
||||
|
||||
static uint8_t internal_detour_align_from_trampoline(const detour_trampoline* trampoline,
|
||||
const uint8_t offset_trampoline)
|
||||
{
|
||||
for (int32_t n = 0; n < ARRAYSIZE(trampoline->align); n++) {
|
||||
if (trampoline->align[n].offset_trampoline == offset_trampoline) {
|
||||
return trampoline->align[n].offset_target;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t internal_detour_align_from_target(const detour_trampoline* trampoline, const uint8_t offset_target)
|
||||
{
|
||||
for (int32_t n = 0; n < ARRAYSIZE(trampoline->align); n++) {
|
||||
if (trampoline->align[n].offset_target == offset_target) {
|
||||
return trampoline->align[n].offset_trampoline;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Transactions
|
||||
|
||||
typedef enum detour_operation_kind
|
||||
{
|
||||
detour_operation_kind_attach,
|
||||
detour_operation_kind_detach,
|
||||
} detour_operation_kind;
|
||||
|
||||
typedef struct detour_operation
|
||||
{
|
||||
struct detour_operation* next;
|
||||
detour_operation_kind kind;
|
||||
uint8_t** pointer;
|
||||
uint8_t* target;
|
||||
detour_trampoline* trampoline;
|
||||
vm_prot_t perm;
|
||||
} detour_operation;
|
||||
|
||||
typedef struct detour_pending_thread
|
||||
{
|
||||
struct detour_pending_thread* next;
|
||||
thread_t thread;
|
||||
} detour_pending_thread;
|
||||
|
||||
static bool s_ignore_too_small = false;
|
||||
static bool s_retain_regions = false;
|
||||
|
||||
|
|
@ -450,100 +404,60 @@ mach_error_t detour_transaction_commit_ex(detour_func_t** out_failed_target)
|
|||
|
||||
// Insert or remove each of the detours.
|
||||
for (detour_operation* operation = s_pending_operations_head; operation != nullptr; operation = operation->next) {
|
||||
if (operation->kind == detour_operation_kind_detach) {
|
||||
memcpy(operation->target, operation->trampoline->restore_code, operation->trampoline->restore_code_size);
|
||||
#ifdef DETOURS_ARM64
|
||||
*operation->pointer = operation->target;
|
||||
#endif
|
||||
} else {
|
||||
DETOUR_TRACE(("detours: trampoline=%p, ptr_remain=%p, ptr_detour=%p, restore_code_size=%u\n",
|
||||
operation->trampoline,
|
||||
operation->trampoline->ptr_remain,
|
||||
operation->trampoline->ptr_detour,
|
||||
operation->trampoline->restore_code_size));
|
||||
switch (operation->kind) {
|
||||
case detour_operation_kind_attach: {
|
||||
DETOUR_TRACE(("detours: trampoline=%p, ptr_remain=%p, ptr_detour=%p, restore_code_size=%u\n",
|
||||
operation->trampoline,
|
||||
operation->trampoline->ptr_remain,
|
||||
operation->trampoline->ptr_detour,
|
||||
operation->trampoline->restore_code_size));
|
||||
|
||||
DETOUR_TRACE(("detours: target=%p: "
|
||||
"%02x %02x %02x %02x "
|
||||
"%02x %02x %02x %02x "
|
||||
"%02x %02x %02x %02x [before]\n",
|
||||
operation->target,
|
||||
operation->target[0], operation->target[1], operation->target[2], operation->target[3],
|
||||
operation->target[4], operation->target[5], operation->target[6], operation->target[7],
|
||||
operation->target[8], operation->target[9], operation->target[10], operation->target[11]));
|
||||
DETOUR_TRACE(("detours: target=%p: "
|
||||
"%02x %02x %02x %02x "
|
||||
"%02x %02x %02x %02x "
|
||||
"%02x %02x %02x %02x [before]\n",
|
||||
operation->target,
|
||||
operation->target[0], operation->target[1], operation->target[2], operation->target[3],
|
||||
operation->target[4], operation->target[5], operation->target[6], operation->target[7],
|
||||
operation->target[8], operation->target[9], operation->target[10], operation->target[11]));
|
||||
|
||||
#ifdef DETOURS_ARM64
|
||||
uint8_t* code = internal_detour_gen_jmp_indirect(operation->target,
|
||||
(uint64_t*)&(operation->trampoline->ptr_detour));
|
||||
code = internal_detour_gen_brk(code, operation->trampoline->ptr_remain);
|
||||
UNUSED_VARIABLE(code);
|
||||
*operation->pointer = operation->trampoline->code;
|
||||
#endif // DETOURS_ARM64
|
||||
internal_detour_operation_commit_detour(operation);
|
||||
*operation->pointer = internal_detour_operation_get_trampoline_ptr(operation)
|
||||
|
||||
DETOUR_TRACE(("detours: target=%p: "
|
||||
"%02x %02x %02x %02x "
|
||||
"%02x %02x %02x %02x "
|
||||
"%02x %02x %02x %02x [after]\n",
|
||||
operation->target,
|
||||
operation->target[0], operation->target[1], operation->target[2], operation->target[3],
|
||||
operation->target[4], operation->target[5], operation->target[6], operation->target[7],
|
||||
operation->target[8], operation->target[9], operation->target[10], operation->target[11]));
|
||||
DETOUR_TRACE(("detours: target=%p: "
|
||||
"%02x %02x %02x %02x "
|
||||
"%02x %02x %02x %02x "
|
||||
"%02x %02x %02x %02x [after]\n",
|
||||
operation->target,
|
||||
operation->target[0], operation->target[1], operation->target[2], operation->target[3],
|
||||
operation->target[4], operation->target[5], operation->target[6], operation->target[7],
|
||||
operation->target[8], operation->target[9], operation->target[10], operation->target[11]));
|
||||
|
||||
DETOUR_TRACE(("detours: trampoline=%p: "
|
||||
"%02x %02x %02x %02x "
|
||||
"%02x %02x %02x %02x "
|
||||
"%02x %02x %02x %02x\n",
|
||||
operation->trampoline,
|
||||
operation->trampoline->code[0], operation->trampoline->code[1],
|
||||
operation->trampoline->code[2], operation->trampoline->code[3],
|
||||
operation->trampoline->code[4], operation->trampoline->code[5],
|
||||
operation->trampoline->code[6], operation->trampoline->code[7],
|
||||
operation->trampoline->code[8], operation->trampoline->code[9],
|
||||
operation->trampoline->code[10], operation->trampoline->code[11]));
|
||||
DETOUR_TRACE(("detours: trampoline=%p: "
|
||||
"%02x %02x %02x %02x "
|
||||
"%02x %02x %02x %02x "
|
||||
"%02x %02x %02x %02x\n",
|
||||
operation->trampoline,
|
||||
operation->trampoline->code[0], operation->trampoline->code[1],
|
||||
operation->trampoline->code[2], operation->trampoline->code[3],
|
||||
operation->trampoline->code[4], operation->trampoline->code[5],
|
||||
operation->trampoline->code[6], operation->trampoline->code[7],
|
||||
operation->trampoline->code[8], operation->trampoline->code[9],
|
||||
operation->trampoline->code[10], operation->trampoline->code[11]));
|
||||
break;
|
||||
}
|
||||
case detour_operation_kind_detach: {
|
||||
memcpy(operation->target, operation->trampoline->restore_code,
|
||||
operation->trampoline->restore_code_size);
|
||||
*operation->pointer = internal_detour_operation_get_target_ptr(operation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update any suspended threads.
|
||||
for (detour_pending_thread* thread = s_pending_threads_head; thread != nullptr; thread = thread->next) {
|
||||
arm_thread_state64_t threadState;
|
||||
mach_msg_type_number_t threadStateCnt = ARM_THREAD_STATE64_COUNT;
|
||||
const kern_return_t error = thread_get_state(thread->thread, ARM_THREAD_STATE64, (thread_state_t)&threadState,
|
||||
&threadStateCnt);
|
||||
if (error != err_none) {
|
||||
DETOUR_BREAK();
|
||||
continue;
|
||||
}
|
||||
const uintptr_t pc = arm_thread_state64_get_pc(threadState);
|
||||
|
||||
for (detour_operation* op = s_pending_operations_head; op != nullptr; op = op->next) {
|
||||
switch (op->kind) {
|
||||
case detour_operation_kind_attach: {
|
||||
const uintptr_t targetAddr = (uintptr_t)op->target;
|
||||
if (pc >= targetAddr && pc < targetAddr + op->trampoline->restore_code_size) {
|
||||
uintptr_t new_pc = (uintptr_t)op->trampoline;
|
||||
new_pc += internal_detour_align_from_target(op->trampoline, pc - targetAddr);
|
||||
DETOUR_TRACE(("detours: thread %u was at 0x%" PRIXPTR ", moved to 0x%" PRIXPTR "\n",
|
||||
thread->thread, pc, new_pc));
|
||||
arm_thread_state64_set_pc_fptr(threadState, new_pc);
|
||||
thread_set_state(thread->thread, ARM_THREAD_STATE64, (thread_state_t)&threadState,
|
||||
ARM_THREAD_STATE64_COUNT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case detour_operation_kind_detach: {
|
||||
const uintptr_t trampAddr = (uintptr_t)op->trampoline;
|
||||
if (pc >= trampAddr && pc < trampAddr + sizeof(*op->trampoline)) {
|
||||
uintptr_t new_pc = (uintptr_t)op->target;
|
||||
new_pc += internal_detour_align_from_trampoline(op->trampoline, pc - trampAddr);
|
||||
DETOUR_TRACE(("detours: thread %u was at 0x%" PRIXPTR ", moved to 0x%" PRIXPTR "\n",
|
||||
thread->thread, pc, new_pc));
|
||||
arm_thread_state64_set_pc_fptr(threadState, new_pc);
|
||||
thread_set_state(thread->thread, ARM_THREAD_STATE64, (thread_state_t)&threadState,
|
||||
ARM_THREAD_STATE64_COUNT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
internal_detour_update_thread_on_commit(thread, s_pending_operations_head);
|
||||
}
|
||||
|
||||
// Restore all the page permissions
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue