diff options
author | Yifan Lu | 2016-11-23 14:34:33 -0600 |
---|---|---|
committer | Yifan Lu | 2016-11-23 14:34:33 -0600 |
commit | bd5ebb7a0a4e102731de72832f3e12e9f54d541a (patch) | |
tree | bef4f637a270d3f7d2551ac74a89e6b4bad8adec /lib/arm/arch-transform-dis.inc.h | |
parent | Fixed proper encoding of PUSH (STMDB) as ARM manual was wrong... (diff) | |
parent | avoid UB (diff) | |
download | substitute-bd5ebb7a0a4e102731de72832f3e12e9f54d541a.tar.gz |
Merge branch 'master' of https://github.com/comex/substitute
Diffstat (limited to 'lib/arm/arch-transform-dis.inc.h')
-rw-r--r-- | lib/arm/arch-transform-dis.inc.h | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/lib/arm/arch-transform-dis.inc.h b/lib/arm/arch-transform-dis.inc.h index 1b8e3d5..1e9579d 100644 --- a/lib/arm/arch-transform-dis.inc.h +++ b/lib/arm/arch-transform-dis.inc.h @@ -12,7 +12,8 @@ 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->rewritten_ptr_ptr, + (uint_tptr) (uintptr_t) *ctx->rewritten_ptr_ptr, ctx->arch.pc_low_bit, cond }; @@ -20,8 +21,7 @@ static struct assemble_ctx tdctx_to_actx(const struct transform_dis_ctx *ctx) { } static int invert_arm_cond(int cc) { - if (cc >= 0xe) - __builtin_abort(); + substitute_assert(cc < 0xe); return cc ^ 1; } @@ -152,9 +152,10 @@ void transform_dis_pcrel(struct transform_dis_ctx *ctx, uint_tptr dpc, static NOINLINE UNUSED 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", + printf("transform_dis (0x%llx): branch => 0x%llx cc=%x\n", (unsigned long long) ctx->base.pc, - (unsigned long long) dpc); + (unsigned long long) dpc, + cc); #endif /* The check in transform_dis_branch_top is correct under the simplifying * assumption here that functions will not try to branch into the middle of @@ -164,26 +165,24 @@ 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); if ((cc & CC_ARMCC) == CC_ARMCC) { + replacement_size += actx.thumb ? 2 : 4; actx.cond = invert_arm_cond(cc & 0xf); - Bccrel(actx, 2+8); + Bccrel(actx, replacement_size); } else if ((cc & CC_CBXZ) == CC_CBXZ) { + replacement_size += 2; ctx->base.modify = true; - ctx->base.newval[0] = ctx->base.pc + 2+8; + ctx->base.newval[0] = actx.pc_of_code_base + replacement_size; ctx->base.newval[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; - if ((cc & CC_CALL)) { - PUSHmulti(actx, 1 << 7 | 1 << 14); // save lr, r7 (for stack alignment, chosen arbitary) - ADD_PC(actx, 14, actx.thumb ? (actx.pc & 2 ? 12 : 8) | 1 : 4); - LDR_PC(actx, dpc | ctx->arch.pc_low_bit); - POPmulti(actx, 1 << 7 | 1 << 14); // restore lr, r7 (for stack alignment) - } else { - LDR_PC(actx, dpc | ctx->arch.pc_low_bit); - } + MOVW_MOVT(actx, 14, dpc | ctx->arch.pc_low_bit); + BLXr(actx, 14); + substitute_assert(*actx.codep - actx.code_base == replacement_size); } static void transform_dis_pre_dis(struct transform_dis_ctx *ctx) { @@ -201,6 +200,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, + ctx->arch.bccrel_p, (uint_tptr) (uintptr_t) ctx->arch.bccrel_p, /*thumb*/ true, ctx->arch.bccrel_bits}; |