1 #include <r_anal.h>
2 #include <r_util.h>
3 #include <sdb.h>
4 
_set_interrupt(RAnalEsil * esil,RAnalEsilHandler * intr,ut32 intr_num)5 static bool _set_interrupt(RAnalEsil *esil, RAnalEsilHandler *intr, ut32 intr_num) {
6 	return intr_num ? dict_set (esil->interrupts, intr_num, intr_num, intr) : (esil->intr0 = intr, true);
7 }
8 
_set_syscall(RAnalEsil * esil,RAnalEsilHandler * sysc,ut32 sysc_num)9 static bool _set_syscall(RAnalEsil *esil, RAnalEsilHandler *sysc, ut32 sysc_num) {
10 	return sysc_num ? dict_set (esil->syscalls, sysc_num, sysc_num, sysc) : (esil->sysc0 = sysc, true);
11 }
12 
_get_interrupt(RAnalEsil * esil,ut32 intr_num)13 static RAnalEsilHandler *_get_interrupt(RAnalEsil *esil, ut32 intr_num) {
14 	return intr_num ? (RAnalEsilHandler *)dict_getu (esil->interrupts, intr_num) : esil->intr0;
15 }
16 
_get_syscall(RAnalEsil * esil,ut32 sysc_num)17 static RAnalEsilHandler *_get_syscall(RAnalEsil *esil, ut32 sysc_num) {
18 	return sysc_num ? (RAnalEsilHandler *)dict_getu (esil->syscalls, sysc_num) : esil->sysc0;
19 }
20 
r_anal_esil_handlers_init(RAnalEsil * esil)21 R_API void r_anal_esil_handlers_init(RAnalEsil *esil) {
22 	r_return_if_fail (esil);
23 	esil->interrupts = dict_new (sizeof (ut32), free);
24 	if (!esil->interrupts) {
25 		return;
26 	}
27 	esil->syscalls = dict_new (sizeof (ut32), free);
28 	if (!esil->syscalls) {
29 		dict_free (esil->interrupts);
30 		return;
31 	}
32 	esil->intr0 = NULL;
33 	esil->sysc0 = NULL;
34 }
35 
36 // does this need to be an API function?
r_anal_esil_handler_new(RAnalEsilHandlerCB cb,void * user)37 R_API RAnalEsilHandler *r_anal_esil_handler_new(RAnalEsilHandlerCB cb, void *user) {
38 	r_return_val_if_fail (cb, NULL);
39 	RAnalEsilHandler *h = R_NEW0 (RAnalEsilHandler);
40 	if (!h) {
41 		return NULL;
42 	}
43 	h->cb = cb;
44 	h->user = user;
45 	return h;
46 }
47 
r_anal_esil_set_interrupt(RAnalEsil * esil,ut32 intr_num,RAnalEsilHandlerCB cb,void * user)48 R_API bool r_anal_esil_set_interrupt(RAnalEsil *esil, ut32 intr_num, RAnalEsilHandlerCB cb, void *user) {
49 	r_return_val_if_fail (esil && esil->interrupts && cb, false);
50 	RAnalEsilHandler *intr = r_anal_esil_handler_new (cb, user);
51 	if (!intr) {
52 		return false;
53 	}
54 	// free potentially existing handler
55 	free (_get_interrupt (esil, intr_num));
56 	// set the new interrupt
57 	return _set_interrupt (esil, intr, intr_num);
58 }
59 
r_anal_esil_set_syscall(RAnalEsil * esil,ut32 sysc_num,RAnalEsilHandlerCB cb,void * user)60 R_API bool r_anal_esil_set_syscall(RAnalEsil *esil, ut32 sysc_num, RAnalEsilHandlerCB cb, void *user) {
61 	r_return_val_if_fail (esil && esil->syscalls && cb, false);
62 	RAnalEsilHandler *sysc = r_anal_esil_handler_new (cb, user);
63 	if (!sysc) {
64 		return false;
65 	}
66 	// free potentially existing handler
67 	free (_get_syscall (esil, sysc_num));
68 	// set the new interrupt
69 	return _set_syscall (esil, sysc, sysc_num);
70 }
71 
r_anal_esil_fire_interrupt(RAnalEsil * esil,ut32 intr_num)72 R_API int r_anal_esil_fire_interrupt(RAnalEsil *esil, ut32 intr_num) {
73 	r_return_val_if_fail (esil, false);
74 
75 	if (esil->cmd && esil->cmd (esil, esil->cmd_intr, intr_num, 0)) { //compatibility
76 		return true;
77 	}
78 
79 	if (!esil->interrupts) {
80 		eprintf ("no interrupts initialized\n");
81 		return false;
82 	}
83 	RAnalEsilHandler *intr = _get_interrupt (esil, intr_num);
84 	return (intr && intr->cb) ? intr->cb (esil, intr_num, intr->user) : false;
85 }
86 
r_anal_esil_do_syscall(RAnalEsil * esil,ut32 sysc_num)87 R_API int r_anal_esil_do_syscall(RAnalEsil *esil, ut32 sysc_num) {
88 	r_return_val_if_fail (esil, false);
89 
90 	if (!esil->syscalls) {
91 		eprintf ("no syscalls initialized\n");
92 		return false;
93 	}
94 	RAnalEsilHandler *sysc = _get_syscall (esil, sysc_num);
95 	return (sysc && sysc->cb) ? sysc->cb (esil, sysc_num, sysc->user) : false;
96 }
97 
r_anal_esil_handlers_fini(RAnalEsil * esil)98 R_API void r_anal_esil_handlers_fini(RAnalEsil *esil) {
99 	if (esil) {
100 		if (esil->interrupts) {
101 			R_FREE (esil->intr0);
102 			dict_free (esil->interrupts);
103 			esil->interrupts = NULL;
104 		}
105 		if (esil->syscalls) {
106 			R_FREE (esil->sysc0);
107 			dict_free (esil->syscalls);
108 			esil->syscalls = NULL;
109 		}
110 	}
111 }
112