diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | lib/arm/dis-arm-multi.inc.h | 2 | ||||
-rw-r--r-- | lib/arm/misc.h | 5 | ||||
-rw-r--r-- | lib/arm/transform-dis-arm-multi.inc.h | 14 | ||||
-rw-r--r-- | lib/jump-dis.c | 7 | ||||
-rw-r--r-- | lib/jump-dis.h | 3 | ||||
-rw-r--r-- | lib/transform-dis.c | 6 | ||||
-rw-r--r-- | lib/transform-dis.h | 2 | ||||
-rw-r--r-- | test/test-jump-dis.c | 7 | ||||
-rw-r--r-- | test/test-transform-dis.c | 7 |
10 files changed, 34 insertions, 21 deletions
@@ -74,7 +74,7 @@ out/inject-asm.S: $(IAR_BINS) Makefile script/gen-inject-asm.sh define define_test out/test-$(1): test/test-$(2).[cm]* $(HEADERS) $(GENERATED) Makefile out/libsubstitute.dylib $(3) -g -o $$@ $$< -Ilib -Isubstrate -Lout -lsubstitute - lipo -info $$@ | grep -q arm && ldid -Sent.plist $$@ || true + lipo -info $$@ | grep -q ':.*:.*arm' && ldid -Sent.plist $$@ || true install_name_tool -change /usr/lib/libsubstitute.dylib '@executable_path/libsubstitute.dylib' $$@ all: out/test-$(1) endef diff --git a/lib/arm/dis-arm-multi.inc.h b/lib/arm/dis-arm-multi.inc.h index 56cde35..bf2767e 100644 --- a/lib/arm/dis-arm-multi.inc.h +++ b/lib/arm/dis-arm-multi.inc.h @@ -3,7 +3,7 @@ #include "dis-arm.inc.h" static INLINE void P(dis)(tdis_ctx ctx) { - if (ctx->pc_low_bit) { + if (ctx->arch.pc_low_bit) { uint16_t op = *(uint16_t *) ctx->ptr; bool is_32 = (op >> 13 & 7) == 7 && (op >> 11 & 3) != 0; if (is_32) diff --git a/lib/arm/misc.h b/lib/arm/misc.h index 44d8e7a..047be2d 100644 --- a/lib/arm/misc.h +++ b/lib/arm/misc.h @@ -3,5 +3,8 @@ #define TARGET_DIS_HEADER "arm/dis-arm-multi.inc.h" #define TARGET_TRANSFORM_DIS_HEADER "arm/transform-dis-arm-multi.inc.h" #define MIN_INSN_SIZE 2 -struct arch_dis_ctx { unsigned thumb_it_length; }; +struct arch_dis_ctx { + unsigned thumb_it_length; + bool pc_low_bit; +}; enum { IS_LDRD_STRD = 1 << 16 }; diff --git a/lib/arm/transform-dis-arm-multi.inc.h b/lib/arm/transform-dis-arm-multi.inc.h index 662b501..f1b9b80 100644 --- a/lib/arm/transform-dis-arm-multi.inc.h +++ b/lib/arm/transform-dis-arm-multi.inc.h @@ -1,19 +1,19 @@ static inline void PUSHone(struct transform_dis_ctx *ctx, int Rt) { - if (ctx->pc_low_bit) + if (ctx->arch.pc_low_bit) op32(ctx, 0x0d04f84d | Rt << 28); else op32(ctx, 0xe52d0004 | Rt << 12); } static inline void POPone(struct transform_dis_ctx *ctx, int Rt) { - if (ctx->pc_low_bit) + if (ctx->arch.pc_low_bit) op32(ctx, 0x0b04f85d | Rt << 28); else op32(ctx, 0xe49d0004 | Rt << 12); } static inline void POPmulti(struct transform_dis_ctx *ctx, uint16_t mask) { - if (ctx->pc_low_bit) + if (ctx->arch.pc_low_bit) op32(ctx, 0x0000e8bd | mask << 16); else op32(ctx, 0xe8bd0000 | mask); @@ -21,7 +21,7 @@ static inline void POPmulti(struct transform_dis_ctx *ctx, uint16_t mask) { static inline void MOVW_MOVT(struct transform_dis_ctx *ctx, int Rd, uint32_t val) { uint16_t hi = val >> 16, lo = (uint16_t) val; - if (ctx->pc_low_bit) { + if (ctx->arch.pc_low_bit) { op32(ctx, 0x0000f240 | Rd << 24 | lo >> 12 | (lo >> 11 & 1) << 10 | (lo >> 8 & 7) << 28 | (lo & 0xff) << 16); op32(ctx, 0x0000f2c0 | Rd << 24 | hi >> 12 | (hi >> 11 & 1) << 10 | @@ -35,7 +35,7 @@ static inline void MOVW_MOVT(struct transform_dis_ctx *ctx, int Rd, uint32_t val } static inline void STRri(struct transform_dis_ctx *ctx, int Rt, int Rn, uint32_t off) { - if (ctx->pc_low_bit) + if (ctx->arch.pc_low_bit) op32(ctx, 0x0000f8c0 | Rn | Rt << 28 | off << 16); else op32(ctx, 0xe4800000 | Rn << 16 | Rt << 12 | off); @@ -43,7 +43,7 @@ static inline void STRri(struct transform_dis_ctx *ctx, int Rt, int Rn, uint32_t static inline void LDRxi(struct transform_dis_ctx *ctx, int Rt, int Rn, uint32_t off, enum pcrel_load_mode load_mode) { - if (ctx->pc_low_bit) { + if (ctx->arch.pc_low_bit) { int subop, sign; switch (load_mode) { case PLM_U8: subop = 0; sign = 0; break; @@ -118,7 +118,7 @@ static NOINLINE UNUSED void transform_dis_data(struct transform_dis_ctx *ctx, } if (out_mask & IS_LDRD_STRD) in_regs |= 1 << (newval[0] + 1); - uint32_t pc = ctx->pc + (ctx->pc_low_bit ? 4 : 8); + uint32_t pc = ctx->pc + (ctx->arch.pc_low_bit ? 4 : 8); int scratch = __builtin_ctz(~(in_regs | (1 << out_reg))); #ifdef TRANSFORM_DIS_VERBOSE diff --git a/lib/jump-dis.c b/lib/jump-dis.c index 2a4f94c..5e06460 100644 --- a/lib/jump-dis.c +++ b/lib/jump-dis.c @@ -25,7 +25,6 @@ struct jump_dis_ctx { uintptr_t pc; uintptr_t pc_patch_start; uintptr_t pc_patch_end; - bool pc_low_bit; unsigned op; const void *ptr; int op_size; @@ -119,15 +118,15 @@ static INLINE UNUSED void jump_dis_bad(struct jump_dis_ctx *ctx) { static void jump_dis_dis(struct jump_dis_ctx *ctx); -bool jump_dis_main(const void *code_ptr, uintptr_t pc_patch_start, - uintptr_t pc_patch_end, bool pc_low_bit) { +bool jump_dis_main(void *code_ptr, uintptr_t pc_patch_start, uintptr_t pc_patch_end, + struct arch_dis_ctx initial_dis_ctx) { bool ret; struct jump_dis_ctx ctx; memset(&ctx, 0, sizeof(ctx)); ctx.pc_patch_start = pc_patch_start; ctx.pc_patch_end = pc_patch_end; - ctx.pc_low_bit = pc_low_bit; ctx.pc = pc_patch_end; + ctx.arch = initial_dis_ctx; while (1) { ctx.bad_insn = false; ctx.continue_after_this_insn = true; diff --git a/lib/jump-dis.h b/lib/jump-dis.h index c567096..575a84d 100644 --- a/lib/jump-dis.h +++ b/lib/jump-dis.h @@ -2,4 +2,5 @@ #include <stdint.h> #include <stdbool.h> -bool jump_dis_main(void *code_ptr, uintptr_t pc_patch_start, uintptr_t pc_patch_end, bool pc_low_bit); +bool jump_dis_main(void *code_ptr, uintptr_t pc_patch_start, uintptr_t pc_patch_end, + struct arch_dis_ctx initial_dis_ctx); diff --git a/lib/transform-dis.c b/lib/transform-dis.c index 6067ea0..9edf89e 100644 --- a/lib/transform-dis.c +++ b/lib/transform-dis.c @@ -13,7 +13,6 @@ struct transform_dis_ctx { bool modify; int err; - bool pc_low_bit; uintptr_t pc_patch_start; uintptr_t pc_patch_end; uintptr_t pc; @@ -73,13 +72,14 @@ int transform_dis_main(const void *restrict code_ptr, void **restrict rewritten_ptr_ptr, uintptr_t pc_patch_start, uintptr_t pc_patch_end, - bool pc_low_bit, + struct arch_dis_ctx initial_arch_ctx, int *offset_by_pcdiff) { struct transform_dis_ctx ctx; + memset(&ctx, 0, sizeof(ctx)); ctx.pc_patch_start = pc_patch_start; ctx.pc_patch_end = pc_patch_end; - ctx.pc_low_bit = pc_low_bit; ctx.pc = pc_patch_start; + ctx.arch = initial_arch_ctx; /* data is written to rewritten both by this function directly and, in case * additional scaffolding is needed, by arch-specific transform_dis_* */ ctx.rewritten_ptr_ptr = rewritten_ptr_ptr; diff --git a/lib/transform-dis.h b/lib/transform-dis.h index 28e5d72..dec38a1 100644 --- a/lib/transform-dis.h +++ b/lib/transform-dis.h @@ -6,5 +6,5 @@ int transform_dis_main(const void *restrict code_ptr, void **restrict rewritten_ptr_ptr, uintptr_t pc_patch_start, uintptr_t pc_patch_end, - bool pc_low_bit, + struct arch_dis_ctx initial_arch_ctx, int *offset_by_pcdiff); diff --git a/test/test-jump-dis.c b/test/test-jump-dis.c index 1a34bc0..ef6add8 100644 --- a/test/test-jump-dis.c +++ b/test/test-jump-dis.c @@ -7,7 +7,12 @@ int main(UNUSED int argc, char **argv) { UNUSED size_t size = fread(buf, 1, sizeof(buf), stdin); printf("size=%zd\n", size); int patch_size = atoi(argv[1]); + struct arch_dis_ctx arch; + memset(&arch, 0, sizeof(arch)); +#ifdef __arm__ int thumb = atoi(argv[2]); - bool bad = P(main)(buf, 0x10000, 0x10000 + patch_size, thumb); + arch.pc_low_bit = thumb; +#endif + bool bad = P(main)(buf, 0x10000, 0x10000 + patch_size, arch); printf("final: bad = %d\n", bad); } diff --git a/test/test-transform-dis.c b/test/test-transform-dis.c index d7c44d6..a0a60d5 100644 --- a/test/test-transform-dis.c +++ b/test/test-transform-dis.c @@ -6,7 +6,12 @@ int main(UNUSED int argc, char **argv) { static uint8_t in[1048576]; UNUSED size_t size = fread(in, 1, sizeof(in), stdin); int patch_size = atoi(argv[1]); + struct arch_dis_ctx arch; + memset(&arch, 0, sizeof(arch)); +#ifdef __arm__ int thumb = atoi(argv[2]); + arch.pc_low_bit = thumb; +#endif uint8_t out[patch_size * 10]; int offsets[patch_size + 1]; void *rewritten_ptr = out; @@ -16,7 +21,7 @@ int main(UNUSED int argc, char **argv) { &rewritten_ptr, 0x10000, 0x10000 + patch_size, - thumb, + arch, offsets); printf("=> %d\n", ret); printf("#endif\n"); |