diff options
author | Yifan Lu | 2016-11-23 17:24:50 -0600 |
---|---|---|
committer | Yifan Lu | 2016-11-23 17:24:50 -0600 |
commit | f1df6fbca8975ceb0eebd51519eb5f753ff75fa4 (patch) | |
tree | cc82fdacbe5c5a5dbceaf5107a5b961dffd6b188 /lib/arm/arch-transform-dis.inc.h | |
parent | Merge branch 'master' of https://github.com/comex/substitute (diff) | |
download | substitute-f1df6fbca8975ceb0eebd51519eb5f753ff75fa4.tar.gz |
Fixed defination of CC_CBXZ collides with other bits
Fixed incorrect pc value in tdctx_to_actx
Fixed ARM32 handling of CC_CBXZ (uses incorrect field in ctx->base)
Fixed ARM32 transform_dis_branch incorrectly trashing LR for non-call based jumps
Fixed ARM32 make_jump_patch not updated to use new assemble_ctx
Added new option SUBSTITUTE_RELAXED to relax the disassembly engine
Currently SUBSTITUTE_RELAXED only disables TRANSFORM_DIS_REL_JUMPS so jumps at the beginning of functions are allowed
Diffstat (limited to 'lib/arm/arch-transform-dis.inc.h')
-rw-r--r-- | lib/arm/arch-transform-dis.inc.h | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/lib/arm/arch-transform-dis.inc.h b/lib/arm/arch-transform-dis.inc.h index 1e9579d..b23c2c3 100644 --- a/lib/arm/arch-transform-dis.inc.h +++ b/lib/arm/arch-transform-dis.inc.h @@ -1,5 +1,6 @@ /* TODO fix BL incl MOV LR, PC */ #include "arm/assemble.h" +#include "arm/jump-patch.h" static struct assemble_ctx tdctx_to_actx(const struct transform_dis_ctx *ctx) { int cond; @@ -13,7 +14,7 @@ static struct assemble_ctx tdctx_to_actx(const struct transform_dis_ctx *ctx) { return (struct assemble_ctx) { ctx->rewritten_ptr_ptr, *ctx->rewritten_ptr_ptr, - (uint_tptr) (uintptr_t) *ctx->rewritten_ptr_ptr, + ctx->base.pc, ctx->arch.pc_low_bit, cond }; @@ -165,23 +166,41 @@ void transform_dis_branch(struct transform_dis_ctx *ctx, uint_tptr dpc, int cc) transform_dis_branch_top(ctx, dpc, cc); struct assemble_ctx actx = tdctx_to_actx(ctx); ctx->write_newop_here = NULL; - int replacement_size = 8 + (actx.thumb ? 2 : 4); + int replacement_size; + + /* Dry run to get size */ + if ((cc & CC_ARMCC) == CC_ARMCC) { + replacement_size = actx.thumb ? 2 : 4; + } else if ((cc & CC_CBXZ) == CC_CBXZ) { + replacement_size = 2; + } + if ((cc & CC_CALL) == CC_CALL) { + replacement_size += 8 + (actx.thumb ? 2 : 4); + } else { + replacement_size += jump_patch_size(actx_pc(actx) + replacement_size, dpc, ctx->arch, 0); + } + + /* Actual run */ if ((cc & CC_ARMCC) == CC_ARMCC) { - replacement_size += actx.thumb ? 2 : 4; actx.cond = invert_arm_cond(cc & 0xf); Bccrel(actx, replacement_size); } else if ((cc & CC_CBXZ) == CC_CBXZ) { - replacement_size += 2; ctx->base.modify = true; - ctx->base.newval[0] = actx.pc_of_code_base + replacement_size; - ctx->base.newval[1] = 1; /* do invert */ + ctx->base.newop[0] = actx.pc_of_code_base + replacement_size; + ctx->base.newop[1] = 1; /* do invert */ void **codep = ctx->rewritten_ptr_ptr; ctx->write_newop_here = *codep; *codep += 2; } - /* If it's a call, we should jump back after the call */ + actx.cond = 0xe; - MOVW_MOVT(actx, 14, dpc | ctx->arch.pc_low_bit); - BLXr(actx, 14); + /* If it's a call, we should jump back after the call */ + if ((cc & CC_CALL) == CC_CALL) { + MOVW_MOVT(actx, 14, dpc | ctx->arch.pc_low_bit); + BLXr(actx, 14); + } else { + // otherwise we can't clobber LR + LDR_PC(actx, dpc | ctx->arch.pc_low_bit); + } substitute_assert(*actx.codep - actx.code_base == replacement_size); } |