1 /* radare2 - LGPL - Copyright 2014-2019 - pancake */
2
3 #include <r_anal.h>
4 #include <r_lib.h>
5 #include <capstone.h>
6 #include <systemz.h>
7 // instruction set: http://www.tachyonsoft.com/inst390m.htm
8
9 #if CS_API_MAJOR < 2
10 #error Old Capstone not supported
11 #endif
12
13 #define esilprintf(op, fmt, ...) r_strbuf_setf (&op->esil, fmt, ##__VA_ARGS__)
14 #define INSOP(n) insn->detail->sysz.operands[n]
15
opex(RStrBuf * buf,csh handle,cs_insn * insn)16 static void opex(RStrBuf *buf, csh handle, cs_insn *insn) {
17 int i;
18 PJ *pj = pj_new ();
19 if (!pj) {
20 return;
21 }
22 pj_o (pj);
23 pj_ka (pj, "operands");
24 cs_sysz *x = &insn->detail->sysz;
25 for (i = 0; i < x->op_count; i++) {
26 cs_sysz_op *op = x->operands + i;
27 pj_o (pj);
28 switch (op->type) {
29 case SYSZ_OP_REG:
30 pj_ks (pj, "type", "reg");
31 pj_ks (pj, "value", cs_reg_name (handle, op->reg));
32 break;
33 case SYSZ_OP_IMM:
34 pj_ks (pj, "type", "imm");
35 pj_kN (pj, "value", op->imm);
36 break;
37 case SYSZ_OP_MEM:
38 pj_ks (pj, "type", "mem");
39 if (op->mem.base != SYSZ_REG_INVALID) {
40 pj_ks (pj, "base", cs_reg_name (handle, op->mem.base));
41 }
42 pj_kN (pj, "disp", op->mem.disp);
43 break;
44 default:
45 pj_ks (pj, "type", "invalid");
46 break;
47 }
48 pj_end (pj); /* o operand */
49 }
50 pj_end (pj); /* a operands */
51 pj_end (pj);
52
53 r_strbuf_init (buf);
54 r_strbuf_append (buf, pj_string (pj));
55 pj_free (pj);
56 }
57
analop(RAnal * a,RAnalOp * op,ut64 addr,const ut8 * buf,int len,RAnalOpMask mask)58 static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
59 csh handle;
60 cs_insn *insn;
61 int mode = CS_MODE_BIG_ENDIAN;
62 int ret = cs_open (CS_ARCH_SYSZ, mode, &handle);
63 if (ret == CS_ERR_OK) {
64 cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON);
65 // capstone-next
66 int n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn);
67 if (n < 1) {
68 op->type = R_ANAL_OP_TYPE_ILL;
69 } else {
70 if (mask & R_ANAL_OP_MASK_OPEX) {
71 opex (&op->opex, handle, insn);
72 }
73 op->size = insn->size;
74 switch (insn->id) {
75 case SYSZ_INS_BRCL:
76 case SYSZ_INS_BRASL:
77 op->type = R_ANAL_OP_TYPE_CALL;
78 break;
79 case SYSZ_INS_BR:
80 op->type = R_ANAL_OP_TYPE_JMP;
81 break;
82 case SYSZ_INS_BRC:
83 case SYSZ_INS_BER:
84 case SYSZ_INS_BHR:
85 case SYSZ_INS_BHER:
86 case SYSZ_INS_BLR:
87 case SYSZ_INS_BLER:
88 case SYSZ_INS_BLHR:
89 case SYSZ_INS_BNER:
90 case SYSZ_INS_BNHR:
91 case SYSZ_INS_BNHER:
92 case SYSZ_INS_BNLR:
93 case SYSZ_INS_BNLER:
94 case SYSZ_INS_BNLHR:
95 case SYSZ_INS_BNOR:
96 case SYSZ_INS_BOR:
97 case SYSZ_INS_BASR:
98 case SYSZ_INS_BRAS:
99 case SYSZ_INS_BRCT:
100 case SYSZ_INS_BRCTG:
101 op->type = R_ANAL_OP_TYPE_CJMP;
102 break;
103 case SYSZ_INS_JE:
104 case SYSZ_INS_JGE:
105 case SYSZ_INS_JHE:
106 case SYSZ_INS_JGHE:
107 case SYSZ_INS_JH:
108 case SYSZ_INS_JGH:
109 case SYSZ_INS_JLE:
110 case SYSZ_INS_JGLE:
111 case SYSZ_INS_JLH:
112 case SYSZ_INS_JGLH:
113 case SYSZ_INS_JL:
114 case SYSZ_INS_JGL:
115 case SYSZ_INS_JNE:
116 case SYSZ_INS_JGNE:
117 case SYSZ_INS_JNHE:
118 case SYSZ_INS_JGNHE:
119 case SYSZ_INS_JNH:
120 case SYSZ_INS_JGNH:
121 case SYSZ_INS_JNLE:
122 case SYSZ_INS_JGNLE:
123 case SYSZ_INS_JNLH:
124 case SYSZ_INS_JGNLH:
125 case SYSZ_INS_JNL:
126 case SYSZ_INS_JGNL:
127 case SYSZ_INS_JNO:
128 case SYSZ_INS_JGNO:
129 case SYSZ_INS_JO:
130 case SYSZ_INS_JGO:
131 case SYSZ_INS_JG:
132 op->type = R_ANAL_OP_TYPE_CJMP;
133 op->jump = INSOP(0).imm;
134 op->fail = addr+op->size;
135 break;
136 case SYSZ_INS_J:
137 op->type = R_ANAL_OP_TYPE_JMP;
138 op->jump = INSOP(0).imm;
139 op->fail = UT64_MAX;
140 break;
141 }
142 }
143 cs_free (insn, n);
144 cs_close (&handle);
145 }
146 return op->size;
147 }
148
set_reg_profile(RAnal * anal)149 static bool set_reg_profile(RAnal *anal) {
150 const char *p =
151 "=PC r15\n"
152 "=LR r14\n"
153 "=SP r13\n"
154 "=BP r12\n"
155 "=A0 r0\n"
156 "=A1 r1\n"
157 "=A2 r2\n"
158 "=A3 r3\n"
159 "=SN r0\n"
160 "gpr sb .32 36 0\n" // r9
161 "gpr sl .32 40 0\n" // rl0
162 "gpr fp .32 44 0\n" // r11
163 "gpr ip .32 48 0\n" // r12
164 "gpr sp .32 52 0\n" // r13
165 "gpr lr .32 56 0\n" // r14
166 "gpr pc .32 60 0\n" // r15
167
168 "gpr r0 .32 0 0\n"
169 "gpr r1 .32 4 0\n"
170 "gpr r2 .32 8 0\n"
171 "gpr r3 .32 12 0\n"
172 "gpr r4 .32 16 0\n"
173 "gpr r5 .32 20 0\n"
174 "gpr r6 .32 24 0\n"
175 "gpr r7 .32 28 0\n"
176 "gpr r8 .32 32 0\n"
177 "gpr r9 .32 36 0\n"
178 "gpr r10 .32 40 0\n"
179 "gpr r11 .32 44 0\n"
180 "gpr r12 .32 48 0\n"
181 "gpr r13 .32 52 0\n"
182 "gpr r14 .32 56 0\n"
183 "gpr r15 .32 60 0\n"
184 ;
185 return r_reg_set_profile_string (anal->reg, p);
186 }
187
archinfo(RAnal * anal,int q)188 static int archinfo(RAnal *anal, int q) {
189 switch (q) {
190 case R_ANAL_ARCHINFO_ALIGN:
191 return 2;
192 case R_ANAL_ARCHINFO_MAX_OP_SIZE:
193 return 4;
194 case R_ANAL_ARCHINFO_MIN_OP_SIZE:
195 return 2;
196 }
197 return 2;
198 }
199
200 RAnalPlugin r_anal_plugin_sysz = {
201 .name = "sysz",
202 .desc = "Capstone SystemZ microanalysis",
203 .esil = false,
204 .license = "BSD",
205 .arch = "sysz",
206 .bits = 32|64,
207 .op = &analop,
208 .archinfo = archinfo,
209 .set_reg_profile = &set_reg_profile,
210 };
211
212 #ifndef R2_PLUGIN_INCORE
213 R_API RLibStruct radare_plugin = {
214 .type = R_LIB_TYPE_ANAL,
215 .data = &r_anal_plugin_sysz,
216 .version = R2_VERSION
217 };
218 #endif
219