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