aboutsummaryrefslogtreecommitdiff
path: root/lib/hook-functions.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hook-functions.c')
-rw-r--r--lib/hook-functions.c58
1 files changed, 29 insertions, 29 deletions
diff --git a/lib/hook-functions.c b/lib/hook-functions.c
index 953683b..7db06d4 100644
--- a/lib/hook-functions.c
+++ b/lib/hook-functions.c
@@ -77,6 +77,8 @@ static int check_intro_trampoline(void **trampoline_ptr_p,
if (*patch_size_p != -1)
return SUBSTITUTE_OK;
+ *need_intro_trampoline_p = true;
+
/* Try existing trampoline */
*patch_size_p = jump_patch_size(pc, (uintptr_t) trampoline_ptr, arch, false);
@@ -122,8 +124,7 @@ skip_after:;
EXPORT
int substitute_hook_functions(const struct substitute_function_hook *hooks,
- size_t nhooks,
- int options) {
+ size_t nhooks, int options) {
struct hook_internal *his = malloc(nhooks * sizeof(*his));
if (!his)
return SUBSTITUTE_ERR_OOM;
@@ -169,20 +170,6 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks,
goto end;
uint_tptr pc_patch_end = pc_patch_start + patch_size;
- /* Generate the rewritten start of the function for the outro
- * trampoline (complaining if any bad instructions are found)
- * (on arm64, this modifies regs_possibly_written, which is used by the
- * two make_jump_patch calls) */
- uint8_t rewritten_temp[TD_MAX_REWRITTEN_SIZE];
- void *rp = rewritten_temp;
- if ((ret = transform_dis_main(code, &rp, pc_patch_start, &pc_patch_end,
- &arch, hi->offset_by_pcdiff)))
- goto end;
- /* Check some of the rest of the function for jumps back into the
- * patched region. */
- if ((ret = jump_dis_main(code, pc_patch_start, pc_patch_end, arch)))
- goto end;
-
uintptr_t initial_target;
if (need_intro_trampoline) {
initial_target = (uintptr_t) trampoline_ptr;
@@ -191,26 +178,26 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks,
} else {
initial_target = (uintptr_t) hook->replacement;
}
+
+ /* Make the real jump patch for the target function. */
void *jp = hi->jump_patch;
make_jump_patch(&jp, pc_patch_start, initial_target, arch);
hi->jump_patch_size = (uint8_t *) jp - hi->jump_patch;
+ size_t align_bytes = (-(uintptr_t) trampoline_ptr)
+ & (arch_code_alignment(arch) - 1);
+ size_t outro_est = align_bytes +
+ TD_MAX_REWRITTEN_SIZE + MAX_JUMP_PATCH_SIZE;
- size_t rewritten_size = (uint8_t *) rp - rewritten_temp;
- size_t jumpback_size =
- jump_patch_size((uintptr_t) trampoline_ptr + rewritten_size,
- pc_patch_end, arch, /* force */ true);
- size_t outro_size = rewritten_size + jumpback_size;
- if (outro_size > trampoline_size_left) {
+ if (outro_est > trampoline_size_left) {
/* Not enough space left in our existing block... */
if ((ret = execmem_alloc_unsealed(0, &trampoline_ptr,
&trampoline_size_left)))
goto end;
hi->trampoline_page = trampoline_ptr;
- jumpback_size =
- jump_patch_size((uintptr_t) trampoline_ptr + rewritten_size,
- pc_patch_end, arch, /* force */ true);
- outro_size = rewritten_size + jumpback_size;
+ } else {
+ trampoline_ptr += align_bytes;
+ trampoline_size_left -= align_bytes;
}
hi->outro_trampoline = trampoline_ptr;
@@ -221,10 +208,23 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks,
dpc++;
}
#endif
- memcpy(trampoline_ptr, rewritten_temp, rewritten_size);
- trampoline_ptr += rewritten_size;
+ /* Generate the rewritten start of the function for the outro
+ * trampoline (complaining if any bad instructions are found)
+ * (on arm64, this modifies regs_possibly_written, which is used by the
+ * ending make_jump_patch call) */
+ if ((ret = transform_dis_main(code, &trampoline_ptr, pc_patch_start,
+ &pc_patch_end, (uintptr_t) trampoline_ptr,
+ &arch, hi->offset_by_pcdiff)))
+ goto end;
+ /* Now that transform_dis_main has given us the final pc_patch_end,
+ * check some of the rest of the function for jumps back into the
+ * patched region. */
+ if ((ret = jump_dis_main(code, pc_patch_start, pc_patch_end, arch)))
+ goto end;
+ /* Okay, continue with the outro. */
make_jump_patch(&trampoline_ptr, (uintptr_t) trampoline_ptr, dpc, arch);
- trampoline_size_left -= outro_size;
+ trampoline_size_left -= (uint8_t *) trampoline_ptr
+ - (uint8_t *) hi->outro_trampoline;
}
/* Now commit. */