diff options
author | comex | 2015-01-17 20:09:42 -0500 |
---|---|---|
committer | comex | 2015-01-17 20:09:42 -0500 |
commit | 17d4d47511fe1a51ffeb83f0fe923993680304dd (patch) | |
tree | 17934be6219f5ec8d870d79c15a7d7516a83f42f /lib | |
parent | transform-dis stuff - compiles for arm, so far (diff) | |
download | substitute-17d4d47511fe1a51ffeb83f0fe923993680304dd.tar.gz |
IT, BX LR - untested
Diffstat (limited to 'lib')
-rw-r--r-- | lib/dis-arm.inc.h | 3 | ||||
-rw-r--r-- | lib/dis-thumb.inc.h | 14 | ||||
-rw-r--r-- | lib/dis-thumb2.inc.h | 5 | ||||
-rw-r--r-- | lib/dis.h | 4 | ||||
-rw-r--r-- | lib/jump-dis.c | 38 | ||||
-rw-r--r-- | lib/transform-dis.inc.h | 2 |
6 files changed, 46 insertions, 20 deletions
diff --git a/lib/dis-arm.inc.h b/lib/dis-arm.inc.h index c95e450..0779205 100644 --- a/lib/dis-arm.inc.h +++ b/lib/dis-arm.inc.h @@ -193,6 +193,9 @@ static INLINE void P(addr_offset_none_addr_postidx_reg_Rm_unk_Rt_3_LDRHTr)(tdis_ static INLINE void P(GPR_Rt_addr_offset_none_addr_postidx_reg_Rm_S_1_STRHTr)(tdis_ctx ctx, struct bitslice Rm, struct bitslice Rt, struct bitslice addr) { data(r(addr), r(Rt), r(Rm)); } +static INLINE void P(GPR_dst_B_2_BX)(tdis_ctx ctx, UNUSED struct bitslice dst) { + return P(ret)(ctx); +} static INLINE void P(dis_arm)(tdis_ctx ctx) { uint32_t op = ctx->op = *(uint32_t *) ctx->ptr; diff --git a/lib/dis-thumb.inc.h b/lib/dis-thumb.inc.h index a0434bc..6d9683e 100644 --- a/lib/dis-thumb.inc.h +++ b/lib/dis-thumb.inc.h @@ -53,14 +53,26 @@ static INLINE void P(t_bcctarget_target_B_1_tBcc)(tdis_ctx ctx, struct bitslice return P(branch)(ctx, ctx->pc + 4 + 2 * sext(bs_get(target, ctx->op), 8), /*cond*/ true); } static INLINE void P(t_brtarget_target_B_1_tB)(tdis_ctx ctx, struct bitslice target) { - return P(branch)(ctx, ctx->pc + 4 + 2 * sext(bs_get(target, ctx->op), 11), /*cond*/ false); + bool cond = ctx->arch.thumb_it_length > 0; + return P(branch)(ctx, ctx->pc + 4 + 2 * sext(bs_get(target, ctx->op), 11), cond); } static INLINE void P(t_cbtarget_target_B_2_tCBNZ)(tdis_ctx ctx, struct bitslice target) { return P(branch)(ctx, ctx->pc + 4 + 2 * bs_get(target, ctx->op), /*cond*/ true); } +static INLINE void P(it_pred_cc_it_mask_mask_1_t2IT)(tdis_ctx ctx, struct bitslice mask, UNUSED struct bitslice cc) { + /* why */ + unsigned mask_val = bs_get(mask, ctx->op); + unsigned length = __builtin_ctz(mask_val); + if (length >= 3) + return P(unidentified)(ctx); /* nop */ + ctx->arch.thumb_it_length = length; + return P(unidentified)(ctx); +} static INLINE void P(dis_thumb)(tdis_ctx ctx) { uint16_t op = ctx->op = *(uint16_t *) ctx->ptr; + if (ctx->arch.thumb_it_length) + ctx->arch.thumb_it_length--; ctx->op_size = 2; #include "../generated/generic-dis-thumb.inc.h" __builtin_abort(); diff --git a/lib/dis-thumb2.inc.h b/lib/dis-thumb2.inc.h index 36d341e..632e2a2 100644 --- a/lib/dis-thumb2.inc.h +++ b/lib/dis-thumb2.inc.h @@ -148,7 +148,8 @@ static INLINE void P(t2ldrlabel_addr_unk_Rt_5_t2LDRBpci)(tdis_ctx ctx, struct bi return P(pcrel)(ctx, ((ctx->pc + 4) & ~2) + (bs_get(addr, ctx->op) & ((1 << 12) - 1)), bs_get(Rt, ctx->op), get_thumb2_load_mode(ctx->op)); } static INLINE void P(uncondbrtarget_target_B_1_t2B)(tdis_ctx ctx, struct bitslice target) { - return P(branch)(ctx, ctx->pc + 4 + 2 * sext(bs_get(target, ctx->op), 24), /*cond*/ false); + bool cond = ctx->arch.thumb_it_length > 0; + return P(branch)(ctx, ctx->pc + 4 + 2 * sext(bs_get(target, ctx->op), 24), cond); } static INLINE void P(unk_Rd_3_t2MOVTi16)(tdis_ctx ctx, struct bitslice Rd) { data(rout(Rd)); @@ -163,6 +164,8 @@ static INLINE void P(unk_Rt_13_VMOVRRD)(tdis_ctx ctx, UNUSED struct bitslice Rt) static INLINE void P(dis_thumb2)(tdis_ctx ctx) { uint32_t op = ctx->op = *(uint32_t *) ctx->ptr; + if (ctx->arch.thumb_it_length) + ctx->arch.thumb_it_length--; ctx->op_size = 4; #include "../generated/generic-dis-thumb2.inc.h" __builtin_abort(); @@ -107,14 +107,18 @@ static const unsigned null_op = -0x100; #if defined(TARGET_x86_64) #define MIN_INSN_SIZE 1 #error "no x86 dis yet" + struct arch_dis_ctx {}; #elif defined(TARGET_i386) #define MIN_INSN_SIZE 1 #error "no x86 dis yet" + struct arch_dis_ctx {}; #elif defined(TARGET_arm) #define MIN_INSN_SIZE 2 #define TARGET_DIS_HEADER "dis-arm-multi.inc.h" + struct arch_dis_ctx { unsigned thumb_it_length; }; #elif defined(TARGET_arm64) #define MIN_INSN_SIZE 4 #define TARGET_DIS_HEADER "dis-arm64.inc.h" + struct arch_dis_ctx {}; #endif diff --git a/lib/jump-dis.c b/lib/jump-dis.c index aa3b5f3..b6ddd13 100644 --- a/lib/jump-dis.c +++ b/lib/jump-dis.c @@ -18,24 +18,26 @@ enum { }; struct jump_dis_ctx { - /* outputs */ - bool bad_insn; - bool continue_after_this_insn; - - uintptr_t pc; - uintptr_t pc_patch_start; - uintptr_t pc_patch_end; - bool pc_low_bit; - unsigned op; - const void *ptr; - int op_size; - uint8_t seen_mask[JUMP_ANALYSIS_MAX_INSNS / 8]; - /* queue of instructions to visit */ - uintptr_t *queue; - size_t queue_write_off; - size_t queue_read_off; - size_t queue_size; - size_t queue_count; + /* outputs */ + bool bad_insn; + bool continue_after_this_insn; + + uintptr_t pc; + uintptr_t pc_patch_start; + uintptr_t pc_patch_end; + bool pc_low_bit; + unsigned op; + const void *ptr; + int op_size; + uint8_t seen_mask[JUMP_ANALYSIS_MAX_INSNS / 8]; + /* queue of instructions to visit */ + uintptr_t *queue; + size_t queue_write_off; + size_t queue_read_off; + size_t queue_size; + size_t queue_count; + + struct arch_dis_ctx arch; }; #undef P diff --git a/lib/transform-dis.inc.h b/lib/transform-dis.inc.h index b20012a..04cd7f2 100644 --- a/lib/transform-dis.inc.h +++ b/lib/transform-dis.inc.h @@ -22,6 +22,8 @@ struct transform_dis_ctx { const void *ptr; void **rewritten_ptr_ptr; void *write_newop_here; + + struct arch_dis_ctx arch; }; #define tdis_ctx struct transform_dis_ctx * |