aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYifan Lu2016-11-03 23:10:30 -0700
committerYifan Lu2016-11-03 23:10:30 -0700
commit89377379e8486b1220384c969bb2897a02e3283b (patch)
tree1464f14a94111008ef6ca8d34096b3ddacc1eb5e
parentMade ARM patch alignment 0x4 so copy from kernel to user works (diff)
downloadsubstitute-89377379e8486b1220384c969bb2897a02e3283b.tar.gz
Implemented call rewrite support, fixes #3
-rw-r--r--lib/arm/arch-transform-dis.inc.h10
-rw-r--r--lib/arm/assemble.h7
2 files changed, 16 insertions, 1 deletions
diff --git a/lib/arm/arch-transform-dis.inc.h b/lib/arm/arch-transform-dis.inc.h
index aa56a9c..b3efc77 100644
--- a/lib/arm/arch-transform-dis.inc.h
+++ b/lib/arm/arch-transform-dis.inc.h
@@ -174,8 +174,16 @@ void transform_dis_branch(struct transform_dis_ctx *ctx, uint_tptr dpc, int cc)
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;
- LDR_PC(actx, dpc | ctx->arch.pc_low_bit);
+ if ((cc & CC_CALL)) {
+ POPmulti(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);
+ }
}
static void transform_dis_pre_dis(struct transform_dis_ctx *ctx) {
diff --git a/lib/arm/assemble.h b/lib/arm/assemble.h
index 625f464..e6a72d0 100644
--- a/lib/arm/assemble.h
+++ b/lib/arm/assemble.h
@@ -111,3 +111,10 @@ static inline void LDR_PC(struct assemble_ctx ctx, uint32_t dpc) {
if (ctx.pc & 2) // for alignment
op16(ctx.codep, 0xbf00);
}
+
+static inline void ADD_PC(struct assemble_ctx ctx, uint32_t Rd, uint32_t imm12) {
+ if (ctx.thumb)
+ op32(ctx.codep, 0x0000f20f | ((imm12 >> 11) << 10) | (((imm12 & 0x700) >> 8) << 28) | Rd << 24 | (imm12 & 0xff) << 16);
+ else
+ op32(ctx.codep, 0x028f0000 | Rd << 12 | imm12 << 0 | ctx.cond << 28);
+}