static int analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) { int i; char str[32][32]; r_strbuf_init (&op->esil); r_strbuf_set (&op->esil, ""); switch (insn->detail->arm.cc) { case ARM_CC_AL: // no condition break; case ARM_CC_EQ: r_strbuf_setf (&op->esil, "zf,0,?,"); break; case ARM_CC_NE: r_strbuf_setf (&op->esil, "zf,!,0,?,"); break; case ARM_CC_GT: case ARM_CC_LE: break; default: break; } // TODO: PREFIX CONDITIONAL switch (insn->id) { case ARM_INS_PUSH: // TODO: increment stack case ARM_INS_STM: for (i=1; i<insn->detail->arm.op_count; i++) { r_strbuf_appendf (&op->esil, "%s,%s,%d,+,=[4],", REG (i), ARG (0), i*4); } break; case ARM_INS_POP: // TODO: decrement stack case ARM_INS_LDM: for (i=1; i<insn->detail->arm.op_count; i++) { r_strbuf_appendf (&op->esil, "%s,%d,+,[4],%s,=", ARG (0), i*4, REG (i)); } break; case ARM_INS_CMP: r_strbuf_appendf (&op->esil, "%s,%s,==", ARG(1), ARG(0)); break; case ARM_INS_LSL: // suffix 'S' forces conditional flag to be updated r_strbuf_appendf (&op->esil, "%s,%s,<<=", ARG(1), ARG(0)); break; case ARM_INS_LSR: // suffix 'S' forces conditional flag to be updated r_strbuf_appendf (&op->esil, "%s,%s,>>=", ARG(1), ARG(0)); break; case ARM_INS_B: r_strbuf_appendf (&op->esil, "%s,pc,=", ARG(0)); break; case ARM_INS_BL: case ARM_INS_BLX: r_strbuf_appendf (&op->esil, "4,pc,+,lr,=,%s,pc,=", ARG(0)); break; case ARM_INS_MOV: case ARM_INS_MOVS: r_strbuf_appendf (&op->esil, "%s,%s,=", ARG(1), REG(0)); break; case ARM_INS_SSUB16: case ARM_INS_SSUB8: case ARM_INS_SUB: r_strbuf_appendf (&op->esil, "%s,%s,-=", ARG(1), ARG(0)); break; case ARM_INS_SADD16: case ARM_INS_SADD8: case ARM_INS_ADD: if (!strcmp (ARG(0),ARG(1))) { r_strbuf_appendf (&op->esil, "%s,%s,+=", ARG(2), ARG(0)); } else if (!strcmp (ARG(2),"0")) { r_strbuf_appendf (&op->esil, "%s,%s,=", ARG(1), ARG(0)); } else { r_strbuf_appendf (&op->esil, "%s,%s,+,%s,=", ARG(2), ARG(1), ARG(0)); } break; case ARM_INS_STR: r_strbuf_appendf (&op->esil, "%s,%s,%d,+,=[4]", REG(0), MEMBASE(1), MEMDISP(1)); break; case ARM_INS_STRB: r_strbuf_appendf (&op->esil, "%s,%s,%d,+,=[1]", REG(0), MEMBASE(1), MEMDISP(1)); break; case ARM_INS_LDR: if (MEMDISP(1)<0) { if (REGBASE(1) == ARM_REG_PC) { r_strbuf_appendf (&op->esil, "8,%s,+,%d,-,[4],%s,=", MEMBASE(1), -MEMDISP(1), REG(0)); switch (a->bits) { case 32: op->ptr = addr + 8 - MEMDISP(1); op->refptr = 4; break; case 16: if ( (addr % 4) == 0 ) { op->ptr = addr + 4 - MEMDISP(1); op->refptr = 4; } else { op->ptr = addr + 2 - MEMDISP(1); op->refptr = 4; } break; } } else { r_strbuf_appendf (&op->esil, "%s,%d,-,[4],%s,=", MEMBASE(1), -MEMDISP(1), REG(0)); } } else { if (REGBASE(1) == ARM_REG_PC) { r_strbuf_appendf (&op->esil, "8,%s,+,%d,+,[4],%s,=", MEMBASE(1), MEMDISP(1), REG(0)); if (a->bits==32) { op->ptr = addr + 8 + MEMDISP(1); op->refptr = 4; } else if (a->bits==16) { if ( (addr % 4) == 0 ) { op->ptr = addr + 4 + MEMDISP(1); op->refptr = 4; } else { op->ptr = addr + 2 + MEMDISP(1); op->refptr = 4; } } } else { r_strbuf_appendf (&op->esil, "%s,%d,+,[4],%s,=", MEMBASE(1), MEMDISP(1), REG(0)); } op->refptr = 4; } break; case ARM_INS_LDRD: case ARM_INS_LDRB: r_strbuf_appendf (&op->esil, "%s,%d,+,[1],%s,=", MEMBASE(1), MEMDISP(1), REG(0)); break; default: break; } return 0; }
static int analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) { int i; char str[32][32]; r_strbuf_init (&op->esil); r_strbuf_set (&op->esil, ""); switch (insn->detail->arm.cc) { case ARM_CC_AL: // no condition break; case ARM_CC_EQ: r_strbuf_setf (&op->esil, "zf,0,?,"); break; case ARM_CC_NE: r_strbuf_setf (&op->esil, "zf,!,0,?,"); break; case ARM_CC_GT: case ARM_CC_LE: break; } // TODO: PREFIX CONDITIONAL switch (insn->id) { case ARM_INS_PUSH: // TODO: increment stack case ARM_INS_STM: for (i=1; i<insn->detail->arm.op_count; i++) { r_strbuf_appendf (&op->esil, "%s,%s,%d,+,=[4],", REG (i), ARG (0), i*4); } break; case ARM_INS_POP: // TODO: decrement stack case ARM_INS_LDM: for (i=1; i<insn->detail->arm.op_count; i++) { r_strbuf_appendf (&op->esil, "%s,%d,+,[4],%s,=", ARG (0), i*4, REG (i)); } break; case ARM_INS_CMP: r_strbuf_appendf (&op->esil, "%s,%s,==", ARG(1), ARG(0)); break; case ARM_INS_LSL: // suffix 'S' forces conditional flag to be updated r_strbuf_appendf (&op->esil, "%s,%s,<<=", ARG(1), ARG(0)); break; case ARM_INS_LSR: // suffix 'S' forces conditional flag to be updated r_strbuf_appendf (&op->esil, "%s,%s,>>=", ARG(1), ARG(0)); break; case ARM_INS_B: case ARM_INS_BL: case ARM_INS_BLX: r_strbuf_appendf (&op->esil, "%s,pc,=", ARG(0)); break; case ARM_INS_MOV: case ARM_INS_MOVS: r_strbuf_appendf (&op->esil, "%s,%s,=", ARG(1), REG(0)); break; case ARM_INS_SSUB16: case ARM_INS_SSUB8: case ARM_INS_SUB: r_strbuf_appendf (&op->esil, "%s,%s,-=", ARG(1), ARG(0)); break; case ARM_INS_SADD16: case ARM_INS_SADD8: case ARM_INS_ADD: r_strbuf_appendf (&op->esil, "%s,%s,+=", ARG(1), ARG(0)); break; case ARM_INS_LDR: r_strbuf_appendf (&op->esil, "%s,%d,+,[4],%s,=", MEMBASE(1), MEMDISP(1), REG(0)); break; case ARM_INS_LDRB: r_strbuf_appendf (&op->esil, "%s,%d,+,[1],%s,=", MEMBASE(1), MEMDISP(1), REG(0)); break; } return 0; }
static void anop32 (RAnalOp *op, cs_insn *insn) { ut64 addr = op->addr; int i; switch (insn->id) { case ARM_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; break; case ARM_INS_POP: case ARM_INS_LDM: op->type = R_ANAL_OP_TYPE_POP; for (i = 0; i < insn->detail->arm.op_count; i++) { if (insn->detail->arm.operands[i].type == ARM_OP_REG && insn->detail->arm.operands[i].reg == ARM_REG_PC) { if (insn->detail->arm.cc == ARM_CC_AL) op->type = R_ANAL_OP_TYPE_RET; else op->type = R_ANAL_OP_TYPE_CRET; break; } } break; case ARM_INS_SUB: op->type = R_ANAL_OP_TYPE_SUB; if (ISREG(0)) { if (REGID(0) == ARM_REG_SP) { // 0x00008254 10d04de2 sub sp, sp, 0x10 op->stackop = R_ANAL_STACK_INC; op->stackptr = IMM (2); } } break; case ARM_INS_ADD: op->type = R_ANAL_OP_TYPE_ADD; if (REGID(1)==ARM_REG_PC) { op->ptr = addr + 8 + IMM(2); op->refptr = 0; } break; case ARM_INS_MOV: case ARM_INS_MOVS: case ARM_INS_MOVT: case ARM_INS_MOVW: case ARM_INS_VMOVL: case ARM_INS_VMOVN: case ARM_INS_VQMOVUN: case ARM_INS_VQMOVN: op->type = R_ANAL_OP_TYPE_MOV; break; case ARM_INS_AND: op->type = R_ANAL_OP_TYPE_AND; break; case ARM_INS_CMP: case ARM_INS_TST: op->type = R_ANAL_OP_TYPE_CMP; break; case ARM_INS_ROR: case ARM_INS_ORN: case ARM_INS_LSL: case ARM_INS_LSR: break; //case ARM_INS_POP: case ARM_INS_PUSH: case ARM64_INS_STRB: case ARM_INS_STR: op->type = R_ANAL_OP_TYPE_STORE; // 0x00008160 04202de5 str r2, [sp, -4]! // 0x000082a0 28000be5 str r0, [fp, -0x28] if (REGBASE(1) == ARM_REG_FP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = 0; op->ptr = MEMDISP(1); } break; case ARM_INS_LDR: case ARM_INS_LDRD: case ARM_INS_LDRB: // 0x000082a8 28301be5 ldr r3, [fp, -0x28] if (insn->detail->arm.operands[0].reg == ARM_REG_PC) { op->type = R_ANAL_OP_TYPE_UJMP; } else { op->type = R_ANAL_OP_TYPE_LOAD; } if (REGBASE(1) == ARM_REG_FP) { op->stackop = R_ANAL_STACK_GET; op->stackptr = 0; op->ptr = MEMDISP(1); } break; case ARM_INS_BL: case ARM_INS_BLX: op->type = R_ANAL_OP_TYPE_CALL; op->jump = IMM(0); break; case ARM_INS_B: case ARM_INS_BX: case ARM_INS_BXJ: // BX LR == RET if (insn->detail->arm.operands[0].reg == ARM_REG_LR) { op->type = R_ANAL_OP_TYPE_RET; } else if (insn->detail->arm.cc) { op->type = R_ANAL_OP_TYPE_CJMP; op->jump = (ut64) (ut32)IMM(0); op->fail = addr+op->size; } else { op->type = R_ANAL_OP_TYPE_JMP; op->jump = IMM(0); } break; default: break; } }