diff options
author | comex | 2015-02-23 00:41:29 -0500 |
---|---|---|
committer | comex | 2015-02-23 00:54:13 -0500 |
commit | b63f1dff9dc736f7fa66f04976436f1f3fe2ac5d (patch) | |
tree | db70eb338a0107fdc70992ea2522fd03f2ecf32e /lib/arm | |
parent | fix some i386 stuff (diff) | |
download | substitute-b63f1dff9dc736f7fa66f04976436f1f3fe2ac5d.tar.gz |
Ban calls within transform regions in threadsafe mode.
Diffstat (limited to '')
-rw-r--r-- | lib/arm/arch-transform-dis.inc.h | 21 | ||||
-rw-r--r-- | lib/arm/dis-arm.inc.h | 7 | ||||
-rw-r--r-- | lib/arm/dis-thumb.inc.h | 3 | ||||
-rw-r--r-- | lib/arm/dis-thumb2.inc.h | 18 | ||||
-rw-r--r-- | lib/arm64/arch-transform-dis.inc.h | 7 | ||||
-rw-r--r-- | lib/arm64/assemble.h | 4 | ||||
-rw-r--r-- | lib/arm64/dis-main.inc.h | 9 |
7 files changed, 47 insertions, 22 deletions
diff --git a/lib/arm/arch-transform-dis.inc.h b/lib/arm/arch-transform-dis.inc.h index c5963e1..8569300 100644 --- a/lib/arm/arch-transform-dis.inc.h +++ b/lib/arm/arch-transform-dis.inc.h @@ -113,7 +113,7 @@ void transform_dis_data(struct transform_dis_ctx *ctx, unsigned o0, unsigned o1, POPone(actx, scratch); } } - ctx->modify = true; + ctx->base.modify = true; #ifdef TRANSFORM_DIS_VERBOSE printf("transform_dis_data: => %x %x %x %x\n", newval[0], newval[1], newval[2], newval[3]); @@ -149,23 +149,18 @@ void transform_dis_pcrel(struct transform_dis_ctx *ctx, uintptr_t dpc, } static NOINLINE UNUSED -void transform_dis_branch(struct transform_dis_ctx *ctx, - uintptr_t dpc, int cc) { +void transform_dis_branch(struct transform_dis_ctx *ctx, uintptr_t dpc, int cc) { #ifdef TRANSFORM_DIS_VERBOSE printf("transform_dis (0x%llx): branch => 0x%llx\n", (unsigned long long) ctx->base.pc, (unsigned long long) dpc); #endif - if (dpc >= ctx->pc_patch_start && dpc < ctx->pc_patch_end) { - /* don't support this for now */ - /* making the simplifying assumption here that functions will not try - * to branch into the middle of an IT block, which is the case where - * pc_patch_end changes to include additional instructions (as opposed - * to include the end of a partially included instruction, which is - * common) */ - ctx->err = SUBSTITUTE_ERR_FUNC_BAD_INSN_AT_START; - return; - } + /* 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 + * an IT block, which is the case where pc_patch_end changes to include + * additional instructions (as opposed to include the end of a partially + * included instruction, which is common). */ + transform_dis_branch_top(ctx, dpc, cc); struct assemble_ctx actx = tdctx_to_actx(ctx); ctx->write_newop_here = NULL; if ((cc & CC_ARMCC) == CC_ARMCC) { diff --git a/lib/arm/dis-arm.inc.h b/lib/arm/dis-arm.inc.h index 3ae0ab9..ab61877 100644 --- a/lib/arm/dis-arm.inc.h +++ b/lib/arm/dis-arm.inc.h @@ -206,6 +206,13 @@ static INLINE void P(GPR_Rt_addr_offset_none_addr_postidx_reg_Rm_S_1_STRHTr)(tdi static INLINE void P(GPR_dst_B_2_BX)(tdis_ctx ctx, UNUSED struct bitslice dst) { return P(ret)(ctx); } +static INLINE void P(GPR_func_3_BLX)(tdis_ctx ctx, UNUSED struct bitslice func) { + return P(indirect_call)(ctx); +} +static INLINE void P(bl_target_func_2_BL)(tdis_ctx ctx, struct bitslice func) { + return P(branch)(ctx, ctx->base.pc + 8 + sext(bs_get(func, ctx->base.op), 24), + CC_CALL); +} static INLINE void P(dis_arm)(tdis_ctx ctx) { uint32_t op = ctx->base.op = *(uint32_t *) ctx->base.ptr; diff --git a/lib/arm/dis-thumb.inc.h b/lib/arm/dis-thumb.inc.h index 4a2b747..4f758bf 100644 --- a/lib/arm/dis-thumb.inc.h +++ b/lib/arm/dis-thumb.inc.h @@ -81,6 +81,9 @@ static INLINE void P(it_pred_cc_it_mask_mask_1_t2IT)(tdis_ctx ctx, struct bitsli ctx->arch.it_conds[i+2] = (cc_val & ~1) | (mask_val >> (3 - i) & 1); return P(thumb_it)(ctx); } +static INLINE void P(GPR_func_1_tBLXr)(tdis_ctx ctx, UNUSED struct bitslice func) { + return P(indirect_call)(ctx); +} static INLINE void P(thumb_do_it)(tdis_ctx ctx) { uint16_t op = ctx->base.op = *(uint16_t *) ctx->base.ptr; diff --git a/lib/arm/dis-thumb2.inc.h b/lib/arm/dis-thumb2.inc.h index 43ca4ab..5f699c9 100644 --- a/lib/arm/dis-thumb2.inc.h +++ b/lib/arm/dis-thumb2.inc.h @@ -170,6 +170,24 @@ static INLINE void P(unk_Rm_B_2_t2TBB)(tdis_ctx ctx, UNUSED struct bitslice Rm) static INLINE void P(unk_Rt_13_VMOVRRD)(tdis_ctx ctx, UNUSED struct bitslice Rt) { return P(unidentified)(ctx); } +static INLINE void P(t_bltarget_func_1_tBL)(tdis_ctx ctx, struct bitslice func) { + unsigned crap = bs_get(func, ctx->base.op) << 1; + unsigned S = crap >> 24 & 1; + if (S) + crap ^= (3 << 22); + return P(branch)(ctx, ctx->base.pc + 4 + 2 * sext(crap, 25), CC_CALL); + +} +static INLINE void P(t_blxtarget_func_1_tBLXi)(tdis_ctx ctx, struct bitslice func) { + unsigned crap = bs_get(func, ctx->base.op); + unsigned S = crap >> 24 & 1; + if (S) + crap ^= (3 << 22); + return P(branch)(ctx, ctx->base.pc + 4 + 2 * sext(crap, 25), CC_CALL); +} +static INLINE void P(rGPR_func_1_t2BXJ)(tdis_ctx ctx, UNUSED struct bitslice func) { + return P(unidentified)(ctx); +} static INLINE void P(thumb2_do_it)(tdis_ctx ctx) { uint32_t op = ctx->base.op; diff --git a/lib/arm64/arch-transform-dis.inc.h b/lib/arm64/arch-transform-dis.inc.h index ac11e45..123c7ae 100644 --- a/lib/arm64/arch-transform-dis.inc.h +++ b/lib/arm64/arch-transform-dis.inc.h @@ -23,10 +23,7 @@ void transform_dis_branch(struct transform_dis_ctx *ctx, uint_tptr dpc, int cc) (unsigned long long) ctx->base.pc, (unsigned long long) dpc); #endif - if (dpc >= ctx->pc_patch_start && dpc < ctx->pc_patch_end) { - ctx->err = SUBSTITUTE_ERR_FUNC_BAD_INSN_AT_START; - return; - } + transform_dis_branch_top(ctx, dpc, cc); ctx->write_newop_here = NULL; int mov_br_size = size_of_MOVi64(dpc) + 4; @@ -42,7 +39,7 @@ void transform_dis_branch(struct transform_dis_ctx *ctx, uint_tptr dpc, int cc) } int reg = arm64_get_unwritten_temp_reg(&ctx->arch); MOVi64(codep, reg, dpc); - BR(codep, reg); + BR(codep, reg, /*link*/ cc & CC_CALL); } static void transform_dis_pre_dis(UNUSED struct transform_dis_ctx *ctx) {} diff --git a/lib/arm64/assemble.h b/lib/arm64/assemble.h index 1dca7eb..42c0f0c 100644 --- a/lib/arm64/assemble.h +++ b/lib/arm64/assemble.h @@ -56,8 +56,8 @@ static inline void ADRP_ADD(void **codep, int reg, uint64_t pc, uint64_t dpc) { } } -static inline void BR(void **codep, int reg) { - op32(codep, 0xd61f0000 | reg << 5); +static inline void BR(void **codep, int reg, bool link) { + op32(codep, 0xd61f0000 | reg << 5 | link << 21); } static inline void Bccrel(void **codep, int cc, int offset) { diff --git a/lib/arm64/dis-main.inc.h b/lib/arm64/dis-main.inc.h index 0107715..a009189 100644 --- a/lib/arm64/dis-main.inc.h +++ b/lib/arm64/dis-main.inc.h @@ -55,8 +55,13 @@ static INLINE void P(am_ldrlit_label_unk_Rt_6_LDRDl)(tdis_ctx ctx, struct bitsli return P(pcrel)(ctx, ctx->base.pc + sext(bs_get(label, ctx->base.op), 19) * 4, (struct arch_pcrel_info) {bs_get(Rt, ctx->base.op), mode}); } -static INLINE void P(GPR64_Rn_1_RET)(tdis_ctx ctx, UNUSED struct bitslice Rn) { - return P(ret)(ctx); + +static INLINE void P(GPR64_Rn_2_BLR)(tdis_ctx ctx, UNUSED struct bitslice Rn) { + int op = ctx->base.op >> 21 & 3; + if (op == 1) + return P(indirect_call)(ctx); + else + return P(ret)(ctx); } static INLINE void P(dis)(tdis_ctx ctx) { |