- Add LICENSES directory - Download additional licenses used - Add .reuse directory - Add doc about SPDX/reuse Co-authored-by: Florian Märkl <info@florianmaerkl.de>
108 lines
3.3 KiB
C
108 lines
3.3 KiB
C
// SPDX-License-Identifier: LGPL-3.0-only
|
|
#include <rz_analysis.h>
|
|
#include <rz_util.h>
|
|
#include <rz_lib.h>
|
|
|
|
static void interrupt_free(HtUPKv *kv) {
|
|
RzAnalysisEsilInterrupt *i = (RzAnalysisEsilInterrupt *)kv->value;
|
|
rz_analysis_esil_interrupt_free(i->esil, i);
|
|
}
|
|
|
|
RZ_API void rz_analysis_esil_interrupts_init(RzAnalysisEsil *esil) {
|
|
rz_return_if_fail(esil);
|
|
esil->interrupts = ht_up_new(NULL, interrupt_free, NULL);
|
|
}
|
|
|
|
RZ_API RzAnalysisEsilInterrupt *rz_analysis_esil_interrupt_new(RzAnalysisEsil *esil, ut32 src_id, RzAnalysisEsilInterruptHandler *ih) {
|
|
rz_return_val_if_fail(esil && ih && ih->cb, NULL);
|
|
RzAnalysisEsilInterrupt *intr = RZ_NEW0(RzAnalysisEsilInterrupt);
|
|
if (!intr) {
|
|
return NULL;
|
|
}
|
|
intr->esil = esil;
|
|
intr->handler = ih;
|
|
if (ih->init && ih->fini) {
|
|
intr->user = ih->init(esil);
|
|
}
|
|
intr->src_id = src_id;
|
|
rz_analysis_esil_claim_source(esil, src_id);
|
|
return intr;
|
|
}
|
|
|
|
RZ_API void rz_analysis_esil_interrupt_free(RzAnalysisEsil *esil, RzAnalysisEsilInterrupt *intr) {
|
|
rz_return_if_fail(esil);
|
|
if (intr) {
|
|
if (intr->user) {
|
|
intr->handler->fini(intr->user); //fini must exist when user is !NULL
|
|
}
|
|
rz_analysis_esil_release_source(esil, intr->src_id);
|
|
free(intr);
|
|
}
|
|
}
|
|
|
|
RZ_API bool rz_analysis_esil_set_interrupt(RzAnalysisEsil *esil, RzAnalysisEsilInterrupt *intr) {
|
|
rz_return_val_if_fail(esil && esil->interrupts && intr && intr->handler && intr->handler->cb, false);
|
|
return ht_up_update(esil->interrupts, intr->handler->num, intr);
|
|
}
|
|
|
|
RZ_API int rz_analysis_esil_fire_interrupt(RzAnalysisEsil *esil, ut32 intr_num) {
|
|
rz_return_val_if_fail(esil, false);
|
|
|
|
if (esil->cmd && esil->cmd(esil, esil->cmd_intr, intr_num, 0)) { //compatibility
|
|
return true;
|
|
}
|
|
|
|
if (!esil->interrupts) {
|
|
eprintf("no interrupts initialized\n");
|
|
return false;
|
|
}
|
|
RzAnalysisEsilInterrupt *intr = ht_up_find(esil->interrupts, intr_num, NULL);
|
|
#if 0
|
|
// we don't want this warning
|
|
if (!intr) {
|
|
eprintf ("Warning no interrupt handler registered for 0x%x\n", intr_num);
|
|
}
|
|
#endif
|
|
return (intr && intr->handler && intr->handler->cb) ? intr->handler->cb(esil, intr_num, intr->user) : false;
|
|
}
|
|
|
|
RZ_API bool rz_analysis_esil_load_interrupts(RzAnalysisEsil *esil, RzAnalysisEsilInterruptHandler *handlers[], ut32 src_id) {
|
|
RzAnalysisEsilInterrupt *intr;
|
|
ut32 i = 0;
|
|
|
|
rz_return_val_if_fail(esil && esil->interrupts && handlers, false);
|
|
|
|
while (handlers[i]) {
|
|
intr = rz_analysis_esil_interrupt_new(esil, src_id, handlers[i]);
|
|
if (!intr) {
|
|
return false;
|
|
}
|
|
if (!rz_analysis_esil_set_interrupt(esil, intr)) {
|
|
free(intr);
|
|
}
|
|
i++;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
RZ_API bool rz_analysis_esil_load_interrupts_from_lib(RzAnalysisEsil *esil, const char *path) {
|
|
rz_return_val_if_fail(esil, false);
|
|
ut32 src_id = rz_analysis_esil_load_source(esil, path);
|
|
if (!src_id) { // why id=0 is invalid?
|
|
return false;
|
|
}
|
|
RzAnalysisEsilInterruptHandler **handlers = (RzAnalysisEsilInterruptHandler **)
|
|
rz_lib_dl_sym(rz_analysis_esil_get_source(esil, src_id), "interrupts");
|
|
if (!handlers) {
|
|
rz_analysis_esil_release_source(esil, src_id); //unload
|
|
return false;
|
|
}
|
|
return rz_analysis_esil_load_interrupts(esil, handlers, src_id);
|
|
}
|
|
|
|
RZ_API void rz_analysis_esil_interrupts_fini(RzAnalysisEsil *esil) {
|
|
rz_return_if_fail(esil && esil->interrupts);
|
|
ht_up_free(esil->interrupts);
|
|
esil->interrupts = NULL;
|
|
}
|