Add user * to REvent Hooking and add all_callbacks for R_EVENT_ALL ##core

This commit is contained in:
Florian Märkl 2019-02-04 23:37:06 +01:00 committed by radare
parent c1d0e59d4d
commit 98308a2617
6 changed files with 119 additions and 58 deletions

View File

@ -26,35 +26,35 @@ R_API void r_anal_unset_limits(RAnal *anal) {
}
static void meta_unset_for(REvent *ev, int type, void *user, void *data) {
RSpaces *s = (RSpaces *)user;
RSpaces *s = (RSpaces *)ev->user;
RAnal *anal = container_of (s, RAnal, meta_spaces);
RSpaceEvent *se = (RSpaceEvent *)data;
r_meta_space_unset_for (anal, se->data.unset.space);
}
static void meta_count_for(REvent *ev, int type, void *user, void *data) {
RSpaces *s = (RSpaces *)user;
RSpaces *s = (RSpaces *)ev->user;
RAnal *anal = container_of (s, RAnal, meta_spaces);
RSpaceEvent *se = (RSpaceEvent *)data;
se->res = r_meta_space_count_for (anal, se->data.count.space);
}
static void zign_unset_for(REvent *ev, int type, void *user, void *data) {
RSpaces *s = (RSpaces *)user;
RSpaces *s = (RSpaces *)ev->user;
RAnal *anal = container_of (s, RAnal, zign_spaces);
RSpaceEvent *se = (RSpaceEvent *)data;
r_sign_space_unset_for (anal, se->data.unset.space);
}
static void zign_count_for(REvent *ev, int type, void *user, void *data) {
RSpaces *s = (RSpaces *)user;
RSpaces *s = (RSpaces *)ev->user;
RAnal *anal = container_of (s, RAnal, zign_spaces);
RSpaceEvent *se = (RSpaceEvent *)data;
se->res = r_sign_space_count_for (anal, se->data.count.space);
}
static void zign_rename_for(REvent *ev, int type, void *user, void *data) {
RSpaces *s = (RSpaces *)user;
RSpaces *s = (RSpaces *)ev->user;
RAnal *anal = container_of (s, RAnal, zign_spaces);
RSpaceEvent *se = (RSpaceEvent *)data;
r_sign_space_rename_for (anal, se->data.rename.space,
@ -167,13 +167,13 @@ R_API RAnal *r_anal_new() {
anal->opt.depth = 32;
anal->opt.noncode = false; // do not analyze data by default
r_spaces_init (&anal->meta_spaces, "CS");
r_event_hook (anal->meta_spaces.event, R_SPACE_EVENT_UNSET, meta_unset_for);
r_event_hook (anal->meta_spaces.event, R_SPACE_EVENT_COUNT, meta_count_for);
r_event_hook (anal->meta_spaces.event, R_SPACE_EVENT_UNSET, meta_unset_for, NULL);
r_event_hook (anal->meta_spaces.event, R_SPACE_EVENT_COUNT, meta_count_for, NULL);
r_spaces_init (&anal->zign_spaces, "zs");
r_event_hook (anal->zign_spaces.event, R_SPACE_EVENT_UNSET, zign_unset_for);
r_event_hook (anal->zign_spaces.event, R_SPACE_EVENT_COUNT, zign_count_for);
r_event_hook (anal->zign_spaces.event, R_SPACE_EVENT_RENAME, zign_rename_for);
r_event_hook (anal->zign_spaces.event, R_SPACE_EVENT_UNSET, zign_unset_for, NULL);
r_event_hook (anal->zign_spaces.event, R_SPACE_EVENT_COUNT, zign_count_for, NULL);
r_event_hook (anal->zign_spaces.event, R_SPACE_EVENT_RENAME, zign_rename_for, NULL);
anal->sdb_fcns = sdb_ns (anal->sdb, "fcns", 1);
anal->sdb_meta = sdb_ns (anal->sdb, "meta", 1);
anal->sdb_hints = sdb_ns (anal->sdb, "hints", 1);

View File

@ -2296,7 +2296,7 @@ R_API bool r_core_init(RCore *core) {
}
r_core_setenv (core);
core->ev = r_event_new (core);
r_event_hook (core->ev, R_EVENT_ALL, cb_event_handler);
r_event_hook (core->ev, R_EVENT_ALL, cb_event_handler, NULL);
core->lock = r_th_lock_new (true);
core->max_cmd_depth = R_CORE_CMD_DEPTH + 1;
core->cmd_depth = core->max_cmd_depth;

View File

@ -202,14 +202,14 @@ static bool unset_flags_space(RFlagItem *fi, void *user) {
}
static void count_flags_in_space(REvent *ev, int type, void *user, void *data) {
RSpaces *sp = (RSpaces *)user;
RSpaces *sp = (RSpaces *)ev->user;
RFlag *f = container_of (sp, RFlag, spaces);
RSpaceEvent *spe = (RSpaceEvent *)data;
r_flag_foreach_space (f, spe->data.count.space, count_flags, &spe->res);
}
static void unset_flagspace(REvent *ev, int type, void *user, void *data) {
RSpaces *sp = (RSpaces *)user;
RSpaces *sp = (RSpaces *)ev->user;
RFlag *f = container_of (sp, RFlag, spaces);
const RSpaceEvent *spe = (const RSpaceEvent *)data;
r_flag_foreach_space (f, spe->data.unset.space, unset_flags_space, NULL);
@ -217,8 +217,8 @@ static void unset_flagspace(REvent *ev, int type, void *user, void *data) {
static void new_spaces(RFlag *f) {
r_spaces_init (&f->spaces, "fs");
r_event_hook (f->spaces.event, R_SPACE_EVENT_COUNT, count_flags_in_space);
r_event_hook (f->spaces.event, R_SPACE_EVENT_UNSET, unset_flagspace);
r_event_hook (f->spaces.event, R_SPACE_EVENT_COUNT, count_flags_in_space, NULL);
r_event_hook (f->spaces.event, R_SPACE_EVENT_UNSET, unset_flagspace, NULL);
}
R_API RFlag *r_flag_new() {

View File

@ -8,13 +8,23 @@ extern "C" {
#endif
#include <sdb/ht_up.h>
#include <r_vector.h>
typedef struct r_event_t {
void *user;
bool incall;
HtUP *callbacks;
RVector *all_callbacks;
int next_handle;
} REvent;
typedef struct r_event_callback_handle_t {
int handle;
int type;
} REventCallbackHandle;
typedef void (*REventCallback)(REvent *ev, int type, void *user, void *data);
typedef enum {
R_EVENT_ALL = 0,
R_EVENT_META_SET,
@ -29,12 +39,11 @@ typedef struct r_event_meta_t {
const char *string;
} REventMeta;
typedef void (*REventCallback)(REvent *ev, int type, void *user, void *data);
R_API REvent *r_event_new(void *user);
R_API void r_event_free(REvent *ev);
R_API void r_event_hook(REvent *ev, int type, REventCallback cb);
R_API void r_event_unhook(REvent *ev, int type, REventCallback cb);
R_API REventCallbackHandle r_event_hook(REvent *ev, int type, REventCallback cb, void *user);
R_API void r_event_unhook(REvent *ev, REventCallbackHandle handle);
R_API void r_event_send(REvent *ev, int type, void *data);
#ifdef __cplusplus

View File

@ -125,6 +125,10 @@ R_API void *r_vector_shrink(RVector *vec);
if ((vec) && (vec)->a) \
for (it = (void *)(vec)->a; (char *)it != (char *)(vec)->a + ((vec)->len * (vec)->elem_size); it = (void *)((char *)it + (vec)->elem_size))
#define r_vector_enumerate(vec, it, i) \
if ((vec) && (vec)->a) \
for (it = (void *)(vec)->a, i = 0; i < (vec)->len; it = (void *)((char *)it + (vec)->elem_size), i++)
// RPVector

View File

@ -3,81 +3,129 @@
#include <r_util.h>
#include <r_vector.h>
typedef struct r_event_callback_hook_t {
REventCallback cb;
void *user;
int handle;
} REventCallbackHook;
static RVector *new_cbhook_vector(void) {
return r_vector_new (sizeof (REventCallbackHook), NULL, NULL);
}
static void ht_callback_free(HtUPKv *kv) {
r_vector_free ((RVector *)kv->value);
}
R_API REvent *r_event_new(void *user) {
REvent *ev = R_NEW0 (REvent);
if (!ev) {
return NULL;
}
ev->callbacks = ht_up_new0 ();
// skip R_EVENT_ALL and R_EVENT_MAX, so that they don't have a mapping
// and if used in hook/unhook/send APIs will raise a warning
ut64 i;
for (i = 1; i < R_EVENT_MAX; ++i) {
ht_up_insert (ev->callbacks, (ut64)i, r_pvector_new (NULL));
}
ev->user = user;
ev->next_handle = 0;
ev->callbacks = ht_up_new (NULL, ht_callback_free, NULL);
if (!ev->callbacks) {
goto err;
}
ev->all_callbacks = new_cbhook_vector ();
if (!ev->all_callbacks) {
goto err;
}
return ev;
err:
r_event_free (ev);
return NULL;
}
R_API void r_event_free(REvent *ev) {
if (!ev) {
return;
}
ut64 i;
for (i = 1; i < R_EVENT_MAX; ++i) {
RVector *entry = ht_up_find (ev->callbacks, i, NULL);
r_vector_free (entry);
}
ht_up_free (ev->callbacks);
r_vector_free (ev->all_callbacks);
free (ev);
}
static bool add_hook(void *cb, const ut64 k, const void *v) {
RPVector *cbs = (RPVector *)v;
r_return_val_if_fail (cbs, false);
r_pvector_push (cbs, cb);
return true;
}
R_API void r_event_hook(REvent *ev, int type, REventCallback cb) {
r_return_if_fail (ev);
if (type == R_EVENT_ALL) {
ht_up_foreach (ev->callbacks, add_hook, cb);
} else {
RPVector *cbs = ht_up_find (ev->callbacks, type, NULL);
add_hook (cb, 0, cbs);
static RVector *get_cbs(REvent *ev, int type) {
RVector *cbs = ht_up_find (ev->callbacks, (ut64)type, NULL);
if (!cbs) {
cbs = new_cbhook_vector ();
if (cbs) {
ht_up_insert (ev->callbacks, (ut64)type, cbs);
}
}
return cbs;
}
static bool del_hook(void *cb, const ut64 k, const void *v) {
RPVector *cbs = (RPVector *)v;
R_API REventCallbackHandle r_event_hook(REvent *ev, int type, REventCallback cb, void *user) {
REventCallbackHandle handle = { 0 };
REventCallbackHook hook;
r_return_val_if_fail (ev, handle);
hook.cb = cb;
hook.user = user;
hook.handle = ev->next_handle++;
if (type == R_EVENT_ALL) {
r_vector_push (ev->all_callbacks, &hook);
} else {
RVector *cbs = get_cbs (ev, type);
if (!cbs) {
return handle;
}
r_vector_push (cbs, &hook);
}
handle.handle = hook.handle;
handle.type = type;
return handle;
}
static bool del_hook(void *user, const ut64 k, const void *v) {
int handle = *(int *)user;
RVector *cbs = (RVector *)v;
REventCallbackHook *hook;
size_t i;
r_return_val_if_fail (cbs, false);
r_pvector_remove_data (cbs, cb);
r_vector_enumerate (cbs, hook, i) {
if (hook->handle == handle) {
r_vector_remove_at (cbs, i, NULL);
break;
}
}
return true;
}
R_API void r_event_unhook(REvent *ev, int type, REventCallback cb) {
R_API void r_event_unhook(REvent *ev, REventCallbackHandle handle) {
r_return_if_fail (ev);
if (type == R_EVENT_ALL) {
ht_up_foreach (ev->callbacks, del_hook, cb);
if (handle.type == R_EVENT_ALL) {
// try to delete it both from each list of callbacks and from
// the "all_callbacks" vector
ht_up_foreach (ev->callbacks, del_hook, &handle.handle);
del_hook (&handle.handle, 0, ev->all_callbacks);
} else {
RPVector *cbs = ht_up_find (ev->callbacks, type, NULL);
del_hook (cb, 0, cbs);
RVector *cbs = ht_up_find (ev->callbacks, (ut64)handle.type, NULL);
r_return_if_fail (cbs);
del_hook (&handle.handle, 0, cbs);
}
}
R_API void r_event_send(REvent *ev, int type, void *data) {
REventCallbackHook *hook;
r_return_if_fail (ev && !ev->incall);
void **it;
RPVector *cbs = ht_up_find (ev->callbacks, type, NULL);
// send to both the per-type callbacks and to the all_callbacks
ev->incall = true;
r_vector_foreach (ev->all_callbacks, hook) {
hook->cb (ev, type, hook->user, data);
}
ev->incall = false;
RVector *cbs = ht_up_find (ev->callbacks, (ut64)type, NULL);
r_return_if_fail (cbs);
ev->incall = true;
r_pvector_foreach (cbs, it) {
REventCallback cb = *it;
cb (ev, type, ev->user, data);
r_vector_foreach (cbs, hook) {
hook->cb (ev, type, hook->user, data);
}
ev->incall = false;
}