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