diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/arm/arch-transform-dis.inc.h | 6 | ||||
-rw-r--r-- | lib/arm/assemble.h | 3 | ||||
-rw-r--r-- | lib/arm/dis-thumb2.inc.h | 2 | ||||
-rw-r--r-- | lib/arm/jump-patch.h | 13 | ||||
-rw-r--r-- | lib/arm64/assemble.h | 2 | ||||
-rw-r--r-- | lib/arm64/jump-patch.h | 5 | ||||
-rw-r--r-- | lib/cbit/vec.c | 6 | ||||
-rw-r--r-- | lib/cbit/vec.h | 4 | ||||
-rw-r--r-- | lib/hook-functions.c | 17 | ||||
-rw-r--r-- | lib/jump-dis.c | 1 | ||||
-rw-r--r-- | lib/x86/arch-transform-dis.inc.h | 2 | ||||
-rw-r--r-- | lib/x86/jump-patch.h | 1 |
12 files changed, 39 insertions, 23 deletions
diff --git a/lib/arm/arch-transform-dis.inc.h b/lib/arm/arch-transform-dis.inc.h index 8569300..4c44913 100644 --- a/lib/arm/arch-transform-dis.inc.h +++ b/lib/arm/arch-transform-dis.inc.h @@ -12,6 +12,7 @@ static struct assemble_ctx tdctx_to_actx(const struct transform_dis_ctx *ctx) { } return (struct assemble_ctx) { ctx->rewritten_ptr_ptr, + (uint_tptr) (uintptr_t) ctx->rewritten_ptr_ptr, ctx->arch.pc_low_bit, cond }; @@ -121,7 +122,7 @@ void transform_dis_data(struct transform_dis_ctx *ctx, unsigned o0, unsigned o1, } static NOINLINE UNUSED -void transform_dis_pcrel(struct transform_dis_ctx *ctx, uintptr_t dpc, +void transform_dis_pcrel(struct transform_dis_ctx *ctx, uint_tptr dpc, struct arch_pcrel_info info) { #ifdef TRANSFORM_DIS_VERBOSE printf("transform_dis_pcrel: (0x%llx) dpc=0x%llx reg=%x mode=%d\n", @@ -149,7 +150,7 @@ void transform_dis_pcrel(struct transform_dis_ctx *ctx, uintptr_t dpc, } static NOINLINE UNUSED -void transform_dis_branch(struct transform_dis_ctx *ctx, uintptr_t dpc, int cc) { +void transform_dis_branch(struct transform_dis_ctx *ctx, uint_tptr dpc, int cc) { #ifdef TRANSFORM_DIS_VERBOSE printf("transform_dis (0x%llx): branch => 0x%llx\n", (unsigned long long) ctx->base.pc, @@ -192,6 +193,7 @@ static void transform_dis_pre_dis(struct transform_dis_ctx *ctx) { static void transform_dis_post_dis(struct transform_dis_ctx *ctx) { if (ctx->arch.bccrel_p) { struct assemble_ctx actx = {&ctx->arch.bccrel_p, + (uint_tptr) (uintptr_t) ctx->arch.bccrel_p, /*thumb*/ true, ctx->arch.bccrel_bits}; Bccrel(actx, *ctx->rewritten_ptr_ptr - ctx->arch.bccrel_p); diff --git a/lib/arm/assemble.h b/lib/arm/assemble.h index c0af020..2303a7a 100644 --- a/lib/arm/assemble.h +++ b/lib/arm/assemble.h @@ -3,6 +3,7 @@ struct assemble_ctx { void **codep; + uint_tptr pc; bool thumb; int cond; }; @@ -100,6 +101,8 @@ static inline void Bccrel(struct assemble_ctx ctx, int offset) { } static inline void LDR_PC(struct assemble_ctx ctx, uint32_t dpc) { + if (ctx.pc & 2) + op16(ctx.codep, 0xbf00); if (ctx.thumb) op32(ctx.codep, 0xf000f8df); else diff --git a/lib/arm/dis-thumb2.inc.h b/lib/arm/dis-thumb2.inc.h index 0a4c12c..b8082f3 100644 --- a/lib/arm/dis-thumb2.inc.h +++ b/lib/arm/dis-thumb2.inc.h @@ -197,7 +197,7 @@ static INLINE void P(thumb2_do_it)(tdis_ctx ctx) { static INLINE void P(dis_thumb2)(tdis_ctx ctx) { ctx->base.op = unaligned_r32(ctx->base.ptr); - ctx->base.op_size = ctx->base.newop_size = 2; + ctx->base.op_size = ctx->base.newop_size = 4; /* LLVM likes to think about Thumb2 instructions the way the ARM manual * does - 15..0 15..0 rather than 31..0 as actually laid out in memory... */ ctx->base.op = flip16(ctx->base.op); diff --git a/lib/arm/jump-patch.h b/lib/arm/jump-patch.h index b65a97d..8787070 100644 --- a/lib/arm/jump-patch.h +++ b/lib/arm/jump-patch.h @@ -2,17 +2,18 @@ #include "dis.h" #include "arm/assemble.h" #define MAX_JUMP_PATCH_SIZE 8 +#define MAX_EXTENDED_PATCH_SIZE (MAX_JUMP_PATCH_SIZE+14) -static inline int jump_patch_size(UNUSED uintptr_t pc, - UNUSED uintptr_t dpc, +static inline int jump_patch_size(uint_tptr pc, + UNUSED uint_tptr dpc, UNUSED struct arch_dis_ctx arch, UNUSED bool force) { - return 8; + return (pc & 2) ? 10 : 8; } -static inline void make_jump_patch(void **codep, UNUSED uintptr_t pc, - uintptr_t dpc, +static inline void make_jump_patch(void **codep, uint_tptr pc, + uint_tptr dpc, struct arch_dis_ctx arch) { - struct assemble_ctx actx = {codep, arch.pc_low_bit, 0xe}; + struct assemble_ctx actx = {codep, pc, arch.pc_low_bit, 0xe}; LDR_PC(actx, dpc); } diff --git a/lib/arm64/assemble.h b/lib/arm64/assemble.h index 42c0f0c..c4fb487 100644 --- a/lib/arm64/assemble.h +++ b/lib/arm64/assemble.h @@ -46,7 +46,7 @@ static inline void LDRxi(void **codep, int Rt, int Rn, uint32_t off, } static inline void ADRP_ADD(void **codep, int reg, uint64_t pc, uint64_t dpc) { - uintptr_t diff = (dpc & ~0xfff) - (pc & ~0xfff); + uint64_t diff = (dpc & ~0xfff) - (pc & ~0xfff); /* ADRP reg, dpc */ op32(codep, 0x90000000 | reg | (diff & 0x3000) << 17 | (diff & 0x1ffffc000) >> 9); uint32_t lo = dpc & 0xfff; diff --git a/lib/arm64/jump-patch.h b/lib/arm64/jump-patch.h index 5a44174..fe36d14 100644 --- a/lib/arm64/jump-patch.h +++ b/lib/arm64/jump-patch.h @@ -1,8 +1,9 @@ #pragma once #include "arm64/assemble.h" #define MAX_JUMP_PATCH_SIZE 20 +#define MAX_EXTENDED_PATCH_SIZE MAX_JUMP_PATCH_SIZE -static inline int jump_patch_size(uintptr_t pc, uintptr_t dpc, +static inline int jump_patch_size(uint_tptr pc, uint_tptr dpc, UNUSED struct arch_dis_ctx arch, bool force) { intptr_t diff = (dpc & ~0xfff) - (pc & ~0xfff); @@ -14,7 +15,7 @@ static inline int jump_patch_size(uintptr_t pc, uintptr_t dpc, return 12; } -static inline void make_jump_patch(void **codep, uintptr_t pc, uintptr_t dpc, +static inline void make_jump_patch(void **codep, uint_tptr pc, uint_tptr dpc, struct arch_dis_ctx arch) { int reg = arm64_get_unwritten_temp_reg(&arch); intptr_t diff = (dpc & ~0xfff) - (pc & ~0xfff); diff --git a/lib/cbit/vec.c b/lib/cbit/vec.c index 21038a2..2f875ff 100644 --- a/lib/cbit/vec.c +++ b/lib/cbit/vec.c @@ -1,12 +1,16 @@ #include "cbit/vec.h" #include <stdio.h> +#include <stdlib.h> void vec_realloc_internal(struct vec_internal *vi, size_t new_capacity, size_t esize) { + if (new_capacity == 0) + abort(); size_t new_size = safe_mul(new_capacity, esize); if (vi->els == vi->storage) { void *new = malloc(new_size); - memcpy(new, vi->els, vi->capacity * esize); + size_t min_cap = new_capacity < vi->capacity ? new_capacity : vi->capacity; + memcpy(new, vi->els, min_cap * esize); vi->els = new; } else { vi->els = realloc(vi->els, new_size); diff --git a/lib/cbit/vec.h b/lib/cbit/vec.h index 2889ac1..eddee6a 100644 --- a/lib/cbit/vec.h +++ b/lib/cbit/vec.h @@ -73,8 +73,8 @@ void vec_realloc_internal_as_necessary(struct vec_internal *vi, VEC_TY(name) vec_pop_##name(struct vec_##name *v) { \ size_t i = v->length - 1; \ VEC_TY(name) ret = v->els[i]; \ - if (i - 1 < v->capacity / 3) \ - vec_realloc_internal_as_necessary(&v->vi, i - 1, sizeof(v->els[0])); \ + if (v->els != v->storage && i < v->capacity / 3) \ + vec_realloc_internal_as_necessary(&v->vi, i, sizeof(v->els[0])); \ v->length = i; \ return ret; \ } \ diff --git a/lib/hook-functions.c b/lib/hook-functions.c index 2a8d618..673d6d9 100644 --- a/lib/hook-functions.c +++ b/lib/hook-functions.c @@ -8,7 +8,7 @@ #include <pthread.h> struct hook_internal { - int offset_by_pcdiff[MAX_JUMP_PATCH_SIZE + 1]; + int offset_by_pcdiff[MAX_EXTENDED_PATCH_SIZE + 1]; uint8_t jump_patch[MAX_JUMP_PATCH_SIZE]; size_t jump_patch_size; void *code; @@ -139,7 +139,7 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks, struct execmem_foreign_write *fws; struct hook_internal *his = malloc(nhooks * sizeof(*his) + - nhooks + sizeof(*fws)); + nhooks * sizeof(*fws)); if (!his) return SUBSTITUTE_ERR_OOM; fws = (void *) (his + nhooks); @@ -202,7 +202,12 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks, hi->trampoline_page = trampoline_ptr; } - hi->outro_trampoline = trampoline_ptr; + void *outro_trampoline_real = trampoline_ptr; + hi->outro_trampoline = outro_trampoline_real; +#ifdef __arm__ + if (arch.pc_low_bit) + hi->outro_trampoline++; +#endif if (hook->old_ptr) *(void **) hook->old_ptr = hi->outro_trampoline; @@ -218,10 +223,8 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks, uintptr_t dpc = pc_patch_end; #ifdef __arm__ - if (arch.pc_low_bit) { - hi->outro_trampoline++; + if (arch.pc_low_bit) dpc++; - } #endif /* Now that transform_dis_main has given us the final pc_patch_end, @@ -233,7 +236,7 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks, make_jump_patch(&trampoline_ptr, (uintptr_t) trampoline_ptr, dpc, arch); trampoline_ptr += -(uintptr_t) trampoline_ptr % ARCH_MAX_CODE_ALIGNMENT; trampoline_size_left -= (uint8_t *) trampoline_ptr - - (uint8_t *) hi->outro_trampoline; + - (uint8_t *) outro_trampoline_real; } /* Now commit. */ diff --git a/lib/jump-dis.c b/lib/jump-dis.c index aa562a6..13845f5 100644 --- a/lib/jump-dis.c +++ b/lib/jump-dis.c @@ -131,6 +131,7 @@ bool jump_dis_main(void *code_ptr, uint_tptr pc_patch_start, uint_tptr pc_patch_ ctx.pc_ret = -1; ctx.base.pc = pc_patch_end; ctx.arch = initial_dis_ctx; + VEC_STORAGE_INIT(&ctx.queue, uint_tptr); while (1) { ctx.bad_insn = false; ctx.continue_after_this_insn = true; diff --git a/lib/x86/arch-transform-dis.inc.h b/lib/x86/arch-transform-dis.inc.h index a4be424..454423b 100644 --- a/lib/x86/arch-transform-dis.inc.h +++ b/lib/x86/arch-transform-dis.inc.h @@ -89,7 +89,7 @@ static void transform_dis_branch(struct transform_dis_ctx *ctx, uint_tptr dpc, ctx->write_newop_here = code; code += ctx->base.op_size; - uintptr_t source = ctx->pc_trampoline + ctx->base.op_size + 2; + uint_tptr source = ctx->pc_trampoline + ctx->base.op_size + 2; int size = jump_patch_size(source, dpc, arch, true); /* If not taken, jmp past the big jump - this is a bit suboptimal but not diff --git a/lib/x86/jump-patch.h b/lib/x86/jump-patch.h index 09554d1..c09cb1c 100644 --- a/lib/x86/jump-patch.h +++ b/lib/x86/jump-patch.h @@ -1,5 +1,6 @@ #pragma once #define MAX_JUMP_PATCH_SIZE 14 +#define MAX_EXTENDED_PATCH_SIZE (MAX_JUMP_PATCH_SIZE+14) #include "dis.h" static inline int jump_patch_size(uint_tptr pc, uint_tptr dpc, |