static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle; cs_insn *insn; int mode, n, ret; mode = CS_MODE_BIG_ENDIAN; if (!strcmp (a->cpu, "v9")) mode |= CS_MODE_V9; ret = cs_open (CS_ARCH_XCORE, mode, &handle); op->type = R_ANAL_OP_TYPE_NULL; op->size = 0; op->delay = 0; r_strbuf_init (&op->esil); if (ret == CS_ERR_OK) { cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); // capstone-next n = cs_disasm (handle, (const 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 XCORE_INS_DRET: case XCORE_INS_KRET: case XCORE_INS_RETSP: op->type = R_ANAL_OP_TYPE_RET; break; case XCORE_INS_DCALL: case XCORE_INS_KCALL: case XCORE_INS_ECALLF: case XCORE_INS_ECALLT: op->type = R_ANAL_OP_TYPE_CALL; op->jump = INSOP(0).imm; break; /* ??? */ case XCORE_INS_BL: case XCORE_INS_BLA: case XCORE_INS_BLAT: case XCORE_INS_BT: case XCORE_INS_BF: case XCORE_INS_BU: case XCORE_INS_BRU: op->type = R_ANAL_OP_TYPE_CALL; op->jump = INSOP(0).imm; break; case XCORE_INS_SUB: case XCORE_INS_LSUB: op->type = R_ANAL_OP_TYPE_SUB; break; case XCORE_INS_ADD: case XCORE_INS_LADD: op->type = R_ANAL_OP_TYPE_ADD; break; } } cs_free (insn, n); cs_close (&handle); } return op->size; }
static int bf_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { ut64 dst = 0LL; if (op == NULL) return 1; /* Ayeeee! What's inside op? Do we have an initialized RAnalOp? Are we going to have a leak here? :-( */ memset (op, 0, sizeof (RAnalOp)); /* We need to refactorize this. Something like r_anal_op_init would be more appropiate */ r_strbuf_init (&op->esil); op->size = 1; switch (buf[0]) { case '[': op->type = R_ANAL_OP_TYPE_CJMP; op->fail = addr+1; { const ut8 *p = buf + 1; int lev = 0, i = 1; while (*p && i<len) { if (*p == '[') lev++; if (*p == ']') { lev--; if (lev==-1) { dst = addr + (size_t)(p-buf); op->jump = dst; r_strbuf_setf (&op->esil, "if (!*ptr) pc=0x%"PFMT64x, dst); break; } } p++; i++; } } // ?1[ptr],pc=${NEW_PC break; case ']': op->type = R_ANAL_OP_TYPE_UJMP; break; case '>': op->type = R_ANAL_OP_TYPE_ADD; r_strbuf_set (&op->esil, "ptr++"); break; case '<': op->type = R_ANAL_OP_TYPE_SUB; r_strbuf_set (&op->esil, "ptr--"); break; case '+': op->type = R_ANAL_OP_TYPE_ADD; r_strbuf_set (&op->esil, "*ptr++"); break; case '-': op->type = R_ANAL_OP_TYPE_SUB; r_strbuf_set (&op->esil, "*ptr--"); break; case '.': op->type = R_ANAL_OP_TYPE_STORE; r_strbuf_set (&op->esil, "=*ptr"); break; case ',': op->type = R_ANAL_OP_TYPE_LOAD; break; case 0x00: case 0xff: op->type = R_ANAL_OP_TYPE_TRAP; break; default: op->type = R_ANAL_OP_TYPE_NOP; break; } return op->size; }
R_API RAnalOp *r_anal_op_new () { RAnalOp *op = R_NEW0 (RAnalOp); if (!op) return NULL; op->addr = UT64_MAX; op->jump = UT64_MAX; op->fail = UT64_MAX; op->ptr = UT64_MAX; op->val = UT64_MAX; r_strbuf_init (&op->esil); return op; }
R_API RAnalOp *r_anal_op_copy (RAnalOp *op) { RAnalOp *nop = R_NEW (RAnalOp); *nop = *op; nop->mnemonic = strdup (op->mnemonic); nop->src[0] = r_anal_value_copy (op->src[0]); nop->src[1] = r_anal_value_copy (op->src[1]); nop->src[2] = r_anal_value_copy (op->src[2]); nop->dst = r_anal_value_copy (op->dst); r_strbuf_init (&nop->esil); r_strbuf_set (&nop->esil, r_strbuf_get (&op->esil)); return nop; }
R_API RAnalOp *r_anal_op_new () { RAnalOp *op = R_NEW0 (RAnalOp); if (op) { op->addr = -1; op->jump = -1; op->fail = -1; op->ptr = -1; op->val = -1; r_strbuf_init (&op->esil); } return op; }
static void opex(RStrBuf *buf, csh handle, cs_insn *insn) { int i; r_strbuf_init (buf); r_strbuf_append (buf, "{"); cs_m68k *x = &insn->detail->m68k; r_strbuf_append (buf, "\"operands\":["); for (i = 0; i < x->op_count; i++) { cs_m68k_op *op = &x->operands[i]; if (i > 0) { r_strbuf_append (buf, ","); } r_strbuf_append (buf, "{"); switch (op->type) { case M68K_OP_REG: r_strbuf_append (buf, "\"type\":\"reg\""); r_strbuf_appendf (buf, ",\"value\":\"%s\"", cs_reg_name (handle, op->reg)); break; case M68K_OP_IMM: r_strbuf_append (buf, "\"type\":\"imm\""); r_strbuf_appendf (buf, ",\"value\":%"PFMT64d, op->imm); break; case M68K_OP_MEM: r_strbuf_append (buf, "\"type\":\"mem\""); if (op->mem.base_reg != M68K_REG_INVALID) { r_strbuf_appendf (buf, ",\"base_reg\":\"%s\"", cs_reg_name (handle, op->mem.base_reg)); } if (op->mem.index_reg != M68K_REG_INVALID) { r_strbuf_appendf (buf, ",\"base_reg\":\"%s\"", cs_reg_name (handle, op->mem.index_reg)); } if (op->mem.in_base_reg != M68K_REG_INVALID) { r_strbuf_appendf (buf, ",\"base_reg\":\"%s\"", cs_reg_name (handle, op->mem.in_base_reg)); } r_strbuf_appendf (buf, ",\"in_disp\":%"PFMT64d"", op->mem.in_disp); r_strbuf_appendf (buf, ",\"out_disp\":%"PFMT64d"", op->mem.out_disp); r_strbuf_appendf (buf, ",\"disp\":%"PFMT64d"", (st64)op->mem.disp); r_strbuf_appendf (buf, ",\"scale\":%"PFMT64d"", (st64)op->mem.scale); r_strbuf_appendf (buf, ",\"bitfield\":%"PFMT64d"", (st64)op->mem.bitfield); r_strbuf_appendf (buf, ",\"width\":%"PFMT64d"", (st64)op->mem.width); r_strbuf_appendf (buf, ",\"offset\":%"PFMT64d"", (st64)op->mem.offset); r_strbuf_appendf (buf, ",\"index_size\":%"PFMT64d"", (st64)op->mem.index_size); break; default: r_strbuf_append (buf, "\"type\":\"invalid\""); break; } r_strbuf_append (buf, "}"); } r_strbuf_append (buf, "]}"); }
R_API RAnalOp *r_anal_op_copy (RAnalOp *op) { RAnalOp *nop = R_NEW0 (RAnalOp); if (!nop) return NULL; *nop = *op; if (op->mnemonic) { nop->mnemonic = strdup (op->mnemonic); if (!nop->mnemonic) { free (nop); return NULL; } } else { nop->mnemonic = NULL; } nop->src[0] = r_anal_value_copy (op->src[0]); nop->src[1] = r_anal_value_copy (op->src[1]); nop->src[2] = r_anal_value_copy (op->src[2]); nop->dst = r_anal_value_copy (op->dst); r_strbuf_init (&nop->esil); r_strbuf_set (&nop->esil, r_strbuf_get (&op->esil)); return nop; }
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 bcl_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { int i; char cache[256] = {0}; ut64 dst = 0LL; if (op == NULL) return 1; int base = *buf & 3; memset (op, 0, sizeof (RAnalOp)); r_strbuf_init (&op->esil); op->size = 1; if (*buf == 0) { op->type = R_ANAL_OP_TYPE_NOP; return 0; } switch (base) { case 0: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = addr + findpair (addr, buf, len, 3); op->fail = addr + 1; r_strbuf_setf (&op->esil, "A,++="); break; case 1: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = addr + findpair(addr, buf, len, 2); op->fail = addr + 1; r_strbuf_setf (&op->esil, "C,++="); break; case 2: op->type = R_ANAL_OP_TYPE_CMP; r_strbuf_setf (&op->esil, "G,++="); break; case 3: op->type = R_ANAL_OP_TYPE_MOV; r_strbuf_setf (&op->esil, "T,++="); break; } return op->size; }
static void opex(RStrBuf *buf, csh handle, cs_insn *insn) { int i; r_strbuf_init (buf); r_strbuf_append (buf, "{"); cs_sysz *x = &insn->detail->sysz; r_strbuf_append (buf, "\"operands\":["); for (i = 0; i < x->op_count; i++) { cs_sysz_op *op = &x->operands[i]; if (i > 0) { r_strbuf_append (buf, ","); } r_strbuf_append (buf, "{"); switch (op->type) { case SYSZ_OP_REG: r_strbuf_append (buf, "\"type\":\"reg\""); r_strbuf_appendf (buf, ",\"value\":\"%s\"", cs_reg_name (handle, op->reg)); break; case SYSZ_OP_IMM: r_strbuf_append (buf, "\"type\":\"imm\""); r_strbuf_appendf (buf, ",\"value\":%"PFMT64d, op->imm); break; case SYSZ_OP_MEM: r_strbuf_append (buf, "\"type\":\"mem\""); if (op->mem.base != SYSZ_REG_INVALID) { r_strbuf_appendf (buf, ",\"base\":\"%s\"", cs_reg_name (handle, op->mem.base)); } r_strbuf_appendf (buf, ",\"index\":%"PFMT64d"", (st64) op->mem.index); r_strbuf_appendf (buf, ",\"length\":%"PFMT64d"", (st64) op->mem.length); r_strbuf_appendf (buf, ",\"disp\":%"PFMT64d"", (st64) op->mem.disp); break; default: r_strbuf_append (buf, "\"type\":\"invalid\""); break; } r_strbuf_append (buf, "}"); } r_strbuf_append (buf, "]}"); }
R_API int r_strbuf_set(RStrBuf *sb, const char *s) { int l; if (!sb) return R_FALSE; if (!s) { r_strbuf_init (sb); return R_TRUE; } l = strlen (s); if (l>=sizeof (sb->buf)) { char *ptr = malloc (l+1); if (!ptr) return R_FALSE; free (sb->ptr); sb->ptr = ptr; memcpy (ptr, s, l+1); } else { sb->ptr = NULL; memcpy (sb->buf, s, l+1); } sb->len = l; return R_TRUE; }
R_API bool r_strbuf_set(RStrBuf *sb, const char *s) { int l; if (!sb) return false; if (!s) { r_strbuf_init (sb); return true; } l = strlen (s); if (l >= sizeof (sb->buf)) { char *ptr = sb->ptr; if (!ptr || l+1 > sb->ptrlen) { ptr = malloc (l + 1); if (!ptr) return false; sb->ptrlen = l + 1; sb->ptr = ptr; } memcpy (ptr, s, l+1); } else { sb->ptr = NULL; memcpy (sb->buf, s, l+1); } sb->len = l; return true; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { static int omode = 0; #if USE_ITER_API static #endif cs_insn *insn = NULL; int mode = (a->bits==64)? CS_MODE_64: (a->bits==32)? CS_MODE_32: (a->bits==16)? CS_MODE_16: 0; int n, ret; int regsz = 4; if (handle && mode != omode) { cs_close (&handle); handle = 0; } omode = mode; if (handle == 0) { ret = cs_open (CS_ARCH_X86, mode, &handle); if (ret != CS_ERR_OK) { handle = 0; return 0; } } #if 0 if (len>3 && !memcmp (buf, "\xff\xff\xff\xff", 4)) return 0; #endif switch (a->bits) { case 64: regsz = 8; break; case 16: regsz = 2; break; default: regsz = 4; break; // 32 } memset (op, '\0', sizeof (RAnalOp)); op->cycles = 1; // aprox op->type = R_ANAL_OP_TYPE_NULL; op->jump = UT64_MAX; op->fail = UT64_MAX; op->ptr = op->val = UT64_MAX; op->src[0] = NULL; op->src[1] = NULL; op->size = 0; op->delay = 0; r_strbuf_init (&op->esil); cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); // capstone-next #if USE_ITER_API { ut64 naddr = addr; size_t size = len; if (insn == NULL) insn = cs_malloc (handle); n = cs_disasm_iter (handle, (const uint8_t**)&buf, &size, (uint64_t*)&naddr, insn); } #else n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); #endif struct Getarg gop = { .handle = handle, .insn = insn, .bits = a->bits }; if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { int rs = a->bits/8; const char *pc = (a->bits==16)?"ip": (a->bits==32)?"eip":"rip"; const char *sp = (a->bits==16)?"sp": (a->bits==32)?"esp":"rsp"; const char *bp = (a->bits==16)?"bp": (a->bits==32)?"ebp":"rbp"; op->size = insn->size; op->family = R_ANAL_OP_FAMILY_CPU; // almost everything is CPU op->prefix = 0; switch (insn->detail->x86.prefix[0]) { case X86_PREFIX_REPNE: op->prefix |= R_ANAL_OP_PREFIX_REPNE; break; case X86_PREFIX_REP: op->prefix |= R_ANAL_OP_PREFIX_REP; break; case X86_PREFIX_LOCK: op->prefix |= R_ANAL_OP_PREFIX_LOCK; break; } switch (insn->id) { case X86_INS_FNOP: op->family = R_ANAL_OP_FAMILY_FPU; /* fallthru */ case X86_INS_NOP: case X86_INS_PAUSE: op->type = R_ANAL_OP_TYPE_NOP; if (a->decode) esilprintf (op, ","); break; case X86_INS_HLT: op->type = R_ANAL_OP_TYPE_TRAP; break; case X86_INS_FBLD: case X86_INS_FBSTP: case X86_INS_FCOMPP: case X86_INS_FDECSTP: case X86_INS_FEMMS: case X86_INS_FFREE: case X86_INS_FICOM: case X86_INS_FICOMP: case X86_INS_FINCSTP: case X86_INS_FNCLEX: case X86_INS_FNINIT: case X86_INS_FNSTCW: case X86_INS_FNSTSW: case X86_INS_FPATAN: case X86_INS_FPREM: case X86_INS_FPREM1: case X86_INS_FPTAN: #if CS_API_MAJOR >=4 case X86_INS_FFREEP: #endif case X86_INS_FRNDINT: case X86_INS_FRSTOR: case X86_INS_FNSAVE: case X86_INS_FSCALE: case X86_INS_FSETPM: case X86_INS_FSINCOS: case X86_INS_FNSTENV: case X86_INS_FXAM: case X86_INS_FXSAVE: case X86_INS_FXSAVE64: case X86_INS_FXTRACT: case X86_INS_FYL2X: case X86_INS_FYL2XP1: case X86_INS_FISTTP: case X86_INS_FSQRT: case X86_INS_FXCH: op->family = R_ANAL_OP_FAMILY_FPU; op->type = R_ANAL_OP_TYPE_STORE; break; case X86_INS_FTST: case X86_INS_FUCOMPI: case X86_INS_FUCOMI: case X86_INS_FUCOMPP: case X86_INS_FUCOMP: case X86_INS_FUCOM: op->family = R_ANAL_OP_FAMILY_FPU; op->type = R_ANAL_OP_TYPE_CMP; break; case X86_INS_FABS: op->type = R_ANAL_OP_TYPE_ABS; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FLDCW: case X86_INS_FLDENV: case X86_INS_FLDL2E: case X86_INS_FLDL2T: case X86_INS_FLDLG2: case X86_INS_FLDLN2: case X86_INS_FLDPI: case X86_INS_FLDZ: case X86_INS_FLD1: case X86_INS_FLD: op->type = R_ANAL_OP_TYPE_LOAD; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FIST: case X86_INS_FISTP: case X86_INS_FST: case X86_INS_FSTP: case X86_INS_FSTPNCE: case X86_INS_FXRSTOR: case X86_INS_FXRSTOR64: op->type = R_ANAL_OP_TYPE_STORE; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FDIV: case X86_INS_FIDIV: case X86_INS_FDIVP: case X86_INS_FDIVR: case X86_INS_FIDIVR: case X86_INS_FDIVRP: op->type = R_ANAL_OP_TYPE_DIV; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FSUBR: case X86_INS_FISUBR: case X86_INS_FSUBRP: case X86_INS_FSUB: case X86_INS_FISUB: case X86_INS_FSUBP: op->type = R_ANAL_OP_TYPE_SUB; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FMUL: case X86_INS_FIMUL: case X86_INS_FMULP: op->type = R_ANAL_OP_TYPE_MUL; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_CLI: case X86_INS_STI: op->type = R_ANAL_OP_TYPE_SWI; op->family = R_ANAL_OP_FAMILY_PRIV; break; case X86_INS_CLC: case X86_INS_STC: case X86_INS_CLAC: case X86_INS_CLGI: case X86_INS_CLTS: #if CS_API_MAJOR >= 4 case X86_INS_CLWB: #endif case X86_INS_STAC: case X86_INS_STGI: op->type = R_ANAL_OP_TYPE_MOV; break; // cmov case X86_INS_SETNE: case X86_INS_SETNO: case X86_INS_SETNP: case X86_INS_SETNS: case X86_INS_SETO: case X86_INS_SETP: case X86_INS_SETS: case X86_INS_SETL: case X86_INS_SETLE: case X86_INS_SETB: case X86_INS_SETG: case X86_INS_SETAE: case X86_INS_SETA: case X86_INS_SETBE: case X86_INS_SETE: case X86_INS_SETGE: op->type = R_ANAL_OP_TYPE_CMOV; op->family = 0; if (a->decode) { char *dst = getarg (&gop, 0, 0, NULL); switch (insn->id) { case X86_INS_SETE: esilprintf (op, "zf,%s,=", dst); break; case X86_INS_SETNE: esilprintf (op, "zf,!,%s,=", dst); break; case X86_INS_SETO: esilprintf (op, "of,%s,=", dst); break; case X86_INS_SETNO: esilprintf (op, "of,!,%s,=", dst); break; case X86_INS_SETP: esilprintf (op, "pf,%s,=", dst); break; case X86_INS_SETNP: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETS: esilprintf (op, "sf,%s,=", dst); break; case X86_INS_SETNS: esilprintf (op, "sf,!,%s,=", dst); break; case X86_INS_SETB: esilprintf (op, "cf,%s,=", dst); break; case X86_INS_SETAE: esilprintf (op, "cf,!,%s,=", dst); break; /* TODO */ #if 0 SETLE/SETNG Sets the byte in the operand to 1 if the Zero Flag is set or the Sign Flag is not equal to the Overflow Flag, otherwise sets the operand to 0. SETBE/SETNA Sets the byte in the operand to 1 if the Carry Flag or the Zero Flag is set, otherwise sets the operand to 0. SETL/SETNGE Sets the byte in the operand to 1 if the Sign Flag is not equal to the Overflow Flag, otherwise sets the operand to 0. case X86_INS_SETL: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETLE: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETG: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETA: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETBE: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETGE: esilprintf (op, "pf,!,%s,=", dst); break; break; #endif } free (dst); } break; // cmov case X86_INS_FCMOVBE: case X86_INS_FCMOVB: case X86_INS_FCMOVNBE: case X86_INS_FCMOVNB: case X86_INS_FCMOVE: case X86_INS_FCMOVNE: case X86_INS_FCMOVNU: case X86_INS_FCMOVU: op->family = R_ANAL_OP_FAMILY_FPU; op->type = R_ANAL_OP_TYPE_MOV; break; case X86_INS_CMOVA: case X86_INS_CMOVAE: case X86_INS_CMOVB: case X86_INS_CMOVBE: case X86_INS_CMOVE: case X86_INS_CMOVG: case X86_INS_CMOVGE: case X86_INS_CMOVL: case X86_INS_CMOVLE: case X86_INS_CMOVNE: case X86_INS_CMOVNO: case X86_INS_CMOVNP: case X86_INS_CMOVNS: case X86_INS_CMOVO: case X86_INS_CMOVP: case X86_INS_CMOVS: op->type = R_ANAL_OP_TYPE_CMOV; break; // mov case X86_INS_MOVSS: case X86_INS_MOV: case X86_INS_MOVAPS: case X86_INS_MOVAPD: case X86_INS_MOVZX: case X86_INS_MOVUPS: case X86_INS_MOVABS: case X86_INS_MOVHPD: case X86_INS_MOVHPS: case X86_INS_MOVLPD: case X86_INS_MOVLPS: case X86_INS_MOVBE: case X86_INS_MOVSB: case X86_INS_MOVSD: case X86_INS_MOVSQ: case X86_INS_MOVSX: case X86_INS_MOVSXD: case X86_INS_MOVSW: case X86_INS_MOVD: case X86_INS_MOVQ: case X86_INS_MOVDQ2Q: { op->type = R_ANAL_OP_TYPE_MOV; op->ptr = UT64_MAX; switch (INSOP(0).type) { case X86_OP_MEM: op->ptr = INSOP(0).mem.disp; op->refptr = INSOP(0).size; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } else { if (op->ptr < 0x1000) op->ptr = UT64_MAX; } if (a->decode) { if (op->prefix & R_ANAL_OP_PREFIX_REP) { int width = INSOP(0).size; const char *src = cs_reg_name(handle, INSOP(1).mem.base); const char *dst = cs_reg_name(handle, INSOP(0).mem.base); const char *counter = (a->bits==16)?"cx": (a->bits==32)?"ecx":"rcx"; esilprintf (op, "%s,!,?{,BREAK,},%s,NUM,%s,NUM,"\ "%s,[%d],%s,=[%d],df,?{,%d,%s,-=,%d,%s,-=,},"\ "df,!,?{,%d,%s,+=,%d,%s,+=,},%s,--=,%s," \ "?{,8,GOTO,},%s,=,%s,=", counter, src, dst, src, width, dst, width, width, src, width, dst, width, src, width, dst, counter, counter, dst, src); } else { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, NULL); esilprintf (op, "%s,%s", src, dst); free (src); free (dst); } } break; case X86_OP_REG: { char *dst = getarg (&gop, 0, 0, NULL); op->dst = r_anal_value_new (); op->dst->reg = r_reg_get (a->reg, dst, R_REG_TYPE_GPR); op->src[0] = r_anal_value_new (); if (INSOP(1).type == X86_OP_MEM) { op->src[0]->delta = INSOP(1).mem.disp; } free (dst); } default: if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,=", src, dst); free (src); free (dst); } break; } if (op->refptr<1 || op->ptr == UT64_MAX) { switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; if (INSOP(1).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_GET; op->stackptr = regsz; } break; case X86_OP_IMM: if (INSOP(1).imm > 10) op->ptr = INSOP(1).imm; break; default: break; } } } break; case X86_INS_ROL: case X86_INS_RCL: // TODO: RCL Still does not work as intended // - Set flags op->type = R_ANAL_OP_TYPE_ROL; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,<<<,%s,=", src, dst, dst); free (src); free (dst); } break; case X86_INS_ROR: case X86_INS_RCR: // TODO: RCR Still does not work as intended // - Set flags op->type = R_ANAL_OP_TYPE_ROR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,>>>,%s,=", src, dst, dst); free (src); free (dst); } break; case X86_INS_SHL: case X86_INS_SHLD: case X86_INS_SHLX: // TODO: Set CF: Carry flag is the last bit shifted out due to // this operation. It is undefined for SHL and SHR where the // number of bits shifted is greater than the size of the // destination. op->type = R_ANAL_OP_TYPE_SHL; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "<<"); esilprintf (op, "%s,%s,$z,zf,=,$p,pf,=,$s,sf,=", src, dst); free (src); free (dst); } break; case X86_INS_SAR: case X86_INS_SARX: // TODO: Set CF. See case X86_INS_SHL for more details. op->type = R_ANAL_OP_TYPE_SAR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, ">>"); esilprintf (op, "%s,%s,$z,zf,=,$p,pf,=,$s,sf,=", src, dst); free (src); free (dst); } break; case X86_INS_SAL: // TODO: Set CF: See case X86_INS_SAL for more details. op->type = R_ANAL_OP_TYPE_SAL; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "<<"); esilprintf (op, "%s,%s,$z,zf,=,$p,pf,=,$s,sf,=", src, dst); free (src); free (dst); } break; case X86_INS_SALC: op->type = R_ANAL_OP_TYPE_SAL; if (a->decode) { esilprintf (op, "$z,DUP,zf,=,al,="); } break; case X86_INS_SHR: case X86_INS_SHRD: case X86_INS_SHRX: // TODO: Set CF: See case X86_INS_SAL for more details. op->type = R_ANAL_OP_TYPE_SHR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,>>=,$z,zf,=,$p,pf,=,$s,sf,=", src, dst); free (src); free (dst); } break; case X86_INS_CMP: case X86_INS_CMPPD: case X86_INS_CMPPS: case X86_INS_CMPSW: case X86_INS_CMPSD: case X86_INS_CMPSQ: case X86_INS_CMPSB: case X86_INS_CMPSS: case X86_INS_TEST: if (insn->id == X86_INS_TEST) { op->type = R_ANAL_OP_TYPE_ACMP; //compare via and if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "0,%s,%s,&,==,$z,zf,=,$p,pf,=,$s,sf,=,0,cf,=,0,of,=", src, dst); free (src); free (dst); } } else { op->type = R_ANAL_OP_TYPE_CMP; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,==,$z,zf,=,$b%d,cf,=,$p,pf,=,$s,sf,=", src, dst, (INSOP(0).size*8)); free (src); free (dst); } } switch (INSOP(0).type) { case X86_OP_MEM: op->ptr = INSOP(0).mem.disp; op->refptr = INSOP(0).size; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } op->ptr = INSOP(1).imm; break; default: switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; if (INSOP(1).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } break; case X86_OP_IMM: op->ptr = INSOP(1).imm; break; default: break; } break; } break; case X86_INS_LEA: op->type = R_ANAL_OP_TYPE_LEA; if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); char *dst = getarg (&gop, 1, 2, NULL); esilprintf (op, "%s,%s,=", dst, src); free (src); free (dst); } switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; switch (INSOP(1).mem.base) { case X86_REG_RIP: op->ptr += addr + op->size; break; case X86_REG_RBP: case X86_REG_EBP: op->stackop = R_ANAL_STACK_GET; op->stackptr = regsz; break; default: /* unhandled */ break; } break; case X86_OP_IMM: if (INSOP(1).imm > 10) op->ptr = INSOP(1).imm; break; default: break; } break; case X86_INS_ENTER: case X86_INS_PUSH: case X86_INS_PUSHAW: case X86_INS_PUSHAL: case X86_INS_PUSHF: { char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%d,%s,-=,%s,%s,=[%d]", rs, sp, dst, sp, rs); free (dst); } switch (INSOP(0).type) { case X86_OP_IMM: op->ptr = INSOP(0).imm; op->type = R_ANAL_OP_TYPE_PUSH; break; default: op->type = R_ANAL_OP_TYPE_UPUSH; break; } op->stackop = R_ANAL_STACK_INC; op->stackptr = regsz; break; case X86_INS_LEAVE: op->type = R_ANAL_OP_TYPE_POP; if (a->decode) { esilprintf (op, "%s,%s,=,%s,[%d],%s,=,%d,%s,+=", bp, sp, sp, rs, bp, rs, sp); } op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_POP: case X86_INS_POPF: case X86_INS_POPAW: case X86_INS_POPAL: case X86_INS_POPCNT: op->type = R_ANAL_OP_TYPE_POP; if (a->decode) { char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,[%d],%s,=,%d,%s,+=", sp, rs, dst, rs, sp); free (dst); } op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_RET: case X86_INS_RETF: case X86_INS_RETFQ: case X86_INS_IRET: case X86_INS_IRETD: case X86_INS_IRETQ: case X86_INS_SYSRET: op->type = R_ANAL_OP_TYPE_RET; if (a->decode) esilprintf (op, "%s,[%d],%s,=,%d,%s,+=", sp, rs, pc, rs, sp); op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_INT3: if (a->decode) esilprintf (op, "3,$"); op->type = R_ANAL_OP_TYPE_TRAP; // TRAP break; case X86_INS_INT1: if (a->decode) esilprintf (op, "1,$"); op->type = R_ANAL_OP_TYPE_SWI; // TRAP break; case X86_INS_INT: if (a->decode) esilprintf (op, "%d,$", R_ABS((int)INSOP(0).imm)); op->type = R_ANAL_OP_TYPE_SWI; break; case X86_INS_SYSCALL: op->type = R_ANAL_OP_TYPE_SWI; break; case X86_INS_INTO: case X86_INS_VMCALL: case X86_INS_VMMCALL: op->type = R_ANAL_OP_TYPE_TRAP; if (a->decode) esilprintf (op, "%d,$", (int)INSOP(0).imm); break; case X86_INS_JL: case X86_INS_JLE: case X86_INS_JA: case X86_INS_JAE: case X86_INS_JB: case X86_INS_JBE: case X86_INS_JCXZ: case X86_INS_JECXZ: case X86_INS_JRCXZ: case X86_INS_JO: case X86_INS_JNO: case X86_INS_JS: case X86_INS_JNS: case X86_INS_JP: case X86_INS_JNP: case X86_INS_JE: case X86_INS_JNE: case X86_INS_JG: case X86_INS_JGE: case X86_INS_LOOP: case X86_INS_LOOPE: case X86_INS_LOOPNE: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = INSOP(0).imm; op->fail = addr+op->size; const char *cnt = (a->bits==16)?"cx":(a->bits==32)?"ecx":"rcx"; if (a->decode) { char *dst = getarg (&gop, 0, 2, NULL); switch (insn->id) { case X86_INS_JL: esilprintf (op, "of,sf,^,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JLE: esilprintf (op, "of,sf,^,zf,|,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JA: esilprintf (op, "cf,zf,|,!,?{,%s,%s,=,}",dst, pc); break; case X86_INS_JAE: esilprintf (op, "cf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JB: esilprintf (op, "cf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JO: esilprintf (op, "of,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNO: esilprintf (op, "of,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JE: esilprintf (op, "zf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JGE: esilprintf (op, "of,!,sf,^,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNE: esilprintf (op, "zf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JG: esilprintf (op, "sf,of,!,^,zf,!,&,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JS: esilprintf (op, "sf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNS: esilprintf (op, "sf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JP: esilprintf (op, "pf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNP: esilprintf (op, "pf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JBE: esilprintf (op, "zf,cf,|,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JCXZ: esilprintf (op, "cx,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JECXZ: esilprintf (op, "ecx,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JRCXZ: esilprintf (op, "rcx,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_LOOP: esilprintf (op, "1,%s,-=,%s,?{,%s,%s,=,}", cnt, cnt, dst, pc); break; case X86_INS_LOOPE: esilprintf (op, "1,%s,-=,%s,?{,zf,?{,%s,%s,=,},}", cnt, cnt, dst, pc); break; case X86_INS_LOOPNE: esilprintf (op, "1,%s,-=,%s,?{,zf,!,?{,%s,%s,=,},}", cnt, cnt, dst, pc); break; } free (dst); } break; case X86_INS_CALL: case X86_INS_LCALL: switch (INSOP(0).type) { case X86_OP_IMM: op->type = R_ANAL_OP_TYPE_CALL; // TODO: what if UCALL? // TODO: use imm_size op->jump = INSOP(0).imm; op->fail = addr+op->size; break; case X86_OP_MEM: op->type = R_ANAL_OP_TYPE_UCALL; op->jump = UT64_MAX; if (INSOP(0).mem.base == 0) { op->ptr = INSOP(0).mem.disp; } break; default: op->type = R_ANAL_OP_TYPE_UCALL; op->jump = UT64_MAX; break; } if (a->decode) { char* arg = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s," "%d,%s,-=,%s," "=[]," "%s,%s,=", pc, rs, sp, sp, arg, pc); free (arg); } break; case X86_INS_JMP: case X86_INS_LJMP: if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,=", src, pc); free (src); } // TODO: what if UJMP? switch (INSOP(0).type) { case X86_OP_IMM: op->jump = INSOP(0).imm; op->type = R_ANAL_OP_TYPE_JMP; if (a->decode) { ut64 dst = INSOP(0).imm; esilprintf (op, "0x%"PFMT64x",%s,=", dst, pc); } break; case X86_OP_MEM: op->type = R_ANAL_OP_TYPE_UJMP; op->ptr = INSOP(0).mem.disp; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; op->refptr = 8; } else { cs_x86_op in = INSOP(0); if (in.mem.index == 0 && in.mem.base == 0 && in.mem.scale == 1) { if (a->decode) { esilprintf (op, "0x%"PFMT64x",[],%s,=", op->ptr, pc); } } } break; case X86_OP_REG: { char *src = getarg (&gop, 0, 0, NULL); op->src[0] = r_anal_value_new (); op->src[0]->reg = r_reg_get (a->reg, src, R_REG_TYPE_GPR); free (src); //XXX fallthrough } case X86_OP_FP: default: // other? op->type = R_ANAL_OP_TYPE_UJMP; op->ptr = UT64_MAX; break; } break; case X86_INS_IN: case X86_INS_INSW: case X86_INS_INSD: case X86_INS_INSB: op->type = R_ANAL_OP_TYPE_IO; op->type2 = 0; break; case X86_INS_OUT: case X86_INS_OUTSB: case X86_INS_OUTSD: case X86_INS_OUTSW: op->type = R_ANAL_OP_TYPE_IO; op->type2 = 1; break; case X86_INS_VXORPD: case X86_INS_VXORPS: case X86_INS_VPXORD: case X86_INS_VPXORQ: case X86_INS_VPXOR: case X86_INS_XORPS: case X86_INS_KXORW: case X86_INS_PXOR: case X86_INS_XOR: op->type = R_ANAL_OP_TYPE_XOR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "^"); esilprintf (op, "%s,%s,$z,zf,=,$p,pf,=,$s,sf,=,0,cf,=,0,of,=", src, dst); free (src); free (dst); } break; case X86_INS_OR: // The OF and CF flags are cleared; the SF, ZF, and PF flags are // set according to the result. The state of the AF flag is // undefined. op->type = R_ANAL_OP_TYPE_OR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,|=,0,of,=,0,cf,=,$s,sf,=,$z,zf,=,$p,pf,=", src, dst); free (src); free (dst); } break; case X86_INS_INC: // The CF flag is not affected. The OF, SF, ZF, AF, and PF flags // are set according to the result. op->type = R_ANAL_OP_TYPE_ADD; op->val = 1; if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); if (strchr (src, '[')) { char *dst = r_str_replace (strdup (src), "[", "=[", 1); esilprintf (op, "1,%s,++,%s,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=", src, dst); free (dst); } else { esilprintf (op, "%s,++=,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=", src); } free (src); } break; case X86_INS_DEC: // The CF flag is not affected. The OF, SF, ZF, AF, and PF flags // are set according to the result. op->type = R_ANAL_OP_TYPE_SUB; op->val = 1; if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); //esilprintf (op, "%s,--=,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=", src); esilprintf (op, "1,%s,[4],-,%s,=[4],$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=", src, src); free (src); } break; case X86_INS_PSUBB: case X86_INS_PSUBW: case X86_INS_PSUBD: case X86_INS_PSUBQ: case X86_INS_PSUBSB: case X86_INS_PSUBSW: case X86_INS_PSUBUSB: case X86_INS_PSUBUSW: op->type = R_ANAL_OP_TYPE_SUB; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "-"); esilprintf (op, "%s,%s", src, dst); free(src); free(dst); } break; case X86_INS_SUB: op->type = R_ANAL_OP_TYPE_SUB; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "-"); // Set OF, SF, ZF, AF, PF, and CF flags. // We use $b rather than $c here as the carry flag really // represents a "borrow" esilprintf (op, "%s,%s,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=,$b,cf,=", src, dst); free (src); free (dst); } if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) { if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) { op->stackop = R_ANAL_STACK_INC; op->stackptr = INSOP(1).imm; } } break; case X86_INS_SBB: // dst = dst - (src + cf) op->type = R_ANAL_OP_TYPE_SUB; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "cf,%s,+,%s,-=,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=,$b,cf,=", src, dst); free (src); free (dst); } break; case X86_INS_LIDT: op->type = R_ANAL_OP_TYPE_LOAD; op->family = R_ANAL_OP_FAMILY_PRIV; break; case X86_INS_SIDT: op->type = R_ANAL_OP_TYPE_STORE; op->family = R_ANAL_OP_FAMILY_PRIV; break; case X86_INS_RDRAND: case X86_INS_RDSEED: case X86_INS_RDMSR: case X86_INS_RDPMC: case X86_INS_RDTSC: case X86_INS_RDTSCP: case X86_INS_CRC32: case X86_INS_SHA1MSG1: case X86_INS_SHA1MSG2: case X86_INS_SHA1NEXTE: case X86_INS_SHA1RNDS4: case X86_INS_SHA256MSG1: case X86_INS_SHA256MSG2: case X86_INS_SHA256RNDS2: case X86_INS_AESDECLAST: case X86_INS_AESDEC: case X86_INS_AESENCLAST: case X86_INS_AESENC: case X86_INS_AESIMC: case X86_INS_AESKEYGENASSIST: // AES instructions op->family = R_ANAL_OP_FAMILY_CRYPTO; op->type = R_ANAL_OP_TYPE_MOV; // XXX break; case X86_INS_AND: case X86_INS_ANDN: case X86_INS_ANDPD: case X86_INS_ANDPS: case X86_INS_ANDNPD: case X86_INS_ANDNPS: op->type = R_ANAL_OP_TYPE_AND; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "&"); esilprintf (op, "%s,%s,0,of,=,0,cf,=,$z,zf,=,$s,sf,=,$o,pf,=", src, dst); free (src); free (dst); } break; case X86_INS_IDIV: op->type = R_ANAL_OP_TYPE_DIV; if (a->decode) { char *a0 = getarg (&gop, 0, 0, NULL); char *a1 = getarg (&gop, 1, 0, NULL); char *a2 = getarg (&gop, 2, 0, NULL); // TODO update flags & handle signedness if (!a2 && !a1) { // TODO: IDIV rbx not implemented. this is just a workaround // http://www.tptp.cc/mirrors/siyobik.info/instruction/IDIV.html // Divides (signed) the value in the AX, DX:AX, or EDX:EAX registers (dividend) by the source operand (divisor) and stores the result in the AX (AH:AL), DX:AX, or EDX:EAX registers. The source operand can be a general-purpose register or a memory location. The action of this instruction depends on the operand size (dividend/divisor), as shown in the following table: // IDIV RBX == RDX:RAX /= RBX esilprintf (op, "%s,%s,/=", a0, "rax"); } else { esilprintf (op, "%s,%s,/,%s,=", a2, a1, a0); } free (a0); free (a1); free (a2); } break; case X86_INS_DIV: op->type = R_ANAL_OP_TYPE_DIV; if (a->decode) { int width = INSOP(0).size; char *dst = getarg (&gop, 0, 0, NULL); const char *r_ax = (width==2)?"ax": (width==4)?"eax":"rax"; const char *r_dx = (width==2)?"dx": (width==4)?"edx":"rdx"; // TODO update flags & handle signedness esilprintf (op, "%s,%s,%%,%s,=,%s,%s,/,%s,=", dst, r_ax, r_dx, dst, r_ax, r_ax); free (dst); } break; case X86_INS_IMUL: op->type = R_ANAL_OP_TYPE_MUL; if (a->decode) { char *a0 = getarg (&gop, 0, 0, NULL); char *a1 = getarg (&gop, 1, 0, NULL); char *a2 = getarg (&gop, 2, 0, NULL); if (a2) { // TODO update flags & handle signedness esilprintf (op, "%s,%s,*,%s,=", a2, a1, a0); free (a2); } else { if (a1) { esilprintf (op, "%s,%s,*=", a1, a0); } else { esilprintf (op, "%s,%s,*=", a0, "rax"); } } free (a0); free (a1); } break; case X86_INS_MUL: case X86_INS_MULX: case X86_INS_MULPD: case X86_INS_MULPS: case X86_INS_MULSD: case X86_INS_MULSS: op->type = R_ANAL_OP_TYPE_MUL; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "*"); if (!src && dst) { switch (dst[0]) { case 'r': src = strdup ("rax"); break; case 'e': src = strdup ("eax"); break; default: src = strdup ("al"); break; } } esilprintf (op, "%s,%s", src, dst); free (src); free (dst); } break; case X86_INS_PACKSSDW: case X86_INS_PACKSSWB: case X86_INS_PACKUSWB: op->type = R_ANAL_OP_TYPE_MOV; op->family = R_ANAL_OP_FAMILY_MMX; break; case X86_INS_PADDB: case X86_INS_PADDD: case X86_INS_PADDW: case X86_INS_PADDSB: case X86_INS_PADDSW: case X86_INS_PADDUSB: case X86_INS_PADDUSW: op->type = R_ANAL_OP_TYPE_ADD; op->family = R_ANAL_OP_FAMILY_MMX; break; case X86_INS_XCHG: op->type = R_ANAL_OP_TYPE_MOV; op->family = R_ANAL_OP_FAMILY_CPU; { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, NULL); esilprintf (op, "%s,%s,%s,=,%s,=", src, dst, src, dst); free (src); free (dst); } break; case X86_INS_XADD: /* xchg + add */ op->type = R_ANAL_OP_TYPE_ADD; op->family = R_ANAL_OP_FAMILY_CPU; { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, NULL); if (src == dst) { esilprintf (op, "%s,%s,+,%s", src, dst, dst); } else { esilprintf (op, "%s,%s,%s,=,%s,=," "%s,%s,+,%s", src, dst, src, dst, src, dst, dst); } free (src); free (dst); } break; case X86_INS_FADD: case X86_INS_FADDP: op->family = R_ANAL_OP_FAMILY_FPU; /* pass thru */ case X86_INS_ADDPS: case X86_INS_ADDSD: case X86_INS_ADDSS: case X86_INS_ADDSUBPD: case X86_INS_ADDSUBPS: case X86_INS_ADDPD: // The OF, SF, ZF, AF, CF, and PF flags are set according to the // result. op->type = R_ANAL_OP_TYPE_ADD; if (a->decode) { if (INSOP(0).type == X86_OP_MEM) { char *src = getarg (&gop, 1, 0, NULL); char *src2 = getarg (&gop, 0, 0, NULL); char *dst = getarg (&gop, 0, 1, NULL); esilprintf (op, "%s,%s,+,%s", src, src2, dst); free (src); free (src2); free (dst); } else { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "+"); esilprintf (op, "%s,%s", src, dst); free (src); free (dst); } } if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) { if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) { op->stackop = R_ANAL_STACK_INC; op->stackptr = -INSOP(1).imm; } } break; case X86_INS_ADD: // The OF, SF, ZF, AF, CF, and PF flags are set according to the // result. op->type = R_ANAL_OP_TYPE_ADD; if (a->decode) { if (INSOP(0).type == X86_OP_MEM) { char *src = getarg (&gop, 1, 0, NULL); char *src2 = getarg (&gop, 0, 0, NULL); char *dst = getarg (&gop, 0, 1, NULL); esilprintf (op, "%s,%s,+,%s,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=,$c,cf,=", src, src2, dst); free (src); free (src2); free (dst); } else { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "+"); esilprintf (op, "%s,%s,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=,$c,cf,=", src, dst); free (src); free (dst); } } if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) { if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) { op->stackop = R_ANAL_STACK_INC; op->stackptr = -INSOP(1).imm; } } break; case X86_INS_ADC: op->type = R_ANAL_OP_TYPE_ADD; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); // dst = dst + src + cf // NOTE: We would like to add the carry first before adding the // source to ensure that the flag computation from $c belongs // to the operation of adding dst += src rather than the one // that adds carry (as esil only keeps track of the last // addition to set the flags). esilprintf (op, "cf,%s,+,%s,+=,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=,$c,cf,=", src, dst); free (src); free (dst); } break; /* Direction flag */ case X86_INS_CLD: op->type = R_ANAL_OP_TYPE_MOV; if (a->decode) esilprintf (op, "0,df,="); break; case X86_INS_STD: op->type = R_ANAL_OP_TYPE_MOV; if (a->decode) esilprintf (op, "1,df,="); break; } switch (insn->id) { case X86_INS_MOVAPS: //cvtss2sd case X86_INS_ADDSD: //cvtss2sd case X86_INS_SUBSD: //cvtss2sd case X86_INS_MULSD: //cvtss2sd case X86_INS_CVTSS2SD: //cvtss2sd case X86_INS_MOVSS: case X86_INS_MOVSD: op->family = R_ANAL_OP_FAMILY_MMX; break; } } //#if X86_GRP_PRIVILEGE>0 if (insn) { #if HAVE_CSGRP_PRIVILEGE if (cs_insn_group (handle, insn, X86_GRP_PRIVILEGE)) op->family = R_ANAL_OP_FAMILY_PRIV; #endif #if !USE_ITER_API cs_free (insn, n); #endif } //cs_close (&handle); return op->size; }
static int nios2_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len) { if (op == NULL) return 1; /* Ayeeee! What's inside op? Do we have an initialized RAnalOp? Are we going to have a leak here? :-( */ memset (op, 0, sizeof (RAnalOp)); /* We need to refactorize this. Something like r_anal_op_init would be more appropiate */ r_strbuf_init (&op->esil); op->size = 4; if ((b[0]&0xff) == 0x3a) { // XXX op->type = R_ANAL_OP_TYPE_RET; } else if ((b[0]&0xf) == 0xa) { op->type = R_ANAL_OP_TYPE_JMP; } else if ((b[0]&0xf) == 4) { op->type = R_ANAL_OP_TYPE_ADD; } else if ((b[0]&0xf) == 5) { op->type = R_ANAL_OP_TYPE_STORE; } else if ((b[0]&0xf) == 6) { // blt, r19, r5, 0x8023480 op->type = R_ANAL_OP_TYPE_CJMP; // TODO: address } else if ((b[0]&0xf) == 7) { // blt, r19, r5, 0x8023480 op->type = R_ANAL_OP_TYPE_LOAD; // TODO: address } else switch (b[0]) { case 0x3a: if (b[1]>=0xa0 && b[1]<=0xaf && b[3]==0x3d) { op->type = R_ANAL_OP_TYPE_TRAP; } else if ((b[1]>=0xe0&&b[1]<=0xe7) && b[2]==0x3e && !b[3]) { // nextpc ra op->type = R_ANAL_OP_TYPE_RET; } break; case 0x01: // jmpi op->type = R_ANAL_OP_TYPE_JMP; break; case 0x00: case 0x20: case 0x40: case 0x80: case 0xc0: // op->type = R_ANAL_OP_TYPE_CALL; break; case 0x26: // beq break; case 0x07: case 0x47: case 0x87: case 0xc7: // ldb op->type = R_ANAL_OP_TYPE_LOAD; break; case 0x0d: case 0x2d: case 0x4d: case 0x8d: case 0xcd: // sth && sthio op->type = R_ANAL_OP_TYPE_LOAD; break; case 0x06: case 0x46: case 0x86: case 0xc6: // br op->type = R_ANAL_OP_TYPE_CALL; break; } return op->size; }
static int bf_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { ut64 dst = 0LL; if (op == NULL) return 1; /* Ayeeee! What's inside op? Do we have an initialized RAnalOp? Are we going to have a leak here? :-( */ memset (op, 0, sizeof (RAnalOp)); /* We need to refactorize this. Something like r_anal_op_init would be more appropiate */ r_strbuf_init (&op->esil); op->size = 1; switch (buf[0]) { case '[': op->type = R_ANAL_OP_TYPE_CJMP; op->fail = addr+1; { const ut8 *p = buf + 1; int lev = 0, i = 1; while (*p && i<len) { if (*p == '[') lev++; if (*p == ']') { lev--; if (lev==-1) { dst = addr + (size_t)(p-buf); dst ++; op->jump = dst; r_strbuf_setf (&op->esil, "pc,brk,=[1],brk,++=," "ptr,[1],!,?{,0x%"PFMT64x",pc,=,}", dst); break; } } p++; i++; } } // ?1[ptr],pc=${NEW_PC break; case ']': op->type = R_ANAL_OP_TYPE_UJMP; // XXX This is wrong esil r_strbuf_set (&op->esil, "brk,--=,brk,[1],pc,="); break; case '>': op->type = R_ANAL_OP_TYPE_ADD; r_strbuf_set (&op->esil, "ptr,++="); break; case '<': op->type = R_ANAL_OP_TYPE_SUB; r_strbuf_set (&op->esil, "ptr,--="); break; case '+': op->size = countChar (buf, len, '+'); op->type = R_ANAL_OP_TYPE_ADD; r_strbuf_setf (&op->esil, "ptr,[1],%d,+,ptr,=[1]", op->size); break; case '-': op->type = R_ANAL_OP_TYPE_SUB; op->size = countChar (buf, len, '-'); r_strbuf_setf (&op->esil, "ptr,[1],%d,-,ptr,=[1]", op->size); break; case '.': // print element in stack to screen op->type = R_ANAL_OP_TYPE_STORE; r_strbuf_set (&op->esil, "ptr,[1],scr,=[1],scr,++="); break; case ',': op->type = R_ANAL_OP_TYPE_LOAD; r_strbuf_set (&op->esil, "kbd,[1],ptr,=[1],kbd,++="); break; case 0x00: case 0xff: op->type = R_ANAL_OP_TYPE_TRAP; break; default: op->type = R_ANAL_OP_TYPE_NOP; r_strbuf_set (&op->esil, ","); break; } return op->size; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { static int omode = 0; #if USE_ITER_API static #endif cs_insn *insn = NULL; int mode = (a->bits==64)? CS_MODE_64: (a->bits==32)? CS_MODE_32: (a->bits==16)? CS_MODE_16: 0; int n, ret; int regsz = 4; if (handle && mode != omode) { cs_close (&handle); handle = 0; } omode = mode; if (handle == 0) { ret = cs_open (CS_ARCH_X86, mode, &handle); if (ret != CS_ERR_OK) { handle = 0; return 0; } } switch (a->bits) { case 64: regsz = 8; break; case 16: regsz = 2; break; default: case 32: regsz = 4; break; } memset (op, '\0', sizeof (RAnalOp)); op->cycles = 1; // aprox op->type = R_ANAL_OP_TYPE_NULL; op->jump = UT64_MAX; op->fail = UT64_MAX; op->ptr = op->val = UT64_MAX; op->src[0] = NULL; op->src[1] = NULL; op->size = 0; op->delay = 0; r_strbuf_init (&op->esil); cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); // capstone-next #if USE_ITER_API { ut64 naddr = addr; size_t size = len; if (insn == NULL) insn = cs_malloc (handle); n = cs_disasm_iter (handle, (const uint8_t**)&buf, &size, (uint64_t*)&naddr, insn); } #else n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); #endif struct Getarg gop = { .handle = handle, .insn = insn, .bits = a->bits }; if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { int rs = a->bits/8; const char *pc = (a->bits==16)?"ip": (a->bits==32)?"eip":"rip"; const char *sp = (a->bits==16)?"sp": (a->bits==32)?"esp":"rsp"; const char *bp = (a->bits==16)?"bp": (a->bits==32)?"ebp":"rbp"; op->size = insn->size; op->family = 0; op->prefix = 0; switch (insn->detail->x86.prefix[0]) { case X86_PREFIX_REPNE: op->prefix |= R_ANAL_OP_PREFIX_REPNE; break; case X86_PREFIX_REP: op->prefix |= R_ANAL_OP_PREFIX_REP; break; case X86_PREFIX_LOCK: op->prefix |= R_ANAL_OP_PREFIX_LOCK; break; } switch (insn->id) { case X86_INS_FNOP: case X86_INS_NOP: case X86_INS_PAUSE: op->type = R_ANAL_OP_TYPE_NOP; if (a->decode) esilprintf (op, ","); break; case X86_INS_HLT: op->type = R_ANAL_OP_TYPE_TRAP; break; case X86_INS_FBLD: case X86_INS_FBSTP: case X86_INS_FCOMPP: case X86_INS_FDECSTP: case X86_INS_FEMMS: case X86_INS_FFREE: case X86_INS_FICOM: case X86_INS_FICOMP: case X86_INS_FINCSTP: case X86_INS_FNCLEX: case X86_INS_FNINIT: case X86_INS_FNSTCW: case X86_INS_FNSTSW: case X86_INS_FPATAN: case X86_INS_FPREM: case X86_INS_FPREM1: case X86_INS_FPTAN: #if CS_API_MAJOR >=4 case X86_INS_FFREEP: #endif case X86_INS_FRNDINT: case X86_INS_FRSTOR: case X86_INS_FNSAVE: case X86_INS_FSCALE: case X86_INS_FSETPM: case X86_INS_FSINCOS: case X86_INS_FNSTENV: case X86_INS_FXAM: case X86_INS_FXSAVE: case X86_INS_FXSAVE64: case X86_INS_FXTRACT: case X86_INS_FYL2X: case X86_INS_FYL2XP1: case X86_INS_FISTTP: case X86_INS_FSQRT: case X86_INS_FXCH: case X86_INS_FTST: case X86_INS_FUCOMPI: case X86_INS_FUCOMI: case X86_INS_FUCOMPP: case X86_INS_FUCOMP: case X86_INS_FUCOM: op->type = R_ANAL_OP_TYPE_SUB; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FLDCW: case X86_INS_FLDENV: case X86_INS_FLDL2E: case X86_INS_FLDL2T: case X86_INS_FLDLG2: case X86_INS_FLDLN2: case X86_INS_FLDPI: case X86_INS_FLDZ: case X86_INS_FLD1: case X86_INS_FLD: op->type = R_ANAL_OP_TYPE_LOAD; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FIST: case X86_INS_FISTP: case X86_INS_FST: case X86_INS_FSTP: case X86_INS_FSTPNCE: case X86_INS_FXRSTOR: case X86_INS_FXRSTOR64: op->type = R_ANAL_OP_TYPE_STORE; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FDIV: case X86_INS_FIDIV: case X86_INS_FDIVP: case X86_INS_FDIVR: case X86_INS_FIDIVR: case X86_INS_FDIVRP: case X86_INS_FSUBR: case X86_INS_FISUBR: case X86_INS_FSUBRP: case X86_INS_FSUB: case X86_INS_FISUB: case X86_INS_FSUBP: op->type = R_ANAL_OP_TYPE_SUB; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FMUL: case X86_INS_FIMUL: case X86_INS_FMULP: op->type = R_ANAL_OP_TYPE_MUL; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_CLI: case X86_INS_STI: op->type = R_ANAL_OP_TYPE_SWI; op->family = R_ANAL_OP_FAMILY_PRIV; break; case X86_INS_CLC: case X86_INS_STC: case X86_INS_CLAC: case X86_INS_CLGI: case X86_INS_CLTS: case X86_INS_CLWB: case X86_INS_STAC: case X86_INS_STGI: op->type = R_ANAL_OP_TYPE_MOV; op->family = R_ANAL_OP_FAMILY_CPU; break; // cmov case X86_INS_SETNE: case X86_INS_SETNO: case X86_INS_SETNP: case X86_INS_SETNS: case X86_INS_SETO: case X86_INS_SETP: case X86_INS_SETS: case X86_INS_SETL: case X86_INS_SETLE: case X86_INS_SETB: case X86_INS_SETG: case X86_INS_SETAE: case X86_INS_SETA: case X86_INS_SETBE: case X86_INS_SETE: case X86_INS_SETGE: op->type = R_ANAL_OP_TYPE_CMOV; op->family = 0; if (a->decode) { char *dst = getarg (&gop, 0, 0, NULL); switch (insn->id) { case X86_INS_SETE: esilprintf (op, "zf,%s,=", dst); break; case X86_INS_SETNE: esilprintf (op, "zf,!,%s,=", dst); break; case X86_INS_SETO: esilprintf (op, "of,%s,=", dst); break; case X86_INS_SETNO: esilprintf (op, "of,!,%s,=", dst); break; case X86_INS_SETP: esilprintf (op, "pf,%s,=", dst); break; case X86_INS_SETNP: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETS: esilprintf (op, "sf,%s,=", dst); break; case X86_INS_SETNS: esilprintf (op, "sf,!,%s,=", dst); break; case X86_INS_SETB: esilprintf (op, "cf,%s,=", dst); break; case X86_INS_SETAE: esilprintf (op, "cf,!,%s,=", dst); break; /* TODO */ #if 0 SETLE/SETNG Sets the byte in the operand to 1 if the Zero Flag is set or the Sign Flag is not equal to the Overflow Flag, otherwise sets the operand to 0. SETBE/SETNA Sets the byte in the operand to 1 if the Carry Flag or the Zero Flag is set, otherwise sets the operand to 0. SETL/SETNGE Sets the byte in the operand to 1 if the Sign Flag is not equal to the Overflow Flag, otherwise sets the operand to 0. case X86_INS_SETL: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETLE: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETG: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETA: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETBE: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETGE: esilprintf (op, "pf,!,%s,=", dst); break; break; #endif } free (dst); } break; // cmov case X86_INS_MOVSS: case X86_INS_CMOVA: case X86_INS_CMOVAE: case X86_INS_CMOVB: case X86_INS_CMOVBE: case X86_INS_FCMOVBE: case X86_INS_FCMOVB: case X86_INS_CMOVE: case X86_INS_FCMOVE: case X86_INS_CMOVG: case X86_INS_CMOVGE: case X86_INS_CMOVL: case X86_INS_CMOVLE: case X86_INS_FCMOVNBE: case X86_INS_FCMOVNB: case X86_INS_CMOVNE: case X86_INS_FCMOVNE: case X86_INS_CMOVNO: case X86_INS_CMOVNP: case X86_INS_FCMOVNU: case X86_INS_CMOVNS: case X86_INS_CMOVO: case X86_INS_CMOVP: case X86_INS_FCMOVU: case X86_INS_CMOVS: // mov case X86_INS_MOV: case X86_INS_MOVAPS: case X86_INS_MOVAPD: case X86_INS_MOVZX: case X86_INS_MOVUPS: case X86_INS_MOVABS: case X86_INS_MOVHPD: case X86_INS_MOVHPS: case X86_INS_MOVLPD: case X86_INS_MOVLPS: case X86_INS_MOVBE: case X86_INS_MOVSB: case X86_INS_MOVSD: case X86_INS_MOVSQ: case X86_INS_MOVSX: case X86_INS_MOVSXD: case X86_INS_MOVSW: case X86_INS_MOVD: case X86_INS_MOVQ: case X86_INS_MOVDQ2Q: { op->type = R_ANAL_OP_TYPE_MOV; op->ptr = UT64_MAX; switch (INSOP(0).type) { case X86_OP_MEM: op->ptr = INSOP(0).mem.disp; op->refptr = INSOP(0).size; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) { op->ptr = UT64_MAX; op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } else { op->ptr = UT64_MAX; } if (a->decode) { if (op->prefix & R_ANAL_OP_PREFIX_REP) { int width = INSOP(0).size; const char *src = cs_reg_name(handle, INSOP(1).mem.base); const char *dst = cs_reg_name(handle, INSOP(0).mem.base); const char *counter = (a->bits==16)?"cx": (a->bits==32)?"ecx":"rcx"; esilprintf (op, "%s,!,?{,BREAK,},%s,DUP,%s,DUP,"\ "%s,[%d],%s,=[%d],df,?{,%d,%s,-=,%d,%s,-=,},"\ "df,!,?{,%d,%s,+=,%d,%s,+=,},%s,--=,%s," \ "?{,8,GOTO,},%s,=,%s,=", counter, src, dst, src, width, dst, width, width, src, width, dst, width, src, width, dst, counter, counter, dst, src); } else { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, NULL); esilprintf (op, "%s,%s", src, dst); free (src); free (dst); } } break; default: if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,=", src, dst); free (src); free (dst); } break; } if (op->refptr<1 || op->ptr == UT64_MAX) { switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; if (INSOP(1).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_GET; op->stackptr = regsz; } break; case X86_OP_IMM: if (INSOP(1).imm > 10) op->ptr = INSOP(1).imm; break; default: break; } } } break; case X86_INS_SHL: case X86_INS_SHLD: case X86_INS_SHLX: op->type = R_ANAL_OP_TYPE_SHL; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "<<"); esilprintf (op, "%s,%s,$z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SAR: case X86_INS_SARX: op->type = R_ANAL_OP_TYPE_SAR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, ">>"); esilprintf (op, "%s,%s,$z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SAL: op->type = R_ANAL_OP_TYPE_SAL; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "<<"); esilprintf (op, "%s,%s,$z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SALC: op->type = R_ANAL_OP_TYPE_SAL; if (a->decode) { esilprintf (op, "$z,DUP,zf,=,al,="); } break; case X86_INS_SHR: case X86_INS_SHRD: case X86_INS_SHRX: op->type = R_ANAL_OP_TYPE_SHR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,>>=,$z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_CMP: case X86_INS_CMPPD: case X86_INS_CMPPS: case X86_INS_CMPSW: case X86_INS_CMPSD: case X86_INS_CMPSQ: case X86_INS_CMPSB: case X86_INS_CMPSS: case X86_INS_TEST: if (insn->id == X86_INS_TEST) { op->type = R_ANAL_OP_TYPE_ACMP; //compare via and if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "0,%s,%s,&,==,$z,zf,=,$p,pf,=,$s,sf,=,0,cf,=,0,of,=", src, dst); free (src); free (dst); } } else { op->type = R_ANAL_OP_TYPE_CMP; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,==,$z,zf,=,$b%d,cf,=,$p,pf,=,$s,sf,=", src, dst, (INSOP(0).size*8)); free (src); free (dst); } } switch (INSOP(0).type) { case X86_OP_MEM: op->ptr = INSOP(0).mem.disp; op->refptr = INSOP(0).size; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } op->ptr = INSOP(1).imm; break; default: switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; if (INSOP(1).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } break; case X86_OP_IMM: op->ptr = INSOP(1).imm; break; default: break; } break; } break; case X86_INS_LEA: op->type = R_ANAL_OP_TYPE_LEA; if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); char *dst = getarg (&gop, 1, 2, NULL); esilprintf (op, "%s,%s,=", dst, src); free (src); free (dst); } switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; switch (INSOP(1).mem.base) { case X86_REG_RIP: op->ptr += addr + op->size; break; case X86_REG_RBP: case X86_REG_EBP: op->stackop = R_ANAL_STACK_GET; op->stackptr = regsz; break; default: /* unhandled */ break; } break; case X86_OP_IMM: if (INSOP(1).imm > 10) op->ptr = INSOP(1).imm; break; default: break; } break; case X86_INS_ENTER: case X86_INS_PUSH: case X86_INS_PUSHAW: case X86_INS_PUSHAL: case X86_INS_PUSHF: { char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%d,%s,-=,%s,%s,=[%d]", rs, sp, dst, sp, rs); free (dst); } switch (INSOP(0).type) { case X86_OP_IMM: op->ptr = INSOP(0).imm; op->type = R_ANAL_OP_TYPE_PUSH; break; default: op->type = R_ANAL_OP_TYPE_UPUSH; break; } op->stackop = R_ANAL_STACK_INC; op->stackptr = regsz; break; case X86_INS_LEAVE: op->type = R_ANAL_OP_TYPE_POP; if (a->decode) { esilprintf (op, "%s,%s,=,%s,[%d],%s,=,%d,%s,+=", bp, sp, sp, rs, bp, rs, sp); } op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_POP: case X86_INS_POPF: case X86_INS_POPAW: case X86_INS_POPAL: case X86_INS_POPCNT: op->type = R_ANAL_OP_TYPE_POP; if (a->decode) { char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,[%d],%s,=,%d,%s,+=", sp, rs, dst, rs, sp); free (dst); } op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_RET: case X86_INS_RETF: case X86_INS_RETFQ: case X86_INS_IRET: case X86_INS_IRETD: case X86_INS_IRETQ: case X86_INS_SYSRET: op->type = R_ANAL_OP_TYPE_RET; if (a->decode) esilprintf (op, "%s,[%d],%s,=,%d,%s,+=", sp, rs, pc, rs, sp); op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_INT3: if (a->decode) esilprintf (op, "3,$"); op->type = R_ANAL_OP_TYPE_TRAP; // TRAP break; case X86_INS_INT1: if (a->decode) esilprintf (op, "1,$"); op->type = R_ANAL_OP_TYPE_SWI; // TRAP break; case X86_INS_INT: if (a->decode) esilprintf (op, "%d,$", R_ABS((int)INSOP(0).imm)); op->type = R_ANAL_OP_TYPE_SWI; break; case X86_INS_SYSCALL: op->type = R_ANAL_OP_TYPE_SWI; break; case X86_INS_INTO: case X86_INS_VMCALL: case X86_INS_VMMCALL: op->type = R_ANAL_OP_TYPE_TRAP; if (a->decode) esilprintf (op, "%d,$", (int)INSOP(0).imm); break; case X86_INS_JL: case X86_INS_JLE: case X86_INS_JA: case X86_INS_JAE: case X86_INS_JB: case X86_INS_JBE: case X86_INS_JCXZ: case X86_INS_JECXZ: case X86_INS_JRCXZ: case X86_INS_JO: case X86_INS_JNO: case X86_INS_JS: case X86_INS_JNS: case X86_INS_JP: case X86_INS_JNP: case X86_INS_JE: case X86_INS_JNE: case X86_INS_JG: case X86_INS_JGE: case X86_INS_LOOP: case X86_INS_LOOPE: case X86_INS_LOOPNE: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = INSOP(0).imm; op->fail = addr+op->size; const char *cnt = (a->bits==16)?"cx":(a->bits==32)?"ecx":"rcx"; if (a->decode) { char *dst = getarg (&gop, 0, 2, NULL); switch (insn->id) { case X86_INS_JL: esilprintf (op, "of,sf,^,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JLE: esilprintf (op, "of,sf,^,zf,|,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JA: esilprintf (op, "cf,zf,|,!,?{,%s,%s,=,}",dst, pc); break; case X86_INS_JAE: esilprintf (op, "cf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JB: esilprintf (op, "cf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JO: esilprintf (op, "of,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNO: esilprintf (op, "of,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JE: esilprintf (op, "zf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JGE: esilprintf (op, "of,!,sf,^,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNE: esilprintf (op, "zf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JG: esilprintf (op, "sf,of,!,^,zf,!,&,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JS: esilprintf (op, "sf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNS: esilprintf (op, "sf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JP: esilprintf (op, "pf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNP: esilprintf (op, "pf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JBE: esilprintf (op, "zf,cf,|,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JCXZ: esilprintf (op, "cx,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JECXZ: esilprintf (op, "ecx,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JRCXZ: esilprintf (op, "rcx,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_LOOP: esilprintf (op, "1,%s,-=,%s,?{,%s,%s,=,}", cnt, cnt, dst, pc); break; case X86_INS_LOOPE: esilprintf (op, "1,%s,-=,%s,?{,zf,?{,%s,%s,=,},}", cnt, cnt, dst, pc); break; case X86_INS_LOOPNE: esilprintf (op, "1,%s,-=,%s,?{,zf,!,?{,%s,%s,=,},}", cnt, cnt, dst, pc); break; } free (dst); } break; case X86_INS_CALL: case X86_INS_LCALL: switch (INSOP(0).type) { case X86_OP_IMM: op->type = R_ANAL_OP_TYPE_CALL; // TODO: what if UCALL? // TODO: use imm_size op->jump = INSOP(0).imm; op->fail = addr+op->size; break; case X86_OP_MEM: op->type = R_ANAL_OP_TYPE_UCALL; op->jump = UT64_MAX; if (INSOP(0).mem.base == 0) { op->ptr = INSOP(0).mem.disp; } break; default: op->type = R_ANAL_OP_TYPE_UCALL; op->jump = UT64_MAX; break; } if (a->decode) { char* arg = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s," "%d,%s,-=,%s," "=[]," "%s,%s,=", pc, rs, sp, sp, arg, pc); free (arg); } break; case X86_INS_JMP: case X86_INS_LJMP: if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,=", src, pc); free (src); } // TODO: what if UJMP? switch (INSOP(0).type) { case X86_OP_IMM: op->jump = INSOP(0).imm; op->type = R_ANAL_OP_TYPE_JMP; if (a->decode) { ut64 dst = INSOP(0).imm; esilprintf (op, "0x%"PFMT64x",%s,=", dst, pc); } break; case X86_OP_MEM: op->type = R_ANAL_OP_TYPE_UJMP; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr = INSOP(0).mem.disp; op->ptr += addr + insn->size; op->refptr = 8; } else { cs_x86_op in = INSOP(0); if (in.mem.index == 0 && in.mem.base == 0 && in.mem.scale == 1) { op->type = R_ANAL_OP_TYPE_UJMP; op->ptr = in.mem.disp; if (a->decode) { esilprintf (op, "0x%"PFMT64x",[],%s,=", op->ptr, pc); } } } break; case X86_OP_REG: case X86_OP_FP: default: // other? op->type = R_ANAL_OP_TYPE_UJMP; break; } break; case X86_INS_IN: case X86_INS_INSW: case X86_INS_INSD: case X86_INS_INSB: case X86_INS_OUT: case X86_INS_OUTSB: case X86_INS_OUTSD: case X86_INS_OUTSW: op->type = R_ANAL_OP_TYPE_IO; break; case X86_INS_VXORPD: case X86_INS_VXORPS: case X86_INS_VPXORD: case X86_INS_VPXORQ: case X86_INS_VPXOR: case X86_INS_XORPS: case X86_INS_KXORW: case X86_INS_PXOR: case X86_INS_XOR: op->type = R_ANAL_OP_TYPE_XOR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "^"); esilprintf (op, "%s,%s,$z,zf,=,$p,pf,=,0,cf,=,0,of,=,$s,sf,=", src, dst); free (src); free (dst); } break; case X86_INS_OR: op->type = R_ANAL_OP_TYPE_OR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,|=", src, dst); free (src); free (dst); } break; case X86_INS_INC: op->type = R_ANAL_OP_TYPE_ADD; op->val = 1; if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,++=", src); free (src); } break; case X86_INS_DEC: op->type = R_ANAL_OP_TYPE_SUB; op->val = 1; if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,--=", src); free (src); } break; case X86_INS_SUB: case X86_INS_PSUBB: case X86_INS_PSUBW: case X86_INS_PSUBD: case X86_INS_PSUBQ: case X86_INS_PSUBSB: case X86_INS_PSUBSW: case X86_INS_PSUBUSB: case X86_INS_PSUBUSW: op->type = R_ANAL_OP_TYPE_SUB; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "-"); esilprintf (op, "%s,%s,$c,cf,=,$z,zf,=,$s,sf,=,$o,of,=", src, dst); // TODO: update flags free (src); free (dst); } if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) { if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) { op->stackop = R_ANAL_STACK_INC; op->stackptr = INSOP(1).imm; } } break; case X86_INS_LIDT: op->type = R_ANAL_OP_TYPE_LOAD; op->family = R_ANAL_OP_FAMILY_PRIV; break; case X86_INS_SIDT: op->type = R_ANAL_OP_TYPE_STORE; op->family = R_ANAL_OP_FAMILY_PRIV; break; case X86_INS_RDRAND: case X86_INS_RDSEED: case X86_INS_RDMSR: case X86_INS_RDPMC: case X86_INS_RDTSC: case X86_INS_RDTSCP: case X86_INS_CRC32: case X86_INS_SHA1MSG1: case X86_INS_SHA1MSG2: case X86_INS_SHA1NEXTE: case X86_INS_SHA1RNDS4: case X86_INS_SHA256MSG1: case X86_INS_SHA256MSG2: case X86_INS_SHA256RNDS2: case X86_INS_AESDECLAST: case X86_INS_AESDEC: case X86_INS_AESENCLAST: case X86_INS_AESENC: case X86_INS_AESIMC: case X86_INS_AESKEYGENASSIST: // AES instructions op->family = R_ANAL_OP_FAMILY_CRYPTO; op->type = R_ANAL_OP_TYPE_MOV; // XXX break; case X86_INS_AND: case X86_INS_ANDN: case X86_INS_ANDPD: case X86_INS_ANDPS: case X86_INS_ANDNPD: case X86_INS_ANDNPS: op->type = R_ANAL_OP_TYPE_AND; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "&"); // TODO: update of = cf = 0 // TODO: update sf, zf and pf // TODO: af is undefined esilprintf (op, "0,of,=,0,cf,=," // set carry and overflow flags "%s,%s," // set reg value "$z,zf,=," // update zero flag "$s,sf,=," // update sign flag "$o,pf,=", // update parity flag // TODO: add sign and parity flags here src, dst); free (src); free (dst); } break; case X86_INS_DIV: case X86_INS_IDIV: op->type = R_ANAL_OP_TYPE_DIV; if (a->decode) { int width = INSOP(0).size; char *dst = getarg (&gop, 0, 0, NULL); const char *r_ax = (width==2)?"ax": (width==4)?"eax":"rax"; const char *r_dx = (width==2)?"dx": (width==4)?"edx":"rdx"; // TODO update flags & handle signedness esilprintf (op, "%s,%s,%%,%s,=,%s,%s,/,%s,=", dst, r_ax, r_dx, dst, r_ax, r_ax); free (dst); } break; case X86_INS_MUL: case X86_INS_MULX: case X86_INS_MULPD: case X86_INS_MULPS: case X86_INS_MULSD: case X86_INS_MULSS: op->type = R_ANAL_OP_TYPE_MUL; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "*"); if (!src && dst) { switch (dst[0]) { case 'r': src = strdup ("rax"); break; case 'e': src = strdup ("eax"); break; default: src = strdup ("al"); break; } } esilprintf (op, "%s,%s", src, dst); free (src); free (dst); } break; case X86_INS_PACKSSDW: case X86_INS_PACKSSWB: case X86_INS_PACKUSWB: op->type = R_ANAL_OP_TYPE_MOV; op->family = R_ANAL_OP_FAMILY_MMX; break; case X86_INS_PADDB: case X86_INS_PADDD: case X86_INS_PADDW: case X86_INS_PADDSB: case X86_INS_PADDSW: case X86_INS_PADDUSB: case X86_INS_PADDUSW: op->type = R_ANAL_OP_TYPE_ADD; op->family = R_ANAL_OP_FAMILY_MMX; break; case X86_INS_FADD: case X86_INS_FADDP: op->family = R_ANAL_OP_FAMILY_FPU; /* pass thru */ case X86_INS_ADD: case X86_INS_ADDPS: case X86_INS_ADDSD: case X86_INS_ADDSS: case X86_INS_ADDSUBPD: case X86_INS_ADDSUBPS: case X86_INS_ADDPD: case X86_INS_XADD: op->type = R_ANAL_OP_TYPE_ADD; if (a->decode) { if (INSOP(0).type == X86_OP_MEM) { char *src = getarg (&gop, 1, 0, NULL); char *src2 = getarg (&gop, 0, 0, NULL); char *dst = getarg (&gop, 0, 1, NULL); // TODO: update flags esilprintf (op, "%s,%s,+,%s", src, src2, dst); free (src); free (src2); free (dst); } else { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "+"); esilprintf (op, "%s,%s", src, dst); // TODO: update flags free (src); free (dst); } } if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) { if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) { op->stackop = R_ANAL_STACK_INC; op->stackptr = -INSOP(1).imm; } } break; /* Direction flag */ case X86_INS_CLD: op->type = R_ANAL_OP_TYPE_MOV; op->family = R_ANAL_OP_FAMILY_CPU; if (a->decode) esilprintf (op, "0,df,="); break; case X86_INS_STD: op->type = R_ANAL_OP_TYPE_MOV; op->family = R_ANAL_OP_FAMILY_CPU; if (a->decode) esilprintf (op, "1,df,="); break; } switch (insn->id) { case X86_INS_MOVAPS: //cvtss2sd case X86_INS_ADDSD: //cvtss2sd case X86_INS_SUBSD: //cvtss2sd case X86_INS_MULSD: //cvtss2sd case X86_INS_CVTSS2SD: //cvtss2sd case X86_INS_MOVSS: case X86_INS_MOVSD: op->family = R_ANAL_OP_FAMILY_MMX; break; } } //#if X86_GRP_PRIVILEGE>0 if (insn) { #if HAVE_CSGRP_PRIVILEGE if (cs_insn_group (handle, insn, X86_GRP_PRIVILEGE)) op->family = R_ANAL_OP_FAMILY_PRIV; #endif #if !USE_ITER_API cs_free (insn, n); #endif } //cs_close (&handle); return op->size; }
static int _6502_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) { char addrbuf[64]; const int buffsize = sizeof(addrbuf)-1; memset (op, '\0', sizeof (RAnalOp)); op->size = snes_op[data[0]].len; //snes-arch is similiar to nes/6502 op->addr = addr; op->type = R_ANAL_OP_TYPE_UNK; r_strbuf_init (&op->esil); switch (data[0]) { case 0x02: case 0x03: case 0x04: case 0x07: case 0x0b: case 0x0c: case 0x0f: case 0x12: case 0x13: case 0x14: case 0x17: case 0x1a: case 0x1b: case 0x1c: case 0x1f: case 0x22: case 0x23: case 0x27: case 0x2b: case 0x2f: case 0x32: case 0x33: case 0x34: case 0x37: case 0x3a: case 0x3b: case 0x3c: case 0x3f: case 0x42: case 0x43: case 0x44: case 0x47: case 0x4b: case 0x4f: case 0x52: case 0x53: case 0x54: case 0x57: case 0x5a: case 0x5b: case 0x5c: case 0x5f: case 0x62: case 0x63: case 0x64: case 0x67: case 0x6b: case 0x6f: case 0x72: case 0x73: case 0x74: case 0x77: case 0x7a: case 0x7b: case 0x7c: case 0x7f: case 0x80: case 0x82: case 0x83: case 0x87: case 0x89: case 0x8b: case 0x8f: case 0x92: case 0x93: case 0x97: case 0x9b: case 0x9c: case 0x9e: case 0x9f: case 0xa3: case 0xa7: case 0xab: case 0xaf: case 0xb2: case 0xb3: case 0xb7: case 0xbb: case 0xbf: case 0xc2: case 0xc3: case 0xc7: case 0xcb: case 0xcf: case 0xd2: case 0xd3: case 0xd4: case 0xd7: case 0xda: case 0xdb: case 0xdc: case 0xdf: case 0xe2: case 0xe3: case 0xe7: case 0xeb: case 0xef: case 0xf2: case 0xf3: case 0xf4: case 0xf7: case 0xfa: case 0xfb: case 0xfc: case 0xff: // undocumented or not-implemented opcodes for 6502. // some of them might be implemented in 65816 op->size = 1; op->type = R_ANAL_OP_TYPE_ILL; break; // BRK case 0x00: // brk op->cycles = 7; op->type = R_ANAL_OP_TYPE_SWI; // override 65816 code which seems to be wrong: size is 1, but pc = pc + 2 op->size = 1; // PC + 2 to Stack, P to Stack B=1 D=0 I=1. "B" is not a flag. Only its bit is pushed on the stack // PC was already incremented by one at this point. Needs to incremented once more // New PC is Interrupt Vector: $fffe. (FIXME: Confirm this is valid for all 6502) r_strbuf_set (&op->esil, ",1,I,=,0,D,=,flags,0x10,|,0x100,sp,+,=[1],pc,1,+,0xfe,sp,+,=[2],3,sp,-=,0xfffe,[2],pc,="); break; // FLAGS case 0x78: // sei case 0x58: // cli case 0x38: // sec case 0x18: // clc case 0xf8: // sed case 0xd8: // cld case 0xb8: // clv op->cycles = 2; // FIXME: what opcode for this? op->type = R_ANAL_OP_TYPE_NOP; _6502_anal_esil_flags (op, data[0]); break; // BIT case 0x24: // bit $ff case 0x2c: // bit $ffff op->type = R_ANAL_OP_TYPE_MOV; _6502_anal_esil_get_addr_pattern3 (op, data, addrbuf, buffsize, 0); r_strbuf_setf (&op->esil, "a,%s,[1],&,0x80,&,!,!,N,=,a,%s,[1],&,0x40,&,!,!,V,=,a,%s,[1],&,0xff,&,!,Z,=",addrbuf, addrbuf, addrbuf); break; // ADC case 0x69: // adc #$ff case 0x65: // adc $ff case 0x75: // adc $ff,x case 0x6d: // adc $ffff case 0x7d: // adc $ffff,x case 0x79: // adc $ffff,y case 0x61: // adc ($ff,x) case 0x71: // adc ($ff,y) // FIXME: update V // FIXME: support BCD mode op->type = R_ANAL_OP_TYPE_ADD; _6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize); if (data[0] == 0x69) // immediate mode r_strbuf_setf (&op->esil, "%s,a,+=,C,NUM,$c7,C,=,a,+=,$c7,C,|=", addrbuf); else r_strbuf_setf (&op->esil, "%s,[1],a,+=,C,NUM,$c7,C,=,a,+=,$c7,C,|=", addrbuf); _6502_anal_update_flags (op, _6502_FLAGS_NZ); // fix Z r_strbuf_append (&op->esil, ",a,a,=,$z,Z,="); break; // SBC case 0xe9: // sbc #$ff case 0xe5: // sbc $ff case 0xf5: // sbc $ff,x case 0xed: // sbc $ffff case 0xfd: // sbc $ffff,x case 0xf9: // sbc $ffff,y case 0xe1: // sbc ($ff,x) case 0xf1: // sbc ($ff,y) // FIXME: update V // FIXME: support BCD mode op->type = R_ANAL_OP_TYPE_SUB; _6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize); if (data[0] == 0xe9) // immediate mode r_strbuf_setf (&op->esil, "C,!,%s,+,a,-=", addrbuf); else r_strbuf_setf (&op->esil, "C,!,%s,[1],+,a,-=", addrbuf); _6502_anal_update_flags (op, _6502_FLAGS_BNZ); // fix Z and revert C r_strbuf_append (&op->esil, ",a,a,=,$z,Z,=,C,!="); break; // ORA case 0x09: // ora #$ff case 0x05: // ora $ff case 0x15: // ora $ff,x case 0x0d: // ora $ffff case 0x1d: // ora $ffff,x case 0x19: // ora $ffff,y case 0x01: // ora ($ff,x) case 0x11: // ora ($ff),y op->type = R_ANAL_OP_TYPE_OR; _6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize); if (data[0] == 0x09) // immediate mode r_strbuf_setf (&op->esil, "%s,a,|=", addrbuf); else r_strbuf_setf (&op->esil, "%s,[1],a,|=", addrbuf); _6502_anal_update_flags (op, _6502_FLAGS_NZ); break; // AND case 0x29: // and #$ff case 0x25: // and $ff case 0x35: // and $ff,x case 0x2d: // and $ffff case 0x3d: // and $ffff,x case 0x39: // and $ffff,y case 0x21: // and ($ff,x) case 0x31: // and ($ff),y op->type = R_ANAL_OP_TYPE_AND; _6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize); if (data[0] == 0x29) // immediate mode r_strbuf_setf (&op->esil, "%s,a,&=", addrbuf); else r_strbuf_setf (&op->esil, "%s,[1],a,&=", addrbuf); _6502_anal_update_flags (op, _6502_FLAGS_NZ); break; // EOR case 0x49: // eor #$ff case 0x45: // eor $ff case 0x55: // eor $ff,x case 0x4d: // eor $ffff case 0x5d: // eor $ffff,x case 0x59: // eor $ffff,y case 0x41: // eor ($ff,x) case 0x51: // eor ($ff),y op->type = R_ANAL_OP_TYPE_XOR; _6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize); if (data[0] == 0x49) // immediate mode r_strbuf_setf (&op->esil, "%s,a,^=", addrbuf); else r_strbuf_setf (&op->esil, "%s,[1],a,^=", addrbuf); _6502_anal_update_flags (op, _6502_FLAGS_NZ); break; // ASL case 0x0a: // asl a case 0x06: // asl $ff case 0x16: // asl $ff,x case 0x0e: // asl $ffff case 0x1e: // asl $ffff,x op->type = R_ANAL_OP_TYPE_SHL; if (data[0] == 0x0a) { r_strbuf_set (&op->esil, "1,a,<<=,$c7,C,=,a,a,="); } else { _6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'x'); r_strbuf_setf (&op->esil, "1,%s,[1],<<,%s,=[1],$c7,C,=", addrbuf, addrbuf); } _6502_anal_update_flags (op, _6502_FLAGS_NZ); break; // LSR case 0x4a: // lsr a case 0x46: // lsr $ff case 0x56: // lsr $ff,x case 0x4e: // lsr $ffff case 0x5e: // lsr $ffff,x op->type = R_ANAL_OP_TYPE_SHR; if (data[0] == 0x4a) { r_strbuf_set (&op->esil, "1,a,&,C,=,1,a,>>="); } else { _6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'x'); r_strbuf_setf (&op->esil, "1,%s,[1],&,C,=,1,%s,[1],>>,%s,=[1]", addrbuf, addrbuf, addrbuf); } _6502_anal_update_flags (op, _6502_FLAGS_NZ); break; // ROL case 0x2a: // rol a case 0x26: // rol $ff case 0x36: // rol $ff,x case 0x2e: // rol $ffff case 0x3e: // rol $ffff,x op->type = R_ANAL_OP_TYPE_ROL; if (data[0] == 0x2a) { r_strbuf_set (&op->esil, "1,a,<<,C,|,a,=,$c7,C,=,a,a,="); } else { _6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'x'); r_strbuf_setf (&op->esil, "1,%s,[1],<<,C,|,%s,=[1],$c7,C,=", addrbuf, addrbuf); } _6502_anal_update_flags (op, _6502_FLAGS_NZ); break; // ROR case 0x6a: // ror a case 0x66: // ror $ff case 0x76: // ror $ff,x case 0x6e: // ror $ffff case 0x7e: // ror $ffff,x // uses N as temporary to hold C value. but in fact, // it is not temporary since in all ROR ops, N will have the value of C op->type = R_ANAL_OP_TYPE_ROR; if (data[0] == 0x6a) { r_strbuf_set (&op->esil, "C,N,=,1,a,&,C,=,1,a,>>,7,N,<<,|,a,="); } else { _6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'x'); r_strbuf_setf (&op->esil, "C,N,=,1,%s,[1],&,C,=,1,%s,[1],>>,7,N,<<,|,%s,=[1]", addrbuf, addrbuf, addrbuf); } _6502_anal_update_flags (op, _6502_FLAGS_NZ); break; // INC case 0xe6: // inc $ff case 0xf6: // inc $ff,x case 0xee: // inc $ffff case 0xfe: // inc $ffff,x op->type = R_ANAL_OP_TYPE_STORE; _6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'x'); r_strbuf_setf (&op->esil, "%s,++=[1]", addrbuf); _6502_anal_update_flags (op, _6502_FLAGS_NZ); break; // DEC case 0xc6: // dec $ff case 0xd6: // dec $ff,x case 0xce: // dec $ffff case 0xde: // dec $ffff,x op->type = R_ANAL_OP_TYPE_STORE; _6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'x'); r_strbuf_setf (&op->esil, "%s,--=[1]", addrbuf); _6502_anal_update_flags (op, _6502_FLAGS_NZ); break; // INX, INY case 0xe8: // inx case 0xc8: // iny op->cycles = 2; op->type = R_ANAL_OP_TYPE_STORE; _6502_anal_esil_inc_reg (op, data[0], "+"); break; // DEX, DEY case 0xca: // dex case 0x88: // dey op->cycles = 2; op->type = R_ANAL_OP_TYPE_STORE; _6502_anal_esil_inc_reg (op, data[0], "-"); break; // CMP case 0xc9: // cmp #$ff case 0xc5: // cmp $ff case 0xd5: // cmp $ff,x case 0xcd: // cmp $ffff case 0xdd: // cmp $ffff,x case 0xd9: // cmp $ffff,y case 0xc1: // cmp ($ff,x) case 0xd1: // cmp ($ff),y op->type = R_ANAL_OP_TYPE_CMP; _6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize); if (data[0] == 0xc9) // immediate mode r_strbuf_setf (&op->esil, "%s,a,==", addrbuf); else r_strbuf_setf (&op->esil, "%s,[1],a,==", addrbuf); _6502_anal_update_flags (op, _6502_FLAGS_BNZ); // invert C, since C=1 when A-M >= 0 r_strbuf_append (&op->esil, ",C,!,C,="); break; // CPX case 0xe0: // cpx #$ff case 0xe4: // cpx $ff case 0xec: // cpx $ffff op->type = R_ANAL_OP_TYPE_CMP; _6502_anal_esil_get_addr_pattern3 (op, data, addrbuf, buffsize, 0); if (data[0] == 0xe0) // immediate mode r_strbuf_setf (&op->esil, "%s,x,==", addrbuf); else r_strbuf_setf (&op->esil, "%s,[1],x,==", addrbuf); _6502_anal_update_flags (op, _6502_FLAGS_BNZ); // invert C, since C=1 when A-M >= 0 r_strbuf_append (&op->esil, ",C,!,C,="); break; // CPY case 0xc0: // cpy #$ff case 0xc4: // cpy $ff case 0xcc: // cpy $ffff op->type = R_ANAL_OP_TYPE_CMP; _6502_anal_esil_get_addr_pattern3 (op, data, addrbuf, buffsize, 0); if (data[0] == 0xc0) // immediate mode r_strbuf_setf (&op->esil, "%s,y,==", addrbuf); else r_strbuf_setf (&op->esil, "%s,[1],y,==", addrbuf); _6502_anal_update_flags (op, _6502_FLAGS_BNZ); // invert C, since C=1 when A-M >= 0 r_strbuf_append (&op->esil, ",C,!,C,="); break; // BRANCHES case 0x10: // bpl $ffff case 0x30: // bmi $ffff case 0x50: // bvc $ffff case 0x70: // bvs $ffff case 0x90: // bcc $ffff case 0xb0: // bcs $ffff case 0xd0: // bne $ffff case 0xf0: // beq $ffff // FIXME: Add 1 if branch occurs to same page. // FIXME: Add 2 if branch occurs to different page op->cycles = 2; op->failcycles = 3; op->type = R_ANAL_OP_TYPE_CJMP; if (data[1] <= 127) op->jump = addr + data[1] + op->size; else op->jump = addr - (256 - data[1]) + op->size; op->fail = addr + op->size; // FIXME: add a type of conditional // op->cond = R_ANAL_COND_LE; _6502_anal_esil_ccall (op, data[0]); break; // JSR case 0x20: // jsr $ffff op->cycles = 6; op->type = R_ANAL_OP_TYPE_CALL; op->jump = data[1] | data[2] << 8; op->stackop = R_ANAL_STACK_INC; op->stackptr = 2; // JSR pushes the address-1 of the next operation on to the stack before transferring program // control to the following address // stack is on page one and sp is an 8-bit reg: operations must be done like: sp + 0x100 r_strbuf_setf (&op->esil, "1,pc,-,0xff,sp,+,=[2],0x%04x,pc,=,2,sp,-=", op->jump); break; // JMP case 0x4c: // jmp $ffff op->cycles = 3; op->type = R_ANAL_OP_TYPE_JMP; op->jump = data[1] | data[2] << 8; r_strbuf_setf (&op->esil, "0x%04x,pc,=", op->jump); break; case 0x6c: // jmp ($ffff) op->cycles = 5; op->type = R_ANAL_OP_TYPE_UJMP; // FIXME: how to read memory? // op->jump = data[1] | data[2] << 8; r_strbuf_setf (&op->esil, "0x%04x,[2],pc,=", data[1] | data[2] << 8); break; // RTS case 0x60: // rts op->eob = 1; op->type = R_ANAL_OP_TYPE_RET; op->cycles = 6; op->stackop = R_ANAL_STACK_INC; op->stackptr = -2; // Operation: PC from Stack, PC + 1 -> PC // stack is on page one and sp is an 8-bit reg: operations must be done like: sp + 0x100 r_strbuf_set (&op->esil, "0x101,sp,+,[2],pc,=,pc,++=,2,sp,+="); break; // RTI case 0x40: // rti op->eob = 1; op->type = R_ANAL_OP_TYPE_RET; op->cycles = 6; op->stackop = R_ANAL_STACK_INC; op->stackptr = -3; // Operation: P from Stack, PC from Stack // stack is on page one and sp is an 8-bit reg: operations must be done like: sp + 0x100 r_strbuf_set (&op->esil, "0x101,sp,+,[1],flags,=,0x102,sp,+,[2],pc,=,3,sp,+="); break; // NOP case 0xea: // nop op->type = R_ANAL_OP_TYPE_NOP; op->cycles = 2; break; // LDA case 0xa9: // lda #$ff case 0xa5: // lda $ff case 0xb5: // lda $ff,x case 0xad: // lda $ffff case 0xbd: // lda $ffff,x case 0xb9: // lda $ffff,y case 0xa1: // lda ($ff,x) case 0xb1: // lda ($ff),y op->type = R_ANAL_OP_TYPE_LOAD; _6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize); if (data[0] == 0xa9) // immediate mode r_strbuf_setf (&op->esil, "%s,a,=", addrbuf); else r_strbuf_setf (&op->esil, "%s,[1],a,=", addrbuf); _6502_anal_update_flags (op, _6502_FLAGS_NZ); break; // LDX case 0xa2: // ldx #$ff case 0xa6: // ldx $ff case 0xb6: // ldx $ff,y case 0xae: // ldx $ffff case 0xbe: // ldx $ffff,y op->type = R_ANAL_OP_TYPE_LOAD; _6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'y'); if (data[0] == 0xa2) // immediate mode r_strbuf_setf (&op->esil, "%s,x,=", addrbuf); else r_strbuf_setf (&op->esil, "%s,[1],x,=", addrbuf); _6502_anal_update_flags (op, _6502_FLAGS_NZ); break; // LDY case 0xa0: // ldy #$ff case 0xa4: // ldy $ff case 0xb4: // ldy $ff,x case 0xac: // ldy $ffff case 0xbc: // ldy $ffff,x op->type = R_ANAL_OP_TYPE_LOAD; _6502_anal_esil_get_addr_pattern3 (op, data, addrbuf, buffsize, 'x'); if (data[0] == 0xa0) // immediate mode r_strbuf_setf (&op->esil, "%s,y,=", addrbuf); else r_strbuf_setf (&op->esil, "%s,[1],y,=", addrbuf); _6502_anal_update_flags (op, _6502_FLAGS_NZ); break; // STA case 0x85: // sta $ff case 0x95: // sta $ff,x case 0x8d: // sta $ffff case 0x9d: // sta $ffff,x case 0x99: // sta $ffff,y case 0x81: // sta ($ff,x) case 0x91: // sta ($ff),y op->type = R_ANAL_OP_TYPE_STORE; _6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize); r_strbuf_setf (&op->esil, "a,%s,=[1]", addrbuf); break; // STX case 0x86: // stx $ff case 0x96: // stx $ff,y case 0x8e: // stx $ffff op->type = R_ANAL_OP_TYPE_STORE; _6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'y'); r_strbuf_setf (&op->esil, "x,%s,=[1]", addrbuf); break; // STY case 0x84: // sty $ff case 0x94: // sty $ff,x case 0x8c: // sty $ffff op->type = R_ANAL_OP_TYPE_STORE; _6502_anal_esil_get_addr_pattern3 (op, data, addrbuf, buffsize, 'x'); r_strbuf_setf (&op->esil, "y,%s,=[1]", addrbuf); break; // PHP/PHA case 0x08: // php case 0x48: // pha op->type = R_ANAL_OP_TYPE_PUSH; op->cycles = 3; op->stackop = R_ANAL_STACK_INC; op->stackptr = 1; _6502_anal_esil_push (op, data[0]); break; // PLP,PLA case 0x28: // plp case 0x68: // plp op->type = R_ANAL_OP_TYPE_POP; op->cycles = 4; op->stackop = R_ANAL_STACK_INC; op->stackptr = -1; _6502_anal_esil_pop (op, data[0]); break; // TAX,TYA,... case 0xaa: // tax case 0x8a: // txa case 0xa8: // tay case 0x98: // tya op->type = R_ANAL_OP_TYPE_MOV; op->cycles = 2; _6502_anal_esil_mov (op, data[0]); break; case 0x9a: // txs op->type = R_ANAL_OP_TYPE_MOV; op->cycles = 2; op->stackop = R_ANAL_STACK_SET; // FIXME: should I get register X a place it here? // op->stackptr = get_register_x(); _6502_anal_esil_mov (op, data[0]); break; case 0xba: // tsx op->type = R_ANAL_OP_TYPE_MOV; op->cycles = 2; op->stackop = R_ANAL_STACK_GET; _6502_anal_esil_mov (op, data[0]); break; } return op->size; }
static int analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf) { int ret = -1; ut8 opcode = buf[0]; if (!op) { return 2; } r_strbuf_init (&op->esil); r_strbuf_set (&op->esil, ""); switch (opcode >> 4) { case H8300_CMP_4BIT: //acc. to manual this is how it's done, could use == in esil r_strbuf_appendf(&op->esil, "0x%02x,r%u%c,-", imm, rdB(0)); //setZ setV("%o"); setN; setHb_B; setCb_B; maskB(0); setZ; return 0; case H8300_OR_4BIT: r_strbuf_appendf(&op->esil, "0x%02x,r%u%c,|=", imm, rdB(0)); //setZ setV("0"); setN; maskB(0); setZ; return 0; case H8300_XOR_4BIT: r_strbuf_appendf(&op->esil, "0x%02x,r%u%c,^=", imm, rdB(0)); //setZ setN; setV("0"); maskB(0); setZ; return 0; case H8300_AND_4BIT: r_strbuf_appendf(&op->esil, "0x%02x,r%u%c,&=", imm, rdB(0)); //setZ setN; setV("0"); maskB(0); setZ; return 0; case H8300_ADD_4BIT: r_strbuf_appendf(&op->esil, "0x%02x,r%u%c,+=", imm, rdB(0)); //setZ setV("%o"); setN; setH_B; setC_B; maskB(0); setZ; return 0; case H8300_ADDX_4BIT: r_strbuf_appendf(&op->esil, "0x%02x,C,+,r%u%c,+= ", imm, rdB(0), rdB(0)); //setZ setV("%o"); setN; setH_B; setC_B; maskB(0); setZ; return 0; case H8300_SUBX_4BIT: //Rd – imm – C → Rd r_strbuf_appendf(&op->esil, "0x%02x,r%u%c,-=,C,r%u%c,-=", imm, rdB(0), rdB(0)); //setZ setV("%o"); setN; setHb_B; setCb_B; maskB(0); setZ; return 0; case H8300_MOV_4BIT_2: /*TODO*/ case H8300_MOV_4BIT_3: /*TODO*/ case H8300_MOV_4BIT: /*TODO*/ return 0; default: break; }; switch (opcode) { case H8300_NOP: r_strbuf_set (&op->esil, ","); return 0; case H8300_SLEEP: /* TODO */ return 0; case H8300_STC: r_strbuf_appendf(&op->esil, "ccr,r%u%c,=", rdB(1)); return 0; case H8300_LDC: r_strbuf_appendf(&op->esil, "r%u%c,ccr,=", rdB(1)); return 0; case H8300_ORC: r_strbuf_appendf(&op->esil, "0x%02x,ccr,|=", imm); return 0; case H8300_XORC: r_strbuf_appendf(&op->esil, "0x%02x,ccr,^=", imm); return 0; case H8300_ANDC: r_strbuf_appendf(&op->esil, "0x%02x,ccr,&=", imm); return 0; case H8300_LDC_2: r_strbuf_appendf(&op->esil, "0x%02x,ccr,=", imm); return 0; case H8300_ADDB_DIRECT: r_strbuf_appendf(&op->esil, "r%u%c,r%u%c,+=", rsB(), rdB(1)); setH_B; setV("%o"); setC_B ; setN; //setZ; maskB(1); setZ; return 0; case H8300_ADDW_DIRECT: r_strbuf_appendf (&op->esil, "r%u,r%u,+=", rs(), rd()); setH_W; setV("%o"); setC_W; setN; mask(); setZ; return 0; case H8300_INC: r_strbuf_appendf(&op->esil, "1,r%u%c,+=", rdB(1)); //setZ setV("%o") ; setN; maskB(1); setZ; return 0; case H8300_ADDS: r_strbuf_appendf (&op->esil, "%d,r%u,+=", ((buf[1] & 0xf0) == 0x80) ? 2 : 1, rd()); return 0; case H8300_MOV_1: /*TODO check if flags are set internally or not*/ r_strbuf_appendf (&op->esil, "r%u%c,r%u%c,=", rsB(), rdB(1)); //setZ setN; maskB(1); setZ; return 0; case H8300_MOV_2: r_strbuf_appendf(&op->esil, "r%u,r%u,=", rs(), rd()); //setZ setN; mask(); setZ; return 0; case H8300_ADDX: //Rd + (Rs) + C → Rd r_strbuf_appendf (&op->esil, "r%u%c,C,+,r%u%c,+=", rsB(), rdB(1), rdB(1)); //setZ setV("%o"); setN; setH_B ; setC_B; maskB(1); setZ; return 0; case H8300_DAA: /*TODO*/ return 0; case H8300_SHL: /*TODO*/ return 0; case H8300_SHR: /*TODO*/ return 0; case H8300_ROTL: /*TODO*/ return 0; case H8300_ROTR: /*TODO*/ return 0; case H8300_OR: r_strbuf_appendf(&op->esil, "r%u%c,r%u%c,|=", rsB(), rdB(1)); //setZ setV("0"); setN; maskB(1); setZ; return 0; case H8300_XOR: r_strbuf_appendf(&op->esil, "r%u%c,r%u%c,^=", rsB(), rdB(1)); //setZ setV("0") ; setN; maskB(1); setZ; return 0; case H8300_AND: r_strbuf_appendf(&op->esil, "r%u%c,r%u%c,&=", rsB(), rdB(1)); //setZ setV("0"); setN; maskB(1); setZ; return 0; case H8300_NOT_NEG: if ((buf[1] & 0xf0) == 0x80) { //NEG r_strbuf_appendf(&op->esil, "r%u%c,0,-,r%u%c,=", rdB(1), rdB(1)); //setZ setHb_B; setV("%o") ; setCb_B ; setN; maskB(1); setZ; } else if ((buf[1] & 0xf0) == 0x00) { //NOT r_strbuf_appendf(&op->esil, "r%u%c,!=", rdB(1)); //setZ setV("0"); setN; maskB(1); setZ; } return 0; case H8300_SUB_1: r_strbuf_appendf(&op->esil, "r%u%c,r%u%c,-=", rsB(), rdB(1)); //setZ setHb_B; setV("%o"); setCb_B; setN; maskB(1); setZ; return 0; case H8300_SUBW: r_strbuf_appendf (&op->esil, "r%u,r%u,-=", rs(), rd()); setHb_W; setV ("%o"); setCb_W; setN; mask(); setZ; return 0; case H8300_DEC: r_strbuf_appendf (&op->esil, "1,r%u%c,-=", rdB(1)); //setZ setV("%o"); setN; maskB(1); setZ; return 0; case H8300_SUBS: r_strbuf_appendf(&op->esil, "%d,r%u,-=", ( (buf[1] & 0xf0) == 0x80) ? 2 : 1, rd()); return 0; case H8300_CMP_1: r_strbuf_appendf(&op->esil, "r%u%c,r%u%c,-", rsB(), rdB(1)); //setZ setHb_B; setV("%o"); setCb_B; setN; maskB(1); setZ; return 0; case H8300_CMP_2: r_strbuf_appendf(&op->esil, "r%u,r%u,-", rs(), rd()); //setZ setHb_W; setV("%o"); setCb_W; setN; mask(); setZ; return 0; case H8300_SUBX: //Rd – (Rs) – C → Rd r_strbuf_appendf(&op->esil, "r%u%c,r%u%c,-=,C,r%u%c,-=", rsB(), rdB(1), rdB(1)); //setZ setHb_B; setV("%o"); setCb_B; setN; maskB(1); setZ; return 0; case H8300_DAS: /*TODO*/ return 0; case H8300_BRA: r_strbuf_appendf(&op->esil, "0x%02x,pc,+=", buf[1]); return 0; case H8300_BRN: r_strbuf_appendf(&op->esil,","); return 0; case H8300_BHI: r_strbuf_appendf(&op->esil, "C,Z,|,!,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BLS: r_strbuf_appendf(&op->esil, "C,Z,|,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BCC: r_strbuf_appendf(&op->esil, "C,!,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BCS: r_strbuf_appendf(&op->esil, "C,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BNE: r_strbuf_appendf(&op->esil, "Z,!,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BEQ: r_strbuf_appendf(&op->esil, "Z,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BVC: r_strbuf_appendf(&op->esil, "V,!,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BVS: r_strbuf_appendf(&op->esil, "V,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BPL: r_strbuf_appendf(&op->esil, "N,!,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BMI: r_strbuf_appendf(&op->esil, "N,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BGE: r_strbuf_appendf(&op->esil, "N,V,^,!,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BLT: r_strbuf_appendf(&op->esil, "N,V,^,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BGT: r_strbuf_appendf(&op->esil, "Z,N,V,^,|,!,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BLE: r_strbuf_appendf(&op->esil, "Z,N,V,^,|,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_MULXU: //Refer to pg. 100 of the manual linked at the beginning r_strbuf_appendf(&op->esil, "r%u%c,r%ul,*,r%u,=", rsB(), rd(), rd()); return 0; case H8300_DIVXU: /*TODO*/ return 0; case H8300_RTS: /*TODO*/ return 0; case H8300_BSR: /*TODO*/ return 0; case H8300_RTE: /*TODO*/ return 0; case H8300_JMP_1: /*TODO*/ return 0; case H8300_JMP_2: /*TODO*/ return 0; case H8300_JMP_3: /*TODO*/ return 0; case H8300_JSR_1: /*TODO*/ return 0; case H8300_JSR_2: /*TODO*/ return 0; case H8300_JSR_3: /*TODO*/ return 0; //NOTE - cases marked with TODO have mem. access also(not impl.) case H8300_BSET_1: /*TODO*/ //set rs&0x7th bit of rd. expr.- rd|= 1<<(rs&0x07) r_strbuf_appendf(&op->esil, "0x7,r%u%c,&,1,<<,r%u%c,|=", rsB(), rdB(1)); return 0; case H8300_BNOT_1: /*TODO*/ //invert rs&0x7th bit of rd. expr.- rd^= 1<<(rs&0x07) r_strbuf_appendf(&op->esil,"0x07,r%u%c,&,1,<<,r%u%c,^=", rsB(), rdB(1)); return 0; case H8300_BCLR_R2R8: /*TODO*/ //clear rs&0x7th bit of rd. expr.- rd&= !(1<<(rs&0x07)) r_strbuf_appendf(&op->esil, "0x7,r%u%c,&,1,<<,!,r%u%c,&=", rsB(), rdB(1)); return 0; case H8300_BTST_R2R8: /*TODO*/ //¬ (<Bit No.> of <EAd>) → Z, extract bit value and shift it back r_strbuf_appendf(&op->esil, "0x7,r%u%c,&,0x7,r%u%c,&,1,<<,r%u%c,&,>>,!,Z,=", rsB(), rsB(), rdB(1)); return 0; case H8300_BST_BIST: /*TODO*/ if (!(buf[1] & 0x80)) { //BST r_strbuf_appendf(&op->esil,"%d,C,<<,r%u%c,|=",rs(),rdB(1)); } else { //BIST r_strbuf_appendf (&op->esil, "%d,C,!,<<,r%u%c,|=", rs (), rdB (1)); } return 0; case H8300_MOV_R82IND16: /*TODO*/ return 0; case H8300_MOV_IND162R16: /*TODO*/ return 0; case H8300_MOV_R82ABS16: /*TODO*/ return 0; case H8300_MOV_ABS162R16: /*TODO*/ return 0; case H8300_MOV_R82RDEC16: /*TODO*/ return 0; case H8300_MOV_INDINC162R16: /*TODO*/ return 0; case H8300_MOV_R82DISPR16: /*TODO*/ return 0; case H8300_MOV_DISP162R16: /*TODO*/ return 0; case H8300_BSET_2: /*TODO*/ //set imm bit of rd. expr.- rd|= (1<<imm) r_strbuf_appendf(&op->esil, "%d,1,<<,r%u%c,|=", rs(), rdB(1)); return 0; case H8300_BNOT_2: /*TODO*/ //inv. imm bit of rd. expr.- rd^= (1<<imm) r_strbuf_appendf(&op->esil,"%d,1,<<,r%u%c,^=",rs(),rdB(1)); return 0; case H8300_BCLR_IMM2R8: //clear imm bit of rd. expr.- rd&= !(1<<imm) r_strbuf_appendf(&op->esil, "%d,1,<<,!,r%u%c,&=", rs(), rdB(1)); return 0; case H8300_BTST: /*TODO*/ //see BTST above r_strbuf_appendf(&op->esil, "%d,%d,1,<<,r%u%c,&,>>,!,Z,=", rs(), rs(), rdB(1)); return 0; case H8300_BOR_BIOR: /*TODO*/ if (!(buf[1] & 0x80)) { //BOR //C|=(rd&(1<<imm))>>imm r_strbuf_appendf(&op->esil, "%d,%d,1,<<,r%u%c,&,>>,C,|=", rs(), rs(), rdB(1)); } else { //BIOR //C|=!(rd&(1<<imm))>>imm r_strbuf_appendf (&op->esil, "%d,%d,1,<<,r%u%c,&,>>,!,C,|=", rs (), rs (), rdB (1)); } return 0; case H8300_BXOR_BIXOR: /*TODO*/ if (!(buf[1] & 0x80)) { //BXOR //C^=(rd&(1<<imm))>>imm r_strbuf_appendf(&op->esil, "%d,%d,1,<<,r%u%c,&,>>,C,^=", rs(), rs(), rdB(1)); } else { //BIXOR r_strbuf_appendf (&op->esil, "%d,%d,1,<<,r%u%c,&,>>,!,C,^=", rs (), rs (), rdB (1)); } return 0; case H8300_BAND_BIAND: /*TODO check functionality*/ //C&=(rd&(1<<imm))>>imm if (!(buf[1] & 0x80)) { //BAND r_strbuf_appendf(&op->esil, "%d,%d,1,<<,r%u%c,&,>>,C,&=", rs(), rs(), rdB(1)); } else { //BIAND r_strbuf_appendf (&op->esil, "%d,%d,1,<<,r%u%c,&,>>,!,C,&=", rs (), rs (), rdB (1)); } return 0; case H8300_BILD_IMM2R8: /*TODO*/ if (!(buf[1] & 0x80)) { //BLD r_strbuf_appendf(&op->esil, "%d,%d,1,<<,r%u%c,&,>>,C,=", rs(), rs(), rdB(1)); } else { //BILD r_strbuf_appendf (&op->esil, "%d,%d,1,<<,r%u%c,&,>>,!,C,=", rs (), rs (), rdB (1)); } return 0; case H8300_MOV_IMM162R16: /*TODO*/ return 0; case H8300_EEPMOV: /*TODO*/ return 0; case H8300_BIAND_IMM2IND16: /*TODO*/ return 0; case H8300_BCLR_R2IND16: /*TODO*/ return 0; case H8300_BIAND_IMM2ABS8: /*TODO*/ return 0; case H8300_BCLR_R2ABS8: /*TODO*/ return 0; default: break; }; return ret; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle; cs_insn *insn; int mode, n, ret; mode = CS_MODE_BIG_ENDIAN; ret = cs_open (CS_ARCH_SYSZ, mode, &handle); op->type = R_ANAL_OP_TYPE_NULL; op->size = 0; op->delay = 0; r_strbuf_init (&op->esil); if (ret == CS_ERR_OK) { cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); // capstone-next n = cs_disasm_ex (handle, (const 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 SYSZ_INS_BRCL: case SYSZ_INS_BRASL: op->type = R_ANAL_OP_TYPE_CALL; break; case SYSZ_INS_BR: op->type = R_ANAL_OP_TYPE_JMP; break; case SYSZ_INS_BRC: case SYSZ_INS_BER: case SYSZ_INS_BHR: case SYSZ_INS_BHER: case SYSZ_INS_BLR: case SYSZ_INS_BLER: case SYSZ_INS_BLHR: case SYSZ_INS_BNER: case SYSZ_INS_BNHR: case SYSZ_INS_BNHER: case SYSZ_INS_BNLR: case SYSZ_INS_BNLER: case SYSZ_INS_BNLHR: case SYSZ_INS_BNOR: case SYSZ_INS_BOR: case SYSZ_INS_BASR: case SYSZ_INS_BRAS: case SYSZ_INS_BRCT: case SYSZ_INS_BRCTG: op->type = R_ANAL_OP_TYPE_CJMP; break; case SYSZ_INS_JE: case SYSZ_INS_JGE: case SYSZ_INS_JHE: case SYSZ_INS_JGHE: case SYSZ_INS_JH: case SYSZ_INS_JGH: case SYSZ_INS_JLE: case SYSZ_INS_JGLE: case SYSZ_INS_JLH: case SYSZ_INS_JGLH: case SYSZ_INS_JL: case SYSZ_INS_JGL: case SYSZ_INS_JNE: case SYSZ_INS_JGNE: case SYSZ_INS_JNHE: case SYSZ_INS_JGNHE: case SYSZ_INS_JNH: case SYSZ_INS_JGNH: case SYSZ_INS_JNLE: case SYSZ_INS_JGNLE: case SYSZ_INS_JNLH: case SYSZ_INS_JGNLH: case SYSZ_INS_JNL: case SYSZ_INS_JGNL: case SYSZ_INS_JNO: case SYSZ_INS_JGNO: case SYSZ_INS_JO: case SYSZ_INS_JGO: case SYSZ_INS_JG: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = INSOP(0).imm; op->fail = addr+op->size; break; case SYSZ_INS_J: op->type = R_ANAL_OP_TYPE_JMP; op->jump = INSOP(0).imm; op->fail = UT64_MAX; break; } } cs_free (insn, n); cs_close (&handle); } return op->size; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle; cs_insn *insn; int mode = (a->bits==64)? CS_MODE_64: (a->bits==32)? CS_MODE_32: (a->bits==16)? CS_MODE_16: 0; int n, ret = cs_open (CS_ARCH_X86, mode, &handle); op->type = R_ANAL_OP_TYPE_NULL; op->jump = UT64_MAX; op->fail = UT64_MAX; op->ptr = op->val = UT64_MAX; op->size = 0; op->delay = 0; r_strbuf_init (&op->esil); if (ret == CS_ERR_OK) { cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); // capstone-next n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { int rs = a->bits/8; const char *pc = (a->bits==16)?"ip": (a->bits==32)?"eip":"rip"; const char *sp = (a->bits==16)?"sp": (a->bits==32)?"esp":"rsp"; op->size = insn->size; op->prefix = 0; switch (insn->detail->x86.prefix[0]) { case X86_PREFIX_REPNE: op->prefix |= R_ANAL_OP_PREFIX_REPNE; case X86_PREFIX_REP: op->prefix |= R_ANAL_OP_PREFIX_REP; case X86_PREFIX_LOCK: op->prefix |= R_ANAL_OP_PREFIX_LOCK; } switch (insn->id) { case X86_INS_FNOP: case X86_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; if (a->decode) esilprintf (op, ""); break; case X86_INS_HLT: op->type = R_ANAL_OP_TYPE_TRAP; break; case X86_INS_CLI: case X86_INS_STI: case X86_INS_CLC: case X86_INS_STC: break; case X86_INS_MOV: case X86_INS_MOVZX: case X86_INS_MOVABS: case X86_INS_MOVHPD: case X86_INS_MOVHPS: case X86_INS_MOVLPD: case X86_INS_MOVLPS: case X86_INS_MOVBE: case X86_INS_MOVSB: case X86_INS_MOVSD: case X86_INS_MOVSQ: case X86_INS_MOVSS: case X86_INS_MOVSW: case X86_INS_MOVD: case X86_INS_MOVQ: case X86_INS_MOVDQ2Q: op->type = R_ANAL_OP_TYPE_MOV; switch (INSOP(0).type) { case X86_OP_MEM: op->ptr = INSOP(0).mem.disp; break; } switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; break; } break; case X86_INS_CMP: case X86_INS_VCMP: case X86_INS_CMPPD: case X86_INS_CMPPS: case X86_INS_CMPSW: case X86_INS_CMPSD: case X86_INS_CMPSQ: case X86_INS_CMPSB: case X86_INS_CMPSS: case X86_INS_TEST: op->type = R_ANAL_OP_TYPE_CMP; break; case X86_INS_LEA: op->type = R_ANAL_OP_TYPE_LEA; switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; break; } break; case X86_INS_ENTER: case X86_INS_PUSH: case X86_INS_PUSHAW: case X86_INS_PUSHAL: case X86_INS_PUSHF: op->type = R_ANAL_OP_TYPE_PUSH; break; case X86_INS_LEAVE: case X86_INS_POP: case X86_INS_POPAW: case X86_INS_POPAL: case X86_INS_POPF: case X86_INS_POPCNT: op->type = R_ANAL_OP_TYPE_POP; break; case X86_INS_RET: case X86_INS_RETF: case X86_INS_IRET: case X86_INS_IRETD: case X86_INS_IRETQ: case X86_INS_SYSRET: op->type = R_ANAL_OP_TYPE_RET; if (a->decode) esilprintf (op, "%s,[%d],%s,=,%d,%s,+=", sp, rs, pc, rs, sp); break; case X86_INS_INT1: case X86_INS_INT3: case X86_INS_INTO: case X86_INS_INT: case X86_INS_VMCALL: case X86_INS_VMMCALL: case X86_INS_SYSCALL: op->type = R_ANAL_OP_TYPE_TRAP; if (a->decode) esilprintf (op, "%d,$", (int)INSOP(0).imm); break; case X86_INS_JL: case X86_INS_JLE: case X86_INS_JA: case X86_INS_JAE: case X86_INS_JB: case X86_INS_JBE: case X86_INS_JCXZ: case X86_INS_JECXZ: case X86_INS_JO: case X86_INS_JNO: case X86_INS_JS: case X86_INS_JNS: case X86_INS_JP: case X86_INS_JNP: case X86_INS_JE: case X86_INS_JNE: case X86_INS_JG: case X86_INS_JGE: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = INSOP(0).imm; op->fail = addr+op->size; if (a->decode) { if (INSOP(0).type==X86_OP_IMM) { // TODO } } break; case X86_INS_CALL: case X86_INS_LCALL: if (INSOP(0).type==X86_OP_IMM) { op->type = R_ANAL_OP_TYPE_CALL; // TODO: what if UCALL? // TODO: use imm_size op->jump = INSOP(0).imm; op->fail = addr+op->size; } else { op->type = R_ANAL_OP_TYPE_UCALL; } break; case X86_INS_JMP: case X86_INS_LJMP: // TODO: what if UJMP? op->jump = INSOP(0).imm; op->type = R_ANAL_OP_TYPE_JMP; if (a->decode) { ut64 dst = INSOP(0).imm; esilprintf (op, "0x%"PFMT64x",%s,=", dst, pc); } break; case X86_INS_IN: case X86_INS_INSW: case X86_INS_INSD: case X86_INS_INSB: case X86_INS_OUT: case X86_INS_OUTSB: case X86_INS_OUTSD: case X86_INS_OUTSW: op->type = R_ANAL_OP_TYPE_IO; break; case X86_INS_VXORPD: case X86_INS_VXORPS: case X86_INS_VPXORD: case X86_INS_VPXORQ: case X86_INS_VPXOR: case X86_INS_KXORW: case X86_INS_PXOR: case X86_INS_XOR: op->type = R_ANAL_OP_TYPE_XOR; break; case X86_INS_OR: op->type = R_ANAL_OP_TYPE_OR; break; case X86_INS_SUB: case X86_INS_DEC: case X86_INS_PSUBB: case X86_INS_PSUBW: case X86_INS_PSUBD: case X86_INS_PSUBQ: case X86_INS_PSUBSB: case X86_INS_PSUBSW: case X86_INS_PSUBUSB: case X86_INS_PSUBUSW: op->type = R_ANAL_OP_TYPE_SUB; break; case X86_INS_AND: case X86_INS_ANDN: case X86_INS_ANDPD: case X86_INS_ANDPS: case X86_INS_ANDNPD: case X86_INS_ANDNPS: op->type = R_ANAL_OP_TYPE_AND; break; case X86_INS_DIV: op->type = R_ANAL_OP_TYPE_DIV; break; case X86_INS_MUL: op->type = R_ANAL_OP_TYPE_MUL; break; case X86_INS_INC: case X86_INS_ADD: case X86_INS_FADD: case X86_INS_ADDPD: op->type = R_ANAL_OP_TYPE_ADD; break; } } cs_free (insn, n); cs_close (&handle); } return op->size; }
static void analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf) { r_strbuf_init (&op->esil); r_strbuf_set (&op->esil, ""); switch (buf[0]) { // Irregulars sorted by lower nibble case 0x00: /* nop */ emit (","); break; case 0x10: /* jbc bit, offset */ k (BIT_R "?{," BIT_MASK XI(BIT, "&") JMP ",}"); break; case 0x20: /* jb bit, offset */ k (BIT_R CJMP); break; case 0x30: /* jnb bit, offset */ k (BIT_R "!," CJMP); break; case 0x40: /* jc offset */ h ("c,1,&," CJMP); break; case 0x50: /* jnc offset */ h ("c,1,&,!," CJMP ); break; case 0x60: /* jz offset */ h ("a,0,==," CJMP); break; case 0x70: /* jnz offset */ h ("a,0,==,!," CJMP); break; case 0x11: case 0x31: case 0x51: case 0x71: case 0x91: case 0xB1: case 0xD1: case 0xF1: /* acall addr11 */ case 0x12: /* lcall addr16 */ j (CALL); /* fall through */ case 0x01: case 0x21: case 0x41: case 0x61: case 0x81: case 0xA1: case 0xC1: case 0xE1: /* ajmp addr11 */ case 0x02: /* ljmp addr16 */ case 0x80: /* sjmp offset */ j (JMP); break; case 0x22: /* ret */ case 0x32: /* reti */ emitf (POP2 "pc,="); break; case 0x03: /* rr a */ emit ("1,a,0x101,*,>>,a,=," FLAG_P); break; case 0x04: /* inc a */ h (XI(A, "++") FLAG_P); break; case 0x05: /* inc direct */ h (XI(IB1, "++")); break; case 0x06: case 0x07: /* inc @Ri */ j (XI(RI, "++")); break; case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0E: case 0x0F: /* dec @Rn */ h (XI(RN, "++")); break; case 0x13: /* rrc a */ emit ("7,c,<<,1,a,&,c,=,0x7f,1,a,>>,&,+,a,=," FLAG_P); break; case 0x14: /* dec a */ h (XI(A, "--") FLAG_P); break; case 0x15: /* dec direct */ h (XI(IB1, "--")); break; case 0x16: case 0x17: /* dec @Ri */ j (XI(RI, "--")); break; case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F: /* dec @Rn */ h (XI(RN, "--")); break; case 0x23: /* rl a */ h ("7,a,0x101,*,>>,a,=," FLAG_P); break; TEMPLATE_ALU (0x20, "+", FLAG_C FLAG_AC FLAG_OV FLAG_P) /* 0x24..0x2f add a,.. */ case 0x33: /* rlc a */ h ("c,1,&,a,a,+=,$c7,c,=,a,+=," FLAG_P); break; TEMPLATE_ALU_C (0x30, "+", FLAG_C FLAG_AC FLAG_OV FLAG_P) /* 0x34..0x2f addc a,.. */ case 0x42: /* orl direct, a */ h (XR(A) XI(IB1, "|")); break; case 0x43: /* orl direct, imm */ h (XR(L2) XI(IB1, "|")); break; TEMPLATE_ALU (0x40, "|", FLAG_P) /* 0x44..0x4f orl a,.. */ case 0x52: /* anl direct, a */ h (XR(A) XI(IB1, "&")); break; case 0x53: /* anl direct, imm */ h (XR(L2) XI(IB1, "&")); break; TEMPLATE_ALU (0x50, "&", FLAG_P) /* 0x54..0x5f anl a,.. */ case 0x62: /* xrl direct, a */ h (XR(A) XI(IB1, "^")); break; case 0x63: /* xrl direct, imm */ h (XR(L2) XI(IB1, "^")); break; TEMPLATE_ALU (0x60, "^", FLAG_P) /* 0x64..0x6f xrl a,.. */ case 0x72: /* orl C, bit */ k (BIT_R XI(C, "|")); break; case 0x73: /* jmp @a+dptr */ emit ("dptr,a,+,pc,="); break; case 0x74: /* mov a, imm */ h (XR(L1) XW(A) FLAG_P); break; case 0x75: /* mov direct, imm */ h (XR(L2) XW(IB1)); break; case 0x76: case 0x77: /* mov @Ri, imm */ j (XR(L1) XW(RI)); break; case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F: /* mov Rn, imm */ h (XR(L1) XW(RN)); break; case 0x82: /* anl C, bit */ k (BIT_R XI(C, "&")); break; case 0x83: /* movc a, @a+pc */ emit ("a,pc,--,+,[1]," XW(A) FLAG_P); break; case 0x84: /* div ab */ emit ("b,!,OV,=,0,a,b,a,/=,a,b,*,-,-,b,=,0,c,="); break; case 0x85: /* mov direct, direct */ h (XR(IB1) XW(IB2)); break; case 0x86: case 0x87: /* mov direct, @Ri */ j (XR(RI) XW(IB1)); break; case 0x88: case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E: case 0x8F: /* mov direct, Rn */ h (XR(RN) XW(IB1)); break; case 0x90: /* mov dptr, imm */ h (XR(L16) XW(DP)); break; case 0x92: /* mov bit, C */ k (BIT_C BIT_MASK XR(BIT) "&,|," XW(BIT)); break; case 0x93: /* movc a, @a+dptr */ h ("a,dptr,+,[1]," XW(A) FLAG_P); break; TEMPLATE_ALU_C (0x90, "-", FLAG_B FLAG_AB FLAG_OB FLAG_P) /* 0x94..0x9f subb a,.. */ case 0xA0: /* orl C, /bit */ k (BIT_R "!," XI(C, "|")); break; case 0xA2: /* mov C, bit */ k (BIT_R XW(C)); break; case 0xA3: /* inc dptr */ h (XI(DP, "++")); break; case 0xA4: /* mul ab */ emit ("8,a,b,*,NUM,>>,NUM,!,!,ov,=,b,=,a,=,0,c,="); break; case 0xA5: /* "reserved" */ emit ("0,trap"); break; case 0xA6: case 0xA7: /* mov @Ri, direct */ j (XR(IB1) XW(RI)); break; case 0xA8: case 0xA9: case 0xAA: case 0xAB: case 0xAC: case 0xAD: case 0xAE: case 0xAF: /* mov Rn, direct */ h (XR(IB1) XW(RN)); break; case 0xB0: /* anl C, /bit */ k (BIT_R "!," XI(C, "&")); break; case 0xB2: /* cpl bit */ k (BIT_SET XI(BIT, "^")); break; case 0xB3: /* cpl C */ h ("1," XI(C, "^")); break; case 0xB4: /* cjne a, imm, offset */ h (XR(L1) XR(A) "-," CJMP); break; case 0xB5: /* cjne a, direct, offset */ h (XR(IB1) XR(A) "-," CJMP); break; case 0xB6: case 0xB7: /* cjne @ri, imm, offset */ j (XR(L1) XR(RI) "-," CJMP); break; case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF: /* cjne Rn, imm, offset */ h (XR(L1) XR(RN) "-," CJMP); break; case 0xC0: /* push direct */ h (XR(IB1) PUSH1); break; case 0xC2: /* clr bit */ k (BIT_MASK XI(BIT, "&")); break; case 0xC3: /* clr C */ h ("0," XW(C)); break; case 0xC4: /* swap a */ h ("0xff,4,a,0x101,*,>>,&," XW(A) FLAG_P); break; case 0xC5: /* xch a, direct */ h (XR(A) "0,+," XR(IB1) XW(A) XW(IB1) FLAG_P); break; case 0xC6: case 0xC7: /* xch a, @Ri */ j (XR(A) "0,+," XR(RI) XW(A) XW(RI) FLAG_P); break; case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF: /* xch a, Rn */ h (XR(A) "0,+," XR(RN) XW(A) XW(RN) FLAG_P); break; case 0xD0: /* pop direct */ h (POP1 XW(IB1)); break; case 0xD2: /* setb bit */ k (BIT_SET XI(BIT, "|")); break; case 0xD3: /* setb C */ h ("1," XW(C)); break; case 0xD4: /* da a */ // BCD adjust after add: // if (lower nibble > 9) or (AC == 1) add 6 // if (higher nibble > 9) or (C == 1) add 0x60 // carry |= carry caused by this operation emit ("a,0x0f,&,9,<,ac,|,?{,6,a,+=,$c7,c,|=,},a,0xf0,&,0x90,<,c,|,?{,0x60,a,+=,$c7,c,|=,}," FLAG_P); break; case 0xD5: /* djnz direct, offset */ h (XI(IB1, "--") XR(IB1) "0,==,!," CJMP); break; case 0xD6: case 0xD7: /* xchd a, @Ri*/ j (XR(A) "0xf0,&," XR(RI) "0x0f,&,|," XR(RI) "0xf0,&," XR(A) "0x0f,&,|," XW(RI) XW(A) FLAG_P); break; case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE: case 0xDF: /* djnz Rn, offset */ h (XI(RN, "--") XR(RN) "0,==,!," CJMP); break; case 0xE0: /* movx a, @dptr */ h (XR(DPX) XW(A) FLAG_P); break; case 0xE2: case 0xE3: /* movx a, @Ri */ j (XR(R0X) XW(A) FLAG_P); break; case 0xE4: /* clr a */ emit ("0," XW(A) FLAG_P); break; case 0xE5: /* mov a, direct */ h (XR(IB1) XW(A) FLAG_P); break; case 0xE6: case 0xE7: /* mov a, @Ri */ j (XR(RI) XW(A) FLAG_P); break; case 0xE8: case 0xE9: case 0xEA: case 0xEB: case 0xEC: case 0xED: case 0xEE: case 0xEF: /* mov a, Rn */ h (XR(RN) XW(A) FLAG_P); break; case 0xF0: /* movx @dptr, a */ h (XR(A) XW(DPX)); break; case 0xF2: case 0xF3: /* movx @Ri, a */ j (XR(A) XW(R0X)); break; case 0xF4: /* cpl a */ h ("255," XI(A, "^") FLAG_P); break; case 0xF5: /* mov direct, a */ h (XR(A) XW(IB1)); break; case 0xF6: case 0xF7: /* mov @Ri, a */ j (XR(A) XW(RI)); break; case 0xF8: case 0xF9: case 0xFA: case 0xFB: case 0xFC: case 0xFD: case 0xFE: case 0xFF: /* mov Rn, a */ h (XR(A) XW(RN)); break; default: break; } }
static int bpf_anal(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) { RBpfSockFilter *f = (RBpfSockFilter *)data; memset (op, '\0', sizeof (RAnalOp)); op->jump = UT64_MAX; op->fail = UT64_MAX; op->ptr = op->val = UT64_MAX; op->type = R_ANAL_OP_TYPE_UNK; op->size = 8; op->addr = addr; r_strbuf_init (&op->esil); switch (f->code) { case BPF_RET | BPF_A: op->type = R_ANAL_OP_TYPE_RET; esilprintf (op, "A,R0,=,0,$"); break; case BPF_RET | BPF_K: case BPF_RET | BPF_X: op->type = R_ANAL_OP_TYPE_RET; if (BPF_SRC (f->code) == BPF_K) { esilprintf (op, "%" PFMT64d ",R0,=,0,$", f->k); } else if (BPF_SRC (f->code) == BPF_X) { esilprintf (op, "X,R0,=,0,$"); } break; case BPF_MISC_TAX: op->type = R_ANAL_OP_TYPE_MOV; SET_REG_SRC_DST (op, "A", "X"); esilprintf (op, "A,X,="); break; case BPF_MISC_TXA: op->type = R_ANAL_OP_TYPE_MOV; SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,="); break; case BPF_ST: if (INSIDE_M (f->k)) { op->type = R_ANAL_OP_TYPE_MOV; SET_REG_SRC_DST (op, "A", M[f->k]); esilprintf (op, "A,M[%" PFMT64d "],=", f->k); } else { op->type = R_ANAL_OP_TYPE_ILL; } break; case BPF_STX: if (INSIDE_M (f->k)) { op->type = R_ANAL_OP_TYPE_MOV; SET_REG_SRC_DST (op, "X", M[f->k]); esilprintf (op, "X,M[%" PFMT64d "],=", f->k); } else { op->type = R_ANAL_OP_TYPE_ILL; } break; case BPF_LD_W | BPF_LEN: op->type = R_ANAL_OP_TYPE_MOV; SET_REG_SRC_DST (op, "len", "A"); esilprintf (op, "len,A,=", f->k); break; case BPF_LDX | BPF_LEN: op->type = R_ANAL_OP_TYPE_MOV; SET_REG_SRC_DST (op, "len", "X"); esilprintf (op, "len,X,=", f->k); break; case BPF_LD_W | BPF_ABS: EMIT_LOAD (op, anal->gp + f->k, 4); SET_A_DST (op); esilprintf (op, "len,%" PFMT64d ",>,?{,0,R0,=,0,$,BREAK,},%" PFMT64d ",[4],A,=", f->k + 4, op->ptr); break; case BPF_LD_H | BPF_ABS: EMIT_LOAD (op, anal->gp + f->k, 2); SET_A_DST (op); esilprintf (op, "len,%" PFMT64d ",>,?{,0,R0,=,0,$,BREAK,}," "%" PFMT64d ",[2],A,=", f->k + 2, op->ptr); break; case BPF_LD_B | BPF_ABS: EMIT_LOAD (op, anal->gp + f->k, 1); SET_A_DST (op); esilprintf (op, "len,%" PFMT64d ",>,?{,0,R0,=,0,$,BREAK,}," "%" PFMT64d ",[1],A,=", f->k + 1, op->ptr); break; case BPF_LD_W | BPF_IND: op->type = R_ANAL_OP_TYPE_LOAD; op->ptrsize = 4; SET_A_DST (op); esilprintf (op, "len,%" PFMT64d ",X,+,0xffffffff,&,>,?{,0,R0,=,0,$,BREAK,}," "%" PFMT64d ",X,+,0xffffffff,&,[4],A,=", (st32)f->k + 4, anal->gp + (st32)f->k); break; case BPF_LD_H | BPF_IND: op->type = R_ANAL_OP_TYPE_LOAD; op->ptrsize = 2; SET_A_DST (op); esilprintf (op, "len,%" PFMT64d ",X,+,0xffffffff,&,>,?{,0,R0,=,0,$,BREAK,}," "%" PFMT64d ",X,+,0xffffffff,&,[2],A,=", (st32)f->k + 2, anal->gp + (st32)f->k); break; case BPF_LD_B | BPF_IND: op->type = R_ANAL_OP_TYPE_LOAD; op->ptrsize = 1; SET_A_DST (op); esilprintf (op, "len,%" PFMT64d ",X,+,0xffffffff,&,>,?{,0,R0,=,0,$,BREAK,}," "%" PFMT64d ",X,+,0xffffffff,&,[1],A,=", (st32)f->k + 1, anal->gp + (st32)f->k); break; case BPF_LD | BPF_IMM: op->type = R_ANAL_OP_TYPE_MOV; op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); esilprintf (op, "0x%08" PFMT64x ",A,=", f->k); break; case BPF_LDX | BPF_IMM: op->type = R_ANAL_OP_TYPE_MOV; op->val = f->k; SET_REG_DST_IMM (op, "X", f->k); esilprintf (op, "0x%08" PFMT64x ",X,=", f->k); break; case BPF_LDX_B | BPF_MSH: op->type = R_ANAL_OP_TYPE_LOAD; op->ptrsize = 1; op->ptr = anal->gp + f->k; SET_A_DST (op); esilprintf (op, "%" PFMT64d ",[1],0xf,&,4,*,X,=", op->ptr); break; case BPF_LD | BPF_MEM: op->type = R_ANAL_OP_TYPE_MOV; if (INSIDE_M (f->k)) { SET_REG_SRC_DST (op, M[f->k], "A"); esilprintf (op, "M[%" PFMT64d "],A,=", f->k); } else { op->type = R_ANAL_OP_TYPE_ILL; } break; case BPF_LDX | BPF_MEM: op->type = R_ANAL_OP_TYPE_MOV; if (INSIDE_M (f->k)) { SET_REG_SRC_DST (op, M[f->k], "X"); esilprintf (op, "M[%" PFMT64d "],X,=", f->k); } else { op->type = R_ANAL_OP_TYPE_ILL; } break; case BPF_JMP_JA: op->type = R_ANAL_OP_TYPE_JMP; op->jump = addr + 8 + f->k * 8; esilprintf (op, "%" PFMT64d ",pc,=", op->jump); break; case BPF_JMP_JGT | BPF_X: case BPF_JMP_JGT | BPF_K: EMIT_CJMP (op, addr, f); op->cond = R_ANAL_COND_GT; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; esilprintf (op, "%" PFMT64d ",A,>,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->val, op->jump, op->fail); } else if (BPF_SRC (f->code) == BPF_X) { esilprintf (op, "X,A,>,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->jump, op->fail); } else { op->type = R_ANAL_OP_TYPE_ILL; } break; case BPF_JMP_JGE | BPF_X: case BPF_JMP_JGE | BPF_K: EMIT_CJMP (op, addr, f); op->cond = R_ANAL_COND_GE; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; esilprintf (op, "%" PFMT64d ",A,>=,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->val, op->jump, op->fail); } else { esilprintf (op, "X,A,>=,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->jump, op->fail); } break; case BPF_JMP_JEQ | BPF_X: case BPF_JMP_JEQ | BPF_K: EMIT_CJMP (op, addr, f); op->cond = R_ANAL_COND_EQ; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; esilprintf (op, "%" PFMT64d ",A,==,$z,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->val, op->jump, op->fail); } else { esilprintf (op, "X,A,==,$z,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->jump, op->fail); } break; case BPF_JMP_JSET | BPF_X: case BPF_JMP_JSET | BPF_K: EMIT_CJMP (op, addr, f); if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; esilprintf (op, "%" PFMT64d ",A,&,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->val, op->jump, op->fail); } else { esilprintf (op, "X,A,&,!,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->val, op->jump, op->fail); } break; case BPF_ALU_NEG: op->type = R_ANAL_OP_TYPE_NOT; esilprintf (op, "A,0,-,A,="); SET_REG_SRC_DST (op, "A", "A"); break; case BPF_ALU_LSH | BPF_X: case BPF_ALU_LSH | BPF_K: op->type = R_ANAL_OP_TYPE_SHL; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); esilprintf (op, "%" PFMT64d ",A,<<=", f->k); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,<<="); } break; case BPF_ALU_RSH | BPF_X: case BPF_ALU_RSH | BPF_K: op->type = R_ANAL_OP_TYPE_SHR; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); esilprintf (op, "%" PFMT64d ",A,>>=", f->k); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,>>="); } break; case BPF_ALU_ADD | BPF_X: case BPF_ALU_ADD | BPF_K: op->type = R_ANAL_OP_TYPE_ADD; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", op->val); esilprintf (op, "%" PFMT64d ",A,+=", op->val); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,+="); } break; case BPF_ALU_SUB | BPF_X: case BPF_ALU_SUB | BPF_K: op->type = R_ANAL_OP_TYPE_SUB; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", op->val); esilprintf (op, "%" PFMT64d ",A,-=", op->val); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,-="); } break; case BPF_ALU_MUL | BPF_X: case BPF_ALU_MUL | BPF_K: op->type = R_ANAL_OP_TYPE_MUL; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); esilprintf (op, "%" PFMT64d ",A,*=", f->k); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,*="); } break; case BPF_ALU_DIV | BPF_X: case BPF_ALU_DIV | BPF_K: op->type = R_ANAL_OP_TYPE_DIV; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); if (f->k == 0) { esilprintf (op, "0,R0,=,0,$"); } else { esilprintf (op, "%" PFMT64d ",A,/=", f->k); } } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "0,X,==,$z,?{,0,R0,=,0,$,BREAK,},X,A,/="); } break; case BPF_ALU_MOD | BPF_X: case BPF_ALU_MOD | BPF_K: op->type = R_ANAL_OP_TYPE_MOD; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); if (f->k == 0) { esilprintf (op, "0,R0,=,0,$"); } else { esilprintf (op, "%" PFMT64d ",A,%%=", f->k); } } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "0,X,==,$z,?{,0,R0,=,0,$,BREAK,},X,A,%%="); } break; case BPF_ALU_AND | BPF_X: case BPF_ALU_AND | BPF_K: op->type = R_ANAL_OP_TYPE_AND; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); esilprintf (op, "%" PFMT64d ",A,&=", f->k); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,&="); } break; case BPF_ALU_OR | BPF_X: case BPF_ALU_OR | BPF_K: op->type = R_ANAL_OP_TYPE_OR; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); esilprintf (op, "%" PFMT64d ",A,|=", f->k); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,|,A,="); } break; case BPF_ALU_XOR | BPF_X: case BPF_ALU_XOR | BPF_K: op->type = R_ANAL_OP_TYPE_XOR; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); esilprintf (op, "%" PFMT64d ",A,^=", f->k); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,^="); } break; default: op->type = R_ANAL_OP_TYPE_ILL; break; } return op->size; }
static int analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) { char str[8][32]; int i; r_strbuf_init (&op->esil); r_strbuf_set (&op->esil, ""); if (insn) { // caching operands for (i=0; i<insn->detail->mips.op_count && i<8; i++) { *str[i]=0; ARG (i); } } if (insn) switch (insn->id) { case MIPS_INS_NOP: r_strbuf_setf (&op->esil, ","); break; case MIPS_INS_BREAK: r_strbuf_setf (&op->esil, "%s,%s,TRAP", ARG (0), ARG (0)); break; case MIPS_INS_SW: case MIPS_INS_SWL: case MIPS_INS_SWR: r_strbuf_appendf (&op->esil, "%s,%s,=[4]", ARG (0), ARG (1)); break; case MIPS_INS_SH: r_strbuf_appendf (&op->esil, "%s,%s,=[2]", ARG (0), ARG (1)); break; case MIPS_INS_SWC1: case MIPS_INS_SWC2: r_strbuf_setf (&op->esil, "%s,$", ARG (1)); break; case MIPS_INS_SB: r_strbuf_appendf (&op->esil, "%s,%s,=[1]", ARG (0), ARG (1)); break; case MIPS_INS_CMP: case MIPS_INS_CMPU: case MIPS_INS_CMPGU: case MIPS_INS_CMPGDU: case MIPS_INS_CMPI: r_strbuf_appendf (&op->esil, "%s,%s,==", ARG (1), ARG (0)); break; case MIPS_INS_SHRAV: case MIPS_INS_SHRAV_R: case MIPS_INS_SHRA: case MIPS_INS_SHRA_R: case MIPS_INS_SRA: r_strbuf_appendf (&op->esil, "%s,%s,>>,31,%s,>>,?{,32,%s,-,%s,1,<<,1,-,<<,}{,0,},|,%s,=,", ARG (2), ARG (1), ARG (1), ARG (2), ARG (2), ARG (0)); break; case MIPS_INS_SHRL: // suffix 'S' forces conditional flag to be updated case MIPS_INS_SRLV: case MIPS_INS_SRL: r_strbuf_appendf (&op->esil, "%s,%s,>>,%s,=", ARG (2), ARG (1), ARG (0)); break; case MIPS_INS_SLLV: case MIPS_INS_SLL: r_strbuf_appendf (&op->esil, "%s,%s,<<,%s,=", ARG (2), ARG (1), ARG (0)); break; case MIPS_INS_BAL: case MIPS_INS_JAL: r_strbuf_appendf (&op->esil, ES_TRAP_DS () "," ES_CALL_D ("%s"), ARG (0)); break; case MIPS_INS_JALR: case MIPS_INS_JALRS: if (OPCOUNT () < 2) { r_strbuf_appendf (&op->esil, ES_TRAP_DS () "," ES_CALL_D ("%s"), ARG (0)); } else { PROTECT_ZERO () { r_strbuf_appendf (&op->esil, ES_TRAP_DS () "," ES_CALL_DR ("%s","%s"), ARG (0), ARG (1)); } } break; case MIPS_INS_JALRC: // no delay if (OPCOUNT () < 2) { r_strbuf_appendf (&op->esil, ES_TRAP_DS () "," ES_CALL_ND ("%s"), ARG (0)); } else { PROTECT_ZERO () { r_strbuf_appendf (&op->esil, ES_TRAP_DS () "," ES_CALL_NDR ("%s","%s"), ARG (0), ARG (1)); } } break; case MIPS_INS_JRADDIUSP: // increment stackpointer in X and jump to %ra r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",%d,sp,+=,"ES_J ("ra"), ARG (0)); break; case MIPS_INS_JR: case MIPS_INS_JRC: case MIPS_INS_J: case MIPS_INS_B: // ??? // jump to address with conditional r_strbuf_appendf (&op->esil, ES_TRAP_DS () "," ES_J ("%s"), ARG (0)); break; case MIPS_INS_BNE: // bne $s, $t, offset r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",%s,%s,==,$z,!,?{,"ES_J ("%s")",}", ARG (0), ARG (1), ARG (2)); break; case MIPS_INS_BEQ: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",%s,%s,==,$z,?{,"ES_J ("%s")",}", ARG (0), ARG (1), ARG (2)); break; case MIPS_INS_BZ: case MIPS_INS_BEQZ: case MIPS_INS_BEQZC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",%s,0,==,$z,?{,"ES_J ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BNEZ: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",%s,0,==,$z,!,?{,"ES_J ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BEQZALC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",%s,0,==,$z,?{,"ES_CALL_ND ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BLEZ: case MIPS_INS_BLEZC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,%s,==,$z,?{,"ES_J ("%s")",BREAK,},", ARG (0), ARG (1)); r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",1,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_J ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BGEZ: case MIPS_INS_BGEZC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_J ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BGEZAL: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_CALL_D ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BGEZALC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_CALL_ND ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BGTZALC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,%s,==,$z,?{,BREAK,},", ARG(0)); r_strbuf_appendf (&op->esil, "0,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_CALL_ND ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BLTZAL: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",1,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_CALL_D ("%s")",}", ARG(0), ARG(1)); break; case MIPS_INS_BLTZ: case MIPS_INS_BLTZC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",1,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_J ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BGTZ: case MIPS_INS_BGTZC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,%s,==,$z,?{,BREAK,},", ARG (0)); r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_J("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BTEQZ: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,t,==,$z,?{,"ES_J ("%s")",}", ARG (0)); break; case MIPS_INS_BTNEZ: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,t,==,$z,!,?{,"ES_J ("%s")",}", ARG (0)); break; case MIPS_INS_MOV: case MIPS_INS_MOVE: PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "%s,%s,=", ARG (1), REG (0)); } break; case MIPS_INS_MOVZ: case MIPS_INS_MOVF: PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "0,%s,==,$z,?{,%s,%s,=,}", ARG (2), ARG (1), REG (0)); } break; case MIPS_INS_MOVT: PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "1,%s,==,$z,?{,%s,%s,=,}", ARG (2), ARG (1), REG (0)); } break; case MIPS_INS_FSUB: case MIPS_INS_SUB: PROTECT_ZERO () { r_strbuf_appendf(&op->esil, "%s,%s,-,%s,=", ARG (1), ARG (2), ARG (0)); //r_strbuf_appendf(&op->esil, "%s,%s,>,?{,1,TRAP,}{,%s,%s,-,%s,=", // ARG (1), ARG (2), ARG (1), ARG (2), ARG (0)); } break; case MIPS_INS_SUBU: case MIPS_INS_DSUB: case MIPS_INS_DSUBU: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); r_strbuf_appendf (&op->esil, "%s,%s,-,%s,=", arg2, arg1, arg0); } break; case MIPS_INS_NEG: case MIPS_INS_NEGU: r_strbuf_appendf (&op->esil, "%s,0,-,%s,=,", ARG (1), ARG (0)); break; /** signed -- sets overflow flag */ case MIPS_INS_ADD: { PROTECT_ZERO () { r_strbuf_appendf(&op->esil, "%s,%s,-,%s,=", ARG (1), ARG (2), ARG (0)); #if 0 r_strbuf_appendf (&op->esil, "0,32,%s,%s,+,>>,>,?{,1,TRAP,}{,%s,%s,+,%s,=,}", ARG(2), ARG(1), ARG(2), ARG(1), ARG(0)); #endif } } break; case MIPS_INS_ADDI: PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "0,32,%s,0xffffffff,&,%s,+,>>,>,?{,1,TRAP,}{,%s,%s,+,%s,=,}", ARG(2), ARG(1), ARG(2), ARG(1), ARG(0)); } break; case MIPS_INS_DADD: case MIPS_INS_DADDI: /** unsigned */ case MIPS_INS_ADDU: case MIPS_INS_ADDIU: case MIPS_INS_DADDIU: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); PROTECT_ZERO () { if (*arg2 == '-') { r_strbuf_appendf (&op->esil, "%s,%s,-,%s,=", arg2+1, arg1, arg0); } else { r_strbuf_appendf (&op->esil, "%s,%s,+,%s,=", arg2, arg1, arg0); } } } break; case MIPS_INS_LI: r_strbuf_appendf (&op->esil, "0x%"PFMT64x",%s,=", IMM(1), ARG(0)); break; case MIPS_INS_LUI: r_strbuf_appendf (&op->esil, "0x%"PFMT64x"0000,%s,=", IMM(1), ARG(0)); break; case MIPS_INS_LB: case MIPS_INS_LBU: //one of these is wrong ESIL_LOAD ("1"); break; case MIPS_INS_LW: case MIPS_INS_LWC1: case MIPS_INS_LWC2: case MIPS_INS_LWL: case MIPS_INS_LWR: case MIPS_INS_LWU: case MIPS_INS_LL: case MIPS_INS_LLD: case MIPS_INS_LD: case MIPS_INS_LDI: case MIPS_INS_LDL: case MIPS_INS_LDC1: case MIPS_INS_LDC2: ESIL_LOAD ("4"); break; case MIPS_INS_LWX: case MIPS_INS_LH: case MIPS_INS_LHU: case MIPS_INS_LHX: ESIL_LOAD ("2"); break; case MIPS_INS_AND: case MIPS_INS_ANDI: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); r_strbuf_appendf (&op->esil, "%s,%s,&,%s,=", arg2, arg1, arg0); } break; case MIPS_INS_OR: case MIPS_INS_ORI: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "%s,%s,|,%s,=", arg2, arg1, arg0); } } break; case MIPS_INS_XOR: case MIPS_INS_XORI: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "%s,%s,^,%s,=", arg2, arg1, arg0); } } break; case MIPS_INS_NOR: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "%s,%s,|,0xffffffff,^,%s,=", arg2, arg1, arg0); } } break; case MIPS_INS_SLT: case MIPS_INS_SLTI: if (OPCOUNT () < 3) { r_strbuf_appendf (&op->esil, ES_IS_NEGATIVE ("%s")"," ES_IS_NEGATIVE ("%s")"," "==,$z,?{," "%s,%s,<,t,=," "}{," "%s,%s,>=,t,=," "}", ARG (1), ARG (0), ARG (1), ARG (0), ARG (1), ARG (0)); } else { r_strbuf_appendf (&op->esil, ES_IS_NEGATIVE ("%s")"," ES_IS_NEGATIVE ("%s")"," "==,$z,?{," "%s,%s,<,%s,=," "}{," "%s,%s,>=,%s,=," "}", ARG (2), ARG (1), ARG (2), ARG (1), ARG (0), ARG (2), ARG (1), ARG (0)); } break; case MIPS_INS_SLTU: case MIPS_INS_SLTIU: if (OPCOUNT () < 3) { r_strbuf_appendf (&op->esil, "%s,0xffffffff,&,%s,0xffffffff,&,<,t,=", ARG (1), ARG (0)); } else { r_strbuf_appendf (&op->esil, "%s,0xffffffff,&,%s,0xffffffff,&,<,%s,=", ARG (2), ARG (1), ARG (0)); } break; case MIPS_INS_MULT: case MIPS_INS_MULTU: r_strbuf_appendf (&op->esil, "%s,%s,*,0xffffffff,&,lo,=," ES_SIGN_EXT64 ("lo") ",32,%s,%s,*,>>,0xffffffff,&,hi,=," ES_SIGN_EXT64 ("hi"), ARG (0), ARG (1), ARG (0), ARG (1)); break; case MIPS_INS_MFLO: PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "lo,%s,=", REG (0)); } break; case MIPS_INS_MFHI: PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "hi,%s,=", REG (0)); } break; case MIPS_INS_MTLO: r_strbuf_appendf (&op->esil, "%s,lo,=,"ES_SIGN_EXT64 ("lo"), REG (0)); break; case MIPS_INS_MTHI: r_strbuf_appendf (&op->esil, "%s,hi,=,"ES_SIGN_EXT64 ("hi"), REG (0)); break; #if 0 // could not test div case MIPS_INS_DIV: case MIPS_INS_DIVU: case MIPS_INS_DDIV: case MIPS_INS_DDIVU: PROTECT_ZERO () { // 32 bit needs sign extend r_strbuf_appendf (&op->esil, "%s,%s,/,lo,=,%s,%s,%%,hi,=", REG(1), REG(0), REG(1), REG(0)); } break; #endif default: return -1; } return 0; }
int x86_udis86_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) { const char *pc = anal->bits==64? "rip": anal->bits==32? "eip": "ip"; const char *sp = anal->bits==64? "rsp": anal->bits==32? "esp": "sp"; const char *bp = anal->bits==64? "rbp": anal->bits==32? "ebp": "bp"; int oplen, regsz = 4; char str[64], src[32], dst[32]; struct ud u; switch (anal->bits) { case 64: regsz = 8; break; case 16: regsz = 2; break; default: case 32: regsz = 4; break; } UDis86Esil *handler; UDis86OPInfo info = {0, anal->bits, (1LL << anal->bits) - 1, regsz, 0, pc, sp, bp}; memset (op, '\0', sizeof (RAnalOp)); r_strbuf_init (&op->esil); op->addr = addr; op->jump = op->fail = -1; op->ptr = op->val = -1; ud_init (&u); ud_set_pc (&u, addr); ud_set_mode (&u, anal->bits); ud_set_syntax (&u, NULL); ud_set_input_buffer (&u, data, len); ud_disassemble (&u); oplen = op->size = ud_insn_len (&u); if (anal->decode && (handler = udis86_esil_get_handler (u.mnemonic))) { info.oplen = oplen; if (handler->argc > 0) { info.n = getval (u.operand); getarg (dst, &u, info.bitmask, 0); if (handler->argc > 1) { getarg (src, &u, info.bitmask, 1); if (handler->argc > 2) getarg (str, &u, info.bitmask, 2); } } handler->callback (&info, op, dst, src, str); } switch (u.mnemonic) { case UD_Iinvalid: oplen = op->size = -1; return -1; break; case UD_Itest: case UD_Icmp: op->type = R_ANAL_OP_TYPE_CMP; break; case UD_Isalc: // ?? // al = cf break; case UD_Ixor: op->type = R_ANAL_OP_TYPE_XOR; break; case UD_Ior: op->type = R_ANAL_OP_TYPE_OR; break; case UD_Iand: op->type = R_ANAL_OP_TYPE_AND; break; case UD_Isar: op->type = R_ANAL_OP_TYPE_SAR; break; // XXX: sal ?!? case UD_Ishl: op->type = R_ANAL_OP_TYPE_SHL; break; case UD_Ishr: op->type = R_ANAL_OP_TYPE_SHR; break; case UD_Irol: op->type = R_ANAL_OP_TYPE_ROL; break; case UD_Iror: op->type = R_ANAL_OP_TYPE_ROR; break; case UD_Iint3: op->type = R_ANAL_OP_TYPE_TRAP; break; case UD_Iint: op->type = R_ANAL_OP_TYPE_SWI; op->val = u.operand[0].lval.uword; break; case UD_Ilea: case UD_Imov: op->type = R_ANAL_OP_TYPE_MOV; switch (u.operand[1].type) { case UD_OP_MEM: op->type = R_ANAL_OP_TYPE_MOV; if (u.operand[1].base == UD_R_RIP) { int delta = u.operand[1].lval.uword; op->ptr = addr + oplen + delta; } break; default: op->type = R_ANAL_OP_TYPE_MOV; op->ptr = getval (&u.operand[1]); // XX break; } op->stackop = R_ANAL_STACK_INC; op->stackptr = regsz; break; case UD_Ipush: case UD_Ipusha: case UD_Ipushad: case UD_Ipushfq: case UD_Ipushfd: case UD_Ipushfw: switch (u.operand[0].type) { case UD_OP_CONST: case UD_OP_JIMM: case UD_OP_IMM: op->type = R_ANAL_OP_TYPE_PUSH; op->ptr = getval (&u.operand[0]); break; case UD_OP_REG: case UD_OP_PTR: case UD_OP_MEM: default: op->type = R_ANAL_OP_TYPE_UPUSH; op->ptr = 0; break; } op->stackop = R_ANAL_STACK_INC; op->stackptr = regsz; break; case UD_Ipop: case UD_Ipopa: case UD_Ipopad: case UD_Ipopfw: case UD_Ipopfd: case UD_Ipopfq: op->type = R_ANAL_OP_TYPE_POP; op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case UD_Ileave: op->type = R_ANAL_OP_TYPE_MOV; op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case UD_Iadd: case UD_Isub: op->type = (u.mnemonic==UD_Iadd)? R_ANAL_OP_TYPE_ADD: R_ANAL_OP_TYPE_SUB; op->ptr = 0; op->stackptr = 0; if (u.operand[0].type == UD_OP_REG) { if (u.operand[0].base == UD_R_RSP) { int o = (int)getval (&u.operand[1]); op->stackop = R_ANAL_STACK_INC; if (u.mnemonic ==UD_Iadd) { op->stackptr = -o; } else { op->stackptr = o; } } if (u.operand[1].type != UD_OP_REG) op->val = getval (&u.operand[1]); } op->stackptr = 4; break; case UD_Iadc: case UD_Iinc: op->type = R_ANAL_OP_TYPE_ADD; break; case UD_Isbb: case UD_Idec: op->type = R_ANAL_OP_TYPE_SUB; break; case UD_Ijmp: switch (u.operand[0].type) { case UD_OP_MEM: case UD_OP_REG: op->type = R_ANAL_OP_TYPE_UJMP; break; default: op->type = R_ANAL_OP_TYPE_JMP; #if 0 { ut16 a = (op->lval.ptr.seg & 0xFFFF); ut16 b = (op->lval.ptr.off); switch (op->size) { case 32: sprintf (src, "%04x:%04x", a, b & 0xFFFF); break; case 48: sprintf (src, "%04x:%04x", a, b); break; default: eprintf ("F**K YOU\n"); } } #endif if (u.operand[0].type==UD_OP_PTR) { op->jump = getval (&u.operand[0]); } else { if (anal->bits==16) { // honor segment op->jump = (addr&0xf0000) + oplen + \ (((addr&0xffff)+getval (&u.operand[0])&0xffff)); } else { op->jump = addr + oplen + (int)getval (&u.operand[0]); } } } break; case UD_Ije: case UD_Ijne: case UD_Ijb: case UD_Ijbe: case UD_Ija: case UD_Ijae: case UD_Ijs: case UD_Ijns: case UD_Ijo: case UD_Ijno: case UD_Ijp: case UD_Ijnp: case UD_Ijl: case UD_Ijge: case UD_Ijle: case UD_Ijg: case UD_Ijcxz: case UD_Iloop: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = addr + oplen + (int)getval (&u.operand[0]); op->fail = addr+oplen; break; case UD_Icall: op->type = R_ANAL_OP_TYPE_CALL; switch (u.operand[0].type) { case UD_OP_REG: op->jump = 0; // EAX, EBX, ... use anal->reg break; case UD_OP_IMM: case UD_OP_MEM: case UD_OP_PTR: default: op->jump = addr + oplen + (int)getval (&u.operand[0]); } op->fail = addr + oplen; break; case UD_Ihlt: //op->type = R_ANAL_OP_TYPE_HALT; break; case UD_Iret: case UD_Iretf: case UD_Isysret: op->type = R_ANAL_OP_TYPE_RET; op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case UD_Isyscall: op->type = R_ANAL_OP_TYPE_SWI; break; case UD_Inop: op->type = R_ANAL_OP_TYPE_NOP; break; default: break; } return oplen; }
int gdbr_connect(libgdbr_t *g, const char *host, int port) { const char *message = "qSupported:multiprocess+;qRelocInsn+;xmlRegisters=i386"; RStrBuf tmp; r_strbuf_init (&tmp); int ret; if (!g || !host) { return -1; } // Initial max_packet_size for remote target (minimum so far for AVR = 64) g->stub_features.pkt_sz = 64; char *env_pktsz_str; ut32 env_pktsz; if ((env_pktsz_str = getenv ("R2_GDB_PKTSZ"))) { if ((env_pktsz = (ut32) strtoul (env_pktsz_str, NULL, 10))) { g->stub_features.pkt_sz = R_MAX (env_pktsz, 64); } } ret = snprintf (tmp.buf, sizeof (tmp.buf) - 1, "%d", port); if (!ret) { return -1; } if (*host == '/') { ret = r_socket_connect_serial (g->sock, host, port, 1); } else { ret = r_socket_connect_tcp (g->sock, host, tmp.buf, 200); } if (!ret) { return -1; } if (send_ack (g) < 0) { return -1; } read_packet (g); g->connected = 1; // TODO add config possibility here ret = send_msg (g, message); if (ret < 0) { return ret; } read_packet (g); ret = handle_qSupported (g); if (ret < 0) { return ret; } if (env_pktsz > 0) { g->stub_features.pkt_sz = R_MAX (R_MIN (env_pktsz, g->stub_features.pkt_sz), 64); } // If no-ack supported, enable no-ack mode (should speed up things) if (g->stub_features.QStartNoAckMode) { if (send_msg (g, "QStartNoAckMode") < 0) { return -1; } read_packet (g); if (!strncmp (g->data, "OK", 2)) { // Just in case, send ack send_ack (g); g->no_ack = true; } } if (g->remote_type == GDB_REMOTE_TYPE_LLDB) { return gdbr_connect_lldb (g); } // Query the thread / process id g->stub_features.qC = true; g->pid = g->tid = 0; ret = send_msg (g, "qC"); if (ret < 0) { return ret; } read_packet (g); ret = handle_qC (g); if (ret < 0) { g->stub_features.qC = false; } // Check if vCont is supported gdbr_check_vcont (g); // Set pid/thread for operations other than "step" and "continue" if (g->stub_features.multiprocess) { snprintf (tmp.buf, sizeof (tmp.buf) - 1, "Hgp%x.0", (ut32) g->pid); #if 0 if (g->tid < 0) { snprintf (tmp.buf, sizeof (tmp.buf) - 1, "Hgp%x.-1", (ut32) g->pid); } else { snprintf (tmp.buf, sizeof (tmp.buf) - 1, "Hgp%x.%x", (ut32) g->pid, (ut32) g->tid); } #endif } else { snprintf (tmp.buf, sizeof (tmp.buf) - 1, "Hg0"); #if 0 if (g->tid < 0) { snprintf (tmp.buf, sizeof (tmp.buf) - 1, "Hg-1"); } else { snprintf (tmp.buf, sizeof (tmp.buf) - 1, "Hg%x", (ut32) g->tid); } #endif } ret = send_msg (g, tmp.buf); if (ret < 0) { return ret; } read_packet (g); ret = send_ack (g); if (strncmp (g->data, "OK", 2)) { // return -1; } // Set thread for "step" and "continue" operations snprintf (tmp.buf, sizeof (tmp.buf) - 1, "Hc-1"); ret = send_msg (g, tmp.buf); if (ret < 0) { return ret; } read_packet (g); ret = send_ack (g); if (strncmp (g->data, "OK", 2)) { // return -1; } if (g->stub_features.qXfer_features_read) { gdbr_read_target_xml (g); } reg_cache_init (g); return ret; }
static int avr_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { short ofst; int imm = 0, d, r, k; ut8 kbuf[4]; ut16 ins = AVR_SOFTCAST (buf[0], buf[1]); char *arg, str[32]; if (op == NULL) { return 2; } memset (op, '\0', sizeof (RAnalOp)); op->type = R_ANAL_OP_TYPE_UNK; op->ptr = UT64_MAX; op->val = UT64_MAX; op->jump = UT64_MAX; op->fail = UT64_MAX; op->refptr = 0; op->nopcode = 1; // Necessary?? op->size = avrdis (str, addr, buf, len); r_strbuf_init (&op->esil); arg = strchr (str, ' '); if (arg) { arg++; imm = (int)r_num_get (NULL, arg); } op->delay = 0; op->type = R_ANAL_OP_TYPE_UNK; if (!strncmp (str, "st", 2)) { op->type = R_ANAL_OP_TYPE_STORE; } else if (str[0] == 'l') { op->type = R_ANAL_OP_TYPE_LOAD; } else if (str[0] == 's') { op->type = R_ANAL_OP_TYPE_SUB; } else if (!strncmp (str, "inv", 3)) { op->type = R_ANAL_OP_TYPE_ILL; } else if (!strncmp (str, "ser ", 4)) { op->type = R_ANAL_OP_TYPE_MOV; } else if (!strncmp (str, "and", 3)) { op->type = R_ANAL_OP_TYPE_AND; } else if (!strncmp (str, "mul", 3)) { op->type = R_ANAL_OP_TYPE_MUL; } else if (!strncmp (str, "out ", 4)) { op->type = R_ANAL_OP_TYPE_IO; op->type2 = 1; op->val = imm; } else if (!strncmp (str, "in ", 3)) { op->type = R_ANAL_OP_TYPE_IO; op->type2 = 0; op->val = imm; } else if (!strncmp (str, "push ", 5)) { op->type = R_ANAL_OP_TYPE_PUSH; } if (ins == 0) { op->type = R_ANAL_OP_TYPE_NOP; op->cycles = 1; } if (buf[1] == 1) { //MOVW d = (buf[0] & 0xf0) >> 3; r = (buf[0] & 0x0f) << 1; op->type = R_ANAL_OP_TYPE_MOV; op->cycles = 1; r_strbuf_setf (&op->esil, "r%d,r%d,=,r%d,r%d,=", r, d, r+1, d+1); }
static void analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, const char *buf_asm) { r_strbuf_init (&op->esil); r_strbuf_set (&op->esil, ""); switch (buf[0]) { // Irregulars sorted by lower nibble case 0x00: /* nop */ emit(","); break; case 0x10: /* jbc */ k(BIT_R "&,?{,%2$d,1,<<,255,^,%1$d,&=[1],%3$hhd,3,+,pc,+=,}"); break; case 0x20: /* jb */ k(BIT_R "&,?{,%3$hhd,3,+,pc,+=,}"); break; case 0x30: /* jnb */ k(BIT_R "&,!,?{,%3$hhd,3,+,pc,+=,}"); break; case 0x40: /* jc */ emitf("C,!,?{,%hhd,2,+,pc,+=,}", buf[1]); break; case 0x50: /* jnc */ emitf("C,""?{,%hhd,2,+,pc,+=,}", buf[1]); break; case 0x60: /* jz */ emitf("A,!,?{,%hhd,2,+,pc,+=,}", buf[1]); break; case 0x70: /* jnz */ emitf("A,""?{,%hhd,2,+,pc,+=,}", buf[1]); break; case 0x80: /* sjmp */ j(ESX_L1 JMP("2")); break; case 0x90: /* mov */ emitf("%d,dptr,=", (buf[1]<<8) + buf[2]); break; case 0xA0: /* orl */ k(BIT_R "C,|="); break; case 0xB0: /* anl */ k(BIT_R "C,&="); break; case 0xC0: /* push */ h(XR(IB1) PUSH1); break; case 0xD0: /* pop */ h(POP1 XW(IB1)); break; case 0xE0: /* movx */ /* TODO */ break; case 0xF0: /* movx */ /* TODO */ break; case 0x11: case 0x31: case 0x51: case 0x71: case 0x91: case 0xB1: case 0xD1: case 0xF1: emit(CALL("2")); // fall through case 0x01: case 0x21: case 0x41: case 0x61: case 0x81: case 0xA1: case 0xC1: case 0xE1: emitf("0x%x,pc,=", (addr & 0xF800) | ((((unsigned short)buf[0])<<3) & 0x0700) | buf[1]); break; case 0x02: /* ljmp */ emitf( "%d,pc,=", (unsigned int)((buf[1]<<8)+buf[2])); break; case 0x12: /* lcall */ emitf(CALL("3")",%d,pc,=", (unsigned int)((buf[1]<<8)+buf[2])); break; case 0x22: /* ret */ emitf(POP2 "pc,="); break; case 0x32: /* reti */ /* TODO */ break; case 0x72: /* orl */ /* TODO */ break; case 0x82: /* anl */ /* TODO */ break; case 0x92: /* mov */ /* TODO */ break; case 0xA2: /* mov */ /* TODO */ break; case 0xB2: /* cpl */ k("%2$d,1,<<,%1$d,^=[1]"); break; case 0xC2: /* clr */ /* TODO */ break; case 0x03: /* rr */ emit("1,A,0x101,*,>>,A,="); break; case 0x13: /* rrc */ /* TODO */ break; case 0x23: /* rl */ emit("7,A,0x101,*,>>,A,="); break; case 0x33: /* rlc */ /* TODO */ break; case 0x73: /* jmp */ emit("dptr,A,+,pc,="); break; case 0x83: /* movc */ emit("A,dptr,+,[1],A,="); break; case 0x93: /* movc */ emit("A,pc,+,[1],A,="); break; case 0xA3: /* inc */ h(XI(IB1, "++")); break; case 0xB3: /* cpl */ emit("1," XI(C, "^")); break; case 0xC3: /* clr */ emit("0,C,="); break; // Regulars sorted by upper nibble OP_GROUP_UNARY_4(0x00, "++") OP_GROUP_UNARY_4(0x10, "--") OP_GROUP_INPLACE_LHS_4(0x20, A, "+") case 0x34: h (XR(L1) "C,+," XI(A, "+")) break; case 0x35: h (XR(IB1) "C,+," XI(A, "+")) break; case 0x36: case 0x37: j (XR(R0I) "C,+," XI(A, "+")) break; case 0x38: case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3E: case 0x3F: h (XR(R0) "C,+," XI(A, "+")) break; OP_GROUP_INPLACE_LHS_4(0x40, A, "|") OP_GROUP_INPLACE_LHS_4(0x50, A, "&") OP_GROUP_INPLACE_LHS_4(0x60, A, "^") case 0x74: h (XR(L1) XW(A)) break; case 0x75: h (XR(L2) XW(IB1)) break; case 0x76: case 0x77: j (XR(L1) XW(R0I)) break; case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F: h (XR(L1) XW(R0)) break; case 0x84: /* div */ emit("B,!,OV,=,0,A,B,A,/=,A,B,*,-,-,B,=,0,C,="); break; case 0x85: /* mov */ h(IRAM_BASE ",%2$d,+,[1]," IRAM_BASE ",%2$d,+,=[1]"); break; case 0x86: case 0x87: j (XR(R0I) XW(IB1)) break; case 0x88: case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E: case 0x8F: h (XR(R0) XW(IB1)) break; OP_GROUP_INPLACE_LHS_4(0x90, A, ".") case 0xA4: /* mul */ emit("8,A,B,*,DUP,>>,DUP,!,!,OV,=,B,=,A,=,0,C,="); break; case 0xA5: /* ??? */ emit("0,TRAP"); break; case 0xA6: case 0xA7: j (XR(IB1) XW(R0I)) break; case 0xA8: case 0xA9: case 0xAA: case 0xAB: case 0xAC: case 0xAD: case 0xAE: case 0xAF: h (XR(IB1) XW(R0)) break; case 0xB4: h (XR(L1) XR(A) "!=,?{,%3$hhd,2,+pc,+=,}") break; case 0xB5: h (XR(IB1) XR(A) "!=,?{,%3$hhd,2,+pc,+=,}") break; case 0xB6: case 0xB7: j (XR(L1) XR(R0I) "!=,?{,%3$hhd,2,+pc,+=,}") break; case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF: h (XR(L1) XR(R0) "!=,?{,%3$hhd,2,+pc,+=,}") break; case 0xC4: /* swap */ emit("4,A,0x101,*,>>,A,="); break; case 0xC5: /* xch */ /* TODO */ break; case 0xC6: case 0xC7: /* xch */ /* TODO */ break; case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF: /* xch */ h (XR(A) XR(R0) XW(A) "," XW(R0)); break; case 0xD2: /* setb */ /* TODO */ break; case 0xD3: /* setb */ /* TODO */ break; case 0xD4: /* da */ emit("A,--="); break; case 0xD5: /* djnz */ h(XI(R0I, "--") "," XR(R0I) CJMP(L2, "2")); break; case 0xD6: /* xchd */ /* TODO */ break; case 0xD7: /* xchd */ /* TODO */ break; case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE: case 0xDF: /* djnz */ h(XI(R0, "--") "," XR(R0) CJMP(L1, "2")); break; case 0xE2: case 0xE3: /* movx */ j(XRAM_BASE "r%0$d,+,[1]," XW(A)); break; case 0xE4: /* clr */ emit("0,A,="); break; case 0xE5: /* mov */ h (XR(IB1) XW(A)) break; case 0xE6: case 0xE7: /* mov */ j (XR(R0I) XW(A)) break; case 0xE8: case 0xE9: case 0xEA: case 0xEB: case 0xEC: case 0xED: case 0xEE: case 0xEF: /* mov */ h (XR(R0) XW(A)) break; case 0xF2: case 0xF3: /* movx */ j(XR(A) XRAM_BASE "r%0$d,+,=[1]"); case 0xF4: /* cpl */ h ("255" XI(A, "^")) break; case 0xF5: /* mov */ h (XR(A) XW(IB1)) break; case 0xF6: case 0xF7: /* mov */ j (XR(A) XW(R0I)) break; case 0xF8: case 0xF9: case 0xFA: case 0xFB: case 0xFC: case 0xFD: case 0xFE: case 0xFF: /* mov */ h (XR(A) XW(R0)) break; default: break; } }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { static csh handle = 0; static int omode; cs_insn *insn; int mode, n, ret; mode = CS_MODE_BIG_ENDIAN; if (!strcmp (a->cpu, "v9")) mode |= CS_MODE_V9; if (mode != omode) { cs_close (&handle); handle = 0; omode = mode; } if (handle == 0) { ret = cs_open (CS_ARCH_SPARC, mode, &handle); if (ret != CS_ERR_OK) { return -1; } cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); } op->type = R_ANAL_OP_TYPE_NULL; op->size = 0; op->delay = 0; op->jump = UT64_MAX; op->fail = UT64_MAX; op->val = UT64_MAX; op->ptr = UT64_MAX; r_strbuf_init (&op->esil); // capstone-next n = cs_disasm (handle, (const 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 SPARC_INS_MOV: op->type = R_ANAL_OP_TYPE_MOV; break; case SPARC_INS_RETT: op->type = R_ANAL_OP_TYPE_RET; break; case SPARC_INS_UNIMP: op->type = R_ANAL_OP_TYPE_UNK; break; case SPARC_INS_CALL: switch (INSOP(0).type) { case SPARC_OP_MEM: // TODO break; case SPARC_OP_REG: op->type = R_ANAL_OP_TYPE_UCALL; break; default: op->type = R_ANAL_OP_TYPE_CALL; op->jump = INSOP(0).imm; break; } break; case SPARC_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; break; case SPARC_INS_CMP: op->type = R_ANAL_OP_TYPE_CMP; break; case SPARC_INS_JMP: case SPARC_INS_JMPL: op->type = R_ANAL_OP_TYPE_JMP; op->jump = INSOP(0).imm; break; case SPARC_INS_LDD: case SPARC_INS_LD: case SPARC_INS_LDQ: case SPARC_INS_LDSB: case SPARC_INS_LDSH: case SPARC_INS_LDSW: case SPARC_INS_LDUB: case SPARC_INS_LDUH: case SPARC_INS_LDX: op->type = R_ANAL_OP_TYPE_LOAD; break; case SPARC_INS_STBAR: case SPARC_INS_STB: case SPARC_INS_STD: case SPARC_INS_ST: case SPARC_INS_STH: case SPARC_INS_STQ: case SPARC_INS_STX: op->type = R_ANAL_OP_TYPE_STORE; break; case SPARC_INS_ORCC: case SPARC_INS_ORNCC: case SPARC_INS_ORN: case SPARC_INS_OR: op->type = R_ANAL_OP_TYPE_OR; break; case SPARC_INS_B: case SPARC_INS_BMASK: case SPARC_INS_BRGEZ: case SPARC_INS_BRGZ: case SPARC_INS_BRLEZ: case SPARC_INS_BRLZ: case SPARC_INS_BRNZ: case SPARC_INS_BRZ: case SPARC_INS_FB: switch (INSOP(0).type) { case SPARC_OP_REG: op->type = R_ANAL_OP_TYPE_CJMP; if (INSCC != SPARC_CC_ICC_N) // never op->jump = INSOP(1).imm; if (INSCC != SPARC_CC_ICC_A) // always op->fail = addr+4; break; case SPARC_OP_IMM: op->type = R_ANAL_OP_TYPE_CJMP; if (INSCC != SPARC_CC_ICC_N) // never op->jump = INSOP(0).imm; if (INSCC != SPARC_CC_ICC_A) // always op->fail = addr+4; break; default: // MEM? break; } break; case SPARC_INS_FHSUBD: case SPARC_INS_FHSUBS: case SPARC_INS_FPSUB16: case SPARC_INS_FPSUB16S: case SPARC_INS_FPSUB32: case SPARC_INS_FPSUB32S: case SPARC_INS_FSUBD: case SPARC_INS_FSUBQ: case SPARC_INS_FSUBS: case SPARC_INS_SUBCC: case SPARC_INS_SUBX: case SPARC_INS_SUBXCC: case SPARC_INS_SUB: case SPARC_INS_TSUBCCTV: case SPARC_INS_TSUBCC: op->type = R_ANAL_OP_TYPE_SUB; break; case SPARC_INS_ADDCC: case SPARC_INS_ADDX: case SPARC_INS_ADDXCC: case SPARC_INS_ADDXC: case SPARC_INS_ADDXCCC: case SPARC_INS_ADD: case SPARC_INS_FADDD: case SPARC_INS_FADDQ: case SPARC_INS_FADDS: case SPARC_INS_FHADDD: case SPARC_INS_FHADDS: case SPARC_INS_FNADDD: case SPARC_INS_FNADDS: case SPARC_INS_FNHADDD: case SPARC_INS_FNHADDS: case SPARC_INS_FPADD16: case SPARC_INS_FPADD16S: case SPARC_INS_FPADD32: case SPARC_INS_FPADD32S: case SPARC_INS_FPADD64: case SPARC_INS_TADDCCTV: case SPARC_INS_TADDCC: op->type = R_ANAL_OP_TYPE_ADD; break; case SPARC_INS_FDMULQ: case SPARC_INS_FMUL8SUX16: case SPARC_INS_FMUL8ULX16: case SPARC_INS_FMUL8X16: case SPARC_INS_FMUL8X16AL: case SPARC_INS_FMUL8X16AU: case SPARC_INS_FMULD: case SPARC_INS_FMULD8SUX16: case SPARC_INS_FMULD8ULX16: case SPARC_INS_FMULQ: case SPARC_INS_FMULS: case SPARC_INS_FSMULD: case SPARC_INS_MULX: case SPARC_INS_SMULCC: case SPARC_INS_SMUL: case SPARC_INS_UMULCC: case SPARC_INS_UMULXHI: case SPARC_INS_UMUL: case SPARC_INS_XMULX: case SPARC_INS_XMULXHI: op->type = R_ANAL_OP_TYPE_MUL; break; case SPARC_INS_FDIVD: case SPARC_INS_FDIVQ: case SPARC_INS_FDIVS: case SPARC_INS_SDIVCC: case SPARC_INS_SDIVX: case SPARC_INS_SDIV: case SPARC_INS_UDIVCC: case SPARC_INS_UDIVX: case SPARC_INS_UDIV: op->type = R_ANAL_OP_TYPE_DIV; break; } cs_free (insn, n); } return op->size; }
static int tms320c64x_analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { static csh handle = 0; static int omode; cs_insn *insn; int mode = 0, n, ret; if (mode != omode) { cs_close (&handle); handle = 0; omode = mode; } if (handle == 0) { ret = cs_open (CS_ARCH_TMS320C64X, mode, &handle); if (ret != CS_ERR_OK) { return -1; } cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); } op->type = R_ANAL_OP_TYPE_NULL; op->size = 0; op->delay = 0; op->jump = UT64_MAX; op->fail = UT64_MAX; op->val = UT64_MAX; op->ptr = UT64_MAX; r_strbuf_init (&op->esil); // capstone-next n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); if (n < 1) { op->type = R_ANAL_OP_TYPE_ILL; } else { opex (&op->opex, handle, insn); op->size = insn->size; op->id = insn->id; switch (insn->id) { case TMS320C64X_INS_INVALID: op->type = R_ANAL_OP_TYPE_ILL; break; case TMS320C64X_INS_AND: case TMS320C64X_INS_ANDN: op->type = R_ANAL_OP_TYPE_AND; break; case TMS320C64X_INS_NOT: op->type = R_ANAL_OP_TYPE_NOT; break; case TMS320C64X_INS_NEG: op->type = R_ANAL_OP_TYPE_NOT; break; case TMS320C64X_INS_SWAP2: case TMS320C64X_INS_SWAP4: op->type = R_ANAL_OP_TYPE_MOV; op->type = R_ANAL_OP_TYPE_MOV; break; case TMS320C64X_INS_BNOP: case TMS320C64X_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; break; case TMS320C64X_INS_CMPEQ: case TMS320C64X_INS_CMPEQ2: case TMS320C64X_INS_CMPEQ4: case TMS320C64X_INS_CMPGT: case TMS320C64X_INS_CMPGT2: case TMS320C64X_INS_CMPGTU4: case TMS320C64X_INS_CMPLT: case TMS320C64X_INS_CMPLTU: op->type = R_ANAL_OP_TYPE_CMP; break; case TMS320C64X_INS_B: op->type = R_ANAL_OP_TYPE_JMP; // higher 32bits of the 64bit address is lost, lets clone op->jump = INSOP(0).imm + (addr & 0xFFFFFFFF00000000); break; case TMS320C64X_INS_LDB: case TMS320C64X_INS_LDBU: case TMS320C64X_INS_LDDW: case TMS320C64X_INS_LDH: case TMS320C64X_INS_LDHU: case TMS320C64X_INS_LDNDW: case TMS320C64X_INS_LDNW: case TMS320C64X_INS_LDW: case TMS320C64X_INS_LMBD: op->type = R_ANAL_OP_TYPE_LOAD; break; case TMS320C64X_INS_STB: case TMS320C64X_INS_STDW: case TMS320C64X_INS_STH: case TMS320C64X_INS_STNDW: case TMS320C64X_INS_STNW: case TMS320C64X_INS_STW: op->type = R_ANAL_OP_TYPE_STORE; break; case TMS320C64X_INS_OR: op->type = R_ANAL_OP_TYPE_OR; break; case TMS320C64X_INS_SSUB: case TMS320C64X_INS_SUB: case TMS320C64X_INS_SUB2: case TMS320C64X_INS_SUB4: case TMS320C64X_INS_SUBAB: case TMS320C64X_INS_SUBABS4: case TMS320C64X_INS_SUBAH: case TMS320C64X_INS_SUBAW: case TMS320C64X_INS_SUBC: case TMS320C64X_INS_SUBU: op->type = R_ANAL_OP_TYPE_SUB; break; case TMS320C64X_INS_ADD: case TMS320C64X_INS_ADD2: case TMS320C64X_INS_ADD4: case TMS320C64X_INS_ADDAB: case TMS320C64X_INS_ADDAD: case TMS320C64X_INS_ADDAH: case TMS320C64X_INS_ADDAW: case TMS320C64X_INS_ADDK: case TMS320C64X_INS_ADDKPC: case TMS320C64X_INS_ADDU: case TMS320C64X_INS_SADD: case TMS320C64X_INS_SADD2: case TMS320C64X_INS_SADDU4: case TMS320C64X_INS_SADDUS2: op->type = R_ANAL_OP_TYPE_ADD; break; } cs_free (insn, n); } return op->size; }
static int baleful_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { const ut8 *r = 0; const ut8 *r0 = 0; const ut8 *r1 = 0; const ut8 *p = 0; const ut32 *imm = 0; const ut32 *imm1 = 0; const ut8 p0[16]; const ut8 p1[16]; const ut8 p2[16]; const ut8 p3[16]; if (op == NULL) return 1; memset (op, 0, sizeof (RAnalOp)); op->type = R_ANAL_OP_TYPE_NULL; op->delay = 0; op->jump = op->fail = -1; op->ptr = op->val = -1; op->refptr = 0; r_strbuf_init (&op->esil); switch (buf[0]) { case 2: // 8 8 11 5 ADD + op->type = R_ANAL_OP_TYPE_ADD; op->size = getp(buf,p0,p1,p2,p3,0); r_strbuf_setf (&op->esil, "%s,%s,+,%s,=",p2,p1,p0); break; case 3: // 8 8 11 5 SUB - op->type = R_ANAL_OP_TYPE_SUB; op->size = getp(buf,p0,p1,p2,p3,0); r_strbuf_setf (&op->esil, "%s,%s,-,%s,=",p2,p1,p0); break; case 4: // 8 8 11 5 MUL * op->type = R_ANAL_OP_TYPE_MUL; op->size = getp(buf,p0,p1,p2,p3,0); r_strbuf_setf (&op->esil, "%s,%s,*,%s,=",p2,p1,p0); break; case 6: // 8 8 11 5 XOR ^ op->type = R_ANAL_OP_TYPE_XOR; op->size = getp(buf,p0,p1,p2,p3,0); r_strbuf_setf (&op->esil, "%s,%s,^,%s,=",p2,p1,p0); break; case 9: // 8 8 11 5 AND & op->type = R_ANAL_OP_TYPE_AND; op->size = getp(buf,p0,p1,p2,p3,0); r_strbuf_setf (&op->esil, "%s,%s,&,%s,=",p2,p1,p0); break; case 10: // 8 8 11 5 OR | op->type = R_ANAL_OP_TYPE_OR; op->size = getp(buf,p0,p1,p2,p3,0); r_strbuf_setf (&op->esil, "%s,%s,|,%s,=",p2,p1,p0); break; case 12: // 8 8 11 5 ROL <<<< op->type = R_ANAL_OP_TYPE_ROL; op->size = getp(buf,p0,p1,p2,p3,0); r_strbuf_setf (&op->esil, "%s,%s,<<<<,%s,=",p2,p1,p0); break; case 13: // 8 8 11 5 ROR >>>> op->type = R_ANAL_OP_TYPE_ROR; op->size = getp(buf,p0,p1,p2,p3,0); r_strbuf_setf (&op->esil, "%s,%s,>>>>,%s,=",p2,p1,p0); break; case 25: // ++ op->type = R_ANAL_OP_TYPE_ADD; op->size = getp(buf,p0,p1,p2,p3,6); r_strbuf_setf (&op->esil, "%s,++,=",p1); break; case 26: // -- op->type = R_ANAL_OP_TYPE_SUB; op->size = getp(buf,p0,p1,p2,p3,6); r_strbuf_setf (&op->esil, "%s,--,=",p1); break; ////////////////////////////////////////// SPECIAL DIV/MOD //////////////////////////////// case 5: // 9 9 12 6 DIV op->type = R_ANAL_OP_TYPE_DIV; op->size = getp(buf,p0,p1,p2,p3,1); r_strbuf_setf (&op->esil, "%s,%s,/,%s,=,%s,%s,%%,%s,=",p2,p1,p0,p2,p1,p3); break; ////////////////////////////////// MOVS /////////////////////////////////////////////////// case 24: //7 4 MOV op->type = R_ANAL_OP_TYPE_MOV; op->size = getp(buf,p0,p1,p2,p3,3); r_strbuf_setf (&op->esil, "%s,%s,=",p2,p1); break; case 27: // MOV r,[r] r = buf + 1; r1 = buf + 2; op->type = R_ANAL_OP_TYPE_MOV; op->size = 3; r_strbuf_setf (&op->esil, "r_%02x,[4],r_%02x,=",*r1,*r); break; case 28:// MOV [r],r1 r = buf + 1; r1 = buf + 2; op->type = R_ANAL_OP_TYPE_MOV; op->size = 3; r_strbuf_setf (&op->esil, "r_%02x,r_%02x,=[4]",*r1,*r); break; ///////////////////////////////// JUMPS ///////////////////////////////////////////////// case 14: //5 JMP imm = (ut32 *)(buf + 1); op->type = R_ANAL_OP_TYPE_JMP; op->size = getp(buf,p0,p1,p2,p3,5); r_strbuf_setf(&op->esil,"%s,pc,=",p1); break; case 16: //5 JZ op->type = R_ANAL_OP_TYPE_CJMP; op->size = getp(buf,p0,p1,p2,p3,5); r_strbuf_setf(&op->esil, "zf,?{,%s,pc,=,}",p1); break; case 21: //5 JNZ op->type = R_ANAL_OP_TYPE_CJMP; op->size = getp(buf,p0,p1,p2,p3,5); r_strbuf_setf(&op->esil, "zf,!,?{,%s,pc,=,}",p1); break; case 17: //5 JS op->type = R_ANAL_OP_TYPE_CJMP; op->size = getp(buf,p0,p1,p2,p3,5); r_strbuf_setf(&op->esil, "sf,?{,%s,pc,=,}",p1); break; case 20: //5 JNS op->type = R_ANAL_OP_TYPE_CJMP; op->size = getp(buf,p0,p1,p2,p3,5); r_strbuf_setf(&op->esil, "sf,!,?{,%s,pc,=,}",p1); break; case 19: //5 JG op->type = R_ANAL_OP_TYPE_CJMP; op->size = getp(buf,p0,p1,p2,p3,5); r_strbuf_setf(&op->esil, "gf,?{,%s,pc,=,}",p1); break; case 18: //5 JBE op->type = R_ANAL_OP_TYPE_CJMP; op->size = getp(buf,p0,p1,p2,p3,5); r_strbuf_setf(&op->esil, "gf,!,?{,%s,pc,=,}",p1); break; //////////////////////////////// EFLAGS WRITER /////////////////////////////////////////////////////////// // http://www.read.seas.harvard.edu/~kohler/class/aosref/i386/appc.htm //http://sourceforge.net/p/fake86/code/ci/master/tree/src/fake86/cpu.c case 22: // 7 7 10 4 AND op->type = R_ANAL_OP_TYPE_AND; op->size = getp(buf,p0,p1,p2,p3,2); break; case 23: // 7 7 10 4 CMP op->type = R_ANAL_OP_TYPE_SUB; op->size = getp(buf,p0,p1,p2,p3,2); r_strbuf_setf(&op->esil,"0,sf,=,%s,%s,<,sf,=,0,zf,=,%s,%s,==,%%z,zf,=,0,gf,=,%s,%s,>,gf,=",p1,p2,p1,p2,p1,p2); //"0,sf,=,%s,%s,<,sf,=" //SF //"0,zf,=,%s,%s,==,%%z,zf,=" //ZF //"0,gf,=,%s,%s,>,gf,=" //GF break; /////////////////////////////////////// STACK //////////////////////////////////////////////////////////// case 30: //6 3 PUSH p = buf + 1; op->type = R_ANAL_OP_TYPE_PUSH; op->size = getp(buf,p0,p1,p2,p3,4); r_strbuf_setf(&op->esil,"%s,stk,=[4],4,stk,+=",p1); break; case 31: // POP op->type = R_ANAL_OP_TYPE_POP; op->size = getp(buf,p0,p1,p2,p3,6); r_strbuf_setf(&op->esil,"4,stk,-=,stk,[4],%s,=",p1); break; case 15: //5 CALL imm = (ut32 *)(buf + 1); op->type = R_ANAL_OP_TYPE_CALL; op->size = getp(buf,p0,p1,p2,p3,5); r_strbuf_setf(&op->esil,"%04x,pc,+,stk,=[4],4,stk,+=,%s,pc,=",op->size,p1); break; case 1: // RET op->type = R_ANAL_OP_TYPE_RET; op->size = 1; r_strbuf_setf(&op->esil,"4,stk,-=,stk,[4],pc,="); break; /////////////////////////////////////////////////////////////////////////////////////////////////////////// case 11: r_strbuf_setf (&op->esil, "regX = regY==0"); op->size = 3; break; case 7: r_strbuf_setf (&op->esil, "regX = NEG regY"); op->size = 3; break; case 8: r_strbuf_setf (&op->esil, "regX = NOT regY"); op->size = 3; break; /////////////////////////////////////////////////////////////////////////////////////////////////////////// case 32: // SYSCALL p = buf + 1; op->type = R_ANAL_OP_TYPE_CALL; op->size = 2; r_strbuf_setf (&op->esil, "%x,$",*p); /*if (*p==0) r_strbuf_setf (&op->esil, "apicall: putchar()"); else r_strbuf_setf (&op->esil, "apicall: %02x",*p);*/ break; case 29:// VMEND op->type = R_ANAL_OP_TYPE_NOP; op->size = 1; r_strbuf_setf (&op->esil, "end virtual"); break; case 0:// NOP default: op->type = R_ANAL_OP_TYPE_NOP; op->size = 1; r_strbuf_setf (&op->esil, "nop"); break; } return op->size; }