aboutsummaryrefslogtreecommitdiff
path: root/lib/arm/arch-transform-dis.inc.h
diff options
context:
space:
mode:
authorYifan Lu2016-11-23 17:24:50 -0600
committerYifan Lu2016-11-23 17:24:50 -0600
commitf1df6fbca8975ceb0eebd51519eb5f753ff75fa4 (patch)
treecc82fdacbe5c5a5dbceaf5107a5b961dffd6b188 /lib/arm/arch-transform-dis.inc.h
parentMerge branch 'master' of https://github.com/comex/substitute (diff)
downloadsubstitute-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.h37
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);
}