1 /* radare - LGPL - Copyright 2009-2020 - pancake, nibble */
2
3 #include <r_anal.h>
4 #include <r_util.h>
5 #include <r_list.h>
6 #include <r_io.h>
7 #include <config.h>
8 #include "../config.h"
9
10 R_LIB_VERSION(r_anal);
11
12 static RAnalPlugin *anal_static_plugins[] = {
13 R_ANAL_STATIC_PLUGINS
14 };
15
16 static RAnalEsilPlugin *esil_static_plugins[] = {
17 R_ESIL_STATIC_PLUGINS
18 };
19
r_anal_set_limits(RAnal * anal,ut64 from,ut64 to)20 R_API void r_anal_set_limits(RAnal *anal, ut64 from, ut64 to) {
21 free (anal->limit);
22 anal->limit = R_NEW0 (RAnalRange);
23 if (anal->limit) {
24 anal->limit->from = from;
25 anal->limit->to = to;
26 }
27 }
28
r_anal_unset_limits(RAnal * anal)29 R_API void r_anal_unset_limits(RAnal *anal) {
30 R_FREE (anal->limit);
31 }
32
meta_unset_for(REvent * ev,int type,void * user,void * data)33 static void meta_unset_for(REvent *ev, int type, void *user, void *data) {
34 RSpaces *s = (RSpaces *)ev->user;
35 RAnal *anal = container_of (s, RAnal, meta_spaces);
36 RSpaceEvent *se = (RSpaceEvent *)data;
37 r_meta_space_unset_for (anal, se->data.unset.space);
38 }
39
meta_count_for(REvent * ev,int type,void * user,void * data)40 static void meta_count_for(REvent *ev, int type, void *user, void *data) {
41 RSpaces *s = (RSpaces *)ev->user;
42 RAnal *anal = container_of (s, RAnal, meta_spaces);
43 RSpaceEvent *se = (RSpaceEvent *)data;
44 se->res = r_meta_space_count_for (anal, se->data.count.space);
45 }
46
zign_unset_for(REvent * ev,int type,void * user,void * data)47 static void zign_unset_for(REvent *ev, int type, void *user, void *data) {
48 RSpaces *s = (RSpaces *)ev->user;
49 RAnal *anal = container_of (s, RAnal, zign_spaces);
50 RSpaceEvent *se = (RSpaceEvent *)data;
51 r_sign_space_unset_for (anal, se->data.unset.space);
52 }
53
zign_count_for(REvent * ev,int type,void * user,void * data)54 static void zign_count_for(REvent *ev, int type, void *user, void *data) {
55 RSpaces *s = (RSpaces *)ev->user;
56 RAnal *anal = container_of (s, RAnal, zign_spaces);
57 RSpaceEvent *se = (RSpaceEvent *)data;
58 se->res = r_sign_space_count_for (anal, se->data.count.space);
59 }
60
zign_rename_for(REvent * ev,int type,void * user,void * data)61 static void zign_rename_for(REvent *ev, int type, void *user, void *data) {
62 RSpaces *s = (RSpaces *)ev->user;
63 RAnal *anal = container_of (s, RAnal, zign_spaces);
64 RSpaceEvent *se = (RSpaceEvent *)data;
65 r_sign_space_rename_for (anal, se->data.rename.space,
66 se->data.rename.oldname, se->data.rename.newname);
67 }
68
69 void r_anal_hint_storage_init(RAnal *a);
70 void r_anal_hint_storage_fini(RAnal *a);
71
r_meta_item_fini(RAnalMetaItem * item)72 static void r_meta_item_fini(RAnalMetaItem *item) {
73 free (item->str);
74 }
75
r_meta_item_free(void * _item)76 static void r_meta_item_free(void *_item) {
77 if (_item) {
78 RAnalMetaItem *item = _item;
79 r_meta_item_fini (item);
80 free (item);
81 }
82 }
83
r_anal_esil_plugin_free(RAnalEsilPlugin * p)84 R_API void r_anal_esil_plugin_free (RAnalEsilPlugin *p) {
85 if (p && p->fini) {
86 p->fini (NULL);
87 }
88 }
89
r_anal_esil_add(RAnal * anal,RAnalEsilPlugin * foo)90 R_API int r_anal_esil_add(RAnal *anal, RAnalEsilPlugin *foo) {
91 if (foo->init) {
92 foo->init (anal->user);
93 }
94 r_list_append (anal->esil_plugins, foo);
95 return true;
96 }
97
r_anal_new(void)98 R_API RAnal *r_anal_new(void) {
99 int i;
100 RAnal *anal = R_NEW0 (RAnal);
101 if (!anal) {
102 return NULL;
103 }
104 if (!r_str_constpool_init (&anal->constpool)) {
105 free (anal);
106 return NULL;
107 }
108 anal->bb_tree = NULL;
109 anal->ht_addr_fun = ht_up_new0 ();
110 anal->ht_name_fun = ht_pp_new0 ();
111 anal->os = strdup (R_SYS_OS);
112 anal->esil_goto_limit = R_ANAL_ESIL_GOTO_LIMIT;
113 anal->opt.nopskip = true; // skip nops in code analysis
114 anal->opt.hpskip = false; // skip `mov reg,reg` and `lea reg,[reg]`
115 anal->gp = 0LL;
116 anal->sdb = sdb_new0 ();
117 anal->cpp_abi = R_ANAL_CPP_ABI_ITANIUM;
118 anal->opt.depth = 32;
119 anal->opt.noncode = false; // do not analyze data by default
120 r_spaces_init (&anal->meta_spaces, "CS");
121 r_event_hook (anal->meta_spaces.event, R_SPACE_EVENT_UNSET, meta_unset_for, NULL);
122 r_event_hook (anal->meta_spaces.event, R_SPACE_EVENT_COUNT, meta_count_for, NULL);
123
124 r_spaces_init (&anal->zign_spaces, "zs");
125 r_event_hook (anal->zign_spaces.event, R_SPACE_EVENT_UNSET, zign_unset_for, NULL);
126 r_event_hook (anal->zign_spaces.event, R_SPACE_EVENT_COUNT, zign_count_for, NULL);
127 r_event_hook (anal->zign_spaces.event, R_SPACE_EVENT_RENAME, zign_rename_for, NULL);
128 r_anal_hint_storage_init (anal);
129 r_interval_tree_init (&anal->meta, r_meta_item_free);
130 anal->sdb_types = sdb_ns (anal->sdb, "types", 1);
131 anal->sdb_fmts = sdb_ns (anal->sdb, "spec", 1);
132 anal->sdb_cc = sdb_ns (anal->sdb, "cc", 1);
133 anal->sdb_zigns = sdb_ns (anal->sdb, "zigns", 1);
134 anal->sdb_classes = sdb_ns (anal->sdb, "classes", 1);
135 anal->sdb_classes_attrs = sdb_ns (anal->sdb_classes, "attrs", 1);
136 anal->zign_path = strdup ("");
137 anal->cb_printf = (PrintfCallback) printf;
138 (void)r_anal_pin_init (anal);
139 (void)r_anal_xrefs_init (anal);
140 anal->diff_thbb = R_ANAL_THRESHOLDBB;
141 anal->diff_thfcn = R_ANAL_THRESHOLDFCN;
142 anal->syscall = r_syscall_new ();
143 r_io_bind_init (anal->iob);
144 r_flag_bind_init (anal->flb);
145 anal->reg = r_reg_new ();
146 anal->last_disasm_reg = NULL;
147 anal->stackptr = 0;
148 anal->lineswidth = 0;
149 anal->fcns = r_list_newf (r_anal_function_free);
150 anal->leaddrs = NULL;
151 anal->imports = r_list_newf (free);
152 r_anal_set_bits (anal, 32);
153 anal->plugins = r_list_newf ((RListFree) r_anal_plugin_free);
154 if (anal->plugins) {
155 for (i = 0; anal_static_plugins[i]; i++) {
156 r_anal_add (anal, anal_static_plugins[i]);
157 }
158 }
159 anal->esil_plugins = r_list_newf ((RListFree) r_anal_esil_plugin_free);
160 if (anal->esil_plugins) {
161 for (i = 0; esil_static_plugins[i]; i++) {
162 r_anal_esil_add (anal, esil_static_plugins[i]);
163 }
164 }
165 return anal;
166 }
167
r_anal_plugin_free(RAnalPlugin * p)168 R_API void r_anal_plugin_free (RAnalPlugin *p) {
169 if (p && p->fini) {
170 p->fini (NULL);
171 }
172 }
173
174 void __block_free_rb(RBNode *node, void *user);
175
r_anal_free(RAnal * a)176 R_API RAnal *r_anal_free(RAnal *a) {
177 if (!a) {
178 return NULL;
179 }
180 /* TODO: Free anals here */
181 r_list_free (a->fcns);
182 ht_up_free (a->ht_addr_fun);
183 ht_pp_free (a->ht_name_fun);
184 set_u_free (a->visited);
185 r_anal_hint_storage_fini (a);
186 r_interval_tree_fini (&a->meta);
187 free (a->cpu);
188 free (a->os);
189 free (a->zign_path);
190 r_list_free (a->plugins);
191 r_list_free (a->esil_plugins);
192 r_rbtree_free (a->bb_tree, __block_free_rb, NULL);
193 r_spaces_fini (&a->meta_spaces);
194 r_spaces_fini (&a->zign_spaces);
195 r_anal_pin_fini (a);
196 r_syscall_free (a->syscall);
197 r_reg_free (a->reg);
198 ht_up_free (a->dict_refs);
199 ht_up_free (a->dict_xrefs);
200 r_list_free (a->leaddrs);
201 sdb_free (a->sdb);
202 if (a->esil) {
203 r_anal_esil_free (a->esil);
204 a->esil = NULL;
205 }
206 free (a->last_disasm_reg);
207 r_list_free (a->imports);
208 r_str_constpool_fini (&a->constpool);
209 free (a);
210 return NULL;
211 }
212
r_anal_set_user_ptr(RAnal * anal,void * user)213 R_API void r_anal_set_user_ptr(RAnal *anal, void *user) {
214 anal->user = user;
215 }
216
r_anal_esil_use(RAnal * anal,const char * name)217 R_API bool r_anal_esil_use(RAnal *anal, const char *name) {
218 RListIter *it;
219 RAnalEsilPlugin *h;
220
221 if (anal) {
222 r_list_foreach (anal->esil_plugins, it, h) {
223 if (!h->name || strcmp (h->name, name)) {
224 continue;
225 }
226 anal->esil_cur = h;
227 return true;
228 }
229 }
230 return false;
231 }
232
r_anal_add(RAnal * anal,RAnalPlugin * foo)233 R_API int r_anal_add(RAnal *anal, RAnalPlugin *foo) {
234 if (foo->init) {
235 foo->init (anal->user);
236 }
237 r_list_append (anal->plugins, foo);
238 return true;
239 }
240
r_anal_use(RAnal * anal,const char * name)241 R_API bool r_anal_use(RAnal *anal, const char *name) {
242 RListIter *it;
243 RAnalPlugin *h;
244
245 if (anal) {
246 r_list_foreach (anal->plugins, it, h) {
247 if (!h->name || strcmp (h->name, name)) {
248 continue;
249 }
250 #if 0
251 // regression happening here for asm.emu
252 if (anal->cur && anal->cur == h) {
253 return true;
254 }
255 #endif
256 anal->cur = h;
257 r_anal_set_reg_profile (anal);
258 return true;
259 }
260 }
261 return false;
262 }
263
r_anal_get_reg_profile(RAnal * anal)264 R_API char *r_anal_get_reg_profile(RAnal *anal) {
265 return (anal && anal->cur && anal->cur->get_reg_profile)
266 ? anal->cur->get_reg_profile (anal) : NULL;
267 }
268
269 // deprecate.. or at least reuse get_reg_profile...
r_anal_set_reg_profile(RAnal * anal)270 R_API bool r_anal_set_reg_profile(RAnal *anal) {
271 bool ret = false;
272 if (anal && anal->cur && anal->cur->set_reg_profile) {
273 ret = anal->cur->set_reg_profile (anal);
274 } else {
275 char *p = r_anal_get_reg_profile (anal);
276 if (p && *p) {
277 r_reg_set_profile_string (anal->reg, p);
278 ret = true;
279 }
280 free (p);
281 }
282 return ret;
283 }
284
r_anal_set_triplet(RAnal * anal,const char * os,const char * arch,int bits)285 R_API bool r_anal_set_triplet(RAnal *anal, const char *os, const char *arch, int bits) {
286 r_return_val_if_fail (anal, false);
287 if (!os || !*os) {
288 os = R_SYS_OS;
289 }
290 if (!arch || !*arch) {
291 arch = anal->cur? anal->cur->arch: R_SYS_ARCH;
292 }
293 if (bits < 1) {
294 bits = anal->bits;
295 }
296 free (anal->os);
297 anal->os = strdup (os);
298 r_anal_set_bits (anal, bits);
299 return r_anal_use (anal, arch);
300 }
301
302 // copypasta from core/cbin.c
sdb_concat_by_path(Sdb * s,const char * path)303 static void sdb_concat_by_path(Sdb *s, const char *path) {
304 Sdb *db = sdb_new (0, path, 0);
305 sdb_merge (s, db);
306 sdb_close (db);
307 sdb_free (db);
308 }
309
r_anal_set_os(RAnal * anal,const char * os)310 R_API bool r_anal_set_os(RAnal *anal, const char *os) {
311 Sdb *types = anal->sdb_types;
312 const char *dir_prefix = r_sys_prefix (NULL);
313 const char *dbpath = sdb_fmt (R_JOIN_3_PATHS ("%s", R2_SDB_FCNSIGN, "types-%s.sdb"),
314 dir_prefix, os);
315 if (r_file_exists (dbpath)) {
316 sdb_concat_by_path (types, dbpath);
317 }
318 return r_anal_set_triplet (anal, os, NULL, -1);
319 }
320
r_anal_set_bits(RAnal * anal,int bits)321 R_API bool r_anal_set_bits(RAnal *anal, int bits) {
322 switch (bits) {
323 case 8:
324 case 16:
325 case 27:
326 case 32:
327 case 64:
328 if (anal->bits != bits) {
329 anal->bits = bits;
330 r_anal_set_reg_profile (anal);
331 }
332 return true;
333 }
334 return false;
335 }
336
r_anal_set_cpu(RAnal * anal,const char * cpu)337 R_API void r_anal_set_cpu(RAnal *anal, const char *cpu) {
338 free (anal->cpu);
339 anal->cpu = cpu ? strdup (cpu) : NULL;
340 int v = r_anal_archinfo (anal, R_ANAL_ARCHINFO_ALIGN);
341 if (v != -1) {
342 anal->pcalign = v;
343 }
344 }
345
r_anal_set_big_endian(RAnal * anal,int bigend)346 R_API void r_anal_set_big_endian(RAnal *anal, int bigend) {
347 r_return_if_fail (anal);
348 anal->big_endian = bigend;
349 anal->reg->big_endian = bigend;
350 }
351
r_anal_mask(RAnal * anal,int size,const ut8 * data,ut64 at)352 R_API ut8 *r_anal_mask(RAnal *anal, int size, const ut8 *data, ut64 at) {
353 RAnalOp *op = NULL;
354 ut8 *ret = NULL;
355 int oplen, idx = 0;
356
357 if (!data) {
358 return NULL;
359 }
360
361 if (anal->cur && anal->cur->anal_mask) {
362 return anal->cur->anal_mask (anal, size, data, at);
363 }
364
365 if (!(op = r_anal_op_new ())) {
366 return NULL;
367 }
368
369 if (!(ret = malloc (size))) {
370 r_anal_op_free (op);
371 return NULL;
372 }
373
374 memset (ret, 0xff, size);
375
376 while (idx < size) {
377 if ((oplen = r_anal_op (anal, op, at, data + idx, size - idx, R_ANAL_OP_MASK_BASIC)) < 1) {
378 break;
379 }
380 if ((op->ptr != UT64_MAX || op->jump != UT64_MAX) && op->nopcode != 0) {
381 memset (ret + idx + op->nopcode, 0, oplen - op->nopcode);
382 }
383 idx += oplen;
384 at += oplen;
385 }
386
387 r_anal_op_free (op);
388
389 return ret;
390 }
391
r_anal_trace_bb(RAnal * anal,ut64 addr)392 R_API void r_anal_trace_bb(RAnal *anal, ut64 addr) {
393 r_return_if_fail (anal);
394 RAnalBlock *bbi;
395 RListIter *iter2;
396 RAnalFunction *fcni = r_anal_get_fcn_in (anal, addr, 0);
397 if (fcni) {
398 r_list_foreach (fcni->bbs, iter2, bbi) {
399 if (addr >= bbi->addr && addr < (bbi->addr + bbi->size)) {
400 bbi->traced = true;
401 break;
402 }
403 }
404 }
405 }
406
r_anal_get_fcns(RAnal * anal)407 R_API RList* r_anal_get_fcns (RAnal *anal) {
408 // avoid received to free this thing
409 anal->fcns->free = NULL;
410 return anal->fcns;
411 }
412
r_anal_op_hexstr(RAnal * anal,ut64 addr,const char * str)413 R_API RAnalOp *r_anal_op_hexstr(RAnal *anal, ut64 addr, const char *str) {
414 RAnalOp *op = R_NEW0 (RAnalOp);
415 if (!op) {
416 return NULL;
417 }
418 ut8 *buf = calloc (1, strlen (str) + 1);
419 if (!buf) {
420 free (op);
421 return NULL;
422 }
423 int len = r_hex_str2bin (str, buf);
424 r_anal_op (anal, op, addr, buf, len, R_ANAL_OP_MASK_BASIC);
425 free (buf);
426 return op;
427 }
428
r_anal_op_is_eob(RAnalOp * op)429 R_API bool r_anal_op_is_eob(RAnalOp *op) {
430 if (op->eob) {
431 return true;
432 }
433 switch (op->type) {
434 case R_ANAL_OP_TYPE_JMP:
435 case R_ANAL_OP_TYPE_UJMP:
436 case R_ANAL_OP_TYPE_RJMP:
437 case R_ANAL_OP_TYPE_IJMP:
438 case R_ANAL_OP_TYPE_IRJMP:
439 case R_ANAL_OP_TYPE_CJMP:
440 case R_ANAL_OP_TYPE_RET:
441 case R_ANAL_OP_TYPE_TRAP:
442 return true;
443 default:
444 return false;
445 }
446 }
447
r_anal_purge(RAnal * anal)448 R_API void r_anal_purge(RAnal *anal) {
449 r_anal_hint_clear (anal);
450 r_interval_tree_fini (&anal->meta);
451 r_interval_tree_init (&anal->meta, r_meta_item_free);
452 sdb_reset (anal->sdb_types);
453 sdb_reset (anal->sdb_zigns);
454 sdb_reset (anal->sdb_classes);
455 sdb_reset (anal->sdb_classes_attrs);
456 r_anal_pin_fini (anal);
457 r_anal_pin_init (anal);
458 sdb_reset (anal->sdb_cc);
459 r_list_free (anal->fcns);
460 anal->fcns = r_list_newf (r_anal_function_free);
461 r_anal_purge_imports (anal);
462 }
463
r_anal_archinfo(RAnal * anal,int query)464 R_API int r_anal_archinfo(RAnal *anal, int query) {
465 r_return_val_if_fail (anal, -1);
466 switch (query) {
467 case R_ANAL_ARCHINFO_MIN_OP_SIZE:
468 case R_ANAL_ARCHINFO_MAX_OP_SIZE:
469 case R_ANAL_ARCHINFO_ALIGN:
470 if (anal->cur && anal->cur->archinfo) {
471 return anal->cur->archinfo (anal, query);
472 }
473 break;
474 }
475 return -1;
476 }
477
__nonreturn_print_commands(void * p,const char * k,const char * v)478 static bool __nonreturn_print_commands(void *p, const char *k, const char *v) {
479 RAnal *anal = (RAnal *)p;
480 if (!strncmp (v, "func", strlen ("func") + 1)) {
481 char *query = sdb_fmt ("func.%s.noreturn", k);
482 if (sdb_bool_get (anal->sdb_types, query, NULL)) {
483 anal->cb_printf ("tnn %s\n", k);
484 }
485 }
486 if (!strncmp (k, "addr.", 5)) {
487 anal->cb_printf ("tna 0x%s %s\n", k + 5, v);
488 }
489 return true;
490 }
491
__nonreturn_print(void * p,const char * k,const char * v)492 static bool __nonreturn_print(void *p, const char *k, const char *v) {
493 RAnal *anal = (RAnal *)p;
494 if (!strncmp (k, "func.", 5) && strstr (k, ".noreturn")) {
495 char *s = strdup (k + 5);
496 char *d = strchr (s, '.');
497 if (d) {
498 *d = 0;
499 }
500 anal->cb_printf ("%s\n", s);
501 free (s);
502 }
503 if (!strncmp (k, "addr.", 5)) {
504 char *off;
505 if (!(off = strdup (k + 5))) {
506 return 1;
507 }
508 char *ptr = strstr (off, ".noreturn");
509 if (ptr) {
510 *ptr = 0;
511 anal->cb_printf ("0x%s\n", off);
512 }
513 free (off);
514 }
515 return true;
516 }
517
r_anal_noreturn_list(RAnal * anal,int mode)518 R_API void r_anal_noreturn_list(RAnal *anal, int mode) {
519 switch (mode) {
520 case 1:
521 case '*':
522 case 'r':
523 sdb_foreach (anal->sdb_types, __nonreturn_print_commands, anal);
524 break;
525 default:
526 sdb_foreach (anal->sdb_types, __nonreturn_print, anal);
527 break;
528 }
529 }
530
531 #define K_NORET_ADDR(x) sdb_fmt ("addr.%"PFMT64x".noreturn", x)
532 #define K_NORET_FUNC(x) sdb_fmt ("func.%s.noreturn", x)
533
r_anal_noreturn_add(RAnal * anal,const char * name,ut64 addr)534 R_API bool r_anal_noreturn_add(RAnal *anal, const char *name, ut64 addr) {
535 const char *tmp_name = NULL;
536 Sdb *TDB = anal->sdb_types;
537 char *fnl_name = NULL;
538 if (addr != UT64_MAX) {
539 if (sdb_bool_set (TDB, K_NORET_ADDR (addr), true, 0)) {
540 RAnalFunction *fcn = r_anal_get_function_at (anal, addr);
541 if (fcn) {
542 fcn->is_noreturn = true;
543 }
544 return true;
545 }
546 }
547 if (name && *name) {
548 tmp_name = name;
549 } else {
550 RAnalFunction *fcn = r_anal_get_fcn_in (anal, addr, -1);
551 RFlagItem *fi = anal->flb.get_at (anal->flb.f, addr, false);
552 if (!fcn && !fi) {
553 eprintf ("Can't find Function at given address\n");
554 return false;
555 }
556 tmp_name = fcn ? fcn->name: fi->name;
557 if (fcn) {
558 fcn->is_noreturn = true;
559 }
560 }
561 if (r_type_func_exist (TDB, tmp_name)) {
562 fnl_name = strdup (tmp_name);
563 } else if (!(fnl_name = r_type_func_guess (TDB, (char *)tmp_name))) {
564 if (addr == UT64_MAX) {
565 if (name) {
566 sdb_bool_set (TDB, K_NORET_FUNC (name), true, 0);
567 } else {
568 eprintf ("Can't find prototype for: %s\n", tmp_name);
569 }
570 } else {
571 eprintf ("Can't find prototype for: %s\n", tmp_name);
572 }
573 //return false;
574 }
575 if (fnl_name) {
576 sdb_bool_set (TDB, K_NORET_FUNC (fnl_name), true, 0);
577 free (fnl_name);
578 }
579 return true;
580 }
581
r_anal_noreturn_drop(RAnal * anal,const char * expr)582 R_API bool r_anal_noreturn_drop(RAnal *anal, const char *expr) {
583 Sdb *TDB = anal->sdb_types;
584 expr = r_str_trim_head_ro (expr);
585 const char *fcnname = NULL;
586 if (!strncmp (expr, "0x", 2)) {
587 ut64 n = r_num_math (NULL, expr);
588 sdb_unset (TDB, K_NORET_ADDR (n), 0);
589 RAnalFunction *fcn = r_anal_get_fcn_in (anal, n, -1);
590 if (!fcn) {
591 // eprintf ("can't find function at 0x%"PFMT64x"\n", n);
592 return false;
593 }
594 fcnname = fcn->name;
595 } else {
596 fcnname = expr;
597 }
598 sdb_unset (TDB, K_NORET_FUNC (fcnname), 0);
599 #if 0
600 char *tmp;
601 // unnsecessary checks, imho the noreturn db should be pretty simple to allow forward and custom declarations without having to define the function prototype before
602 if (r_type_func_exist (TDB, fcnname)) {
603 sdb_unset (TDB, K_NORET_FUNC (fcnname), 0);
604 return true;
605 } else if ((tmp = r_type_func_guess (TDB, (char *)fcnname))) {
606 sdb_unset (TDB, K_NORET_FUNC (fcnname), 0);
607 free (tmp);
608 return true;
609 }
610 eprintf ("Can't find prototype for %s in types database", fcnname);
611 #endif
612 return false;
613 }
614
r_anal_noreturn_at_name(RAnal * anal,const char * name)615 static bool r_anal_noreturn_at_name(RAnal *anal, const char *name) {
616 if (sdb_bool_get (anal->sdb_types, K_NORET_FUNC(name), NULL)) {
617 return true;
618 }
619 char *tmp = r_type_func_guess (anal->sdb_types, (char *)name);
620 if (tmp) {
621 if (sdb_bool_get (anal->sdb_types, K_NORET_FUNC (tmp), NULL)) {
622 free (tmp);
623 return true;
624 }
625 free (tmp);
626 }
627 if (r_str_startswith (name, "reloc.")) {
628 return r_anal_noreturn_at_name (anal, name + 6);
629 }
630 return false;
631 }
632
r_anal_noreturn_at_addr(RAnal * anal,ut64 addr)633 R_API bool r_anal_noreturn_at_addr(RAnal *anal, ut64 addr) {
634 return sdb_bool_get (anal->sdb_types, K_NORET_ADDR (addr), NULL);
635 }
636
noreturn_recurse(RAnal * anal,ut64 addr)637 static bool noreturn_recurse(RAnal *anal, ut64 addr) {
638 RAnalOp op = {0};
639 ut8 bbuf[0x10] = {0};
640 ut64 recurse_addr = UT64_MAX;
641 if (!anal->iob.read_at (anal->iob.io, addr, bbuf, sizeof (bbuf))) {
642 eprintf ("Couldn't read buffer\n");
643 return false;
644 }
645 if (r_anal_op (anal, &op, addr, bbuf, sizeof (bbuf), R_ANAL_OP_MASK_BASIC | R_ANAL_OP_MASK_VAL) < 1) {
646 return false;
647 }
648 switch (op.type & R_ANAL_OP_TYPE_MASK) {
649 case R_ANAL_OP_TYPE_JMP:
650 if (op.jump == UT64_MAX) {
651 recurse_addr = op.ptr;
652 } else {
653 recurse_addr = op.jump;
654 }
655 break;
656 case R_ANAL_OP_TYPE_UCALL:
657 case R_ANAL_OP_TYPE_RCALL:
658 case R_ANAL_OP_TYPE_ICALL:
659 case R_ANAL_OP_TYPE_IRCALL:
660 recurse_addr = op.ptr;
661 break;
662 case R_ANAL_OP_TYPE_CCALL:
663 case R_ANAL_OP_TYPE_CALL:
664 recurse_addr = op.jump;
665 break;
666 }
667 if (recurse_addr == UT64_MAX || recurse_addr == addr) {
668 return false;
669 }
670 return r_anal_noreturn_at (anal, recurse_addr);
671 }
672
r_anal_noreturn_at(RAnal * anal,ut64 addr)673 R_API bool r_anal_noreturn_at(RAnal *anal, ut64 addr) {
674 if (!addr || addr == UT64_MAX) {
675 return false;
676 }
677 if (r_anal_noreturn_at_addr (anal, addr)) {
678 return true;
679 }
680 /* XXX this is very slow */
681 RAnalFunction *f = r_anal_get_function_at (anal, addr);
682 if (f) {
683 if (r_anal_noreturn_at_name (anal, f->name)) {
684 return true;
685 }
686 }
687 RFlagItem *fi = anal->flag_get (anal->flb.f, addr);
688 if (fi) {
689 if (r_anal_noreturn_at_name (anal, fi->realname ? fi->realname : fi->name)) {
690 return true;
691 }
692 }
693 if (anal->recursive_noreturn) {
694 return noreturn_recurse (anal, addr);
695 }
696 return false;
697 }
698
r_anal_bind(RAnal * anal,RAnalBind * b)699 R_API void r_anal_bind(RAnal *anal, RAnalBind *b) {
700 if (b) {
701 b->anal = anal;
702 b->get_fcn_in = r_anal_get_fcn_in;
703 b->get_hint = r_anal_hint_get;
704 }
705 }
706
r_anal_preludes(RAnal * anal)707 R_API RList *r_anal_preludes(RAnal *anal) {
708 if (anal->cur && anal->cur->preludes ) {
709 return anal->cur->preludes (anal);
710 }
711 return NULL;
712 }
713
r_anal_is_prelude(RAnal * anal,const ut8 * data,int len)714 R_API bool r_anal_is_prelude(RAnal *anal, const ut8 *data, int len) {
715 RList *l = r_anal_preludes (anal);
716 if (l) {
717 RSearchKeyword *kw;
718 RListIter *iter;
719 r_list_foreach (l, iter, kw) {
720 int ks = kw->keyword_length;
721 if (len >= ks && !memcmp (data, kw->bin_keyword, ks)) {
722 r_list_free (l);
723 return true;
724 }
725 }
726 r_list_free (l);
727 }
728 return false;
729 }
730
r_anal_add_import(RAnal * anal,const char * imp)731 R_API void r_anal_add_import(RAnal *anal, const char *imp) {
732 RListIter *it;
733 const char *eimp;
734 r_list_foreach (anal->imports, it, eimp) {
735 if (!strcmp (eimp, imp)) {
736 return;
737 }
738 }
739 char *cimp = strdup (imp);
740 if (!cimp) {
741 return;
742 }
743 r_list_push (anal->imports, cimp);
744 }
745
r_anal_remove_import(RAnal * anal,const char * imp)746 R_API void r_anal_remove_import(RAnal *anal, const char *imp) {
747 RListIter *it;
748 const char *eimp;
749 r_list_foreach (anal->imports, it, eimp) {
750 if (!strcmp (eimp, imp)) {
751 r_list_delete (anal->imports, it);
752 return;
753 }
754 }
755 }
756
r_anal_purge_imports(RAnal * anal)757 R_API void r_anal_purge_imports(RAnal *anal) {
758 r_list_purge (anal->imports);
759 }
760