static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle = 0; cs_insn *insn = NULL; int mode = (a->bits==16)? CS_MODE_THUMB: CS_MODE_ARM; int n, ret; mode |= (a->big_endian)? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN; ret = (a->bits==64)? cs_open (CS_ARCH_ARM64, mode, &handle): cs_open (CS_ARCH_ARM, mode, &handle); cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); op->type = R_ANAL_OP_TYPE_NULL; op->size = (a->bits==16)? 2: 4; op->delay = 0; op->jump = op->fail = -1; op->addr = addr; op->ptr = op->val = -1; op->refptr = 0; r_strbuf_init (&op->esil); if (ret == CS_ERR_OK) { n = cs_disasm (handle, (ut8*)buf, len, addr, 1, &insn); if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { op->size = insn->size; if (a->bits == 64) { anop64 (op, insn); } else { anop32 (op, insn); } if (a->decode) { analop_esil (a, op, addr, buf, len, &handle, insn); } cs_free (insn, n); } cs_close (&handle); } return op->size; }
static int i8051_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { char *tmp = NULL; char buf_asm[64]; op->delay = 0; r_8051_op o = r_8051_decode (buf, len); memset(buf_asm, 0, sizeof (buf_asm)); if (!o.name) return 0; // invalid instruction tmp = r_8051_disasm (o, addr, buf_asm, sizeof (buf_asm)); if (tmp) { if (strlen (tmp) < sizeof (buf_asm)) { strncpy (buf_asm, tmp, strlen (tmp)); } else { eprintf ("8051 analysis: too big opcode!\n"); free (tmp); op->size = -1; return -1; } free (tmp); } if (!strncmp (buf_asm, "push", 4)) { op->type = R_ANAL_OP_TYPE_UPUSH; op->ptr = 0; op->stackop = R_ANAL_STACK_INC; op->stackptr = 1; } else if (!strncmp (buf_asm, "pop", 3)) { op->type = R_ANAL_OP_TYPE_POP; op->ptr = 0; op->stackop = R_ANAL_STACK_INC; op->stackptr = -1; } else if (!strncmp (buf_asm, "ret", 3)) { op->type = R_ANAL_OP_TYPE_RET; op->stackop = R_ANAL_STACK_INC; op->stackptr = -2; } else if (!strncmp (buf_asm, "nop", 3)) { op->type = R_ANAL_OP_TYPE_NOP; } else if (!strncmp (buf_asm, "inv", 3)) { op->type = R_ANAL_OP_TYPE_ILL; } else if ((!strncmp (buf_asm, "inc", 3)) || (!strncmp (buf_asm, "add", 3))) { op->type = R_ANAL_OP_TYPE_ADD; } else if ((!strncmp (buf_asm, "dec", 3)) || (!strncmp (buf_asm, "sub", 3))) { op->type = R_ANAL_OP_TYPE_SUB; } else if (!strncmp (buf_asm, "mov", 3)) { op->type = R_ANAL_OP_TYPE_MOV; } else if (*buf_asm && !strncmp (buf_asm+1, "call", 4)) { op->type = R_ANAL_OP_TYPE_CALL; op->jump = o.addr; op->fail = addr+o.length; } else /* CJNE, DJNZ, JC, JNC, JZ, JB, JNB, LJMP, SJMP */ if (buf_asm[0]=='j' || (buf_asm[0] && buf_asm[1] == 'j')) { op->type = R_ANAL_OP_TYPE_JMP; if (o.operand == OFFSET) op->jump = o.addr+addr+o.length; else op->jump = o.addr; op->fail = addr+o.length; } if (anal->decode) { ut8 copy[3] = {0, 0, 0}; memcpy (copy, buf, len >= 3 ? 3 : len); analop_esil (anal, op, addr, copy, buf_asm); } return op->size = o.length; }
static int analop(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { int n, ret, opsize = -1; static csh hndl = 0; static csh *handle = &hndl; static int omode = -1; static int obits = 32; cs_insn* insn; int mode = anal->big_endian? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN; mode |= (anal->bits==64)? CS_MODE_64: CS_MODE_32; if (mode != omode || anal->bits != obits) { cs_close (&hndl); hndl = 0; omode = mode; obits = anal->bits; } // XXX no arch->cpu ?!?! CS_MODE_MICRO, N64 op->delay = 0; op->type = R_ANAL_OP_TYPE_ILL; if (len<4) return -1; op->size = 4; if (hndl == 0) { ret = cs_open (CS_ARCH_MIPS, mode, &hndl); if (ret != CS_ERR_OK) goto fin; cs_option (hndl, CS_OPT_DETAIL, CS_OPT_ON); } n = cs_disasm (hndl, (ut8*)buf, len, addr, 1, &insn); if (n<1 || insn->size<1) goto beach; op->type = R_ANAL_OP_TYPE_NULL; op->delay = 0; op->jump = UT64_MAX; op->fail = UT64_MAX; opsize = op->size = insn->size; switch (insn->id) { case MIPS_INS_INVALID: op->type = R_ANAL_OP_TYPE_ILL; break; case MIPS_INS_LB: case MIPS_INS_LBU: case MIPS_INS_LBUX: case MIPS_INS_LW: case MIPS_INS_LWC1: case MIPS_INS_LWC2: case MIPS_INS_LWL: case MIPS_INS_LWR: case MIPS_INS_LWXC1: case MIPS_INS_LD: case MIPS_INS_LDC1: case MIPS_INS_LDC2: case MIPS_INS_LDL: case MIPS_INS_LDR: case MIPS_INS_LDXC1: op->type = R_ANAL_OP_TYPE_LOAD; op->refptr = 4; switch (OPERAND(1).type) { case MIPS_OP_MEM: if (OPERAND(1).mem.base == MIPS_REG_GP) { op->ptr = anal->gp + OPERAND(1).mem.disp; op->refptr = 4; } break; case MIPS_OP_IMM: op->ptr = OPERAND(1).imm; break; case MIPS_OP_REG: // wtf? break; default: break; } // TODO: fill break; case MIPS_INS_SW: case MIPS_INS_SWC1: case MIPS_INS_SWC2: case MIPS_INS_SWL: case MIPS_INS_SWR: case MIPS_INS_SWXC1: op->type = R_ANAL_OP_TYPE_STORE; break; case MIPS_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; break; case MIPS_INS_SYSCALL: case MIPS_INS_BREAK: op->type = R_ANAL_OP_TYPE_TRAP; break; case MIPS_INS_JALR: op->type = R_ANAL_OP_TYPE_UCALL; op->delay = 1; break; case MIPS_INS_JAL: case MIPS_INS_JALS: case MIPS_INS_JALX: case MIPS_INS_JRADDIUSP: case MIPS_INS_BAL: // (no blezal/bgtzal or blezall/bgtzall, only blezalc/bgtzalc) case MIPS_INS_BLTZAL: // Branch on <0 and link case MIPS_INS_BGEZAL: // Branch on >=0 and link case MIPS_INS_BLTZALL: // "likely" versions case MIPS_INS_BGEZALL: case MIPS_INS_BLTZALC: // compact versions case MIPS_INS_BLEZALC: case MIPS_INS_BGEZALC: case MIPS_INS_BGTZALC: case MIPS_INS_JIALC: case MIPS_INS_JIC: op->type = R_ANAL_OP_TYPE_CALL; op->jump = IMM(0); switch (insn->id) { case MIPS_INS_JIALC: case MIPS_INS_JIC: case MIPS_INS_BLTZALC: case MIPS_INS_BLEZALC: case MIPS_INS_BGEZALC: case MIPS_INS_BGTZALC: // compact vesions (no delay) op->delay = 0; op->fail = addr+4; break; default: op->delay = 1; op->fail = addr+8; break; } break; case MIPS_INS_LUI: case MIPS_INS_MOVE: op->type = R_ANAL_OP_TYPE_MOV; SET_SRC_DST_2_REGS (op); break; case MIPS_INS_ADD: case MIPS_INS_ADDI: case MIPS_INS_ADDU: case MIPS_INS_ADDIU: case MIPS_INS_DADD: case MIPS_INS_DADDI: case MIPS_INS_DADDIU: SET_VAL (op, 2); SET_SRC_DST_3_REG_OR_IMM (op); op->type = R_ANAL_OP_TYPE_ADD; break; case MIPS_INS_SUB: case MIPS_INS_SUBV: case MIPS_INS_SUBVI: case MIPS_INS_DSUBU: case MIPS_INS_FSUB: case MIPS_INS_FMSUB: case MIPS_INS_SUBU: case MIPS_INS_DSUB: case MIPS_INS_SUBS_S: case MIPS_INS_SUBS_U: case MIPS_INS_SUBUH: case MIPS_INS_SUBUH_R: SET_VAL (op,2); SET_SRC_DST_3_REG_OR_IMM (op); op->type = R_ANAL_OP_TYPE_SUB; break; case MIPS_INS_MULV: case MIPS_INS_MULT: case MIPS_INS_MULSA: case MIPS_INS_FMUL: case MIPS_INS_MUL: case MIPS_INS_DMULT: case MIPS_INS_DMULTU: op->type = R_ANAL_OP_TYPE_MUL; break; case MIPS_INS_XOR: case MIPS_INS_XORI: SET_VAL (op,2); SET_SRC_DST_3_REG_OR_IMM (op); op->type = R_ANAL_OP_TYPE_XOR; break; case MIPS_INS_AND: case MIPS_INS_ANDI: SET_VAL (op,2); SET_SRC_DST_3_REG_OR_IMM (op); op->type = R_ANAL_OP_TYPE_AND; break; case MIPS_INS_NOT: op->type = R_ANAL_OP_TYPE_NOT; break; case MIPS_INS_OR: case MIPS_INS_ORI: SET_VAL (op,2); SET_SRC_DST_3_REG_OR_IMM (op); op->type = R_ANAL_OP_TYPE_OR; break; case MIPS_INS_DIV: case MIPS_INS_DIVU: case MIPS_INS_DDIV: case MIPS_INS_DDIVU: case MIPS_INS_FDIV: case MIPS_INS_DIV_S: case MIPS_INS_DIV_U: SET_SRC_DST_3_REGS (op); op->type = R_ANAL_OP_TYPE_DIV; break; case MIPS_INS_CMPGDU: case MIPS_INS_CMPGU: case MIPS_INS_CMPU: case MIPS_INS_CMPI: op->type = R_ANAL_OP_TYPE_CMP; break; case MIPS_INS_J: case MIPS_INS_B: case MIPS_INS_BZ: case MIPS_INS_BEQ: case MIPS_INS_BNZ: case MIPS_INS_BNE: case MIPS_INS_BEQZ: case MIPS_INS_BNEG: case MIPS_INS_BNEGI: case MIPS_INS_BNEZ: case MIPS_INS_BTEQZ: case MIPS_INS_BTNEZ: case MIPS_INS_BLTZ: case MIPS_INS_BLTZL: case MIPS_INS_BLEZ: case MIPS_INS_BLEZL: case MIPS_INS_BGEZ: case MIPS_INS_BGEZL: case MIPS_INS_BGTZ: case MIPS_INS_BGTZL: case MIPS_INS_BLEZC: case MIPS_INS_BGEZC: case MIPS_INS_BLTZC: case MIPS_INS_BGTZC: if (insn->id == MIPS_INS_J || insn->id == MIPS_INS_B ) { op->type = R_ANAL_OP_TYPE_JMP; } else { op->type = R_ANAL_OP_TYPE_CJMP; } if (OPERAND(0).type == MIPS_OP_IMM) { op->jump = IMM(0); } else if (OPERAND(1).type == MIPS_OP_IMM) { op->jump = IMM(1); } else if (OPERAND(2).type == MIPS_OP_IMM) { op->jump = IMM(2); } switch (insn->id) { case MIPS_INS_BLEZC: case MIPS_INS_BGEZC: case MIPS_INS_BLTZC: case MIPS_INS_BGTZC: // compact vesions (no delay) op->delay = 0; op->fail = addr+4; break; default: op->delay = 1; op->fail = addr+8; break; } break; case MIPS_INS_JR: case MIPS_INS_JRC: op->type = R_ANAL_OP_TYPE_JMP; op->delay = 1; // register is $ra, so jmp is a return if (insn->detail->mips.operands[0].reg == MIPS_REG_RA) { op->type = R_ANAL_OP_TYPE_RET; } break; case MIPS_INS_SLTI: case MIPS_INS_SLTIU: SET_SRC_DST_3_IMM (op); SET_VAL (op,2); break; case MIPS_INS_SHRAV: case MIPS_INS_SHRAV_R: case MIPS_INS_SHRA: case MIPS_INS_SHRA_R: case MIPS_INS_SRA: op->type = R_ANAL_OP_TYPE_SAR; SET_SRC_DST_3_REG_OR_IMM (op); SET_VAL (op,2); break; case MIPS_INS_SHRL: case MIPS_INS_SRLV: case MIPS_INS_SRL: op->type = R_ANAL_OP_TYPE_SHR; SET_SRC_DST_3_REG_OR_IMM (op); SET_VAL (op,2); break; case MIPS_INS_SLLV: case MIPS_INS_SLL: op->type = R_ANAL_OP_TYPE_SHL; SET_SRC_DST_3_REG_OR_IMM (op); SET_VAL (op,2); break; } beach: if (anal->decode) { if (analop_esil (anal, op, addr, buf, len, &hndl, insn) != 0) r_strbuf_fini (&op->esil); } cs_free (insn, n); //cs_close (&handle); fin: return opsize; }
static int i8051_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { op->delay = 0; int i = 0; while (_8051_ops[i].string && _8051_ops[i].op != (buf[0] & ~_8051_ops[i].mask)) { i++; } op->size = _8051_ops[i].len; op->jump = op->fail = -1; op->ptr = op->val = -1; ut8 arg1 = _8051_ops[i].arg1; ut8 arg2 = _8051_ops[i].arg2; switch (arg1) { case A_DIRECT: op->ptr = buf[1]; break; case A_BIT: op->ptr = arg_bit (buf[1]); break; case A_IMMEDIATE: op->val = buf[1]; break; case A_IMM16: op->val = buf[1] * 256 + buf[2]; break; default: break; } switch (arg2) { case A_DIRECT: op->ptr = (arg1 == A_RI || arg1 == A_RN) ? buf[1] : buf[2]; break; case A_BIT: op->ptr = arg_bit ((arg1 == A_RI || arg1 == A_RN) ? buf[1] : buf[2]); break; case A_IMMEDIATE: op->val = (arg1 == A_RI || arg1 == A_RN) ? buf[1] : buf[2]; break; default: break; } switch(_8051_ops[i].instr) { case OP_PUSH: op->type = R_ANAL_OP_TYPE_PUSH; op->ptr = 0; op->stackop = R_ANAL_STACK_INC; op->stackptr = 1; break; case OP_POP: op->type = R_ANAL_OP_TYPE_POP; op->ptr = 0; op->stackop = R_ANAL_STACK_INC; op->stackptr = -1; break; case OP_RET: op->type = R_ANAL_OP_TYPE_RET; op->stackop = R_ANAL_STACK_INC; op->stackptr = -2; break; case OP_NOP: op->type = R_ANAL_OP_TYPE_NOP; break; case OP_INC: case OP_ADD: case OP_ADDC: op->type = R_ANAL_OP_TYPE_ADD; break; case OP_DEC: case OP_SUBB: op->type = R_ANAL_OP_TYPE_SUB; break; case OP_ANL: op->type = R_ANAL_OP_TYPE_AND; break; case OP_ORL: op->type = R_ANAL_OP_TYPE_OR; break; case OP_XRL: op->type = R_ANAL_OP_TYPE_XOR; break; case OP_CPL: op->type = R_ANAL_OP_TYPE_CPL; break; case OP_XCH: op->type = R_ANAL_OP_TYPE_XCHG; break; case OP_MOV: op->type = R_ANAL_OP_TYPE_MOV; break; case OP_MUL: op->type = R_ANAL_OP_TYPE_MUL; break; case OP_DIV: op->type = R_ANAL_OP_TYPE_DIV; break; case OP_CALL: op->type = R_ANAL_OP_TYPE_CALL; if (arg1 == A_ADDR11) { op->jump = arg_addr11 (addr + op->size, buf); op->fail = addr + op->size; } else if (arg1 == A_ADDR16) { op->jump = 0x100 * buf[1] + buf[2]; op->fail = addr + op->size; } break; case OP_JMP: op->type = R_ANAL_OP_TYPE_JMP; if (arg1 == A_ADDR11) { op->jump = arg_addr11 (addr + op->size, buf); op->fail = addr + op->size; } else if (arg1 == A_ADDR16) { op->jump = 0x100 * buf[1] + buf[2]; op->fail = addr + op->size; } else if (arg1 == A_OFFSET) { op->jump = arg_offset (addr + op->size, buf[1]); op->fail = addr + op->size; } break; case OP_CJNE: case OP_DJNZ: case OP_JC: case OP_JNC: case OP_JZ: case OP_JNZ: case OP_JB: case OP_JBC: case OP_JNB: op->type = R_ANAL_OP_TYPE_CJMP; if (op->size == 2) { op->jump = arg_offset (addr + 2, buf[1]); op->fail = addr + 2; } else if (op->size == 3) { op->jump = arg_offset (addr + 3, buf[2]); op->fail = addr + 3; } break; case OP_INVALID: op->type = R_ANAL_OP_TYPE_ILL; break; default: op->type = R_ANAL_OP_TYPE_UNK; break; } if (op->ptr != -1 && op->refptr == 0) { op->refptr = 1; } if (anal->decode) { ut8 copy[3] = {0, 0, 0}; memcpy (copy, buf, len >= 3 ? 3 : len); analop_esil (anal, op, addr, copy); } return op->size; }
static int h8300_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) { int ret; ut8 opcode = buf[0]; struct h8300_cmd cmd; if (!op) { return 2; } memset(op, 0, sizeof (RAnalOp)); op->addr = addr; op->jump = op->fail = -1; op->ptr = op->val = -1; ret = op->size = h8300_decode_command(buf, &cmd); if (ret < 0) { return ret; } switch (opcode >> 4) { case H8300_MOV_4BIT_2: case H8300_MOV_4BIT_3: case H8300_MOV_4BIT: op->type = R_ANAL_OP_TYPE_MOV; break; case H8300_CMP_4BIT: op->type = R_ANAL_OP_TYPE_CMP; break; case H8300_XOR_4BIT: op->type = R_ANAL_OP_TYPE_XOR; break; case H8300_AND_4BIT: op->type = R_ANAL_OP_TYPE_AND; break; case H8300_ADD_4BIT: case H8300_ADDX_4BIT: op->type = R_ANAL_OP_TYPE_AND; break; case H8300_SUBX_4BIT: op->type = R_ANAL_OP_TYPE_SUB; break; default: op->type = R_ANAL_OP_TYPE_UNK; break; }; if (op->type != R_ANAL_OP_TYPE_UNK) { analop_esil(anal, op, addr, buf); return ret; } switch (opcode) { case H8300_MOV_R82IND16: case H8300_MOV_IND162R16: case H8300_MOV_R82ABS16: case H8300_MOV_ABS162R16: case H8300_MOV_R82RDEC16: case H8300_MOV_INDINC162R16: case H8300_MOV_R82DISPR16: case H8300_MOV_DISP162R16: case H8300_MOV_IMM162R16: case H8300_MOV_1: case H8300_MOV_2: case H8300_EEPMOV: op->type = R_ANAL_OP_TYPE_MOV; break; case H8300_RTS: op->type = R_ANAL_OP_TYPE_RET; break; case H8300_CMP_1: case H8300_CMP_2: case H8300_BTST_R2R8: case H8300_BTST: op->type = R_ANAL_OP_TYPE_CMP; break; case H8300_SHL: op->type = R_ANAL_OP_TYPE_SHL; break; case H8300_SHR: op->type = R_ANAL_OP_TYPE_SHR; break; case H8300_XOR: case H8300_XORC: op->type = R_ANAL_OP_TYPE_XOR; break; case H8300_MULXU: op->type = R_ANAL_OP_TYPE_MUL; break; case H8300_ANDC: op->type = R_ANAL_OP_TYPE_AND; break; case H8300_ADDB_DIRECT: case H8300_ADDW_DIRECT: case H8300_ADDS: case H8300_ADDX: op->type = R_ANAL_OP_TYPE_ADD; break; case H8300_SUB_1: case H8300_SUBW: case H8300_SUBS: case H8300_SUBX: op->type = R_ANAL_OP_TYPE_SUB; break; case H8300_NOP: op->type = R_ANAL_OP_TYPE_NOP; break; case H8300_JSR_1: case H8300_JSR_2: case H8300_JSR_3: h8300_anal_jsr(op, addr, buf); break; case H8300_JMP_1: case H8300_JMP_2: case H8300_JMP_3: h8300_anal_jmp(op, addr, buf); break; case H8300_BRA: case H8300_BRN: case H8300_BHI: case H8300_BLS: case H8300_BCC: case H8300_BCS: case H8300_BNE: case H8300_BEQ: case H8300_BVC: case H8300_BVS: case H8300_BPL: case H8300_BMI: case H8300_BGE: case H8300_BLT: case H8300_BGT: case H8300_BLE: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = addr + 2 + (st8)(buf[1]); op->fail = addr + 2; break; default: op->type = R_ANAL_OP_TYPE_UNK; break; }; if (mask & R_ANAL_OP_MASK_ESIL) { analop_esil(anal, op, addr, buf); } return ret; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle; cs_insn *insn; int mode = (a->bits==16)? CS_MODE_THUMB: CS_MODE_ARM; int i, n, ret = (a->bits==64)? cs_open (CS_ARCH_ARM64, mode, &handle): cs_open (CS_ARCH_ARM, mode, &handle); cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); op->type = R_ANAL_OP_TYPE_NULL; op->size = (a->bits==16)? 2: 4; op->delay = 0; r_strbuf_init (&op->esil); if (ret == CS_ERR_OK) { n = cs_disasm_ex (handle, (ut8*)buf, len, addr, 1, &insn); if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { op->size = insn->size; switch (insn->id) { 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; break; case ARM_INS_ADD: op->type = R_ANAL_OP_TYPE_ADD; 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_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_PUSH: case ARM_INS_STR: //case ARM_INS_POP: case ARM_INS_LDR: op->type = R_ANAL_OP_TYPE_LOAD; 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: if (insn->detail->arm.cc) { op->type = R_ANAL_OP_TYPE_CJMP; op->jump = IMM(0); op->fail = addr+op->size; } else { op->type = R_ANAL_OP_TYPE_JMP; op->jump = IMM(0); } break; } if (a->decode) { if (!analop_esil (a, op, addr, buf, len, &handle, insn)) r_strbuf_fini (&op->esil); } cs_free (insn, n); } } cs_close (&handle); return op->size; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { int n, ret, opsize = -1; csh handle; cs_insn* insn; int mode = a->big_endian? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN; mode |= (a->bits==64)? CS_MODE_64: CS_MODE_32; // XXX no arch->cpu ?!?! CS_MODE_MICRO, N64 ret = cs_open (CS_ARCH_MIPS, mode, &handle); op->delay = 0; op->type = R_ANAL_OP_TYPE_ILL; op->size = 4; if (ret != CS_ERR_OK) goto fin; cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); n = cs_disasm (handle, (ut8*)buf, len, addr, 1, &insn); if (n<1 || insn->size<1) goto beach; op->type = R_ANAL_OP_TYPE_NULL; op->delay = 0; opsize = op->size = insn->size; switch (insn->id) { case MIPS_INS_INVALID: op->type = R_ANAL_OP_TYPE_ILL; break; case MIPS_INS_LB: case MIPS_INS_LBU: case MIPS_INS_LBUX: case MIPS_INS_LW: case MIPS_INS_LWC1: case MIPS_INS_LWC2: case MIPS_INS_LWL: case MIPS_INS_LWR: case MIPS_INS_LWXC1: case MIPS_INS_LD: case MIPS_INS_LDC1: case MIPS_INS_LDC2: case MIPS_INS_LDL: case MIPS_INS_LDR: case MIPS_INS_LDXC1: op->type = R_ANAL_OP_TYPE_LOAD; op->refptr = 4; switch (OPERAND(1).type) { case MIPS_OP_MEM: if (OPERAND(1).mem.base == MIPS_REG_GP) { op->ptr = a->gp + OPERAND(1).mem.disp; op->refptr = 4; } break; case MIPS_OP_IMM: op->ptr = OPERAND(1).imm; break; case MIPS_OP_REG: // wtf? break; default: break; } // TODO: fill break; case MIPS_INS_SW: case MIPS_INS_SWC1: case MIPS_INS_SWC2: case MIPS_INS_SWL: case MIPS_INS_SWR: case MIPS_INS_SWXC1: op->type = R_ANAL_OP_TYPE_STORE; break; case MIPS_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; break; case MIPS_INS_SYSCALL: case MIPS_INS_BREAK: op->type = R_ANAL_OP_TYPE_TRAP; break; case MIPS_INS_JALR: op->type = R_ANAL_OP_TYPE_UCALL; op->delay = 1; break; case MIPS_INS_JAL: case MIPS_INS_JALS: case MIPS_INS_JALX: case MIPS_INS_JIALC: case MIPS_INS_JIC: case MIPS_INS_JRADDIUSP: case MIPS_INS_BAL: case MIPS_INS_BGEZAL: // Branch on less than zero and link op->type = R_ANAL_OP_TYPE_CALL; op->delay = 1; op->jump = IMM(0); op->fail = addr+4; break; case MIPS_INS_MOVE: op->type = R_ANAL_OP_TYPE_MOV; break; case MIPS_INS_ADD: case MIPS_INS_ADDI: case MIPS_INS_ADDIU: case MIPS_INS_DADD: case MIPS_INS_DADDI: case MIPS_INS_DADDIU: op->type = R_ANAL_OP_TYPE_ADD; break; case MIPS_INS_SUB: case MIPS_INS_SUBV: case MIPS_INS_SUBVI: case MIPS_INS_DSUBU: case MIPS_INS_FSUB: case MIPS_INS_FMSUB: case MIPS_INS_SUBU: case MIPS_INS_DSUB: case MIPS_INS_SUBS_S: case MIPS_INS_SUBS_U: case MIPS_INS_SUBUH: case MIPS_INS_SUBUH_R: op->type = R_ANAL_OP_TYPE_SUB; break; case MIPS_INS_MULV: case MIPS_INS_MULT: case MIPS_INS_MULSA: case MIPS_INS_FMUL: case MIPS_INS_MUL: case MIPS_INS_DMULT: case MIPS_INS_DMULTU: op->type = R_ANAL_OP_TYPE_MUL; break; case MIPS_INS_XOR: case MIPS_INS_XORI: op->type = R_ANAL_OP_TYPE_XOR; break; case MIPS_INS_AND: case MIPS_INS_ANDI: op->type = R_ANAL_OP_TYPE_AND; break; case MIPS_INS_NOT: op->type = R_ANAL_OP_TYPE_NOT; break; case MIPS_INS_OR: case MIPS_INS_ORI: op->type = R_ANAL_OP_TYPE_OR; break; case MIPS_INS_DIV: case MIPS_INS_DIVU: case MIPS_INS_DDIV: case MIPS_INS_DDIVU: case MIPS_INS_FDIV: case MIPS_INS_DIV_S: case MIPS_INS_DIV_U: op->type = R_ANAL_OP_TYPE_DIV; break; case MIPS_INS_CMPGDU: case MIPS_INS_CMPGU: case MIPS_INS_CMPU: case MIPS_INS_CMPI: op->type = R_ANAL_OP_TYPE_CMP; break; case MIPS_INS_J: case MIPS_INS_B: case MIPS_INS_BZ: case MIPS_INS_BEQ: case MIPS_INS_BNZ: case MIPS_INS_BNE: case MIPS_INS_BEQZ: case MIPS_INS_BNEG: case MIPS_INS_BNEGI: case MIPS_INS_BNEZ: case MIPS_INS_BTEQZ: case MIPS_INS_BTNEZ: case MIPS_INS_BLTZ: case MIPS_INS_BGEZ: case MIPS_INS_BGEZC: case MIPS_INS_BGEZALC: op->type = R_ANAL_OP_TYPE_JMP; op->delay = 1; if (OPERAND(0).type == MIPS_OP_IMM) { op->jump = IMM(0); } else if (OPERAND(1).type == MIPS_OP_IMM) { op->jump = IMM(1); } else if (OPERAND(2).type == MIPS_OP_IMM) { op->jump = IMM(2); } break; case MIPS_INS_JR: case MIPS_INS_JRC: op->type = R_ANAL_OP_TYPE_JMP; op->delay = 1; // register 32 is $ra, so jmp is a return if (insn->detail->mips.operands[0].reg == 32) { op->type = R_ANAL_OP_TYPE_RET; } break; } beach: if (a->decode) { if (!analop_esil (a, op, addr, buf, len, &handle, insn)) r_strbuf_fini (&op->esil); } cs_free (insn, n); cs_close (&handle); fin: return opsize; }