diff options
-rw-r--r-- | Makefile | 18 | ||||
-rw-r--r-- | lib/dis.h | 14 | ||||
-rw-r--r-- | lib/jump-dis-arm-multi.c | 6 | ||||
-rw-r--r-- | lib/jump-dis.c (renamed from lib/jump-dis.inc.h) | 32 | ||||
-rw-r--r-- | lib/jump-dis.h | 5 | ||||
-rw-r--r-- | lib/substitute-internal.h | 25 | ||||
-rw-r--r-- | test/test-jump-dis.c | 2 |
7 files changed, 75 insertions, 27 deletions
@@ -30,7 +30,7 @@ out/%.o: lib/%.c Makefile $(HEADERS) $(CC) -fvisibility=hidden -std=c11 -c -o $@ $< out/%.o: lib/%.S Makefile $(HEADERS) $(CC) -fvisibility=hidden -c -o $@ $< -out/jump-dis-arm-multi.o: generated/generic-dis-arm.inc.h generated/generic-dis-thumb.inc.h generated/generic-dis-thumb2.inc.h +out/jump-dis.o: $(GENERATED) LIB_OBJS := \ out/find-syms.o \ @@ -38,7 +38,7 @@ LIB_OBJS := \ out/objc.o \ out/objc-asm.o \ out/substrate-compat.o \ - out/jump-dis-arm-multi.o + out/jump-dis.o out/libsubstitute.dylib: $(LIB_OBJS) $(CC) -o $@ $(LIB_OBJS) $(LIB_LDFLAGS) @@ -47,15 +47,17 @@ out/test-$(1): test/test-$(2).[cm]* $(HEADERS) $(GENERATED) Makefile out/libsubs $(3) -g -o $$@ $$< -Ilib -Isubstrate -Lout -lsubstitute all: out/test-$(1) endef -$(eval $(call define_test,tdarm-simple,td-simple,$(CC) -std=c11 -DHDR='"dis-arm.inc.h"' -Dxdis=dis_arm)) -$(eval $(call define_test,tdthumb-simple,td-simple,$(CC) -std=c11 -DHDR='"dis-thumb.inc.h"' -Dxdis=dis_thumb)) -$(eval $(call define_test,tdthumb2-simple,td-simple,$(CC) -std=c11 -DHDR='"dis-thumb2.inc.h"' -Dxdis=dis_thumb2)) -$(eval $(call define_test,tdarm64-simple,td-simple,$(CC) -std=c11 -DHDR='"dis-arm64.inc.h"' -Dxdis=dis)) -$(eval $(call define_test,dis,dis,$(CC) -std=c11)) +$(eval $(call define_test,tdarm-simple,td-simple,$(CC) -std=c11 -DHDR='"dis-arm.inc.h"' -Dxdis=dis_arm -DFORCE_TARGET_arm)) +$(eval $(call define_test,tdthumb-simple,td-simple,$(CC) -std=c11 -DHDR='"dis-thumb.inc.h"' -Dxdis=dis_thumb -DFORCE_TARGET_arm)) +$(eval $(call define_test,tdthumb2-simple,td-simple,$(CC) -std=c11 -DHDR='"dis-thumb2.inc.h"' -Dxdis=dis_thumb2 -DFORCE_TARGET_arm)) +$(eval $(call define_test,tdarm64-simple,td-simple,$(CC) -std=c11 -DHDR='"dis-arm64.inc.h"' -Dxdis=dis -DFORCE_TARGET_arm64)) +$(eval $(call define_test,dis-arm,dis,$(CC) -std=c11 -DFORCE_TARGET_arm)) +$(eval $(call define_test,dis-arm64,dis,$(CC) -std=c11 -DFORCE_TARGET_arm64)) +$(eval $(call define_test,jump-dis-arm,jump-dis,$(CC) -std=c11 -DFORCE_TARGET_arm)) +$(eval $(call define_test,jump-dis-arm64,jump-dis,$(CC) -std=c11 -DFORCE_TARGET_arm64)) $(eval $(call define_test,find-syms,find-syms,$(CC) -std=c89)) $(eval $(call define_test,find-syms-cpp,find-syms,$(CXX) -x c++ -std=c++98)) $(eval $(call define_test,substrate,substrate,$(CXX) -std=c++98)) -$(eval $(call define_test,jump-dis,jump-dis,$(CC) -std=c11)) $(eval $(call define_test,imp-forwarding,imp-forwarding,$(CC) -std=c11 -framework Foundation -lobjc)) $(eval $(call define_test,objc-hook,objc-hook,$(CC) -std=c11 -framework Foundation -lsubstitute)) $(eval $(call define_test,interpose,interpose,$(CC) -std=c11 -lsubstitute)) @@ -104,3 +104,17 @@ static const unsigned null_op = -0x100; return; \ } while (0) +#if defined(TARGET_x86_64) + #define MIN_INSN_SIZE 1 + #error "no x86 dis yet" +#elif defined(TARGET_i386) + #define MIN_INSN_SIZE 1 + #error "no x86 dis yet" +#elif defined(TARGET_arm) + #define MIN_INSN_SIZE 2 + #define TARGET_DIS_HEADER "dis-arm-multi.inc.h" +#elif defined(TARGET_arm64) + #define MIN_INSN_SIZE 4 + #define TARGET_DIS_HEADER "dis-arm64.inc.h" +#endif + diff --git a/lib/jump-dis-arm-multi.c b/lib/jump-dis-arm-multi.c deleted file mode 100644 index b5967f5..0000000 --- a/lib/jump-dis-arm-multi.c +++ /dev/null @@ -1,6 +0,0 @@ -enum { - MIN_INSN_SIZE = 2 -}; -#define P(x) jump_dis_##x -#include "jump-dis.inc.h" -#include "dis-arm-multi.inc.h" diff --git a/lib/jump-dis.inc.h b/lib/jump-dis.c index a070a74..c7c7346 100644 --- a/lib/jump-dis.inc.h +++ b/lib/jump-dis.c @@ -1,3 +1,5 @@ +#include "substitute-internal.h" +#ifndef TARGET_UNSUPPORTED #include "dis.h" #include <stdint.h> #include <stdbool.h> @@ -36,12 +38,15 @@ struct jump_dis_ctx { size_t queue_count; }; +#undef P +#define P(x) jump_dis_##x + #define tdis_ctx struct jump_dis_ctx * #define TDIS_CTX_MODIFY(ctx) 0 #define TDIS_CTX_NEWVAL(ctx, n) 0 #define TDIS_CTX_SET_NEWOP(ctx, new) ((void) 0) -static void P(add_to_queue)(struct jump_dis_ctx *ctx, uintptr_t pc) { +static void jump_dis_add_to_queue(struct jump_dis_ctx *ctx, uintptr_t pc) { size_t diff = (pc - ctx->pc_patch_start) / MIN_INSN_SIZE; if (diff >= JUMP_ANALYSIS_MAX_INSNS) { #ifdef JUMP_DIS_VERBOSE @@ -73,21 +78,21 @@ static void P(add_to_queue)(struct jump_dis_ctx *ctx, uintptr_t pc) { } -static INLINE inline void P(data)(UNUSED struct jump_dis_ctx *ctx, UNUSED unsigned o0, UNUSED unsigned o1, UNUSED unsigned o2, UNUSED unsigned o3, UNUSED unsigned out_mask) { +static INLINE inline void jump_dis_data(UNUSED struct jump_dis_ctx *ctx, UNUSED unsigned o0, UNUSED unsigned o1, UNUSED unsigned o2, UNUSED unsigned o3, UNUSED unsigned out_mask) { /* on ARM, ignore mov PC jumps, as they're unlikely to be in the same function */ } -static INLINE inline void P(pcrel)(struct jump_dis_ctx *ctx, uintptr_t dpc, UNUSED unsigned reg, UNUSED bool is_load) { +static INLINE inline void jump_dis_pcrel(struct jump_dis_ctx *ctx, uintptr_t dpc, UNUSED unsigned reg, UNUSED bool is_load) { ctx->bad_insn = dpc >= ctx->pc_patch_start && dpc < ctx->pc_patch_end; } NOINLINE UNUSED -static void P(ret)(struct jump_dis_ctx *ctx) { +static void jump_dis_ret(struct jump_dis_ctx *ctx) { ctx->continue_after_this_insn = false; } NOINLINE UNUSED -static void P(branch)(struct jump_dis_ctx *ctx, uintptr_t dpc, bool conditional) { +static void jump_dis_branch(struct jump_dis_ctx *ctx, uintptr_t dpc, bool conditional) { if (dpc >= ctx->pc_patch_start && dpc < ctx->pc_patch_end) { ctx->bad_insn = true; return; @@ -95,22 +100,22 @@ static void P(branch)(struct jump_dis_ctx *ctx, uintptr_t dpc, bool conditional) #ifdef JUMP_DIS_VERBOSE printf("jump-dis: enqueueing %llx\n", (unsigned long long) dpc); #endif - P(add_to_queue)(ctx, dpc); + jump_dis_add_to_queue(ctx, dpc); ctx->continue_after_this_insn = conditional; } NOINLINE UNUSED -static void P(unidentified)(UNUSED struct jump_dis_ctx *ctx) { +static void jump_dis_unidentified(UNUSED struct jump_dis_ctx *ctx) { } NOINLINE UNUSED -static void P(bad)(struct jump_dis_ctx *ctx) { +static void jump_dis_bad(struct jump_dis_ctx *ctx) { ctx->continue_after_this_insn = false; } -static void P(dis)(tdis_ctx ctx); +static void jump_dis_dis(tdis_ctx ctx); -bool P(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, bool pc_low_bit) { bool ret; struct jump_dis_ctx ctx; memset(&ctx, 0, sizeof(ctx)); @@ -122,7 +127,7 @@ bool P(main)(void *code_ptr, uintptr_t pc_patch_start, uintptr_t pc_patch_end, b ctx.bad_insn = false; ctx.continue_after_this_insn = true; ctx.ptr = code_ptr + (ctx.pc - pc_patch_start); - P(dis)(&ctx); + jump_dis_dis(&ctx); #ifdef JUMP_DIS_VERBOSE printf("jump-dis: pc=%llx op=%08x size=%x bad=%d continue_after=%d\n", (unsigned long long) ctx.pc, @@ -136,7 +141,7 @@ bool P(main)(void *code_ptr, uintptr_t pc_patch_start, uintptr_t pc_patch_end, b goto fail; } if (ctx.continue_after_this_insn) - P(add_to_queue)(&ctx, ctx.pc + ctx.op_size); + jump_dis_add_to_queue(&ctx, ctx.pc + ctx.op_size); /* get next address */ if (ctx.queue_read_off == ctx.queue_write_off) @@ -151,3 +156,6 @@ fail: free(ctx.queue); return ret; } + +#include TARGET_DIS_HEADER +#endif /* TARGET_UNSUPPORTED */ diff --git a/lib/jump-dis.h b/lib/jump-dis.h new file mode 100644 index 0000000..c567096 --- /dev/null +++ b/lib/jump-dis.h @@ -0,0 +1,5 @@ +#pragma once +#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); diff --git a/lib/substitute-internal.h b/lib/substitute-internal.h index 2550d2a..cf50a99 100644 --- a/lib/substitute-internal.h +++ b/lib/substitute-internal.h @@ -26,3 +26,28 @@ typedef struct section section_x; #define LC_SEGMENT_X LC_SEGMENT #endif #endif + +/* FORCE_* are for tests */ +#if defined(FORCE_TARGET_x86_64) + #define TARGET_x86_64 +#elif defined(FORCE_TARGET_i386) + #define TARGET_i386 + #define TARGET_UNSUPPORTED +#elif defined(FORCE_TARGET_arm) + #define TARGET_arm +#elif defined(FORCE_TARGET_arm64) + #define TARGET_arm64 +#elif defined(__x86_64__) + #define TARGET_x86_64 +#elif defined(__i386__) + #define TARGET_i386 +#elif defined(__arm__) + #define TARGET_arm +#elif defined(__arm64__) + #define TARGET_arm64 +#else + #error target? +#endif +#if defined(TARGET_x86_64) || defined(TARGET_i386) + #define TARGET_UNSUPPORTED +#endif diff --git a/test/test-jump-dis.c b/test/test-jump-dis.c index 161c80c..1afa4e5 100644 --- a/test/test-jump-dis.c +++ b/test/test-jump-dis.c @@ -1,6 +1,6 @@ #define JUMP_DIS_VERBOSE #include <stdio.h> -#include "jump-dis-arm-multi.c" +#include "jump-dis.c" #include <stdlib.h> int main(UNUSED int argc, char **argv) { static char buf[1048576]; |