From 57c9ab3da6650e61955b31314d657746e0c12e86 Mon Sep 17 00:00:00 2001 From: condret Date: Tue, 30 Oct 2018 13:05:18 +0100 Subject: [PATCH] Fix zero interrupt issue ##esil --- libr/anal/esil_interrupt.c | 93 ++++++++++++++++++++------------------ libr/include/r_anal.h | 2 + 2 files changed, 50 insertions(+), 45 deletions(-) diff --git a/libr/anal/esil_interrupt.c b/libr/anal/esil_interrupt.c index 0abac7851d..9ea500d209 100644 --- a/libr/anal/esil_interrupt.c +++ b/libr/anal/esil_interrupt.c @@ -11,28 +11,41 @@ static void _interrupt_free_cb(void *user) { free (intr); } -R_API void r_anal_esil_interrupts_init(RAnalEsil *esil) { - if (!esil) { - return; +static bool _set_interrupt(RAnalEsil *esil, RAnalEsilInterrupt *intr) { + return intr->handler->num ? + dict_set (esil->interrupts, intr->handler->num, intr->handler->num, intr) : + (esil->intr0 = intr, true); +} + +static RAnalEsilInterrupt *_get_interrupt(RAnalEsil *esil, ut32 intr_num) { + return intr_num ? + (RAnalEsilInterrupt *)dict_getu(esil->interrupts, intr_num) : + esil->intr0; +} + +static void _del_interrupt(RAnalEsil *esil, ut32 intr_num) { + if (intr_num) { + dict_del (esil->interrupts, intr_num); + } else { + esil->intr0 = NULL; } - esil->interrupts = dict_new (sizeof(ut32), NULL); +} + +R_API void r_anal_esil_interrupts_init(RAnalEsil *esil) { + r_return_if_fail (esil); + esil->interrupts = dict_new (sizeof (ut32), NULL); + esil->intr0 = NULL; // is this needed? } R_API RAnalEsilInterrupt *r_anal_esil_interrupt_new(RAnalEsil *esil, ut32 src_id, RAnalEsilInterruptHandler *ih) { - RAnalEsilInterrupt *intr; - - if (!esil || !ih || !ih->cb) { - return NULL; - } - - intr = R_NEW0(RAnalEsilInterrupt); + r_return_val_if_fail (esil && ih && ih->cb, NULL); + RAnalEsilInterrupt *intr = R_NEW0 (RAnalEsilInterrupt); if (!intr) { return NULL; } - intr->handler = ih; if (ih->init && ih->fini) { - intr->user = ih->init(esil); + intr->user = ih->init (esil); } intr->src_id = src_id; r_anal_esil_claim_source (esil, src_id); @@ -41,38 +54,30 @@ R_API RAnalEsilInterrupt *r_anal_esil_interrupt_new(RAnalEsil *esil, ut32 src_id R_API void r_anal_esil_interrupt_free(RAnalEsil *esil, RAnalEsilInterrupt *intr) { if (intr && esil) { - dict_del (esil->interrupts, intr->handler->num); + _del_interrupt (esil, intr->handler->num); } if (intr) { if (intr->user) { - intr->handler->fini(intr->user); //fini must exist when user is !NULL + intr->handler->fini (intr->user); //fini must exist when user is !NULL } r_anal_esil_release_source (esil, intr->src_id); } - free(intr); + free (intr); } R_API bool r_anal_esil_set_interrupt(RAnalEsil *esil, RAnalEsilInterrupt *intr) { - RAnalEsilInterrupt *o_intr; - - if (!esil || !esil->interrupts || !intr || !intr->handler || !intr->handler->cb) { - return false; - } - -// check if interrupt is already set - o_intr = (RAnalEsilInterrupt *)dict_getu(esil->interrupts, intr->handler->num); + r_return_val_if_fail (esil && esil->interrupts && intr && intr->handler && intr->handler->cb, false); + // check if interrupt is already set + RAnalEsilInterrupt *o_intr = _get_interrupt(esil, intr->handler->num); if (o_intr) { - r_anal_esil_interrupt_free(esil, o_intr); + r_anal_esil_interrupt_free (esil, o_intr); } - -//set the new interrupt - return dict_set(esil->interrupts, intr->handler->num, intr->handler->num, intr); + //set the new interrupt + return _set_interrupt(esil, intr); } R_API int r_anal_esil_fire_interrupt(RAnalEsil *esil, ut32 intr_num) { - if (!esil) { - return false; - } + r_return_val_if_fail (esil, false); if (esil->cmd && esil->cmd (esil, esil->cmd_intr, intr_num, 0)) { //compatibility return true; @@ -82,7 +87,7 @@ R_API int r_anal_esil_fire_interrupt(RAnalEsil *esil, ut32 intr_num) { eprintf ("no interrupts initialized\n"); return false; } - RAnalEsilInterrupt *intr = (RAnalEsilInterrupt *)dict_getu(esil->interrupts, intr_num); + RAnalEsilInterrupt *intr = _get_interrupt (esil, intr_num); if (!intr) { eprintf ("no handler registered for 0x%x\n", intr_num); } @@ -94,22 +99,19 @@ R_API bool r_anal_esil_load_interrupts (RAnalEsil *esil, RAnalEsilInterruptHandl RAnalEsilInterrupt *intr; ut32 i = 0; - if (!esil || !esil->interrupts || !handlers) { - return false; - } + r_return_val_if_fail (esil && esil->interrupts && handlers, false); while (handlers[i]) { - intr = (RAnalEsilInterrupt *)dict_getu(esil->interrupts, handlers[i]->num); + intr = _get_interrupt (esil, handlers[i]->num); if (intr) { //first free, then load the new handler or stuff might break in the handlers r_anal_esil_interrupt_free (esil, intr); } intr = r_anal_esil_interrupt_new (esil, src_id, handlers[i]); - if (intr) { - r_anal_esil_set_interrupt (esil, intr); - } else { + if (!intr) { return false; } + r_anal_esil_set_interrupt (esil, intr); i++; } @@ -117,16 +119,15 @@ R_API bool r_anal_esil_load_interrupts (RAnalEsil *esil, RAnalEsilInterruptHandl } R_API bool r_anal_esil_load_interrupts_from_lib(RAnalEsil *esil, const char *path) { - RAnalEsilInterruptHandler **handlers; + r_return_val_if_fail (esil, false); ut32 src_id = r_anal_esil_load_source (esil, path); - - if (!src_id) { + if (!src_id) { // why id=0 is invalid? return false; } - - handlers = (RAnalEsilInterruptHandler **)r_lib_dl_sym (r_anal_esil_get_source (esil, src_id), "interrupts"); + RAnalEsilInterruptHandler **handlers = (RAnalEsilInterruptHandler **)\ + r_lib_dl_sym (r_anal_esil_get_source (esil, src_id), "interrupts"); if (!handlers) { - r_anal_esil_release_source(esil, src_id); //unload + r_anal_esil_release_source (esil, src_id); //unload return false; } return r_anal_esil_load_interrupts (esil, handlers, src_id); @@ -134,6 +135,8 @@ R_API bool r_anal_esil_load_interrupts_from_lib(RAnalEsil *esil, const char *pat R_API void r_anal_esil_interrupts_fini(RAnalEsil *esil) { if (esil && esil->interrupts) { + _interrupt_free_cb (esil->intr0); + esil->intr0 = NULL; esil->interrupts->f = _interrupt_free_cb; dict_free (esil->interrupts); esil->interrupts = NULL; diff --git a/libr/include/r_anal.h b/libr/include/r_anal.h index 9f69789d95..2af9c38924 100644 --- a/libr/include/r_anal.h +++ b/libr/include/r_anal.h @@ -1114,6 +1114,8 @@ typedef struct r_anal_esil_t { Sdb *ops; RIDStorage *sources; SdbMini *interrupts; + //this is a disgusting workaround, because we have no ht-like storage without magic keys, that you cannot use, with int-keys + RAnalEsilInterrupt *intr0; /* deep esil parsing fills this */ Sdb *stats; Sdb *db_trace;