1 /* radare2 - LGPL - Copyright 2014-2017 - pancake */
2
3 #include <r_anal.h>
4 #include <r_lib.h>
5 #include <capstone.h>
6 #include <xcore.h>
7
8 #if CS_API_MAJOR < 2
9 #error Old Capstone not supported
10 #endif
11
12 #define esilprintf(op, fmt, ...) r_strbuf_setf (&op->esil, fmt, ##__VA_ARGS__)
13 #define INSOP(n) insn->detail->xcore.operands[n]
14
opex(RStrBuf * buf,csh handle,cs_insn * insn)15 static void opex(RStrBuf *buf, csh handle, cs_insn *insn) {
16 int i;
17 PJ *pj = pj_new ();
18 if (!pj) {
19 return;
20 }
21 pj_o (pj);
22 pj_ka (pj, "operands");
23 cs_xcore *x = &insn->detail->xcore;
24 for (i = 0; i < x->op_count; i++) {
25 cs_xcore_op *op = x->operands + i;
26 pj_o (pj);
27 switch (op->type) {
28 case XCORE_OP_REG:
29 pj_ks (pj, "type", "reg");
30 pj_ks (pj, "value", cs_reg_name (handle, op->reg));
31 break;
32 case XCORE_OP_IMM:
33 pj_ks (pj, "type", "imm");
34 pj_ki (pj, "value", op->imm);
35 break;
36 case XCORE_OP_MEM:
37 pj_ks (pj, "type", "mem");
38 if (op->mem.base != XCORE_REG_INVALID) {
39 pj_ks (pj, "base", cs_reg_name (handle, op->mem.base));
40 }
41 pj_ki (pj, "disp", op->mem.disp);
42 break;
43 default:
44 pj_ks (pj, "type", "invalid");
45 break;
46 }
47 pj_end (pj); /* o operand */
48 }
49 pj_end (pj); /* a operands */
50 pj_end (pj);
51
52 r_strbuf_init (buf);
53 r_strbuf_append (buf, pj_string (pj));
54 pj_free (pj);
55 }
56
analop(RAnal * a,RAnalOp * op,ut64 addr,const ut8 * buf,int len,RAnalOpMask mask)57 static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
58 static csh handle = 0;
59 static int omode = 0;
60 cs_insn *insn;
61 int mode, n, ret;
62 mode = CS_MODE_BIG_ENDIAN;
63 if (!strcmp (a->cpu, "v9")) {
64 mode |= CS_MODE_V9;
65 }
66 if (mode != omode) {
67 if (handle) {
68 cs_close (&handle);
69 handle = 0;
70 }
71 omode = mode;
72 }
73 if (handle == 0) {
74 ret = cs_open (CS_ARCH_XCORE, mode, &handle);
75 if (ret != CS_ERR_OK) {
76 return -1;
77 }
78 cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON);
79 }
80 // capstone-next
81 n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn);
82 if (n < 1) {
83 op->type = R_ANAL_OP_TYPE_ILL;
84 } else {
85 if (mask & R_ANAL_OP_MASK_OPEX) {
86 opex (&op->opex, handle, insn);
87 }
88 op->size = insn->size;
89 op->id = insn->id;
90 switch (insn->id) {
91 case XCORE_INS_DRET:
92 case XCORE_INS_KRET:
93 case XCORE_INS_RETSP:
94 op->type = R_ANAL_OP_TYPE_RET;
95 break;
96 case XCORE_INS_DCALL:
97 case XCORE_INS_KCALL:
98 case XCORE_INS_ECALLF:
99 case XCORE_INS_ECALLT:
100 op->type = R_ANAL_OP_TYPE_CALL;
101 op->jump = INSOP(0).imm;
102 break;
103 /* ??? */
104 case XCORE_INS_BL:
105 case XCORE_INS_BLA:
106 case XCORE_INS_BLAT:
107 case XCORE_INS_BT:
108 case XCORE_INS_BF:
109 case XCORE_INS_BU:
110 case XCORE_INS_BRU:
111 op->type = R_ANAL_OP_TYPE_CALL;
112 op->jump = INSOP(0).imm;
113 break;
114 case XCORE_INS_SUB:
115 case XCORE_INS_LSUB:
116 op->type = R_ANAL_OP_TYPE_SUB;
117 break;
118 case XCORE_INS_ADD:
119 case XCORE_INS_LADD:
120 op->type = R_ANAL_OP_TYPE_ADD;
121 break;
122 }
123 cs_free (insn, n);
124 }
125 // cs_close (&handle);
126 return op->size;
127 }
128
129 RAnalPlugin r_anal_plugin_xcore_cs = {
130 .name = "xcore",
131 .desc = "Capstone XCORE analysis",
132 .license = "BSD",
133 .esil = false,
134 .arch = "xcore",
135 .bits = 32,
136 .op = &analop,
137 //.set_reg_profile = &set_reg_profile,
138 };
139
140 #ifndef R2_PLUGIN_INCORE
141 R_API RLibStruct radare_plugin = {
142 .type = R_LIB_TYPE_ANAL,
143 .data = &r_anal_plugin_xcore_cs,
144 .version = R2_VERSION
145 };
146 #endif
147