1 /* radare - LGPL - Copyright 2010-2020 - pancake, nibble */
2
3 #include <r_anal.h>
4 #include <r_util.h>
5 #include <r_list.h>
6
r_anal_op_new(void)7 R_API RAnalOp *r_anal_op_new(void) {
8 RAnalOp *op = R_NEW (RAnalOp);
9 r_anal_op_init (op);
10 return op;
11 }
12
r_anal_op_list_new(void)13 R_API RList *r_anal_op_list_new(void) {
14 RList *list = r_list_new ();
15 if (list) {
16 list->free = &r_anal_op_free;
17 }
18 return list;
19 }
20
r_anal_op_init(RAnalOp * op)21 R_API void r_anal_op_init(RAnalOp *op) {
22 if (op) {
23 memset (op, 0, sizeof (*op));
24 op->addr = UT64_MAX;
25 op->jump = UT64_MAX;
26 op->fail = UT64_MAX;
27 op->ptr = UT64_MAX;
28 op->refptr = 0;
29 op->val = UT64_MAX;
30 op->disp = UT64_MAX;
31 }
32 }
33
r_anal_op_fini(RAnalOp * op)34 R_API bool r_anal_op_fini(RAnalOp *op) {
35 if (!op) {
36 return false;
37 }
38 r_anal_value_free (op->src[0]);
39 r_anal_value_free (op->src[1]);
40 r_anal_value_free (op->src[2]);
41 op->src[0] = NULL;
42 op->src[1] = NULL;
43 op->src[2] = NULL;
44 r_anal_value_free (op->dst);
45 op->dst = NULL;
46 r_list_free (op->access);
47 op->access = NULL;
48 r_strbuf_fini (&op->opex);
49 r_strbuf_fini (&op->esil);
50 r_anal_switch_op_free (op->switch_op);
51 op->switch_op = NULL;
52 R_FREE (op->mnemonic);
53 return true;
54 }
55
r_anal_op_free(void * _op)56 R_API void r_anal_op_free(void *_op) {
57 if (!_op) {
58 return;
59 }
60 r_anal_op_fini (_op);
61 memset (_op, 0, sizeof (RAnalOp));
62 free (_op);
63 }
64
defaultCycles(RAnalOp * op)65 static int defaultCycles(RAnalOp *op) {
66 switch (op->type) {
67 case R_ANAL_OP_TYPE_PUSH:
68 case R_ANAL_OP_TYPE_POP:
69 case R_ANAL_OP_TYPE_STORE:
70 case R_ANAL_OP_TYPE_LOAD:
71 return 2;
72 case R_ANAL_OP_TYPE_LEA:
73 case R_ANAL_OP_TYPE_MOV:
74 case R_ANAL_OP_TYPE_NOP:
75 return 1;
76 case R_ANAL_OP_TYPE_TRAP:
77 case R_ANAL_OP_TYPE_SWI:
78 return 4;
79 case R_ANAL_OP_TYPE_SYNC:
80 return 4;
81 case R_ANAL_OP_TYPE_RET:
82 case R_ANAL_OP_TYPE_JMP:
83 case R_ANAL_OP_TYPE_RJMP:
84 case R_ANAL_OP_TYPE_CALL:
85 return 4;
86 default:
87 return 1;
88 }
89 }
90
r_anal_op(RAnal * anal,RAnalOp * op,ut64 addr,const ut8 * data,int len,RAnalOpMask mask)91 R_API int r_anal_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask) {
92 r_anal_op_init (op);
93 r_return_val_if_fail (anal && op && len > 0, -1);
94
95 int ret = R_MIN (2, len);
96 if (len > 0 && anal->cur && anal->cur->op) {
97 //use core binding to set asm.bits correctly based on the addr
98 //this is because of the hassle of arm/thumb
99 if (anal && anal->coreb.archbits) {
100 anal->coreb.archbits (anal->coreb.core, addr);
101 }
102 if (anal->pcalign && addr % anal->pcalign) {
103 op->type = R_ANAL_OP_TYPE_ILL;
104 op->addr = addr;
105 // eprintf ("Unaligned instruction for %d bits at 0x%"PFMT64x"\n", anal->bits, addr);
106 op->size = 1;
107 return -1;
108 }
109 ret = anal->cur->op (anal, op, addr, data, len, mask);
110 if (ret < 1) {
111 op->type = R_ANAL_OP_TYPE_ILL;
112 }
113 op->addr = addr;
114 /* consider at least 1 byte to be part of the opcode */
115 if (op->nopcode < 1) {
116 op->nopcode = 1;
117 }
118 } else if (!memcmp (data, "\xff\xff\xff\xff", R_MIN (4, len))) {
119 op->type = R_ANAL_OP_TYPE_ILL;
120 } else {
121 op->type = R_ANAL_OP_TYPE_MOV;
122 if (op->cycles == 0) {
123 op->cycles = defaultCycles (op);
124 }
125 }
126 if (!op->mnemonic && (mask & R_ANAL_OP_MASK_DISASM)) {
127 if (anal->verbose) {
128 eprintf ("Warning: unhandled R_ANAL_OP_MASK_DISASM in r_anal_op\n");
129 }
130 }
131 if (mask & R_ANAL_OP_MASK_HINT) {
132 RAnalHint *hint = r_anal_hint_get (anal, addr);
133 if (hint) {
134 r_anal_op_hint (op, hint);
135 r_anal_hint_free (hint);
136 }
137 }
138 return ret;
139 }
140
r_anal_op_copy(RAnalOp * op)141 R_API RAnalOp *r_anal_op_copy(RAnalOp *op) {
142 RAnalOp *nop = R_NEW0 (RAnalOp);
143 if (!nop) {
144 return NULL;
145 }
146 *nop = *op;
147 if (op->mnemonic) {
148 nop->mnemonic = strdup (op->mnemonic);
149 if (!nop->mnemonic) {
150 free (nop);
151 return NULL;
152 }
153 } else {
154 nop->mnemonic = NULL;
155 }
156 nop->src[0] = r_anal_value_copy (op->src[0]);
157 nop->src[1] = r_anal_value_copy (op->src[1]);
158 nop->src[2] = r_anal_value_copy (op->src[2]);
159 nop->dst = r_anal_value_copy (op->dst);
160 if (op->access) {
161 RListIter *it;
162 RAnalValue *val;
163 RList *naccess = r_list_newf ((RListFree)r_anal_value_free);
164 r_list_foreach (op->access, it, val) {
165 r_list_append (naccess, r_anal_value_copy (val));
166 }
167 nop->access = naccess;
168 }
169 r_strbuf_init (&nop->esil);
170 r_strbuf_copy (&nop->esil, &op->esil);
171 return nop;
172 }
173
r_anal_op_nonlinear(int t)174 R_API bool r_anal_op_nonlinear(int t) {
175 t &= R_ANAL_OP_TYPE_MASK;
176 switch (t) {
177 //call
178 case R_ANAL_OP_TYPE_CALL:
179 case R_ANAL_OP_TYPE_RCALL:
180 case R_ANAL_OP_TYPE_ICALL:
181 case R_ANAL_OP_TYPE_UCALL:
182 case R_ANAL_OP_TYPE_IRCALL:
183 case R_ANAL_OP_TYPE_UCCALL:
184 // jmp
185 case R_ANAL_OP_TYPE_JMP:
186 case R_ANAL_OP_TYPE_MJMP:
187 case R_ANAL_OP_TYPE_UJMP:
188 case R_ANAL_OP_TYPE_CJMP:
189 case R_ANAL_OP_TYPE_UCJMP:
190 case R_ANAL_OP_TYPE_RJMP:
191 case R_ANAL_OP_TYPE_IJMP:
192 case R_ANAL_OP_TYPE_IRJMP:
193 // trap| ill| unk
194 case R_ANAL_OP_TYPE_TRAP:
195 case R_ANAL_OP_TYPE_ILL:
196 case R_ANAL_OP_TYPE_UNK:
197 case R_ANAL_OP_TYPE_SWI:
198 case R_ANAL_OP_TYPE_RET:
199 return true;
200 default:
201 return false;
202 }
203 }
204
r_anal_op_ismemref(int t)205 R_API bool r_anal_op_ismemref(int t) {
206 t &= R_ANAL_OP_TYPE_MASK;
207 switch (t) {
208 case R_ANAL_OP_TYPE_LOAD:
209 case R_ANAL_OP_TYPE_MOV:
210 case R_ANAL_OP_TYPE_STORE:
211 case R_ANAL_OP_TYPE_LEA:
212 case R_ANAL_OP_TYPE_CMP:
213 return true;
214 default:
215 return false;
216 }
217 }
218
219 static struct optype {
220 int type;
221 const char *name;
222 } optypes[] = {
223 { R_ANAL_OP_TYPE_IO, "io" },
224 { R_ANAL_OP_TYPE_ACMP, "acmp" },
225 { R_ANAL_OP_TYPE_ADD, "add" },
226 { R_ANAL_OP_TYPE_SYNC, "sync" },
227 { R_ANAL_OP_TYPE_AND, "and" },
228 { R_ANAL_OP_TYPE_CALL, "call" },
229 { R_ANAL_OP_TYPE_CCALL, "ccall" },
230 { R_ANAL_OP_TYPE_CJMP, "cjmp" },
231 { R_ANAL_OP_TYPE_MJMP, "mjmp" },
232 { R_ANAL_OP_TYPE_CMP, "cmp" },
233 { R_ANAL_OP_TYPE_IO, "cret" },
234 { R_ANAL_OP_TYPE_ILL, "ill" },
235 { R_ANAL_OP_TYPE_JMP, "jmp" },
236 { R_ANAL_OP_TYPE_LEA, "lea" },
237 { R_ANAL_OP_TYPE_LEAVE, "leave" },
238 { R_ANAL_OP_TYPE_LOAD, "load" },
239 { R_ANAL_OP_TYPE_NEW, "new" },
240 { R_ANAL_OP_TYPE_MOD, "mod" },
241 { R_ANAL_OP_TYPE_CMOV, "cmov" },
242 { R_ANAL_OP_TYPE_MOV, "mov" },
243 { R_ANAL_OP_TYPE_CAST, "cast" },
244 { R_ANAL_OP_TYPE_MUL, "mul" },
245 { R_ANAL_OP_TYPE_DIV, "div" },
246 { R_ANAL_OP_TYPE_NOP, "nop" },
247 { R_ANAL_OP_TYPE_NOT, "not" },
248 { R_ANAL_OP_TYPE_NULL , "null" },
249 { R_ANAL_OP_TYPE_OR , "or" },
250 { R_ANAL_OP_TYPE_POP , "pop" },
251 { R_ANAL_OP_TYPE_PUSH , "push" },
252 { R_ANAL_OP_TYPE_REP , "rep" },
253 { R_ANAL_OP_TYPE_RET , "ret" },
254 { R_ANAL_OP_TYPE_ROL , "rol" },
255 { R_ANAL_OP_TYPE_ROR , "ror" },
256 { R_ANAL_OP_TYPE_SAL , "sal" },
257 { R_ANAL_OP_TYPE_SAR , "sar" },
258 { R_ANAL_OP_TYPE_SHL , "shl" },
259 { R_ANAL_OP_TYPE_SHR , "shr" },
260 { R_ANAL_OP_TYPE_STORE , "store" },
261 { R_ANAL_OP_TYPE_SUB , "sub" },
262 { R_ANAL_OP_TYPE_SWI , "swi" },
263 { R_ANAL_OP_TYPE_CSWI , "cswi" },
264 { R_ANAL_OP_TYPE_SWITCH, "switch" },
265 { R_ANAL_OP_TYPE_TRAP , "trap" },
266 { R_ANAL_OP_TYPE_UCALL , "ucall" },
267 { R_ANAL_OP_TYPE_RCALL , "rcall" }, // needs to be changed
268 { R_ANAL_OP_TYPE_ICALL , "ucall" }, // needs to be changed
269 { R_ANAL_OP_TYPE_IRCALL, "ucall" }, // needs to be changed
270 { R_ANAL_OP_TYPE_UCCALL, "uccall" },
271 { R_ANAL_OP_TYPE_UCJMP , "ucjmp" },
272 { R_ANAL_OP_TYPE_UJMP , "ujmp" },
273 { R_ANAL_OP_TYPE_RJMP , "rjmp" }, // needs to be changed
274 { R_ANAL_OP_TYPE_IJMP , "ujmp" }, // needs to be changed
275 { R_ANAL_OP_TYPE_IRJMP , "ujmp" }, // needs to be changed
276 { R_ANAL_OP_TYPE_UNK , "unk" },
277 { R_ANAL_OP_TYPE_UPUSH , "upush" },
278 { R_ANAL_OP_TYPE_RPUSH , "rpush" },
279 { R_ANAL_OP_TYPE_XCHG , "xchg" },
280 { R_ANAL_OP_TYPE_XOR , "xor" },
281 { R_ANAL_OP_TYPE_CASE , "case" },
282 { R_ANAL_OP_TYPE_CPL , "cpl" },
283 { R_ANAL_OP_TYPE_CRYPTO, "crypto" },
284 {0,NULL}
285 };
286
r_anal_optype_from_string(const char * type)287 R_API int r_anal_optype_from_string(const char *type) {
288 int i;
289 for (i = 0; optypes[i].name;i++) {
290 if (!strcmp (optypes[i].name, type)) {
291 return optypes[i].type;
292 }
293 }
294 return -1;
295 }
296
r_anal_optype_to_string(int t)297 R_API const char *r_anal_optype_to_string(int t) {
298 bool once = true;
299 repeat:
300 // TODO: delete
301 switch (t) {
302 case R_ANAL_OP_TYPE_IO : return "io";
303 case R_ANAL_OP_TYPE_ACMP : return "acmp";
304 case R_ANAL_OP_TYPE_ADD : return "add";
305 case R_ANAL_OP_TYPE_SYNC : return "sync";
306 case R_ANAL_OP_TYPE_AND : return "and";
307 case R_ANAL_OP_TYPE_CALL : return "call";
308 case R_ANAL_OP_TYPE_CCALL : return "ccall";
309 case R_ANAL_OP_TYPE_CJMP : return "cjmp";
310 case R_ANAL_OP_TYPE_MJMP : return "mjmp";
311 case R_ANAL_OP_TYPE_CMP : return "cmp";
312 case R_ANAL_OP_TYPE_CRET : return "cret";
313 case R_ANAL_OP_TYPE_DIV : return "div";
314 case R_ANAL_OP_TYPE_ILL : return "ill";
315 case R_ANAL_OP_TYPE_JMP : return "jmp";
316 case R_ANAL_OP_TYPE_LEA : return "lea";
317 case R_ANAL_OP_TYPE_LEAVE : return "leave";
318 case R_ANAL_OP_TYPE_LOAD : return "load";
319 case R_ANAL_OP_TYPE_NEW : return "new";
320 case R_ANAL_OP_TYPE_MOD : return "mod";
321 case R_ANAL_OP_TYPE_CMOV : return "cmov";
322 case R_ANAL_OP_TYPE_MOV : return "mov";
323 case R_ANAL_OP_TYPE_CAST : return "cast";
324 case R_ANAL_OP_TYPE_MUL : return "mul";
325 case R_ANAL_OP_TYPE_NOP : return "nop";
326 case R_ANAL_OP_TYPE_NOT : return "not";
327 case R_ANAL_OP_TYPE_NULL : return "null";
328 case R_ANAL_OP_TYPE_OR : return "or";
329 case R_ANAL_OP_TYPE_POP : return "pop";
330 case R_ANAL_OP_TYPE_PUSH : return "push";
331 case R_ANAL_OP_TYPE_RPUSH : return "rpush";
332 case R_ANAL_OP_TYPE_REP : return "rep";
333 case R_ANAL_OP_TYPE_RET : return "ret";
334 case R_ANAL_OP_TYPE_ROL : return "rol";
335 case R_ANAL_OP_TYPE_ROR : return "ror";
336 case R_ANAL_OP_TYPE_SAL : return "sal";
337 case R_ANAL_OP_TYPE_SAR : return "sar";
338 case R_ANAL_OP_TYPE_SHL : return "shl";
339 case R_ANAL_OP_TYPE_SHR : return "shr";
340 case R_ANAL_OP_TYPE_STORE : return "store";
341 case R_ANAL_OP_TYPE_SUB : return "sub";
342 case R_ANAL_OP_TYPE_SWI : return "swi";
343 case R_ANAL_OP_TYPE_CSWI : return "cswi";
344 case R_ANAL_OP_TYPE_SWITCH: return "switch";
345 case R_ANAL_OP_TYPE_TRAP : return "trap";
346 case R_ANAL_OP_TYPE_UCALL : return "ucall";
347 case R_ANAL_OP_TYPE_RCALL : return "rcall"; // needs to be changed
348 case R_ANAL_OP_TYPE_ICALL : return "ucall"; // needs to be changed
349 case R_ANAL_OP_TYPE_IRCALL: return "ucall"; // needs to be changed
350 case R_ANAL_OP_TYPE_UCCALL: return "uccall";
351 case R_ANAL_OP_TYPE_UCJMP : return "ucjmp";
352 case R_ANAL_OP_TYPE_UJMP : return "ujmp";
353 case R_ANAL_OP_TYPE_RJMP : return "rjmp"; // needs to be changed
354 case R_ANAL_OP_TYPE_IJMP : return "ujmp"; // needs to be changed
355 case R_ANAL_OP_TYPE_IRJMP : return "ujmp"; // needs to be changed
356 case R_ANAL_OP_TYPE_UNK : return "unk";
357 case R_ANAL_OP_TYPE_UPUSH : return "upush";
358 case R_ANAL_OP_TYPE_XCHG : return "xchg";
359 case R_ANAL_OP_TYPE_XOR : return "xor";
360 case R_ANAL_OP_TYPE_CASE : return "case";
361 case R_ANAL_OP_TYPE_CPL : return "cpl";
362 case R_ANAL_OP_TYPE_CRYPTO: return "crypto";
363 }
364 if (once) {
365 once = false;
366 t &= R_ANAL_OP_TYPE_MASK; // ignore the modifier bits... we don't want this!
367 goto repeat;
368 }
369 return "undefined";
370 }
371
r_anal_op_to_esil_string(RAnal * anal,RAnalOp * op)372 R_API const char *r_anal_op_to_esil_string(RAnal *anal, RAnalOp *op) {
373 return r_strbuf_get (&op->esil);
374 }
375
376 // TODO: use esil here?
r_anal_op_to_string(RAnal * anal,RAnalOp * op)377 R_API char *r_anal_op_to_string(RAnal *anal, RAnalOp *op) {
378 RAnalBlock *bb;
379 RAnalFunction *f;
380 char *cstr, ret[128];
381 char *r0 = r_anal_value_to_string (op->dst);
382 char *a0 = r_anal_value_to_string (op->src[0]);
383 char *a1 = r_anal_value_to_string (op->src[1]);
384 if (!r0) {
385 r0 = strdup ("?");
386 }
387 if (!a0) {
388 a0 = strdup ("?");
389 }
390 if (!a1) {
391 a1 = strdup ("?");
392 }
393
394 switch (op->type) {
395 case R_ANAL_OP_TYPE_MOV:
396 snprintf (ret, sizeof (ret), "%s = %s", r0, a0);
397 break;
398 case R_ANAL_OP_TYPE_CJMP:
399 if ((bb = r_anal_bb_from_offset (anal, op->addr))) {
400 cstr = r_anal_cond_to_string (bb->cond);
401 snprintf (ret, sizeof (ret), "if (%s) goto 0x%"PFMT64x, cstr, op->jump);
402 free (cstr);
403 } else {
404 snprintf (ret, sizeof (ret), "if (%s) goto 0x%"PFMT64x, "?", op->jump);
405 }
406 break;
407 case R_ANAL_OP_TYPE_JMP:
408 snprintf (ret, sizeof (ret), "goto 0x%"PFMT64x, op->jump);
409 break;
410 case R_ANAL_OP_TYPE_UJMP:
411 case R_ANAL_OP_TYPE_RJMP:
412 case R_ANAL_OP_TYPE_IJMP:
413 case R_ANAL_OP_TYPE_IRJMP:
414 snprintf (ret, sizeof (ret), "goto %s", r0);
415 break;
416 case R_ANAL_OP_TYPE_PUSH:
417 case R_ANAL_OP_TYPE_UPUSH:
418 case R_ANAL_OP_TYPE_RPUSH:
419 snprintf (ret, sizeof (ret), "push %s", a0);
420 break;
421 case R_ANAL_OP_TYPE_POP:
422 snprintf (ret, sizeof (ret), "pop %s", r0);
423 break;
424 case R_ANAL_OP_TYPE_UCALL:
425 case R_ANAL_OP_TYPE_RCALL:
426 case R_ANAL_OP_TYPE_ICALL:
427 case R_ANAL_OP_TYPE_IRCALL:
428 snprintf (ret, sizeof (ret), "%s()", r0);
429 break;
430 case R_ANAL_OP_TYPE_CALL:
431 f = r_anal_get_fcn_in (anal, op->jump, R_ANAL_FCN_TYPE_NULL);
432 if (f) {
433 snprintf (ret, sizeof (ret), "%s()", f->name);
434 } else {
435 snprintf (ret, sizeof (ret), "0x%"PFMT64x"()", op->jump);
436 }
437 break;
438 case R_ANAL_OP_TYPE_CCALL:
439 f = r_anal_get_fcn_in (anal, op->jump, R_ANAL_FCN_TYPE_NULL);
440 if ((bb = r_anal_bb_from_offset (anal, op->addr))) {
441 cstr = r_anal_cond_to_string (bb->cond);
442 if (f) {
443 snprintf (ret, sizeof (ret), "if (%s) %s()", cstr, f->name);
444 } else {
445 snprintf (ret, sizeof (ret), "if (%s) 0x%" PFMT64x "()", cstr, op->jump);
446 }
447 free (cstr);
448 } else {
449 if (f) {
450 snprintf (ret, sizeof (ret), "if (unk) %s()", f->name);
451 } else {
452 snprintf (ret, sizeof (ret), "if (unk) 0x%" PFMT64x "()", op->jump);
453 }
454 }
455 break;
456 case R_ANAL_OP_TYPE_ADD:
457 if (!a1 || !strcmp (a0, a1)) {
458 snprintf (ret, sizeof (ret), "%s += %s", r0, a0);
459 } else {
460 snprintf (ret, sizeof (ret), "%s = %s + %s", r0, a0, a1);
461 }
462 break;
463 case R_ANAL_OP_TYPE_SUB:
464 if (!a1 || !strcmp (a0, a1)) {
465 snprintf (ret, sizeof (ret), "%s -= %s", r0, a0);
466 } else {
467 snprintf (ret, sizeof (ret), "%s = %s - %s", r0, a0, a1);
468 }
469 break;
470 case R_ANAL_OP_TYPE_MUL:
471 if (!a1 || !strcmp (a0, a1)) {
472 snprintf (ret, sizeof (ret), "%s *= %s", r0, a0);
473 } else {
474 snprintf (ret, sizeof (ret), "%s = %s * %s", r0, a0, a1);
475 }
476 break;
477 case R_ANAL_OP_TYPE_DIV:
478 if (!a1 || !strcmp (a0, a1)) {
479 snprintf (ret, sizeof (ret), "%s /= %s", r0, a0);
480 } else {
481 snprintf (ret, sizeof (ret), "%s = %s / %s", r0, a0, a1);
482 }
483 break;
484 case R_ANAL_OP_TYPE_AND:
485 if (!a1 || !strcmp (a0, a1)) {
486 snprintf (ret, sizeof (ret), "%s &= %s", r0, a0);
487 } else {
488 snprintf (ret, sizeof (ret), "%s = %s & %s", r0, a0, a1);
489 }
490 break;
491 case R_ANAL_OP_TYPE_OR:
492 if (!a1 || !strcmp (a0, a1)) {
493 snprintf (ret, sizeof (ret), "%s |= %s", r0, a0);
494 } else {
495 snprintf (ret, sizeof (ret), "%s = %s | %s", r0, a0, a1);
496 }
497 break;
498 case R_ANAL_OP_TYPE_XOR:
499 if (!a1 || !strcmp (a0, a1)) {
500 snprintf (ret, sizeof (ret), "%s ^= %s", r0, a0);
501 } else {
502 snprintf (ret, sizeof (ret), "%s = %s ^ %s", r0, a0, a1);
503 }
504 break;
505 case R_ANAL_OP_TYPE_LEA:
506 snprintf (ret, sizeof (ret), "%s -> %s", r0, a0);
507 break;
508 case R_ANAL_OP_TYPE_CMP:
509 memcpy (ret, ";", 2);
510 break;
511 case R_ANAL_OP_TYPE_NOP:
512 memcpy (ret, "nop", 4);
513 break;
514 case R_ANAL_OP_TYPE_RET:
515 memcpy (ret, "ret", 4);
516 break;
517 case R_ANAL_OP_TYPE_CRET:
518 if ((bb = r_anal_bb_from_offset (anal, op->addr))) {
519 cstr = r_anal_cond_to_string (bb->cond);
520 snprintf (ret, sizeof (ret), "if (%s) ret", cstr);
521 free (cstr);
522 } else {
523 strcpy (ret, "if (unk) ret");
524 }
525 break;
526 case R_ANAL_OP_TYPE_LEAVE:
527 memcpy (ret, "leave", 6);
528 break;
529 case R_ANAL_OP_TYPE_MOD:
530 if (!a1 || !strcmp (a0, a1)) {
531 snprintf (ret, sizeof (ret), "%s %%= %s", r0, a0);
532 } else {
533 snprintf (ret, sizeof (ret), "%s = %s %% %s", r0, a0, a1);
534 }
535 break;
536 case R_ANAL_OP_TYPE_XCHG:
537 if (!a1 || !strcmp (a0, a1)) {
538 snprintf (ret, sizeof (ret), "tmp = %s; %s = %s; %s = tmp", r0, r0, a0, a0);
539 } else {
540 snprintf (ret, sizeof (ret), "%s = %s ^ %s", r0, a0, a1);
541 }
542 break;
543 case R_ANAL_OP_TYPE_ROL:
544 case R_ANAL_OP_TYPE_ROR:
545 case R_ANAL_OP_TYPE_SWITCH:
546 case R_ANAL_OP_TYPE_CASE:
547 eprintf ("Command not implemented.\n");
548 free (r0);
549 free (a0);
550 free (a1);
551 return NULL;
552 default:
553 free (r0);
554 free (a0);
555 free (a1);
556 return NULL;
557 }
558 free (r0);
559 free (a0);
560 free (a1);
561 return strdup (ret);
562 }
563
r_anal_stackop_tostring(int s)564 R_API const char *r_anal_stackop_tostring(int s) {
565 switch (s) {
566 case R_ANAL_STACK_NULL:
567 return "null";
568 case R_ANAL_STACK_NOP:
569 return "nop";
570 case R_ANAL_STACK_INC:
571 return "inc";
572 case R_ANAL_STACK_GET:
573 return "get";
574 case R_ANAL_STACK_SET:
575 return "set";
576 case R_ANAL_STACK_RESET:
577 return "reset";
578 }
579 return "unk";
580 }
581
r_anal_op_family_to_string(int n)582 R_API const char *r_anal_op_family_to_string(int n) {
583 switch (n) {
584 case R_ANAL_OP_FAMILY_UNKNOWN: return "unk";
585 case R_ANAL_OP_FAMILY_CPU: return "cpu";
586 case R_ANAL_OP_FAMILY_SECURITY: return "sec";
587 case R_ANAL_OP_FAMILY_FPU: return "fpu";
588 case R_ANAL_OP_FAMILY_MMX: return "mmx";
589 case R_ANAL_OP_FAMILY_SSE: return "sse";
590 case R_ANAL_OP_FAMILY_PRIV: return "priv";
591 case R_ANAL_OP_FAMILY_THREAD: return "thrd";
592 case R_ANAL_OP_FAMILY_CRYPTO: return "crpt";
593 case R_ANAL_OP_FAMILY_IO: return "io";
594 case R_ANAL_OP_FAMILY_VIRT: return "virt";
595 }
596 return NULL;
597 }
598
r_anal_op_family_from_string(const char * f)599 R_API int r_anal_op_family_from_string(const char *f) {
600 struct op_family {
601 const char *name;
602 int id;
603 };
604 static const struct op_family of[] = {
605 {"cpu", R_ANAL_OP_FAMILY_CPU},
606 {"fpu", R_ANAL_OP_FAMILY_FPU},
607 {"mmx", R_ANAL_OP_FAMILY_MMX},
608 {"sse", R_ANAL_OP_FAMILY_SSE},
609 {"priv", R_ANAL_OP_FAMILY_PRIV},
610 {"virt", R_ANAL_OP_FAMILY_VIRT},
611 {"crpt", R_ANAL_OP_FAMILY_CRYPTO},
612 {"io", R_ANAL_OP_FAMILY_IO},
613 {"sec", R_ANAL_OP_FAMILY_SECURITY},
614 {"thread", R_ANAL_OP_FAMILY_THREAD},
615 };
616
617 int i;
618 for (i = 0; i < sizeof (of) / sizeof (of[0]); i ++) {
619 if (!strcmp (f, of[i].name)) {
620 return of[i].id;
621 }
622 }
623 return R_ANAL_OP_FAMILY_UNKNOWN;
624 }
625
626 /* apply hint to op, return the number of hints applied */
r_anal_op_hint(RAnalOp * op,RAnalHint * hint)627 R_API int r_anal_op_hint(RAnalOp *op, RAnalHint *hint) {
628 int changes = 0;
629 if (hint) {
630 if (hint->val != UT64_MAX) {
631 op->val = hint->val;
632 changes++;
633 }
634 if (hint->type > 0) {
635 op->type = hint->type;
636 changes++;
637 }
638 if (hint->jump != UT64_MAX) {
639 op->jump = hint->jump;
640 changes++;
641 }
642 if (hint->fail != UT64_MAX) {
643 op->fail = hint->fail;
644 changes++;
645 }
646 if (hint->opcode) {
647 /* XXX: this is not correct */
648 free (op->mnemonic);
649 op->mnemonic = strdup (hint->opcode);
650 changes++;
651 }
652 if (hint->esil) {
653 r_strbuf_set (&op->esil, hint->esil);
654 changes++;
655 }
656 if (hint->size) {
657 op->size = hint->size;
658 changes++;
659 }
660 }
661 return changes;
662 }
663
664 // returns the '33' in 'rax + 33'
665 // returns value for the given register name in specific address / range
666 // imho this should not iterate, should be just a helper to get that value
r_anal_op_reg_delta(RAnal * anal,ut64 addr,const char * name)667 R_API int r_anal_op_reg_delta(RAnal *anal, ut64 addr, const char *name) {
668 ut8 buf[32];
669 anal->iob.read_at (anal->iob.io, addr, buf, sizeof (buf));
670 RAnalOp op = { 0 };
671 if (r_anal_op (anal, &op, addr, buf, sizeof (buf), R_ANAL_OP_MASK_ALL) > 0) {
672 if (op.dst && op.dst->reg && op.dst->reg->name && (!name || !strcmp (op.dst->reg->name, name))) {
673 if (op.src[0]) {
674 return op.src[0]->delta;
675 }
676 }
677 }
678 return 0;
679 }
680