diff options
author | comex | 2015-02-08 23:45:24 -0500 |
---|---|---|
committer | comex | 2015-02-08 23:45:24 -0500 |
commit | eb93cee2a22cde812ccd6b9bd418d36185c058f5 (patch) | |
tree | 43a22ccf021a1513dba3a9c99f7b81822fe950fa /lib/transform-dis.c | |
parent | formatting (diff) | |
download | substitute-eb93cee2a22cde812ccd6b9bd418d36185c058f5.tar.gz |
Refactor disassembly so x86 works, and add x86 transform-dis.
This patch is a monolithic mess, because I was too lazy to do the
refactor first (that would require some stash fun, since I wasn't
actually sure before doing x86 transform-dis what would be needed).
Anyway, the resulting code should be cleaner - less duplication.
This breaks ARM/ARM64.
Diffstat (limited to '')
-rw-r--r-- | lib/transform-dis.c | 55 |
1 files changed, 21 insertions, 34 deletions
diff --git a/lib/transform-dis.c b/lib/transform-dis.c index 867a981..8f89fb3 100644 --- a/lib/transform-dis.c +++ b/lib/transform-dis.c @@ -1,5 +1,6 @@ #include "substitute-internal.h" #ifdef TARGET_DIS_SUPPORTED +#define DIS_MAY_MODIFY 1 #include "substitute.h" #include "dis.h" @@ -13,21 +14,15 @@ struct transform_dis_ctx { /* outputs */ bool modify; int err; + struct dis_ctx_base base; - uintptr_t pc_patch_start; + uint_tptr pc_patch_start; /* this is only tentative - it will be updated to include parts of * instructions poking out, and instructions forced to be transformed by IT */ - uintptr_t pc_patch_end; - uintptr_t pc; - int op_size; - unsigned op; - unsigned newop; - unsigned newval[4]; - + uint_tptr pc_patch_end; /* for IT - eww */ bool force_keep_transforming; - const void *ptr; void **rewritten_ptr_ptr; void *write_newop_here; @@ -35,10 +30,6 @@ struct transform_dis_ctx { }; #define tdis_ctx struct transform_dis_ctx * -#define TDIS_CTX_MODIFY(ctx) ((ctx)->modify) -#define TDIS_CTX_NEWVAL(ctx, n) ((ctx)->newval[n]) -#define TDIS_CTX_NEWOP(ctx) ((ctx)->newop) -#define TDIS_CTX_SET_NEWOP(ctx, new) ((ctx)->newop = (new)) /* largely similar to jump_dis */ @@ -46,14 +37,14 @@ static INLINE UNUSED void transform_dis_ret(struct transform_dis_ctx *ctx) { /* ret is okay if it's at the end of the required patch (past the original * patch size is good too) */ - if (ctx->pc + ctx->op_size < ctx->pc_patch_end) + if (ctx->base.pc + ctx->base.op_size < ctx->pc_patch_end) ctx->err = SUBSTITUTE_ERR_FUNC_TOO_SHORT; } static INLINE UNUSED void transform_dis_unidentified(UNUSED struct transform_dis_ctx *ctx) { #ifdef TRANSFORM_DIS_VERBOSE - printf("transform_dis (%p): unidentified\n", (void *) ctx->pc); + printf("transform_dis (%p): unidentified\n", (void *) ctx->base.pc); #endif /* this isn't exhaustive, so unidentified is fine */ } @@ -74,15 +65,15 @@ static void transform_dis_post_dis(struct transform_dis_ctx *ctx); int transform_dis_main(const void *restrict code_ptr, void **restrict rewritten_ptr_ptr, - uintptr_t pc_patch_start, - uintptr_t *pc_patch_end_p, + uint_tptr pc_patch_start, + uint_tptr *pc_patch_end_p, struct arch_dis_ctx *arch_ctx_p, 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_p; - ctx.pc = pc_patch_start; + ctx.base.pc = pc_patch_start; ctx.arch = *arch_ctx_p; /* data is written to rewritten both by this function directly and, in case * additional scaffolding is needed, by arch-specific transform_dis_* */ @@ -90,10 +81,10 @@ int transform_dis_main(const void *restrict code_ptr, void *rewritten_start = *rewritten_ptr_ptr; int written_pcdiff = 0; offset_by_pcdiff[written_pcdiff++] = 0; - while (ctx.pc < ctx.pc_patch_end && !ctx.force_keep_transforming) { - ctx.modify = false; + while (ctx.base.pc < ctx.pc_patch_end && !ctx.force_keep_transforming) { + ctx.base.modify = false; ctx.err = 0; - ctx.ptr = code_ptr + (ctx.pc - pc_patch_start); + ctx.base.ptr = code_ptr + (ctx.base.pc - pc_patch_start); transform_dis_pre_dis(&ctx); @@ -105,33 +96,29 @@ int transform_dis_main(const void *restrict code_ptr, if (ctx.err) return ctx.err; if (ctx.write_newop_here != NULL) { - if (!ctx.modify) - ctx.newop = ctx.op; - if (ctx.op_size == 4) - *(uint32_t *) ctx.write_newop_here = ctx.newop; - else if (ctx.op_size == 2) - *(uint16_t *) ctx.write_newop_here = ctx.newop; + if (ctx.base.modify) + memcpy(ctx.write_newop_here, ctx.base.newop, ctx.base.newop_size); else - __builtin_abort(); + memcpy(ctx.write_newop_here, ctx.base.ptr, ctx.base.op_size); if (*rewritten_ptr_ptr == rewritten_ptr) - *rewritten_ptr_ptr += ctx.op_size; + *rewritten_ptr_ptr += ctx.base.op_size; } - ctx.pc += ctx.op_size; + ctx.base.pc += ctx.base.op_size; transform_dis_post_dis(&ctx); - int pcdiff = ctx.pc - ctx.pc_patch_start; + int pcdiff = ctx.base.pc - ctx.pc_patch_start; while (written_pcdiff < pcdiff) offset_by_pcdiff[written_pcdiff++] = -1; offset_by_pcdiff[written_pcdiff++] = (int) (*rewritten_ptr_ptr - rewritten_start); } - *pc_patch_end_p = ctx.pc; + *pc_patch_end_p = ctx.base.pc; *arch_ctx_p = ctx.arch; return SUBSTITUTE_OK; } -#include TARGET_TRANSFORM_DIS_HEADER -#include TARGET_DIS_HEADER +#include stringify(TARGET_DIR/arch-transform-dis.inc.h) +#include stringify(TARGET_DIR/dis-main.inc.h) #endif /* TARGET_DIS_SUPPORTED */ |