ZZSTATUS ZzBuildHalfTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { zbyte temp_code_slice_data[256] = {0}; ZzArm64Writer *arm64_writer = NULL; ZzCodeSlice *code_slice = NULL; ZzArm64HookFunctionEntryBackend *entry_backend = (ZzArm64HookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zaddr target_addr = (zaddr)entry->target_ptr; arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); /* prepare 2 stack space: 1. next_hop 2. entry arg */ zz_arm64_writer_put_sub_reg_reg_imm(arm64_writer, ZZ_ARM64_REG_SP, ZZ_ARM64_REG_SP, 2 * 0x8); zz_arm64_writer_put_ldr_b_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)entry); zz_arm64_writer_put_str_reg_reg_offset(arm64_writer, ZZ_ARM64_REG_X17, ZZ_ARM64_REG_SP, 0x0); /* jump to half thunk */ zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)self->half_thunk); /* code patch */ code_slice = zz_code_patch_arm64_writer(arm64_writer, self->allocator, 0, 0); if (code_slice) entry->on_half_trampoline = code_slice->data; else return ZZ_FAILED; return status; }
ZZSTATUS ZzBuildEnterTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { zbyte temp_code_slice_data[256] = {0}; ZzArm64Writer *arm64_writer = NULL; ZzCodeSlice *code_slice = NULL; ZzArm64HookFunctionEntryBackend *entry_backend = (ZzArm64HookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zaddr target_addr = (zaddr)entry->target_ptr; arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); /* prepare 2 stack space: 1. next_hop 2. entry arg */ zz_arm64_writer_put_sub_reg_reg_imm(arm64_writer, ZZ_ARM64_REG_SP, ZZ_ARM64_REG_SP, 2 * 0x8); zz_arm64_writer_put_ldr_b_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)entry); zz_arm64_writer_put_str_reg_reg_offset(arm64_writer, ZZ_ARM64_REG_X17, ZZ_ARM64_REG_SP, 0x0); /* jump to enter thunk */ zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)self->enter_thunk); /* code patch */ code_slice = zz_code_patch_arm64_writer(arm64_writer, self->allocator, 0, 0); if (code_slice) entry->on_enter_trampoline = code_slice->data; else return ZZ_FAILED; /* debug log */ if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzBuildEnterTrampoline:"); sprintf(buffer + strlen(buffer), "LogInfo: on_enter_trampoline at %p, length: %ld. hook-entry: %p. and will jump to enter_thunk(%p).\n", code_slice->data, code_slice->size, (void *)entry, (void *)self->enter_thunk); ZzInfoLog("%s", buffer); } if (entry_backend->redirect_code_size == ZZ_ARM64_TINY_REDIRECT_SIZE) { ZzBuildEnterTransferTrampoline(self, entry); } free(code_slice); return status; }
void zz_arm64_thunker_build_half_thunk(ZzWriter *writer) { /* save general registers and sp */ zz_arm64_writer_put_bytes(writer, (void *)ctx_save, 23 * 4); zz_arm64_writer_put_add_reg_reg_imm(writer, ZZ_ARM64_REG_X1, ZZ_ARM64_REG_SP, 8 + CTX_SAVE_STACK_OFFSET + 2 * 8); /* trick: use the `ctx_save` left [sp]*/ zz_arm64_writer_put_str_reg_reg_offset(writer, ZZ_ARM64_REG_X1, ZZ_ARM64_REG_SP, 0 * 8); /* alignment padding + dummy PC */ zz_arm64_writer_put_sub_reg_reg_imm(writer, ZZ_ARM64_REG_SP, ZZ_ARM64_REG_SP, 2 * 8); /* pass enter func args */ /* entry */ zz_arm64_writer_put_ldr_reg_reg_offset(writer, ZZ_ARM64_REG_X0, ZZ_ARM64_REG_SP, 2 * 8 + 8 + CTX_SAVE_STACK_OFFSET); /* next hop*/ zz_arm64_writer_put_add_reg_reg_imm(writer, ZZ_ARM64_REG_X1, ZZ_ARM64_REG_SP, 2 * 8 + 8 + CTX_SAVE_STACK_OFFSET + 0x8); /* RegState */ zz_arm64_writer_put_add_reg_reg_imm(writer, ZZ_ARM64_REG_X2, ZZ_ARM64_REG_SP, 2 * 8); /* caller ret address */ zz_arm64_writer_put_add_reg_reg_imm(writer, ZZ_ARM64_REG_X3, ZZ_ARM64_REG_SP, 2 * 8 + 2 * 8 + 28 * 8 + 8); /* call function_context_half_invocation */ zz_arm64_writer_put_ldr_blr_b_reg_address(writer, ZZ_ARM64_REG_X17, (zz_addr_t)function_context_half_invocation); /* alignment padding + dummy PC */ zz_arm64_writer_put_add_reg_reg_imm(writer, ZZ_ARM64_REG_SP, ZZ_ARM64_REG_SP, 2 * 8); /* restore general registers stack */ zz_arm64_writer_put_bytes(writer, (void *)ctx_restore, 21 * 4); /* load next hop to x17 */ zz_arm64_writer_put_ldr_reg_reg_offset(writer, ZZ_ARM64_REG_X17, ZZ_ARM64_REG_SP, 0x8); /* restore next hop and arg stack */ zz_arm64_writer_put_add_reg_reg_imm(writer, ZZ_ARM64_REG_SP, ZZ_ARM64_REG_SP, 2 * 8); /* jump to next hop */ zz_arm64_writer_put_br_reg(writer, ZZ_ARM64_REG_X17); }