mirror of
https://github.com/radareorg/radare2.git
synced 2025-01-27 08:12:44 +00:00
Rewrite RSpaces to use RBTree and remove use of indices everywhere (#12904)
* Rewrite RSpaces to use RBTree and remove use of indixes everywhere * Use RSpace in r_meta_space_unset_for * Use r_str_ndup instead of strndup because windows does not support it * Add some comments
This commit is contained in:
parent
a8f5b045c4
commit
54d5cc3ae0
@ -25,34 +25,40 @@ R_API void r_anal_unset_limits(RAnal *anal) {
|
||||
R_FREE (anal->limit);
|
||||
}
|
||||
|
||||
static void meta_unset_for(void *user, int idx) {
|
||||
RSpaces *s = (RSpaces*)user;
|
||||
RAnal *anal = (RAnal*)s->user;
|
||||
r_meta_space_unset_for (anal, idx);
|
||||
static void meta_unset_for(REvent *ev, int type, void *user, void *data) {
|
||||
RSpaces *s = (RSpaces *)user;
|
||||
RAnal *anal = container_of (s, RAnal, meta_spaces);
|
||||
RSpaceEvent *se = (RSpaceEvent *)data;
|
||||
r_meta_space_unset_for (anal, se->data.unset.space);
|
||||
}
|
||||
|
||||
static int meta_count_for(void *user, int idx) {
|
||||
RSpaces *s = (RSpaces*)user;
|
||||
RAnal *anal = (RAnal*)s->user;
|
||||
return r_meta_space_count_for (anal, idx);
|
||||
static void meta_count_for(REvent *ev, int type, void *user, void *data) {
|
||||
RSpaces *s = (RSpaces *)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(void *user, int idx) {
|
||||
RSpaces *s = (RSpaces*)user;
|
||||
RAnal *anal = (RAnal*)s->user;
|
||||
r_sign_space_unset_for (anal, idx);
|
||||
static void zign_unset_for(REvent *ev, int type, void *user, void *data) {
|
||||
RSpaces *s = (RSpaces *)user;
|
||||
RAnal *anal = container_of (s, RAnal, zign_spaces);
|
||||
RSpaceEvent *se = (RSpaceEvent *)data;
|
||||
r_sign_space_unset_for (anal, se->data.unset.space);
|
||||
}
|
||||
|
||||
static int zign_count_for(void *user, int idx) {
|
||||
RSpaces *s = (RSpaces*)user;
|
||||
RAnal *anal = (RAnal*)s->user;
|
||||
return r_sign_space_count_for (anal, idx);
|
||||
static void zign_count_for(REvent *ev, int type, void *user, void *data) {
|
||||
RSpaces *s = (RSpaces *)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(void *user, int idx, const char *oname, const char *nname) {
|
||||
RSpaces *s = (RSpaces*)user;
|
||||
RAnal *anal = (RAnal*)s->user;
|
||||
r_sign_space_rename_for (anal, idx, oname, nname);
|
||||
static void zign_rename_for(REvent *ev, int type, void *user, void *data) {
|
||||
RSpaces *s = (RSpaces *)user;
|
||||
RAnal *anal = container_of (s, RAnal, zign_spaces);
|
||||
RSpaceEvent *se = (RSpaceEvent *)data;
|
||||
r_sign_space_rename_for (anal, se->data.rename.space,
|
||||
se->data.rename.oldname, se->data.rename.newname);
|
||||
}
|
||||
|
||||
//not used
|
||||
@ -160,8 +166,14 @@ R_API RAnal *r_anal_new() {
|
||||
anal->cpp_abi = R_ANAL_CPP_ABI_ITANIUM;
|
||||
anal->opt.depth = 32;
|
||||
anal->opt.noncode = false; // do not analyze data by default
|
||||
r_space_new (&anal->meta_spaces, "CS", meta_unset_for, meta_count_for, NULL, anal);
|
||||
r_space_new (&anal->zign_spaces, "zs", zign_unset_for, zign_count_for, zign_rename_for, anal);
|
||||
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_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);
|
||||
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);
|
||||
@ -217,8 +229,8 @@ R_API RAnal *r_anal_free(RAnal *a) {
|
||||
r_list_free (a->plugins);
|
||||
a->fcns->free = r_anal_fcn_free;
|
||||
r_list_free (a->fcns);
|
||||
r_space_free (&a->meta_spaces);
|
||||
r_space_free (&a->zign_spaces);
|
||||
r_spaces_fini (&a->meta_spaces);
|
||||
r_spaces_fini (&a->zign_spaces);
|
||||
r_anal_pin_fini (a);
|
||||
r_list_free (a->refs);
|
||||
r_syscall_free (a->syscall);
|
||||
|
@ -111,7 +111,7 @@ R_API int r_meta_set_string(RAnal *a, int type, ut64 addr, const char *s) {
|
||||
char key[100], val[2048], *e_str;
|
||||
int ret;
|
||||
ut64 size;
|
||||
int space_idx = a->meta_spaces.space_idx;
|
||||
const char *space = r_spaces_current_name (&a->meta_spaces);
|
||||
meta_type_add (a, type, addr);
|
||||
|
||||
snprintf (key, sizeof (key)-1, "meta.%c.0x%"PFMT64x, type, addr);
|
||||
@ -129,7 +129,7 @@ R_API int r_meta_set_string(RAnal *a, int type, ut64 addr, const char *s) {
|
||||
free (msg);
|
||||
}
|
||||
e_str = sdb_encode ((const void*)s, -1);
|
||||
snprintf (val, sizeof (val)-1, "%d,%d,%s", (int)size, space_idx, e_str);
|
||||
snprintf (val, sizeof (val)-1, "%d,%s,%s", (int)size, space, e_str);
|
||||
sdb_set (DB, key, val, 0);
|
||||
free ((void*)e_str);
|
||||
|
||||
@ -148,7 +148,7 @@ R_API int r_meta_set_var_comment(RAnal *a, int type, ut64 idx, ut64 addr, const
|
||||
char key[100], val[2048], *e_str;
|
||||
int ret;
|
||||
ut64 size;
|
||||
int space_idx = a->meta_spaces.space_idx;
|
||||
const char *space = r_spaces_current_name (&a->meta_spaces);
|
||||
meta_type_add (a, type, addr);
|
||||
|
||||
snprintf (key, sizeof (key)-1, "meta.%c.0x%"PFMT64x".0x%"PFMT64x, type, addr, idx);
|
||||
@ -161,7 +161,7 @@ R_API int r_meta_set_var_comment(RAnal *a, int type, ut64 idx, ut64 addr, const
|
||||
ret = false;
|
||||
}
|
||||
e_str = sdb_encode ((const void*)s, -1);
|
||||
snprintf (val, sizeof (val)-1, "%d,%d,%s", (int)size, space_idx, e_str);
|
||||
snprintf (val, sizeof (val)-1, "%d,%s,%s", (int)size, space, e_str);
|
||||
sdb_set (DB, key, val, 0);
|
||||
free ((void*)e_str);
|
||||
return ret;
|
||||
@ -308,8 +308,13 @@ R_API int r_meta_cleanup(RAnal *a, ut64 from, ut64 to) {
|
||||
return r_meta_del (a, R_META_TYPE_ANY, from, (to-from));
|
||||
}
|
||||
|
||||
static void r_meta_item_fini(RAnalMetaItem *item) {
|
||||
free (item->str);
|
||||
}
|
||||
|
||||
R_API void r_meta_item_free(void *_item) {
|
||||
RAnalMetaItem *item = _item;
|
||||
r_meta_item_fini (item);
|
||||
free (item);
|
||||
}
|
||||
|
||||
@ -323,24 +328,25 @@ R_API RAnalMetaItem *r_meta_item_new(int type) {
|
||||
|
||||
static void meta_serialize(RAnalMetaItem *it, char *k, size_t k_size, char *v, size_t v_size) {
|
||||
snprintf (k, k_size, "meta.%c.0x%" PFMT64x, it->type, it->from);
|
||||
const char *name = it->space? it->space->name: "*";
|
||||
if (it->subtype) {
|
||||
snprintf (v, v_size, "%d,%d,%c,%s", (int)it->size, it->space, it->subtype, it->str);
|
||||
snprintf (v, v_size, "%d,%s,%c,%s", (int)it->size, name, it->subtype, it->str);
|
||||
} else {
|
||||
snprintf (v, v_size, "%d,%d,%s", (int)it->size, it->space, it->str);
|
||||
snprintf (v, v_size, "%d,%s,%s", (int)it->size, name, it->str);
|
||||
}
|
||||
}
|
||||
|
||||
static bool meta_deserialize(RAnalMetaItem *it, const char *k, const char *v) {
|
||||
static bool meta_deserialize(RAnal *a, RAnalMetaItem *it, const char *k, const char *v) {
|
||||
if (strlen (k) < 8) {
|
||||
return false;
|
||||
}
|
||||
if (memcmp (k + 6, ".0x", 3)) {
|
||||
return false;
|
||||
}
|
||||
return r_meta_deserialize_val (it, k[5], sdb_atoi (k + 7), v);
|
||||
return r_meta_deserialize_val (a, it, k[5], sdb_atoi (k + 7), v);
|
||||
}
|
||||
|
||||
R_API bool r_meta_deserialize_val(RAnalMetaItem *it, int type, ut64 from, const char *v) {
|
||||
R_API bool r_meta_deserialize_val(RAnal *a, RAnalMetaItem *it, int type, ut64 from, const char *v) {
|
||||
const char *v2;
|
||||
char *v3;
|
||||
it->type = type;
|
||||
@ -352,7 +358,13 @@ R_API bool r_meta_deserialize_val(RAnalMetaItem *it, int type, ut64 from, const
|
||||
if (!v2) {
|
||||
return false;
|
||||
}
|
||||
it->space = atoi (v2 + 1);
|
||||
v3 = strchr (v2 + 1, ',');
|
||||
if (!v3) {
|
||||
return false;
|
||||
}
|
||||
char *tmp = r_str_ndup (v2 + 1, v3 - v2 - 1);
|
||||
it->space = r_spaces_add (&a->meta_spaces, tmp);
|
||||
free (tmp);
|
||||
it->str = strchr (v2 + 1, ',');
|
||||
if (it->str) {
|
||||
if (it->type == R_META_TYPE_STRING) {
|
||||
@ -368,7 +380,7 @@ R_API bool r_meta_deserialize_val(RAnalMetaItem *it, int type, ut64 from, const
|
||||
}
|
||||
|
||||
static int meta_add(RAnal *a, int type, int subtype, ut64 from, ut64 to, const char *str) {
|
||||
int space_idx = a->meta_spaces.space_idx;
|
||||
const RSpace *space = r_spaces_current (&a->meta_spaces);
|
||||
char key[100], val[2048];
|
||||
if (from > to) {
|
||||
return false;
|
||||
@ -381,7 +393,7 @@ static int meta_add(RAnal *a, int type, int subtype, ut64 from, ut64 to, const c
|
||||
}
|
||||
/* set entry */
|
||||
char *e_str = sdb_encode ((const void*)str, -1);
|
||||
RAnalMetaItem mi = {from, to, (int)(to - from), type, subtype, e_str, space_idx};
|
||||
RAnalMetaItem mi = {from, to, (int)(to - from), type, subtype, e_str, space};
|
||||
meta_serialize (&mi, key, sizeof (key), val, sizeof (val));
|
||||
bool exists = sdb_exists (DB, key);
|
||||
|
||||
@ -447,7 +459,7 @@ static RAnalMetaItem *r_meta_find_(RAnal *a, ut64 at, int type, int where, int e
|
||||
snprintf (key, sizeof (key), "meta.%c.0x%" PFMT64x, *infos, at);
|
||||
metas = sdb_const_get (s, key, 0);
|
||||
if (metas) {
|
||||
if (!r_meta_deserialize_val (&mi, *infos, at, metas)) {
|
||||
if (!r_meta_deserialize_val (a, &mi, *infos, at, metas)) {
|
||||
continue;
|
||||
}
|
||||
return &mi;
|
||||
@ -508,11 +520,9 @@ R_API void r_meta_print(RAnal *a, RAnalMetaItem *d, int rad, bool show_full) {
|
||||
char *pstr, *str, *base64_str;
|
||||
RCore *core = a->coreb.core;
|
||||
bool esc_bslash = core ? core->print->esc_bslash : false;
|
||||
//eprintf ("%d %d\n", d->space, a->meta_spaces.space_idx);
|
||||
if (a->meta_spaces.space_idx != -1) {
|
||||
if (a->meta_spaces.space_idx != d->space) {
|
||||
return;
|
||||
}
|
||||
if (r_spaces_current (&a->meta_spaces) &&
|
||||
r_spaces_current (&a->meta_spaces) != d->space) {
|
||||
return;
|
||||
}
|
||||
if (d->type == 's') {
|
||||
if (d->subtype == R_STRING_ENC_UTF8) {
|
||||
@ -716,7 +726,7 @@ R_API void r_meta_print(RAnal *a, RAnalMetaItem *d, int rad, bool show_full) {
|
||||
static int meta_print_item(void *user, const char *k, const char *v) {
|
||||
RAnalMetaUserItem *ui = user;
|
||||
RAnalMetaItem it;
|
||||
if (!meta_deserialize (&it, k, v)) {
|
||||
if (!meta_deserialize (ui->anal, &it, k, v)) {
|
||||
return 1;
|
||||
}
|
||||
if (ui->fcn && !r_anal_fcn_in (ui->fcn, it.from)) {
|
||||
@ -815,7 +825,7 @@ static int meta_enumerate_cb(void *user, const char *k, const char *v) {
|
||||
if (!it) {
|
||||
return 0;
|
||||
}
|
||||
if (!meta_deserialize (it, k, v)) {
|
||||
if (!meta_deserialize (ui->anal, it, k, v)) {
|
||||
free (it);
|
||||
goto beach;
|
||||
}
|
||||
@ -842,23 +852,24 @@ static int meta_unset_cb(void *user, const char *k, const char *v) {
|
||||
if (!strstr (k, ".0x")) {
|
||||
return 1;
|
||||
}
|
||||
meta_deserialize (&it, k, v);
|
||||
if (it.space != -1) {
|
||||
it.space = -1;
|
||||
meta_deserialize (ui->anal, &it, k, v);
|
||||
if (it.space && it.space == ui->user) {
|
||||
it.space = NULL;
|
||||
meta_serialize (&it, nk, sizeof (nk), nv, sizeof (nv));
|
||||
sdb_set (DB, nk, nv, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
R_API void r_meta_space_unset_for(RAnal *a, int type) {
|
||||
r_meta_list_cb (a, type, 0, meta_unset_cb, NULL, UT64_MAX);
|
||||
R_API void r_meta_space_unset_for(RAnal *a, const RSpace *space) {
|
||||
RAnalMetaUserItem ui = { .anal = a, .user = (void *)space };
|
||||
r_meta_list_cb (a, R_META_TYPE_ANY, 0, meta_unset_cb, &ui, UT64_MAX);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int count;
|
||||
int index;
|
||||
int ctx;
|
||||
const RSpace *ctx;
|
||||
} myMetaUser;
|
||||
|
||||
static int meta_count_cb(void *user, const char *k, const char *v) {
|
||||
@ -868,17 +879,16 @@ static int meta_count_cb(void *user, const char *k, const char *v) {
|
||||
if (!strstr (k, ".0x")) {
|
||||
return 1;
|
||||
}
|
||||
meta_deserialize (&it, k, v);
|
||||
if (mu) {
|
||||
if (it.space == mu->ctx) {
|
||||
mu->count++;
|
||||
}
|
||||
meta_deserialize (ui->anal, &it, k, v);
|
||||
if (mu && it.space == mu->ctx) {
|
||||
mu->count++;
|
||||
}
|
||||
r_meta_item_fini (&it);
|
||||
return 1;
|
||||
}
|
||||
|
||||
R_API int r_meta_space_count_for(RAnal *a, int space_idx) {
|
||||
myMetaUser mu = {.ctx = space_idx};
|
||||
R_API int r_meta_space_count_for(RAnal *a, const RSpace *space) {
|
||||
myMetaUser mu = { .ctx = space };
|
||||
r_meta_list_cb (a, R_META_TYPE_ANY, 0, meta_count_cb, &mu, UT64_MAX);
|
||||
return mu.count;
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ static bool deserialize(RAnal *a, RSignItem *it, const char *k, const char *v) {
|
||||
}
|
||||
|
||||
// space (1)
|
||||
it->space = r_space_add (&a->zign_spaces, r_str_word_get0 (k2, 1));
|
||||
it->space = r_spaces_add (&a->zign_spaces, r_str_word_get0 (k2, 1));
|
||||
|
||||
// name (2)
|
||||
it->name = r_str_new (r_str_word_get0 (k2, 2));
|
||||
@ -210,13 +210,14 @@ out:
|
||||
free (k2);
|
||||
free (v2);
|
||||
free (refs);
|
||||
free (vars);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void serializeKey(RAnal *a, int space, const char* name, char *k) {
|
||||
static void serializeKey(RAnal *a, const RSpace *space, const char* name, char *k) {
|
||||
snprintf (k, R_SIGN_KEY_MAXSZ, "zign|%s|%s",
|
||||
space >= 0? a->zign_spaces.spaces[space]: "*", name);
|
||||
space? space->name: "*", name);
|
||||
}
|
||||
|
||||
static void serializeKeySpaceStr(RAnal *a, const char *space, const char* name, char *k) {
|
||||
@ -464,7 +465,7 @@ static bool addBytes(RAnal *a, const char *name, ut64 size, const ut8 *bytes, co
|
||||
free (it);
|
||||
return false;
|
||||
}
|
||||
it->space = a->zign_spaces.space_idx;
|
||||
it->space = r_spaces_current (&a->zign_spaces);
|
||||
it->bytes = R_NEW0 (RSignBytes);
|
||||
if (!it->bytes) {
|
||||
goto fail;
|
||||
@ -550,7 +551,7 @@ R_API bool r_sign_add_graph(RAnal *a, const char *name, RSignGraph graph) {
|
||||
free (it);
|
||||
return false;
|
||||
}
|
||||
it->space = a->zign_spaces.space_idx;
|
||||
it->space = r_spaces_current (&a->zign_spaces);
|
||||
it->graph = R_NEW0 (RSignGraph);
|
||||
if (!it->graph) {
|
||||
free (it->name);
|
||||
@ -572,7 +573,7 @@ R_API bool r_sign_add_addr(RAnal *a, const char *name, ut64 addr) {
|
||||
return NULL;
|
||||
}
|
||||
it->name = r_str_new (name);
|
||||
it->space = a->zign_spaces.space_idx;
|
||||
it->space = r_spaces_current (&a->zign_spaces);
|
||||
it->addr = addr;
|
||||
|
||||
bool retval = addItem (a, it);
|
||||
@ -597,7 +598,7 @@ R_API bool r_sign_add_vars(RAnal *a, const char *name, RList *vars) {
|
||||
r_sign_item_free (it);
|
||||
return false;
|
||||
}
|
||||
it->space = a->zign_spaces.space_idx;
|
||||
it->space = r_spaces_current (&a->zign_spaces);
|
||||
it->vars = r_list_newf ((RListFree) free);
|
||||
r_list_foreach (vars, iter, var) {
|
||||
r_list_append (it->vars, strdup (var));
|
||||
@ -622,7 +623,7 @@ R_API bool r_sign_add_refs(RAnal *a, const char *name, RList *refs) {
|
||||
free (it);
|
||||
return false;
|
||||
}
|
||||
it->space = a->zign_spaces.space_idx;
|
||||
it->space = r_spaces_current (&a->zign_spaces);
|
||||
it->refs = r_list_newf ((RListFree) free);
|
||||
r_list_foreach (refs, iter, ref) {
|
||||
r_list_append (it->refs, strdup (ref));
|
||||
@ -657,17 +658,17 @@ R_API bool r_sign_delete(RAnal *a, const char *name) {
|
||||
}
|
||||
// Remove all zigns
|
||||
if (*name == '*') {
|
||||
if (a->zign_spaces.space_idx == -1) {
|
||||
if (!r_spaces_current (&a->zign_spaces)) {
|
||||
sdb_reset (a->sdb_zigns);
|
||||
return true;
|
||||
}
|
||||
ctx.anal = a;
|
||||
serializeKey (a, a->zign_spaces.space_idx, "", ctx.buf);
|
||||
serializeKey (a, r_spaces_current (&a->zign_spaces), "", ctx.buf);
|
||||
sdb_foreach (a->sdb_zigns, deleteBySpaceCB, &ctx);
|
||||
return true;
|
||||
}
|
||||
// Remove specific zign
|
||||
serializeKey (a, a->zign_spaces.space_idx, name, k);
|
||||
serializeKey (a, r_spaces_current (&a->zign_spaces), name, k);
|
||||
return sdb_remove (a->sdb_zigns, k, 0);
|
||||
}
|
||||
|
||||
@ -843,7 +844,8 @@ static int listCB(void *user, const char *k, const char *v) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (a->zign_spaces.space_idx != it->space && a->zign_spaces.space_idx != -1) {
|
||||
RSpace *cur = r_spaces_current (&a->zign_spaces);
|
||||
if (cur != it->space && cur) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -857,19 +859,19 @@ static int listCB(void *user, const char *k, const char *v) {
|
||||
|
||||
// Zignspace and name (except for radare format)
|
||||
if (ctx->format == '*') {
|
||||
if (it->space >= 0) {
|
||||
a->cb_printf ("zs %s\n", a->zign_spaces.spaces[it->space]);
|
||||
if (it->space) {
|
||||
a->cb_printf ("zs %s\n", it->space->name);
|
||||
} else {
|
||||
a->cb_printf ("zs *\n");
|
||||
}
|
||||
} else if (ctx->format == 'j') {
|
||||
if (it->space >= 0) {
|
||||
a->cb_printf ("{\"zignspace\":\"%s\",", a->zign_spaces.spaces[it->space]);
|
||||
if (it->space) {
|
||||
a->cb_printf ("{\"zignspace\":\"%s\",", it->space->name);
|
||||
}
|
||||
a->cb_printf ("\"name\":\"%s\",", it->name);
|
||||
} else {
|
||||
if (a->zign_spaces.space_idx == -1 && it->space >= 0) {
|
||||
a->cb_printf ("(%s) ", a->zign_spaces.spaces[it->space]);
|
||||
if (!r_spaces_current (&a->zign_spaces) && it->space) {
|
||||
a->cb_printf ("(%s) ", it->space->name);
|
||||
}
|
||||
a->cb_printf ("%s:\n", it->name);
|
||||
}
|
||||
@ -1006,7 +1008,7 @@ beach:
|
||||
|
||||
struct ctxCountForCB {
|
||||
RAnal *anal;
|
||||
int idx;
|
||||
const RSpace *space;
|
||||
int count;
|
||||
};
|
||||
|
||||
@ -1019,7 +1021,7 @@ static int countForCB(void *user, const char *k, const char *v) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (it->space == ctx->idx) {
|
||||
if (it->space == ctx->space) {
|
||||
ctx->count++;
|
||||
}
|
||||
|
||||
@ -1029,8 +1031,8 @@ out:
|
||||
return 1;
|
||||
}
|
||||
|
||||
R_API int r_sign_space_count_for(RAnal *a, int idx) {
|
||||
struct ctxCountForCB ctx = { a, idx, 0 };
|
||||
R_API int r_sign_space_count_for(RAnal *a, const RSpace *space) {
|
||||
struct ctxCountForCB ctx = { a, space, 0 };
|
||||
|
||||
if (!a) {
|
||||
return 0;
|
||||
@ -1043,7 +1045,7 @@ R_API int r_sign_space_count_for(RAnal *a, int idx) {
|
||||
|
||||
struct ctxUnsetForCB {
|
||||
RAnal *anal;
|
||||
int idx;
|
||||
const RSpace *space;
|
||||
};
|
||||
|
||||
static int unsetForCB(void *user, const char *k, const char *v) {
|
||||
@ -1058,12 +1060,12 @@ static int unsetForCB(void *user, const char *k, const char *v) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (it->space != ctx->idx) {
|
||||
if (it->space != ctx->space) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (it->space != -1) {
|
||||
it->space = -1;
|
||||
if (it->space) {
|
||||
it->space = NULL;
|
||||
serialize (a, it, nk, nv);
|
||||
sdb_remove (db, k, 0);
|
||||
sdb_set (db, nk, nv, 0);
|
||||
@ -1075,8 +1077,8 @@ out:
|
||||
return 1;
|
||||
}
|
||||
|
||||
R_API void r_sign_space_unset_for(RAnal *a, int idx) {
|
||||
struct ctxUnsetForCB ctx = { a, idx };
|
||||
R_API void r_sign_space_unset_for(RAnal *a, const RSpace *space) {
|
||||
struct ctxUnsetForCB ctx = { a, space };
|
||||
|
||||
if (!a) {
|
||||
return;
|
||||
@ -1108,7 +1110,7 @@ static int renameForCB(void *user, const char *k, const char *v) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
R_API void r_sign_space_rename_for(RAnal *a, int idx, const char *oname, const char *nname) {
|
||||
R_API void r_sign_space_rename_for(RAnal *a, const RSpace *space, const char *oname, const char *nname) {
|
||||
struct ctxRenameForCB ctx;
|
||||
|
||||
if (!a || !oname || !nname) {
|
||||
@ -1139,7 +1141,8 @@ static int foreachCB(void *user, const char *k, const char *v) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (a->zign_spaces.space_idx != it->space && a->zign_spaces.space_idx != -1) {
|
||||
RSpace *cur = r_spaces_current (&a->zign_spaces);
|
||||
if (cur != it->space && cur) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -1486,7 +1489,7 @@ R_API RSignItem *r_sign_item_new() {
|
||||
RSignItem *ret = R_NEW0 (RSignItem);
|
||||
if (ret) {
|
||||
ret->addr = UT64_MAX;
|
||||
ret->space = -1;
|
||||
ret->space = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -1885,7 +1885,7 @@ static int bin_symbols(RCore *r, int mode, ut64 laddr, int va, ut64 at, const ch
|
||||
const char *lang = bin_demangle ? r_config_get (r->config, "bin.lang") : NULL;
|
||||
|
||||
RList *symbols = r_bin_get_symbols (r->bin);
|
||||
r_space_set (&r->anal->meta_spaces, "bin");
|
||||
r_spaces_push (&r->anal->meta_spaces, "bin");
|
||||
|
||||
if (IS_MODE_JSON (mode) && !printHere) {
|
||||
r_cons_printf ("[");
|
||||
@ -2146,7 +2146,7 @@ static int bin_symbols(RCore *r, int mode, ut64 laddr, int va, ut64 at, const ch
|
||||
r_cons_printf ("]");
|
||||
}
|
||||
|
||||
r_space_set (&r->anal->meta_spaces, NULL);
|
||||
r_spaces_pop (&r->anal->meta_spaces);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -686,7 +686,7 @@ static int cmd_meta_others(RCore *core, const char *input) {
|
||||
if (!val) {
|
||||
break;
|
||||
}
|
||||
if (!r_meta_deserialize_val (&mi, type, addr, val)) {
|
||||
if (!r_meta_deserialize_val (core->anal, &mi, type, addr, val)) {
|
||||
break;
|
||||
}
|
||||
if (!mi.str) {
|
||||
@ -1070,11 +1070,11 @@ static int cmd_meta(void *data, const char *input) {
|
||||
r_core_cmd_help (core, help_msg_CS);
|
||||
break;
|
||||
case '+': // "CS+"
|
||||
r_space_push (ms, input + 2);
|
||||
r_spaces_push (ms, input + 2);
|
||||
break;
|
||||
case 'r': // "CSr"
|
||||
if (input[2] == ' ') {
|
||||
r_space_rename (ms, NULL, input+2);
|
||||
r_spaces_rename (ms, NULL, input+2);
|
||||
} else {
|
||||
eprintf ("Usage: CSr [newname]\n");
|
||||
}
|
||||
@ -1082,44 +1082,32 @@ static int cmd_meta(void *data, const char *input) {
|
||||
case '-': // "CS-"
|
||||
if (input[2]) {
|
||||
if (input[2]=='*') {
|
||||
r_space_unset (ms, NULL);
|
||||
r_spaces_unset (ms, NULL);
|
||||
} else {
|
||||
r_space_unset (ms, input+2);
|
||||
r_spaces_unset (ms, input+2);
|
||||
}
|
||||
} else {
|
||||
r_space_pop (ms);
|
||||
r_spaces_pop (ms);
|
||||
}
|
||||
break;
|
||||
case 'j': // "CSj"
|
||||
case '\0': // "CS"
|
||||
case '*': // "CS*"
|
||||
r_space_list (ms, input[1]);
|
||||
spaces_list (ms, input[1]);
|
||||
break;
|
||||
case ' ': // "CS "
|
||||
r_space_set (ms, input + 2);
|
||||
r_spaces_set (ms, input + 2);
|
||||
break;
|
||||
#if 0
|
||||
case 'm':
|
||||
{ RFlagItem *f;
|
||||
ut64 off = core->offset;
|
||||
if (input[2] == ' ')
|
||||
off = r_num_math (core->num, input+2);
|
||||
f = r_flag_get_i (core->flags, off);
|
||||
if (f) {
|
||||
f->space = core->flags->space_idx;
|
||||
} else eprintf ("Cannot find any flag at 0x%"PFMT64x".\n", off);
|
||||
default: {
|
||||
RSpace *s;
|
||||
RBIter it;
|
||||
const RSpace *cur = r_spaces_current (ms);
|
||||
r_rbtree_foreach (ms->spaces, it, s, RSpace, rb) {
|
||||
r_cons_printf ("%c %s\n", (s == cur)? '*': ' ',
|
||||
s->name);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default: {
|
||||
int i, j = 0;
|
||||
for (i = 0; i < R_FLAG_SPACES_MAX; i++) {
|
||||
if (!ms->spaces[i]) continue;
|
||||
r_cons_printf ("%02d %c %s\n", j++,
|
||||
(i == ms->space_idx)?'*':' ',
|
||||
ms->spaces[i]);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <r_list.h>
|
||||
#include <r_cons.h>
|
||||
#include <r_util.h>
|
||||
#include "i/private.h"
|
||||
|
||||
static const char *help_msg_z[] = {
|
||||
"Usage:", "z[*j-aof/cs] [args] ", "# Manage zignatures",
|
||||
@ -148,13 +149,13 @@ static bool addFcnVars(RCore *core, RAnalFunction *fcn, const char *name) {
|
||||
|
||||
static void addFcnZign(RCore *core, RAnalFunction *fcn, const char *name) {
|
||||
char *zigname = NULL;
|
||||
int curspace = core->anal->zign_spaces.space_idx;
|
||||
const RSpace *curspace = r_spaces_current (&core->anal->zign_spaces);
|
||||
|
||||
if (name) {
|
||||
zigname = r_str_new (name);
|
||||
} else {
|
||||
if (curspace != -1) {
|
||||
zigname = r_str_newf ("%s.", core->anal->zign_spaces.spaces[curspace]);
|
||||
if (curspace) {
|
||||
zigname = r_str_newf ("%s.", curspace->name);
|
||||
}
|
||||
zigname = r_str_appendf (zigname, "%s", fcn->name);
|
||||
}
|
||||
@ -508,35 +509,35 @@ static int cmdSpace(void *data, const char *input) {
|
||||
eprintf ("usage: zs+zignspace\n");
|
||||
return false;
|
||||
}
|
||||
r_space_push (zs, input + 1);
|
||||
r_spaces_push (zs, input + 1);
|
||||
break;
|
||||
case 'r':
|
||||
if (input[1] != ' ' || !input[2]) {
|
||||
eprintf ("usage: zsr newname\n");
|
||||
return false;
|
||||
}
|
||||
r_space_rename (zs, NULL, input + 2);
|
||||
r_spaces_rename (zs, NULL, input + 2);
|
||||
break;
|
||||
case '-':
|
||||
if (input[1] == '\x00') {
|
||||
r_space_pop (zs);
|
||||
r_spaces_pop (zs);
|
||||
} else if (input[1] == '*') {
|
||||
r_space_unset (zs, NULL);
|
||||
r_spaces_unset (zs, NULL);
|
||||
} else {
|
||||
r_space_unset (zs, input + 1);
|
||||
r_spaces_unset (zs, input + 1);
|
||||
}
|
||||
break;
|
||||
case 'j':
|
||||
case '*':
|
||||
case '\0':
|
||||
r_space_list (zs, input[0]);
|
||||
spaces_list (zs, input[0]);
|
||||
break;
|
||||
case ' ':
|
||||
if (!input[1]) {
|
||||
eprintf ("usage: zs zignspace\n");
|
||||
return false;
|
||||
}
|
||||
r_space_set (zs, input + 1);
|
||||
r_spaces_set (zs, input + 1);
|
||||
break;
|
||||
case '?':
|
||||
r_core_cmd_help (core, help_msg_zs);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#if __UNIX__
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#include "i/private.h"
|
||||
|
||||
#define DB core->sdb
|
||||
|
||||
@ -1170,20 +1171,22 @@ static void autocomplete_zignatures(RLine* line, const char* msg) {
|
||||
return;
|
||||
}
|
||||
int length = strlen (msg);
|
||||
RSpaces zs = core->anal->zign_spaces;
|
||||
int j, i = 0;
|
||||
for (j = 0; j < R_SPACES_MAX; j++) {
|
||||
if (zs.spaces[j]) {
|
||||
if (i == TMP_ARGV_SZ - 1) {
|
||||
break;
|
||||
}
|
||||
if (!strncmp (msg, zs.spaces[j], length)) {
|
||||
if (i + 1 < TMP_ARGV_SZ) {
|
||||
tmp_argv[i++] = zs.spaces[j];
|
||||
}
|
||||
RSpaces *zs = &core->anal->zign_spaces;
|
||||
RSpace *s;
|
||||
RBIter it;
|
||||
int i = 0;
|
||||
|
||||
r_rbtree_foreach (zs->spaces, it, s, RSpace, rb) {
|
||||
if (i == TMP_ARGV_SZ - 1) {
|
||||
break;
|
||||
}
|
||||
if (!strncmp (msg, s->name, length)) {
|
||||
if (i + 1 < TMP_ARGV_SZ) {
|
||||
tmp_argv[i++] = s->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen (msg) == 0 && i + 1 < TMP_ARGV_SZ) {
|
||||
tmp_argv[i++] = "*";
|
||||
}
|
||||
@ -2205,7 +2208,38 @@ static char *get_comments_cb(void *user, ut64 addr) {
|
||||
return r_core_anal_get_comments ((RCore *)user, addr);
|
||||
}
|
||||
|
||||
static void cb_event_handler(REvent *ev, REventType event_type, void *data) {
|
||||
R_IPI void spaces_list(RSpaces *sp, int mode) {
|
||||
RBIter it;
|
||||
RSpace *s;
|
||||
bool first = true;
|
||||
const RSpace *cur = r_spaces_current (sp);
|
||||
if (mode == 'j') {
|
||||
r_cons_printf ("[");
|
||||
}
|
||||
r_rbtree_foreach (sp->spaces, it, s, RSpace, rb) {
|
||||
int count = r_spaces_count (sp, s->name);
|
||||
if (mode == 'j') {
|
||||
r_cons_printf ("%s{\"name\":\"%s\"%s,\"count\":%d}",
|
||||
!first? ",": "", s->name,
|
||||
cur == s? ",\"selected\":true": "",
|
||||
count);
|
||||
} else if (mode == '*') {
|
||||
r_cons_printf ("%s %s\n", sp->name, s->name);
|
||||
} else {
|
||||
r_cons_printf ("%d %c %s\n", count, cur == s? '*': '.',
|
||||
s->name);
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
if (mode == '*' && r_spaces_current (sp)) {
|
||||
r_cons_printf ("%s %s # current\n", sp->name, r_spaces_current_name (sp));
|
||||
}
|
||||
if (mode == 'j') {
|
||||
r_cons_printf ("]\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void cb_event_handler(REvent *ev, int event_type, void *user, void *data) {
|
||||
RCore *core = (RCore *)ev->user;
|
||||
if (!core->log_events) {
|
||||
return;
|
||||
@ -2362,7 +2396,6 @@ R_API bool r_core_init(RCore *core) {
|
||||
core->anal->ev = core->ev;
|
||||
core->anal->log = r_core_anal_log;
|
||||
core->anal->read_at = r_core_anal_read_at;
|
||||
core->anal->meta_spaces.cb_printf = r_cons_printf;
|
||||
core->anal->cb.on_fcn_new = on_fcn_new;
|
||||
core->anal->cb.on_fcn_delete = on_fcn_delete;
|
||||
core->anal->cb.on_fcn_rename = on_fcn_rename;
|
||||
|
@ -2693,7 +2693,7 @@ static int ds_print_meta_infos(RDisasmState *ds, ut8* buf, int len, int idx) {
|
||||
if (!metas) {
|
||||
continue;
|
||||
}
|
||||
if (!r_meta_deserialize_val (mi, *infos, ds->at, metas)) {
|
||||
if (!r_meta_deserialize_val (core->anal, mi, *infos, ds->at, metas)) {
|
||||
continue;
|
||||
}
|
||||
// TODO: implement ranged meta find (if not at the begging of function..
|
||||
|
10
libr/core/i/private.h
Normal file
10
libr/core/i/private.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef R_CORE_PRIVATE_H_
|
||||
#define R_CORE_PRIVATE_H_
|
||||
|
||||
#include <r_core.h>
|
||||
#include <r_util.h>
|
||||
#include <r_types.h>
|
||||
|
||||
R_IPI void spaces_list(RSpaces *sp, int mode);
|
||||
|
||||
#endif
|
@ -1817,14 +1817,14 @@ R_API int r_core_visual_trackflags(RCore *core) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static bool meta_deserialize(RAnalMetaItem *it, const char *k, const char *v) {
|
||||
static bool meta_deserialize(RAnal *a, RAnalMetaItem *it, const char *k, const char *v) {
|
||||
if (strlen (k) < 8) {
|
||||
return false;
|
||||
}
|
||||
if (memcmp (k + 6, ".0x", 3)) {
|
||||
return false;
|
||||
}
|
||||
return r_meta_deserialize_val (it, k[5], sdb_atoi (k + 7), v);
|
||||
return r_meta_deserialize_val (a, it, k[5], sdb_atoi (k + 7), v);
|
||||
}
|
||||
|
||||
static int meta_enumerate_cb(void *user, const char *k, const char *v) {
|
||||
@ -1834,7 +1834,7 @@ static int meta_enumerate_cb(void *user, const char *k, const char *v) {
|
||||
if (!it) {
|
||||
return 0;
|
||||
}
|
||||
if (!meta_deserialize (it, k, v)) {
|
||||
if (!meta_deserialize (ui->anal, it, k, v)) {
|
||||
free (it);
|
||||
goto beach;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ typedef struct r_anal_meta_item_t {
|
||||
int type;
|
||||
int subtype;
|
||||
char *str;
|
||||
int space;
|
||||
const RSpace *space;
|
||||
} RAnalMetaItem;
|
||||
|
||||
typedef struct {
|
||||
@ -1612,8 +1612,8 @@ R_API void r_anal_data_free (RAnalData *d);
|
||||
R_API char *r_anal_data_to_string(RAnalData *d, RConsPrintablePalette *pal);
|
||||
|
||||
R_API void r_meta_free(RAnal *m);
|
||||
R_API void r_meta_space_unset_for(RAnal *a, int type);
|
||||
R_API int r_meta_space_count_for(RAnal *a, int space_idx);
|
||||
R_API void r_meta_space_unset_for(RAnal *a, const RSpace *space);
|
||||
R_API int r_meta_space_count_for(RAnal *a, const RSpace *space_name);
|
||||
R_API RList *r_meta_enumerate(RAnal *a, int type);
|
||||
R_API int r_meta_count(RAnal *m, int type, ut64 from, ut64 to);
|
||||
R_API char *r_meta_get_string(RAnal *m, int type, ut64 addr);
|
||||
@ -1636,7 +1636,7 @@ R_API int r_meta_list_cb(RAnal *m, int type, int rad, SdbForeachCallback cb, voi
|
||||
R_API void r_meta_list_offset(RAnal *m, ut64 addr, char input);
|
||||
R_API void r_meta_item_free(void *_item);
|
||||
R_API RAnalMetaItem *r_meta_item_new(int type);
|
||||
R_API bool r_meta_deserialize_val(RAnalMetaItem *it, int type, ut64 from, const char *v);
|
||||
R_API bool r_meta_deserialize_val(RAnal *a, RAnalMetaItem *it, int type, ut64 from, const char *v);
|
||||
R_API void r_meta_print(RAnal *a, RAnalMetaItem *d, int rad, bool show_full);
|
||||
|
||||
/* hints */
|
||||
@ -1733,9 +1733,9 @@ R_API int r_anal_noreturn_drop(RAnal *anal, const char *expr);
|
||||
R_API bool r_anal_noreturn_at_addr(RAnal *anal, ut64 addr);
|
||||
|
||||
/* zign spaces */
|
||||
R_API int r_sign_space_count_for(RAnal *a, int idx);
|
||||
R_API void r_sign_space_unset_for(RAnal *a, int idx);
|
||||
R_API void r_sign_space_rename_for(RAnal *a, int idx, const char *oname, const char *nname);
|
||||
R_API int r_sign_space_count_for(RAnal *a, const RSpace *space);
|
||||
R_API void r_sign_space_unset_for(RAnal *a, const RSpace *space);
|
||||
R_API void r_sign_space_rename_for(RAnal *a, const RSpace *space, const char *oname, const char *nname);
|
||||
|
||||
/* vtables */
|
||||
typedef struct {
|
||||
|
@ -47,7 +47,7 @@ typedef struct r_sign_hash_t {
|
||||
|
||||
typedef struct r_sign_item_t {
|
||||
char *name;
|
||||
int space;
|
||||
const RSpace *space;
|
||||
|
||||
RSignBytes *bytes;
|
||||
RSignGraph *graph;
|
||||
|
@ -29,13 +29,13 @@ typedef struct r_event_meta_t {
|
||||
const char *string;
|
||||
} REventMeta;
|
||||
|
||||
typedef void (*REventCallback)(REvent *ev, REventType type, void *data);
|
||||
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, REventType type, REventCallback cb);
|
||||
R_API void r_event_unhook(REvent *ev, REventType type, REventCallback cb);
|
||||
R_API void r_event_send(REvent *ev, REventType type, void *data);
|
||||
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 void r_event_send(REvent *ev, int type, void *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -3,33 +3,94 @@
|
||||
|
||||
#define R_SPACES_MAX 512
|
||||
|
||||
#include "r_util.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* RSpaces represents a set of Spaces.
|
||||
* A Space is used to group similar objects and it can have a name. Name
|
||||
* "*"/""/NULL is reserved to indicate "all spaces".
|
||||
*
|
||||
* You can have groups of "meta" (e.g. bin meta, format meta, etc.), groups of
|
||||
* zign info, groups of flags, etc.
|
||||
*
|
||||
* It is possible to hook into the RSpaces functions by using REvent.
|
||||
* R_SPACE_EVENT_COUNT: called when you need to count how many elements there are in a given RSpace
|
||||
* R_SPACE_EVENT_RENAME: called when renaming a RSpace with an oldname to a newname
|
||||
* R_SPACE_EVENT_UNSET: called when deleting a RSpace with a given name
|
||||
*/
|
||||
|
||||
typedef struct r_space_t {
|
||||
char *name;
|
||||
int space_idx;
|
||||
char *spaces[R_SPACES_MAX];
|
||||
RBNode rb;
|
||||
} RSpace;
|
||||
|
||||
typedef enum {
|
||||
R_SPACE_EVENT_COUNT = 1,
|
||||
R_SPACE_EVENT_RENAME,
|
||||
R_SPACE_EVENT_UNSET,
|
||||
} RSpaceEventType;
|
||||
|
||||
typedef struct r_space_event_t {
|
||||
union {
|
||||
struct {
|
||||
const RSpace *space;
|
||||
} count;
|
||||
struct {
|
||||
const RSpace *space;
|
||||
} unset;
|
||||
struct {
|
||||
const RSpace *space;
|
||||
const char *oldname;
|
||||
const char *newname;
|
||||
} rename;
|
||||
} data;
|
||||
int res;
|
||||
} RSpaceEvent;
|
||||
|
||||
typedef struct r_spaces_t {
|
||||
const char *name;
|
||||
RSpace *current;
|
||||
RBTree spaces;
|
||||
RList *spacestack;
|
||||
PrintfCallback cb_printf;
|
||||
void (*unset_for)(void *user, int idx);
|
||||
int (*count_for)(void *user, int idx);
|
||||
void (*rename_for)(void *user, int idx, const char *oname, const char *nname);
|
||||
void *user;
|
||||
REvent *event;
|
||||
} RSpaces;
|
||||
|
||||
R_API void r_space_new(RSpaces *s, const char *name, void (*unset_for)(void*,int), int (*count_for)(void*,int), void (*rename_for)(void*,int,const char*,const char*), void *user);
|
||||
R_API void r_space_free(RSpaces *s);
|
||||
R_API int r_space_get(RSpaces *s, const char *name);
|
||||
R_API const char *r_space_get_i(RSpaces *s, int idx);
|
||||
R_API int r_space_add(RSpaces *s, const char *name);
|
||||
R_API bool r_space_push(RSpaces *s, const char *name);
|
||||
R_API bool r_space_pop(RSpaces *s);
|
||||
R_API int r_space_set(RSpaces *s, const char *name);
|
||||
R_API int r_space_unset (RSpaces *s, const char *name);
|
||||
R_API int r_space_list(RSpaces *s, int mode);
|
||||
R_API bool r_space_rename (RSpaces *s, const char *oname, const char *nname);
|
||||
// Create a new RSpaces with the given name
|
||||
R_API RSpaces *r_spaces_new(const char *name);
|
||||
// Initialize an existing RSpaces with the given name
|
||||
R_API bool r_spaces_init(RSpaces *sp, const char *name);
|
||||
// Finalize an existing RSpaces
|
||||
R_API void r_spaces_fini(RSpaces *sp);
|
||||
// Finalize and free an existing RSpaces
|
||||
R_API void r_spaces_free(RSpaces *sp);
|
||||
// Get the RSpace with the given name
|
||||
R_API RSpace *r_spaces_get(RSpaces *sp, const char *name);
|
||||
// Add a new RSpace if one does not already exist, otherwise return the existing one
|
||||
R_API RSpace *r_spaces_add(RSpaces *sp, const char *name);
|
||||
// Add and select a new RSpace if one does not already exist, otherwise return and select the existing one
|
||||
R_API RSpace *r_spaces_set(RSpaces *sp, const char *name);
|
||||
// Remove the RSpace with the given name
|
||||
R_API bool r_spaces_unset(RSpaces *sp, const char *name);
|
||||
// Change the name of RSpace with oname to nname
|
||||
R_API bool r_spaces_rename(RSpaces *sp, const char *oname, const char *nname);
|
||||
// Count the elements that belong to the RSpace with the given name
|
||||
R_API int r_spaces_count(RSpaces *sp, const char *name);
|
||||
// Add/Select the RSpace with the given name and save the current one in the history
|
||||
R_API bool r_spaces_push(RSpaces *sp, const char *name);
|
||||
// Select the RSpace that was set before the current one
|
||||
R_API bool r_spaces_pop(RSpaces *sp);
|
||||
|
||||
static inline RSpace *r_spaces_current(RSpaces *sp) {
|
||||
return sp->current;
|
||||
}
|
||||
|
||||
static inline const char *r_spaces_current_name(RSpaces *sp) {
|
||||
return sp->current? sp->current->name: "*";
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ static bool add_hook(void *cb, const ut64 k, const void *v) {
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API void r_event_hook(REvent *ev, REventType type, REventCallback cb) {
|
||||
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);
|
||||
@ -58,7 +58,7 @@ static bool del_hook(void *cb, const ut64 k, const void *v) {
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API void r_event_unhook(REvent *ev, REventType type, REventCallback cb) {
|
||||
R_API void r_event_unhook(REvent *ev, int type, REventCallback cb) {
|
||||
r_return_if_fail (ev);
|
||||
if (type == R_EVENT_ALL) {
|
||||
ht_up_foreach (ev->callbacks, del_hook, cb);
|
||||
@ -68,7 +68,7 @@ R_API void r_event_unhook(REvent *ev, REventType type, REventCallback cb) {
|
||||
}
|
||||
}
|
||||
|
||||
R_API void r_event_send(REvent *ev, REventType type, void *data) {
|
||||
R_API void r_event_send(REvent *ev, int type, void *data) {
|
||||
r_return_if_fail (ev && !ev->incall);
|
||||
|
||||
void **it;
|
||||
@ -77,7 +77,7 @@ R_API void r_event_send(REvent *ev, REventType type, void *data) {
|
||||
ev->incall = true;
|
||||
r_pvector_foreach (cbs, it) {
|
||||
REventCallback cb = *it;
|
||||
cb (ev, type, data);
|
||||
cb (ev, type, ev->user, data);
|
||||
}
|
||||
ev->incall = false;
|
||||
}
|
||||
|
@ -1,213 +1,185 @@
|
||||
/* radare - LGPL - Copyright 2015 - pancake */
|
||||
/* radare - LGPL - Copyright 2019 - pancake, ret2libc */
|
||||
|
||||
#include <r_anal.h>
|
||||
#include "r_util/r_spaces.h"
|
||||
|
||||
R_API void r_space_new(RSpaces *s, const char *name, void (*unset_for)(void*,int), int (*count_for)(void*,int), void (*rename_for)(void*,int,const char*,const char*), void *user) {
|
||||
int i;
|
||||
s->name = r_str_new (name);
|
||||
s->space_idx = -1;
|
||||
s->spacestack = r_list_new ();
|
||||
s->cb_printf = (PrintfCallback)printf;
|
||||
s->unset_for = unset_for;
|
||||
s->count_for = count_for;
|
||||
s->rename_for = rename_for;
|
||||
s->user = user;
|
||||
for (i = 0; i < R_SPACES_MAX; i++) {
|
||||
s->spaces[i] = NULL;
|
||||
R_API RSpaces *r_spaces_new(const char *name) {
|
||||
RSpaces *sp = R_NEW0 (RSpaces);
|
||||
if (!sp || !r_spaces_init (sp, name)) {
|
||||
return NULL;
|
||||
}
|
||||
return sp;
|
||||
}
|
||||
|
||||
R_API void r_space_free(RSpaces *s) {
|
||||
int i;
|
||||
for (i = 0; i < R_SPACES_MAX; i++) {
|
||||
R_FREE (s->spaces[i]);
|
||||
R_API bool r_spaces_init(RSpaces *sp, const char *name) {
|
||||
r_return_val_if_fail (sp && name, false);
|
||||
sp->name = strdup (name);
|
||||
if (!sp->name) {
|
||||
goto fail;
|
||||
}
|
||||
r_list_free (s->spacestack);
|
||||
free (s->name);
|
||||
}
|
||||
|
||||
R_API int r_space_get(RSpaces *s, const char *name) {
|
||||
int i;
|
||||
if (!name || *name == '*') {
|
||||
return -1;
|
||||
sp->spaces = NULL;
|
||||
sp->current = NULL;
|
||||
sp->spacestack = r_list_new ();
|
||||
if (!sp->spacestack) {
|
||||
goto fail;
|
||||
}
|
||||
for (i = 0; i < R_SPACES_MAX; i++) {
|
||||
if (s->spaces[i] && !strcmp (name, s->spaces[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
R_API const char *r_space_get_i(RSpaces *s, int idx) {
|
||||
if (idx==-1 || idx>=R_SPACES_MAX) {
|
||||
return "";
|
||||
sp->event = r_event_new (sp);
|
||||
if (!sp->event) {
|
||||
goto fail;
|
||||
}
|
||||
return s->spaces[idx];
|
||||
}
|
||||
|
||||
R_API int r_space_add(RSpaces *s, const char *name) {
|
||||
int i;
|
||||
if (!name || *name == '*') {
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < R_SPACES_MAX; i++) {
|
||||
if (s->spaces[i] && !strcmp (name, s->spaces[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
// not found
|
||||
for (i = 0; i < R_SPACES_MAX; i++) {
|
||||
if (!s->spaces[i]) {
|
||||
s->spaces[i] = strdup (name);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return true;
|
||||
|
||||
R_API bool r_space_push(RSpaces *s, const char *name) {
|
||||
int ret = false;
|
||||
if (name && *name) {
|
||||
if (s->space_idx >= 0 && s->spaces[s->space_idx]) {
|
||||
r_list_push (s->spacestack, s->spaces[s->space_idx]);
|
||||
} else {
|
||||
r_list_push (s->spacestack, "*");
|
||||
}
|
||||
r_space_set (s, name);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API bool r_space_pop(RSpaces *s) {
|
||||
char *p = r_list_pop (s->spacestack);
|
||||
if (p) {
|
||||
if (*p) {
|
||||
r_space_set (s, p);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
fail:
|
||||
r_spaces_free (sp);
|
||||
return false;
|
||||
}
|
||||
|
||||
R_API int r_space_set(RSpaces *s, const char *name) {
|
||||
s->space_idx = r_space_add (s, name);
|
||||
return s->space_idx;
|
||||
R_API void r_spaces_free(RSpaces *sp) {
|
||||
r_spaces_fini (sp);
|
||||
free (sp);
|
||||
}
|
||||
|
||||
R_API int r_space_unset (RSpaces *s, const char *name) {
|
||||
int i, count = 0;
|
||||
static void space_free(RSpace *s) {
|
||||
if (s) {
|
||||
free (s->name);
|
||||
free (s);
|
||||
}
|
||||
}
|
||||
|
||||
static void space_node_free(RBNode *n) {
|
||||
RSpace *s = container_of (n, RSpace, rb);
|
||||
space_free (s);
|
||||
}
|
||||
|
||||
R_API void r_spaces_fini(RSpaces *sp) {
|
||||
r_list_free (sp->spacestack);
|
||||
sp->spacestack = NULL;
|
||||
r_rbtree_free (sp->spaces, space_node_free);
|
||||
sp->spaces = NULL;
|
||||
r_event_free (sp->event);
|
||||
sp->event = NULL;
|
||||
R_FREE (sp->name);
|
||||
}
|
||||
|
||||
static int name_space_cmp(const void *incoming, const RBNode *rb) {
|
||||
const RSpace *s = container_of (rb, const RSpace, rb);
|
||||
return strcmp (incoming, s->name);
|
||||
}
|
||||
|
||||
R_API RSpace *r_spaces_get(RSpaces *sp, const char *name) {
|
||||
RBNode *n = r_rbtree_find (sp->spaces, (void *)name, name_space_cmp);
|
||||
return n? container_of (n, RSpace, rb): NULL;
|
||||
}
|
||||
|
||||
static int space_cmp(const void *incoming, const RBNode *rb) {
|
||||
const RSpace *a = (const RSpace *)incoming;
|
||||
const RSpace *b = container_of (rb, const RSpace, rb);
|
||||
return strcmp (a->name, b->name);
|
||||
}
|
||||
|
||||
R_API RSpace *r_spaces_add(RSpaces *sp, const char *name) {
|
||||
r_return_val_if_fail (sp, NULL);
|
||||
if (!name || !*name || *name == '*') {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RSpace *s = r_spaces_get (sp, name);
|
||||
if (s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
s = R_NEW0 (RSpace);
|
||||
if (!s) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s->name = strdup (name);
|
||||
if (!s->name) {
|
||||
free (s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r_rbtree_insert (&sp->spaces, s, &s->rb, space_cmp);
|
||||
return s;
|
||||
}
|
||||
|
||||
R_API RSpace *r_spaces_set(RSpaces *sp, const char *name) {
|
||||
sp->current = r_spaces_add (sp, name);
|
||||
return sp->current;
|
||||
}
|
||||
|
||||
R_API bool r_spaces_unset(RSpaces *sp, const char *name) {
|
||||
RSpace *space = r_spaces_get (sp, name);
|
||||
if (!space) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RSpaceEvent ev = { .data.unset.space = space };
|
||||
r_event_send (sp->event, R_SPACE_EVENT_UNSET, &ev);
|
||||
return r_rbtree_delete (&sp->spaces, (void *)name, name_space_cmp, space_node_free);
|
||||
}
|
||||
|
||||
R_API int r_spaces_count(RSpaces *sp, const char *name) {
|
||||
RSpace *s = r_spaces_get (sp, name);
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
RSpaceEvent ev = { .data.count.space = s, .res = 0 };
|
||||
r_event_send (sp->event, R_SPACE_EVENT_COUNT, &ev);
|
||||
return ev.res;
|
||||
}
|
||||
|
||||
R_API bool r_spaces_push(RSpaces *sp, const char *name) {
|
||||
r_return_val_if_fail (sp, false);
|
||||
|
||||
r_list_push (sp->spacestack, sp->current? sp->current->name: "*");
|
||||
r_spaces_set (sp, name);
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API bool r_spaces_pop(RSpaces *sp) {
|
||||
char *name = r_list_pop (sp->spacestack);
|
||||
if (!name) {
|
||||
r_space_set (s, NULL);
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i < R_SPACES_MAX; i++) {
|
||||
if (!s->spaces[i]) {
|
||||
continue;
|
||||
}
|
||||
if (!name || !strcmp (name, s->spaces[i])) {
|
||||
if (s->space_idx == i) {
|
||||
s->space_idx = -1;
|
||||
}
|
||||
R_FREE (s->spaces[i]);
|
||||
if (s->unset_for) {
|
||||
s->unset_for (s, i);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
|
||||
RSpace *s = r_spaces_get (sp, name);
|
||||
r_spaces_set (sp, s? s->name: NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int r_space_count (RSpaces *s, int n) {
|
||||
if (s->count_for) {
|
||||
return s->count_for (s, n);
|
||||
R_API bool r_spaces_rename(RSpaces *sp, const char *oname, const char *nname) {
|
||||
if (!oname && !sp->current) {
|
||||
return false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
R_API int r_space_list(RSpaces *s, int mode) {
|
||||
const char *defspace = NULL;
|
||||
int count, len, i, j = 0;
|
||||
if (mode == 'j') {
|
||||
s->cb_printf ("[");
|
||||
}
|
||||
for (i = 0; i < R_SPACES_MAX; i++) {
|
||||
if (!s->spaces[i]) {
|
||||
continue;
|
||||
}
|
||||
count = r_space_count (s, i);
|
||||
if (mode == 'j') {
|
||||
s->cb_printf ("%s{\"name\":\"%s\"%s,\"count\":%d}",
|
||||
j? ",": "", s->spaces[i],
|
||||
(i == s->space_idx)? ",\"selected\":true": "",
|
||||
count);
|
||||
} else if (mode == '*') {
|
||||
s->cb_printf ("%s %s\n", s->name, s->spaces[i]);
|
||||
if (i == s->space_idx) {
|
||||
defspace = s->spaces[i];
|
||||
}
|
||||
} else {
|
||||
#define INDENT 5
|
||||
char num0[64], num1[64], spaces[32];
|
||||
snprintf (num0, sizeof (num0), "%d", i);
|
||||
snprintf (num1, sizeof (num1), "%d", count);
|
||||
memset (spaces, ' ', sizeof (spaces));
|
||||
len = strlen (num0) + strlen (num1);
|
||||
if (len < INDENT) {
|
||||
spaces[INDENT-len] = 0;
|
||||
} else {
|
||||
spaces[0] = 0;
|
||||
}
|
||||
s->cb_printf ("%s%s %s %c %s\n", num0, spaces, num1,
|
||||
(i == s->space_idx)? '*': '.',
|
||||
s->spaces[i]);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
if (defspace) {
|
||||
s->cb_printf ("%s %s # current\n", s->name, defspace);
|
||||
}
|
||||
if (mode == 'j') {
|
||||
s->cb_printf ("]\n");
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
R_API bool r_space_rename (RSpaces *s, const char *oname, const char *nname) {
|
||||
int i;
|
||||
|
||||
if (!oname) {
|
||||
if (s->space_idx == -1) {
|
||||
RSpace *s;
|
||||
if (oname) {
|
||||
s = r_spaces_get (sp, oname);
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
oname = s->spaces[s->space_idx];
|
||||
} else {
|
||||
s = sp->current;
|
||||
}
|
||||
if (!nname) {
|
||||
|
||||
RSpace *sn = r_spaces_get (sp, nname);
|
||||
if (sn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (*oname==' ') {
|
||||
oname++;
|
||||
}
|
||||
while (*nname==' ') {
|
||||
nname++;
|
||||
}
|
||||
RSpaceEvent ev = {
|
||||
.data.rename.oldname = s->name,
|
||||
.data.rename.newname = nname,
|
||||
.data.rename.space = s
|
||||
};
|
||||
r_event_send (sp->event, R_SPACE_EVENT_RENAME, &ev);
|
||||
|
||||
if (r_space_get (s, nname) != -1) {
|
||||
eprintf ("error: dupplicated name\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < R_SPACES_MAX; i++) {
|
||||
if (s->spaces[i] && !strcmp (oname, s->spaces[i])) {
|
||||
if (s->rename_for) {
|
||||
s->rename_for (s, i, oname, nname);
|
||||
}
|
||||
free (s->spaces[i]);
|
||||
s->spaces[i] = strdup (nname);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
r_rbtree_delete (&sp->spaces, (void *)s->name, name_space_cmp, NULL);
|
||||
free (s->name);
|
||||
s->name = strdup (nname);
|
||||
r_rbtree_insert (&sp->spaces, s, &s->rb, space_cmp);
|
||||
return true;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user